Private Message to Jeff Shaffer: The pointed barbs of ignorance you aim at me are blunted by my shield of knowledge. Besides, while I was vactioning at a luxury, seaside resort with one of the founders of our company, you were exploring the barren wastelands of Oregon and Washington, obviously preferring the company of the spotted owl to that of our revered founder, a fact that I brought to his attention and that he promised to remember when the next round of executive promotions comes up. Should one of our vice presidents retire anytime soon, I fully expect to kiss the XSAR project goodbye!
I have verified that we can implement the static X/Y plot hardcopy
generator as described in the CDR: using code borrowed from the UNIX
print-screen utilities, xwd and xpr, retrieve the X/Y
plot's bit-map image from the X server, convert the image to PostScript,
and print it. To test this approach, I implemented a PRINT
button, a capability now needed for XSAR.
On UNIX systems, a screen dump is usually created by the xwd(1) program. xwd allows the user to select a window or region on the screen that is to be dumped. It then retrieves the bit-map image of the window or region from the X server and writes it out to a file. xpr(1) is used to print a screen dump. xpr reads the xwd-generated screen dump, converts the image to PostScript, and writes the resulting output to a file, which can then be spooled to a printer.
The source code and an executable for the VMS version of xwd were
already available in the DECWindows examples directory. I obtained the
xpr source code from the MIT X11R4 distribution and ported it to
the VAX (a non-trivial task, thanks to the use of undocumented Xlib
routines not available under VMS). Once I had xwd and
xpr working, I cut and pasted the source code for these programs
to produce two subroutine packages, xwd_util.c and
xpr_util.c, that together perform the screen dump function.
For performance reasons, I eliminated the intermediate dump file; the
memory-resident image data gathered by the xwd routines is passed
directly to the xpr routines.
PRINT Button
Using the new xwd and xpr routines, I added a
print screen command to my Tcl-based WIMP program:
wmp_print [name] [-output file] [-root] [-xpr options]
This command generates a PostScript screen dump of an arbitrary widget
(specified by its name) or of the entire screen. The xpr options
allow you to control gray-scale representation, size scaling, and other
attributes of the screen dump. For example, the Print 2x2
button on the Min-Max form:

(Oops! I lost a couple of buttons!)
is defined as follows in WIMP:
wmp_button Print_2 -label "Print 2x2" -parent control_row -command {wmp_print minmax_form -output minmax_2 -xpr "-gray 2 -scale 1"}
The WIMP command assigned to the button prints the minmax_form
widget, which is the top-level, row-column widget of the form. The
PostScript dump of the form's image is written to a file,
minmax_2.ps. The first xpr option, "-gray
2", specifies 2x2 dithering to represent 5 levels of gray; the
default is to generate a black-and-white image. A screen dump with 3x3
dithering is also attached. The other xpr option, "-scale
1", specifies a one pixel-to-one pixel rendering of the form; by
default, the screen image is enlarged or reduced to fill the entire page.
The code fragment in wmp_print that does the printing is
fairly simple:
char *output_file ; /* Output file name. */
char *xpr_options ; /* UNIX-like XPR options. */
void *xwd_image ; /* XWD-generated image. */
Widget top_level ; /* Application shell. */
Widget w ; /* Widget to dump. */
Window window_to_dump ;
...
if (w == NULL) /* Entire screen? */
window_to_dump = DefaultRootWindow (XtDisplay (top_level)) ;
else /* Partial screen. */
window_to_dump = XtWindow (w) ;
/* Get screen image. */
xwd_get_window (top_level, window_to_dump, &xwd_image) ;
/* Convert to PostScript. */
xpr_print_window (top_level, xwd_image, output_file, xpr_options) ;
The following times were measured for the generation of the attached screen dumps:
2x2 image: ~15 seconds
3x3 image: ~30 seconds
Screen capture takes less than a second; the remainder of the time is spend
converting the image to PostScript and outputting it to a file. The code
that writes the hex dump of the image to the PostScript file looks
inefficient, so some speed tuning in this department may be possible. The
gray-scale dithering obviously affects the timing. Size scaling, on the
other hand, doesn't affect the timing of the dump or the size of the output
file; the scaling of the image is performed by the PostScript printer.
xpr has a "-compact" option that uses run-length
encoding for white pixels to produce smaller PostScript files (50% or more
in the case of the Min-Max form), but these compressed files take longer to
print.
Two alternatives for more quickly generating screen dumps come to mind. First, rather than going directly to PostScript, a program like Dynamic Display could save the raw image data in an xwd intermediate file and spawn a separate xpr process to convert the image to PostScript. Unfortunately, generating the xwd file is itself rather slow, although speed tuning (e.g., pre-sizing the output file) might help.
A second alternative would be to write a print server. When a
PRINT button is pushed, the display program would capture the
screen and send its image across a network connection to the print server.
The print server could then, at its own leisure, convert the image to
PostScript without holding up the display program. This approach assumes
that transferring an image over the network would be faster than writing it
to an intermediate file.
As you can see, the xwd_get_window() and
xpr_print_window() functions could be used by XSAR's
hardcopy-generating, X/Y plot program. In fact, if there were a means of
determining when the fields on a page were fully populated (*), a generic
page snap program could be written that would work with both ADT- and
GDT-defined pages. And, if the Dynamic/Static Display program had a way of
accepting artificial input (e.g., simulated PRINT button
presses), it could be used to generate static page snaps, saving us the
trouble of writing one or more separate programs. Oh, well ... time to
wake up!
(*) Come to think of it, doesn't the static display program have this same problem when automatically stepping from major frame to major frame!