v08i053: wscrawl, Part01/05

Brian Wilson brianw at hpcvlx.cv.hp.com
Mon Jul 16 04:57:10 AEST 1990


Submitted-by: Brian Wilson <brianw at hpcvlx.cv.hp.com>
Posting-number: Volume 8, Issue 53
Archive-name: wscrawl/part01

[ moderator's note:
    this archive consists of a file wscrawl.c, which is about 185K.
    I had to split the file into parts (labeled xaa, xab, xac...).
    You need to do:
	% cat xa? > wscrawl.c
    before you attempt to "make" anything.
    --dan
]

			      wscrawl

If you have never used wscrawl before, it can be thought of as a paint
program shared between multiple people, displays, and workstations.  Any
number of people can draw independantly of each other, yet they all work
on the same picture.

This is a complete reposting of the program wscrawl.  Many enhancements have
been made to the original, including File I/O in standard "xwd" format, and
adding displays to the session by anyone in the session, during the session.
Other enhancements include the drawing of shapes, and a Rubber Pointer for
pointing (without drawing) on other member's displays.  Resizing the window
no longer clears the contents, and on MOST systems, the menus will not clear
the drawing away like they used to.

Thanks to the people who sent me ideas and bug reports.  They were all very
helpful.


   File Name            Archive #       Description
----------------------------------------------------------
 wscrawl                    1
 wscrawl/Imakefile          1
 wscrawl/Makefile           1
 wscrawl/README             2
 wscrawl/image_f_io.c       5
 wscrawl/patchlevel.h       1
 wscrawl/pause_curs.h       1
 wscrawl/wscrawl.1          1
 wscrawl/xaa                4
 wscrawl/xab                5
 wscrawl/xac                2
 wscrawl/xad                3
 wscrawl/xae                1
 wscrawl/xaf                1

You can annonymous ftp a file called "wscrawl.shar" from machine 
"15.255.72.15".  Use login "ftp" and passwd "ftp" and once logged in, "cd pub"
then "get wscrawl.shar".  This file contains my posting, but in the shar
format I am more familiar with.

Thanks,
Brian Wilson
(503) 750-3929

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of archive 1 (of 5)."
# Contents:  wscrawl wscrawl/Imakefile wscrawl/Makefile
#   wscrawl/patchlevel.h wscrawl/pause_curs.h wscrawl/wscrawl.1
#   wscrawl/xae wscrawl/xaf
# Wrapped by argv at turnpike on Sun Jul 15 11:47:10 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'wscrawl' ; then
    echo shar: Creating directory \"'wscrawl'\"
    mkdir 'wscrawl'
fi
if test -f 'wscrawl/Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/Imakefile'\"
else
echo shar: Extracting \"'wscrawl/Imakefile'\" \(230 characters\)
sed "s/^X//" >'wscrawl/Imakefile' <<'END_OF_FILE'
XINCLUDES = -I. -I$(INCLUDESRC)
XLOCAL_LIBRARIES = $(XLIB)
X           SRCS = wscrawl.c image_f_io.c
X           OBJS = wscrawl.o image_f_io.o
X
XNormalLibraryObjectRule()
XComplexProgramTarget(wscrawl)
XInstallProgram(wscrawl,$(BINDIR))
END_OF_FILE
if test 230 -ne `wc -c <'wscrawl/Imakefile'`; then
    echo shar: \"'wscrawl/Imakefile'\" unpacked with wrong size!
fi
# end of 'wscrawl/Imakefile'
fi
if test -f 'wscrawl/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/Makefile'\"
else
echo shar: Extracting \"'wscrawl/Makefile'\" \(201 characters\)
sed "s/^X//" >'wscrawl/Makefile' <<'END_OF_FILE'
X# Makefile for wscrawl
X
Xwscrawl: wscrawl.o image_f_io.o
X	cc -o wscrawl wscrawl.o image_f_io.o -lX11
X
Xwscrawl.o: wscrawl.c pause_curs.h
X	cc -c wscrawl.c
X
Ximage_f_io.o: image_f_io.c
X	cc -c image_f_io.c
X
END_OF_FILE
if test 201 -ne `wc -c <'wscrawl/Makefile'`; then
    echo shar: \"'wscrawl/Makefile'\" unpacked with wrong size!
fi
# end of 'wscrawl/Makefile'
fi
if test -f 'wscrawl/patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/patchlevel.h'\"
else
echo shar: Extracting \"'wscrawl/patchlevel.h'\" \(21 characters\)
sed "s/^X//" >'wscrawl/patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 0
END_OF_FILE
if test 21 -ne `wc -c <'wscrawl/patchlevel.h'`; then
    echo shar: \"'wscrawl/patchlevel.h'\" unpacked with wrong size!
