aboutsummaryrefslogtreecommitdiff
path: root/libX11/specs/XKB/ch13.xml
diff options
context:
space:
mode:
Diffstat (limited to 'libX11/specs/XKB/ch13.xml')
-rw-r--r--libX11/specs/XKB/ch13.xml4146
1 files changed, 4146 insertions, 0 deletions
diff --git a/libX11/specs/XKB/ch13.xml b/libX11/specs/XKB/ch13.xml
new file mode 100644
index 000000000..6f8fce033
--- /dev/null
+++ b/libX11/specs/XKB/ch13.xml
@@ -0,0 +1,4146 @@
+<chapter id='keyboard_geometry'>
+<title>Keyboard Geometry</title>
+
+<para>
+The Xkb description of a keyboard includes an optional keyboard geometry that
+describes the physical appearance of the keyboard. Keyboard geometry describes
+the shape, location, and color of all keyboard keys or other visible keyboard
+components such as indicators. The information contained in a keyboard geometry
+is sufficient to allow a client program to draw an accurate two-dimensional
+image of the keyboard.
+</para>
+
+
+<para>
+You can retrieve a keyboard geometry from an X server that supports Xkb, or you
+can allocate it from scratch and initialize it in a client program. The
+keyboard geometry need not have any correspondence with the physical keyboard
+that is connected to the X server.
+</para>
+
+
+<para>
+Geometry measurements are specified in mm/10 units. The origin (0,0) is in the
+top left corner of the keyboard image. A component’s own origin is also its
+upper left corner. In some cases a component needs to be drawn rotated. For
+example, a special keyboard may have a section of keys arranged in rows in a
+rectangular area, but the entire rectangle may not be in alignment with the
+rest of the keyboard, and instead, it is rotated from horizontal by 30<emphasis>
+o</emphasis>
+. Rotation for a geometry object is specified in 1/10 o increments about its
+origin. An example of a keyboard with rotated sections is shown in Figure 13.1.
+</para>
+
+<mediaobject>
+ <imageobject> <imagedata format="SVG" fileref="XKBlib-7.svg"/>
+ </imageobject>
+<caption>Rotated Keyboard Sections</caption>
+</mediaobject>
+
+
+<!-- <H5 CLASS="Figure">
+Rotated Keyboard Sections</H5>
+-->
+
+<para>
+Some geometry components include a <emphasis>
+priority</emphasis>
+, which indicates the order in which overlapping objects should be drawn.
+Objects should be drawn in order from highest priority (0) to lowest (255).
+</para>
+
+
+<para>
+The keyboard geometry’s top-level description is stored in a <emphasis>
+XkbGeometryRec</emphasis>
+ structure. This structure contains three types of information:
+</para>
+
+<orderedlist>
+ <listitem>
+ <para>
+Lists of items, not used to draw the basic keyboard, but indexed by the
+geometry descriptions that comprise the entire keyboard geometry (colors,
+geometry properties, key aliases, shapes)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+A number of singleton items that describe the keyboard as a whole (keyboard
+name, width and height, a color for the keyboard as a whole, and a color for
+keyboard key labels)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+A list of the keyboard’s sections and nonkey doodads
+ </para>
+ </listitem>
+</orderedlist>
+
+<para>
+The top-level geometry is described in more detail in the following.
+</para>
+
+
+<para>
+The lists of items used by components of the keyboard geometry description is
+as follows:
+</para>
+
+<itemizedlist>
+<listitem>
+ <para>
+The top-level keyboard geometry description includes a list of up to <emphasis>
+MaxColors</emphasis>
+ (32) <emphasis>
+color names</emphasis>
+. A color name is a string whose interpretation is not specified by Xkb. The
+<emphasis>
+XkbColorRec</emphasis>
+ structure provides a field for this name as well as a pixel field. The pixel
+field is a convenient place for an application to store a pixel value or color
+definition, if it needs to. All other geometry data structures refer to colors
+using their indices in this global list.
+ </para>
+</listitem>
+<listitem>
+ <para>
+The top-level keyboard geometry description includes a list of <emphasis>
+geometry properties</emphasis>
+. A geometry property associates an arbitrary string with an equally arbitrary
+name. Geometry properties can be used to provide hints to programs that display
+images of keyboards, but they are not interpreted by Xkb. No other geometry
+structures refer to geometry properties. As an example of a possible use of
+<emphasis>
+properties</emphasis>
+, consider the pause/break key on most PC keyboards: the "break" symbol is
+usually on the front of the key and is often a different color. A program might
+set a property to:
+ </para>
+ <para>
+LBL_PAUS = "{Pause/top/black,Break/front/red}"
+ </para>
+ <para>
+and use the property information to draw the key with a front label as well as
+a top label.
+ </para>
+</listitem>
+<listitem>
+ <para>
+The top-level keyboard geometry description includes a list of <emphasis>
+key aliases</emphasis>
+ (see Chapter 18). Key aliases allow the keyboard layout designer to assign
+multiple key names to a single key.
+ </para>
+<note><para>Key aliases defined in the geometry component of a keyboard mapping
+override those defined in the keycodes component of the server database, which
+are stored in the <emphasis>
+XkbNamesRec</emphasis>
+ (<emphasis>
+xkb-&gt;names</emphasis>
+). Therefore, consider the key aliases defined by the geometry before
+considering key aliases supplied by the keycodes.</para></note>
+</listitem>
+<listitem>
+ <para>
+The top-level keyboard geometry description includes a list of <emphasis>
+shapes</emphasis>
+; other keyboard components refer to shapes by their index in this list. A
+shape consists of an arbitrary name of type Atom and one or more closed-polygon
+<emphasis>
+outlines</emphasis>
+. All points in an outline are specified relative to the origin of its
+enclosing shape, that is, whichever shape that contains this outline in its
+list of outlines. One outline is the primary outline. The primary outline is by
+default the first outline, or it can be optionally specified by the <emphasis>
+primary</emphasis>
+ field in the <emphasis>
+XkbShapeRec</emphasis>
+ structure. A keyboard display application can generate a simpler but still
+accurate keyboard image by displaying only the primary outlines for each shape.
+Nonrectangular keys must include a rectangular <emphasis>
+approximation</emphasis>
+ as one of the outlines associated with the shape. The approximation is not
+normally displayed but can be used by very simple keyboard display applications
+to generate a recognizable but degraded image of the keyboard.
+ </para>
+</listitem>
+</itemizedlist>
+
+<para>
+The <emphasis>
+XkbGeometryRec</emphasis>
+ top-level geometry description contains the following information that
+pertains to the keyboard as a whole:
+</para>
+
+<itemizedlist>
+<listitem>
+ <para>
+A <emphasis>
+keyboard symbolic name</emphasis>
+ of type Atom to help users identify the keyboard.
+ </para>
+</listitem>
+<listitem>
+ <para>
+The <emphasis>
+width</emphasis>
+ and <emphasis>
+height</emphasis>
+ of the keyboard, in mm/10. For nonrectangular keyboards, the width and height
+describe the smallest bounding box that encloses the outline of the keyboard.
+ </para>
+</listitem>
+<listitem>
+ <para>
+The<emphasis>
+ base color</emphasis>
+ of the keyboard is the predominant color on the keyboard and is used as the
+default color for any components whose color is not explicitly specified.
+ </para>
+</listitem>
+<listitem>
+ <para>
+The <emphasis>
+label color</emphasis>
+ is the color used to draw the labels on most of the keyboard keys.
+ </para>
+</listitem>
+<listitem>
+ <para>
+The <emphasis>
+label font</emphasis>
+ is a string that describes the font used to draw labels on most keys; label
+fonts are arbitrary strings, because Xkb does not specify the format or name
+space for font names.
+ </para>
+</listitem>
+</itemizedlist>
+
+<para>
+The keyboard is subdivided into named <emphasis>
+sections</emphasis>
+ of related keys and doodads. The sections and doodads on the keyboard are
+listed in the <emphasis>
+XkbGeometryRec</emphasis>
+ top-level keyboard geometry description. A section is composed of keys that
+are physically together and logically related. Figure 13.2 shows a keyboard
+that is divided into four sections. A <emphasis>
+doodad</emphasis>
+ describes some visible aspect of the keyboard that is not a key and is not a
+section.
+</para>
+
+<mediaobject>
+ <imageobject> <imagedata format="SVG" fileref="XKBlib-8.svg"/>
+ </imageobject>
+<caption>Keyboard with Four Sections</caption>
+</mediaobject>
+
+<!--
+<H5 CLASS="Figure">
+Keyboard with Four Sections</H5>
+-->
+
+<sect1 id='shapes_and_outlines'>
+<title>Shapes and Outlines</title>
+
+<para>
+A <emphasis>
+shape</emphasis>
+, used to draw keyboard components and stored in a <emphasis>
+XkbShapeRec</emphasis>
+ structure, has:
+</para>
+
+<itemizedlist>
+<listitem>
+ <para>
+An arbitrary name of type Atom.
+ </para>
+</listitem>
+<listitem>
+ <para>
+Bounds (two x and y coordinates) that describe the corners of a rectangle
+containing the shape’s top surface outline.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A list of one or more outlines (described below).
+ </para>
+</listitem>
+<listitem>
+ <para>
+Optional pointers to a primary and an approximation outline (described below).
+If either of these pointers is <emphasis>
+NULL</emphasis>
+, the default primary/approximation outline is the first one in the list of
+outlines for the shape.
+ </para>
+</listitem>
+</itemizedlist>
+
+<para>
+An <emphasis>
+outline</emphasis>
+, stored in a <emphasis>
+XkbOutlineRec</emphasis>
+ structure, is a list of one or more points that describes a single
+closed-polygon, as follows:
+</para>
+
+<itemizedlist>
+<listitem>
+ <para>
+A list with a single point describes a rectangle with one corner at the origin
+of the shape (0,0) and the opposite corner at the specified point.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A list of two points describes a rectangle with one corner at the position
+specified by the first point and the opposite corner at the position specified
+by the second point.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A list of three or more points describes an arbitrary polygon. If necessary,
+the polygon is automatically closed by connecting the last point in the list
+with the first.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A nonzero value for the <emphasis>
+corner_radius</emphasis>
+ field specifies that the corners of the polygon should be drawn as circles
+with the specified radius.
+ </para>
+</listitem>
+</itemizedlist>
+
+<para>
+All points in an outline are specified relative to the origin of the enclosing
+shape. Points in an outline may have negative values for the X and Y coordinate.
+</para>
+
+
+<para>
+One outline is the primary outline; a keyboard display application can generate
+a simple but still accurate keyboard image by displaying only the primary
+outlines for each shape. The default primary outline is the first in a
+shape’s list of outlines. If the <emphasis>
+primary</emphasis>
+ field of the <emphasis>
+XkbShapeRec</emphasis>
+ structure is not <emphasis>
+NULL</emphasis>
+, it points to the primary outline. A rectangular <emphasis>
+approximation</emphasis>
+ must be included for nonrectangular keys as one of the outlines associated
+with the shape; the approximation is not normally displayed but can be used by
+very simple keyboard display applications to generate a recognizable but
+degraded image of the keyboard.
+</para>
+
+</sect1>
+<sect1 id='sections'>
+<title>Sections</title>
+
+<para>
+As previously noted, a keyboard is subdivided into <emphasis>
+sections</emphasis>
+ of related keys. Each section has its own coordinate system — if a section
+is rotated, the coordinates of any components within the section are
+interpreted relative to the edges that were on the top and left before
+rotation. The components that make up a section, stored in a <emphasis>
+XkbSectionRec</emphasis>
+, include:
+</para>
+
+<itemizedlist>
+<listitem>
+ <para>
+An arbitrary name of type Atom.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A priority, to indicate drawing order. 0 is the highest priority, 255 the
+lowest.
+ </para>
+</listitem>
+<listitem>
+ <para>
+Origin of the section, relative to the origin of the keyboard.
+ </para>
+</listitem>
+<listitem>
+ <para>
+The width and height and the angle of rotation.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A list of <emphasis>
+rows</emphasis>
+. A row is a list of horizontally or vertically adjacent keys. Horizontal rows
+parallel the (prerotation) top of the section, and vertical rows parallel the
+(prerotation) left of the section. All keys in a horizontal row share a common
+top coordinate; all keys in a vertical row share a left coordinate. Figure 13.3
+shows the alpha section from the keyboard shown in Figure 13.2, divided into
+rows. Rows and keys are defined below.
+ </para>
+</listitem>
+</itemizedlist>
+
+<mediaobject>
+ <imageobject> <imagedata format="SVG" fileref="XKBlib-9.svg"/>
+ </imageobject>
+ <caption>Rows in a Section</caption>
+</mediaobject>
+
+
+
+<!--
+<H5 CLASS="Figure">
+Rows in a Section</H5>
+-->
+<itemizedlist>
+<listitem>
+ <para>
+An optional list of <emphasis>
+doodads</emphasis>
+; any type of doodad can be enclosed within a section. Position and angle of
+rotation are relative to the origin and angle of rotation of the sections that
+contain them. Priority for doodads in a section is relative to the other
+components of the section, not to the keyboard as a whole.
+ </para>
+</listitem>
+<listitem>
+ <para>
+An optional <emphasis>
+overlay</emphasis>
+ with a name of type Atom and a list of overlay rows (described below).
+ </para>
+</listitem>
+<listitem>
+ <para>
+Bounds (two x and y coordinates) that describe the corners of a rectangle
+containing the entire section.
+ </para>
+</listitem>
+</itemizedlist>
+</sect1>
+<sect1 id='rows_and_keys'>
+<title>Rows and Keys</title>
+
+<para>
+A row description (<emphasis>
+XkbRowRec</emphasis>
+) consists of the coordinates of its origin relative to its enclosing section,
+a flag indicating whether the row is horizontal or vertical, and a list of keys
+in the row.
+</para>
+
+
+<para>
+A key description (<emphasis>
+XkbKeyRec</emphasis>
+) consists of a key name, a shape, a key color, and a gap. The key name should
+correspond to one of the keys named in the keyboard names description, the
+shape specifies the appearance of the key, and the key color specifies the
+color of the key (not the label on the key; the label color is stored in the
+<emphasis>
+XkbGeometryRec</emphasis>
+). Keys are normally drawn immediately adjacent to one another from left to
+right (or top to bottom) within a row. The gap field specifies the distance
+between a key and its predecessor.
+</para>
+
+
+</sect1>
+<sect1 id='doodads'>
+<title>Doodads</title>
+
+<para>
+Doodads can be global to the keyboard or part of a section. Doodads have
+symbolic names of arbitrary length. The only doodad name whose interpretation
+is specified by Xkb is "Edges", which, if present, describes the outline of the
+entire keyboard.
+</para>
+
+
+<para>
+Each doodad’s origin is stored in fields named <emphasis>
+left</emphasis>
+ and <emphasis>
+top</emphasis>
+, which are the coordinates of the doodad’s origin relative to its enclosing
+object, whether it be a section or the top-level keyboard. The priority for
+doodads that are listed in the top-level geometry is relative to the other
+doodads listed in the top-level geometry and the sections listed in the
+top-level geometry. The priority for doodads listed in a section are relative
+to the other components of the section. Each doodad is stored in a structure
+with a <emphasis>
+type</emphasis>
+ field, which specifies the type of doodad.
+</para>
+
+<para>
+Xkb supports five types of doodads:
+</para>
+
+<itemizedlist>
+<listitem>
+ <para>
+An <emphasis>
+indicator doodad</emphasis>
+ describes one of the physical keyboard indicators. Indicator doodads specify
+the shape of the indicator, the indicator color when it is lit (<emphasis>
+on_color</emphasis>
+) and the indicator color when it is dark (<emphasis>
+off_color</emphasis>
+).
+ </para>
+</listitem>
+<listitem>
+ <para>
+An <emphasis>
+outline doodad</emphasis>
+ describes some aspect of the keyboard to be drawn as one or more hollow,
+closed polygons. Outline doodads specify the shape, color, and angle of
+rotation about the doodad origin at which they should be drawn.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A <emphasis>
+solid doodad</emphasis>
+ describes some aspect of the keyboard to be drawn as one or more filled
+polygons. Solid doodads specify the shape, color, and angle of rotation about
+the doodad origin at which they should be drawn.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A <emphasis>
+text doodad</emphasis>
+ describes a text label somewhere on the keyboard. Text doodads specify the
+label string, the font and color to use when drawing the label, and the angle
+of rotation of the doodad about its origin.
+ </para>
+</listitem>
+<listitem>
+ <para>
+A <emphasis>
+logo doodad </emphasis>
+is a catch-all, which describes some other visible element of the keyboard. A
+logo doodad is essentially an outline doodad with an additional symbolic name
+that describes the element to be drawn. If a keyboard display program
+recognizes the symbolic name, it can draw something appropriate within the
+bounding region of the shape specified in the doodad. If the symbolic name does
+not describe a recognizable image, it should draw an outline using the
+specified shape, outline, and angle of rotation. The Xkb extension does not
+specify the interpretation of logo names.
+ </para>
+</listitem>
+</itemizedlist>
+
+<para>
+The structures these doodads are stored in and the values of the <emphasis>
+type</emphasis>
+ fields are shown in Table 13.1.
+</para>
+
+<table frame='none'>
+<title>Doodad Types</title>
+<tgroup cols='3'>
+<colspec colsep='0'/>
+<thead>
+<row rowsep='0'>
+ <entry>Doodad</entry>
+ <entry>Structure</entry>
+ <entry>Type</entry>
+ </row>
+</thead>
+<tbody>
+ <row rowsep='0'>
+ <entry><emphasis>
+indicator doodad</emphasis>
+</entry>
+ <entry><emphasis>
+XkbIndicatorDoodadRec</emphasis>
+</entry>
+ <entry><emphasis>
+XkbIndicatorDoodad</emphasis>
+</entry>
+ </row>
+ <row rowsep='0'>
+ <entry><emphasis>
+outline doodad</emphasis>
+</entry>
+ <entry><emphasis>
+XkbShapeDoodadRec</emphasis>
+</entry>
+ <entry><emphasis>
+XkbOutlineDoodad</emphasis>
+</entry>
+ </row>
+ <row rowsep='0'>
+ <entry><emphasis>
+solid doodad</emphasis>
+</entry>
+ <entry><emphasis>
+XkbShapeDoodadRec</emphasis>
+</entry>
+ <entry><emphasis>
+XkbSolidDoodad</emphasis>
+</entry>
+ </row>
+ <row rowsep='0'>
+ <entry><emphasis>
+text doodad</emphasis>
+</entry>
+ <entry><emphasis>
+XkbTextDoodadRec</emphasis>
+</entry>
+ <entry><emphasis>
+XkbTextDoodad</emphasis>
+</entry>
+ </row>
+ <row rowsep='0'>
+ <entry><emphasis>
+logo doodad</emphasis>
+</entry>
+ <entry><emphasis>
+XkbLogoDoodadRec</emphasis>
+</entry>
+ <entry><emphasis>
+XkbLogoDoodad</emphasis>
+</entry>
+ </row>
+</tbody>
+</tgroup>
+</table>
+
+</sect1>
+<sect1 id='overlay_rows_and_overlay_keys'>
+<title>Overlay Rows and Overlay Keys</title>
+
+<para>
+An <emphasis>
+overlay row</emphasis>
+ (<emphasis>
+XkbOverlayRowRec</emphasis>
+) contains a pointer to the row it overlays and a list of <emphasis>
+overlay keys</emphasis>
+.
+</para>
+
+
+<para>
+Each overlay key definition (<emphasis>
+XkbOverlayKeyRec</emphasis>
+) indicates a key that can yield multiple keycodes and consists of a field
+named <emphasis>
+under</emphasis>
+, which specifies the primary name of the key and a field named <emphasis>
+over</emphasis>
+, which specifies the name for the key when the overlay keycode is selected.
+The key specified in <emphasis>
+under</emphasis>
+ must be a member of the section that contains the overlay key definition,
+while the key specified in over must not be.
+</para>
+
+
+</sect1>
+<sect1 id='drawing_a_keyboard_representation'>
+<title>Drawing a Keyboard Representation</title>
+
+<para>
+To draw a representation of the keyboard, draw in the following order:
+</para>
+
+<para><programlisting>
+ Draw the top-level keyboard as a rectangle, using its width and height.
+ For each component (section or doodad) of the top-level geometry, in priority order:
+ If component is a section
+ For each row, in the order it appears in the section
+ Draw keys in the order they appear in the row
+ Draw doodads within the section in priority order.
+ Else draw doodad
+</programlisting></para>
+
+</sect1>
+<sect1 id='geometry_data_structures'>
+<title>Geometry Data Structures</title>
+
+<para>
+In the following figures, a solid arrow denotes a pointer to an array of
+structures or a singleton structure. A dotted arrow denotes an index or a
+pointer into the array.
+</para>
+
+<!--
+<MAP NAME="XKBlib-10">
+</MAP>
+-->
+<mediaobject>
+ <imageobject> <imagedata format="SVG" fileref="XKBlib-10.svg"/>
+ </imageobject>
+<caption>Xkb Geometry Data Structures</caption>
+</mediaobject>
+
+<!--
+<H5 CLASS="Figure">
+Xkb Geometry Data Structures</H5>
+<P CLASS="SmallBody">
+&nbsp;</P>
+<MAP NAME="XKBlib-11">
+</MAP>
+-->
+<mediaobject>
+ <imageobject> <imagedata format="SVG" fileref="XKBlib-11.svg"/>
+ </imageobject>
+<caption>Xkb Geometry Data Structures (Doodads)</caption>
+</mediaobject>
+
+<!--
+<H5 CLASS="Figure">
+Xkb Geometry Data Structures (Doodads)</H5>
+-->
+
+<!--
+<MAP NAME="XKBlib-12">
+</MAP>
+-->
+<mediaobject>
+ <imageobject> <imagedata format="SVG" fileref="XKBlib-12.svg"/>
+ </imageobject>
+<caption>Xkb Geometry Data Structures (Overlays)</caption>
+</mediaobject>
+
+<!--
+<H5 CLASS="Figure">
+Xkb Geometry Data Structures (Overlays)</H5>
+-->
+<para><programlisting>
+typedef struct _XkbGeometry { /* top-level keyboard geometry structure */
+ Atom name; /* keyboard name */
+ unsigned short width_mm; /* keyboard width in <emphasis> mm</emphasis> /<emphasis> 10</emphasis> */
+ unsigned short height_mm; /* keyboard height in <emphasis> mm</emphasis> /<emphasis> 10</emphasis> */
+ char * label_font; /* font for key labels */
+ XkbColorPtr label_color; /* color for key labels - pointer into colors array */
+ XkbColorPtr base_color; /* color for basic keyboard - pointer into colors array */
+ unsigned short sz_properties; /* size of properties array */
+ unsigned short sz_colors; /* size of colors array */
+ unsigned short sz_shapes; /* size of shapes array */
+ unsigned short sz_sections; /* size of sections array */
+ unsigned short sz_doodads; /* size of doodads array */
+ unsigned short sz_key_aliases; /* size of key aliases array */
+ unsigned short num_properties; /* number of properties in the properties array */
+ unsigned short num_colors; /* number of colors in the colors array */
+ unsigned short num_shapes; /* number of shapes in the shapes array */
+ unsigned short num_sections; /* number of sections in the sections array */
+ unsigned short num_doodads; /* number of doodads in the doodads array */
+ unsigned short num_key_aliases; /* number of key aliases in the key */
+ XkbPropertyPtr properties; /* properties array */
+ XkbColorPtr colors; /* colors array */
+ XkbShapePtr shapes; /* shapes array */
+ XkbSectionPtr sections; /* sections array */
+ XkbDoodadPtr doodads; /* doodads array */
+ XkbKeyAliasPtr key_aliases; /* key aliases array */
+} <emphasis>XkbGeometryRec</emphasis>*XkbGeometryPtr;
+</programlisting></para>
+
+<para>
+The <emphasis>
+doodads</emphasis>
+ array is only for doodads not contained in any of the <emphasis>
+sections</emphasis>
+ that has its own <emphasis>
+doodads</emphasis>
+. The key aliases contained in the <emphasis>
+key_aliases</emphasis>
+ array take precedence over any defined in the keycodes component of the
+keyboard description.
+</para>
+
+<para><programlisting>
+typedef struct _XkbProperty {
+ char * name; /* property name */
+ char * value; /* property value */
+} <emphasis>XkbPropertyRec</emphasis>,*XkbPropertyPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbColor {
+ unsigned int pixel; /* color */
+ char * spec; /* color name */
+} <emphasis>XkbColorRec</emphasis>,*XkbColorPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbKeyAliasRec {
+ char real[XkbKeyNameLength]; /* real name of the key */
+ char alias[XkbKeyNameLength]; /* alias for the key */
+} <emphasis>XkbKeyAliasRec</emphasis>,*XkbKeyAliasPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbPoint { /* x,y coordinates */
+ short x;
+ short y;
+} <emphasis>XkbPointRec</emphasis>, *XkbPointPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbOutline {
+ unsigned short num_points; /* number of points in the outline */
+ unsigned short sz_points; /* size of the points array */
+ unsigned short corner_radius; /* draw corners as circles with this radius */
+ XkbPointPtr points; /* array of points defining the outline */
+} <emphasis>XkbOutlineRec</emphasis>, *XkbOutlinePtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbBounds {
+ short x1,y1; /* upper left corner of the bounds,
+ in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short x2,y2; /* lower right corner of the bounds, in
+ <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+} <emphasis>XkbBoundsRec</emphasis>, *XkbBoundsPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbShape {
+ Atom name; /* shape’s name */
+ unsigned short num_outlines; /* number of outlines for the shape */
+ unsigned short sz_outlines; /* size of the outlines array */
+ XkbOutlinePtr outlines; /* array of outlines for the shape */
+ XkbOutlinePtr approx; /* pointer into the array to the approximating outline */
+ XkbOutlinePtr primary; /* pointer into the array to the primary outline */
+ XkbBoundsRec bounds; /* bounding box for the shape; encompasses all outlines */
+} <emphasis>XkbShapeRec</emphasis>, *XkbShapePtr;
+</programlisting></para>
+
+<para>
+If <emphasis>
+approx</emphasis>
+ and/or <emphasis>
+primary</emphasis>
+ is <emphasis>
+NULL</emphasis>
+, the default value is used. The default primary outline is the first element
+in the outlines array, as is the default approximating outline.
+</para>
+
+<para><programlisting>
+typedef struct _XkbKey { /* key in a row */
+ XkbKeyNameRec name; /* key name */
+ short gap; /* gap in <emphasis>mm</emphasis>/<emphasis>10</emphasis> from previous key in row */
+ unsigned char shape_ndx; /* index of shape for key */
+ unsigned char color_ndx; /* index of color for key body */
+} <emphasis>XkbKeyRec</emphasis>, *XkbKeyPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbRow { /* row in a section */
+ short top; /* top coordinate of row origin, relative to section’s origin */
+ short left; /* left coordinate of row origin, relative to section’s origin */
+ unsigned short num_keys; /* number of keys in the keys array */
+ unsigned short sz_keys; /* size of the keys array */
+ int vertical; /* <emphasis>True</emphasis> =&gt;vertical row,
+ <emphasis> False</emphasis> =&gt;horizontal row */
+ XkbKeyPtr keys; /* array of keys in the row*/
+ XkbBoundsRec bounds; /* bounding box for the row */
+} <emphasis>XkbRowRec</emphasis>, *XkbRowPtr;
+</programlisting></para>
+
+<para>
+<emphasis>
+top</emphasis>
+ and <emphasis>
+left</emphasis>
+ are in <emphasis>
+mm</emphasis>
+/<emphasis>
+10</emphasis>
+.
+</para>
+
+<para><programlisting>
+typedef struct _XkbOverlayRec {
+ Atom name; /* overlay name */
+ XkbSectionPtr section_under; /* the section under this overlay */
+ unsigned short num_rows; /* number of rows in the rows array */
+ unsigned short sz_rows; /* size of the rows array */
+ XkbOverlayRowPtr rows; /* array of rows in the overlay */
+ XkbBoundsPtr bounds; /* bounding box for the overlay */
+} <emphasis>XkbOverlayRec</emphasis>,*XkbOverlayPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbOverlayRow {
+ unsigned short row_under; /* index into the row under this overlay row */
+ unsigned short num_keys; /* number of keys in the keys array */
+ unsigned short sz_keys; /* size of the keys array */
+ XkbOverlayKeyPtr keys; /* array of keys in the overlay row */
+} <emphasis>XkbOverlayRowRec</emphasis>,*XkbOverlayRowPtr;
+</programlisting></para>
+
+<para>
+<emphasis>
+row_under</emphasis>
+ is an index into the array of <emphasis>
+rows</emphasis>
+ in the section under this overlay. The section under this overlay row is the
+one pointed to by <emphasis>
+section_under</emphasis>
+ in this overlay row’s <emphasis>
+XkbOverlayRec</emphasis>
+.
+</para>
+
+<para><programlisting>
+typedef struct _XkbOverlayKey {
+ XkbKeyNameRec over; /* name of this overlay key */
+ XkbKeyNameRec under; /* name of the key under this overlay key */
+} <emphasis>XkbOverlayKeyRec</emphasis>,*XkbOverlayKeyPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbSection {
+ Atom name; /* section name */
+ unsigned char priority; /* drawing priority, 0=&gt;highest, 255=&gt;lowest */
+ short top; /* top coordinate of section origin */
+ short left; /* left coordinate of row origin */
+ unsigned short width; /* section width, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ unsigned short height; /* section height, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short angle; /* angle of section rotation, counterclockwise */
+ unsigned short num_rows; /* number of rows in the rows array */
+ unsigned short num_doodads; /* number of doodads in the doodads array */
+ unsigned short num_overlays; /* number of overlays in the overlays array */
+ unsigned short sz_rows; /* size of the rows array */
+ unsigned short sz_doodads; /* size of the doodads array */
+ unsigned short sz_overlays; /* size of the overlays array */
+ XkbRowPtr rows; /* section rows array */
+ XkbDoodadPtr doodads; /* section doodads array */
+ XkbBoundsRec bounds; /* bounding box for the section, before rotation*/
+ XkbOverlayPtr overlays; /* section overlays array */
+} <emphasis>XkbSectionRec</emphasis>, *XkbSectionPtr;
+</programlisting></para>
+
+<para>
+<emphasis>
+top</emphasis>
+ and <emphasis>
+left</emphasis>
+ are the origin of the section, relative to the origin of the keyboard, in
+<emphasis>
+mm</emphasis>
+/<emphasis>
+10</emphasis>
+. <emphasis>
+angle</emphasis>
+ is in <emphasis>
+1</emphasis>
+/<emphasis>
+10</emphasis>
+ degrees.
+</para>
+
+<sect2 id='doodadrec_structures'>
+<title>DoodadRec Structures</title>
+
+<para>
+The doodad arrays in the <emphasis>
+XkbGeometryRec</emphasis>
+ and the <emphasis>
+XkbSectionRec</emphasis>
+ may contain any of the doodad structures and types shown in Table 13.1.
+</para>
+
+
+<para>
+The doodad structures form a union:
+</para>
+
+<para><programlisting>
+typedef union _XkbDoodad {
+ XkbAnyDoodadRec any;
+ XkbShapeDoodadRec shape;
+ XkbTextDoodadRec text;
+ XkbIndicatorDoodadRec indicator;
+ XkbLogoDoodadRec logo;
+} <emphasis>XkbDoodadRec</emphasis>, *XkbDoodadPtr;
+</programlisting></para>
+
+<para>
+The <emphasis>
+top</emphasis>
+ and <emphasis>
+left</emphasis>
+ coordinates of each doodad are the coordinates of the origin of the doodad
+relative to the keyboard’s origin if the doodad is in the <emphasis>
+XkbGeometryRec</emphasis>
+ doodad array, and with respect to the section’s origin if the doodad is in a
+<emphasis>
+XkbSectionRec</emphasis>
+ doodad array. The <emphasis>
+color_ndx</emphasis>
+ or <emphasis>
+on_color_ndx</emphasis>
+ and <emphasis>
+off_color_ndx</emphasis>
+ fields are color indices into the <emphasis>
+XkbGeometryRec</emphasis>
+’s color array and are the colors to draw the doodads with. Similarly, the
+<emphasis>
+shape_ndx</emphasis>
+ fields are indices into the <emphasis>
+XkbGeometryRec</emphasis>
+’s shape array.
+</para>
+
+<para><programlisting>
+typedef struct _XkbShapeDoodad {
+ Atom name; /* doodad name */
+ unsigned char type; /* <emphasis>XkbOutlineDoodad</emphasis>
+ or <emphasis>XkbSolidDoodad</emphasis> */
+ unsigned char priority; /* drawing priority,
+ 0=&gt;highest, 255=&gt;lowest */
+ short top; /* top coordinate, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short left; /* left coordinate, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short angle; /* angle of rotation, clockwise, in <emphasis>1</emphasis>/<emphasis>10</emphasis> degrees */
+ unsigned short color_ndx; /* doodad color */
+ unsigned short shape_ndx; /* doodad shape */
+} <emphasis>XkbShapeDoodadRec</emphasis>, *XkbShapeDoodadPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbTextDoodad {
+ Atom name; /* doodad name */
+ unsigned char type; /* <emphasis> XkbTextDoodad</emphasis> */
+ unsigned char priority; /* drawing priority,
+ 0=&gt;highest, 255=&gt;lowest */
+ short top; /* top coordinate, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short left; /* left coordinate, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short angle; /* angle of rotation, clockwise, in <emphasis>1</emphasis>/<emphasis>10</emphasis> degrees */
+ short width; /* width in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short height; /* height in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ unsigned short color_ndx; /* doodad color */
+ char * text; /* doodad text */
+ char * font; /* arbitrary font name for doodad text */
+} <emphasis>XkbTextDoodadRec</emphasis>, *XkbTextDoodadPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbIndicatorDoodad {
+ Atom name; /* doodad name */
+ unsigned char type; /* <emphasis>XkbIndicatorDoodad</emphasis> */
+ unsigned char priority; /* drawing priority, 0=&gt;highest, 255=&gt;lowest */
+ short top; /* top coordinate, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short left; /* left coordinate, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short angle; /* angle of rotation, clockwise, in <emphasis>1</emphasis>/<emphasis>10</emphasis> degrees */
+ unsigned short shape_ndx; /* doodad shape */
+ unsigned short on_color_ndx; /* color for doodad if indicator is on */
+ unsigned short off_color_ndx; /* color for doodad if indicator is off */
+} <emphasis>XkbIndicatorDoodadRec</emphasis>, *XkbIndicatorDoodadPtr;
+</programlisting></para>
+
+<para><programlisting>
+typedef struct _XkbLogoDoodad {
+ Atom name; /* doodad name */
+ unsigned char type; /* <emphasis> XkbLogoDoodad</emphasis> */
+ unsigned char priority; /* drawing priority, 0=&gt;highest, 255=&gt;lowest */
+ short top; /* top coordinate, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short left; /* left coordinate, in <emphasis>mm</emphasis>/<emphasis>10</emphasis> */
+ short angle; /* angle of rotation, clockwise, in <emphasis>1</emphasis>/<emphasis>10</emphasis> degrees */
+ unsigned short color_ndx; /* doodad color */
+ unsigned short shape_ndx; /* doodad shape */
+ char * logo_name; /* text for logo */
+} <emphasis>XkbLogoDoodadRec</emphasis>, *XkbLogoDoodadPtr
+</programlisting></para>
+
+</sect2>
+</sect1>
+<sect1 id='getting_keyboard_geometry_from_the_server'>
+<title>Getting Keyboard Geometry From the Server</title>
+
+<para>
+You can load a keyboard geometry as part of the keyboard description returned
+by <emphasis>
+XkbGetKeyboard</emphasis>
+. However, if a keyboard description has been previously loaded, you can
+instead obtain the geometry by calling the <emphasis>
+XkbGetGeometry</emphasis>
+. In this case, the geometry returned is the one associated with the keyboard
+whose device ID is contained in the keyboard description.
+</para>
+
+<para>
+To load a keyboard geometry if you already have the keyboard description, use
+<emphasis>XkbGetGeometry</emphasis>.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbGetGeometry</emphasis>
+(<emphasis>
+dpy</emphasis>
+,<emphasis>
+ xkb</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Display * <emphasis>
+dpy</emphasis>
+; /* connection to the X server */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbDescPtr <emphasis>
+ xkb</emphasis>
+; /* keyboard description that contains the ID for the keyboard and into
+which the geometry should be loaded */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbGetGeometry</emphasis>
+ can return <emphasis>
+BadValue</emphasis>
+, <emphasis>
+BadImplementation</emphasis>
+, <emphasis>
+BadName</emphasis>
+, <emphasis>
+BadAlloc,</emphasis>
+ or <emphasis>
+BadLength</emphasis>
+ errors or <emphasis>
+Success</emphasis>
+ if it succeeds.
+</para>
+
+<para>
+It is also possible to load a keyboard geometry by name. The X server maintains
+a database of keyboard components (see Chapter 20). To load a keyboard geometry
+description from this database by name, use <emphasis>
+XkbGetNamedGeometry</emphasis>.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbGetNamedGeometry</emphasis>
+(<emphasis>
+dpy</emphasis>
+,<emphasis>
+ xkb</emphasis>
+,<emphasis>
+ name</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Display * <emphasis>
+dpy</emphasis>
+; /* connection to the X server */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbDescPtr <emphasis>
+xkb</emphasis>
+; /* keyboard description into which the geometry should be loaded */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Atom <emphasis>
+name</emphasis>
+; /* name of the geometry to be loaded */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbGetNamedGeometry</emphasis>
+ can return <emphasis>
+BadName</emphasis>
+ if the <emphasis>
+name</emphasis>
+ cannot be found.
+</para>
+
+</sect1>
+<sect1 id='using_keyboard_geometry'>
+<title>Using Keyboard Geometry</title>
+
+<para>
+Xkb provides a number of convenience functions to help use a keyboard geometry.
+These include functions to return the bounding box of a shape’s top surface
+and to update the bounding box of a shape row or section.
+</para>
+
+<para>
+A shape is made up of a number of outlines. Each outline is a polygon made up
+of a number of points. The bounding box of a shape is a rectangle that contains
+all the outlines of that shape.
+</para>
+
+<mediaobject>
+ <imageobject> <imagedata format="SVG" fileref="XKBlib-13.svg"/>
+ </imageobject>
+<caption>Key Surface, Shape Outlines, and Bounding Box</caption>
+ </mediaobject>
+
+
+<!--
+<H5 CLASS="Figure">
+Key Surface, Shape Outlines, and Bounding Box</H5>
+-->
+
+<para>
+To determine the bounding box of the top surface of a shape, use <emphasis>
+XkbComputeShapeTop</emphasis>.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Bool <emphasis>
+XkbComputeShapeTop</emphasis>
+(<emphasis>
+shape</emphasis>
+,<emphasis>
+ bounds_rtrn</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbShapePtr <emphasis>
+ shape</emphasis>
+; /* shape to be examined */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbBoundsPtr <emphasis>
+ bounds_rtrn</emphasis>
+ /* backfilled with the bounding box for the shape */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbComputeShapeTop</emphasis>
+ returns a <emphasis>
+BoundsRec</emphasis>
+ that contains two x and y coordinates. These coordinates describe the corners
+of a rectangle that contains the outline that describes the top surface of the
+shape. The top surface is defined to be the approximating outline if the
+<emphasis>
+approx</emphasis>
+ field of <emphasis>
+shape</emphasis>
+ is not <emphasis>
+NULL</emphasis>
+. If <emphasis>
+approx</emphasis>
+ is <emphasis>
+NULL</emphasis>
+, the top surface is defined as the last outline in the <emphasis>
+shape</emphasis>
+’s array of outlines. <emphasis>
+XkbComputeShapeTop</emphasis>
+ returns <emphasis>
+False</emphasis>
+ if <emphasis>
+shape</emphasis>
+ is <emphasis>
+NULL</emphasis>
+ or if there are no outlines for the shape; otherwise, it returns
+<emphasis>True</emphasis>.
+</para>
+
+
+<para>
+A <emphasis>
+ShapeRec</emphasis>
+ contains a <emphasis>
+BoundsRec</emphasis>
+ that describes the bounds of the shape. If you add or delete an outline to or
+from a shape, the bounding box must be updated. To update the bounding box of a
+shape, use <emphasis>XkbComputeShapeBounds</emphasis>.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Bool <emphasis>
+XkbComputeShapeBounds</emphasis>
+(<emphasis>
+shape</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbShapePtr <emphasis>
+ shape</emphasis>
+; /* shape to be examined */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbComputeShapeBounds</emphasis>
+ updates the <emphasis>
+BoundsRec</emphasis>
+ contained in the <emphasis>
+shape</emphasis>
+ by examining all the outlines of the shape and setting the <emphasis>
+BoundsRec</emphasis>
+ to the minimum x and minimum y, and maximum x and maximum y values found in
+those outlines. <emphasis>
+XkbComputeShapeBounds</emphasis>
+ returns <emphasis>
+False</emphasis>
+ if <emphasis>
+shape</emphasis>
+ is <emphasis>
+NULL</emphasis>
+ or if there are no outlines for the shape; otherwise, it returns <emphasis>
+True</emphasis>
+.
+</para>
+
+<para>
+ If you add or delete a key to or from a row, or if you update the shape of one
+of the keys in that row, you may need to update the bounding box of that row.
+To update the bounding box of a row, use <emphasis>XkbComputeRowBounds</emphasis>.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Bool <emphasis>
+XkbComputeRowBounds</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ section</emphasis>
+,<emphasis>
+ row</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry that contains the <emphasis>
+section</emphasis>
+ */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section that contains the row */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbRowPtr <emphasis>
+row</emphasis>
+; /* row to be examined and updated */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbComputeRowBounds</emphasis>
+ checks the bounds of all keys in the <emphasis>
+row </emphasis>
+and updates the bounding box of the row if necessary. <emphasis>
+XkbComputeRowBounds</emphasis>
+ returns <emphasis>
+False</emphasis>
+ if any of the arguments is <emphasis>
+NULL</emphasis>
+; otherwise, it returns <emphasis>
+True</emphasis>
+.
+</para>
+
+<para>
+ If you add or delete a row to or from a section, or if you change the geometry
+of any of the rows in that section, you may need to update the bounding box for
+that section. To update the bounding box of a section, use
+<emphasis>XkbComputeSectionBounds</emphasis>.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Bool <emphasis>
+XkbComputeSectionBounds</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ section</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry that contains the <emphasis>
+section</emphasis>
+ */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section to be examined and updated */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbComputeSectionBounds</emphasis>
+ examines all the rows of the <emphasis>
+section</emphasis>
+ and updates the bounding box of that section so that it contains all rows.
+<emphasis>
+XkbComputeSectionBounds</emphasis>
+ returns <emphasis>
+False</emphasis>
+ if any of the arguments is <emphasis>
+NULL</emphasis>
+; otherwise, it returns <emphasis>
+True</emphasis>
+.
+</para>
+
+<para>
+Keys that can generate multiple keycodes may be associated with multiple names.
+Such keys have a primary name and an alternate name. To find the alternate name
+by using the primary name for a key that is part of an overlay, use <emphasis>
+XkbFindOverlayForKey</emphasis>.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+char * <emphasis>
+XkbFindOverlayForKey</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ section</emphasis>
+,<emphasis>
+ under</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry that contains the <emphasis>
+section</emphasis>
+ */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section to be searched for matching keys */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+char * <emphasis>
+ under</emphasis>
+. /* primary name of the key to be considered */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbFindOverlayForKey</emphasis>
+ uses the primary name of the key, <emphasis>
+under</emphasis>
+, to look up the alternate name, which it returns.
+</para>
+
+
+</sect1>
+<sect1 id='adding_elements_to_a_keyboard_geometry'>
+<title>Adding Elements to a Keyboard Geometry</title>
+
+<para>
+Xkb provides functions to add a single new element to the top-level keyboard
+geometry. In each case the <emphasis>
+num_ </emphasis>
+<emphasis>
+*</emphasis>
+ fields of the corresponding structure is incremented by 1. These functions do
+not change <emphasis>
+sz_</emphasis>
+<emphasis>
+*</emphasis>
+ unless there is no more room in the array. Some of these functions fill in the
+values of the element’s structure from the arguments. For other functions,
+you must explicitly write code to fill the structure’s elements.
+</para>
+
+
+<para>
+The top-level geometry description includes a list of <emphasis>
+geometry properties</emphasis>
+. A geometry property associates an arbitrary string with an equally arbitrary
+name. Programs that display images of keyboards can use geometry properties as
+hints, but they are not interpreted by Xkb. No other geometry structures refer
+to geometry properties.
+</para>
+
+
+<para>
+To add one property to an existing keyboard geometry description, use <emphasis>
+XkbAddGeomProperty</emphasis>
+.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbPropertyPtr <emphasis>
+XkbAddGeomProperty</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ name</emphasis>
+,<emphasis>
+ value</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+char * <emphasis>
+ name</emphasis>
+; /* name of the new property */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+char * <emphasis>
+ value</emphasis>
+; /* value for the new property */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAddGeomProperty</emphasis>
+ adds one property with the specified <emphasis>
+name</emphasis>
+ and <emphasis>
+value</emphasis>
+ to the keyboard geometry specified by geom.<emphasis>
+ </emphasis>
+<emphasis>
+XkbAddGeomProperty</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space for
+the property. To allocate space for an arbitrary number of properties, use the
+XkbAllocGeomProps function.
+</para>
+
+
+<para>
+To add one key alias to an existing keyboard geometry description, use
+<emphasis>
+XkbAddGeomKeyAlias</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbKeyAliasPtr <emphasis>
+XkbAddGeomKeyAlias</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ alias, real</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+char * <emphasis>
+ alias</emphasis>
+; /* alias to be added */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+char * <emphasis>
+ real</emphasis>
+; /* real name to be bound to the new alias */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAddGeomKeyAlias</emphasis>
+ adds one key alias with the value alias to the geometry geom, and associates
+it with the key whose real name is real. <emphasis>
+XkbAddGeomKeyAlias</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space for
+the alias. To allocate space for an arbitrary number of aliases, use the
+XkbAllocGeomKeyAliases function.
+</para>
+
+
+<para>
+To add one color name to an existing keyboard geometry description, use
+<emphasis>
+XkbAddGeomColor</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbColorPtr <emphasis>
+XkbAddGeomColor</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ spec</emphasis>
+,<emphasis>
+ pixel</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+char * <emphasis>
+ spec</emphasis>
+; /* color to be added */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+unsigned int <emphasis>
+ pixel</emphasis>
+; /* color to be added */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAddGeomColor</emphasis>
+ adds the specified color <emphasis>
+name</emphasis>
+ and <emphasis>
+pixel</emphasis>
+ to the specified geometry <emphasis>
+geom</emphasis>
+. The top-level geometry description includes a list of up to <emphasis>
+MaxColors</emphasis>
+ (32) <emphasis>
+color names</emphasis>
+. A color <emphasis>
+name</emphasis>
+ is a string whose interpretation is not specified by Xkb and neither is the
+<emphasis>
+pixel</emphasis>
+ value’s interpretation. All other geometry data structures refer to colors
+using their indices in this global list or pointers to colors in this list.
+<emphasis>
+XkbAddGeomColor</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space for
+the color. To allocate space for an arbitrary number of colors to a geometry,
+use the <emphasis>
+XkbAllocGeomColors</emphasis>
+ function.
+</para>
+
+<para>
+To add one outline to an existing shape, use <emphasis>
+XkbAddGeomOutline</emphasis>.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbOutlinePtr <emphasis>
+XkbAddGeomOutline</emphasis>
+(<emphasis>
+shape</emphasis>
+,<emphasis>
+ sz_points</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbShapePtr <emphasis>
+ shape</emphasis>
+; /* shape to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ sz_points</emphasis>
+; /* number of points to be reserved */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+An outline consists of an arbitrary number of points. <emphasis>
+XkbAddGeomOutline</emphasis>
+ adds an outline to the specified <emphasis>
+shape</emphasis>
+ by reserving <emphasis>
+sz_points</emphasis>
+ points for it. The new outline is allocated and zeroed. <emphasis>
+XkbAddGeomOutline</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space. To
+allocate space for an arbitrary number of outlines to a shape, use
+XkbAllocGeomOutlines.
+</para>
+
+
+<para>
+To add a shape to a keyboard geometry, use <emphasis>
+XkbAddGeomShape</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbShapePtr <emphasis>
+XkbAddGeomShape</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ name</emphasis>
+,<emphasis>
+ sz_outlines</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Atom <emphasis>
+ name</emphasis>
+; /* name of the new shape */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ sz_outlines</emphasis>
+; /* number of outlines to be reserved */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+A geometry contains an arbitrary number of shapes, each of which is made up of
+an arbitrary number of outlines. <emphasis>
+XkbAddGeomShape</emphasis>
+ adds a shape to a geometry <emphasis>
+geom</emphasis>
+ by allocating space for <emphasis>
+sz_outlines</emphasis>
+ outlines for it and giving it the name specified by name. If a shape with name
+<emphasis>
+name</emphasis>
+ already exists in the geometry, a pointer to the existing shape is returned.
+<emphasis>
+XkbAddGeomShape</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space. To
+allocate space for an arbitrary number of geometry shapes, use <emphasis>
+XkbAllocGeomShapes</emphasis>
+.
+</para>
+
+
+<para>
+To add one key at the end of an existing row of keys, use <emphasis>
+XkbAddGeomKey</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbKeyPtr <emphasis>
+XkbAddGeomKey</emphasis>
+(<emphasis>
+row</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbRowPtr <emphasis>
+ row</emphasis>
+; /* row to be updated */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+Keys are grouped into rows. <emphasis>
+XkbAddGeomKey</emphasis>
+ adds one key to the end of the specified <emphasis>
+row</emphasis>
+. The key is allocated and zeroed. <emphasis>
+XkbAddGeomKey</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if <emphasis>
+row</emphasis>
+ is empty or if it was not able to allocate space for the key. To allocate
+space for an arbitrary number of keys to a row, use XkbAllocGeomKeys.
+</para>
+
+
+<para>
+To add one section to an existing keyboard geometry, use <emphasis>
+XkbAddGeomSection</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbSectionPtr <emphasis>
+XkbAddGeomSection</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ name</emphasis>
+,<emphasis>
+ sz_rows</emphasis>
+,<emphasis>
+ sz_doodads</emphasis>
+,<emphasis>
+ sz_overlays</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Atom <emphasis>
+ name</emphasis>
+; /* name of the new section */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ sz_rows</emphasis>
+; /* number of rows to reserve in the section */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ sz_doodads</emphasis>
+; /* number of doodads to reserve in the section */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ sz_overlays</emphasis>
+; /* number of overlays to reserve in the section */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+A keyboard geometry contains an arbitrary number of sections. <emphasis>
+XkbAddGeomSection</emphasis>
+ adds one section to an existing keyboard geometry <emphasis>
+geom</emphasis>
+. The new section contains space for the number of rows, doodads, and overlays
+specified by <emphasis>
+sz_rows</emphasis>
+, <emphasis>
+sz_doodads</emphasis>
+, and <emphasis>
+sz_overlays</emphasis>
+. The new section is allocated and zeroed and given the name specified by
+<emphasis>
+name</emphasis>
+. If a section with name <emphasis>
+name</emphasis>
+ already exists in the geometry, a pointer to the existing section is
+returned.<emphasis>
+ XkbAddGeomSection</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space for
+the section. To allocate space for an arbitrary number of sections to a
+geometry, use XkbAllocGeomSections.
+</para>
+
+
+<para>
+To add a row to a section, use <emphasis>
+XkbAddGeomRow</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbRowPtr <emphasis>
+XkbAddGeomRow</emphasis>
+(<emphasis>
+section</emphasis>
+,<emphasis>
+ sz_keys</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+sz_keys</emphasis>
+; /* number of keys to be reserved */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+One of the components of a keyboard geometry section is one or more rows of
+keys. <emphasis>
+XkbAddGeomRow</emphasis>
+ adds one row to the specified <emphasis>
+section</emphasis>
+. The newly created row contains space for the number of keys specified in
+<emphasis>
+sz_keys</emphasis>
+. They are allocated and zeroed, but otherwise uninitialized. <emphasis>
+XkbAddGeomRow</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space for
+the row. To allocate space for an arbitrary number of rows to a section, use
+the XkbAllocGeomRows function.
+</para>
+
+
+<para>
+To add one doodad to a section of a keyboard geometry or to the top-level
+geometry, use <emphasis>
+XkbAddGeomDoodad</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbDoodadPtr <emphasis>
+XkbAddGeomDoodad</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ section</emphasis>
+,<emphasis>
+ name</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry to which the doodad is added */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section, if any, to which the doodad is added */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Atom <emphasis>
+ name</emphasis>
+; /* name of the new doodad */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+A <emphasis>
+doodad</emphasis>
+ describes some visible aspect of the keyboard that is not a key and is not a
+section. <emphasis>
+XkbAddGeomDoodad</emphasis>
+ adds a doodad with name specified by name to the geometry <emphasis>
+geom</emphasis>
+ if section is <emphasis>
+NULL</emphasis>
+ or to the section of the geometry specified by section if <emphasis>
+section</emphasis>
+ is not <emphasis>
+NULL</emphasis>
+. <emphasis>
+XkbAddGeomDoodad</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space for
+the doodad. If there is already a doodad with the name <emphasis>
+name</emphasis>
+ in the doodad array for the geometry (if <emphasis>
+section</emphasis>
+ is <emphasis>
+NULL</emphasis>
+) or the section (if <emphasis>
+section</emphasis>
+ is non-<emphasis>
+NULL</emphasis>
+), a pointer to that doodad is returned. To allocate space for an arbitrary
+number of doodads to a section, use the XkbAllocGeomSectionDoodads function. To
+allocate space for an arbitrary number of doodads to a keyboard geometry, use
+the XkbAllocGeomDoodads function.
+</para>
+
+
+<para>
+To add one overlay to a section, use <emphasis>
+XkbAddGeomOverlay</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbOverlayPtr <emphasis>
+XkbAddGeomOverlay</emphasis>
+(<emphasis>
+section</emphasis>
+,<emphasis>
+ name</emphasis>
+,<emphasis>
+ sz_rows</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section to which an overlay will be added */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Atom <emphasis>
+ name</emphasis>
+; /* name of the overlay */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ sz_rows</emphasis>
+; /* number of rows to reserve in the overlay */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAddGeomOverlay</emphasis>
+ adds an overlay with the specified name to the specified <emphasis>
+section</emphasis>
+. The new overlay is created with space allocated for sz_rows rows. If an
+overlay with name <emphasis>
+name</emphasis>
+ already exists in the section, a pointer to the existing overlay is
+returned.<emphasis>
+ XkbAddGeomOverlay</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space for
+the overlay. To allocate space for an arbitrary number of overlays to a
+section, use the XkbAllocGeomOverlay function.
+</para>
+
+
+<para>
+To add a row to an existing overlay, use <emphasis>
+XkbAddGeomOverlayRow</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbOverlayRowPtr <emphasis>
+XkbAddGeomOverlayRow</emphasis>
+(<emphasis>
+overlay</emphasis>
+,<emphasis>
+ row_under, sz_keys</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbOverlayPtr <emphasis>
+ overlay</emphasis>
+; /* overlay to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbRowPtr <emphasis>
+ row_under</emphasis>
+; /* row to be overlayed in the section <emphasis>
+overlay</emphasis>
+ overlays */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ sz_keys</emphasis>
+; /* number of keys to reserve in the row */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAddGeomOverlayRow</emphasis>
+ adds one row to the <emphasis>
+overlay</emphasis>
+. The new row contains space for <emphasis>
+sz_keys</emphasis>
+ keys. If <emphasis>
+row_under</emphasis>
+ specifies a row that doesn’t exist on the underlying section, <emphasis>
+XkbAddGeomOverlayRow</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ and doesn’t change the overlay.<emphasis>
+ XkbAddGeomOverlayRow</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+ if any of the parameters is empty or if it was not able to allocate space for
+the overlay.
+</para>
+
+
+<para>
+To add a key to an existing overlay row, use <emphasis>
+XkbAddGeomOverlayKey</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+XkbOverlayKeyPtr <emphasis>
+XkbAddGeomOverlayKey</emphasis>
+(<emphasis>
+overlay</emphasis>
+,<emphasis>
+ row, under</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbOverlayPtr <emphasis>
+ overlay</emphasis>
+; /* overlay to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbRowPtr <emphasis>
+ row</emphasis>
+; /* row in overlay to be updated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+char * <emphasis>
+ under</emphasis>
+; /* primary name of the key to be considered */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAddGeomOverlayKey</emphasis>
+ adds one key to the <emphasis>
+row</emphasis>
+ in the <emphasis>
+overlay</emphasis>
+. If there is no key named <emphasis>
+under</emphasis>
+ in the row of the underlying section, <emphasis>
+XkbAddGeomOverlayKey</emphasis>
+ returns <emphasis>
+NULL</emphasis>
+.
+</para>
+
+
+</sect1>
+<sect1 id='allocating_and_freeing_geometry_components'>
+<title>Allocating and Freeing Geometry Components</title>
+
+<para>
+Xkb provides a number of functions to allocate and free subcomponents of a
+keyboard geometry. Use these functions to create or modify keyboard geometries.
+Note that these functions merely allocate space for the new element(s), and it
+is up to you to fill in the values explicitly in your code. These allocation
+functions increase <emphasis>
+sz_</emphasis>
+<emphasis>
+*</emphasis>
+ but never touch <emphasis>
+num_</emphasis>
+<emphasis>
+*</emphasis>
+ (unless there is an allocation failure, in which case they reset both
+<emphasis>
+sz_</emphasis>
+<emphasis>
+*</emphasis>
+ and <emphasis>
+num_</emphasis>
+<emphasis>
+*</emphasis>
+ to zero). These functions return <emphasis>
+Success</emphasis>
+ if they succeed, <emphasis>
+BadAlloc</emphasis>
+ if they are not able to allocate space, or <emphasis>
+BadValue</emphasis>
+ if a parameter is not as expected.
+</para>
+
+
+<para>
+To allocate space for an arbitrary number of outlines to a shape, use
+XkbAllocGeomOutlines.
+</para>
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomOutlines</emphasis>
+(<emphasis>
+shape</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbShapePtr <emphasis>
+shape</emphasis>
+; /* shape for which outlines should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new outlines required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomOutlines</emphasis>
+ allocates space for <emphasis>
+num_needed</emphasis>
+ outlines in the specified <emphasis>
+shape</emphasis>
+. The outlines are not initialized.
+</para>
+
+
+<para>
+To free geometry outlines, use <emphasis>
+XkbFreeGeomOutlines</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomOutlines</emphasis>
+(<emphasis>
+shape</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbShapePtr <emphasis>
+ shape</emphasis>
+; /* shape in which outlines should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first outline to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of outlines to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all outlines are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all outlines are freed regardless of the value of first or count. Otherwise,
+count outlines are freed beginning with the one specified by first.
+</para>
+
+
+<para>
+To allocate space for an arbitrary number of keys to a row, use
+XkbAllocGeomKeys.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomKeys</emphasis>
+(<emphasis>
+row</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbRowPtr <emphasis>
+ row</emphasis>
+; /* row to which keys should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new keys required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomKeys</emphasis>
+ allocates num_needed keys and adds them to the row. No initialization of the
+keys is done.
+</para>
+
+
+<para>
+To free geometry keys, use <emphasis>
+XkbFreeGeomKeys</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomKeys</emphasis>
+(<emphasis>
+row</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbRowPtr <emphasis>
+ row</emphasis>
+; /* row in which keys should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first key to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of keys to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all keys are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all keys are freed regardless of the value of first or count. Otherwise,
+count keys are freed beginning with the one specified by first.
+</para>
+
+
+<para>
+To allocate geometry properties, use <emphasis>
+XkbAllocGeomProps</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomProps</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry for which properties should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new properties required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomProps</emphasis>
+ allocates space for num_needed properties and adds them to the specified
+geometry <emphasis>
+geom</emphasis>
+. No initialization of the properties is done. A geometry property associates
+an arbitrary string with an equally arbitrary name. Geometry properties can be
+used to provide hints to programs that display images of keyboards, but they
+are not interpreted by Xkb. No other geometry structures refer to geometry
+properties.
+</para>
+
+
+<para>
+To free geometry properties, use <emphasis>
+XkbFreeGeomProperties</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomProperties</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry in which properties should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first property to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of properties to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all properties are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all properties are freed regardless of the value of first or count.
+Otherwise, count properties are freed beginning with the one specified by first.
+</para>
+
+
+<para>
+To allocate geometry key aliases, use <emphasis>
+XkbAllocGeomKeyAliases</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomKeyAliases</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry for which key aliases should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new key aliases required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomKeyAliases</emphasis>
+ allocates space for num_needed key aliases and adds them to the specified
+geometry <emphasis>
+geom</emphasis>
+. A key alias is a pair of strings that associates an alternate name for a key
+with the real name for that key.
+</para>
+
+
+<para>
+To free geometry key aliases, use <emphasis>
+XkbFreeGeomKeyAliases</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomKeyAliases</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ first</emphasis>
+, <emphasis>
+count</emphasis>
+, <emphasis>
+free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry in which key aliases should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first key alias to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of key aliases to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all key aliases are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all aliases in the top level of the specified geometry <emphasis>
+geom</emphasis>
+ are freed regardless of the value of first or count. Otherwise, count aliases
+in <emphasis>
+geom</emphasis>
+ are freed beginning with the one specified by first.
+</para>
+
+
+<para>
+To allocate geometry colors, use <emphasis>
+XkbAllocGeomColors</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomColors</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry for which colors should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new colors required. */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomColors</emphasis>
+ allocates space for num_needed colors and adds them to the specified geometry
+<emphasis>
+geom</emphasis>
+. A color name is a string whose interpretation is not specified by Xkb. All
+other geometry data structures refer to colors using their indices in this
+global list or pointers to colors in this list.
+</para>
+
+
+<para>
+To free geometry colors, use <emphasis>
+XkbFreeGeomColors</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomColors</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry in which colors should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first color to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of colors to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all colors are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all colors are freed regardless of the value of first or count. Otherwise,
+count colors are freed beginning with the one specified by first.
+</para>
+
+
+<para>
+To allocate points in an outline, use <emphasis>
+XkbAllocGeomPoints</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomPoints</emphasis>
+(<emphasis>
+outline</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbOutlinePtr <emphasis>
+ outline</emphasis>
+; /* outline for which points should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new points required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomPoints</emphasis>
+ allocates space for <emphasis>
+num_needed</emphasis>
+ points in the specified <emphasis>
+outline</emphasis>
+. The points are not initialized.
+</para>
+
+
+<para>
+To free points in a outline, use <emphasis>
+XkbFreeGeomPoints</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomPoints</emphasis>
+(<emphasis>
+outline</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbOutlinePtr <emphasis>
+ outline</emphasis>
+; /* outline in which points should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first point to be freed. */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of points to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all points are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all points are freed regardless of the value of first and count. Otherwise,
+the number of points specified by count are freed, beginning with the point
+specified by first in the specified outline.
+</para>
+
+
+<para>
+To allocate space for an arbitrary number of geometry shapes, use <emphasis>
+XkbAllocGeomShapes</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomShapes</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry for which shapes should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new shapes required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomShapes</emphasis>
+ allocates space for <emphasis>
+num_needed</emphasis>
+ shapes in the specified geometry <emphasis>
+geom</emphasis>
+. The shapes are not initialized.
+</para>
+
+
+<para>
+To free geometry shapes, use <emphasis>
+XkbFreeGeomShapes</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomShapes</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ f ree_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry in which shapes should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first shape to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of shapes to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all shapes are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all shapes in the geometry are freed regardless of the values of first and
+count. Otherwise, count shapes are freed, beginning with the shape specified by
+first.
+</para>
+
+
+<para>
+To allocate geometry sections, use <emphasis>
+XkbAllocGeomSections</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomSections</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /*geometry for which sections should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new sections required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomSections</emphasis>
+ allocates num_needed sections and adds them to the geometry geom. No
+initialization of the sections is done.
+</para>
+
+
+<para>
+To free geometry sections, use <emphasis>
+XkbFreeGeomSections</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomSections</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry in which sections should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first section to be freed. */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of sections to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all sections are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all sections are freed regardless of the value of first and count. Otherwise,
+the number of sections specified by count are freed, beginning with the section
+specified by first in the specified geometry.
+</para>
+
+
+<para>
+To allocate rows in a section, use <emphasis>
+XkbAllocGeomRows</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomRows</emphasis>
+(<emphasis>
+section</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+section</emphasis>
+; /* section for which rows should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new rows required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomRows</emphasis>
+ allocates num_needed rows and adds them to the section. No initialization of
+the rows is done.
+</para>
+
+
+<para>
+To free rows in a section, use <emphasis>
+XkbFreeGeomRows</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomRows</emphasis>
+(<emphasis>
+section</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section in which rows should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first row to be freed. */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of rows to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all rows are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all rows are freed regardless of the value of first and count. Otherwise, the
+number of rows specified by count are freed, beginning with the row specified
+by first in the specified section.
+</para>
+
+
+<para>
+To allocate overlays in a section, use <emphasis>
+XkbAllocGeomOverlays</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomOverlays</emphasis>
+(<emphasis>
+section</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+section</emphasis>
+; /* section for which overlays should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new overlays required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomRows</emphasis>
+ allocates num_needed overlays and adds them to the section. No initialization
+of the overlays is done.
+</para>
+
+
+<para>
+To free rows in an section, use <emphasis>
+XkbFreeGeomOverlays</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomOverlays</emphasis>
+(<emphasis>
+section</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section in which overlays should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first overlay to be freed. */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of overlays to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all overlays are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all overlays are freed regardless of the value of first and count. Otherwise,
+the number of overlays specified by count are freed, beginning with the overlay
+specified by first in the specified section.
+</para>
+
+
+<para>
+To allocate rows in a overlay, use <emphasis>
+XkbAllocGeomOverlayRows</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomOverlayRows</emphasis>
+(<emphasis>
+overlay</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+overlay</emphasis>
+; /* section for which rows should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new rows required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomOverlayRows</emphasis>
+ allocates num_needed rows and adds them to the overlay. No initialization of
+the rows is done.
+</para>
+
+
+<para>
+To free rows in an overlay, use <emphasis>
+XkbFreeGeomOverlayRows</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomOverlayRows</emphasis>
+(<emphasis>
+overlay</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ overlay</emphasis>
+; /* section in which rows should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first row to be freed. */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of rows to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all rows are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all rows are freed regardless of the value of first and count. Otherwise, the
+number of rows specified by count are freed, beginning with the row specified
+by first in the specified overlay.
+</para>
+
+
+<para>
+To allocate keys in an overlay row, use <emphasis>
+XkbAllocGeomOverlayKeys</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomOverlayKeys</emphasis>
+(<emphasis>
+row</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbRowPtr <emphasis>
+row</emphasis>
+; /* section for which rows should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new rows required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomOverlayKeys</emphasis>
+ allocates num_needed keys and adds them to the row. No initialization of the
+keys is done.
+</para>
+
+
+<para>
+To free keys in an overlay row, use <emphasis>
+XkbFreeGeomOverlayKeys</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomOverlayKeys</emphasis>
+(<emphasis>
+row</emphasis>
+,<emphasis>
+ first</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbRowPtr <emphasis>
+ row</emphasis>
+; /* row in which keys should be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ first</emphasis>
+; /* first key to be freed. */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of keys to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all keys are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, all keys are freed regardless of the value of first and count. Otherwise, the
+number of keys specified by count are freed, beginning with the key specified
+by first in the specified row.
+</para>
+
+
+<para>
+To allocate doodads that are global to a keyboard geometry, use <emphasis>
+XkbAllocGeomDoodads</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomDoodads</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry for which doodads should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new doodads required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomDoodads</emphasis>
+ allocates num_needed doodads and adds them to the specified geometry <emphasis>
+geom</emphasis>
+. No initialization of the doodads is done.
+</para>
+
+
+<para>
+To allocate doodads that are specific to a section, use <emphasis>
+XkbAllocGeomSectionDoodads</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeomSectionDoodads</emphasis>
+(<emphasis>
+section</emphasis>
+,<emphasis>
+ num_needed</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbSectionPtr <emphasis>
+ section</emphasis>
+; /* section for which doodads should be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ num_needed</emphasis>
+; /* number of new doodads required */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeomSectionDoodads</emphasis>
+ allocates num_needed doodads and adds them to the specified <emphasis>
+section</emphasis>
+. No initialization of the doodads is done.
+</para>
+
+
+<para>
+To free geometry doodads, use <emphasis>
+XkbFreeGeomDoodads</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeomDoodads</emphasis>
+(<emphasis>
+doodads</emphasis>
+,<emphasis>
+ count</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbDoodadPtr <emphasis>
+ doodads</emphasis>
+; /* doodads to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+int <emphasis>
+ count</emphasis>
+; /* number of doodads to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; all doodads are freed */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+If <emphasis>
+free_all</emphasis>
+ is <emphasis>
+True</emphasis>
+, all doodads in the array are freed, regardless of the value of count.
+Otherwise, count doodads are freed.
+</para>
+
+
+<para>
+To allocate an entire geometry, use <emphasis>
+XkbAllocGeometry</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+Status <emphasis>
+XkbAllocGeometry</emphasis>
+(<emphasis>
+xkb</emphasis>
+,<emphasis>
+ sizes</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbDescPtr <emphasis>
+ xkb</emphasis>
+; /* keyboard description for which geometry is to be allocated */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometrySizesPtr<emphasis>
+ sizes</emphasis>
+; /* initial sizes for all geometry components */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+<emphasis>
+XkbAllocGeometry</emphasis>
+ allocates a keyboard geometry and adds it to the keyboard description
+specified by xkb. The keyboard description should be obtained via the
+XkbGetKeyboard or XkbAllockeyboard functions. The sizes parameter specifies the
+number of elements to be reserved for the subcomponents of the keyboard
+geometry and can be zero or more. These subcomponents include the properties,
+colors, shapes, sections, and doodads.
+</para>
+
+
+<para>
+To free an entire geometry, use <emphasis>
+XkbFreeGeometry</emphasis>
+.
+</para>
+
+
+<informaltable frame='none'>
+<tgroup cols='1'>
+<colspec colsep='0'/>
+<tbody>
+ <row rowsep='0'>
+ <entry role='functiondecl'>
+void <emphasis>
+XkbFreeGeometry</emphasis>
+(<emphasis>
+geom</emphasis>
+,<emphasis>
+ which</emphasis>
+,<emphasis>
+ free_all</emphasis>
+)
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+XkbGeometryPtr <emphasis>
+ geom</emphasis>
+; /* geometry to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+unsigned int <emphasis>
+ which</emphasis>
+; /* mask of geometry components to be freed */
+ </entry>
+ </row>
+ <row rowsep='0'>
+ <entry role='functionargdecl'>
+Bool <emphasis>
+ free_all;</emphasis>
+ /* <emphasis>
+True</emphasis>
+ =&gt; the entire geometry is freed. */
+ </entry>
+</row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+The values of which and free_all determine how much of the specified geometry
+is freed. The valid values for which are:
+</para>
+
+<para><programlisting>
+#define XkbGeomPropertiesMask (1&lt;&lt;0)
+#define XkbGeomColorsMask (1&lt;&lt;1)
+#define XkbGeomShapesMask (1&lt;&lt;2)
+#define XkbGeomSectionsMask (1&lt;&lt;3)
+#define XkbGeomDoodadsMask (1&lt;&lt;4)
+#define XkbGeomAllMask (0x1f)
+</programlisting></para>
+
+<para>
+If free_all is <emphasis>
+True</emphasis>
+, the entire geometry is freed regardless of the value of which. Otherwise, the
+portions of the geometry specified by which are freed.
+</para>
+
+</sect1>
+</chapter>