Sometimes, however, the user may want to refer to a single element in the document instance. For example, the user may want to extract the contents of a specific element and therefore has to refer to that individual element inside the document. Of course, the user does not want to extract the content of all elements of a certain type, but the contents of a single individual element. Therefore, the user wants to refer to an element instance.
The sgml widget solves this problem by providing two ways to access SGML elements: element names and element handles. Element names and element handles can not be used interchangeably; some of the widget commands (or subcommands of widget commands) expect element handles as parameters; some expect element names. It should be clear from the semantics of the command which type of parameter is expected; if you find that you want to use a command that expects an element handle, but you want to provide an element name, the command is not appropriate for achieving the desired effects.
<!ELEMENT...> statement in the DTD.
![]() |
Widget commands that take element names as parameters affect all elements with that name in the document instance. |
Element handles are created by the sgml widget on demand and remain valid as long as the element referred to exists. Element handles may be obtained in three ways:
Widget commands that take element handles as parameters affect only one element in the document instance (and possible the children of this element), regardless of whether there are any other element with the same name in the document.
The command element at can be used to determine which element contains a given position in the document. Most of the time, the element containing the insertion cursor will be retrieved with:
| .s element at insert |
A slightly more complex example is given below. This script traces the location of the mouse cursor and sets the title of the Tk application window to the name containing the element.
{}
proc motion_proc { x y } {
set ref [ .s element at @$x,$y ]
if { $ref != "" } {
wm title . [ .s element name $ref ]
}
}
bind .s <Motion> {motion_proc %x %y}
Please note that you should not take this example too seriously. In a
real-world application, you would probably not want to set the title
of the the application window, especially if you are concerned
about performance issues. Configuring the text of a Tk label widget is
usually much faster than setting the window title which involves the
overhead of the ICCCM protocol to communicate with the window
manager.
An element handle for the parent element of an element can be retrieved by the element parent command which takes one parameter, the handle for the element for which the parent is requested. The element parent command returns a handle for the parent element of the element:
| .s element at insert | |
| E420a12c | |
| .s element name E420a12c | |
| SECTION | |
| .s element parent [ .s element at insert ] | |
| E4644072 | |
| .s element name E4644072 | |
| CHAPTER |
The element parent command returns an empty string if a handle for the top-level element has been used:
| .s element parent [ .s document element ] | |
| "" |
The element content command makes it possible to access the contents of an element. Like the element parent command, it takes an element handle to refer to a specific element in the document instance. The content of the element is returned in a special format. This format is a list of specifier-content pairs that represents the contents of the element in the order in which they appear in the document text.
Each element of the list returned by the element content command is a pair that has a specifier character as its first element. The specifier character is used to distinguish different kinds of element content. The element content appears as the second element of each pair.
For example, the contents of the EXAMPLE2 element in
figure
would be returned as the following list:
{{D {Line 1}} {E E8561c80} {D {Line 2}}}
This list has three elements, each element being a list itself. Each of these embedded lists contains a specifier character that gives information about the content type of the embedded list and the content itself (formatted in such a way that it can be retrieved with Tcl list command, e.g. with lindex).
The first pair in this list consists of the two elements D as th specifier character and {Line 1} as the content. The specifier D states the the second element of the pair contains data. The second pair in the list contains the specifier E, denoting an element handle as the second pair element.
The following table lists the content specifiers that are returned by the sgml widget together with the content type they denote:
| D | PCDATA formatted as a proper list element |
| E | An element handle for a subordinated element |
| N | An entity name |
| R | A record end character |
These commands can be used to implement rudimentary document traversal. For example, the following script would traverse the document tree and print an indented structural representation of the document in the sgml widget .s
Many of the examples above have used an index for retrieving an element handle, but sometimes it is necessary to determine the location of an element in the SGML document. The sgml widget provides the element index command for this purposes.
This command expects an element handle as a parameter an returns an index string that can be used in sucessive Tcl commands. If used with only one parameter ref, the command returns the location of the start tag of the element referenced by ref. The location returned is the position immediately to the left of the element tag, i.e. it is outside of the element:
| set ref [.s document element] | |
| E8644200 | |
| .s element index $ref | |
| 1.0 |
In a second form, the element index command accepts the additional keyword parameter end after the element handle parameter and returns the location of the end tag of the element.
Again, the location returned is the position immediately to the left of the element tag, i.e. it is inside the element:
| set ref [.s document element] | |
| E8644200 | |
| .s element index $ref end | |
| 13.24 |
The element index command can be used for several interesting purposes. For example, it is possibe to make an element responsive to mouse clicks as demonstrated in the following script:
proc show_name { x y } {
set ref [ .s element at @$x,$y ]
if { $ref != "" } {
puts "Element [ .s element name $ref ] selected"
}
}
set eref [ .s element at insert ]
set idx_start [ .s element index $eref ]
set idx_end [ .s element index $eref end ]
.s tag add myTag $idx_start $idx_end
.s tag bind myTag <ButtonRelease> { show_name %x %y }
This script makes use of the tag command. The tags inserted by
the tag command are essentially text widget tags and the
command name tag has been retained for compatibility with the
text widget. It is important not to confuse these text widget tags
with element tags that relate to the element strucutre of the SGML
document. More details on text widget tags can be found in the
documentation for the Tk text widget.
, but
most of the command options are explained in detail in the following
chapters.
The element insert command takes two parameters to specify what type of element to insert and where to insert this element. The following command would insert a new element P before the three characters before the end of the document.
| .s element insert P end-3c | |
| E3514a42 |
The first parameter for the element insert command is the name of an element as it has been defined in the DTD. (The current implementation of the sgml widget requires the correct case for element names.)
The second parameter denotes the location where the element should be inserted into the document. Locations are specified as indices in the same way as text widget indices.
The element insert command verifies that the element can be inserted at the specified location and refuses to insert the element if the DTD does not allow an element of the specified kind to appear at that location.
Inserting an element that is not specified in the DTD is an error:
| .s element insert BLA insert+2c | |
| Element "BLA" not found in dtd |
The element insert command returns a handle for the new element if the element insertion was successful. If the DTD does not allow the insertion of this element at index, an error is signalled.
It is possible to determine which elements can be inserted at a location in the document by using the element allowed command. This command uses exactly the same mechanisms as element insert command, but it returns a list of insertable elements instead of inserting an element. The following command can be used to determine the elements that could be inserted at the current location of the insertion cursor:
| .s element allowed insert |
The element allowed command return a Tcl list with element names. Each of these names could be used as a parameter to the element insert command. The element insert command, in turn, is guaranteed to return a new element handle for any element of the list returned by the element allowed command (provided, of course, that both commands refer to the same absolute position in the document and that the element structure has not been changed between the invocations of the two commands. Therefore, the following sequence of commands will never fail:
| set l [ .s element allowed insert ] | |
| if { [ llenght $l ] > 0 } { | |
| .s element insert [ lindex $l 0 ] insert } | |
| E8641e80 |
It is possible to enclose data already present in a new element by providing a second index to the element insert command. If a second index is provided, all data in the range from the first to the second index becomes the content of the new element.
The sgml widget will not insert an enclosing element if any of the following conditions are met:
EMPTY in the DTD.
When enclosing exisiting data in a new element, the sgml widget does not verify that the enclosed data is compatible with the elements content model (apart from checking that the element has not been declared as an empty element). Adding further markup may be necessary in order to make the element valid.
A convenient way to turn a portion of the document into a new element is to use the selection for these purposes. When the user selects a region of the text with the mouse, the two indices sel.first and sel.last can be used to refer to the boundaries of the selected text. The following command encloses the currently selected text with the element em:
| .s element insert EM sel.first sel.last | |
| E8641e80 |
Hint: If you implement this approach in an X11 environment and provide a listbox for the user to choose an element, make sure to prevent the listbox from exporting the selection by using the option -exportselection 0 when creating the listbox. If you do not inhibit the selection export for the listbox, the listbox will steal the selection from the sgml widget when the user selects an entry in the list. This will result in the sgml widget failing to enclose the selected data because the selection has been removed and the index specifications have become invalid.
Please refer to the documentation of the Tk text widget for any details about the selection mechanism.
Attempts to enclose data in a new element results in an error message if the range specified for enclosure is invalid with respect to any of the conditions mentioned above.
pathName element rename handle ?name?
can be used. If the argument name is omitted, the command returns a list of element names to which the element identified by handle can be renamed. If handle can not be renamed to another element, this list will be empty.
If the name argument is provided, the element type of the element identified by handle will be changed to name. If handle can not be renamed to name, the command generates an error.
When an element is renamed, the current attributes of the element will be retained if they are compatible with the attribute definitions of the new element type. Attributes are considered to be compatible if they have the same name, the same declared value, and the same defaullt value type. Incompatible attributes will be dropped when an element is renamed.
| .s element delete [.s document element] | |
| Can't delete top-level element |
Deleting an element destroys the element and all of its child elements including their data content. Any handles to the deleted element and its children become invalid when the element has been deleted:
| set ref [ .s element at insert ] | |
| E8561c80 | |
| set parent_ref [ .s element parent $ref ] | |
| E85582a0 | |
| .s element delete $parent_ref | |
| .s element name $parent_ref | |
| Invalid element handle "E85582a0" | |
| .s element name $ref | |
| Invalid element handle "E8561c80" |
The element remove command can be used to remove any element in the document instance other than the document element:
| .s element remove [.s document element] | |
| Can't remove top-level element |
As opposed to the element delete command, removing an element with the element remove command does not destroy any data but removes the markup around the data embedded into the removed element.
| set ref [ .s element at 3.17 ] | |
| E8561c80 | |
| .s element name $ref | |
| P | |
| set parent_ref [ .s element parent $ref ] | |
| E85582a0 | |
| .s element remove $parent_ref | |
| .s element name $parent_ref | |
| Invalid element handle "E85582a0" | |
| .s element name $ref | |
| P |
Removing an element can be seen as the inversion of enclosing data in a new element.
It is possible to search for elements with the pcrmelement search widget command. This command has has the following general form:
pathName element search name index
?index2?
The command searches for the first ocurrence of an element with a name that matches the name argument and returns a handle for this element or an empty string if no such element is found.
The search starts at the index1 and stops at the end of the document (or at index2 if provided). The following example shows a procedure that accepts an element name as argument and returns the number of elements with this name in the current document:
proc countElement { name } {
set idx "1.0"
set count 0
for { set handle [ .s element search $name $idx ] } \
{ $handle != ""} \
{ set handle [ .s element search $name $idx ] } {
incr count
set idx "[ .s element index $handle]+1c"
}
return $count
}
Elements may become invalid during the editing process, e.g. because a required child element was deleted or a required attribute still needs to be specified. The current status of an element can be checked with the pcrmelement valid widget command. The command has has the following general form:
The result of the command is a boolean value that indicates whether the element identified by handle is currently valid or not.
While the pcrmelement valid command returns only the current status of an element, the content of a single element can be checked with the pcrmelement check widget command.
The command performs a quick check of the element identified by handle and returns a list of error messages that describe the problems that have been found. If no problems were detected with the given element, the command returns an empty list.
| .s element check E8641e80 | |
| Missing required attribute "ID" |
The pcrmelement check command performs only a quick test of the
element structure, but it does not carry out an in-depth validation of
the element content. Please refer to the description of the
pcrmvalidate widget command in section
for more details.
Elements can be configured to modify the text properties of their contents. There are two levels of element configuration: element type configuration and element insance configuration. When configuring an element type with the pathname element configure widget command, the configuration options apply to all elements of the specified type. The command
| .s element configure HEADING -bold 1 |
results in all elements of type heading being shown in bold face. Settings for the element type can be overridden by configuring element instances with the pathname element instanceconfigure widget command. The command
| .s element instanceconfigure E120ea45 -family times |
results in a times-font being used for the specific element instance E120ea45, regardless of which font-family configuration options have been set for the corresponding element type.
Specifies the normal background color to use when displaying the widget.
Bitmap specifies a bitmap that is used as a stipple pattern for
the background. It may have any of the forms described in
section
. If bitmap hasn't been specified, or if it is
specified as an empty string, then a solid fill will be used for the
background.
Specifies a non-negative value indicating the width
of the 3-D border to draw around the outside of the widget (if such a
border is being drawn; the -relief option typically determines
this). The value may also be used when drawing 3-D effects in the
interior of the widget. The value may have any of the forms described
in section
.
Usually, this option is only set during the load process in a prolog callback command. This option can not be used to configure an element instance.
Bitmap specifies a bitmap that is used as a stipple pattern
when drawing text and other foreground information such as
underlines. It may have any of the forms described in section
.
If bitmap hasn't been specified, or if it is
specified as an empty string, then a solid fill will be used.
Specifies the font to use when drawing text inside the widget.
This option is supported for compatibility with other Tk widgets and
applications only. Using the more flexible options -family,
-size, -bold, and -italic (see below) is
preferred since these options provider smoother interaction with the
text property inheritance scheme described in section
.
Specifies the normal foreground color to use when displaying the widget.
Specifies an image to display immediately to the left of the element's end tag. The image argument must be the name of an existing Tk image that has been created with the image create command. Note that the -image option can only be specified on a per-element basis, i.e. it can only be used as an option for the pcrmelement instanceconfigure widget command.
If the first character of a display line has a tag for which this option has been specified, then justify determines how to justify the line. It must be one of left, right, or center. If a line wraps, then the justification for each line on the display is determined by the first character of that display line.
If the first character of a text line has a tag for which this option has been specified, then pixels specifies how much the line should be indented from the left edge of the window. Pixels may have any of the standard forms for screen distances. If a line of text wraps, this option only applies to the first line on the display; the -lmargin2 option controls the indentation for subsequent lines.
If the first character of a display line has a tag for which this option has been specified, and if the display line is not the first for its text line (i.e., the text line has wrapped), then pixels specifies how much the line should be indented from the left edge of the window. Pixels may have any of the standard forms for screen distances. This option is only used when wrapping is enabled, and it only applies to the second and later display lines for a text line.
Pixels specifies an amount by which the text's baseline should be offset vertically from the baseline of the overall line, in pixels. For example, a positive offset can be used for superscripts and a negative offset can be used for subscripts. Pixels may have any of the standard forms for screen distances.
Specifies the 3-D effect desired for the widget. Acceptable values are raised, sunken, flat, ridge, solid , and groove.
The value indicates how the interior of the widget should appear relative to its exterior; for example, raised means the interior of the widget should appear to protrude from the screen, relative to the exterior of the widget.
If the first character of a display line has a tag for which this option has been specified, then pixels specifies how wide a margin to leave between the end of the line and the right edge of the window. Pixels may have any of the standard forms for screen distances. This option is only used when wrapping is enabled. If a text line wraps, the right margin for each line on the display is determined by the first character of that display line.
Requests additional space above each text line in the widget, using any of the standard forms for screen distances. If a line wraps, this option only applies to the first line on the display. This option may be overriden with -spacing1 options in tags and elements.
For lines that wrap (so that they cover more than one line on the display) this option specifies additional space to provide between the display lines that represent a single line of text. The value may have any of the standard forms for screen distances. This option may be overriden with -spacing2 options in tags and elements.
Requests additional space below each text line in the widget, using any of the standard forms for screen distances. If a line wraps, this option only applies to the last line on the display. This option may be overriden with -spacing3 options in tags and elements.
This option can not be used to configure an element instance.
Specifies a set of tab stops for the window. The option's value consists of a list of screen distances giving the positions of the tab stops. Each position may optionally be followed in the next list element by one of the keywords left , right , center , or numeric , which specifies how to justify text relative to the tab stop.
The default is left ; it causes the text following the tab character to be positioned with its left edge at the tab position. Right means that the right edge of the text following the tab character is positioned at the tab position, and center means that the text is centered at the tab position. Numeric means that the decimal point in the text is positioned at the tab position; if there is no decimal point then the least significant digit of the number is positioned just to the left of the tab position; if there is no number in the text then the text is right-justified at the tab position.
For example, -tabs {2c left 4c 6c center} creates three tab stops at two-centimeter intervals; the first two use left justification and the third uses center justification. If the list of tab stops does not have enough elements to cover all of the tabs in a text line, then Tk extrapolates new tab stops using the spacing and alignment from the last tab stop in the list.
The value of the -tabs option may be overridden by -tabs options in tags and elements. If no -tabs option is specified, or if it is specified as an empty list, then Tk uses default tabs spaced every eight (average size) characters.
Specifies whether or not to draw an underline underneath characters.
The value may have any of the forms describedin section
.
Specifies whether or not to draw an horizontal line through the middle
of characters. The value may have any of the forms describedin
section
.
Specifies whether characters are to be italicised or not.
The value may have any of the forms describedin section
.
Specifies whether characters are to be printed in bold font or
not. The value may have any of the forms describedin
section
.
Specifies the default font size of the element. If the size argument is a positive number, it is interpreted as a size in points. If size is a negative number, its absolute value is interpreted as a size in pixels. If a font cannot be displayed at the specified size, a nearby size will be chosen. If size is unspecified or zero, a platform-dependent default size will be chosen.
Specifies the default font family of the widget. Tk guarantees to support the font families named Courier (a monospaced ``typewriter'' font), Times (a serifed ``newspaper'' font), and Helvetica (a sans-serif ``European'' font). The most closely matching native font family will automatically be substituted when one of the above font families is used. The name may also be the name of a native, platform-specific font family; in that case it will work as desired on one platform but may not display correctly on other platforms. If the family is unspecified or unrecognized, a platform-specific default font will be chosen.
Specifies how to handle lines in the text that are too long to be displayed in a single line of the text's window. The value must be none or char or word.
A wrap mode of none means that each line of text appears as exactly one line on the screen; extra characters that don't fit on the screen are not displayed.
In the other modes each line of text will be broken up into several screen lines if necessary to keep all the characters visible. In char mode a screen line break may occur after any character; in word mode a line break will only be made at word boundaries.