fi
# end of 'wscrawl/patchlevel.h'
fi
if test -f 'wscrawl/pause_curs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/pause_curs.h'\"
else
echo shar: Extracting \"'wscrawl/pause_curs.h'\" \(3349 characters\)
sed "s/^X//" >'wscrawl/pause_curs.h' <<'END_OF_FILE'
X#define pause_curs_width 64
X#define pause_curs_height 64
X#define pause_curs_x_hot 32
X#define pause_curs_y_hot 31
Xstatic char pause_curs_bits[] = {
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x86, 0x01, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x07, 0x22, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x02, 0x04, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x11, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x02, 0x84, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x02, 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x84, 0x08, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x02, 0xc4, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x02, 0x44, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x42, 0x04, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0xba, 0x43, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18,
X   0xe2, 0x40, 0x02, 0x7c, 0xe0, 0x00, 0x07, 0x36, 0x02, 0x40, 0x02, 0x83,
X   0x18, 0x81, 0x01, 0x63, 0x02, 0x40, 0x03, 0x41, 0x08, 0x81, 0x01, 0x41,
X   0x02, 0xc0, 0x01, 0x23, 0x04, 0x01, 0x83, 0x7f, 0x02, 0xc0, 0x00, 0x1f,
X   0x84, 0x01, 0x86, 0x00, 0x02, 0xc0, 0x00, 0x01, 0x84, 0x20, 0xc4, 0x00,
X   0x02, 0xa0, 0x00, 0x01, 0x84, 0x21, 0x48, 0x00, 0x02, 0x10, 0x01, 0x01,
X   0x4c, 0x61, 0x48, 0x00, 0x03, 0x18, 0x03, 0x02, 0x38, 0xc3, 0xcf, 0x40,
X   0x03, 0x0e, 0x0c, 0x86, 0x00, 0x00, 0x80, 0x60, 0x02, 0x02, 0x00, 0x78,
X   0x00, 0x00, 0x80, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x20,
X   0x00, 0xc0, 0x07, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x04, 0x00,
X   0x00, 0x10, 0x00, 0x10, 0x00, 0x40, 0x04, 0x00, 0x00, 0x10, 0x00, 0x10,
X   0x00, 0xc0, 0x84, 0x01, 0x00, 0x10, 0x00, 0x10, 0x00, 0x80, 0x87, 0x00,
X   0x00, 0x10, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x08,
X   0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x08, 0xc0, 0x41, 0xf8, 0x07,
X   0x00, 0x20, 0x08, 0x04, 0xb8, 0x41, 0x40, 0x00, 0x00, 0x20, 0x1c, 0x04,
X   0x8c, 0x41, 0x60, 0x00, 0x00, 0x40, 0x34, 0x06, 0x84, 0x41, 0x20, 0x00,
X   0x00, 0x40, 0x26, 0x03, 0x82, 0x20, 0x20, 0x00, 0x00, 0x40, 0x62, 0x01,
X   0xc2, 0x20, 0x20, 0x00, 0x00, 0xc0, 0xc2, 0x01, 0xc2, 0x20, 0x20, 0x00,
X   0x00, 0x80, 0xc1, 0x00, 0xe2, 0x21, 0x40, 0x04, 0x00, 0x80, 0xc1, 0x00,
X   0x3c, 0x67, 0xc1, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
END_OF_FILE
if test 3349 -ne `wc -c <'wscrawl/pause_curs.h'`; then
    echo shar: \"'wscrawl/pause_curs.h'\" unpacked with wrong size!
fi
# end of 'wscrawl/pause_curs.h'
fi
if test -f 'wscrawl/wscrawl.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/wscrawl.1'\"
else
echo shar: Extracting \"'wscrawl/wscrawl.1'\" \(3719 characters\)
sed "s/^X//" >'wscrawl/wscrawl.1' <<'END_OF_FILE'
X.TH WSCRAWL 1
X.ds )H eXcess engineering
X.ds ]W July 1990
X.SH NAME
Xwscrawl \- a multiple person paint program shared between displays
X.SH SYNOPSIS
X.B wscrawl 
X[
X.I options
X]
X.SH DESCRIPTION
X.I Wscrawl\^
Xpaints or types on single or multiple displays. The
X.B [\-d displayname]
Xoption causes 
X.I wscrawl
Xto wscrawl on both the invoker's display and on a target display.
XAny person on a target display may scrawl back in the window provided.
XAll members of the session will always see the same thing in their 
Xrespective wscrawl windows.
X.SS Options
X.PP
XThere are several options:
X.TP
X.B  \-d displayname1 \-d displayname2 . . .
Xopen a wscrawl window on displayname1 and displayname2 at the same time as 
Xthe HOME display
X.TP
X.B  \-pc pen_color
Xset the pen color
X.TP
X.B  \-pw pen_width
Xset the pen width
X.TP
X.B  \-ps pen_style
Xpen style can be one of the following: dot, airbrush, draw_shapes, eraser
X.TP
X.B  \-cs pen_style
Xcap style can be one of the following: CapButt, CapNotLast, CapRound, 
XCapProjecting
X.TP
X.B  \-nd num_dots
Xset the number of dots in the airbrush (airbrush density)
X.TP
X.B  \-tm
Xtype a message, don't wscrawl
X.TP
X.B  \-fn font
Xspecify the font if typing a message
X.TP
X.B  \-sh shape
Xspecify the shape to use if the pen_style is "draw_shapes"
X.SH FILE INPUT AND OUTPUT
XThere are several forms of File I\/O available during a session of wscrawl.
X.PP
XForms of I/O include:
X.TP
X.B  Save Bitmap
XAfter selecting this menu option, click and drag the mouse over the
Xregion you wish to convert to a standard X-Windows bitmap file.  Upon
Xrelease of the button, you will be prompted for a file name.  The background
Xcolor is converted to a "0" in the bitmap, while anything other than background
Xis converted to a "1" in the bitmap.
X.TP
X.B  Read In Bitmap
XAfter selecting this menu option, type the name of the bitmap file into
Xthe dialog box provided.  Upon hitting return, a rubber band type box will
Xappear indicating the size and location of the bitmap.  To place the bitmap,
Xclick the left button.  The bitmap is drawn in using the current PenColor as
Xthe foreground and the background color as the background.
X.TP
X.B  Read Text File
XAfter selecting this menu option, type the name of the text file into
Xthe dialog box provided.  Upon hitting return, a rubber band type box will
Xappear indicating the size and location of the text.  To place the text,
Xclick the left mouse button.
X.TP
X.B  Save Image
XAfter selecting this menu option, click and drag the mouse over the
Xregion you wish to convert to an "image" file.  Upon
Xrelease of the button, you will be prompted for a file name.  The region
Xselected will be saved in a form that the MIT client "xwud" can read.
X.TP
X.B  Read In Image
XAfter selecting this menu option, type the name of the image file into
Xthe dialog box provided.  Upon hitting return, a rubber band type box will
Xappear indicating the size and location of the image.  To place the bitmap,
Xclick the left button.  The image is restored to any wscrawl windows open
Xthat are the same depth as the original image.  Image files can either be
Xcreated earlier by wscrawl, or by the MIT client "xwd".
X.SH DIAGNOSTICS
XThere are no diagnostics.  Source is available.
X.SH EXAMPLES
XThis command opens a wscrawl window on the HOME display, the "dove:0" 
Xdisplay and the "hawk:0" display ready to type messages in the color cyan, 
Xand the font "vgl-40".
X.IP
Xwscrawl -d dove:0 -d hawk:0 -tm -pc cyan -fn vgl-40
X.SH AUTHOR
X.I wscrawl
Xwas developed by Brian Wilson of Hewlett-Packard.
X.SH EXTERNAL INFLUENCES
X.SS Environment Variables
X.SM DISPLAY
Xdetermines the home display which wscrawl will wscrawl to regardless of
Xcommand line displays.
X.PP
X.SH "STANDARDS CONFORMANCE"
X.IR wscrawl ": X11, Xlib, R4"
END_OF_FILE
if test 3719 -ne `wc -c <'wscrawl/wscrawl.1'`; then
    echo shar: \"'wscrawl/wscrawl.1'\" unpacked with wrong size!
