v08i057: wscrawl, Part05/05

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


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

#! /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 5 (of 5)."
# Contents:  wscrawl/image_f_io.c wscrawl/xab
# Wrapped by argv at turnpike on Sun Jul 15 11:47:13 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'wscrawl/image_f_io.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/image_f_io.c'\"
else
echo shar: Extracting \"'wscrawl/image_f_io.c'\" \(17959 characters\)
sed "s/^X//" >'wscrawl/image_f_io.c' <<'END_OF_FILE'
X/*
X * This file: image_f_io.c (part of the WSCRAWL program)
X *
X * This file contains the "Image File I/O" package for wscrawl (or anything
X * for that matter.)  The format used is the standard X-Window Dump form
X * that the MIT client "xwd" uses.  This File I/O was made possible by the 
X * help and extensive source code of Mark Cook of Hewlett-Packard, who I 
X * bothered endlessly to get this working.  
X * 
X * I tried to make this file of routines as self-contained and portable as
X * possible.  Please feel free to use this file as is, or with modifications,
X * for any and all applications.  -- Brian Wilson
X *
X * This file was last modified: 7/14/90
X */
X
X#define TRUE                    1
X#define FALSE                   0
X#define BAD_CHOICE		-1
X#define NO_DUPLICATE   		-1
X#define UNALLOCATED    		-1
X
X#include <X11/Xos.h>
X#include <X11/XWDFile.h>
X#include <X11/Xlib.h>
X#include <stdio.h>
X
Xextern char *malloc();
XXImage *read_image_from_disk();
X
X
X/*
X * save_image_on_disk - this routine saves the region specified by the various
X *               parameters out to disk in the "defacto standard" (xwd) format.
X */
Xsave_image_on_disk(disp, win_id, x, y, width, height, name_of_file)
XDisplay *disp;
XWindow win_id;
Xint x, y, width, height;
Xchar *name_of_file;
X{
X    unsigned long swaptest = TRUE;
X    XRectangle box2;
X    XRectangle *box;
X    FILE *out_file_ptr;
X    XColor *colors;
X    unsigned buffer_size;
X    int win_name_size;
X    int header_size;
X    int format=ZPixmap;
X    int ncolors, i;
X    XWindowAttributes win_info;
X    XImage *ImagePix;
X    XWDFileHeader header;
X
X    /*
X     * convert to form this code understands (I got code from Mark Cook)
X     */
X    box = &box2;
X    box->x = x;
X    box->y = y;
X    box->width = width;
X    box->height = height;
X
X    /*
X     * Open the file in which the image is to be stored
X     */
X    if ((out_file_ptr = fopen(name_of_file, "w")) == NULL) 
X    {
X        printf("ERROR: Could not open file %s.\n", name_of_file);
X        return(0);
X    }
X    else
X    {         /* Dump the image to the specified file */
X    
X        if (!XGetWindowAttributes(disp, win_id, &win_info)) 
X        {
X            printf("Can't get window attributes.\n");
X            return(0);
X        }
X    
X        /*
X         * sizeof(char) is included for the null string terminator. 
X         */
X        win_name_size = strlen(name_of_file) + sizeof(char);
X    
X        ImagePix = XGetImage(disp, win_id, box->x, box->y, box->width,
X                               box->height, AllPlanes, format); 
X        XFlush(disp);
X    
X        if (ImagePix == NULL) 
X        {
X            printf("GetImage failed.\n");
X            return(0);
X        }
X    
X        buffer_size = Image_Size(ImagePix,format);/*determines size of pixmap*/
X    
X        /*
X         * Get the RGB values for the current color cells
X         */
X        if ((ncolors = Get_Colors(&colors, disp)) == 0) 
X        {
X            printf("Cannot alloc memory for color structs.\n");
X            return(0);
X        }
X        XFlush(disp);
X    
X        header_size = sizeof(header) +win_name_size; /*Calculates header size*/
X    
X        /*
X         * Assemble the file header information
X         */
X        header.header_size = (xwdval) header_size;
X        header.file_version = (xwdval) XWD_FILE_VERSION;
X        header.pixmap_format = (xwdval) format;
X        header.pixmap_depth = (xwdval) ImagePix->depth;
X
X        header.pixmap_width = (xwdval) ImagePix->width;
X        header.pixmap_height = (xwdval) ImagePix->height;
X        header.xoffset = (xwdval) ImagePix->xoffset;
X        header.byte_order = (xwdval) ImagePix->byte_order;
X        header.bitmap_unit = (xwdval) ImagePix->bitmap_unit;
X        header.bitmap_bit_order = (xwdval) ImagePix->bitmap_bit_order;
X        header.bitmap_pad = (xwdval) ImagePix->bitmap_pad;
X        header.bits_per_pixel = (xwdval) ImagePix->bits_per_pixel;
X        header.bytes_per_line = (xwdval) ImagePix->bytes_per_line;
X        header.visual_class = (xwdval) win_info.visual->class;
X        header.red_mask = (xwdval) win_info.visual->red_mask;
X        header.green_mask = (xwdval) win_info.visual->green_mask;
X        header.blue_mask = (xwdval) win_info.visual->blue_mask;
X        header.bits_per_rgb = (xwdval) win_info.visual->bits_per_rgb;
X        header.colormap_entries = (xwdval) win_info.visual->map_entries;
X        header.ncolors = ncolors;
X        header.window_width = (xwdval) ImagePix->width;
X        header.window_height = (xwdval) ImagePix->height;
X        header.window_x = (xwdval) 0;
X        header.window_y = (xwdval) 0;
X        header.window_bdrwidth = (xwdval) 0;
X      
X        if (*(char *) &swaptest) 
X        {
X            _swaplong((char *) &header, sizeof(header));
X            for (i = 0; i < ncolors; i++) 
X	    {
X                _swaplong((char *) &colors[i].pixel, sizeof(long));
X                _swapshort((char *) &colors[i].red, 3 * sizeof(short));
X            }
X        }
X    
X        /*
X         * Write out the file header information
X         */
X        (void) fwrite((char *)&header, sizeof(header), 1, out_file_ptr);
X        (void) fwrite(name_of_file, win_name_size, 1, out_file_ptr);
X    
X        /*
X         * Write out the color cell RGB values
X         */
X        (void) fwrite((char *) colors, sizeof(XColor), ncolors, out_file_ptr);
X    
X        /*
X         * Write out the buffer
X         */
X        (void) fwrite(ImagePix->data, (int) buffer_size, 1, out_file_ptr);
X    
X        if(ncolors > 0) 
X            free(colors);    /*free the color buffer*/
X    
X        fclose(out_file_ptr);
X        XFlush(disp);
X    }
X}
X
X
X/*
X * Image_Size - this routine takes an XImage and returns it's total byte count
X */
Xint Image_Size(image, format)
XXImage *image;
Xint format;
X{
X    if (format != ZPixmap)
X        return(image->bytes_per_line * image->height * image->depth);
X    else
X        return(image->bytes_per_line * image->height);
X}
X
X
X/*
X * Get_Colors - takes a pointer to an XColor struct and returns the total
X *            number of cells in the current colormap, plus all of their
X *            RGB values.
X */
XGet_Colors(colors, disp)
XXColor **colors;
XDisplay *disp;
X{
X    int i, ncolors;
X
X    ncolors = DisplayCells(disp, DefaultScreen(disp));
X
X    if ((*colors = (XColor *) malloc (sizeof(XColor) * ncolors)) == NULL)
X        return(FALSE);
X
X    for (i=0; i<ncolors; i++)
X        (*colors)[i].pixel = i;
X
X    XQueryColors(disp, XDefaultColormapOfScreen(XDefaultScreenOfDisplay(disp)),
X		 *colors, ncolors);
X    return(ncolors);
X}
X
X
X/*
X * _swapshort - this routine is stolen, and I don't know what it does
X */
X_swapshort (bp, n)
Xregister char *bp;
Xregister unsigned n;
X{
X    register char c;
X    /* register char *ep = bp + n; */
X    register char *ep;
X
X    ep = bp + n;
X    while (bp < ep) 
X    {
X        c = *bp;
X        *bp = *(bp + 1);
X        bp++;
X        *bp++ = c;
X    }
X}
X
X
X/*
X * _swaplong - this routine is stolen, and I don't know what it does
X */
X_swaplong (bp, n)
Xregister char *bp;
Xregister unsigned n;
X{
X    register char c;
X    /* register char *ep = bp + n; */
X    register char *sp;
X    register char *ep;
X
X    ep = bp + n;
X    while (bp < ep) 
X    {
X        sp = bp + 3;
X        c = *sp;
X        *sp = *bp;
X        *bp++ = c;
X        sp = bp + 1;
X        c = *sp;
X        *sp = *bp;
X        *bp++ = c;
X        bp += 2;
X    }
X}
X
X
X/*
X * read_image_from_disk - this routine reads the file indicated and allocates
X *               and loads up and then finally returns the XImage structure
X *               ready to blow out to the indicated display.  If at all
X *               possible, it attempts to return an image with the
X *               depth equalling the depth of the disp passed in.  Either
X *               way, it will return the depth it managed to get.
X */
XXImage *read_image_from_disk(disp, win_id, name_of_file, width, height, depth)
XDisplay *disp;
XWindow win_id;
Xchar *name_of_file;
Xint *width, *height, *depth;
X{
X    XImage *ImagePix;
X    unsigned long swaptest = TRUE;
X    unsigned buffer_size;
X    char *buffer;
X    char *win_name;
X    int format;
X    int i, name_size, ncolors;
X    XColor *colors;
X    FILE *in_file;
X    XWDFileHeader header;
X
X    if ((in_file = fopen(name_of_file, "r")) == NULL)  /*open file for read*/
X    {
X	printf("ERROR: could not open file %s.\n", name_of_file);
X        return(0);
X    }
X  
X    if(fread((char *)&header, sizeof(header), 1, in_file) != 1) /*read header*/
X    {
X	printf("ERROR: unable to read imagefile header.\n");
X        return(0);
X    }
X
X    if (*(char *) &swaptest)
X        _swaplong((char *) &header, sizeof(header));
X
X    /*
X     * check to see if the dump file is in the proper format 
X     */
X    if (header.file_version != XWD_FILE_VERSION) 
X    {
X	printf("ERROR: Imagefile format version mismatch.\n");
X        return(0);
X    }
X
X    if (header.header_size < sizeof(header)) 
X    {
X	printf("ERROR: Imagefile header is too small.\n");
X        return(0);
X    }
X
X    name_size = (header.header_size - sizeof(header)); /*space for window name*/
X
X    if((win_name = malloc((unsigned) name_size*sizeof(char))) == NULL) 
X    {
X        printf("ERROR: Can't malloc window name storage.\n");
X        return(0);
X    }
X
X    /*
X     * Read in window name
X     */
X    if(fread(win_name, sizeof(char), name_size, in_file) != name_size) 
X    {
X        printf("ERROR: Unable to read window name from file.\n");
X        return(0);
X    }
X
X    /*
X     * Malloc the image data space and initialize it 
X     */
X    if((ImagePix = (XImage *) malloc(sizeof(XImage))) == NULL) 
X    {
X	printf("ERROR: Can't malloc space for the image.\n");
X        return(0);
X    }
X
X    ImagePix->width = (int) header.pixmap_width;
X    ImagePix->height = (int) header.pixmap_height;
X    ImagePix->xoffset = (int) header.xoffset;
X    ImagePix->format = (int) header.pixmap_format;
X    ImagePix->byte_order = (int) header.byte_order;
X    ImagePix->bitmap_unit = (int) header.bitmap_unit;
X    ImagePix->bitmap_bit_order = (int) header.bitmap_bit_order;
X    ImagePix->bitmap_pad = (int) header.bitmap_pad;
X    ImagePix->depth = (int) header.pixmap_depth;
X    ImagePix->bits_per_pixel = (int) header.bits_per_pixel;
X    ImagePix->bytes_per_line = (int) header.bytes_per_line;
X    ImagePix->red_mask = header.red_mask;
X    ImagePix->green_mask = header.green_mask;
X    ImagePix->blue_mask = header.blue_mask;
X    ImagePix->obdata = NULL;
X    _XInitImageFuncPtrs(ImagePix);
X
X    format = ImagePix->format;
X
X    /* malloc memory for the RGB values from the old colormap and read 
X     * in the values
X     */
X    if (ncolors = header.ncolors) 
X    {
X        if ((colors = (XColor *) malloc(ncolors * sizeof(XColor))) == NULL) 
X	{
X	    printf("ERROR: Can't malloc space for the image cmap.\n");
X            if (win_name) 
X		free(win_name);
X            if (ImagePix) 
X		XDestroyImage(ImagePix);
X            return(0);
X        }
X
X        if (fread((char *)colors, sizeof(XColor), ncolors, in_file) != ncolors)
X	{
X	    printf("ERROR: Unable to read cmap from imagefile.\n");
X            if (win_name) 
X		free(win_name);
X            if (ImagePix) 
X		XDestroyImage(ImagePix);
X            if (colors) 
X		free((char *) colors);
X            return(0);
X        }
X
X        if (*(char *) &swaptest) 
X	{
X            for (i = 0; i < ncolors; i++) 
X	    {
X                _swaplong((char *) &colors[i].pixel, sizeof(long));
X                _swapshort((char *) &colors[i].red, 3 * sizeof(short));
X            }
X        }
X    }
X
X    buffer_size = Image_Size(ImagePix, format);   /*malloc the pixel buffer*/
X    if ((buffer = malloc(buffer_size * sizeof(char))) == NULL) 
X    {
X        printf("ERROR: Can't malloc the data buffer.\n");
X        if (win_name) 
X            free(win_name);
X        if(ImagePix) 
X	    XDestroyImage(ImagePix);
X        if (colors) 
X	    free((char *) colors);
X        return(0);
X    }
X    ImagePix->data = buffer;
X
X    /*
X     * Read in the pixmap buffer
X     */
X    if(fread(buffer, sizeof(char), (int)buffer_size, in_file) != buffer_size) 
X    {
X        printf("ERROR: Unable to read pixmap from imagefile.\n");
X        if (win_name) 
X	    free(win_name);
X        if(ImagePix) 
X	    XDestroyImage(ImagePix);
X        if (colors) 
X	    free((char *) colors);
X        if (buffer) 
X	    free((char *) buffer);
X        return(0);
X    }
X
X    (void) fclose(in_file);   /*we are done with the infile*/
X
X    *depth = ImagePix->depth; /*even if the rest fails, return the dimensions*/
X    *width = ImagePix->width;
X    *height = ImagePix->height;
X
X    if (win_name && (name_size > 0)) 
X        free(win_name);
X    if (allocate_colors_and_assign_em(disp, win_id, &ImagePix, colors)
X	!= TRUE) 
X    {
X        /* the above
X         * converts the pixels in the xwd file over to the current colormap,
X         * and also swaps the image to a new depth if the depth the
X         * image was stored on disk as disagrees with the depth of the window
X         * it is to be blasted into.  This block is if that fails.
X         */
X        printf("ERROR: Can't convert xwd file to usuable format.\n");
X        printf("       Probably because the display is a wimpy non-HP.\n");
X        if(ImagePix) 
X	    XDestroyImage(ImagePix);
X        if (colors) 
X	    free((char *) colors);
X        return(0);
X    }
X    else if (colors) 
X	free((char *) colors);
X
X    *depth = ImagePix->depth;    /*the depth may have changed*/
X    return(ImagePix);
X}
X
X
X/*
X * allocate_colors_and_assign_em - this function takes an XImage and it's 
X *            colormap as it was at the time the image was created, and 
X *            allocates cells in the system colormap matching those old colors 
X *            and shuffles the pixels in the image to point to our new color
X *            cells instead of those old color cells.
X */
Xallocate_colors_and_assign_em(disp, win_id, image_ptr, cells)
XDisplay *disp;
XWindow win_id;
XXImage **image_ptr;
XXColor *cells;
X{
X    int width, height, i, j, num_cells_in_colormap;
X    unsigned long *opv, *npv;      /*old and new pixel values*/
X    unsigned long tmp_pixel_value;
X    XColor screen_in_out;
X    XImage *diff_depth_im, *image;
X    XWindowAttributes win_attr;
X    int buffer_size;
X    char *buffer;
X
X    image = *image_ptr;    /*for my sanity*/
X    height    = image->height;
X    width     = image->width;
X
X    /*
X     * determine the number of cells in the colormap by taking 2 to the power
X     * of the number of bits of depth this display has.
X     */
X    for (i=0, num_cells_in_colormap=1; i<(*image_ptr)->depth; i++)
X	num_cells_in_colormap *= 2;
X
X    if (num_cells_in_colormap > 256)
X    {
X        printf("WARNING: This is a monster deep display image, dude.  This "); 
X	printf("image\n");
X	printf("         will take %d mega-bytes of free memory to process.\n", 
X	       ((num_cells_in_colormap * sizeof(unsigned long))/1024)/1024);
X    }
X
X    /*
X     * set up temporary storage for the old and new pixel values
X     */
X    opv = (unsigned long *) malloc(num_cells_in_colormap*sizeof(unsigned long));
X    npv = (unsigned long *) malloc(num_cells_in_colormap*sizeof(unsigned long));
X
X    if (!opv || !npv) 
X    {
X	printf("ERROR: unable to malloc the temporary pixel storage.\n");
X        if (opv) 
X	    free((char *) opv);
X        if (npv) 
X	    free((char *) npv);
X        return(0);
X    }
X
X    /* 
X     * Each opv value is a flag indicating whether or not that pixel is
X     * present in the image.  Each npv value is it's replacement value. 
X     */
X    for (i=0; i<num_cells_in_colormap; i++) 
X    {
X        opv[i] = FALSE;
X        npv[i] = UNALLOCATED;
X    }
X
X    for (i=0; i<height;i++) /*examine each pxl in image; recrd all used values*/
X         for (j=0; j<width; j++)
X	 {
X	     tmp_pixel_value = XGetPixel(image, j, i);
X	     if (tmp_pixel_value >= num_cells_in_colormap)
X	     {
X	         printf("ERROR: Bad pixel value at x=%d, y=%d, pixel=%ld\n", 
X			 j, i, tmp_pixel_value);
X	     }
X             else
X		 opv[tmp_pixel_value] = TRUE;
X         }
X
X    /*
X     * For each TRUE opv allocate the colors
X     */
X    for (i=0; i<num_cells_in_colormap; i++)
X    {
X        if (opv[i])
X        {
X            screen_in_out.red   = cells[i].red;
X            screen_in_out.green = cells[i].green;
X            screen_in_out.blue  = cells[i].blue;
X            screen_in_out.flags = DoRed | DoGreen | DoBlue;
X
X            if (XAllocColor(disp, 
X		      XDefaultColormapOfScreen(XDefaultScreenOfDisplay(disp)),
X		      &screen_in_out) == 0)
X	    {
X	        printf("ERROR: out of colors on this display. ");
X	        printf("Cannot import image.\n");
X	        return(0);
X	    }
X            else 
X                npv[i] = screen_in_out.pixel;
X        }
X    }
X
X    XGetWindowAttributes(disp, win_id, &win_attr);
X
X    if (win_attr.depth == image->depth)    /*cool, this is easy*/
X    {
X        for (i=0; i<height; i++)
X            for (j=0; j<width; j++)
X                XPutPixel(image, j, i, npv[XGetPixel(image, j, i)]);
X    }
X    else                                   /*oh darn it, this is tough*/
X    {
X	/*
X	 * the concept here is to creat a new image that IS the correct
X	 * depth and then do "PutPixel" into it, filling it with the correct
X	 * color pixels.
X	 */
X        diff_depth_im = XCreateImage(disp, win_attr.visual, win_attr.depth, 
X	              image->format, image->xoffset, NULL, width, 
X		      height, image->bitmap_pad, 0);
X
X        buffer_size = Image_Size(diff_depth_im, 
X			      diff_depth_im->format);  /*malloc pixel buffer*/
X        if ((buffer = malloc(buffer_size * sizeof(char))) == NULL) 
X        {
X            printf("ERROR: Can't malloc data buffer for differing depth.\n");
X            return(0);
X        }
X        diff_depth_im->data = buffer;
X
X        for (i=0; i<height; i++)
X            for (j=0; j<width; j++)
X                XPutPixel(diff_depth_im, j, i, 
X			  npv[XGetPixel(image, j, i)]);
X
X	*image_ptr = diff_depth_im;
X        XDestroyImage(image);   /*free up space of wrong depth image*/
X    }
X
X    if (opv) 
X	free((char *) opv);
X    if (npv) 
X	free((char *) npv);
X
X    return(1);
X}
X
END_OF_FILE
if test 17959 -ne `wc -c <'wscrawl/image_f_io.c'`; then
    echo shar: \"'wscrawl/image_f_io.c'\" unpacked with wrong size!
