Drawing Boxes
From Open Watcom
Contents |
Introduction
This page explores the box-drawing behavior of wgml 4.0. It includes the device library blocks that are used in the actual drawing as well as the control words and layout/document tags that are used to cause boxes to be drawn.
This initial version records what is known so far. Additional work is needed and will eventually be done.
The Required :BOX Block
The :BOX block, which is a required part of the :DEVICE block, defines the line-drawing characters and the font they are to be taken from.
The :ABSOLUTEADDRESS, :HLINE, :VLINE, and :DBOX Blocks
These blocks are all optional, but that does not mean that they can be used arbitrarily.
While attempting to get wgml 4.0 to interpret the :VLINE block, I discovered that :DRIVER block without an :ABSOLUTEADDRESS block but with the :HLINE, :VLINE, and :DBOX blocks would produce an "Abnormal program termination" -- but only when used to process a document specification which caused :VLINE to be interpreted.
This table shows every occurrence in the source files available to me:
Source File :ABSOLUTEADDRESS :HLINE :VLINE :DBOX hpldrv.pcd Yes hplpdrv.pcd Yes Yes Yes hplpldrv.pcd Yes Yes Yes mltdrv.pcd Yes Yes Yes psdrv.pcd Yes Yes Yes Yes x2700drv.pcd Yes Yes Yes
No other source file available to me has any of these blocks in it.
Two obvious deductions can be drawn:
- An :ABSOLUTEADDRESS block is a prerequisite the other three blocks.
- The :HLINE and :VLINE blocks always appear together.
Section "15.9.15 VLINE Block" of the WGML Reference describes the intended context of :VLINE in this way:
The special symbols %y_size and %thickness are defined prior to processing the vline block. The symbol %y_size is set to the height of the vertical line, from the top edge to the bottom edge. The symbol %thickness is set to the value specified by the vline blocks thickness attribute. WATCOM Script/GML positions to the bottom left corner of the line before creating the rule line, and assumes the current point of the device is set to the top left corner of the line when finished.
In other words, a :VLINE block is expected to draw the line in an upward direction. Since a device that does not define :ABSOLUTEADDRESS has no ability to move the print position upwards (negative values of the attribute skip of the :NEWLINE block are not allowed, see the discussion here), it is not surprising that attempting to use :VLINE without :ABSOLUTEADDRESS causes a problem.
An :HLINE block, in contrast, is expected to draw the line from left to right, and so does not require :ABSOLUTEADDRESS -- provided wgml 4.0 always starts it on the correct line and does not attempt to go back up to print out text.
The :DBOX block starts at the bottom left corner and so would, in practice, have to go back up to draw the top and sides of the box, although it does not produce an "Abnormal program termination" in the absense of an :ABSOLUTEADDRESS block.
Clearly, which blocks are present depends on the characteristics of the device. Many devices have none of them, presumably because they produce their output one line at a time.
The .bx Control Word
This is a Script control word, and wgml 4.0 will ignore it entirely unless "script" is placed on the command line (or in an option file, such as default.opt).
This is the box drawn using this and other script control words and used for testing:
.in 2 .tb set > .tb 28 .bx 1 26 62 %binary(3)>the appropriate graphic appears .br;%binary1(4)>the appropriate graphic appears .bx 1 26 62 %binary2(5)>the appropriate graphic appears .br;%binary4(6)>the appropriate graphic appears .bx off .tb set .tb .in
There are, of course, many control words, and this example does not in any way exhaust the ways in which a box may be drawn using them. The box produced is quite something: it has four cells, each with properly-left-justified text in it.
The initial testing, for some reason, did not reliably produce uses of the :VLINE block. It is not clear why, and it could be as simple as a short line length or other factor introduced by the test device.
The observed behavior of .bx is:
- If the :HLINE and :VLINE blocks are defined, they are used; as noted above, the initial testing had problems getting the :VLINE block to be used, although the test box above certainly results in it being used.
- If the :HLINE and :VLINE blocks are not present, then the characters specified by the :BOX block are used.
The Layout/Document Tags
There are three tags which can cause wgml to draw boxes if a particular attribute is given the value "box":
Tag Type Attribute :FIG Document frame :FIG Layout default_frame :IXHEAD Layout frame
The :FIG tags pertain to figures; the :IXHEAD tag pertains to index headings.
The observed behavior (so far, with limited testing) is:
- If :DBOX is present, then it is used.
- If :DBOX is not present, but :HLINE and :VLINE are present, then :HLINE and :VLINE are used to draw the box for figures but not for index headings (no box appears at all around the index headings in this case). Note that :VLINE, in the limited testing performed, was only used here when it was used with .bx.
- If neither :DBOX nor :HLINE/:VLINE are present, then the characters specified by :BOX are used for both figures and index headings.
It is surprising that :IXHEAD behaves differently from :FIG when :DBOX is not provided but :HLINE and :VLINE are.
This is the :FIG used for testing:
:FIG frame=box width='6i' place=inline. %x_address() returns the current horizontal print position %y_address() returns the current vertical print position :FIGCAP.Sample caption with multiple words :eFIG.
There are, of course, many other options possible, all of which the layout code will most likely need to implement. This page, however, is concerned with drawing boxes, not with other options.
Text Line Formatting
While exploring how text lines were output by wgml 4.0, boxing was tested using each of .bx, :FIG, and :IXHEAD. This produced results which turned out to be more generally applicable, and which are discussed to a very limited extent here.
The boxes produced by the IXHEAD tag only contain a single character which, by necessity, is placed in a single text_chars instance.
When the :FIG tag is used, the text_line struct for the text itself contains one text_chars instance for each tab in actual use which controls all of the text starting at that tab stop, including the embedded spaces. This text is never right-justified, even when right justification is turned on. Text given with the :FIGCAP tag is processed normally.
When the .bx control word is used, then the text is processed normally.
Of course, "processed normally" means that what happens depends on which control words are in use.
If the box is drawn using :BOX block characters then, whether the box is created by .bx, :FIG, or :IXHEAD, each :BOX block character is placed in its own text_chars instance.
Implementation Notes
Our wgml is intended to be a drop-in replacement for wgml 4.0 in the Open Watcom document build system. As such, it will be used with two devices (PS and WHELP). One of these devices (PS) provides all four of the :ABSOLUTEADDRSS, :HLINE, :VLINE and :DBOX blocks, and so boxes requested by tags :IXHEAD and :FIG appear and are drawn by wgml 4.0 using :DBOX. The other device (WHELP) provides none of them, and so boxes requested by tags :IXHEAD and :FIG appear and are drawn by wgml 4.0 using the characters and font prescribed by the :BOX block.
These notes take PS to be typical of devices that define the :ABSOLUTEADDRESS block and at least the :HLINE block (referred to as "line-drawing devices") and WHELP to be typical of the devices which use the characters and font prescribed by the :BOX block (referred to as "character devices"). In the case of the line-drawing devices, the results may not be generally applicable: some of them could be PS-specific augmentations. In the case of the character devices, testing was done with devices HELP, TASA and TERM and well as WHELP, so the results should be generally applicable.
Dividing devices in line-drawing devices and character devices makes sense because drawing a box with :DBOX or with :HLINE and :VLINE is very different from drawing a box with the :BOX block characters. The notes here are primarily observations that will be useful to the page layout code; the actual sequencing within the output code is discussed elsewhere.
The general pattern used should be something like this:
- If the :ABSOLUTEADDRESS block is defined (that is, the device is PS):
- use the :DBOX block for the :FIG and :IXHEAD tags; and
- use the :HLINE and :VLINE blocks for .bx.
- Otherwise, use the characters provided by :BOX block.
This should work properly for the OpenWatcom documentation. If our wgml is release more widely, it may be necessary to make other tests and implement other cases.
Line-Drawing Devices
Line-drawing devices use the :HLINE, :VLINE, and :DBOX blocks. This section contains notes on how this is done. These notes are based on the behavior seen with the sample .bx and sample :FIG shown above.
For the :DBOX block, the sequence noted is very simple:
- Use the :ABSOLUTEADDRESS block to locate the print head to the lower left corner of the box.
- Use the :DBOX block to draw the box from that point.
For :HLINE and :VLINE, the sequence noted is not so simple:
- For the top line of the box:
- Use the :ABSOLUTEADDRESS block to locate the print head to the upper left corner of the box.
- Use the :HLINE block to draw the top line from that point.
- For the middle line of the box:
- Use the :ABSOLUTEADDRESS block to locate the print head to the leftmost position on the middle line.
- Use the :VLINE block to draw the left side of the top part of the box from that point.
- Use the :ABSOLUTEADDRESS block to locate the print head to the middle position on the middle line.
- Use the :VLINE block to draw the middle line of the top part of the box from that point.
- Use the :ABSOLUTEADDRESS block to locate the print head to the rightmost position on the middle line.
- Use the :ABSOLUTEADDRESS block to locate the print head to the rightmost position on the middle line again.
- Use the :VLINE block to draw the right line of the top part of the box from that point.
- Use the :ABSOLUTEADDRESS block to locate the print head to the leftmost position on the middle line.
- Use the :HLINE block to draw the middle line from that point.
- For the bottom line of the box:
- Use the :ABSOLUTEADDRESS block to locate the print head to the lower left corner of the box.
- Use the :HLINE block to draw the bottom line from that point.
- Use the :ABSOLUTEADDRESS block to locate the print head to the leftmost position on the bottom line.
- Use the :VLINE block to draw the left side of the bottom part of the box from that point.
- Use the :ABSOLUTEADDRESS block to locate the print head to the middle position on the bottom line.
- Use the :ABSOLUTEADDRESS block to locate the print head to the middle position on the bottom line again.
- Use the :VLINE block to draw the bottom line of the top part of the box from that point.
- Use the :ABSOLUTEADDRESS block to locate the print head to the rightmost position on the bottom line.
- Use the :ABSOLUTEADDRESS block to locate the print head to the rightmost position on the bottom line again.
- Use the :VLINE block to draw the right line of the bottom part of the box from that point.
Testing shows that the PS device does show the duplicated invocations of the :ABSOLUTEADDRESS block in the positions indicated.
When the functions intended to be used for invoking the :DBOX, :HLINE and :VLINE blocks were written, they were written to invoke the :ABSOLUTEADDRESS block as well. Indeed, the function used to invoke the :ABSOLUTEADDRESS block was a static function, used entirely within its module. Since the layout code will need to invoke the :ABSOLUTEADDRESS block redundantly from time to time to produce bytewise identity between the output of wgml 4.0 and our wgml for device PS, the function used to do this is now globally accessible.
Character Devices
Future Directions
This are easily-seen topics for future exploration:
- Verification of how .bx works in wgml 4.0 (it has several operands).
- Determining whether or not .bx and the GML tags use a common context for box-drawing.

