brianw@hpcvlx.cv.hp.com (Brian Wilson) (07/16/90)
Submitted-by: Brian Wilson <brianw@hpcvlx.cv.hp.com> Posting-number: Volume 8, Issue 55 Archive-name: wscrawl/part03 #! /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 3 (of 5)." # Contents: wscrawl/xad # Wrapped by argv@turnpike on Sun Jul 15 11:47:11 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'wscrawl/xad' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'wscrawl/xad'\" else echo shar: Extracting \"'wscrawl/xad'\" \(35313 characters\) sed "s/^X//" >'wscrawl/xad' <<'END_OF_FILE' X disp_info[input_disp].prompt_width, X disp_info[input_disp].cur_pos.y); X X push_letter_to_history(input_disp, the_char[0]); X X disp_info[input_disp].cur_pos.x = disp_info[input_disp].orig_x; X disp_info[input_disp].cur_pos.y += X disp_info[input_disp].char_height; X X /*draw the cursor*/ X disp_info[input_disp].cursor_on = TRUE; X XDrawLine(disp_info[input_disp].disp, X disp_info[input_disp].win_id, X disp_info[input_disp].cursor_gc, X disp_info[input_disp].cur_pos.x, X disp_info[input_disp].cur_pos.y, X disp_info[input_disp].cur_pos.x + X disp_info[input_disp].prompt_width, X disp_info[input_disp].cur_pos.y); X } X else if ((the_char[0] == 8) || /*8 == Backspace*/ X (the_char[0] == 127)) /*127 == Del or Rubout*/ X { X /*erase the cursor*/ X disp_info[input_disp].cursor_on = FALSE; X XDrawLine(disp_info[input_disp].disp, X disp_info[input_disp].win_id, X disp_info[input_disp].cursor_gc, X disp_info[input_disp].cur_pos.x, X disp_info[input_disp].cur_pos.y, X disp_info[input_disp].cur_pos.x + X disp_info[input_disp].prompt_width, X disp_info[input_disp].cur_pos.y); X backspace_letter_from_history(input_disp); X X /*draw the cursor*/ X disp_info[input_disp].cursor_on = TRUE; X XDrawLine(disp_info[input_disp].disp, X disp_info[input_disp].win_id, X disp_info[input_disp].cursor_gc, X disp_info[input_disp].cur_pos.x, X disp_info[input_disp].cur_pos.y, X disp_info[input_disp].cur_pos.x + X disp_info[input_disp].prompt_width, X disp_info[input_disp].cur_pos.y); X } X else /*it is a valid letter*/ X { X push_letter_to_history(input_disp, the_char[0]); X X /*erase the cursor*/ X disp_info[input_disp].cursor_on = FALSE; X XDrawLine(disp_info[input_disp].disp, X disp_info[input_disp].win_id, X disp_info[input_disp].cursor_gc, X disp_info[input_disp].cur_pos.x, X disp_info[input_disp].cur_pos.y, X disp_info[input_disp].cur_pos.x + X disp_info[input_disp].prompt_width, X disp_info[input_disp].cur_pos.y); 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 XDrawString(disp_info[i].disp, disp_info[i].win_id, X disp_info[input_disp].win_gc[i], X disp_info[input_disp].cur_pos.x, X disp_info[input_disp].cur_pos.y, the_char, 1); X XFlush(disp_info[i].disp); X } X } X disp_info[input_disp].cur_pos.x += X XTextWidth(disp_info[input_disp].the_font_struct, X the_char, 1); X X /*draw the cursor*/ X disp_info[input_disp].cursor_on = TRUE; X XDrawLine(disp_info[input_disp].disp, X disp_info[input_disp].win_id, X disp_info[input_disp].cursor_gc, X disp_info[input_disp].cur_pos.x, X disp_info[input_disp].cur_pos.y, X disp_info[input_disp].cur_pos.x + X disp_info[input_disp].prompt_width, X disp_info[input_disp].cur_pos.y); X } X } X } X} X X X/* X * push_letter_to_history - this function takes a pointer to the top of X * the history stack and adds the character passed in to that X * stack. This is to save the characters for future backspacing. X */ Xpush_letter_to_history(input_disp, the_char) Xint input_disp; Xchar the_char; X{ X struct char_node *temp; X X temp = (struct char_node *) malloc(sizeof(struct char_node)); X temp->the_char = the_char; X temp->next = disp_info[input_disp].type_history; X X if (the_char == 13) /*carriage return*/ X { X temp->x = disp_info[input_disp].cur_pos.x; X temp->y = disp_info[input_disp].cur_pos.y; X } X X disp_info[input_disp].type_history = temp; X} X X X/* X * backspace_letter_from_history - this function returns the most recently X * typed character from the history stack, and sets the top of X * the stack pointer appropriately. X */ Xbackspace_letter_from_history(input_disp) Xint input_disp; X{ X int dr, far, fdr, i; X struct char_node *char_node; X XCharStruct the_fnt_strct; X X if (disp_info[input_disp].type_history == NULL) X return(0); X else X { X char_node = disp_info[input_disp].type_history; X X if (char_node->the_char == 13) /*it was a carriage return*/ X { X disp_info[input_disp].cur_pos.x = char_node->x; X disp_info[input_disp].cur_pos.y = char_node->y; X } X else /*it was a normal letter*/ X { X disp_info[input_disp].cur_pos.x -= XTextWidth( X disp_info[input_disp].the_font_struct,&(char_node->the_char), 1); X X XTextExtents(disp_info[input_disp].the_font_struct, X &(char_node->the_char), 1, &dr, &far, &fdr, &the_fnt_strct); X X for (i=0; i< num_of_disps; i++) X { X XClearArea(disp_info[i].disp, disp_info[i].win_id, X disp_info[input_disp].cur_pos.x, X disp_info[input_disp].cur_pos.y - the_fnt_strct.ascent, X the_fnt_strct.lbearing + the_fnt_strct.rbearing, X the_fnt_strct.ascent + the_fnt_strct.descent, False); X } X } X X /* now pop the top char node from the history stack */ X disp_info[input_disp].type_history = X disp_info[input_disp].type_history->next; X free(char_node); X } X} X X X/* X * draw_status_win_message - this function spits (in camel like fashion) out X * the status window message to the display indicated. X */ Xdraw_status_win_message(disp_num) X{ X int i, num_disps; X char mesg[510], *cur_loc_ptr; X X for (i=0, num_disps=0; i< num_of_disps; i++) X if (disp_info[i].in_session_bool) /*only if this window is alive*/ X num_disps++; X X if (num_disps == 1) X sprintf(mesg, "STATUS: 1 scrawl window currently open. --> "); X else X sprintf(mesg, "STATUS: %d scrawl windows currently open. --> ", X num_disps); X X cur_loc_ptr = mesg + strlen(mesg); X X for (i=0; i< num_of_disps; i++) X { X if (disp_info[i].in_session_bool) /*only if this window is alive*/ X { X strncpy(cur_loc_ptr, disp_args[i], 25); X cur_loc_ptr += strlen(disp_args[i]); X cur_loc_ptr[0] = ','; X cur_loc_ptr[1] = ' '; /*space delineates*/ X cur_loc_ptr += 2; X } X } X cur_loc_ptr -= 2; X cur_loc_ptr[0] = '\0'; /*end the string*/ X X XClearWindow(disp_info[disp_num].disp, disp_info[disp_num].status_win_id); X XDrawString(disp_info[disp_num].disp, disp_info[disp_num].status_win_id, X disp_info[disp_num].fg_menu_gc, 10, 14, mesg, strlen(mesg)); X XFlush(disp_info[disp_num].disp); X} X X X/* X * draw_rubber_pointer - this function draws the rubber cursor of the input X * disp on the target disp at the indicated location. The X * indicated location is the upper left corner of the cursor X * area, NOT the hotspot. This simulated cursor consists of X * the machine name that is drawing, and a small arrow pointing X * to the lower left corner. X */ Xdraw_rubber_pointer(input_disp, target_disp, x, y) Xint input_disp, target_disp; X{ X XDrawString(disp_info[target_disp].disp, disp_info[target_disp].win_id, X disp_info[target_disp].fg_menu_gc, X x + 15, y + disp_info[input_disp].rubber_pointer.height - 15, X disp_args[input_disp], strlen(disp_args[input_disp])); X X XDrawLine(disp_info[target_disp].disp, disp_info[target_disp].win_id, X disp_info[target_disp].fg_menu_gc, X x+2, y - 2 + disp_info[input_disp].rubber_pointer.height, X x+12, y - 12 + disp_info[input_disp].rubber_pointer.height); X XDrawLine(disp_info[target_disp].disp, disp_info[target_disp].win_id, X disp_info[target_disp].fg_menu_gc, X x+3, y - 2 + disp_info[input_disp].rubber_pointer.height, X x+3, y - 9 + disp_info[input_disp].rubber_pointer.height); X XDrawLine(disp_info[target_disp].disp, disp_info[target_disp].win_id, X disp_info[target_disp].fg_menu_gc, X x+3, y - 2 + disp_info[input_disp].rubber_pointer.height, X x+9, y - 2 + disp_info[input_disp].rubber_pointer.height); X} X X X/* X * place_and_draw_status_win - this function places the status window at the X * correct location on the scrawl window, and draws X * the contents. (Also updates the contents of all X * other scrawl windows, but DOES NOT change their X * locations.) X */ Xplace_and_draw_status_win(disp_num) Xint disp_num; X{ X XWindowAttributes window_attr; X X if (disp_info[disp_num].in_session_bool == FALSE) X return(0); /*This window is no longer active*/ X X XGetWindowAttributes(disp_info[disp_num].disp, X disp_info[disp_num].win_id, &window_attr); X XMoveResizeWindow(disp_info[disp_num].disp, X disp_info[disp_num].status_win_id, X 0, window_attr.height - 24, window_attr.width-4, 20); X X draw_status_win_message(disp_num); X} X X X/* X * draw_on_screens - this function draws the segment that is indicated X * by the current mouse position and previous mouse X * position on the display passed to it as an argument. X * This segment is drawn to ALL displays currently open. X * If this dude is airbrushing, then of course an airbrush X * pattern is sprayed all over, and if it is an eraser, X * then erasing happens. If it is a rubber pointer, rubber X * pointing happens. X */ Xdraw_on_screens(input_disp) Xint input_disp; X{ X Window rr, cr; X unsigned int mskr; X int i, j, left, top, oldleft, oldtop, rxr, ryr, win_x, win_y; X X if (disp_info[input_disp].scrawl_mode == SCRAWLING) X { X if (disp_info[input_disp].first_point_bool) X { X XQueryPointer(disp_info[input_disp].disp, X disp_info[input_disp].win_id, &rr, &cr, &rxr, X &ryr, &win_x, &win_y,&mskr); X disp_info[input_disp].last_point.x = win_x; X disp_info[input_disp].last_point.y = win_y; X disp_info[input_disp].first_point_bool = FALSE; X } X X XQueryPointer(disp_info[input_disp].disp, disp_info[input_disp].win_id, X &rr, &cr, &rxr, &ryr, &win_x, &win_y, &mskr); X for (i=0; i< num_of_disps; i++) X { X if (disp_info[i].in_session_bool) /*only if this window is alive*/ X { X XDrawLine(disp_info[i].disp,disp_info[i].win_id, X disp_info[input_disp].win_gc[i], X disp_info[input_disp].last_point.x, X disp_info[input_disp].last_point.y, win_x, win_y); X XFlush(disp_info[i].disp); X } X } X X disp_info[input_disp].last_point.x = win_x; X disp_info[input_disp].last_point.y = win_y; X } X else if (disp_info[input_disp].scrawl_mode == AIRBRUSHING) X { X XQueryPointer(disp_info[input_disp].disp, disp_info[input_disp].win_id, X &rr, &cr, &rxr, &ryr, &win_x, &win_y, &mskr); X for (i=0; i< num_of_disps; i++) X { X if (disp_info[i].in_session_bool) /*only if this window is alive*/ X { X airbrush(input_disp, disp_info[i].disp, disp_info[i].win_id, X disp_info[input_disp].win_gc[i], win_x, win_y); X XFlush(disp_info[i].disp); X } X } X } X else if (disp_info[input_disp].scrawl_mode == ERASING) X { X XQueryPointer(disp_info[input_disp].disp, disp_info[input_disp].win_id, X &rr, &cr, &rxr, &ryr, &win_x, &win_y, &mskr); X XMoveWindow(disp_info[input_disp].disp, X disp_info[input_disp].eraser_win_id, X win_x - disp_info[input_disp].pen_width/2, X win_y - disp_info[input_disp].pen_width/2); X X for (i=0; i< num_of_disps; i++) X { X if (disp_info[i].in_session_bool) /*only if this window is alive*/ X { X XClearArea(disp_info[i].disp, disp_info[i].win_id, X win_x - disp_info[input_disp].pen_width/2, X win_y - disp_info[input_disp].pen_width/2, X disp_info[input_disp].pen_width, X disp_info[input_disp].pen_width, False); X XFlush(disp_info[i].disp); X } X } X } X else if (disp_info[input_disp].scrawl_mode == RUBBER_POINTING) X { X if (disp_info[input_disp].first_point_bool) X { X XQueryPointer(disp_info[input_disp].disp, X disp_info[input_disp].win_id, &rr, &cr, &rxr, X &ryr, &win_x, &win_y,&mskr); X disp_info[input_disp].last_point.x = win_x; X disp_info[input_disp].last_point.y = win_y; X disp_info[input_disp].first_point_bool = FALSE; X /* X * turn off any other cursors that are on before getting the X * background pixmap. (So you we don't copy the cursors as X * part of the background.) X */ X for (i=0; i< num_of_disps; i++) X { X if (disp_info[i].in_session_bool) /*only if window is alive*/ X { X if (disp_info[i].rubber_pointer.is_mapped_bool == TRUE) X { X oldleft = disp_info[i].last_point.x; X oldtop = disp_info[i].last_point.y - X disp_info[i].rubber_pointer.height; X for (j=0; j< num_of_disps; j++) X if (disp_info[j].in_session_bool) X { X XCopyArea(disp_info[j].disp, X disp_info[i].rubber_pointer.rubber_pointer_pix[j], X disp_info[j].win_id, disp_info[i].win_gc[j], X 0, 0, disp_info[i].rubber_pointer.width, X disp_info[i].rubber_pointer.height, oldleft, X oldtop); X XFlush(disp_info[j].disp); X } X } X } X } X /* X * now get the background pixmap. X */ X left = win_x; X top = win_y - disp_info[input_disp].rubber_pointer.height; X for (i=0; i< num_of_disps; i++) X { X if (disp_info[i].in_session_bool) /*only if window is alive*/ X { X XCopyArea(disp_info[i].disp, X disp_info[i].win_id, X disp_info[input_disp].rubber_pointer.rubber_pointer_pix[i], X disp_info[input_disp].win_gc[i], X left, top, disp_info[input_disp].rubber_pointer.width, X disp_info[input_disp].rubber_pointer.height, 0, 0); X } X } X /* X * draw (map) all of the cursors that are supposed to be mapped X */ X disp_info[input_disp].rubber_pointer.is_mapped_bool = TRUE; X for (i=0; i< num_of_disps; i++) X if (disp_info[i].in_session_bool) /*only if window is alive*/ X { X if (disp_info[i].rubber_pointer.is_mapped_bool == TRUE) X { X left = disp_info[i].last_point.x; X top = disp_info[i].last_point.y - X disp_info[i].rubber_pointer.height; X for (j=0; j< num_of_disps; j++) X if (disp_info[j].in_session_bool) X draw_rubber_pointer(i, j, left, top); X } X } X } X X XQueryPointer(disp_info[input_disp].disp, disp_info[input_disp].win_id, X &rr, &cr, &rxr, &ryr, &win_x, &win_y, &mskr); X if ((win_x != disp_info[input_disp].last_point.x) || X (win_y != disp_info[input_disp].last_point.y)) X { X /* X * turn off any other cursors that are on before getting the X * background pixmap. (So we don't copy the cursors as X * part of the background.) X */ X for (i=0; i< num_of_disps; i++) X { X if (disp_info[i].in_session_bool) /*only if window is alive*/ X { X if (disp_info[i].rubber_pointer.is_mapped_bool == TRUE) X { X oldleft = disp_info[i].last_point.x; X oldtop = disp_info[i].last_point.y - X disp_info[i].rubber_pointer.height; X for (j=0; j< num_of_disps; j++) X if (disp_info[j].in_session_bool) X { X XCopyArea(disp_info[j].disp, X disp_info[i].rubber_pointer.rubber_pointer_pix[j], X disp_info[j].win_id, disp_info[i].win_gc[j], X 0, 0, disp_info[i].rubber_pointer.width, X disp_info[i].rubber_pointer.height, oldleft, X oldtop); X } X } X } X } X X /* X * save new cursor area for the input cursor X */ X left = win_x; X top = win_y - disp_info[input_disp].rubber_pointer.height; X for (i=0; i< num_of_disps; i++) X { X if (disp_info[i].in_session_bool) /*only if window is alive*/ X { X XCopyArea(disp_info[i].disp, X disp_info[i].win_id, X disp_info[input_disp].rubber_pointer.rubber_pointer_pix[i], X disp_info[input_disp].win_gc[i], X left, top, disp_info[input_disp].rubber_pointer.width, X disp_info[input_disp].rubber_pointer.height, 0, 0); X } X } X X disp_info[input_disp].last_point.x = win_x; X disp_info[input_disp].last_point.y = win_y; X /* X * now draw (map) all of the cursors that are currently unmapped X */ X for (i=0; i< num_of_disps; i++) X if (disp_info[i].in_session_bool) /*only if window is alive*/ X { X if (disp_info[i].rubber_pointer.is_mapped_bool == TRUE) X { X left = disp_info[i].last_point.x; X top = disp_info[i].last_point.y - X disp_info[i].rubber_pointer.height; X for (j=0; j< num_of_disps; j++) X if (disp_info[j].in_session_bool) X draw_rubber_pointer(i, j, left, top); X } X } X for (i=0; i< num_of_disps; i++) X if (disp_info[i].in_session_bool) /*only if window is alive*/ X XFlush(disp_info[i].disp); X } X } X} X X X/* X * parse_command_line - this function parses the command line and sets the X * various global variables for the opening display X * and color party coming up. Sorry that this routine is so X * ugly, but just go slow, and it's not too bad. I'd look at X * the "command_line_err()" routine to understand what each X * of the command line options mean. X * (ex. % wscrawl -d hpcvxbw:0 -d hpcvxca:0 -pc red -cs CapRound X * -pw 45 -bs off -nd 50 -ps airbrush) X */ Xparse_command_line(argv, argc) Xchar *argv[]; Xint argc; X{ X int i, current_arg, W_SET = 0; X X strncpy(PEN_COLOR, "magenta", 40); /*defaults set here*/ X strncpy(BACKGROUND_COLOR, "white", 40); X strncpy(MENU_FOREGROUND_COLOR, "black", 40); X strncpy(MENU_BACKGROUND_COLOR, "wheat", 40); X strncpy(MENU_HIGHLIGHT_COLOR, "black", 40); X strncpy(PEN_STYLE, "dot", 40); X strncpy(FONT, "vgl-40", 100); X strncpy(disp_args[0], "", 30); X TYPE_NOT_DRAW = FALSE; X CAP_STYLE = CapRound; X PEN_WIDTH = 8; X NUM_DOTS = 50; X for (i=0; i< num_of_disps; i++) X { X disp_info[i].pen_width = 8; X } X X for (current_arg = 1; current_arg < argc; current_arg+=2) X { X if (strcmp(argv[current_arg],"-d") == 0) X { X strncpy(disp_args[num_of_disps], argv[current_arg+1], 48); X num_of_disps++; X } X else if (strcmp(argv[current_arg],"-mfg") == 0) X { X if (current_arg != argc-1) X strncpy(MENU_FOREGROUND_COLOR, argv[current_arg+1], 40); X else X command_line_err(); /*no color was specified*/ X } X else if (strcmp(argv[current_arg],"-mbg") == 0) X { X if (current_arg != argc-1) X strncpy(MENU_BACKGROUND_COLOR, argv[current_arg+1], 40); X else X command_line_err(); /*no color was specified*/ X } X else if (strcmp(argv[current_arg],"-mhc") == 0) X { X if (current_arg != argc-1) X strncpy(MENU_HIGHLIGHT_COLOR, argv[current_arg+1], 40); X else X command_line_err(); /*no color was specified*/ X } X else if (strcmp(argv[current_arg],"-bg") == 0) X { X if (current_arg != argc-1) X strncpy(BACKGROUND_COLOR, argv[current_arg+1], 40); X else X command_line_err(); /*no color was specified*/ X } X else if (strcmp(argv[current_arg],"-pc") == 0) X { X if (current_arg != argc-1) X strncpy(PEN_COLOR, argv[current_arg+1], 40); X else X command_line_err(); /*no color was specified*/ X } X else if (strcmp(argv[current_arg],"-fn") == 0) X { X if (current_arg != argc-1) X strncpy(FONT, argv[current_arg+1], 220); X else X command_line_err(); /*no color was specified*/ X } X else if (strcmp(argv[current_arg],"-tm") == 0) X { X TYPE_NOT_DRAW = TRUE; X current_arg--; /*type message is an argumentless option*/ X } X else if (strcmp(argv[current_arg],"-nd") == 0) X { X if (current_arg != argc-1) X { X sscanf(argv[current_arg+1], "%d", &NUM_DOTS); X if ((NUM_DOTS < 1) || (NUM_DOTS > 500)) X command_line_err(); /*incorrect range*/ X } X else X command_line_err(); /*no number was specified*/ X } X else if (strcmp(argv[current_arg],"-ps") == 0) X { X if (current_arg != argc-1) X { X if ((strcmp(argv[current_arg+1],"dot") == 0) || X (strcmp(argv[current_arg+1],"airbrush")) == 0) X { X strncpy(PEN_STYLE, argv[current_arg+1], 40); X if ((strcmp(PEN_STYLE,"airbrush") == 0) && !W_SET) X disp_info[0].pen_width = 40; /*default penwidth*/ X } X else X command_line_err(); /*incorrect pen style specified*/ X } X else X command_line_err(); /*no pen style was specified*/ X } X else if (strcmp(argv[current_arg],"-pw") == 0) X { X if (current_arg != argc-1) X { X sscanf(argv[current_arg+1], "%d", &PEN_WIDTH); X W_SET = TRUE; /*the width has been set*/ X } X else X command_line_err(); /*no pen width was specified*/ X } X else if (strcmp(argv[current_arg],"-cs") == 0) X { X if (current_arg != argc-1) X { X if (strcmp(argv[current_arg+1],"CapButt") == 0) X CAP_STYLE = CapButt; X else if (strcmp(argv[current_arg+1],"CapNotLast") == 0) X CAP_STYLE = CapNotLast; X else if (strcmp(argv[current_arg+1],"CapRound") == 0) X CAP_STYLE = CapRound; X else if (strcmp(argv[current_arg+1],"CapProjecting") == 0) X CAP_STYLE = CapProjecting; X else X command_line_err(); /*bad cap style was specified*/ X } X else X command_line_err(); /*no cap style was specified*/ X } X else X { X command_line_err(); X } X } X} X X X/* X * command_line_err - this function spits out a standard error message and X * exits the program. X */ Xcommand_line_err() X{ X printf("\nBad command line option dude.\n"); X printf("Try: wscrawl\n"); X printf(" [-d displayname1 -d displayname2 . . .]\n"); X printf(" [-bg background_color]\n"); X printf(" [-mfg menu_foreground_color]\n"); X printf(" [-mbg menu_background_color]\n"); X printf(" [-mhc menu_highlight_color]\n"); X printf(" [-pc pen_color]\n"); X printf(" [-pw pen_width]\n"); X printf(" [-ps pen_style] (dot,airbrush)\n"); X printf(" [-cs cap_style] (CapButt,CapNotLast,CapRound,CapProjecting)\n"); X printf(" [-nd num_dots] (number of dots in the airbrush (1-500))\n"); X printf(" [-tm] (type a message, don't draw)\n"); X printf(" [-fn font] (name of font to use if typing a message)\n\n"); X exit(0); X} X X X/* X * add_a_new_display - this function opens a new display to the scrawl X * session. It calls the function that initializes X * all the windows, and it transfers the image. X */ Xadd_a_new_display(disp_name) Xchar *disp_name; X{ X int i, k, found_source, disp_num, source_disp_num, width, height; X XWindowAttributes new_win_attr, old_win_attr, root_win_attr; X int cur_depth, print_it, win_left, win_top, left, top, fully_printed; X char *mesg; X Window dummy; X X set_paused_cursors(); /*this is going to take a while*/ X X if (XOpenDisplay(disp_name) == NULL) X { X printf("XOpenDisplay failed on the Added Display: %s\n", disp_name); X unset_paused_cursors(); /*done*/ X return(0); X } X X X for (disp_num=0; disp_num<num_of_disps; disp_num++) X if (disp_info[disp_num].in_session_bool == FALSE) /*this is available*/ X break; X X if (disp_num == num_of_disps) X { X num_of_disps++; /*it goes after all the rest*/ X } X X disp_info[disp_num].in_session_bool = TRUE; /*this is the one*/ X strncpy(disp_args[disp_num], disp_name, 48); X X if (initialize_a_single_display(disp_num, &num_people_drawing) != TRUE) X { X printf("ERROR: Could not add display %s for some reason.\n", X disp_args[disp_num]); X disp_info[disp_num].in_session_bool = FALSE; X unset_paused_cursors(); /*done*/ X return(0); X } X X else X { X if (NOTHING_DRAWN_YET == TRUE) /*global variable*/ X { X for (k=0; k<num_of_disps; k++) X if (disp_info[k].in_session_bool) X place_and_draw_status_win(k); X unset_paused_cursors(); /*we are done*/ X return(1); X } X X /* X * now figure out what window we should get an image from to X * put onto this new window. Best case is one that is the same X * depth and fully visible, next best case is the most depth, etc... X */ X XGetWindowAttributes(disp_info[disp_num].disp, X disp_info[disp_num].win_id, &new_win_attr); X X /* X * get the same depth image fully on screen, if at all possible X */ X for (i=0,found_source=FALSE;(i<num_of_disps)&&(found_source==FALSE);i++) X { X if ((disp_info[i].in_session_bool==TRUE) && (i!=disp_num)) X { X XGetWindowAttributes(disp_info[i].disp, disp_info[i].win_id, X &old_win_attr); X if (old_win_attr.depth == new_win_attr.depth) X { X XTranslateCoordinates(disp_info[i].disp, X disp_info[i].win_id, RootWindow(disp_info[i].disp, X DefaultScreen(disp_info[i].disp)), X 0, 0, &left, &top, &dummy); X XGetWindowAttributes(disp_info[i].disp, X RootWindow(disp_info[i].disp, X DefaultScreen(disp_info[i].disp)), X &root_win_attr); X if (((left + old_win_attr.width) < root_win_attr.width) && X ((top + old_win_attr.height) < root_win_attr.height)) X { X source_disp_num = i; /*we found the ideal case*/ X found_source = TRUE; /*same depth, fully on monitor*/ X break; X } X } X } X } X X if (found_source == FALSE) X { X /* X * get the same depth image if at all possible, not fully on screen X */ X for (i=0; (i<num_of_disps) && (found_source==FALSE); i++) X { X if ((disp_info[i].in_session_bool==TRUE) && (i!=disp_num)) X { X XGetWindowAttributes(disp_info[i].disp, disp_info[i].win_id, X &old_win_attr); X if (old_win_attr.depth == new_win_attr.depth) X { X source_disp_num = i; /*we found an OK case*/ X found_source = TRUE; /*same depth, part on monitor*/ X break; X } X } X } X } X X if (found_source == FALSE) X { X /* X * we didn't find a display of equal depth, so look for the one of X * the greatest depth in the session. It is the best one to use. X */ X for (i=0, cur_depth=0; (i<num_of_disps)&&(found_source==FALSE); i++) X { X if ((disp_info[i].in_session_bool==TRUE) && (i!=disp_num)) X { X XGetWindowAttributes(disp_info[i].disp, disp_info[i].win_id, X &old_win_attr); X if (old_win_attr.depth > cur_depth) X { X source_disp_num = i; X cur_depth = old_win_attr.depth; X } X } X } X } X X /* X * now that we have our favorite choice, make sure we don't get any X * image from a part of a window that is offscreen. This is X * not allowed and causes core dump. X */ X XTranslateCoordinates(disp_info[source_disp_num].disp, X disp_info[source_disp_num].win_id, X RootWindow(disp_info[source_disp_num].disp, X DefaultScreen(disp_info[source_disp_num].disp)), X 0, 0, &left, &top, &dummy); X XGetWindowAttributes(disp_info[source_disp_num].disp, X RootWindow(disp_info[source_disp_num].disp, X DefaultScreen(disp_info[source_disp_num].disp)), X &root_win_attr); X X fully_printed = TRUE; X print_it = TRUE; X X if (left < 0) X { X printf("ERROR: Get the dang window from out from under the "); X printf("left edge of the monitor.\n"); X print_it = FALSE; X } X else X win_left = 0; X X if (top < 0) X { X printf("ERROR: Get the dang window from out from under the "); X printf("top edge of the monitor.\n"); X print_it = FALSE; X } X else X win_top = 0; X X if ((left + old_win_attr.width) < root_win_attr.width) X width = old_win_attr.width; /*we are inside the boundary*/ X else X { X width = root_win_attr.width - left; /*we are outside the boundary*/ X fully_printed = FALSE; X } X X if ((top + old_win_attr.height) < root_win_attr.height) X height = old_win_attr.height; /*we are inside the boundary*/ X else X { X height = root_win_attr.height - top; /*we are outside the boundary*/ X fully_printed = FALSE; X } X X if (print_it == TRUE) X { X transfer_image_between_displays(source_disp_num, disp_num,win_left, X win_top, width, height); X } X else X { X printf("WARNING: image not displayed on display %s.\n", X disp_args[disp_num]); X X left = 0; X top = 0; X width = old_win_attr.width; X height = old_win_attr.height; X X mesg = "You are missing an image here."; X XDrawString(disp_info[disp_num].disp, disp_info[disp_num].win_id, X disp_info[disp_num].fg_menu_gc, X (left + (width/2) - 88), (top + (height/2) + 5), X mesg, strlen(mesg)); X } X X if (fully_printed == FALSE) X { X printf("WARNING: image not fully displayed on display %s.\n", X disp_args[disp_num]); X } X X for (k=0; k<num_of_disps; k++) X if (disp_info[k].in_session_bool) X place_and_draw_status_win(k); X unset_paused_cursors(); /*we are done*/ X } X} X X X/* X * transfer_image_between_displays - this function tranfers an image from X * one display to another as specified by the upper X * left corner x, y and the width and height parameters. X * Currently this is done using the "save to disk" and X * "restore from disk" functions as an easy shortcut. X */ Xtransfer_image_between_displays(source_disp_num, dest_disp_num, x, y, width, X height) Xint source_disp_num, dest_disp_num, x, y, width, height; X{ X XImage *the_full_screen_image; X char *mesg, temp_file_name[256]; X int depth; X X sprintf(temp_file_name, "/tmp/wscr.%d", getpid()); X X save_image_on_disk(disp_info[source_disp_num].disp, X disp_info[source_disp_num].win_id, x, y, width, height, X temp_file_name); X X if ((the_full_screen_image = read_image_from_disk( X disp_info[dest_disp_num].disp, X disp_info[dest_disp_num].win_id, X temp_file_name, &width, X &height, &depth)) == NULL) X { X printf("WARNING: image not displayed on display %s.\n", X disp_args[dest_disp_num]); X XClearArea(disp_info[dest_disp_num].disp, X disp_info[dest_disp_num].win_id, X 0, 0, width, height, False); X X XSetLineAttributes(disp_info[dest_disp_num].disp, X disp_info[dest_disp_num].rubber_band_gc, 3, X LineSolid, CapButt, JoinBevel); X if ((width > 4) && (height > 4)) X { X XDrawRectangle(disp_info[dest_disp_num].disp, X disp_info[dest_disp_num].win_id, X disp_info[dest_disp_num].rubber_band_gc, X 2, 2, width - 4, height - 4); X } X XSetLineAttributes(disp_info[dest_disp_num].disp, X disp_info[dest_disp_num].rubber_band_gc, 0, X LineSolid, CapButt, JoinBevel); X X mesg = "You are missing an image here."; X XDrawString(disp_info[dest_disp_num].disp, X disp_info[dest_disp_num].win_id, X disp_info[dest_disp_num].fg_menu_gc, (width/2) - 88, X (height/2) + 5, mesg, strlen(mesg)); X } X else if (DefaultDepth(disp_info[dest_disp_num].disp, X DefaultScreen(disp_info[dest_disp_num].disp)) != depth) X { X printf("WARNING: image not displayed on display %s. ", X disp_args[dest_disp_num]); X printf("(Inconsistent depths.)\n"); X XDestroyImage(the_full_screen_image); X } X else X { X XPutImage(disp_info[dest_disp_num].disp, X disp_info[dest_disp_num].win_id, X disp_info[dest_disp_num].win_gc[dest_disp_num], X the_full_screen_image, X 0, 0, x, y, width, height); X XFlush(disp_info[dest_disp_num].disp); X XDestroyImage(the_full_screen_image); X } X} X X X/* X * initialize_a_single_display - this function creates all the win_ids, gcs, X * etc, for a new display assuming that the the "disp_num" X * passed in is the location in the global disp_info X * structure of the display, and that all the other X * displays are set up VERY well (i.e. the X * "in_session_bool" field is accurate. This function X * also allocates gc's to draw on THIS NEW DISPLAY from X * the previous existing displays. X */ Xinitialize_a_single_display(disp_num, num_people_drawing) Xint disp_num, *num_people_drawing; X{ X unsigned long nothing_mask = 0; X unsigned long alter_these_mask = GCSubwindowMode | GCLineWidth | X GCForeground | GCCapStyle | GCFont | X GCBackground | GCGraphicsExposures; X unsigned long alter_menu_mask = GCSubwindowMode | GCForeground | GCFont | X GCBackground | GCLineWidth; X unsigned long alter_these2_mask = CWEventMask | CWBackPixel | X CWBackingStore | CWWinGravity | X CWBitGravity | CWSaveUnder; X unsigned long alter_menu2_mask = CWEventMask | CWBackPixel | CWSaveUnder | X CWBackingStore | CWWinGravity; X unsigned long gc_copy_mask = GCSubwindowMode | GCLineWidth | X GCForeground | GCCapStyle | GCFont | X GCBackground | GCGraphicsExposures; X XSizeHints win_size_hints; X Cursor the_cursor, menu_cursor; X XColor scrn_def_ret, exact_def_ret, scrn_def_ret2, exact_def_ret2; END_OF_FILE if test 35313 -ne `wc -c <'wscrawl/xad'`; then echo shar: \"'wscrawl/xad'\" unpacked with wrong size! fi # end of 'wscrawl/xad' fi echo shar: End of archive 3 \(of 5\). cp /dev/null ark3isdone 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.