fi
# end of 'wscrawl/image_f_io.c'
fi
if test -f 'wscrawl/xab' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wscrawl/xab'\"
else
echo shar: Extracting \"'wscrawl/xab'\" \(33168 characters\)
sed "s/^X//" >'wscrawl/xab' <<'END_OF_FILE'
X                (*num_people_drawing)++;        /*another dude is now drawing*/
X	    return(1);
X	} 
X	else if ((the_event->window == disp_info[disp_num].status_win_id) ||
X	         (the_event->window == disp_info[disp_num].eraser_win_id) ||
X	         (the_event->window == disp_info[disp_num].dialog_win_id))
X	{                                       /*it is in the status window*/
X            return(1);    /*no action taken*/
X	}
X	else     /*it is in a menu, determine which menu*/
X	{
X	    for (i=0, menu_num = -1; i<NUM_OF_MENUS; i++)
X	        if (the_event->window == disp_info[disp_num].menu[i].win_id)
X		{
X		    menu_num = i;
X		    break;
X		}
X	    if (menu_num == -1)
X	    {
X		printf("\nSome error occured.  ButtonPress in WHAT window?\n");
X		return(0);
X            }
X
X	    /*if we got this far, the button press is in a menu*/
X            disp_info[disp_num].current_menu = menu_num;
X            disp_info[disp_num].pointer_state = IN_MENU;
X	    disp_info[disp_num].menu[menu_num].item_selected = 0;
X	    if (disp_info[disp_num].scrawl_mode != TYPING)
X                (*num_people_drawing)++;  /*another dude is now drawing*/
X	    draw_menu(disp_num);          /*draw the menus with this new info*/
X	}
X    }
X}
X
X
X/*
X * handle_Expose_event - this function handles an Expose event in any window.
X *               The most important windows are the menu and status windows,
X *               which contain text that must always be there.  Therefore,
X *               this preserves that text.
X */
Xhandle_Expose_event(our_event, disp_num)
XXEvent *our_event;
Xint disp_num;
X{
X    XExposeEvent *the_event;
X    int menu_num;
X
X    the_event = (XExposeEvent *) our_event;
X   
X    if ((the_event->window == disp_info[disp_num].win_id) ||
X        (the_event->window == disp_info[disp_num].eraser_win_id))
X    {
X        return(1);      /*we don't care about these window expose events*/
X    }
X    else if (the_event->window == disp_info[disp_num].dialog_win_id)
X    {
X	draw_dialog_win_message(disp_num);
X        return(1);
X    }
X    else if (the_event->window == disp_info[disp_num].status_win_id)
X    {
X	draw_status_win_message(disp_num);
X        return(1);
X    }
X    else  /*It must be in a menu.  Determine which menu and draw text.*/
X    {
X        for (menu_num=0; menu_num<NUM_OF_MENUS; menu_num++)
X        {
X            if (the_event->window == disp_info[disp_num].menu[menu_num].win_id)
X	        break;
X        }
X    
X        if (menu_num >= NUM_OF_MENUS)
X        {
X            printf("\nERROR: unknown window in handle_Expose_event().\n");
X	    exit(0);
X        }
X    
X        draw_menu_text(disp_num, menu_num);          /*draw the menu text*/
X    }
X}
X
X
X/*
X * handle_KeyPress_event - this function handles a KeyPress event in
X *                   this particular scrawler's window. 
X */
Xhandle_KeyPress_event(our_event, disp_num)
XXEvent *our_event;
Xint disp_num;
X{
X    XKeyPressedEvent *the_event;
X
X    the_event = (XKeyPressedEvent *) our_event;
X   
X    if ((disp_info[disp_num].scrawl_mode == TYPING) &&
X        (disp_info[disp_num].pointer_state != IN_MENU))
X    {
X         XPutBackEvent(disp_info[disp_num].disp, (XEvent *) the_event);
X    }
X    else if ((disp_info[disp_num].scrawl_mode == RESPONDING_TO_DIALOG) &&
X        (the_event->window == disp_info[disp_num].dialog_win_id))
X    {
X         XPutBackEvent(disp_info[disp_num].disp, (XEvent *) the_event);
X    }
X}
X
X
X/*
X * handle_ConfigureNotify_event - this function handles the resizing of a
X *                   window.  If a person resizes their window, it resizes
X *                   ALL the windows associated with this session.  In this
X *                   way, the scrawlers share the size of their window.
X *                   NOTE: This routine is not full proof.  I never figured
X *                   out how to remove all contention problems.  For instance,
X *                   if two people resize their windows simultaneously, there
X *                   occurs this wierd bouncing action.  If you can figure 
X *                   something better than this out, you're a stud.  As for
X *                   me, it's 3am and I'm going home now.
X */
Xhandle_ConfigureNotify_event(our_event, disp_num)
XXEvent *our_event;
Xint disp_num;
X{
X    XConfigureEvent *the_event, *tmp_event, *(event_history[50]);
X    XEvent *the_new_event;
X    int i, history_index;
X
X    the_event = (XConfigureEvent *) our_event;
X   
X    if ((the_event->window != disp_info[disp_num].win_id) ||
X	(disp_info[disp_num].in_session_bool == FALSE))
X    {
X	return(0);	/*we are not interested in this event*/
X    }
X    
X    if ((the_event->width == disp_info[disp_num].win_width) &&
X        (the_event->height == disp_info[disp_num].win_height))
X    {
X	return(0);	/*we are not interested in this event*/
X    }
X    else
X    {
X        disp_info[disp_num].win_width = the_event->width;   /*the new height*/
X        disp_info[disp_num].win_height = the_event->height;
X    }
X
X    /*
X     * first go through ALL the resize events for ALL scrawl windows and
X     * throw away all that do not agree exactly with this one.  Put the
X     * ones that do agree back on the queue, as those are for other windows.
X     *
X     * this was necessary to avoid a perpetual loop that occurs if two people
X     * try to resize at the same time.
X     */
X    the_new_event = (XEvent *) malloc (sizeof(XEvent));
X
X    for (i=0; i<num_of_disps; i++)
X    {
X	history_index=0;
X
X	if (disp_info[i].in_session_bool == TRUE)
X	{
X            while (XCheckTypedWindowEvent(disp_info[i].disp, 
X				          disp_info[i].win_id,
X				          ConfigureNotify, the_new_event))
X            {
X                tmp_event = (XConfigureEvent *) the_new_event;
X
X		if ((the_event->width == tmp_event->width) &&
X		    (the_event->height == tmp_event->height))
X		{
X		    event_history[history_index] = tmp_event;
X		    history_index++;
X                    the_new_event = (XEvent *) malloc (sizeof(XEvent));
X		}
X            }
X
X	    /*put all the events back onto the queue*/
X	    for (history_index--; history_index>=0; history_index--)
X	    {
X                XPutBackEvent(disp_info[i].disp, 
X			      (XEvent *) event_history[history_index]);
X	        free(event_history[history_index]);
X	    }
X	}
X    }
X
X
X    for (i=0; i<num_of_disps; i++)
X    {
X	if (disp_info[i].in_session_bool == TRUE)
X	{
X	    if ((disp_info[i].win_width != the_event->width) ||
X	        (disp_info[i].win_height != the_event->height))
X	    {
X                XResizeWindow(disp_info[i].disp, disp_info[i].win_id, 
X			  the_event->width, the_event->height);
X	        disp_info[i].win_width = the_event->width;
X	        disp_info[i].win_height = the_event->height;
X
X                XSync(disp_info[i].disp, False);
X	    }
X	}
X    }
X
X    for (i=0; i<num_of_disps; i++)
X    {
X	if (disp_info[i].in_session_bool == TRUE)
X	{
X            XSync(disp_info[i].disp, False);
X	    /*
X	    XClearWindow(disp_info[i].disp, disp_info[i].win_id);
X	    */
X            XFlush(disp_info[i].disp);
X
X	    if (disp_info[i].cursor_on == TRUE)
X	    {    /*then turn it BACK on from the "clear window turnoff"*/
X                 XDrawLine(disp_info[i].disp, 
X		         disp_info[i].win_id,
X		         disp_info[i].cursor_gc, 
X		         disp_info[i].cur_pos.x, 
X		         disp_info[i].cur_pos.y, 
X		         disp_info[i].cur_pos.x + 
X		         disp_info[i].prompt_width, 
X		         disp_info[i].cur_pos.y);
X            }
X            XSync(disp_info[i].disp, False);   /*all the XSyncs are trying*/
X	} 				       /*to avoid a bad timing prob*/
X    }                                         
X
X    for (i=0; i<num_of_disps; i++)
X    {
X	if (disp_info[i].in_session_bool == TRUE)
X	{
X            XSync(disp_info[i].disp, False);
X            place_and_draw_status_win(i);
X	}
X    }
X    /*
X    NOTHING_DRAWN_YET = TRUE;
X     */
X}
X
X
X/*
X * handle_ButtonRelease_event - this function handles a ButtonRelease event in
X *                  this particular scrawler's window.  It is probably a
X *                  scrawler stopping drawing, but it could be a menu selection
X *                  or a "select area" finishing, so those are checked for 
X *                  also.
X */
Xhandle_ButtonRelease_event(our_event, disp_num, num_people_drawing)
XXEvent *our_event;
Xint disp_num, *num_people_drawing;
X{
X    XButtonPressedEvent *the_event;
X    int menu_num, item_selected, tot_num_items, i;
X    int start_x, start_y, last_x, last_y, temp, oldleft, oldtop;
X
X    the_event = (XButtonPressedEvent *) our_event;
X
X    if (disp_info[disp_num].scrawl_mode == RESPONDING_TO_DIALOG)
X	return(0);	/*not allowed to do anything else*/
X
X    if (the_event->button == Button1)
X    {
X	if (the_event->window == disp_info[disp_num].win_id)
X	{
X            disp_info[disp_num].pointer_state = NOT_PRESSED;
X	    if (disp_info[disp_num].scrawl_mode != TYPING)
X                (*num_people_drawing)--;    /*a dude has stopped drawing*/
X
X	    if (disp_info[disp_num].scrawl_mode == ERASING)
X	    {
X                XUnmapWindow(disp_info[disp_num].disp, 
X		       disp_info[disp_num].eraser_win_id);
X	    } 
X	    else if (disp_info[disp_num].scrawl_mode == RUBBER_POINTING)
X	    {
X		/*erase last pointer*/
X	        oldleft = disp_info[disp_num].last_point.x;
X	        oldtop = disp_info[disp_num].last_point.y -
X			      disp_info[disp_num].rubber_pointer.height;
X                disp_info[disp_num].rubber_pointer.is_mapped_bool = FALSE;
X                for (i=0; i<num_of_disps; i++)
X                {
X	            if (disp_info[i].in_session_bool)
X                    {
X		        XCopyArea(disp_info[i].disp, 
X		       disp_info[disp_num].rubber_pointer.rubber_pointer_pix[i],
X		           disp_info[i].win_id, disp_info[disp_num].win_gc[i],
X		           0, 0, disp_info[disp_num].rubber_pointer.width, 
X		           disp_info[disp_num].rubber_pointer.height, oldleft, 
X		           oldtop);
X                        XFlush(disp_info[i].disp);
X		    }
X		}
X	    }
X	    else if ((disp_info[disp_num].scrawl_mode == PLACING_A_BITMAP) ||
X	             (disp_info[disp_num].scrawl_mode == PLACING_AN_IMAGE) ||
X	             (disp_info[disp_num].scrawl_mode == PLACING_A_TEXTFILE))
X	    {
X		if (disp_info[disp_num].just_placed_something_bool == TRUE)
X		{
X		    disp_info[disp_num].just_placed_something_bool = FALSE;
X                    return(0);   /*throw this event away*/
X		}
X	    }
X	    else if (disp_info[disp_num].scrawl_mode == SELECTING_AN_AREA)
X	    {
X	        /*erase select rectangle*/
X	        start_x = disp_info[disp_num].select_start_pos.x;
X	        start_y = disp_info[disp_num].select_start_pos.y;
X	        last_x = disp_info[disp_num].cur_pos.x;
X	        last_y = disp_info[disp_num].cur_pos.y;
X        
X                if (start_x > last_x)  /*switch so lesser coordinate is first*/
X                {
X                    temp = start_x;
X	            start_x = last_x;
X	            last_x = temp;
X	        }
X	        if (start_y > last_y)  /*switch so lesser coordinate is first*/
X	        {
X                    temp = start_y;
X	            start_y = last_y;
X	            last_y = temp;
X	        }
X                XDrawRectangle(disp_info[disp_num].disp, 
X		       disp_info[disp_num].win_id,
X	               disp_info[disp_num].rubber_band_gc,
X		       start_x, start_y, last_x - start_x,  last_y - start_y);
X               
X		/*
X		 * shapes was really hacked in here. This is a kludge. 
X		 */
X		if (disp_info[disp_num].dialog_what == DRAW_SHAPE)
X		{
X	            start_x = disp_info[disp_num].select_start_pos.x;
X	            start_y = disp_info[disp_num].select_start_pos.y;
X	            last_x = disp_info[disp_num].cur_pos.x;
X	            last_y = disp_info[disp_num].cur_pos.y;
X		    draw_shape(disp_num, start_x, start_y, last_x, last_y);
X		    return(1);
X		}
X		
X		if (start_x > last_x)  /*switch so lesser coordinate is first*/
X		{
X                    temp = start_x;
X		    start_x = last_x;
X		    last_x = temp;
X		}
X		if (start_y > last_y)  /*switch so lesser coordinate is first*/
X		{
X                    temp = start_y;
X		    start_y = last_y;
X		    last_y = temp;
X		}
X		if (disp_info[disp_num].dialog_what == SAVE_BITMAP)
X		{
X		    disp_info[disp_num].dialog_text_prompt =
X						    "File To Save Bitmap To:";
X		}
X		else if (disp_info[disp_num].dialog_what == SAVE_IMAGE)
X		{
X		    disp_info[disp_num].dialog_text_prompt =
X						    "File To Save Image To:";
X		}
X		disp_info[disp_num].dialog_text_return[0] = '\0';
X		disp_info[disp_num].dialog_reply_index = 0;
X		put_up_dialog(disp_num);
X		disp_info[disp_num].scrawl_mode = RESPONDING_TO_DIALOG;
X	    }
X	    return(1);
X	} 
X	else if ((the_event->window == disp_info[disp_num].status_win_id) ||
X	         (the_event->window == disp_info[disp_num].eraser_win_id) ||
X	         (the_event->window == disp_info[disp_num].dialog_win_id))
X	{                                       /*it is in a boring window*/
X            return(1);    /*no action taken*/
X	}
X	else     /*it is in a menu*/
X	{
X	    menu_num = disp_info[disp_num].current_menu;
X	    item_selected = disp_info[disp_num].menu[menu_num].item_selected;
X            tot_num_items = disp_info[disp_num].menu[menu_num].num_items;
X
X	    if (disp_info[disp_num].scrawl_mode != TYPING)
X                (*num_people_drawing)--;  /*a dude has stopped input for now*/
X
X            if ((item_selected > 0) && (item_selected < tot_num_items))
X	    {
X                menu_selection(disp_num, menu_num, num_people_drawing, 
X			       item_selected);
X	    }
X
X            disp_info[disp_num].pointer_state = NOT_PRESSED;
X	    if (disp_info[disp_num].in_session_bool)
X	        draw_menu(disp_num);      /*draw the menus with this new info*/
X	}
X    }
X}
X
X
X/*
X * get_dimensions_of_text_file - this function finds and returns the 
X *              dimensions (in in screen pixels) of the text file that 
X *              is passed in as an argument.
X */
Xget_dimensions_of_text_file(disp_num, text_file_ptr, width, height)
Xint disp_num;
XFILE *text_file_ptr;
Xint *width, *height;
X{
X    int c, length, current_width, current_height, max_width_found;
X    char current_line[512];
X   
X    disp_info[disp_num].char_height =
X	       (disp_info[disp_num].the_font_struct)->max_bounds.ascent +
X               (disp_info[disp_num].the_font_struct)->max_bounds.descent;
X
X    for (max_width_found=0, current_height=0; (c=getc(text_file_ptr)) != EOF;)
X    {
X        ungetc(c, text_file_ptr);
X        fgets(current_line, 510, text_file_ptr);       /*get the line*/
X        for (length=0; current_line[length] != '\n'; length++)
X            ;
X
X	current_height += disp_info[disp_num].char_height;
X
X	if ((current_width = XTextWidth(disp_info[disp_num].the_font_struct,
X				   current_line, length)) > max_width_found)
X	{
X            max_width_found = current_width;
X	}
X    }
X
X    *width = max_width_found;
X    *height = current_height;
X}
X
X
X/*
X * draw_dialog_win_message - this function draws the contents of the 
X *                 dialog box in case of expose event, etc.
X */
Xdraw_dialog_win_message(disp_num)
X{
X    int i;
X    char the_char[10];
X
X    XDrawString(disp_info[disp_num].disp, disp_info[disp_num].dialog_win_id,
X		disp_info[disp_num].fg_menu_gc, 8, 14, 
X		disp_info[disp_num].dialog_text_prompt, 
X		strlen(disp_info[disp_num].dialog_text_prompt));
X    XDrawRectangle(disp_info[disp_num].disp,disp_info[disp_num].dialog_win_id,
X	        disp_info[disp_num].fg_menu_gc, 8, 20, DIALOG_WIN_WIDTH - 15,
X		DIALOG_WIN_HEIGHT - 24);
X
X    for (i=0; i<disp_info[disp_num].dialog_reply_index; i++)
X    { 
X	 the_char[0] = disp_info[disp_num].dialog_text_return[i];
X
X	 XDrawString(disp_info[disp_num].disp, 
X			disp_info[disp_num].dialog_win_id,
X			disp_info[disp_num].fg_menu_gc, 
X			14 + i*FIXED_CHAR_WIDTH, DIALOG_WIN_HEIGHT - 12,
X			the_char, 1);
X    } 
X    XFlush(disp_info[disp_num].disp);
X}
X
X
X/*
X * put_up_dialog - this function displays the dialog box with the text
X *                 passed in.  The text is usually something like:
X *                 "Enter the file name:".
X */
Xput_up_dialog(disp_num)
Xint disp_num;
X{
X    XMapWindow(disp_info[disp_num].disp, disp_info[disp_num].dialog_win_id);
X    XFlush(disp_info[disp_num].disp);
X 
X    draw_dialog_win_message(disp_num);
X}
X
X
X/*
X * do_dialog_action - this is called when a dialog is finally unmapped.  This
X *                    then takes the appropriate action.
X */
Xdo_dialog_action(disp_num)
Xint disp_num;
X{
X    int width, height, depth, xhr, yhr;
X    Pixmap the_pixmap;
X    int temp, start_x, start_y, last_x, last_y;
X    FILE *fp;
X    XImage *the_image;
X
X    switch(disp_info[disp_num].dialog_what)
X    { 
X	case SAVE_BITMAP:
X	    if (disp_info[disp_num].dialog_reply_index == 0)
X	        printf("Bitmap Save was canceled.\n");
X	    else
X	    {
X                start_x = disp_info[disp_num].select_start_pos.x;
X                start_y = disp_info[disp_num].select_start_pos.y;
X                last_x = disp_info[disp_num].cur_pos.x;
X                last_y = disp_info[disp_num].cur_pos.y;
X                if (start_x > last_x)  /*switch so lesser coordinate is first*/
X                {
X                    temp = start_x;
X	            start_x = last_x;
X	            last_x = temp;
X	        }
X	        if (start_y > last_y)  /*switch so lesser coordinate is first*/
X	        {
X                    temp = start_y;
X	            start_y = last_y;
X	            last_y = temp;
X	        }
X
X                set_paused_cursors();   /*this may take a while*/
X                save_bitmap_on_disk(disp_num, start_x, start_y, 
X		           last_x - start_x, last_y - start_y, 
X		           disp_info[disp_num].dialog_text_return);
X                unset_paused_cursors(); /*done*/
X	    }
X	    /*simulate choosing the "scrawl" menu selection*/
X	    menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X            break;
X	case READ_IN_BITMAP:
X	    if (disp_info[disp_num].dialog_reply_index == 0)
X	    {
X	        printf("Bitmap Read In was canceled.\n");
X	        /*simulate choosing the "scrawl" menu selection*/
X	        menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X                return(0);
X	    }
X            else if (XReadBitmapFile(disp_info[disp_num].disp, 
X		     disp_info[disp_num].win_id,
X	             disp_info[disp_num].dialog_text_return, 
X		     &width, &height, &the_pixmap, &xhr, &yhr)==BitmapSuccess)
X	    {
X		disp_info[disp_num].rubber_band_width = width;
X		disp_info[disp_num].rubber_band_height = height;
X		disp_info[disp_num].first_point_bool = TRUE;
X		disp_info[disp_num].scrawl_mode = PLACING_A_BITMAP;
X	    }
X	    else
X	    {
X	        printf("ERROR: Not a valid bitmap file.\n");
X	        /*simulate choosing the "scrawl" menu selection*/
X	        menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X	    }
X	    break;
X	case ADD_A_DISPLAY:
X	    if (disp_info[disp_num].dialog_reply_index == 0)
X	    {
X	        printf("Add Display was canceled.\n");
X	        menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X                return(0);
X	    }
X            else 
X	    {
X                add_a_new_display(disp_info[disp_num].dialog_text_return);
X		/*go back to whatever you were doing before*/
X	        menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X	    }
X	    break;
X	case READ_TEXTFILE:
X	    if (disp_info[disp_num].dialog_reply_index == 0)
X	    {
X	        printf("Read In Textfile was canceled.\n");
X	        menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X                return(0);
X	    }
X            else if ((fp = fopen(disp_info[disp_num].dialog_text_return,"r")) 
X		     != NULL)
X	    {
X                set_paused_cursors();   /*this may take a while*/
X		get_dimensions_of_text_file(disp_num, fp, &width, &height);
X		fclose(fp);
X                unset_paused_cursors(); /*done*/
X		disp_info[disp_num].rubber_band_width = width;
X		disp_info[disp_num].rubber_band_height = height;
X		disp_info[disp_num].first_point_bool = TRUE;
X		disp_info[disp_num].scrawl_mode = PLACING_A_TEXTFILE;
X		XDefineCursor(disp_info[disp_num].disp,
X		             disp_info[disp_num].win_id,
X		             XCreateFontCursor(disp_info[disp_num].disp, 
X					       XC_xterm));
X	    }
X	    else
X	    {
X	        printf("ERROR: Not a valid text file.\n");
X	        /*simulate choosing the "scrawl" menu selection*/
X	        menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X	    }
X	    break;
X	case SAVE_IMAGE:
X	    if (disp_info[disp_num].dialog_reply_index == 0)
X	        printf("Image Save was canceled.\n");
X	    else
X	    {
X                start_x = disp_info[disp_num].select_start_pos.x;
X                start_y = disp_info[disp_num].select_start_pos.y;
X                last_x = disp_info[disp_num].cur_pos.x;
X                last_y = disp_info[disp_num].cur_pos.y;
X                if (start_x > last_x)  /*switch so lesser coordinate is first*/
X                {
X                    temp = start_x;
X	            start_x = last_x;
X	            last_x = temp;
X	        }
X	        if (start_y > last_y)  /*switch so lesser coordinate is first*/
X	        {
X                    temp = start_y;
X	            start_y = last_y;
X	            last_y = temp;
X	        }
X                set_paused_cursors();   /*this may take a while*/
X                save_image_on_disk(disp_info[disp_num].disp, 
X			   disp_info[disp_num].win_id, start_x, start_y, 
X		           last_x - start_x, last_y - start_y, 
X		           disp_info[disp_num].dialog_text_return);
X                unset_paused_cursors();   /*done*/
X	    }
X	    /*simulate choosing the "scrawl" menu selection*/
X	    menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X            break;
X	case READ_IN_IMAGE:
X	    if (disp_info[disp_num].dialog_reply_index == 0)
X	    {
X	        printf("Image Read In was canceled.\n");
X	        /*simulate choosing the "scrawl" menu selection*/
X	        menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X                return(0);
X	    }
X            else 
X	    {
X		set_paused_cursors();     /*this may take a while*/
X                if ((fp = fopen(disp_info[disp_num].dialog_text_return,"r")) 
X		        != NULL)
X		{
X		    fclose(fp);
X		    depth = -1;   /*to see if it actually worked at all*/
X		    the_image = read_image_from_disk(disp_info[disp_num].disp,
X			       disp_info[disp_num].win_id,
X			       disp_info[disp_num].dialog_text_return, &width,
X		     	       &height, &depth);
X
X		    unset_paused_cursors();   /*done*/
X		    if ((depth == -1) || (the_image == NULL))  /*it failed*/
X		    {
X	                printf("ERROR: Something went wrong with the ");
X			printf("Read Image.\n");
X	                /*simulate choosing the "scrawl" menu selection*/
X	                menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X		        return(0);
X		    }
X		    else
X		    {
X		        XDestroyImage(the_image);
X		        disp_info[disp_num].rubber_band_width = width;
X		        disp_info[disp_num].rubber_band_height = height;
X		        disp_info[disp_num].first_point_bool = TRUE;
X		        disp_info[disp_num].scrawl_mode = PLACING_AN_IMAGE;
X		    }
X		}
X		else
X		{
X	            printf("ERROR: Not a valid file.\n");
X	            /*simulate choosing the "scrawl" menu selection*/
X	            menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X		    unset_paused_cursors();   /*done*/
X		    return(0);
X		}
X	    }
X	    break;
X	default:
X	    printf("ERROR: unknown action in do_dialog_action().\n");
X	    break;
X    } 
X}
X
X
X/*
X * draw_shape - this function draws the current shape on all displays with
X *              dimensions indicated
X */
Xdraw_shape(disp_num, start_x, start_y, last_x, last_y)
Xint disp_num, start_x, start_y, last_x, last_y;
X{
X    int i, temp, width, height;
X
X    if (disp_info[disp_num].current_shape != STRAIGHT_LINE)
X    {
X        if (start_x > last_x)  /*switch so lesser coordinate is first*/
X        {
X            temp = start_x;
X	    start_x = last_x;
X	    last_x = temp;
X	}
X	if (start_y > last_y)  /*switch so lesser coordinate is first*/
X	{
X            temp = start_y;
X	    start_y = last_y;
X	    last_y = temp;
X	}
X    }
X
X    width = last_x - start_x;
X    height = last_y - start_y;
X
X    switch(disp_info[disp_num].current_shape)
X    {
X	case STRAIGHT_LINE:
X	    for (i=0; i < num_of_disps; i++)
X                if (disp_info[i].in_session_bool)
X                    XDrawLine(disp_info[i].disp, disp_info[i].win_id,
X		          disp_info[disp_num].win_gc[i], start_x, start_y, 
X			  last_x, last_y);
X	    break;
X	case OUTLINE_RECT:
X	    for (i=0; i < num_of_disps; i++)
X                if (disp_info[i].in_session_bool)
X                    XDrawRectangle(disp_info[i].disp, disp_info[i].win_id,
X		          disp_info[disp_num].win_gc[i], start_x, start_y, 
X			  width, height);
X	    break;
X	case FILLED_RECT:
X	    for (i=0; i < num_of_disps; i++)
X                if (disp_info[i].in_session_bool)
X                    XFillRectangle(disp_info[i].disp, disp_info[i].win_id,
X		          disp_info[disp_num].win_gc[i], start_x, start_y, 
X			  width, height);
X	    break;
X	case OUTLINE_OVAL:
X	    for (i=0; i < num_of_disps; i++)
X                if (disp_info[i].in_session_bool)
X                    XDrawArc(disp_info[i].disp, disp_info[i].win_id,
X		          disp_info[disp_num].win_gc[i], start_x, start_y, 
X			  width, height, 0, 23040);
X	    break;
X	case FILLED_OVAL:
X	    for (i=0; i < num_of_disps; i++)
X                if (disp_info[i].in_session_bool)
X                    XFillArc(disp_info[i].disp, disp_info[i].win_id,
X		          disp_info[disp_num].win_gc[i], start_x, start_y, 
X			  width, height, 0, 23040);
X	    break;
X	default:
X	    printf("ERROR: in draw_shape routine.\n");
X	    break;
X    }
X}
X
X
X/*
X * read_in_and_place_bitmap - this function reads the bitmap named in the 
X *                  second parameter and puts it at the indicated spot on
X *                  all the displays.  It does this in a hokey way, reading
X *                  it from the file for every display.  It is a bit slow,
X *                  but is short and easy for me.
X */
Xread_in_and_place_bitmap(disp_num, bitmap_filename, x, y)
Xint disp_num;
Xchar *bitmap_filename;
Xint x, y;
X{
X    int width, height, xhr, yhr, i;
X
X    Pixmap the_pixmap;
X
X    set_paused_cursors();                     /*this may take a while*/
X
X    for (i=0; i<num_of_disps; i++)
X    {
X        if (disp_info[i].in_session_bool)
X        {
X            if (XReadBitmapFile(disp_info[i].disp, disp_info[i].win_id,
X	       bitmap_filename, &width, &height, &the_pixmap, &xhr, &yhr) ==
X	       BitmapSuccess)        
X            {                           /*we got it! run with it!*/
X                XCopyPlane(disp_info[i].disp, the_pixmap, disp_info[i].win_id, 
X		  disp_info[disp_num].win_gc[i], 0, 0, width, height, x, y, 1);
X                XFlush(disp_info[i].disp);
X	    }
X            else
X	    {
X	        printf("ERROR: Not a valid bitmap file.\n");
X	        break;
X	    }
X        }
X    }
X
X    unset_paused_cursors();                     /*this may take a while*/
X    /*simulate choosing the "scrawl" menu selection*/
X    menu_selection(disp_num, 0, &num_people_drawing, 
X			       disp_info[disp_num].previous_scrawl_mode);
X}
X
X
X/*
X * save_bitmap_on_disk - this routine saves the region selected as a bitmap
X *                   on the disk.  The background is saved as a 0, and any
X *                   and all foreground colors (anything different from the
X *                   background) is stored as a 1.
X */
Xsave_bitmap_on_disk(disp_num, x, y, width, height, bitmap_name)
Xint disp_num, x, y, width, height;
Xchar *bitmap_name;
X{
X    XImage *the_image;
X    int x_cord, y_cord, cur_left_byte, cur_right_byte;
X    int num_on_this_line, done, i;
X    FILE *bitmap_file;
X
X    /*
X     * the width must be an even multiple of 8 for a standard bitmap file
X     */
X    width = ((width/8) + 1) * 8;
X
X    if ((the_image = XGetImage(disp_info[disp_num].disp, 
X		          disp_info[disp_num].win_id, x, y, width, height,
X			  (~0), ZPixmap)) == NULL)
X    {
X         printf("ERROR: XGetImage failed.\n");
X	 return(0);
X    }
X    else if ((bitmap_file = fopen(bitmap_name, "w")) == NULL) 
X    {
X         /*fopen failed*/
X	 XDestroyImage(the_image);
X         printf("ERROR: attempt to save bitmap to a file failed.\n");
X	 return(0);
X    }
X
X    fprintf(bitmap_file, "#define %s_width %d\n", bitmap_name, width);
X    fprintf(bitmap_file, "#define %s_height %d\n", bitmap_name, height);
X    fprintf(bitmap_file, "static char %s_bits[] = {\n", bitmap_name);
X    fprintf(bitmap_file, "   ");
X
X    /*
X     * the following blows the data out to the file on disk
X     */
X    num_on_this_line = 0;
X    for (y_cord=0, done=FALSE; done==FALSE; y_cord++)
X    {
X        for (x_cord=0; x_cord < width; x_cord+=8)
X        {
X	    cur_right_byte = 0;
X	    cur_left_byte = 0;
X    
X	    for (i=0; i<4; i++)
X	    {
X                if (XGetPixel(the_image, x_cord+i, y_cord) != 
X	            disp_info[disp_num].background)
X	        { 
X	            cur_right_byte |= 1<<i;
X	        }
X            }
X	    for (i=0; i<4; i++)
X	    {
X                if (XGetPixel(the_image, x_cord+i+4, y_cord) != 
X	            disp_info[disp_num].background)
X	        { 
X	            cur_left_byte |= 1<<i;
X	        }
X            }
X            fprintf(bitmap_file, "0x%x%x", cur_left_byte, cur_right_byte);
X	    num_on_this_line++;
X    
X	    if ((y_cord == height-1) && (x_cord == (width-8)))
X	    {
X                fprintf(bitmap_file, "};\n");
X	        done = TRUE;
X	        break;
X	    }
X	    else if (num_on_this_line == 12)
X	    {
X                fprintf(bitmap_file, ",\n");
X                fprintf(bitmap_file, "   ");
X	        num_on_this_line = 0;
X	    }
X            else
X                fprintf(bitmap_file, ", ");
X        }
X    }
X    fclose(bitmap_file);
X    XDestroyImage(the_image);
X}
X
X
X/*
X * handle_SelectionNotify_event - this function handles a SelectionNotify event
X *                   in this particular scrawler's window.  It is probably a
X *                   "paste" of characters from the window manager.
X */
Xhandle_SelectionNotify_event(the_event, disp_num)
XXEvent *the_event;
Xint disp_num;
X{
X    XSelectionEvent *temp_event;
X    int i, alive;
X
X    temp_event = (XSelectionEvent *) the_event;
X    printf("Hey!  We just got a Selection Notify event!\n");
X}
X
X
X/*
X * handle_ClientMessage_event - this function handles a ClientMessage event in
X *                   this particular scrawler's window.  It is probably a
X *                   a "WM_DESTROY" from the window manager.
X */
Xhandle_ClientMessage_event(the_event, disp_num)
XXEvent *the_event;
Xint disp_num;
X{
X    XClientMessageEvent *temp_event;
X    int i, alive;
X
X    temp_event = (XClientMessageEvent *) the_event;
X    if (temp_event->data.l[0] == disp_info[disp_num].xa_WM_DELETE_WINDOW)
X    {
X        XDestroyWindow(disp_info[disp_num].disp, disp_info[disp_num].win_id);
X        disp_info[disp_num].in_session_bool = FALSE; /*no window*/
X        XCloseDisplay(disp_info[disp_num].disp);
X
X        for (i=alive=0; i< num_of_disps; i++)
X        {
X           if (disp_info[i].in_session_bool)
X	   {
X	       alive = TRUE;
X	       break;
X	   }
X	}
X	if (alive)
X	{
X            for (i=0; i<num_of_disps; i++)
X	        place_and_draw_status_win(i);
X	}
X	else
X	   exit(0);/*if no one is still in session, stop running*/
X    }
X    else
X        printf("ERROR: in handle_ClientMessage_event.\n");
X}
X
X
X/*
X * load_moron_fonts - this function loads fonts for real morons and owners
X *              of Sun workstations.  The thing is, both morons and
X *              owners of Sun workstations have systems that are so screwed
X *              up, they can't find R4 fonts when you try to allocate them 
X *              using the font name.  Therefore, this is a really, really ugly
X *              hack to allow their systems to find ONLY MY default fonts 
X *              using xlfd strings.  This will work with NO OTHER fonts.  
X *              This function returns TRUE if it allocated a font, and FALSE
X *              if not.  Hopefully this function will keep 90% of the Sun
X *              users happy, and thinking they got their moneys worth when
X *              buying Sun, when actually they made a drastic mistake.
X */
Xload_moron_fonts(disp_num, i, font_file_name)
Xint disp_num, i;
Xchar *font_file_name;
X{
X    char xlfd_string[512];
X    XFontStruct *the_font_struct;
X
X    if (strcmp(font_file_name, "fixed") == 0)
X	strcpy(xlfd_string, "fixed");
X    else if (strcmp(font_file_name, "variable") == 0)
X	strcpy(xlfd_string, "-*-helvetica-bold-r-normal-*-*-120-*-*-*-*-*-*");
X    else if (strcmp(font_file_name, "timR12") == 0)
X	strcpy(xlfd_string, 
X	       "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1");
X    else if (strcmp(font_file_name, "helvO12") == 0)
X	strcpy(xlfd_string, 
X	       "-adobe-helvetica-medium-o-normal--12-120-75-75-p-67-iso8859-1");
X    else if (strcmp(font_file_name, "courR12") == 0)
X	strcpy(xlfd_string, 
END_OF_FILE
if test 33168 -ne `wc -c <'wscrawl/xab'`; then
    echo shar: \"'wscrawl/xab'\" unpacked with wrong size!
fi
# end of 'wscrawl/xab'
fi
echo shar: End of archive 5 \(of 5\).
cp /dev/null ark5isdone
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