fi
# end of 'wscrawl/wscrawl.1'
fi
if test -f 'wscrawl/xae' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/xae'\"
else
echo shar: Extracting \"'wscrawl/xae'\" \(39069 characters\)
sed "s/^X//" >'wscrawl/xae' <<'END_OF_FILE'
X    XColor curs_foregrexact, curs_foregr, curs_backgr, curs_backgrexact;
X    Pixmap source, mask;
X    int i, j, k, menu_num;
X    GC *(old_win_gc[MAX_NUM_DISPS]);
X    int menu_x_val;
X    XWindowAttributes attr_ret;
X    XFontStruct *the_font_struct;
X    char tmp_str[50], tmp_str2[50];
X    XGCValues cursor_gc_values;
X
X    /*
X     * The following opens the new display and window and initializes some
X     * of the disp_info fields.  The cursor is defined for the window, and
X     * the window manager is instructed how to behave with the new window.
X     */
X
X    /*open this particular display*/
X    if ((disp_info[disp_num].disp = XOpenDisplay(disp_args[disp_num])) == NULL)
X    {
X        printf("ERROR: XOpenDisplay failed on display: %s\n", 
X	       disp_args[disp_num]);
X        exit(0);
X    }
X
X    winvals.backing_store = Always;
X    if (!XAllocNamedColor(disp_info[disp_num].disp, 
X    	        DefaultColormap(disp_info[disp_num].disp, 
X	        DefaultScreen(disp_info[disp_num].disp)), BACKGROUND_COLOR, 
X	        &scrn_def_ret, &exact_def_ret))
X    {
X        printf("\nThe color %s is not supported", BACKGROUND_COLOR);
X        printf(" on the display %s.\n", disp_args[disp_num]);
X        exit(0);
X    }
X    winvals.background_pixel = scrn_def_ret.pixel;
X    winvals.bit_gravity = NorthWestGravity;
X    disp_info[disp_num].background = scrn_def_ret.pixel;
X
X    disp_info[disp_num].win_id = XCreateWindow(disp_info[disp_num].disp, 
X		  RootWindow(disp_info[disp_num].disp, DefaultScreen(
X		  disp_info[disp_num].disp)), 5+(disp_num*80), 5+(disp_num*80),
X		  WSCRAWL_WIN_WIDTH, WSCRAWL_WIN_HEIGHT, 3, 0,
X		  CopyFromParent,CopyFromParent,alter_these2_mask, &winvals);
X
X
X    disp_info[disp_num].connection_num = 
X				    ConnectionNumber(disp_info[disp_num].disp);
X    disp_info[disp_num].first_point_bool = FALSE;
X    disp_info[disp_num].pointer_state = NOT_PRESSED;
X    disp_info[disp_num].scrawl_mode = SCRAWLING;
X    disp_info[disp_num].current_shape = OUTLINE_RECT;
X    disp_info[disp_num].just_placed_something_bool = FALSE;
X    disp_info[disp_num].type_history = NULL;
X
X    cursor_gc_values.line_width = 5;
X    cursor_gc_values.function = GXinvert;
X    cursor_gc_values.background =  BlackPixelOfScreen(
X		             DefaultScreenOfDisplay(disp_info[disp_num].disp));
X    cursor_gc_values.foreground =  WhitePixelOfScreen(
X		             DefaultScreenOfDisplay(disp_info[disp_num].disp));
X    disp_info[disp_num].cursor_gc = XCreateGC(disp_info[disp_num].disp, 
X	              disp_info[disp_num].win_id,
X	              GCFunction | GCBackground | GCForeground | GCLineWidth, 
X		      &cursor_gc_values);
X
X    if (!TYPE_NOT_DRAW)
X        the_cursor = XCreateFontCursor(disp_info[disp_num].disp, XC_dot);
X
X    XDefineCursor(disp_info[disp_num].disp, disp_info[disp_num].win_id, 
X		   the_cursor);
X
X    win_size_hints.flags = USPosition | PPosition;
X    win_size_hints.x = 5 + (disp_num * 80);
X    win_size_hints.y = 5 + (disp_num * 80);
X
X    XSetStandardProperties(disp_info[disp_num].disp, disp_info[disp_num].win_id,
X	        "WSCRAWL: a product of eXcess engineering", "wscrawl", None, 
X		NULL, 0, &win_size_hints);
X
X    /* the following three calls are to change window manager behavior*/
X    disp_info[disp_num].xa_WM_PROTOCOLS = XInternAtom(disp_info[disp_num].disp, 
X						   "WM_PROTOCOLS", FALSE);
X    disp_info[disp_num].xa_WM_DELETE_WINDOW = XInternAtom(
X						    disp_info[disp_num].disp, 
X					            "WM_DELETE_WINDOW", FALSE);
X    XChangeProperty(disp_info[disp_num].disp, disp_info[disp_num].win_id, 
X		disp_info[disp_num].xa_WM_PROTOCOLS, 
X		disp_info[disp_num].xa_WM_PROTOCOLS, 32, 
X		PropModeReplace,
X		(char *) &(disp_info[disp_num].xa_WM_DELETE_WINDOW), 1);
X
X    /*
X     * The following changes the names in the "disp_args[]" array to reflect
X     * the ACTUAL machine and display instead of things like "local:0" etc.
X     */
X    if ((strncmp(disp_args[disp_num], "local", 5) == 0) ||
X        (strncmp(disp_args[disp_num], "unix", 4) == 0) ||
X        (strncmp(disp_args[disp_num], ":", 1) == 0))
X    {
X        /*
X         * this is a wscrawl window on the invoker's home display, so
X         * change it to be meaningful.
X         */
X        gethostname(tmp_str, 30);
X        sprintf(tmp_str2, "%s%s", tmp_str, strpbrk(disp_args[disp_num], ":"));
X        strncpy(disp_args[disp_num], tmp_str2, 30);
X    }
X
X    for (i=0; i<num_of_disps; i++)
X	if (disp_info[i].in_session_bool)  /*only if this session is in use*/
X            old_win_gc[i] = disp_info[i].win_gc;  /*save the old array of GCs*/
X
X    for (i=0; i<num_of_disps; i++)                /*malloc new array of GCs*/
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X            disp_info[i].win_gc = (GC *) malloc(num_of_disps * sizeof(GC));
X    /*
X     * The following assigns each "user" N graphics contexts, where N
X     * is the number of open displays.  This "user" wants his particular
X     * color on every display, and since gc's are attached to displays,
X     * we need one with this color loaded on every display.  These gc's
X     * are then used for pen width, pen caps, etc.
X     *
X     * The complex part (well, one of the complex parts) comes in when 
X     * you want a user to retain his or her same GC.  In some cases, this
X     * is simply a copy over from the former one.  But one doesn't exist
X     * yet for the new display, so we create it as close as possible.
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X	    /*
X	     * The following assigns this "user" N graphics contexts, where N
X	     * is the number of open displays.  This "user" wants his particular
X	     * color on every display, and since gc's are attached to displays,
X	     * we need one with this color loaded on every display.  These gc's
X	     * are then used for pen width, pen caps, etc.
X	     */
X	    for (j=0; j<num_of_disps; j++)
X	    {
X	        if (disp_info[j].in_session_bool) /*only if session is wanted*/
X	        {
X		    if ((i != disp_num) && (j != disp_num))
X		    {
X                        disp_info[i].win_gc[j] = XCreateGC(disp_info[j].disp, 
X		                           disp_info[j].win_id, nothing_mask, 
X					   &gcvalues);
X                        XCopyGC(disp_info[j].disp, old_win_gc[i][j], 
X				gc_copy_mask, disp_info[i].win_gc[j]);
X			XFreeGC(disp_info[j].disp, old_win_gc[i][j]);
X		    }
X		    else
X		    {
X			if (i == disp_num) /*this is the new guy, set defaults*/
X			{
X                            disp_info[i].pen_width = PEN_WIDTH;
X	                    disp_info[i].pen_widths.scrawl = 8;
X	                    disp_info[i].pen_widths.airbrush = 40;
X	                    disp_info[i].pen_widths.eraser = 40;
X	                    disp_info[i].pen_widths.shape = 8;
X                            disp_info[i].capstyle = CAP_STYLE;
X			    strncpy(disp_info[i].pen_color_str, PEN_COLOR, 40);
X			    strncpy(disp_info[i].font_str, FONT, 250);
X			}
X
X                        /*
X			 * create the gc from scratch
X			 */
X                        if (XAllocNamedColor(disp_info[j].disp,DefaultColormap(
X		             disp_info[j].disp, 
X			     DefaultScreen(disp_info[j].disp)), 
X			     disp_info[i].pen_color_str, 
X			     &scrn_def_ret, &exact_def_ret))
X	                {
X		            ;  /*great!  it worked!*/
X	                }
X	                else if (!XAllocNamedColor(disp_info[j].disp, 
X			     DefaultColormap(disp_info[j].disp, 
X			     DefaultScreen(disp_info[j].disp)), 
X		             "black", &scrn_def_ret, &exact_def_ret))
X	                {
X	                    printf("The color %s is not", PEN_COLOR);
X	                    printf(" supported on the display %s.\n", 
X				   disp_args[i]);
X	                    exit(0);
X	                }
X                        gcvalues.foreground = scrn_def_ret.pixel;
X            
X                        gcvalues.background =
X				     WhitePixelOfScreen(DefaultScreenOfDisplay(
X				     disp_info[j].disp));
X        
X		        gcvalues.line_width = disp_info[i].pen_width;
X                        gcvalues.cap_style = disp_info[i].capstyle;
X                        gcvalues.graphics_exposures = False;
X            
X                        if ((the_font_struct =XLoadQueryFont(disp_info[j].disp,
X			     disp_info[i].font_str)) != NULL)
X	                {
X	                    gcvalues.font = the_font_struct->fid;
X	                }
X	                else if ((the_font_struct=XLoadQueryFont(
X				  disp_info[j].disp, "fixed")) != NULL)
X	                {
X	                    printf("WARNING: Couldn't allocate font: %s",FONT);
X	                    printf(" on display %s.  Using fixed.\n",
X				    disp_args[j]);
X	                    gcvalues.font = the_font_struct->fid;
X	                }
X	                else
X	                {
X	                    printf("\nERROR: Couldn't allocate a font ");
X		            printf("on display: %s.\n", disp_args[j]);
X	                    exit(0);
X                        }
X            
X                        disp_info[i].win_gc[j] = XCreateGC(disp_info[j].disp, 
X		             disp_info[j].win_id, alter_these_mask, &gcvalues);
X	                disp_info[i].the_font_struct = the_font_struct;
X		    }
X	        }
X            }
X	}
X    }
X    
X    /*
X     * create the rubber_band_gc's for all the scrawl windows
X     */
X    gcvalues.function = GXinvert;
X    gcvalues.line_width = 0;
X    disp_info[disp_num].rubber_band_gc = XCreateGC(disp_info[disp_num].disp, 
X              disp_info[disp_num].win_id, GCLineWidth | GCFunction, &gcvalues);
X
X    /*
X     * create and initialize the menus on this scrawl window
X     */
X    for (menu_num=0; menu_num<NUM_OF_MENUS; menu_num++)
X    {
X        if (XAllocNamedColor(disp_info[disp_num].disp, 
X		    DefaultColormap(disp_info[disp_num].disp, 
X	            DefaultScreen(disp_info[disp_num].disp)), 
X		    MENU_BACKGROUND_COLOR, 
X	            &scrn_def_ret, &exact_def_ret))
X        {
X            menuwinvals.background_pixel = scrn_def_ret.pixel;
X        }
X        else if (XAllocNamedColor(disp_info[disp_num].disp, 
X		    DefaultColormap(disp_info[disp_num].disp, 
X	            DefaultScreen(disp_info[disp_num].disp)), "white", 
X	            &scrn_def_ret, &exact_def_ret))
X        {
X            printf("The color %s is not", MENU_BACKGROUND_COLOR);
X	    printf(" supported on display %s.\n", disp_args[disp_num]);
X	    printf("Using white for the menu background color.\n");
X	    strcpy(MENU_BACKGROUND_COLOR, "white");
X	    menuwinvals.background_pixel = scrn_def_ret.pixel;
X        }
X        else
X        {
X	    printf("The menu background color had extra problems on");
X	    printf(" display %s.\n", disp_args[disp_num]);
X	    return(0);
X        }
X    
X	menu_x_val = menu_num*MENU_ITEM_WIDTH + (menu_num*2);
X        menuwinvals.save_under = True;
X    
X	disp_info[disp_num].menu[menu_num].win_id =
X		     XCreateWindow(disp_info[disp_num].disp, 
X		     disp_info[disp_num].win_id, 
X		     menu_x_val, 0, MENU_ITEM_WIDTH, MENU_ITEM_HEIGHT, 2, 
X		     0, CopyFromParent, CopyFromParent, alter_menu2_mask, 
X		     &menuwinvals);
X        XMapWindow(disp_info[disp_num].disp,
X			    disp_info[disp_num].menu[menu_num].win_id);
X    
X	menu_cursor =XCreateFontCursor(disp_info[disp_num].disp,XC_right_ptr);
X	XDefineCursor(disp_info[disp_num].disp, 
X	              disp_info[disp_num].menu[menu_num].win_id, menu_cursor);
X    
X	disp_info[disp_num].menu[menu_num].item_selected = NO_ITEM_SELECTED;
X    }
X    
X    /*
X     * find the num of items in each menu and assign it to the correct
X     * variable in the structure. "k" is the menu_item_num.
X     */
X    for (menu_num=0; menu_num < NUM_OF_MENUS; menu_num++)
X    {
X        for (k=0; strcmp(menu_text[menu_num][k], "****") != 0; k++)
X            ;
X        disp_info[disp_num].menu[menu_num].num_items = k;
X
X	switch(menu_num)  /*set default checkmark*/
X	{
X	    case 0:                   /*Control menu*/
X	        disp_info[disp_num].menu[menu_num].checked_item = 1;
X		break;
X	    case 1:                   /*PenColor menu*/
X	        disp_info[disp_num].menu[menu_num].checked_item = 2;
X		break;
X	    case 2:                   /*PenWidth menu*/
X	        disp_info[disp_num].menu[menu_num].checked_item = 4;
X		break;
X	    case 3:                   /*PenCapStyle menu*/
X	        disp_info[disp_num].menu[menu_num].checked_item = 1;
X		break;
X	    case 4:                   /*Font menu*/
X	        disp_info[disp_num].menu[menu_num].checked_item = 14;
X		break;
X	    case 5:                   /*Shapes menu*/
X	        disp_info[disp_num].menu[menu_num].checked_item = 2;
X		break;
X	    default:
X		break;
X	}
X    }
X    
X    if (!XAllocNamedColor(disp_info[disp_num].disp, 
X		    DefaultColormap(disp_info[disp_num].disp, 
X	            DefaultScreen(disp_info[disp_num].disp)), 
X		    MENU_HIGHLIGHT_COLOR, 
X	            &scrn_def_ret, &exact_def_ret))
X    {
X        printf("The color %s is not", MENU_HIGHLIGHT_COLOR);
X        printf(" supported on the display %s.\n", disp_args[disp_num]);
X        return(0);
X    }
X    menugcvalues.foreground = scrn_def_ret.pixel;
X    
X    if (!XAllocNamedColor(disp_info[disp_num].disp, 
X	        DefaultColormap(disp_info[disp_num].disp, 
X	        DefaultScreen(disp_info[disp_num].disp)), 
X		MENU_BACKGROUND_COLOR, 
X	        &scrn_def_ret2, &exact_def_ret2))
X    {
X	        printf("The menu background color had second round problems ");
X    	        printf("on the display %s.\n", disp_args[disp_num]);
X	        return(0);
X    }
X    
X    menugcvalues.background = scrn_def_ret2.pixel;
X    
X    menugcvalues.line_width = 2;
X    menugcvalues.font = XLoadFont(disp_info[disp_num].disp, "fixed");
X    disp_info[disp_num].hi_menu_gc = XCreateGC(disp_info[disp_num].disp, 
X          disp_info[disp_num].menu[0].win_id, alter_menu_mask, &menugcvalues);
X    
X    /*
X     * switch foreground and background colors for bg_menu_gc
X     */
X    menugcvalues.foreground = scrn_def_ret2.pixel;
X    menugcvalues.background = scrn_def_ret.pixel;
X    disp_info[disp_num].bg_menu_gc = XCreateGC(disp_info[disp_num].disp, 
X    disp_info[disp_num].menu[0].win_id, alter_menu_mask, &menugcvalues);
X    
X    if (!XAllocNamedColor(disp_info[disp_num].disp, 
X	    DefaultColormap(disp_info[disp_num].disp, 
X            DefaultScreen(disp_info[disp_num].disp)), MENU_FOREGROUND_COLOR, 
X            &scrn_def_ret, &exact_def_ret))
X    {
X        printf("The color %s is not", MENU_FOREGROUND_COLOR);
X        printf(" supported on the display %s.\n", disp_args[disp_num]);
X        return(0);
X    }
X    menugcvalues.foreground = scrn_def_ret.pixel;
X    menugcvalues.background = scrn_def_ret2.pixel;
X    disp_info[disp_num].fg_menu_gc = XCreateGC(disp_info[disp_num].disp, 
X    disp_info[disp_num].menu[0].win_id, alter_menu_mask, &menugcvalues);
X    
X    for (menu_num=0; menu_num<NUM_OF_MENUS; menu_num++)
X    {
X        disp_info[disp_num].current_menu = menu_num;
X        draw_menu(disp_num);
X    }
X    
X    /*
X     * create the status window and eraser window, and dialog window for 
X     * this scrawl window 
X     */
X    if (!XAllocNamedColor(disp_info[disp_num].disp, 
X		DefaultColormap(disp_info[disp_num].disp, 
X	        DefaultScreen(disp_info[disp_num].disp)), 
X		MENU_BACKGROUND_COLOR, 
X	        &scrn_def_ret, &exact_def_ret))
X    {
X        printf("The color %s is not", MENU_BACKGROUND_COLOR);
X	printf(" supported on the display %s.\n", disp_args[disp_num]);
X	return(0);
X    }
X    menuwinvals.background_pixel = scrn_def_ret.pixel;
X    menuwinvals.save_under = True;
X    disp_info[disp_num].eraser_win_id = XCreateWindow(disp_info[disp_num].disp,
X            disp_info[disp_num].win_id, 0, 350, 550, 20, 2, 0, CopyFromParent, 
X	    CopyFromParent, alter_menu2_mask, &menuwinvals);
X    disp_info[disp_num].status_win_id = XCreateWindow(disp_info[disp_num].disp,
X	   disp_info[disp_num].win_id, 0, 350, 550, 20, 2, 0, CopyFromParent, 
X	   CopyFromParent, alter_menu2_mask, &menuwinvals);
X    disp_info[disp_num].dialog_win_id = XCreateWindow(disp_info[disp_num].disp,
X	   disp_info[disp_num].win_id, 50, 80, DIALOG_WIN_WIDTH, 
X	   DIALOG_WIN_HEIGHT, 2, 0, CopyFromParent, 
X	   CopyFromParent, alter_menu2_mask, &menuwinvals);
X    XMapWindow(disp_info[disp_num].disp, disp_info[disp_num].status_win_id);
X    XDefineCursor(disp_info[disp_num].disp, disp_info[disp_num].status_win_id,
X			  XCreateFontCursor(disp_info[disp_num].disp, XC_star));
X    XDefineCursor(disp_info[disp_num].disp, disp_info[disp_num].eraser_win_id,
X			  XCreateFontCursor(disp_info[disp_num].disp, 
X			  XC_draped_box));
X    XDefineCursor(disp_info[disp_num].disp, disp_info[disp_num].dialog_win_id,
X			  XCreateFontCursor(disp_info[disp_num].disp, 
X			  XC_xterm));
X    XLowerWindow(disp_info[disp_num].disp, disp_info[disp_num].eraser_win_id);
X
X    /*
X     * if typing, set cursor, font, etc correctly with a call to 
X     * menu_selection (which is usually called when you pull down a menu).
X     */
X    if (TYPE_NOT_DRAW)
X        menu_selection(disp_num, 0, num_people_drawing, 3);
X
X    /*
X     * create the pause cursor for the new display
X     */
X    source = XCreatePixmapFromBitmapData(disp_info[disp_num].disp, 
X	      disp_info[disp_num].win_id, pause_curs_bits, pause_curs_width, 
X	      pause_curs_height, WhitePixel(disp_info[disp_num].disp, 
X	      DefaultScreen(disp_info[disp_num].disp)), 
X	      BlackPixel(disp_info[disp_num].disp, 
X	      DefaultScreen(disp_info[disp_num].disp)), 1);
X    mask = XCreatePixmapFromBitmapData(disp_info[disp_num].disp, 
X	      disp_info[disp_num].win_id, pause_curs_bits, pause_curs_width, 
X	      pause_curs_height, WhitePixel(disp_info[disp_num].disp, 
X	      DefaultScreen(disp_info[disp_num].disp)), 
X	      BlackPixel(disp_info[disp_num].disp, 
X	      DefaultScreen(disp_info[disp_num].disp)), 1);
X
X    XAllocNamedColor(disp_info[disp_num].disp, DefaultColormapOfScreen(
X		         DefaultScreenOfDisplay(disp_info[disp_num].disp)),
X			 "white", &curs_backgr, &curs_backgrexact);
X    XAllocNamedColor(disp_info[disp_num].disp, DefaultColormapOfScreen(
X		         DefaultScreenOfDisplay(disp_info[disp_num].disp)),
X			 "black", &curs_foregr, &curs_foregrexact);
X
X    disp_info[disp_num].pause_cursor = 
X		      XCreatePixmapCursor(disp_info[disp_num].disp, 
X		      source, mask, &curs_foregrexact, &curs_backgrexact, 
X		      pause_curs_x_hot, pause_curs_y_hot);
X
X    XDefineCursor(disp_info[disp_num].disp, disp_info[disp_num].win_id,
X		      disp_info[disp_num].pause_cursor);
X    XDefineCursor(disp_info[disp_num].disp, disp_info[disp_num].status_win_id, 
X	              disp_info[disp_num].pause_cursor);
X    for (j=0; j<NUM_OF_MENUS; j++)
X	XDefineCursor(disp_info[disp_num].disp, 
X	              disp_info[disp_num].menu[j].win_id, 
X	              disp_info[disp_num].pause_cursor);
X
X    /*
X     * create the rubber cursor pixmaps for all the displays that don't have 
X     * them yet
X     */
X    for (i=0; i<num_of_disps; i++)
X    {
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X            the_font_struct = XLoadQueryFont(disp_info[i].disp, "fixed");
X            disp_info[i].rubber_pointer.width = 15 + 
X					  XTextWidth(the_font_struct,
X		                          disp_args[i], strlen(disp_args[i]));
X            disp_info[i].rubber_pointer.height =
X				   15 + the_font_struct->max_bounds.ascent + 
X				   the_font_struct->max_bounds.descent;
X            disp_info[i].rubber_pointer.is_mapped_bool = FALSE;
X
X            for (j=0; j<num_of_disps; j++)
X            {
X	        if (disp_info[j].in_session_bool)
X	        {
X	            if ((i == disp_num) || (j == disp_num))
X	            {
X	                disp_info[i].rubber_pointer.rubber_pointer_pix[j] = 
X				 XCreatePixmap(
X				     disp_info[j].disp, disp_info[j].win_id,
X	                             disp_info[i].rubber_pointer.width, 
X				     disp_info[i].rubber_pointer.height, 
X				     DefaultDepth(disp_info[j].disp, 
X				     DefaultScreen(disp_info[j].disp)));
X                    }
X	        }
X	    }
X	}
X    }
X
X    /*
X     * size the new window correctly
X     */
X    for (i=0; i<num_of_disps; i++)
X    {
X        if ((disp_info[i].in_session_bool==TRUE) && (i!=disp_num))
X        {
X             XGetWindowAttributes(disp_info[i].disp, disp_info[i].win_id,
X			 &attr_ret);
X	     XResizeWindow(disp_info[disp_num].disp, disp_info[disp_num].win_id,
X			   attr_ret.width, attr_ret.height);
X             disp_info[disp_num].win_width = attr_ret.width;
X             disp_info[disp_num].win_height = attr_ret.height;
X	     break;
X	}
X    }
X
X    /*
X     * bring this window up with all this fun new information.
X     */
X    XMapWindow(disp_info[disp_num].disp, disp_info[disp_num].win_id);
X    XSync(disp_info[disp_num].disp, False);
X    place_and_draw_status_win(disp_num);
X
X    return(TRUE);   /*it was successful, we are ready to rock and roll*/
X}
X
X
X/*
X * initialize_displays - this function opens all the displays, including
X *                       the home one, opens a window on each and assigns
X *                       each window a gc, window id, menus, etc.
X */
Xinitialize_displays(num_people_drawing)
Xint *num_people_drawing;
X{
X    unsigned long alter_these_mask = GCSubwindowMode | GCLineWidth | 
X				     GCForeground | GCCapStyle | GCFont |
X				     GCBackground | GCGraphicsExposures;
X    unsigned long alter_menu_mask =  GCSubwindowMode | GCForeground | GCFont |
X				     GCBackground | GCLineWidth;
X    unsigned long alter_these2_mask = CWEventMask | CWBackPixel | 
X				   CWBackingStore | CWWinGravity |
X				   CWBitGravity | CWSaveUnder;
X    unsigned long alter_menu2_mask = CWEventMask | CWBackPixel | CWSaveUnder |
X				     CWBackingStore | CWWinGravity;
X    XSizeHints win_size_hints;
X    Cursor the_cursor, menu_cursor;
X    XColor scrn_def_ret, exact_def_ret, scrn_def_ret2, exact_def_ret2;
X    XColor curs_foregrexact, curs_foregr, curs_backgr, curs_backgrexact;
X    Pixmap source, mask;
X    int i, j, k, menu_num;
X    int menu_x_val;
X    XWindowAttributes attr_ret;
X    XFontStruct *the_font_struct;
X    char tmp_str[50], tmp_str2[50];
X    XGCValues cursor_gc_values;
X
X    menu_text[0] = menu_text0;   /*connect the menu text to the global struct*/
X    menu_text[1] = menu_text1;
X    menu_text[2] = menu_text2;
X    menu_text[3] = menu_text3;
X    menu_text[4] = menu_text4;
X    menu_text[5] = menu_text5;
X    menu_text[6] = menu_text6;
X
X    for (i=0; i<MAX_NUM_DISPS; i++)
X        disp_info[i].in_session_bool = FALSE;
X
X    for (i=0; i<num_of_disps; i++)
X        disp_info[i].in_session_bool = TRUE;
X
X    /*
X     * The following opens all the displays and windows and initializes some
X     * of the disp_info fields.  The cursor is defined for the window, and
X     * the window manager is instructed how to behave with these new windows.
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (i==0)     /*open home display*/
X	{
X	    if (disp_info[0].in_session_bool)/*only if this session is wanted*/
X	    {
X                if (strcmp(disp_args[0], "") == 0) /*not written into yet*/
X		{
X                    if ((disp_info[0].disp = XOpenDisplay(NULL)) == NULL)
X                    {
X                       printf("XOpenDisplay failed on DISPLAY env variable.\n");
X	               disp_info[0].in_session_bool = FALSE; /*not in session*/
X		       if (num_of_disps <= 1)
X			   exit(0);         /*bag it*/
X		       else
X			   continue;
X                    }
X	            else
X		       strncpy(disp_args[0], 
X				DisplayString(disp_info[0].disp), 30);
X		}
X                else if ((disp_info[0].disp=XOpenDisplay(disp_args[0]))== NULL)
X                {
X                   printf("XOpenDisplay failed on display: %s\n",disp_args[0]);
X                   exit(0);
X                }
X	    }
X	}
X	else         /*open this particular away display*/
X	{
X	    if (disp_info[i].in_session_bool)/*only if this session is wanted*/
X	    {
X                if ((disp_info[i].disp = XOpenDisplay (disp_args[i])) == NULL)
X                {
X                   printf("XOpenDisplay failed on display: %s\n", disp_args[i]);
X                   exit(0);
X                }
X	    }
X        }
X
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X	    winvals.backing_store = Always;
X            if (!XAllocNamedColor(disp_info[i].disp, 
X		DefaultColormap(disp_info[i].disp, 
X	        DefaultScreen(disp_info[i].disp)), BACKGROUND_COLOR, 
X	        &scrn_def_ret, &exact_def_ret))
X            {
X	         printf("\nThe color %s is not supported", BACKGROUND_COLOR);
X	         printf(" on the display %s.\n", disp_args[i]);
X	         exit(0);
X	    }
X	    winvals.background_pixel = scrn_def_ret.pixel;
X	    winvals.bit_gravity = NorthWestGravity;
X            disp_info[i].background = scrn_def_ret.pixel;
X
X	    disp_info[i].win_id = XCreateWindow(disp_info[i].disp, RootWindow(
X		  disp_info[i].disp, DefaultScreen(disp_info[i].disp)), 
X		  5+(i*80), 5+(i*80), WSCRAWL_WIN_WIDTH, WSCRAWL_WIN_HEIGHT, 3,
X		  0,CopyFromParent,CopyFromParent,alter_these2_mask, &winvals);
X
X
X            disp_info[i].win_gc = (GC *) malloc(num_of_disps * sizeof(GC));
X
X	    disp_info[i].connection_num = ConnectionNumber(disp_info[i].disp);
X            disp_info[i].first_point_bool = FALSE;
X            disp_info[i].pointer_state = NOT_PRESSED;
X	    disp_info[i].scrawl_mode = SCRAWLING;
X	    disp_info[i].current_shape = OUTLINE_RECT;
X            disp_info[i].type_history = NULL;
X            disp_info[i].just_placed_something_bool = FALSE;
X
X	    cursor_gc_values.line_width = 5;
X	    cursor_gc_values.function = GXinvert;
X	    cursor_gc_values.background =  BlackPixelOfScreen(
X		               DefaultScreenOfDisplay(disp_info[i].disp));
X            cursor_gc_values.foreground =  WhitePixelOfScreen(
X		               DefaultScreenOfDisplay(disp_info[i].disp));
X            disp_info[i].cursor_gc = XCreateGC(disp_info[i].disp, 
X	              disp_info[i].win_id,
X	              GCFunction | GCBackground | GCForeground | GCLineWidth, 
X		      &cursor_gc_values);
X
X            if (!TYPE_NOT_DRAW)
X                the_cursor = XCreateFontCursor(disp_info[i].disp, XC_dot);
X
X            XDefineCursor(disp_info[i].disp, disp_info[i].win_id, the_cursor);
X
X	    win_size_hints.flags = USPosition | PPosition;
X	    win_size_hints.x = 5 + (i * 80);
X	    win_size_hints.y = 5 + (i * 80);
X
X	    XSetStandardProperties(disp_info[i].disp, disp_info[i].win_id, 
X	        "WSCRAWL: a product of eXcess engineering", "wscrawl", None, 
X		NULL, 0, &win_size_hints);
X
X	    /* the following three calls are to change window manager behavior*/
X            disp_info[i].xa_WM_PROTOCOLS = XInternAtom(disp_info[i].disp, 
X						   "WM_PROTOCOLS", FALSE);
X            disp_info[i].xa_WM_DELETE_WINDOW = XInternAtom(disp_info[i].disp, 
X					            "WM_DELETE_WINDOW", FALSE);
X            XChangeProperty(disp_info[i].disp, disp_info[i].win_id, 
X			disp_info[i].xa_WM_PROTOCOLS, 
X			disp_info[i].xa_WM_PROTOCOLS, 32, PropModeReplace,
X		        (char *) &(disp_info[i].xa_WM_DELETE_WINDOW), 1);
X	}
X    }
X
X    /*
X     * The following changes the names in the "disp_args[]" array to reflect
X     * the ACTUAL machine and display instead of things like "local:0" etc.
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X            if ((strncmp(disp_args[i], "local", 5) == 0) ||
X                (strncmp(disp_args[i], "unix", 4) == 0) ||
X                (strncmp(disp_args[i], ":", 1) == 0))
X	    {
X                /*
X	         * this is a wscrawl window on the invoker's home display, so
X	         * change it to be meaningful.
X	         */
X                gethostname(tmp_str, 30);
X                sprintf(tmp_str2, "%s%s", tmp_str, strpbrk(disp_args[i], ":"));
X                strncpy(disp_args[i], tmp_str2, 30);
X	    }
X	}
X    }
X
X    /*
X     * The following initializes the win_gc's for all the displays.
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X	    /*
X	     * The following assigns this "user" N graphics contexts, where N
X	     * is the number of open displays.  This "user" wants his particular
X	     * color on every display, and since gc's are attached to displays,
X	     * we need one with this color loaded on every display.  These gc's
X	     * are then used for pen width, pen caps, etc.
X	     */
X	    strncpy(disp_info[i].pen_color_str, PEN_COLOR, 40);
X	    strncpy(disp_info[i].font_str, FONT, 250);
X	    disp_info[i].capstyle = CAP_STYLE;
X
X	    for (j=0; j<num_of_disps; j++)
X	    {
X	        if (disp_info[j].in_session_bool) /*only if session is wanted*/
X	        {
X                    if (XAllocNamedColor(disp_info[j].disp, DefaultColormap(
X		         disp_info[j].disp, DefaultScreen(disp_info[j].disp)), 
X		         PEN_COLOR, &scrn_def_ret, &exact_def_ret))
X	            {
X		        ;  /*great!  it worked!*/
X	            }
X	            else if (!XAllocNamedColor(disp_info[j].disp, 
X			 DefaultColormap(
X		         disp_info[j].disp, DefaultScreen(disp_info[j].disp)), 
X		         "black", &scrn_def_ret, &exact_def_ret))
X	            {
X	                printf("The color %s is not", PEN_COLOR);
X	                printf(" supported on the display %s.\n", disp_args[i]);
X	                exit(0);
X	            }
X                    gcvalues.foreground = scrn_def_ret.pixel;
X        
X                    gcvalues.background =
X				     WhitePixelOfScreen(DefaultScreenOfDisplay(
X					         disp_info[j].disp));
X    
X		    gcvalues.line_width = PEN_WIDTH;
X                    gcvalues.cap_style = CAP_STYLE;
X                    gcvalues.graphics_exposures = False;
X        
X                    if ((the_font_struct = XLoadQueryFont(disp_info[j].disp, 
X			 FONT)) != NULL)
X	            {
X	                 gcvalues.font = the_font_struct->fid;
X	            }
X	            else if ((the_font_struct=XLoadQueryFont(disp_info[j].disp,
X		        "fixed")) != NULL)
X	            {
X	                 printf("WARNING: Couldn't allocate font: %s", FONT);
X	                 printf(" on display %s.  Using fixed.\n",disp_args[j]);
X	                 gcvalues.font = the_font_struct->fid;
X	            }
X	            else
X	            {
X	                printf("\nERROR: Couldn't allocate a font ");
X		        printf("on display: %s.\n", disp_args[j]);
X	                exit(0);
X                    }
X        
X                    disp_info[i].win_gc[j] = XCreateGC(disp_info[j].disp, 
X		             disp_info[j].win_id, alter_these_mask, &gcvalues);
X	            disp_info[i].the_font_struct = the_font_struct;
X	        }
X            }
X	}
X    }
X    
X    /*
X     * create the rubber_band_gc's for all the scrawl windows
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X	    gcvalues.function = GXinvert;
X	    gcvalues.line_width = 0;
X            disp_info[i].rubber_band_gc = XCreateGC(disp_info[i].disp, 
X		 disp_info[i].win_id, GCLineWidth | GCFunction, &gcvalues);
X	}
X    }
X
X    /*
X     * create and initialize the menus on each scrawl window
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X	    for (menu_num=0; menu_num<NUM_OF_MENUS; menu_num++)
X	    {
X                if (XAllocNamedColor(disp_info[i].disp, 
X		    DefaultColormap(disp_info[i].disp, 
X	            DefaultScreen(disp_info[i].disp)), MENU_BACKGROUND_COLOR, 
X	            &scrn_def_ret, &exact_def_ret))
X                {
X	            menuwinvals.background_pixel = scrn_def_ret.pixel;
X	        }
X                else if (XAllocNamedColor(disp_info[i].disp, 
X		    DefaultColormap(disp_info[i].disp, 
X	            DefaultScreen(disp_info[i].disp)), "white", 
X	            &scrn_def_ret, &exact_def_ret))
X                {
X	            printf("The color %s is not", MENU_BACKGROUND_COLOR);
X	            printf(" supported on display %s.\n", disp_args[i]);
X	            printf("Using white for the menu background color.\n");
X		    strcpy(MENU_BACKGROUND_COLOR, "white");
X	            menuwinvals.background_pixel = scrn_def_ret.pixel;
X	        }
X	        else
X	        {
X	            printf("The menu background color had extra problems on");
X		    printf(" display %s.\n", disp_args[i]);
X		    exit(0);
X                }
X    
X	        menu_x_val = menu_num*MENU_ITEM_WIDTH + (menu_num*2);
X    
X	        /* uncomment this line to reproduce HP backingstore bug
X	        menuwinvals.backing_store = Always;
X                 */
X    
X	        menuwinvals.save_under = True;
X	        disp_info[i].menu[menu_num].win_id =
X		     XCreateWindow(disp_info[i].disp, disp_info[i].win_id, 
X		       menu_x_val, 0, MENU_ITEM_WIDTH, MENU_ITEM_HEIGHT, 2, 
X		       0, CopyFromParent, CopyFromParent, alter_menu2_mask, 
X		       &menuwinvals);
X                XMapWindow(disp_info[i].disp,
X			    disp_info[i].menu[menu_num].win_id);
X    
X	        menu_cursor =XCreateFontCursor(disp_info[i].disp,XC_right_ptr);
X	        XDefineCursor(disp_info[i].disp, 
X			    disp_info[i].menu[menu_num].win_id, menu_cursor);
X    
X	        disp_info[i].menu[menu_num].item_selected = NO_ITEM_SELECTED;
X            }
X    
X	    /*
X	     * find the num of items in each menu and assign it to the correct
X	     * variable in the structure. "k" is the menu_item_num.
X	     */
X	    for (menu_num=0; menu_num < NUM_OF_MENUS; menu_num++)
X	    {
X	        for (k=0; strcmp(menu_text[menu_num][k], "****") != 0; k++)
X	            ;
X                disp_info[i].menu[menu_num].num_items = k;
X		switch(menu_num)
X		{
X		    case 0:                   /*Control menu*/
X		        disp_info[i].menu[menu_num].checked_item = 1;
X			break;
X		    case 1:                   /*PenColor menu*/
X		        disp_info[i].menu[menu_num].checked_item = 2;
X			break;
X		    case 2:                   /*PenWidth menu*/
X		        disp_info[i].menu[menu_num].checked_item = 4;
X			break;
X		    case 3:                   /*PenCapStyle menu*/
X		        disp_info[i].menu[menu_num].checked_item = 1;
X			break;
X		    case 4:                   /*Font menu*/
X		        disp_info[i].menu[menu_num].checked_item = 14;
X			break;
X		    case 5:                   /*Shapes menu*/
X		        disp_info[i].menu[menu_num].checked_item = 2;
X			break;
X		    default:
X			break;
X		}
X            }
X    
X            if (!XAllocNamedColor(disp_info[i].disp, 
X		    DefaultColormap(disp_info[i].disp, 
X	            DefaultScreen(disp_info[i].disp)), MENU_HIGHLIGHT_COLOR, 
X	            &scrn_def_ret, &exact_def_ret))
X            {
X	            printf("The color %s is not", MENU_HIGHLIGHT_COLOR);
X	            printf(" supported on the display %s.\n", disp_args[i]);
X	            exit(0);
X            }
X            menugcvalues.foreground = scrn_def_ret.pixel;
X    
X            if (!XAllocNamedColor(disp_info[i].disp, 
X	        DefaultColormap(disp_info[i].disp, 
X	        DefaultScreen(disp_info[i].disp)), MENU_BACKGROUND_COLOR, 
X	        &scrn_def_ret2, &exact_def_ret2))
X            {
X	        printf("The menu background color had second round problems ");
X    	        printf("on the display %s.\n", disp_args[i]);
X	        exit(0);
X            }
X    
X            menugcvalues.background = scrn_def_ret2.pixel;
X    
X            menugcvalues.line_width = 2;
X            menugcvalues.font = XLoadFont(disp_info[i].disp, "fixed");
X	    disp_info[i].hi_menu_gc = XCreateGC(disp_info[i].disp, 
X	          disp_info[i].menu[0].win_id, alter_menu_mask, &menugcvalues);
X    
X	    /*
X	     * switch foreground and background colors for bg_menu_gc
X	     */
X            menugcvalues.foreground = scrn_def_ret2.pixel;
X            menugcvalues.background = scrn_def_ret.pixel;
X	    disp_info[i].bg_menu_gc = XCreateGC(disp_info[i].disp, 
X	          disp_info[i].menu[0].win_id, alter_menu_mask, &menugcvalues);
X    
X            if (!XAllocNamedColor(disp_info[i].disp, 
X		    DefaultColormap(disp_info[i].disp, 
X	            DefaultScreen(disp_info[i].disp)), MENU_FOREGROUND_COLOR, 
X	            &scrn_def_ret, &exact_def_ret))
X            {
X	            printf("The color %s is not", MENU_FOREGROUND_COLOR);
X	            printf(" supported on the display %s.\n", disp_args[i]);
X	            exit(0);
X            }
X            menugcvalues.foreground = scrn_def_ret.pixel;
X            menugcvalues.background = scrn_def_ret2.pixel;
X	    disp_info[i].fg_menu_gc = XCreateGC(disp_info[i].disp, 
X	        disp_info[i].menu[0].win_id, alter_menu_mask, &menugcvalues);
X    
X	    for (menu_num=0; menu_num<NUM_OF_MENUS; menu_num++)
X	    {
X	        disp_info[i].current_menu = menu_num;
X	        draw_menu(i);
X	    }
X        }
X    }
X    
X    /*
X     * create the status window and eraser window, and dialog window for 
X     * each scrawl window 
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X            if (!XAllocNamedColor(disp_info[i].disp, 
X		DefaultColormap(disp_info[i].disp, 
X	        DefaultScreen(disp_info[i].disp)), MENU_BACKGROUND_COLOR, 
X	        &scrn_def_ret, &exact_def_ret))
X            {
X	        printf("The color %s is not", MENU_BACKGROUND_COLOR);
X	        printf(" supported on the display %s.\n", disp_args[i]);
X	        exit(0);
X            }
X            menuwinvals.background_pixel = scrn_def_ret.pixel;
X            menuwinvals.save_under = True;
X	    disp_info[i].eraser_win_id = XCreateWindow(disp_info[i].disp,
X	       disp_info[i].win_id, 0, 350, 550, 20, 2, 0, CopyFromParent, 
X	       CopyFromParent, alter_menu2_mask, &menuwinvals);
X	    disp_info[i].status_win_id = XCreateWindow(disp_info[i].disp,
X		   disp_info[i].win_id, 0, 350, 550, 20, 2, 0, CopyFromParent, 
X		   CopyFromParent, alter_menu2_mask, &menuwinvals);
X	    disp_info[i].dialog_win_id = XCreateWindow(disp_info[i].disp,
X		   disp_info[i].win_id, 50, 80, DIALOG_WIN_WIDTH, 
X		   DIALOG_WIN_HEIGHT, 2, 0, CopyFromParent, 
X		   CopyFromParent, alter_menu2_mask, &menuwinvals);
X            XMapWindow(disp_info[i].disp, disp_info[i].status_win_id);
X	    XDefineCursor(disp_info[i].disp, disp_info[i].status_win_id,
X			  XCreateFontCursor(disp_info[i].disp, XC_star));
X	    XDefineCursor(disp_info[i].disp, disp_info[i].eraser_win_id,
X			  XCreateFontCursor(disp_info[i].disp, XC_draped_box));
X	    XDefineCursor(disp_info[i].disp, disp_info[i].dialog_win_id,
X			  XCreateFontCursor(disp_info[i].disp, XC_xterm));
X	    XLowerWindow(disp_info[i].disp, disp_info[i].eraser_win_id);
X        }
X    }
X
X    /*
X     * if typing, set cursor, font, etc correctly with a call to 
X     * menu_selection (which is usually called when you pull down a menu).
X     */
X    for (i=0; i<num_of_disps; i++)
X    {
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X            if (TYPE_NOT_DRAW)
X                 menu_selection(i, 0, num_people_drawing, 3);
X	}
X    }
X
X    /*
X     * create the "pause cursor" for each display
X     */
X    for (i=0; i<num_of_disps; i++)
X    {
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X            source = XCreatePixmapFromBitmapData(disp_info[i].disp, 
X	      disp_info[i].win_id, pause_curs_bits, pause_curs_width, 
X	      pause_curs_height, 
END_OF_FILE
if test 39069 -ne `wc -c <'wscrawl/xae'`; then
    echo shar: \"'wscrawl/xae'\" unpacked with wrong size!
fi
# end of 'wscrawl/xae'
fi
if test -f 'wscrawl/xaf' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/xaf'\"
else
echo shar: Extracting \"'wscrawl/xaf'\" \(4708 characters\)
sed "s/^X//" >'wscrawl/xaf' <<'END_OF_FILE'
X	      WhitePixel(disp_info[i].disp, DefaultScreen(disp_info[i].disp)), 
X	      BlackPixel(disp_info[i].disp, DefaultScreen(disp_info[i].disp)), 
X	      1);
X
X            mask = XCreatePixmapFromBitmapData(disp_info[i].disp, 
X	      disp_info[i].win_id, pause_curs_bits, pause_curs_width, 
X	      pause_curs_height, 
X	      WhitePixel(disp_info[i].disp, DefaultScreen(disp_info[i].disp)), 
X	      BlackPixel(disp_info[i].disp, DefaultScreen(disp_info[i].disp)), 
X	      1);
X
X	    XAllocNamedColor(disp_info[i].disp, DefaultColormapOfScreen(
X		         DefaultScreenOfDisplay(disp_info[i].disp)),
X			 "white", &curs_backgr, &curs_backgrexact);
X	    XAllocNamedColor(disp_info[i].disp, DefaultColormapOfScreen(
X		         DefaultScreenOfDisplay(disp_info[i].disp)),
X			 "black", &curs_foregr, &curs_foregrexact);
X
X            disp_info[i].pause_cursor = XCreatePixmapCursor(disp_info[i].disp, 
X		      source, mask, &curs_foregrexact, &curs_backgrexact, 
X		      pause_curs_x_hot, pause_curs_y_hot);
X	 }
X    }
X
X    /*
X     * create the rubber cursor pixmaps for all the displays
X     */
X    for (i=0; i<num_of_disps; i++)
X    {
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X            the_font_struct = XLoadQueryFont(disp_info[i].disp, "fixed");
X            disp_info[i].rubber_pointer.width = 15 + XTextWidth(the_font_struct,
X		                          disp_args[i], strlen(disp_args[i]));
X            disp_info[i].rubber_pointer.height =
X				   15 + the_font_struct->max_bounds.ascent + 
X				   the_font_struct->max_bounds.descent;
X            disp_info[i].rubber_pointer.is_mapped_bool = FALSE;
X
X            for (j=0; j<num_of_disps; j++)
X            {
X	        if (disp_info[j].in_session_bool)
X	        {
X	            disp_info[i].rubber_pointer.rubber_pointer_pix[j] = 
X				 XCreatePixmap(
X				     disp_info[j].disp, disp_info[j].win_id,
X	                             disp_info[i].rubber_pointer.width, 
X				     disp_info[i].rubber_pointer.height, 
X				     DefaultDepth(disp_info[j].disp, 
X				     DefaultScreen(disp_info[j].disp)));
X                }
X	    }
X	}
X    }
X
X    /*
X     * set the default penwidths
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X	    disp_info[i].pen_widths.scrawl = 8;
X	    disp_info[i].pen_widths.airbrush = 40;
X	    disp_info[i].pen_widths.eraser = 40;
X	    disp_info[i].pen_widths.shape = 8;
X	}
X    }
X
X    /*
X     * bring all the windows up with all this fun new information.
X     */
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X	    XMapWindow(disp_info[i].disp, disp_info[i].win_id);
X            XSync(disp_info[i].disp, False);
X	}
X    }
X
X    for (i=0; i<num_of_disps; i++)
X    {
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	    place_and_draw_status_win(i);
X    }
X
X    for (i=0; i<num_of_disps; i++)
X    { 
X	if (disp_info[i].in_session_bool)  /*only if this session is wanted*/
X	{
X            XGetWindowAttributes(disp_info[i].disp, disp_info[i].win_id,
X				 &attr_ret);
X	    disp_info[i].win_width = attr_ret.width;
X	    disp_info[i].win_height = attr_ret.height;
X        }
X    }
X    NOTHING_DRAWN_YET = TRUE;
X}
X
X
X/*
X * airbrush - this function draws a "spray can" type stipple on the window
X *            window passed as an argument.  Thanks to Mark Cook for supplying
X *            this algorithm.
X */
Xairbrush(input_disp, disp, win, win_gc, win_x, win_y)
XDisplay *disp;
XWindow win; 
XGC win_gc;
Xint win_x, win_y;
X{
X    int i, rx, ry, RADIUS;
X    XPoint spray_points[502];
X
X    RADIUS = (disp_info[input_disp].pen_width)/2;
X
X    for (i=0; i<NUM_DOTS; i++)
X    {
X        rx = (my_rand()*RADIUS) - (my_rand()*RADIUS);
X        ry = (my_rand()*RADIUS) - (my_rand()*RADIUS);
X        if (rx < (-RADIUS))
X	    rx = (-RADIUS);
X        if (rx > (RADIUS))
X	    rx = RADIUS;
X        if (ry < (-RADIUS))
X	    ry = (-RADIUS);
X        if (ry > (RADIUS))
X	    ry = RADIUS;
X        spray_points[i].x = win_x + rx;
X        spray_points[i].y = win_y + ry;
X    }
X    XDrawPoints(disp, win, win_gc, spray_points, NUM_DOTS, CoordModeOrigin);
X}
X
X
X/*
X * my_rand - NOTE: THIS MAY REQUIRE A PORT: due to the non-standard "rand"
X *           function, this routine is not entirely portable.  The reason
X *           this function is here is to allow you to hack on it to get it
X *           to return a value between 0 and 1.  This only affects the 
X *           airbrush.
X */
Xfloat my_rand()
X{
X    float ret_val;
X
X    ret_val = (float) ((double)rand()/(double)MAX_RAND);
X
X    if (ret_val > 1.0)
X        ret_val = (ret_val - ((float) (1 * ((int) ret_val))));
X
X    return(ret_val);
X}
X
END_OF_FILE
if test 4708 -ne `wc -c <'wscrawl/xaf'`; then
    echo shar: \"'wscrawl/xaf'\" unpacked with wrong size!
fi
# end of 'wscrawl/xaf'
fi
echo shar: End of archive 1 \(of 5\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
dan
----------------------------------------------------
O'Reilly && Associates   argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.



More information about the Comp.sources.x mailing list