brianw@hpcvlx.cv.hp.com (Brian Wilson) (07/16/90)
Submitted-by: Brian Wilson <brianw@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@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@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@sun.com / argv@ora.com Opinions expressed reflect those of the author only.