home *** CD-ROM | disk | FTP | other *** search
- Path: 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: v08i056: wscrawl, Part04/05
- Message-ID: <138941@sun.Eng.Sun.COM>
- Date: 15 Jul 90 18:57:31 GMT
- Sender: news@sun.Eng.Sun.COM
- Lines: 1047
- Approved: argv@sun.com
-
- Submitted-by: Brian Wilson <brianw@hpcvlx.cv.hp.com>
- Posting-number: Volume 8, Issue 56
- Archive-name: wscrawl/part04
-
- #! /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 4 (of 5)."
- # Contents: wscrawl/xaa
- # Wrapped by argv@turnpike on Sun Jul 15 11:47:12 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'wscrawl/xaa' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'wscrawl/xaa'\"
- else
- echo shar: Extracting \"'wscrawl/xaa'\" \(35046 characters\)
- sed "s/^X//" >'wscrawl/xaa' <<'END_OF_FILE'
- X/*
- X * WSCRAWL
- X *
- X * This file is: wscrawl.c
- X * ("image_f_io.c" and "pause_curs.h" are also part of this program)
- X *
- X * This is the source code to the program "wscrawl". The word "wscrawl"
- X * stands for "window-scrawl", reflecting the history of wscrawl. The user
- X * may think of wscrawl as a paint program shared by any number of people
- X * at the same time. When wscrawl is run, it opens a separate window on
- X * each participant's display. From that point, each participant may draw
- X * in his or her window. All participants see everything drawn by the other
- X * participants instantly.
- X *
- X * NOTES OF PORTABILITY: The routine "block_until_input()" uses a "select"
- X * system call. Some systems do not have this call. To patch for this
- X * problem, simply comment out all source inside that routine. The other
- X * potential problem is with the "rand" function. If the airbrush is not
- X * "scattering" properly, then take a look at the function "my_rand" and
- X * try to get it to return a random decimal between 0 and 1.
- X *
- X * Feel free to use/change/modify/erase/whatever this source code. Comments
- X * requests, hacked up versions of wscrawl should go to: brianw@cv.hp.com
- X *
- X * This program was written by Brian Wilson of Hewlett Packard Co.
- X * Email: brianw@cv.hp.com
- X *
- X * To compile: "cc -o wscrawl wscrawl.c image_f_io.c -lX11"
- X * To invoke: "wscrawl -d displayname1 -d displayname2 . . ."
- X * For a complete usage message, just do a: "wscrawl -help"
- X */
- X
- X#define INTERESTING_EVENTS ButtonPressMask | ButtonReleaseMask | KeyPressMask \
- X | StructureNotifyMask | ExposureMask
- X
- X#define WSCRAWL_WIN_WIDTH 760 /*initial window dimensions*/
- X#define WSCRAWL_WIN_HEIGHT 550
- X#define DIALOG_WIN_WIDTH 300
- X#define DIALOG_WIN_HEIGHT 50
- X
- X#define MAX_NUM_DISPS 10 /*general global variables*/
- X#define NUM_OF_MENUS 7
- X#define FIXED_CHAR_WIDTH 7
- X#define TRUE 1
- X#define FALSE 0
- X
- X#define STRAIGHT_LINE 0 /*types of shapes*/
- X#define OUTLINE_RECT 1
- X#define FILLED_RECT 2
- X#define OUTLINE_OVAL 3
- X#define FILLED_OVAL 4
- X
- X#define NOT_PRESSED 0 /*Pointer States*/
- X#define PRESSED 1
- X#define IN_MENU 2
- X#define BETWEEN_MENUS 3
- X
- X#define SCRAWLING 1 /*modes of drawing*/
- X#define AIRBRUSHING 2
- X#define TYPING 3
- X#define ERASING 4
- X#define SELECTING_AN_AREA 5
- X#define RUBBER_POINTING 6
- X#define PLACING_A_BITMAP 7
- X#define PLACING_A_TEXTFILE 8
- X#define RESPONDING_TO_DIALOG 9
- X#define PLACING_AN_IMAGE 10
- X
- X#define SAVE_BITMAP 1 /*things to do after answering dialog*/
- X#define READ_IN_BITMAP 2
- X#define ADD_A_DISPLAY 3
- X#define READ_TEXTFILE 4
- X#define SAVE_IMAGE 5
- X#define READ_IN_IMAGE 6
- X#define DRAW_SHAPE 7 /*this is a hack to allow me use of the
- X rubber select box*/
- X
- X#define MENU_ITEM_WIDTH 104 /*menu parameters*/
- X#define MENU_ITEM_HEIGHT 25
- X#define NO_ITEM_SELECTED -1
- X
- X#define MAX_RAND ((1<<15) - 1)
- X
- X#include <stdio.h> /*standard i/o functions*/
- X#include <stdlib.h> /*for the "getenv" command*/
- X#include <X11/Xos.h> /*"time.h" necessary for the "select" stuff */
- X#include <X11/Xlib.h> /*standard x defs*/
- X#include <X11/Xutil.h> /*necessary for the XWMhints stuff*/
- X#include <X11/cursorfont.h> /*we are gonna change the pointer*/
- X#include "pause_curs.h" /*our custom pause cursor*/
- X
- Xstatic char what[] = "@(#)WSCRAWL - Brian Wilson 7/14/90";
- X
- Xfloat my_rand(); /*hack, hack, cough, wheez, sputter, hack*/
- X
- XXSetWindowAttributes menuwinvals = /*struct for the menu windows*/
- X{
- X None, /*default background pixmap*/
- X 1, /*background pixel*/
- X CopyFromParent, /*border_pixmap*/
- X 0, 0,
- X NorthWestGravity, /*window gravity*/
- X NotUseful, /*backing store*/
- X 0, 0, 0,
- X INTERESTING_EVENTS, /*events we are interested in*/
- X 0,
- X True, /*override redirect flag*/
- X 0, 0
- X};
- X
- XXSetWindowAttributes winvals = /*struct for the window*/
- X{
- X None, /*default background pixmap*/
- X 1, /*background pixel*/
- X CopyFromParent, /*border_pixmap*/
- X 0, 0,
- X NorthWestGravity, /*window gravity*/
- X Always, /*backing store*/
- X 0, 0, 0,
- X INTERESTING_EVENTS, /*events we are interested in*/
- X 0,
- X False, /*override redirect flag*/
- X 0, 0
- X};
- X
- XXGCValues menugcvalues = /*menu graphics context values*/
- X{ /*so we need a gc values structure*/
- X GXxor, /*write rule*/
- X 0,0,0,0,0,0,
- X 0,0,0,0,0,0,0,0,0, /*bunch of placeholders*/
- X None, /*subwindow_mode*/
- X 0,0,0,0,0,0
- X};
- X
- XXGCValues gcvalues = /*We want to "include inferiors"*/
- X{ /*so we need a gc values structure*/
- X 0,0,
- X 0, /*foreground color*/
- X 0,
- X 8, /*width of the line*/
- X 0,
- X CapRound, /*CapRound looks good, but is VERY SLOW*/
- X 0,0,0,0,0,0,0,0,0, /*bunch of placeholders*/
- X None, /*subwindow_mode*/
- X 0,0,0,0,0,0
- X};
- X
- XXGCValues cursor_gc_values = /*We want the cursor to have XOR */
- X{ /*so we need a gc values structure*/
- X GXor,
- X 0,0,0,
- X 4, /*Line width*/
- X 0,0,0,0,0,0,0,0,0,0,0, /*bunch of placeholders*/
- X 0,0,0,0,0,0,0
- X};
- X
- X/*
- X * The following text definitions deserve some explanation. If you want a new
- X * color, or font, or pen_width, simply add the desired value to these lists.
- X * The routines automatically incorporate these new values and change menu
- X * lengths. If you want to add a brand new menu, then I recommend
- X * you add create a menu_text5 list, then link it appropriately in
- X * "initialize_displays()", change the "#define NUM_OF_MENUS 7" to 8,
- X * and add the new functionality to the "menu_selection()" routine. Good
- X * luck, as their are lots of little special cases to worry about, depending
- X * on your particular functionality. Remember to mail interesting versions
- X * to the above address. :-)
- X */
- Xstatic char *menu_text0[] = {"Control",
- X "Scrawl",
- X "Airbrush",
- X "Type",
- X "Eraser",
- X "Draw Shapes",
- X "Rubber Pointer",
- X "Clear Windows",
- X "--------------",
- X "Add Display",
- X "Close Window", "****"};
- Xstatic char *menu_text1[] = {"PenColor", "white", "magenta", "red", "blue",
- X "cyan", "LightSteelBlue", "navy blue", "green",
- X "coral", "light grey", "orange", "plum", "yellow",
- X "black", "****"};
- Xstatic char *menu_text2[] = {"PenWidth", "1", "2", "4", "8", "15", "25", "30",
- X "45", "60", "100", "150", "500", "****"};
- Xstatic char *menu_text3[] = {"PenCapStyle", "CapRound", "CapButt",
- X "CapNotLast", "CapProjecting", "****"};
- Xstatic char *menu_text4[] = {"Font", "fixed", "variable",
- X "timR12", "helvO12", "courR12", "courR14",
- X "timBI18", "courR24", "timR24", "timBI24",
- X "ncenR24", "vbee-36", "vr-40", "vgl-40",
- X "vsgn-57", "****"};
- Xstatic char *menu_text5[] = {"Shapes", "Straight Line", "Outline Rect",
- X "Filled Rect", "Outline Oval", "Filled Oval",
- X "****"};
- Xstatic char *menu_text6[] = {"File I/O", "Save Bitmap", "Read In Bitmap",
- X "Read Text File", "Save Image",
- X "Read In Image", "****"};
- Xchar **menu_text[NUM_OF_MENUS];
- X
- Xint num_of_disps = 1; /*start with your home display*/
- Xchar disp_args[MAX_NUM_DISPS][50]; /*No more than 50 letters in display name*/
- Xchar PEN_COLOR[42];
- Xchar BACKGROUND_COLOR[42];
- Xchar MENU_HIGHLIGHT_COLOR[42];
- Xchar MENU_FOREGROUND_COLOR[42];
- Xchar MENU_BACKGROUND_COLOR[42];
- Xchar PEN_STYLE[42];
- Xchar FONT[256];
- Xint NUM_DOTS;
- Xint PEN_WIDTH;
- Xint CAP_STYLE;
- Xint NOTHING_DRAWN_YET; /*I am so, so ashamed of this variable*/
- Xint TYPE_NOT_DRAW;
- X
- Xextern XImage *read_image_from_disk();
- X
- Xstruct char_node /*for the history of typing (for backspacing)*/
- X{
- X char the_char;
- X int x, y; /*where this letter was typed (only for <CR>)*/
- X struct char_node *next; /*pointer to the next character*/
- X};
- X
- Xstruct a_menu /*one of these for every menu*/
- X{
- X Window win_id; /*the window which IS the menu*/
- X int num_items; /*the number of items in this menu*/
- X int item_selected; /*the current item which is selected*/
- X int checked_item; /*the current item which is checked*/
- X};
- X
- Xstruct penwidthstruct /*keeps track of all the current penwidths*/
- X{
- X int scrawl; /*the scrawl penwidth*/
- X int airbrush; /*the airbrush penwidth*/
- X int eraser; /*the eraser penwidth*/
- X int shape; /*the shape penwidth*/
- X};
- X
- Xstruct rubberpointstruct /*this holds the rubberband cursor pixmap and dim*/
- X{
- X Pixmap rubber_pointer_pix[MAX_NUM_DISPS]; /*a rubber pointer for each disp*/
- X int width; /*the width of the pointer*/
- X int height; /*the height of the pointer*/
- X int is_mapped_bool; /*TRUE when this person's pointer is mapped*/
- X};
- X
- Xstruct disp_info_struct /*one of these exists for every "wscrawl" window*/
- X{
- X Display *disp; /*the display variable for this scrawl window*/
- X Window win_id; /*the window id of this scrawl window*/
- X Window status_win_id; /*the status window id for this scrawl window*/
- X Window eraser_win_id; /*the eraser window id for this scrawl window*/
- X Window dialog_win_id; /*the dialog window id for this scrawl window*/
- X GC *win_gc; /*one graphics context for every scrawl window*/
- X GC rubber_band_gc; /*the graphics context for rubber band boxes*/
- X GC fg_menu_gc; /*the graphics context for the menu foreground*/
- X GC hi_menu_gc; /*the graphics context for highlighting of menus*/
- X GC bg_menu_gc; /*the graphics context for unhighlighting of mens*/
- X int current_menu; /*the current menu that is pulled down(if one is)*/
- X struct a_menu menu[NUM_OF_MENUS]; /*each menu in a scrawl window*/
- X int in_session_bool; /*whether this win is still in the session or not*/
- X int connection_num; /*socket that this window is on*/
- X int pointer_state; /*choices include: NOT_PRESSED, PRESSED, IN_MENU*/
- X int scrawl_mode; /*choices include: SCRAWLING, AIRBRUSHING, TYPING*/
- X int previous_scrawl_mode;/*choices include: SCRAWLING, AIRBRUSHING, TYPING*/
- X int first_point_bool; /*boolean: is this first point drawn in this win?*/
- X int just_placed_something_bool; /*boolean: set if person placed bitmap,etc*/
- X int dialog_what; /*the thing we will do after user answers dialog*/
- X char *dialog_text_prompt;/*the prompt that goes in the dialog box*/
- X char dialog_text_return[256];/*text that the user has typed in dialog box*/
- X int dialog_reply_index; /*current location of the text in dialog_text_ret*/
- X int capstyle; /*pen width of this display*/
- X int pen_width; /*pen width of this display*/
- X char pen_color_str[42]; /*pen color that this display is scrawling with*/
- X char font_str[256]; /*font that this display is typing with*/
- X int current_shape; /*the current shape to be drawn (if one is)*/
- X struct penwidthstruct pen_widths; /*all the various penwidths*/
- X XFontStruct *the_font_struct;
- X struct char_node *type_history; /*history of all typed characters*/
- X GC cursor_gc; /*graphics context for the typing cursor*/
- X Cursor pause_cursor; /*the pause cursor for this display*/
- X struct rubberpointstruct rubber_pointer; /*the rubber pointer*/
- X int prompt_width; /*width of the typing cursor*/
- X int orig_x, char_height; /*x origin and height of current font*/
- X int cursor_on; /*boolean indication of whether cursor is shown*/
- X unsigned long background;/*planes mask of the background color*/
- X XPoint select_start_pos; /*x,y of first click position of select area*/
- X XPoint cur_pos; /*current position of the typing cursor*/
- X int rubber_band_width; /*width of rubber band box for placing bitmap*/
- X int rubber_band_height; /*height of rubber band box for placing bitmap*/
- X int win_width; /*current width of this window*/
- X int win_height; /*current height of this window*/
- X XPoint last_point; /*the last point drawn in this window*/
- X Atom xa_WM_DELETE_WINDOW;/*for communication with the window manager*/
- X Atom xa_WM_PROTOCOLS; /*for communication with the window manager*/
- X};
- X
- Xstruct disp_info_struct disp_info[MAX_NUM_DISPS];
- Xint num_people_drawing = 0;
- X
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i;
- X
- X parse_command_line(argv, argc);
- X initialize_displays(&num_people_drawing); /*open displays, windows, etc*/
- X
- X while (1)
- X {
- X block_until_input();
- X
- X do
- X {
- X for (i=0; i<num_of_disps; i++)
- X if (disp_info[i].in_session_bool)
- X {
- X XFlush(disp_info[i].disp);
- X process_event(i, &num_people_drawing);
- X if (disp_info[i].in_session_bool == FALSE)
- X break;
- X switch (disp_info[i].pointer_state)
- X {
- X case PRESSED:
- X switch(disp_info[i].scrawl_mode)
- X {
- X case SELECTING_AN_AREA:
- X update_select_area(i);
- X break;
- X case SCRAWLING:
- X case AIRBRUSHING:
- X case ERASING:
- X case RUBBER_POINTING:
- X draw_on_screens(i); /*draw on ALL displays*/
- X break;
- X default:
- X break;
- X }
- X break;
- X case IN_MENU:
- X update_menu_highlights(i);
- X break;
- X case NOT_PRESSED:
- X switch (disp_info[i].scrawl_mode)
- X {
- X case TYPING:
- X type_on_screens(i);/*type on ALL displays*/
- X break;
- X case PLACING_A_TEXTFILE:
- X case PLACING_A_BITMAP:
- X case PLACING_AN_IMAGE:
- X slide_rubberband_box(i,&num_people_drawing);
- X break;
- X case RESPONDING_TO_DIALOG:
- X type_on_dialog(i); /*type in dialog box*/
- X break;
- X default:
- X break;
- X }
- X break;
- X default:
- X break;
- X }
- X }
- X } while (num_people_drawing); /*while someone is still drawing*/
- X }
- X}
- X
- X
- X/*
- X * set_paused_cursors - this function sets all cursors on all displays to be
- X * "Pause" cursors. This function is called when some action is
- X * done that totally sucks all cycles for a minute or two, like
- X * reading an image in.
- X *
- X */
- Xset_paused_cursors()
- X{
- X int i, j;
- X
- X for (i=0; i<num_of_disps; i++)
- X {
- X if (disp_info[i].in_session_bool) /*if window is alive*/
- X {
- X XDefineCursor(disp_info[i].disp, disp_info[i].win_id,
- X disp_info[i].pause_cursor);
- X XDefineCursor(disp_info[i].disp, disp_info[i].status_win_id,
- X disp_info[i].pause_cursor);
- X XDefineCursor(disp_info[i].disp, disp_info[i].eraser_win_id,
- X disp_info[i].pause_cursor);
- X XDefineCursor(disp_info[i].disp, disp_info[i].dialog_win_id,
- X disp_info[i].pause_cursor);
- X for (j=0; j<NUM_OF_MENUS; j++)
- X XDefineCursor(disp_info[i].disp, disp_info[i].menu[j].win_id,
- X disp_info[i].pause_cursor);
- X XFlush(disp_info[i].disp);
- X }
- X }
- X}
- X
- X
- X/*
- X * unset_paused_cursors - this function sets all cursors on all displays to be
- X * the cursors they were before the "Pause" occured.
- X */
- Xunset_paused_cursors()
- X{
- X int i, j, the_cursor;
- X
- X for (i=0; i< num_of_disps; i++)
- X {
- X if (disp_info[i].in_session_bool) /*if window is alive*/
- X {
- X switch (disp_info[i].scrawl_mode)
- X {
- X case SCRAWLING:
- X the_cursor = XC_dot;
- X break;
- X case AIRBRUSHING:
- X the_cursor = XC_spraycan;
- X break;
- X case TYPING:
- X the_cursor = XC_xterm;
- X break;
- X case ERASING:
- X the_cursor = XC_draped_box;
- X break;
- X case RUBBER_POINTING:
- X the_cursor = XC_target;
- X break;
- X case SELECTING_AN_AREA:
- X the_cursor = XC_crosshair;
- X break;
- X case PLACING_A_BITMAP:
- X case PLACING_A_TEXTFILE:
- X case RESPONDING_TO_DIALOG:
- X case PLACING_AN_IMAGE:
- X the_cursor = XC_cross;
- X break;
- X default:
- X break;
- X }
- X
- X XDefineCursor(disp_info[i].disp, disp_info[i].win_id,
- X XCreateFontCursor(disp_info[i].disp, the_cursor));
- X XDefineCursor(disp_info[i].disp, disp_info[i].status_win_id,
- X XCreateFontCursor(disp_info[i].disp, XC_star));
- X XDefineCursor(disp_info[i].disp, disp_info[i].dialog_win_id,
- X XCreateFontCursor(disp_info[i].disp, XC_xterm));
- X XDefineCursor(disp_info[i].disp, disp_info[i].eraser_win_id,
- X XCreateFontCursor(disp_info[i].disp, XC_draped_box));
- X for (j=0; j<NUM_OF_MENUS; j++)
- X XDefineCursor(disp_info[i].disp, disp_info[i].menu[j].win_id,
- X XCreateFontCursor(disp_info[i].disp, XC_right_ptr));
- X XFlush(disp_info[i].disp);
- X }
- X }
- X}
- X
- X
- X/*
- X * place_a_textfile - this function places a text file onto the wscrawl
- X * windows in the current font and color, at the location
- X * this individual has just clicked.
- X */
- Xplace_a_textfile(disp_num, the_event)
- Xint disp_num;
- XXButtonPressedEvent *the_event;
- X{
- X int i, c, length, top, left, width, height;
- X FILE *text_file_ptr;
- X char current_line[512];
- X
- X (num_people_drawing)--; /*done drawing now*/
- X
- X /*
- X * erase rubber band box
- X */
- X top = disp_info[disp_num].cur_pos.y -
- X disp_info[disp_num].rubber_band_height/2;
- X left = disp_info[disp_num].cur_pos.x -
- X disp_info[disp_num].rubber_band_width/2;
- X width = disp_info[disp_num].rubber_band_width;
- X height = disp_info[disp_num].rubber_band_height;
- X XDrawRectangle(disp_info[disp_num].disp,
- X disp_info[disp_num].win_id,
- X disp_info[disp_num].rubber_band_gc,
- X left, top, width, height);
- X /*
- X * place the text file at the current pointer location
- X */
- X if ((text_file_ptr = fopen(disp_info[disp_num].dialog_text_return,"r")) ==
- X NULL)
- X {
- X printf("ERROR: Could not open text file %s.\n",
- X disp_info[disp_num].dialog_text_return);
- X }
- X else
- X {
- X set_paused_cursors(); /*this may take a while*/
- X
- X disp_info[disp_num].orig_x = left;
- 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 while ((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 /*draw this line to all the displays*/
- X for (i=0; i< num_of_disps; i++)
- X {
- X if (disp_info[i].in_session_bool) /*if window is alive*/
- X {
- X XDrawString(disp_info[i].disp, disp_info[i].win_id,
- X disp_info[disp_num].win_gc[i],
- X left, top, current_line, length);
- X }
- X }
- X left = disp_info[disp_num].orig_x;
- X top += disp_info[disp_num].char_height;
- X
- X }
- X fclose(text_file_ptr);
- X for (i=0; i< num_of_disps; i++)
- X if (disp_info[i].in_session_bool) /*if window is alive*/
- X XFlush(disp_info[i].disp);
- X
- X unset_paused_cursors(); /*done with long action*/
- X /*go back to appropriate drawing tool*/
- X menu_selection(disp_num, 0, &num_people_drawing,
- X disp_info[disp_num].previous_scrawl_mode);
- X }
- X}
- X
- X
- X/*
- X * place_an_image - this routine places an image at the current location
- X */
- Xplace_an_image(disp_num, the_event)
- Xint disp_num;
- XXButtonPressedEvent *the_event;
- X{
- X int i, top, left, width, height, depth;
- X XImage *the_image;
- X char *mesg;
- X
- X (num_people_drawing)--; /*done drawing now*/
- X /*
- X * erase rubber band box
- X */
- X top = disp_info[disp_num].cur_pos.y -
- X disp_info[disp_num].rubber_band_height/2;
- X left = disp_info[disp_num].cur_pos.x -
- X disp_info[disp_num].rubber_band_width/2;
- X width = disp_info[disp_num].rubber_band_width;
- X height = disp_info[disp_num].rubber_band_height;
- X XDrawRectangle(disp_info[disp_num].disp,
- X disp_info[disp_num].win_id,
- X disp_info[disp_num].rubber_band_gc,
- X left, top, width, height);
- X
- X set_paused_cursors(); /*this will 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 ((the_image = read_image_from_disk(disp_info[i].disp,
- X disp_info[i].win_id,
- X disp_info[disp_num].dialog_text_return, &width,
- X &height, &depth)) == NULL)
- X {
- X printf("WARNING: image not displayed on display %s.\n",
- X disp_args[i]);
- X XClearArea(disp_info[i].disp, disp_info[i].win_id,
- X left, top, width, height, False);
- X
- X XSetLineAttributes(disp_info[i].disp,
- X disp_info[i].rubber_band_gc, 3, LineSolid,
- X CapButt, JoinBevel);
- X if ((width > 4) && (height > 4))
- X {
- X XDrawRectangle(disp_info[i].disp,
- X disp_info[i].win_id,
- X disp_info[i].rubber_band_gc,
- X left + 2, top + 2, width - 4, height - 4);
- X }
- X XSetLineAttributes(disp_info[i].disp,
- X disp_info[i].rubber_band_gc, 0, LineSolid,
- X CapButt, JoinBevel);
- X
- X mesg = "You are missing an image here.";
- X XDrawString(disp_info[i].disp, disp_info[i].win_id,
- X disp_info[i].fg_menu_gc,
- X (left + (width/2) - 88), (top + (height/2) + 5),
- X mesg, strlen(mesg));
- X }
- X else if (DefaultDepth(disp_info[i].disp,
- X DefaultScreen(disp_info[i].disp)) != depth)
- X {
- X printf("WARNING: image not displayed on display %s. ",
- X disp_args[i]);
- X printf("(Inconsistent depths.)\n");
- X XDestroyImage(the_image); /*free the image memory*/
- X }
- X else
- X {
- X XPutImage(disp_info[i].disp, disp_info[i].win_id,
- X disp_info[disp_num].win_gc[i], the_image,
- X 0, 0, left, top, width, height);
- X XFlush(disp_info[i].disp);
- X XDestroyImage(the_image);
- X }
- X }
- X }
- X unset_paused_cursors(); /*done*/
- X
- X /*go back to appropriate drawing tool*/
- X menu_selection(disp_num, 0, &num_people_drawing,
- X disp_info[disp_num].previous_scrawl_mode);
- X}
- X
- X
- X/*
- X * place_a_bitmap - this routine places a bitmap at the current location
- X */
- Xplace_a_bitmap(disp_num, the_event)
- Xint disp_num;
- XXButtonPressedEvent *the_event;
- X{
- X int top, left, width, height;
- X
- X (num_people_drawing)--; /*stop this dude's talley*/
- X
- X /*
- X * erase rubber band box
- X */
- X top = disp_info[disp_num].cur_pos.y -
- X disp_info[disp_num].rubber_band_height/2;
- X left = disp_info[disp_num].cur_pos.x -
- X disp_info[disp_num].rubber_band_width/2;
- X width = disp_info[disp_num].rubber_band_width;
- X height = disp_info[disp_num].rubber_band_height;
- X XDrawRectangle(disp_info[disp_num].disp,
- X disp_info[disp_num].win_id,
- X disp_info[disp_num].rubber_band_gc,
- X left, top, width, height);
- X read_in_and_place_bitmap(disp_num,
- X disp_info[disp_num].dialog_text_return,
- X the_event->x - width/2, the_event->y - height/2);
- X}
- X
- X
- X/*
- X * update_select_area - this function updates the rubber-band box that this
- X * user is selecting an area with. This function has no effect
- X * other than visual.
- X */
- Xupdate_select_area(disp_num)
- Xint disp_num;
- X{
- X Window rr, cr; /* <-- Some strange ass variables, dude.*/
- X unsigned int mskr;
- X int temp, rxr, ryr, win_x, win_y;
- X int start_x, start_y, last_x, last_y;
- X
- X if (disp_info[disp_num].first_point_bool)
- X {
- X XQueryPointer(disp_info[disp_num].disp,
- X disp_info[disp_num].win_id, &rr, &cr, &rxr,
- X &ryr, &win_x, &win_y,&mskr);
- X disp_info[disp_num].select_start_pos.x = win_x;
- X disp_info[disp_num].select_start_pos.y = win_y;
- X disp_info[disp_num].cur_pos.x = win_x;
- X disp_info[disp_num].cur_pos.y = win_y;
- X disp_info[disp_num].first_point_bool = FALSE;
- X }
- X
- X XQueryPointer(disp_info[disp_num].disp,
- X disp_info[disp_num].win_id, &rr, &cr, &rxr,
- X &ryr, &win_x, &win_y,&mskr);
- X /*
- X * if the user has changed the x and y position of the pointer, change
- X * the rubberband box.
- X */
- X if ((win_x != disp_info[disp_num].cur_pos.x) ||
- X (win_y != disp_info[disp_num].cur_pos.y))
- 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
- 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 /*erase old one*/
- X XDrawRectangle(disp_info[disp_num].disp, 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 disp_info[disp_num].cur_pos.x = win_x;
- X disp_info[disp_num].cur_pos.y = win_y;
- 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
- X /* draw the new one */
- X XDrawRectangle(disp_info[disp_num].disp, 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 XFlush(disp_info[disp_num].disp);
- X }
- X}
- X
- X
- X/*
- X * update_menu_highlights - this function highlights the proper menu selection.
- X * It does not have any affect except visual upon any operations.
- X * However, it could entail switching between menus on the menu
- X * bar if the user has moved the mouse too far off the menu.
- X * It also is responsible for updating the "item_selected" field
- X * of the disp_info structure.
- X */
- Xupdate_menu_highlights(disp_num)
- X{
- X int new_item_num, num_items, menu_num;
- X Window rr, cr;
- X unsigned int mskr;
- X int rxr, ryr, win_x, win_y, oldy, old_item_selected;
- X
- X
- X menu_num = disp_info[disp_num].current_menu;
- X old_item_selected = disp_info[disp_num].menu[menu_num].item_selected;
- X num_items = disp_info[disp_num].menu[menu_num].num_items;
- X XQueryPointer(disp_info[disp_num].disp,
- X disp_info[disp_num].menu[menu_num].win_id,
- X &rr, &cr, &rxr, &ryr, &win_x, &win_y,&mskr);
- X
- X /*first figure out what item the pointer is pointing at*/
- X for (new_item_num=0; new_item_num < num_items; new_item_num++)
- X {
- X if (win_y < (new_item_num * MENU_ITEM_HEIGHT)+ MENU_ITEM_HEIGHT)
- X break;
- X }
- X
- X /*only draw highlight if not the menu title, and not already selected*/
- X if ((new_item_num != 0) && (new_item_num != old_item_selected))
- X {
- X disp_info[disp_num].menu[menu_num].item_selected = new_item_num;
- X /*erase old highlight*/
- X oldy = (old_item_selected * MENU_ITEM_HEIGHT) + 4;
- X XDrawRectangle(disp_info[disp_num].disp,
- X disp_info[disp_num].menu[menu_num].win_id,
- X disp_info[disp_num].bg_menu_gc, 2, oldy,
- X MENU_ITEM_WIDTH - 4, MENU_ITEM_HEIGHT - 6);
- X
- X /*draw new highlight*/
- X XDrawRectangle(disp_info[disp_num].disp,
- X disp_info[disp_num].menu[menu_num].win_id,
- X disp_info[disp_num].hi_menu_gc, 2,
- X 4 + (MENU_ITEM_HEIGHT * new_item_num),
- X MENU_ITEM_WIDTH - 4, MENU_ITEM_HEIGHT - 6);
- X }
- X else if ((new_item_num == 0) && (new_item_num != old_item_selected))
- X {
- X disp_info[disp_num].menu[menu_num].item_selected = new_item_num;
- X /*erase old highlight*/
- X oldy = (old_item_selected * MENU_ITEM_HEIGHT) + 4;
- X XDrawRectangle(disp_info[disp_num].disp,
- X disp_info[disp_num].menu[menu_num].win_id,
- X disp_info[disp_num].bg_menu_gc, 2, oldy,
- X MENU_ITEM_WIDTH - 4, MENU_ITEM_HEIGHT - 6);
- X }
- X else if ((new_item_num == 0) && (new_item_num == old_item_selected))
- X {
- X /*
- X * The following code decides if it is necessary to release a menu,
- X * and if so, it releases the old menu and pulls down a new one.
- X */
- X if ((win_x < 0) && (menu_num != 0)) /*move to the left one menu*/
- X {
- X disp_info[disp_num].pointer_state = BETWEEN_MENUS;
- X draw_menu(disp_num); /*retract the old menu*/
- X
- X disp_info[disp_num].current_menu = menu_num-1;
- X disp_info[disp_num].pointer_state = IN_MENU;
- X disp_info[disp_num].menu[menu_num].item_selected = 0;
- X draw_menu(disp_num); /*draw the menus with this new info*/
- X }
- X else if ((win_x>(MENU_ITEM_WIDTH+1)) && (menu_num!=(NUM_OF_MENUS-1)))
- X { /*move to the right one menu*/
- X disp_info[disp_num].pointer_state = BETWEEN_MENUS;
- X draw_menu(disp_num); /*retract the old menu*/
- X
- X disp_info[disp_num].current_menu = menu_num + 1;
- X disp_info[disp_num].pointer_state = IN_MENU;
- X disp_info[disp_num].menu[menu_num].item_selected = 0;
- X draw_menu(disp_num); /*draw the menus with this new info*/
- X }
- X }
- X}
- X
- X
- X/*
- X * block_until_input - this function blocks using a "select" until someone
- X * inputs on one of the windows involved with the "wscrawling"
- X * session. this function returns nothing. the rest of the
- X * program looks at the input queues to decide whether or not
- X * to scrawl and on which windows.
- X */
- Xblock_until_input()
- X{
- X int i, read_mask, top_con_num;
- X struct timeval timeout;
- X
- X timeout.tv_sec = 5;
- X timeout.tv_usec = 0;
- X
- X for (i = read_mask = top_con_num = 0; i<num_of_disps; i++)
- X {
- X if (disp_info[i].in_session_bool == TRUE)
- X {
- X if (XPending(disp_info[i].disp))
- X return(1); /*an event is pending on live display; don't block*/
- X
- X read_mask |= 1 << disp_info[i].connection_num;
- X if (disp_info[i].connection_num > top_con_num)
- X top_con_num = disp_info[i].connection_num;
- X }
- X }
- X
- X select(top_con_num+1, &read_mask, (int *) 0, (int *) 0, &timeout);
- X return(1); /*either an event has occured, or a timeout*/
- X}
- X
- X
- X/*
- X * process_event - this function takes an event off the event queue and
- X * calls the appropriate routine to handle this type of event.
- X */
- Xprocess_event(disp_num, num_people_drawing)
- Xint disp_num;
- Xint *num_people_drawing;
- X{
- X XEvent the_event;
- X
- X if (XPending(disp_info[disp_num].disp))
- X {
- X XNextEvent(disp_info[disp_num].disp, &the_event);
- X switch (the_event.type)
- X {
- X case ButtonPress:
- X handle_ButtonPress_event(&the_event, disp_num,
- X num_people_drawing);
- X break;
- X case ButtonRelease:
- X handle_ButtonRelease_event(&the_event, disp_num,
- X num_people_drawing);
- X break;
- X case KeyPress:
- X handle_KeyPress_event(&the_event, disp_num);
- X break;
- X case Expose:
- X handle_Expose_event(&the_event, disp_num);
- X break;
- X case ConfigureNotify:
- X handle_ConfigureNotify_event(&the_event, disp_num);
- X break;
- X case ClientMessage:
- X handle_ClientMessage_event(&the_event, disp_num);
- X break;
- X case SelectionNotify:
- X handle_SelectionNotify_event(&the_event, disp_num);
- X break;
- X default:
- X break;
- X }
- X }
- X}
- X
- X
- X/*
- X * handle_ButtonPress_event - this function handles a ButtonPress event in
- X * this particular scrawler's window. It is probably a
- X * scrawler starting to draw, but it could be a menu selection
- X * so that is checked for also.
- X */
- Xhandle_ButtonPress_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, i;
- 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 if (NOTHING_DRAWN_YET == TRUE) /*global variable*/
- X NOTHING_DRAWN_YET = FALSE;
- X
- X disp_info[disp_num].first_point_bool = TRUE;
- X
- X switch(disp_info[disp_num].scrawl_mode)
- X {
- X case PLACING_A_BITMAP:
- X place_a_bitmap(disp_num, the_event);
- X disp_info[disp_num].just_placed_something_bool = TRUE;
- X break;
- X case PLACING_AN_IMAGE:
- X place_an_image(disp_num, the_event);
- X disp_info[disp_num].just_placed_something_bool = TRUE;
- X break;
- X case PLACING_A_TEXTFILE:
- X place_a_textfile(disp_num, the_event);
- X disp_info[disp_num].just_placed_something_bool = TRUE;
- X break;
- X case TYPING:
- X disp_info[disp_num].pointer_state = NOT_PRESSED;
- X break;
- X default:
- X disp_info[disp_num].pointer_state = PRESSED;
- X break;
- X }
- X
- X if (disp_info[disp_num].scrawl_mode == ERASING)
- X {
- X if (disp_info[disp_num].pen_width - 4 > 0)
- X {
- X XMoveResizeWindow(disp_info[disp_num].disp,
- X disp_info[disp_num].eraser_win_id,
- X the_event->x - disp_info[disp_num].pen_width/2,
- X the_event->y - disp_info[disp_num].pen_width/2,
- X disp_info[disp_num].pen_width - 4,
- X disp_info[disp_num].pen_width - 4);
- X }
- X else
- X {
- X XMoveResizeWindow(disp_info[disp_num].disp,
- X disp_info[disp_num].eraser_win_id,
- X the_event->x - disp_info[disp_num].pen_width/2,
- X the_event->y - disp_info[disp_num].pen_width/2,
- X 1, 1);
- X }
- X XMapWindow(disp_info[disp_num].disp,
- X disp_info[disp_num].eraser_win_id);
- X }
- X
- X if (disp_info[disp_num].cursor_on == TRUE) /*erase the cursor*/
- X {
- X XDrawLine(disp_info[disp_num].disp,
- X disp_info[disp_num].win_id,
- X disp_info[disp_num].cursor_gc,
- X disp_info[disp_num].cur_pos.x,
- X disp_info[disp_num].cur_pos.y,
- X disp_info[disp_num].cur_pos.x +
- X disp_info[disp_num].prompt_width,
- X disp_info[disp_num].cur_pos.y);
- X }
- X
- X if (disp_info[disp_num].scrawl_mode != TYPING)
- END_OF_FILE
- if test 35046 -ne `wc -c <'wscrawl/xaa'`; then
- echo shar: \"'wscrawl/xaa'\" unpacked with wrong size!
- fi
- # end of 'wscrawl/xaa'
- fi
- echo shar: End of archive 4 \(of 5\).
- cp /dev/null ark4isdone
- 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.
-