Path: utzoo!mnetor!tmsoft!torsqnt!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!samsung!munnari.oz.au!metro!sunaus.oz!newstop!sun!hpcvlx.cv.hp.com From: brianw@hpcvlx.cv.hp.com (Brian Wilson) Newsgroups: comp.sources.x Subject: v08i057: wscrawl, Part05/05 Message-ID: <138942@sun.Eng.Sun.COM> Date: 15 Jul 90 18:57:36 GMT Sender: news@sun.Eng.Sun.COM Lines: 1673 Approved: argv@sun.com Submitted-by: Brian Wilson 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 X#include X#include X#include 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; iwidth = (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) 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; idepth) /*cool, this is easy*/ X { X for (i=0; iformat, 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'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; iwindow == 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_numwindow == 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; iwidth == 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; iwidth) || 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; ibutton == 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 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 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; idata.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