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