1 /*
2  * FIG : Facility for Interactive Generation of figures
3  * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4  * Parts Copyright (c) 1989-2007 by Brian V. Smith
5  * Parts Copyright (c) 1991 by Paul King
6  *
7  * Any party obtaining a copy of these files is granted, free of charge, a
8  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9  * nonexclusive right and license to deal in this software and documentation
10  * files (the "Software"), including without limitation the rights to use,
11  * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
12  * the Software, and to permit persons who receive copies from any such
13  * party to do so, with the only requirement being that the above copyright
14  * and this permission notice remain intact.
15  *
16  */
17 
18 #include "fig.h"
19 #include "resources.h"
20 #include "object.h"
21 #include "paintop.h"
22 #include "mode.h"
23 #include "d_arc.h"
24 #include "e_flip.h"
25 #include "e_rotate.h"
26 #include "u_draw.h"
27 #include "u_redraw.h"
28 #include "w_canvas.h"
29 #include "w_drawprim.h"
30 #include "w_file.h"
31 #include "w_indpanel.h"
32 #include "w_layers.h"
33 #include "w_setup.h"
34 #include "w_util.h"
35 #include "w_zoom.h"
36 
37 #include "d_text.h"
38 #include "u_bound.h"
39 #include "u_elastic.h"
40 #include "u_markers.h"
41 #include "w_cursor.h"
42 #include "w_rulers.h"
43 
44 /* EXPORTS */
45 
46 /* set in redisplay_region if called when preview_in_progress is true */
47 Boolean	request_redraw = False;
48 
49 /*
50  * Support for rendering based on correct object depth.	 A simple depth based
51  * caching scheme; anything more will require major surgery on the object
52  * data structures that will percolate throughout program.
53  *
54  * One ``counts'' structure for each object type at each nesting depth from 0
55  * to MAX_DEPTH - 1.  We track both the number of objects per type per depth,
56  * as well as the number of objects drawn so far per type per depth to cut
57  * down on search loop overhead.
58  */
59 
60 /*
61  * The array of ``counts'' structures.	All objects at depth >= MAX_DEPTH are
62  * accounted for in the counts[MAX_DEPTH] entry.
63  */
64 
65 struct counts	counts[MAX_DEPTH + 1], saved_counts[MAX_DEPTH + 1];
66 
67 /*
68  * Function to clear the array of object counts with file load or new command.
69  */
70 
71 
72 void redisplay_arcobject (F_arc *arcs, int depth);
73 void redisplay_compoundobject (F_compound *compounds, int depth);
74 void redisplay_ellipseobject (F_ellipse *ellipses, int depth);
75 void redisplay_lineobject (F_line *lines, int depth);
76 void redisplay_splineobject (F_spline *splines, int depth);
77 void redisplay_textobject (F_text *texts, int depth);
78 void redraw_pageborder (void);
79 void draw_pb (int x, int y, int w, int h);
80 
81 void
clearallcounts(void)82 clearallcounts(void)
83 {
84     register struct counts *cp;
85 
86     for (cp = &counts[0]; cp <= &counts[MAX_DEPTH]; ++cp) {
87 	cp->num_arcs = 0;
88 	cp->num_lines = 0;
89 	cp->num_ellipses = 0;
90 	cp->num_splines = 0;
91 	cp->num_texts = 0;
92     }
93     clearcounts();
94 }
95 
96 /*
97  * Clear count of objects drawn at each depth
98  */
99 
100 void
clearcounts(void)101 clearcounts(void)
102 {
103     register struct counts *cp;
104 
105     for (cp = &counts[0]; cp <= &counts[MAX_DEPTH]; ++cp) {
106 	cp->cnt_arcs = 0;
107 	cp->cnt_lines = 0;
108 	cp->cnt_ellipses = 0;
109 	cp->cnt_splines = 0;
110 	cp->cnt_texts = 0;
111     }
112 }
113 
redisplay_objects(F_compound * active_objects)114 void redisplay_objects(F_compound *active_objects)
115 {
116     int		    depth;
117     F_compound	   *objects, *save_objects;
118 
119     objects = active_objects;
120     save_objects = (F_compound *) NULL;
121 
122     draw_parent_gray = False;
123 
124     if (objects == NULL)
125 	return;
126 
127     /*
128      * Opened compound with `keep parent visible'?
129      */
130     for (; (objects->parent != NULL) && (objects->draw_parent); ) {
131 	if (!save_objects)
132 	    save_objects = objects;
133 	/* put in any changes */
134 	*((F_compound*)objects->GABPtr) = *objects;
135 	/* follow parent to the top */
136 	objects = objects->parent;
137 	/* instruct lower level procs to draw gray */
138 	draw_parent_gray = True;
139     }
140 
141     clearcounts();
142 
143     /* if user wants gray inactive layers, draw them first */
144     /* remove_depth() in u_list.c sets min_depth = -1 if there are no objects */
145     if ((gray_layers || draw_parent_gray) && min_depth > -1) {
146 	for (depth = max_depth; depth >= min_depth; --depth) {
147 	    if (!active_layer(depth) || draw_parent_gray) {
148 		redisplay_arcobject(objects->arcs, depth);
149 		redisplay_compoundobject(objects->compounds, depth);
150 		redisplay_ellipseobject(objects->ellipses, depth);
151 		redisplay_lineobject(objects->lines, depth);
152 		redisplay_splineobject(objects->splines, depth);
153 		redisplay_textobject(objects->texts, depth);
154 	    }
155 	}
156     }
157 
158     if (draw_parent_gray) {
159 	/* now point to just the open compound and (re)draw it */
160 	clearcounts();
161 	objects = save_objects;
162 	draw_parent_gray = False;
163     }
164 
165     /* now draw the active layers in their normal colors */
166     if (min_depth > -1) { /* if there are no objects, remove_depth() in
167 			     u_list.c sets min_depth = -1 */
168 	for (depth = max_depth; depth >= min_depth; --depth) {
169 	    if (active_layer(depth)) {
170 		redisplay_arcobject(objects->arcs, depth);
171 		redisplay_compoundobject(objects->compounds, depth);
172 		redisplay_ellipseobject(objects->ellipses, depth);
173 		redisplay_lineobject(objects->lines, depth);
174 		redisplay_splineobject(objects->splines, depth);
175 		redisplay_textobject(objects->texts, depth);
176 	    }
177 	}
178     }
179 
180     /*
181      * Point markers and compounds, not being ``real objects'', are handled
182      * outside the depth loop.
183      */
184 
185     /* show the markers if they are on */
186     toggle_markers_in_compound(active_objects);
187     /* mark any center if requested */
188     if (setcenter)
189 	center_marker(setcenter_x, setcenter_y);
190     /* and any anchor */
191     if (setanchor)
192 	center_marker(setanchor_x, setanchor_y);
193 }
194 
195 /*
196  * Redisplay a list of arcs.  Only display arcs of the correct depth.
197  * For each arc drawn, update the count for the appropriate depth in
198  * the counts array.
199  */
200 
redisplay_arcobject(F_arc * arcs,int depth)201 void redisplay_arcobject(F_arc *arcs, int depth)
202 {
203     F_arc	   *arc;
204     struct counts  *cp;
205 
206     if (arcs == NULL)
207 	return;
208     cp = &counts[min2(depth, MAX_DEPTH)];
209 
210     arc = arcs;
211     while (arc != NULL && cp->cnt_arcs < cp->num_arcs) {
212 	if (depth == arc->depth) {
213 		draw_arc(arc, PAINT);
214 		++cp->cnt_arcs;
215 	    }
216 	arc = arc->next;
217     }
218 }
219 
220 /*
221  * Redisplay a list of ellipses.  Only display ellipses of the correct depth
222  * For each ellipse drawn, update the count for the
223  * appropriate depth in the counts array.
224  */
225 
redisplay_ellipseobject(F_ellipse * ellipses,int depth)226 void redisplay_ellipseobject(F_ellipse *ellipses, int depth)
227 {
228     F_ellipse	   *ep;
229     struct counts  *cp;
230 
231     if (ellipses == NULL)
232 	return;
233     cp = &counts[min2(depth, MAX_DEPTH)];
234 
235 
236     ep = ellipses;
237     while (ep != NULL && cp->cnt_ellipses < cp->num_ellipses) {
238 	if (depth == ep->depth) {
239 		draw_ellipse(ep, PAINT);
240 		++cp->cnt_ellipses;
241 	    }
242 	ep = ep->next;
243     }
244 }
245 
246 /*
247  * Redisplay a list of lines.  Only display lines of the correct depth.
248  * For each line drawn, update the count for the appropriate
249  * depth in the counts array.
250  */
251 
redisplay_lineobject(F_line * lines,int depth)252 void redisplay_lineobject(F_line *lines, int depth)
253 {
254     F_line	   *lp;
255     struct counts  *cp;
256 
257     if (lines == NULL)
258 	return;
259     cp = &counts[min2(depth, MAX_DEPTH)];
260 
261 
262     lp = lines;
263     while (lp != NULL && cp->cnt_lines < cp->num_lines) {
264 	if (depth == lp->depth) {
265 		draw_line(lp, PAINT);
266 		++cp->cnt_lines;
267 	    }
268 	lp = lp->next;
269     }
270 }
271 
272 /*
273  * Redisplay a list of splines.	 Only display splines of the correct depth
274  * For each spline drawn, update the count for the
275  * appropriate depth in the counts array.
276  */
277 
redisplay_splineobject(F_spline * splines,int depth)278 void redisplay_splineobject(F_spline *splines, int depth)
279 {
280     F_spline	   *spline;
281     struct counts  *cp;
282 
283     if (splines == NULL)
284 	return;
285     cp = &counts[min2(depth, MAX_DEPTH)];
286 
287     spline = splines;
288     while (spline != NULL && cp->cnt_splines < cp->num_splines) {
289 	if (depth == spline->depth) {
290 		draw_spline(spline, PAINT);
291 		++cp->cnt_splines;
292 	    }
293 	spline = spline->next;
294     }
295 }
296 
297 /*
298  * Redisplay a list of texts.  Only display texts of the correct depth.	 For
299  * each text drawn, update the count for the appropriate depth in the counts
300  * array.
301  */
302 
redisplay_textobject(F_text * texts,int depth)303 void redisplay_textobject(F_text *texts, int depth)
304 {
305     F_text	   *text;
306     struct counts  *cp;
307 
308     if (texts == NULL)
309 	return;
310     cp = &counts[min2(depth, MAX_DEPTH)];
311 
312     text = texts;
313     while (text != NULL && cp->cnt_texts < cp->num_texts) {
314 	if (depth == text->depth) {
315 	    draw_text(text, PAINT);
316 	    ++cp->cnt_texts;
317 	}
318 	text = text->next;
319     }
320 }
321 
322 /*
323  * Redisplay a list of compounds at a current depth.  Basically just farm the
324  * work out to the objects contained in the compound.
325  */
326 
redisplay_compoundobject(F_compound * compounds,int depth)327 void redisplay_compoundobject(F_compound *compounds, int depth)
328 {
329     F_compound	   *c;
330 
331     for (c = compounds; c != NULL; c = c->next) {
332 	redisplay_arcobject(c->arcs, depth);
333 	redisplay_compoundobject(c->compounds, depth);
334 	redisplay_ellipseobject(c->ellipses, depth);
335 	redisplay_lineobject(c->lines, depth);
336 	redisplay_splineobject(c->splines, depth);
337 	redisplay_textobject(c->texts, depth);
338     }
339 }
340 
341 /*
342  * Redisplay the entire drawing.
343  */
344 void
redisplay_canvas(void)345 redisplay_canvas(void)
346 {
347     /* turn off Compose key LED */
348     setCompLED(0);
349 
350     redisplay_region(0, 0, CANVAS_WD, CANVAS_HT);
351     reset_rulers();
352 }
353 
354 /* redisplay the object currently being created by the user (if any) */
355 
redisplay_curobj(void)356 void redisplay_curobj(void)
357 {
358     F_point	*p;
359     int		 rx,ry,i;
360 
361     /* no object currently being created to refresh, return */
362     if (!action_on)
363 	return;
364 
365     /* find which type of object we need to refresh */
366 
367     /* creating an object */
368     /* placing a library object is slightly different */
369     if (cur_mode < FIRST_EDIT_MODE) {
370       switch (cur_mode) {
371 	case F_PLACE_LIB_OBJ:
372 	   break;	/* don't do anything */
373 	case F_PICOBJ:
374 	case F_ARCBOX:
375 	case F_BOX:
376 	   elastic_box(fix_x, fix_y, cur_x, cur_y);
377 	   break;
378 	case F_CIRCLE_BY_RAD:
379 	   elastic_cbr();
380 	   break;
381 	case F_CIRCLE_BY_DIA:
382 	   elastic_cbd();
383 	   break;
384 	case F_ELLIPSE_BY_RAD:
385 	   elastic_ebr();
386 	   break;
387 	case F_ELLIPSE_BY_DIA:
388 	   elastic_ebd();
389 	   break;
390 	case F_POLYLINE:
391 	case F_POLYGON:
392 	case F_APPROX_SPLINE:
393 	case F_CLOSED_APPROX_SPLINE:
394 	case F_INTERP_SPLINE:
395 	case F_CLOSED_INTERP_SPLINE:
396 	    for (p = first_point; p != NULL; p = p->next) {
397 		if (p->next) {
398 		    rx = p->next->x;
399 		    ry = p->next->y;
400 		} else {
401 		    /* no more points in the list, draw to current now */
402 		    rx = cur_x;
403 		    ry = cur_y;
404 		}
405 		pw_vector(canvas_win, p->x, p->y, rx, ry,
406 		      PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
407 		/* erase endpoint because next seg will redraw it */
408 		pw_vector(canvas_win, rx, ry, rx, ry,
409 		      INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
410 	    }
411 	    break;
412 	case F_CIRCULAR_ARC:
413 	    if (center_marked) {
414 	        center_marker(center_point.x, center_point.y);
415 		/* redraw either circle or partial arc */
416 		if (num_point)
417 		    elastic_arc();
418 		else
419 		    elastic_cbr();
420 	    } else {
421 		for (i=0; i<num_point; i++) {
422 		    if (i < num_point-1) {
423 			rx = point[i+1].x;
424 			ry = point[i+1].y;
425 		    } else {
426 			rx = cur_x;
427 			ry = cur_y;
428 		    }
429 		    pw_vector(canvas_win, point[i].x, point[i].y, rx, ry,
430 				INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
431 		}
432 	    }
433 	    break;
434 	case F_TEXT:
435 	    /* if the user is editing an existing string, erase the original
436 	       because redisplay_objects just re-drew it */
437 	    if (cur_t)
438 		draw_text(cur_t, INV_PAINT);
439 	    /* now refresh the temporary edit string */
440 	    draw_char_string();
441 	    break;
442       }
443     } else {
444 	/* editing an object, just refresh it as is */
445 	(*canvas_ref_proc)(cur_x, cur_y);
446     }
447 }
448 
redisplay_region(int xmin,int ymin,int xmax,int ymax)449 void redisplay_region(int xmin, int ymin, int xmax, int ymax)
450 {
451     /* if we're generating a preview, don't redisplay the canvas
452        but set request flag so preview will call us with full canvas
453        after it is done generating the preview */
454 
455     if (preview_in_progress) {
456 	request_redraw = True;
457 	return;
458     }
459 
460     set_temp_cursor(wait_cursor);
461     /* kludge so that markers are redrawn */
462     xmin -= 10;
463     ymin -= 10;
464     xmax += 10;
465     ymax += 10;
466     set_clip_window(xmin, ymin, xmax, ymax);
467     clear_canvas();
468     redisplay_objects(&objects);
469     redisplay_curobj();
470     reset_clip_window();
471     reset_cursor();
472 }
473 
474 /* update page border with new page size */
475 
update_pageborder(void)476 void update_pageborder(void)
477 {
478     if (appres.show_pageborder) {
479 	clear_canvas();
480 	redisplay_canvas();
481     }
482 }
483 
484 /* make a light blue line showing the right and bottom edge of the current page size */
485 /* also make light blue lines vertically and horizontally through 0,0 if
486    showaxislines is true */
487 
redisplay_pageborder(void)488 void redisplay_pageborder(void)
489 {
490 
491     set_clip_window(clip_xmin, clip_ymin, clip_xmax, clip_ymax);
492     /* first the axis lines */
493     if (appres.showaxislines) {
494 	/* set the color */
495 	XSetForeground(tool_d, border_gc, axis_lines_color);
496 	XDrawLine(tool_d, canvas_win, border_gc, round(-zoomxoff*zoomscale), 0,
497 					  round(-zoomxoff*zoomscale), CANVAS_HT);
498 	XDrawLine(tool_d, canvas_win, border_gc, 0, round(-zoomyoff*zoomscale), CANVAS_WD,
499 					  round(-zoomyoff*zoomscale));
500     }
501     /* now the page border if user wants it */
502     if (appres.show_pageborder)
503 	redraw_pageborder();
504 }
505 
redraw_pageborder(void)506 void redraw_pageborder(void)
507 {
508     int		   pwd, pht, ux;
509     int		   x, y;
510     char	   pname[80];
511 
512     /* set the color */
513     XSetForeground(tool_d, border_gc, pageborder_color);
514 
515     pwd = paper_sizes[appres.papersize].width;
516     pht = paper_sizes[appres.papersize].height;
517     if (!appres.INCHES) {
518 	pwd = (int)(pwd*2.54*PIX_PER_CM/PIX_PER_INCH);
519 	pht = (int)(pht*2.54*PIX_PER_CM/PIX_PER_INCH);
520     }
521     /* swap height and width if landscape */
522     if (appres.landscape) {
523 	ux = pwd;
524 	pwd = pht;
525 	pht = ux;
526     }
527     /* if multiple page mode, draw all page borders that are visible */
528     if (appres.multiple) {
529 	int	wd, ht;
530 
531 	wd = CANVAS_WD/zoomscale;
532 	ht = CANVAS_HT/zoomscale;
533 
534 	/* draw the page borders in the positive direction */
535 	for (y=0; y < ht+zoomyoff; y += pht) {
536 	    for (x=0; x < wd+zoomxoff; x += pwd) {
537 		draw_pb(x, y, pwd, pht);
538 	    }
539 	}
540 	/* now draw the page borders in the -X, -Y direction */
541 	for (y=0; y > zoomyoff; y -= pht) {
542 	    for (x=0; x > zoomxoff; x -= pwd) {
543 		draw_pb(x, y, -pwd, -pht);
544 	    }
545 	}
546 	/* now draw the page borders in the -X, +Y direction */
547 	for (y=0; y < ht+zoomyoff; y += pht) {
548 	    for (x=0; x > zoomxoff; x -= pwd) {
549 		draw_pb(x, y, -pwd, pht);
550 	    }
551 	}
552 	/* now draw the page borders in the +X, -Y direction */
553 	for (y=0; y > zoomyoff; y -= pht) {
554 	    for (x=0; x < wd+zoomxoff; x += pwd) {
555 		draw_pb(x, y, pwd, -pht);
556 	    }
557 	}
558     } else {
559 	zXDrawLine(tool_d, canvas_win, border_gc, 0,   0,   pwd, 0);
560 	zXDrawLine(tool_d, canvas_win, border_gc, pwd, 0,   pwd, pht);
561 	zXDrawLine(tool_d, canvas_win, border_gc, pwd, pht, 0,   pht);
562 	zXDrawLine(tool_d, canvas_win, border_gc, 0,   pht, 0,   0);
563     }
564     /* Now put the paper size in the lower-right corner just outside the page border.
565        We want the full name except for the size in parenthesis */
566     strcpy(pname,paper_sizes[appres.papersize].fname);
567     /* truncate after first part of name */
568     *(strchr(pname, '('))= '\0';
569     XDrawString(tool_d,canvas_win,border_gc,ZOOMX(pwd)+3,ZOOMY(pht),pname,strlen(pname));
570 }
571 
draw_pb(int x,int y,int w,int h)572 void draw_pb(int x, int y, int w, int h)
573 {
574 	zXDrawLine(tool_d, canvas_win, border_gc, x,   y,   x+w, y);
575 	zXDrawLine(tool_d, canvas_win, border_gc, x+w, y,   x+w, y+h);
576 	zXDrawLine(tool_d, canvas_win, border_gc, x+w, y+h, x,   y+h);
577 	zXDrawLine(tool_d, canvas_win, border_gc, x,   y+h, x,   y);
578 }
579 
redisplay_zoomed_region(int xmin,int ymin,int xmax,int ymax)580 void redisplay_zoomed_region(int xmin, int ymin, int xmax, int ymax)
581 {
582     redisplay_region(ZOOMX(xmin), ZOOMY(ymin), ZOOMX(xmax), ZOOMY(ymax));
583 }
584 
redisplay_ellipse(F_ellipse * e)585 void redisplay_ellipse(F_ellipse *e)
586 {
587     int		    xmin, ymin, xmax, ymax;
588 
589     ellipse_bound(e, &xmin, &ymin, &xmax, &ymax);
590     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
591 }
592 
redisplay_ellipses(F_ellipse * e1,F_ellipse * e2)593 void redisplay_ellipses(F_ellipse *e1, F_ellipse *e2)
594 {
595     int		    xmin1, ymin1, xmax1, ymax1;
596     int		    xmin2, ymin2, xmax2, ymax2;
597 
598     ellipse_bound(e1, &xmin1, &ymin1, &xmax1, &ymax1);
599     ellipse_bound(e2, &xmin2, &ymin2, &xmax2, &ymax2);
600     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
601 }
602 
redisplay_arc(F_arc * a)603 void redisplay_arc(F_arc *a)
604 {
605     int		    xmin, ymin, xmax, ymax;
606     int		    cx, cy;
607 
608     arc_bound(a, &xmin, &ymin, &xmax, &ymax);
609     /* if vertices (and center point) are shown, make sure to include them in the clip area */
610     if (appres.shownums) {
611 	/* first adjust for height/width of labels (don't really care which way they are) */
612 	xmin -= 175;
613 	xmax += 175;
614 	ymin -= 175;
615 	/* (the numbers are above the vertices so we don't need to move ymax) */
616 
617 	/* now adjust for center point if it is outside the arc */
618 	cx = a->center.x;
619 	cy = a->center.y;
620 	if (cx < xmin+80)
621 	    xmin = cx-80;
622 	if (cx > xmax-150)
623 	    xmax = cx+150;
624 	if (cy < ymin+150)
625 	    ymin = cy-150;
626 	if (cy > ymax-80)
627 	    ymax = cy;
628     }
629     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
630 }
631 
redisplay_arcs(F_arc * a1,F_arc * a2)632 void redisplay_arcs(F_arc *a1, F_arc *a2)
633 {
634     int		    xmin1, ymin1, xmax1, ymax1;
635     int		    xmin2, ymin2, xmax2, ymax2;
636 
637     arc_bound(a1, &xmin1, &ymin1, &xmax1, &ymax1);
638     arc_bound(a2, &xmin2, &ymin2, &xmax2, &ymax2);
639     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
640 }
641 
redisplay_spline(F_spline * s)642 void redisplay_spline(F_spline *s)
643 {
644     int		    xmin, ymin, xmax, ymax;
645 
646     spline_bound(s, &xmin, &ymin, &xmax, &ymax);
647     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
648 }
649 
redisplay_splines(F_spline * s1,F_spline * s2)650 void redisplay_splines(F_spline *s1, F_spline *s2)
651 {
652     int		    xmin1, ymin1, xmax1, ymax1;
653     int		    xmin2, ymin2, xmax2, ymax2;
654 
655     spline_bound(s1, &xmin1, &ymin1, &xmax1, &ymax1);
656     spline_bound(s2, &xmin2, &ymin2, &xmax2, &ymax2);
657     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
658 }
659 
redisplay_line(F_line * l)660 void redisplay_line(F_line *l)
661 {
662     int		    xmin, ymin, xmax, ymax;
663 
664     line_bound(l, &xmin, &ymin, &xmax, &ymax);
665     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
666 }
667 
redisplay_lines(F_line * l1,F_line * l2)668 void redisplay_lines(F_line *l1, F_line *l2)
669 {
670     int		    xmin1, ymin1, xmax1, ymax1;
671     int		    xmin2, ymin2, xmax2, ymax2;
672 
673     line_bound(l1, &xmin1, &ymin1, &xmax1, &ymax1);
674     line_bound(l2, &xmin2, &ymin2, &xmax2, &ymax2);
675     redisplay_regions(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2);
676 }
677 
redisplay_compound(F_compound * c)678 void redisplay_compound(F_compound *c)
679 {
680     redisplay_zoomed_region(c->nwcorner.x, c->nwcorner.y,
681 			    c->secorner.x, c->secorner.y);
682 }
683 
redisplay_compounds(F_compound * c1,F_compound * c2)684 void redisplay_compounds(F_compound *c1, F_compound *c2)
685 {
686     redisplay_regions(c1->nwcorner.x, c1->nwcorner.y,
687 		      c1->secorner.x, c1->secorner.y,
688 		      c2->nwcorner.x, c2->nwcorner.y,
689 		      c2->secorner.x, c2->secorner.y);
690 }
691 
redisplay_text(F_text * t)692 void redisplay_text(F_text *t)
693 {
694     int		    xmin, ymin, xmax, ymax;
695     int		    dum;
696 
697     text_bound(t, &xmin, &ymin, &xmax, &ymax,
698 		&dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
699     redisplay_zoomed_region(xmin, ymin, xmax, ymax);
700 }
701 
redisplay_texts(F_text * t1,F_text * t2)702 void redisplay_texts(F_text *t1, F_text *t2)
703 {
704     int		    xmin1, ymin1, xmax1, ymax1;
705     int		    xmin2, ymin2, xmax2, ymax2;
706     int		    dum;
707 
708     text_bound(t1, &xmin1, &ymin1, &xmax1, &ymax1,
709 		&dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
710     text_bound(t2, &xmin2, &ymin2, &xmax2, &ymax2,
711 		&dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
712     redisplay_regions(xmin1, ymin1, xmax1, ymax1,
713 		      xmin2, ymin2, xmax2, ymax2);
714 }
715 
redisplay_regions(int xmin1,int ymin1,int xmax1,int ymax1,int xmin2,int ymin2,int xmax2,int ymax2)716 void redisplay_regions(int xmin1, int ymin1, int xmax1, int ymax1, int xmin2, int ymin2, int xmax2, int ymax2)
717 {
718     if (xmin1 == xmin2 && ymin1 == ymin2 && xmax1 == xmax2 && ymax1 == ymax2) {
719 	redisplay_zoomed_region(xmin1, ymin1, xmax1, ymax1);
720 	return;
721     }
722     /* below is easier than sending clip rectangle array to X */
723     if (overlapping(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2)) {
724 	redisplay_zoomed_region(min2(xmin1, xmin2), min2(ymin1, ymin2),
725 				max2(xmax1, xmax2), max2(ymax1, ymax2));
726     } else {
727 	redisplay_zoomed_region(xmin1, ymin1, xmax1, ymax1);
728 	redisplay_zoomed_region(xmin2, ymin2, xmax2, ymax2);
729     }
730 }
731 
732