Mercurial > hg > xemacs-beta
comparison pkg-src/tree-x/draw.c @ 167:85ec50267440 r20-3b10
Import from CVS: tag r20-3b10
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:45:46 +0200 |
parents | 0132846995bd |
children | 15872534500d |
comparison
equal
deleted
inserted
replaced
166:7a77eb660975 | 167:85ec50267440 |
---|---|
2 * File : draw.c | 2 * File : draw.c |
3 * Purpose : drawing-specific routines for dynamic tree program | 3 * Purpose : drawing-specific routines for dynamic tree program |
4 * ---------------------------------------------------------------------------- | 4 * ---------------------------------------------------------------------------- |
5 */ | 5 */ |
6 | 6 |
7 #include <stdlib.h> | |
7 #include <X11/Intrinsic.h> | 8 #include <X11/Intrinsic.h> |
8 #include <X11/StringDefs.h> | 9 #include <X11/StringDefs.h> |
9 | 10 |
11 #include "dissolve.h" | |
10 #include "defs.h" | 12 #include "defs.h" |
11 #include "tree.h" | 13 #include "tree.h" |
12 #include "dbl.h" | 14 #include "dbl.h" |
13 #include "intf.h" | 15 #include "intf.h" |
14 | 16 |
21 | 23 |
22 /* ------------------------------------------------------------------------- */ | 24 /* ------------------------------------------------------------------------- */ |
23 /* Local Variables */ | 25 /* Local Variables */ |
24 /* ------------------------------------------------------------------------- */ | 26 /* ------------------------------------------------------------------------- */ |
25 | 27 |
26 static char AnimationMode = FALSE; | 28 static char AnimationMode = FALSE; |
27 static char strbuf[BUFSIZ]; | 29 static char strbuf[BUFSIZ]; |
28 static int AnimationStep = ANIMATION_STEP; | 30 static int AnimationStep = ANIMATION_STEP; |
29 | |
30 /* ------------------------------------------------------------------------- */ | |
31 /* Forward Function Declarations */ | |
32 /* ------------------------------------------------------------------------- */ | |
33 | |
34 void DrawNode(); | |
35 void DrawTreeContour(); | |
36 | 31 |
37 | 32 |
38 /* ------------------------------------------------------------------------- */ | 33 /* ------------------------------------------------------------------------- */ |
39 /* Functions */ | 34 /* Functions */ |
40 /* ------------------------------------------------------------------------- */ | 35 /* ------------------------------------------------------------------------- */ |
41 | 36 |
42 | 37 |
43 /* ---------------------------------------------------------------------------- | 38 /* ---------------------------------------------------------------------------- |
44 * | 39 * |
45 * BeginFrame() provides an abstraction for double buffering. It should | 40 * BeginFrame() provides an abstraction for double buffering. It should |
46 * be called prior to creating a new frame of animation. | 41 * be called prior to creating a new frame of animation. |
47 * | 42 * |
48 * ---------------------------------------------------------------------------- | 43 * ---------------------------------------------------------------------------- |
49 */ | 44 */ |
50 | 45 |
51 void | 46 void |
52 BeginFrame() | 47 BeginFrame(void) |
53 { | 48 { |
54 DBLbegin_frame(TreeDrawingAreaDB); | 49 DBLbegin_frame(TreeDrawingAreaDB); |
55 } | 50 } |
56 | 51 |
57 | 52 |
58 /* ---------------------------------------------------------------------------- | 53 /* ---------------------------------------------------------------------------- |
59 * | 54 * |
60 * EndFrame() provides an abstraction for double buffering. It should | 55 * EndFrame() provides an abstraction for double buffering. It should |
61 * be called after creating a new frame of animation. | 56 * be called after creating a new frame of animation. |
62 * | 57 * |
63 * ---------------------------------------------------------------------------- | 58 * ---------------------------------------------------------------------------- |
64 */ | 59 */ |
65 | 60 |
66 void | 61 void |
67 EndFrame() | 62 EndFrame(void) |
68 { | 63 { |
69 DBLend_frame(TreeDrawingAreaDB, 0); | 64 DBLend_frame(TreeDrawingAreaDB, 0); |
70 } | 65 } |
71 | 66 |
72 | 67 |
73 /* ---------------------------------------------------------------------------- | 68 /* ---------------------------------------------------------------------------- |
74 * | 69 * |
75 * GetDrawingSize() gets the size of the drawing area, and returns the | 70 * GetDrawingSize() gets the size of the drawing area, and returns the |
76 * dimensions in the arguments. | 71 * dimensions in the arguments. |
77 * | 72 * |
78 * ---------------------------------------------------------------------------- | 73 * ---------------------------------------------------------------------------- |
79 */ | 74 */ |
80 | 75 |
81 void | 76 static void |
82 GetDrawingSize(width, height) | 77 GetDrawingSize(int *width, int *height) |
83 int *width, *height; | |
84 { | 78 { |
85 Dimension w, h; | 79 Dimension w, h; |
86 | 80 Arg al [2]; |
87 XtVaGetValues(TreeDrawingArea, | 81 |
88 XtNwidth, &w, | 82 XtSetArg (al [0], XtNwidth, &w); |
89 XtNheight, &h, | 83 XtSetArg (al [1], XtNheight, &h); |
90 NULL); | 84 XtGetValues(TreeDrawingArea, al, 2); |
91 | 85 |
92 *width = (int) w; | 86 *width = (int) w; |
93 *height = (int) h; | 87 *height = (int) h; |
94 } | 88 } |
95 | 89 |
96 | 90 |
97 /* ---------------------------------------------------------------------------- | 91 /* ---------------------------------------------------------------------------- |
98 * | 92 * |
99 * SetDrawingSize() sets the size of the drawing area to the given | 93 * SetDrawingSize() sets the size of the drawing area to the given |
100 * dimensions. | 94 * dimensions. |
101 * | 95 * |
102 * ---------------------------------------------------------------------------- | 96 * ---------------------------------------------------------------------------- |
103 */ | 97 */ |
104 | 98 |
105 void | 99 static void |
106 SetDrawingSize(width, height) | 100 SetDrawingSize(int width, int height) |
107 int width, height; | 101 { |
108 { | 102 Arg al [2]; |
109 XtVaSetValues(TreeDrawingArea, | 103 XtSetArg (al [0], XtNwidth, (Dimension) width); |
110 XtNwidth, (Dimension) width, | 104 XtSetArg (al [1], XtNheight, (Dimension) height); |
111 XtNheight, (Dimension) height, | 105 XtSetValues (TreeDrawingArea, al, 2); |
112 NULL); | 106 } |
113 } | 107 |
114 | 108 |
115 | 109 /* ---------------------------------------------------------------------------- |
116 /* ---------------------------------------------------------------------------- | 110 * |
117 * | |
118 * SetDrawingTree() is used to specify what tree is to be drawn in the | 111 * SetDrawingTree() is used to specify what tree is to be drawn in the |
119 * drawing area. | 112 * drawing area. |
120 * | 113 * |
121 * ---------------------------------------------------------------------------- | 114 * ---------------------------------------------------------------------------- |
122 */ | 115 */ |
123 | 116 |
124 void | 117 void |
125 SetDrawingTree(tree) | 118 SetDrawingTree(Tree *tree) |
126 Tree *tree; | 119 { |
127 { | 120 TheTree = tree; |
128 TheTree = tree; | 121 } |
129 } | 122 |
130 | 123 |
131 | 124 /* ---------------------------------------------------------------------------- |
132 /* ---------------------------------------------------------------------------- | 125 * |
133 * | |
134 * SetNodeLabel() sets the label text of the specified node and computes | 126 * SetNodeLabel() sets the label text of the specified node and computes |
135 * the bounding rectangle so that the layout can be determined. This | 127 * the bounding rectangle so that the layout can be determined. This |
136 * function is called when new nodes are created. If TreeAlignNodes is | 128 * function is called when new nodes are created. If TreeAlignNodes is |
137 * True, the string is truncated so that the node's width is no longer | 129 * True, the string is truncated so that the node's width is no longer |
138 * than TreeParentDistance. | 130 * than TreeParentDistance. |
139 * | 131 * |
140 * ---------------------------------------------------------------------------- | 132 * ---------------------------------------------------------------------------- |
141 */ | 133 */ |
142 | 134 |
143 void | 135 void |
144 SetNodeLabel(node, label) | 136 SetNodeLabel(Tree *node, char *label) |
145 Tree *node; | |
146 char *label; | |
147 { | 137 { |
148 int len; | 138 int len; |
149 int dummy; | 139 int dummy; |
150 XCharStruct rtrn; | 140 XCharStruct rtrn; |
151 | 141 |
152 len = strlen(label); | 142 len = strlen(label); |
153 while (len > 1) { | 143 while (len > 1) { |
154 XTextExtents(TreeLabelFont, label, len, &dummy, &dummy, &dummy, &rtrn); | 144 XTextExtents(TreeLabelFont, label, len, &dummy, &dummy, &dummy, &rtrn); |
155 node->width = rtrn.lbearing + rtrn.rbearing + (LABEL_MAT_WIDTH * 2) + 1; | 145 node->width = rtrn.lbearing + rtrn.rbearing + (LABEL_MAT_WIDTH * 2) + 1; |
156 node->height = rtrn.ascent + rtrn.descent + (LABEL_MAT_HEIGHT * 2) + 1; | 146 node->height = rtrn.ascent + rtrn.descent + (LABEL_MAT_HEIGHT * 2) + 1; |
161 len--; | 151 len--; |
162 } | 152 } |
163 else | 153 else |
164 break; | 154 break; |
165 } | 155 } |
166 | 156 |
167 node->label.text = label; | 157 node->label.text = label; |
168 node->label.len = len; | 158 node->label.len = len; |
169 node->label.xoffset = LABEL_MAT_WIDTH + 1, | 159 node->label.xoffset = LABEL_MAT_WIDTH + 1, |
170 node->label.yoffset = rtrn.ascent + LABEL_MAT_HEIGHT + 1; | 160 node->label.yoffset = rtrn.ascent + LABEL_MAT_HEIGHT + 1; |
171 } | 161 } |
172 | 162 |
173 | 163 |
174 /* ---------------------------------------------------------------------------- | 164 /* ---------------------------------------------------------------------------- |
175 * | 165 * |
176 * SetDrawColor() sets the drawing color of the TreeDrawingArea. | 166 * SetDrawColor() sets the drawing color of the TreeDrawingArea. |
177 * | 167 * |
178 * ---------------------------------------------------------------------------- | 168 * ---------------------------------------------------------------------------- |
179 */ | 169 */ |
180 | 170 |
181 void | 171 void |
182 SetDrawColor(color) | 172 SetDrawColor(int color) |
183 int color; | |
184 { | 173 { |
185 XSetForeground(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, | 174 XSetForeground(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, |
186 TreeDrawingAreaDB->colors[color]); | 175 TreeDrawingAreaDB->colors[color]); |
187 } | 176 } |
188 | 177 |
189 /* ---------------------------------------------------------------------------- | 178 /* ---------------------------------------------------------------------------- |
190 * | 179 * |
191 * SetLineWidth() sets the line width of lines drawn in the TreeDrawingArea. | 180 * SetLineWidth() sets the line width of lines drawn in the TreeDrawingArea. |
192 * | 181 * |
193 * ---------------------------------------------------------------------------- | 182 * ---------------------------------------------------------------------------- |
194 */ | 183 */ |
195 | 184 |
196 void | 185 static void |
197 SetLineWidth(width) | 186 SetLineWidth(unsigned int width) |
198 unsigned int width; | |
199 { | 187 { |
200 XSetLineAttributes(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, | 188 XSetLineAttributes(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, |
201 width, LineSolid, CapButt, JoinRound); | 189 width, LineSolid, CapButt, JoinRound); |
202 } | 190 } |
203 | 191 |
204 | 192 |
205 /* ---------------------------------------------------------------------------- | 193 /* ---------------------------------------------------------------------------- |
206 * | 194 * |
207 * SetContours() sets the visibility of three possible contour modes: | 195 * SetContours() sets the visibility of three possible contour modes: |
208 * the outside contour, all subtree contours, or selected contours. | 196 * the outside contour, all subtree contours, or selected contours. |
209 * | 197 * |
210 * ---------------------------------------------------------------------------- | 198 * ---------------------------------------------------------------------------- |
211 */ | 199 */ |
212 | 200 |
213 void | 201 static void |
214 SetContours(option) | 202 SetContours(ContourOption option) |
215 ContourOption option; | |
216 { | 203 { |
217 if (option == NoContours) { | 204 if (option == NoContours) { |
218 switch (TreeShowContourOption) { | 205 switch (TreeShowContourOption) { |
219 case OutsideContour: | 206 case OutsideContour: |
220 DrawTreeContour(TheTree, New, BACKGROUND_COLOR, FALSE, FALSE, FALSE); | 207 DrawTreeContour(TheTree, New, BACKGROUND_COLOR, FALSE, FALSE, FALSE); |
260 TreeShowContourOption = option; | 247 TreeShowContourOption = option; |
261 } | 248 } |
262 | 249 |
263 | 250 |
264 /* ---------------------------------------------------------------------------- | 251 /* ---------------------------------------------------------------------------- |
265 * | 252 * |
266 * HiliteNode() is called by Unzip() to change the color of a node. | 253 * HiliteNode() is called by Unzip() to change the color of a node. |
267 * | 254 * |
268 * ---------------------------------------------------------------------------- | 255 * ---------------------------------------------------------------------------- |
269 */ | 256 */ |
270 | 257 |
271 void | 258 void |
272 HiliteNode(tree, pos_mode) | 259 HiliteNode(Tree *tree, PosMode pos_mode) |
273 Tree *tree; | |
274 { | 260 { |
275 SetDrawColor(HIGHLIGHT_COLOR); | 261 SetDrawColor(HIGHLIGHT_COLOR); |
276 DrawNode(tree, pos_mode); | 262 DrawNode(tree, pos_mode); |
277 SetDrawColor(TREE_COLOR); | 263 SetDrawColor(TREE_COLOR); |
278 } | 264 } |
279 | 265 |
280 | 266 |
281 /* ---------------------------------------------------------------------------- | 267 /* ---------------------------------------------------------------------------- |
282 * | 268 * |
283 * DrawNode() takes a node and draws the node in the specified widget | 269 * DrawNode() takes a node and draws the node in the specified widget |
284 * at its (x,y) coordinate. (x, y) indicates the upper-left corner where | 270 * at its (x,y) coordinate. (x, y) indicates the upper-left corner where |
285 * the node is drawn. Also, a line is drawn from the center of the left | 271 * the node is drawn. Also, a line is drawn from the center of the left |
286 * edge to the center of the parent's right edge. 'draw_mode' specifies | 272 * edge to the center of the parent's right edge. 'draw_mode' specifies |
287 * the drawing mode (whether or not the node is erased, rather than drawn). | 273 * the drawing mode (whether or not the node is erased, rather than drawn). |
288 * 'pos_mode' determines whether or not to use the old position of the node. | 274 * 'pos_mode' determines whether or not to use the old position of the node. |
289 * This flag is used in animating the movement of a node from its old | 275 * This flag is used in animating the movement of a node from its old |
290 * position to its new position. | 276 * position to its new position. |
291 * | 277 * |
292 * ---------------------------------------------------------------------------- | 278 * ---------------------------------------------------------------------------- |
293 */ | 279 */ |
294 | 280 |
295 void | 281 void |
296 DrawNode(node, pos_mode) | 282 DrawNode(Tree *node, PosMode pos_mode) |
297 Tree *node; | |
298 PosMode pos_mode; | |
299 { | 283 { |
300 Widget w; | 284 Widget w; |
301 GC gc; | 285 GC gc; |
302 | 286 |
303 w = TreeDrawingArea; | 287 w = TreeDrawingArea; |
304 gc = TreeDrawingAreaDB->gc; | 288 gc = TreeDrawingAreaDB->gc; |
305 | 289 |
306 if (pos_mode == Old) { | 290 if (pos_mode == Old) { |
307 XDrawString(XtDisplay(w), XtWindow(w), gc, | 291 XDrawString(XtDisplay(w), XtWindow(w), gc, |
308 node->old_pos.x + node->label.xoffset, | 292 node->old_pos.x + node->label.xoffset, |
309 node->old_pos.y + node->label.yoffset, | 293 node->old_pos.y + node->label.yoffset, |
310 node->label.text, node->label.len); | 294 node->label.text, node->label.len); |
311 XDrawRectangle(XtDisplay(w), XtWindow(w), gc, | 295 XDrawRectangle(XtDisplay(w), XtWindow(w), gc, |
312 node->old_pos.x, node->old_pos.y, | 296 node->old_pos.x, node->old_pos.y, |
313 node->width, node->height); | 297 node->width, node->height); |
314 if (node->parent) | 298 if (node->parent) |
315 XDrawLine(XtDisplay(w), XtWindow(w), gc, | 299 XDrawLine(XtDisplay(w), XtWindow(w), gc, |
316 node->old_pos.x - 1, | 300 node->old_pos.x - 1, |
317 node->old_pos.y + (node->height / 2), | 301 node->old_pos.y + (node->height / 2), |
318 node->parent->old_pos.x + node->parent->width + 1, | 302 node->parent->old_pos.x + node->parent->width + 1, |
319 node->parent->old_pos.y + (node->parent->height / 2)); | 303 node->parent->old_pos.y + (node->parent->height / 2)); |
329 } else { | 313 } else { |
330 XDrawString(XtDisplay(w), XtWindow(w), gc, | 314 XDrawString(XtDisplay(w), XtWindow(w), gc, |
331 node->pos.x + node->label.xoffset, | 315 node->pos.x + node->label.xoffset, |
332 node->pos.y + node->label.yoffset, | 316 node->pos.y + node->label.yoffset, |
333 node->label.text, node->label.len); | 317 node->label.text, node->label.len); |
334 | 318 |
335 XDrawRectangle(XtDisplay(w), XtWindow(w), gc, | 319 XDrawRectangle(XtDisplay(w), XtWindow(w), gc, |
336 node->pos.x, node->pos.y, | 320 node->pos.x, node->pos.y, |
337 node->width, node->height); | 321 node->width, node->height); |
338 if (node->parent) | 322 if (node->parent) |
339 XDrawLine(XtDisplay(w), XtWindow(w), gc, | 323 XDrawLine(XtDisplay(w), XtWindow(w), gc, |
340 node->pos.x - 1, | 324 node->pos.x - 1, |
341 node->pos.y + (node->height / 2), | 325 node->pos.y + (node->height / 2), |
342 node->parent->pos.x + node->parent->width + 1, | 326 node->parent->pos.x + node->parent->width + 1, |
343 node->parent->pos.y + (node->parent->height / 2)); | 327 node->parent->pos.y + (node->parent->height / 2)); |
353 } | 337 } |
354 } | 338 } |
355 | 339 |
356 | 340 |
357 /* ---------------------------------------------------------------------------- | 341 /* ---------------------------------------------------------------------------- |
358 * | 342 * |
359 * DrawTreeContour() draws the contour of the specified subtree. Bridges | 343 * DrawTreeContour() draws the contour of the specified subtree. Bridges |
360 * are not traversed, so the actual subtree contour is drawn, as opposed | 344 * are not traversed, so the actual subtree contour is drawn, as opposed |
361 * to the merged contour. 'color' specifies the drawing color. If 'detach' | 345 * to the merged contour. 'color' specifies the drawing color. If 'detach' |
362 * is True, the lines attaching the subtree contour to the node are not | 346 * is True, the lines attaching the subtree contour to the node are not |
363 * drawn. If 'select' is true, then only subtrees that are flagged as | 347 * drawn. If 'select' is true, then only subtrees that are flagged as |
364 * selected are shown. If 'recursive' is True, the entire tree is traversed. | 348 * selected are shown. If 'recursive' is True, the entire tree is traversed. |
365 * | 349 * |
366 * ---------------------------------------------------------------------------- | 350 * ---------------------------------------------------------------------------- |
367 */ | 351 */ |
368 | 352 |
369 void | 353 void |
370 DrawTreeContour(tree, pos_mode, color, detach, select, recursive) | 354 DrawTreeContour(Tree *tree, PosMode pos_mode, |
371 Tree *tree; | 355 int color, int detach_p, int select_p, int recursive) |
372 PosMode pos_mode; | |
373 int color; | |
374 int detach; | |
375 int select; | |
376 int recursive; | |
377 { | 356 { |
378 Widget w = TreeDrawingArea; | 357 Widget w = TreeDrawingArea; |
379 Polyline *contour, *tail; | 358 Polyline *contour, *tail; |
380 Tree *child; | 359 Tree *child; |
381 int x, y, i; | 360 int x, y, i; |
382 | 361 |
383 if (tree == NULL) | 362 if (tree == NULL) |
384 return; | 363 return; |
385 | 364 |
386 if ((select && tree->show_contour) || !select) { | 365 if ((select_p && tree->show_contour) || !select_p) { |
387 | 366 |
388 SetDrawColor(color); | 367 SetDrawColor(color); |
389 SetLineWidth(TreeContourWidth); | 368 SetLineWidth(TreeContourWidth); |
390 | 369 |
391 /* draw upper contour */ | 370 /* draw upper contour */ |
392 contour = tree->contour.upper.head; | 371 contour = tree->contour.upper.head; |
393 tail = tree->contour.upper.tail; | 372 tail = tree->contour.upper.tail; |
394 if (pos_mode == Old) { | 373 if (pos_mode == Old) { |
395 x = tree->old_pos.x - tree->border; | 374 x = tree->old_pos.x - tree->border; |
398 else { | 377 else { |
399 x = tree->pos.x - tree->border; | 378 x = tree->pos.x - tree->border; |
400 y = tree->pos.y - tree->border; | 379 y = tree->pos.y - tree->border; |
401 } | 380 } |
402 | 381 |
403 if (detach) { /* skip over attaching lines */ | 382 if (detach_p) { /* skip over attaching lines */ |
404 for (i = 0 ; i < 2 ; i++) { | 383 for (i = 0 ; i < 2 ; i++) { |
405 x += contour->dx; | 384 x += contour->dx; |
406 y += contour->dy; | 385 y += contour->dy; |
407 contour = contour->link; | 386 contour = contour->link; |
408 } | 387 } |
409 } | 388 } |
410 | 389 |
411 while (contour) { | 390 while (contour) { |
412 XDrawLine(XtDisplay(w), XtWindow(w), TreeDrawingAreaDB->gc, | 391 XDrawLine(XtDisplay(w), XtWindow(w), TreeDrawingAreaDB->gc, |
413 x, y, x + contour->dx, y + contour->dy); | 392 x, y, x + contour->dx, y + contour->dy); |
414 x += contour->dx; | 393 x += contour->dx; |
415 y += contour->dy; | 394 y += contour->dy; |
428 } else { | 407 } else { |
429 x = tree->pos.x - tree->border; | 408 x = tree->pos.x - tree->border; |
430 y = tree->pos.y + tree->border + tree->height; | 409 y = tree->pos.y + tree->border + tree->height; |
431 } | 410 } |
432 | 411 |
433 if (detach) { /* skip over attaching lines */ | 412 if (detach_p) { /* skip over attaching lines */ |
434 for (i = 0 ; i < 2 ; i++) { | 413 for (i = 0 ; i < 2 ; i++) { |
435 x += contour->dx; | 414 x += contour->dx; |
436 y += contour->dy; | 415 y += contour->dy; |
437 contour = contour->link; | 416 contour = contour->link; |
438 } | 417 } |
447 contour = NULL; | 426 contour = NULL; |
448 else | 427 else |
449 contour = contour->link; | 428 contour = contour->link; |
450 } | 429 } |
451 } | 430 } |
452 | 431 |
453 if (recursive) { | 432 if (recursive) { |
454 FOREACH_CHILD(child, tree) | 433 FOREACH_CHILD(child, tree) |
455 if (!child->elision) | 434 if (!child->elision) |
456 DrawTreeContour(child, pos_mode, color, | 435 DrawTreeContour(child, pos_mode, color, |
457 detach, select, recursive); | 436 detach_p, select_p, recursive); |
458 } | 437 } |
459 | 438 |
460 SetDrawColor(TREE_COLOR); | 439 SetDrawColor(TREE_COLOR); |
461 SetLineWidth(0); | 440 SetLineWidth(0); |
462 } | 441 } |
463 | 442 |
464 | 443 |
465 /* ---------------------------------------------------------------------------- | 444 /* ---------------------------------------------------------------------------- |
466 * | 445 * |
467 * DrawTree() traverses the given tree, drawing the node and connecting | 446 * DrawTree() traverses the given tree, drawing the node and connecting |
468 * segments. The tree contours are also drawn at each step, if enabled. | 447 * segments. The tree contours are also drawn at each step, if enabled. |
469 * 'draw_mode' specifies the drawing mode in which the tree is drawn. | 448 * 'draw_mode' specifies the drawing mode in which the tree is drawn. |
470 * 'pos_mode' determines whether or not to use the old position of the node. | 449 * 'pos_mode' determines whether or not to use the old position of the node. |
471 * This flag is used in animating the movement of a node from its old | 450 * This flag is used in animating the movement of a node from its old |
472 * position to its new position. DrawNode() is called to draw an individual | 451 * position to its new position. DrawNode() is called to draw an individual |
473 * node. | 452 * node. |
474 * | 453 * |
475 * ---------------------------------------------------------------------------- | 454 * ---------------------------------------------------------------------------- |
476 */ | 455 */ |
477 | 456 |
478 void | 457 void |
479 DrawTree(tree, pos_mode) | 458 DrawTree(Tree *tree, PosMode pos_mode) |
480 Tree *tree; | |
481 PosMode pos_mode; | |
482 { | 459 { |
483 if (tree == NULL) | 460 if (tree == NULL) |
484 return; | 461 return; |
485 | 462 |
486 DrawNode(tree, pos_mode); | 463 DrawNode(tree, pos_mode); |
495 DrawTreeContour(tree, pos_mode, ACTION_COLOR, FALSE, FALSE, FALSE); | 472 DrawTreeContour(tree, pos_mode, ACTION_COLOR, FALSE, FALSE, FALSE); |
496 } | 473 } |
497 if (tree->on_path) | 474 if (tree->on_path) |
498 HiliteNode(tree, pos_mode); | 475 HiliteNode(tree, pos_mode); |
499 | 476 |
500 if (tree->child && !tree->elision) | 477 if (tree->child && !tree->elision) |
501 DrawTree(tree->child, pos_mode); | 478 DrawTree(tree->child, pos_mode); |
502 if (tree->sibling) | 479 if (tree->sibling) |
503 DrawTree(tree->sibling, pos_mode); | 480 DrawTree(tree->sibling, pos_mode); |
504 } | 481 } |
505 | 482 |
506 | 483 |
507 /* ---------------------------------------------------------------------------- | 484 /* ---------------------------------------------------------------------------- |
508 * | 485 * |
509 * ShiftTree() adjusts the positions of each node so that it moves from | 486 * ShiftTree() adjusts the positions of each node so that it moves from |
510 * the "old" position towards the "new position". This is used by | 487 * the "old" position towards the "new position". This is used by |
511 * AnimateTree(). 'done' is set to FALSE if the tree is not in its | 488 * AnimateTree(). 'done' is set to FALSE if the tree is not in its |
512 * final position; it is used to determine when to stop animating the tree. | 489 * final position; it is used to determine when to stop animating the tree. |
513 * | 490 * |
514 * ---------------------------------------------------------------------------- | 491 * ---------------------------------------------------------------------------- |
515 */ | 492 */ |
516 | 493 |
517 void | 494 static void |
518 ShiftTree(tree, done) | 495 ShiftTree(Tree *tree, int *done) |
519 Tree *tree; | |
520 int *done; | |
521 { | 496 { |
522 Tree *child; | 497 Tree *child; |
523 | 498 |
524 if (tree->old_pos.x != tree->pos.x || | 499 if (tree->old_pos.x != tree->pos.x || |
525 tree->old_pos.y != tree->pos.y) | 500 tree->old_pos.y != tree->pos.y) |
526 { | 501 { |
527 tree->old_pos.x = tree->pos.x; | 502 tree->old_pos.x = tree->pos.x; |
528 tree->old_pos.y = tree->pos.y; | 503 tree->old_pos.y = tree->pos.y; |
529 } | 504 } |
530 | 505 |
531 FOREACH_CHILD(child, tree) | 506 FOREACH_CHILD(child, tree) |
532 ShiftTree(child, done); | 507 ShiftTree(child, done); |
533 } | 508 } |
534 | 509 |
535 | 510 |
536 /* ---------------------------------------------------------------------------- | 511 /* ---------------------------------------------------------------------------- |
537 * | 512 * |
538 * AnimateTree() draws the given tree in a series of steps to give the | 513 * AnimateTree() draws the given tree in a series of steps to give the |
539 * effect of animation from the "old" layout to the "new" layout of the | 514 * effect of animation from the "old" layout to the "new" layout of the |
540 * tree. | 515 * tree. |
541 * | 516 * |
542 * The algorithm used here is not efficient; the entire tree is drawn | 517 * The algorithm used here is not efficient; the entire tree is drawn |
543 * on each iteration of the animation sequence; it would be more efficient | 518 * on each iteration of the animation sequence; it would be more efficient |
544 * to only redraw what is necessary. However, the method used here takes | 519 * to only redraw what is necessary. However, the method used here takes |
545 * advantage of existing code without modification. | 520 * advantage of existing code without modification. |
546 * | 521 * |
547 * ---------------------------------------------------------------------------- | 522 * ---------------------------------------------------------------------------- |
548 */ | 523 */ |
549 | 524 |
550 void | 525 static void |
551 AnimateTree(tree) | 526 AnimateTree(Tree *tree) |
552 Tree *tree; | |
553 { | 527 { |
554 int done = FALSE; | 528 int done = FALSE; |
555 | 529 |
556 AnimationMode = FALSE; | 530 AnimationMode = FALSE; |
557 /* highlight which nodes have to move */ | 531 /* highlight which nodes have to move */ |
558 BeginFrame(); | 532 BeginFrame(); |
559 DrawTree(tree, Old); | 533 DrawTree(tree, Old); |
560 EndFrame(); | 534 EndFrame(); |
561 Pause(); | 535 Pause(); |
562 if (PauseAfterStep) | 536 if (PauseAfterStep) |
563 AnimationStep = ANIMATION_STEP_STEP; | 537 AnimationStep = ANIMATION_STEP_STEP; |
564 while (!done) { | 538 while (!done) { |
565 done = TRUE; | 539 done = TRUE; |
566 ShiftTree(tree, &done); | 540 ShiftTree(tree, &done); |
575 AnimationMode = FALSE; | 549 AnimationMode = FALSE; |
576 } | 550 } |
577 | 551 |
578 | 552 |
579 /* ---------------------------------------------------------------------------- | 553 /* ---------------------------------------------------------------------------- |
580 * | 554 * |
581 * AnimateZip() generates a sequence of frames that animates the Zip() step. | 555 * AnimateZip() generates a sequence of frames that animates the Zip() step. |
582 * It is similar in logical structure to Zip(). | 556 * It is similar in logical structure to Zip(). |
583 * | 557 * |
584 * ---------------------------------------------------------------------------- | 558 * ---------------------------------------------------------------------------- |
585 */ | 559 */ |
586 | 560 |
587 void | 561 static void |
588 AnimateZip(tree) | 562 AnimateZip(Tree *tree) |
589 Tree *tree; | |
590 { | 563 { |
591 Tree *child; | 564 Tree *child; |
592 | 565 |
593 /* show results of Join() step */ | 566 /* show results of Join() step */ |
594 if (tree->child) { | 567 if (tree->child) { |
595 BeginFrame(); | 568 BeginFrame(); |
596 FOREACH_CHILD(child, tree) | 569 FOREACH_CHILD(child, tree) |
597 child->split = FALSE; | 570 child->split = FALSE; |
598 DrawTree(TheTree, New); | 571 DrawTree(TheTree, New); |
599 DrawTreeContour(tree, New, CONTOUR_COLOR, TRUE, FALSE, FALSE); | 572 DrawTreeContour(tree, New, CONTOUR_COLOR, TRUE, FALSE, FALSE); |
600 EndFrame(); | 573 EndFrame(); |
601 | 574 |
602 StatusMsg("Zip: merge and join contours", FALSE); | 575 StatusMsg("Zip: merge and join contours", FALSE); |
603 Pause(); | 576 Pause(); |
604 | 577 |
605 /* show results of AttachParent() step */ | 578 /* show results of AttachParent() step */ |
606 BeginFrame(); | 579 BeginFrame(); |
607 DrawTree(TheTree, New); | 580 DrawTree(TheTree, New); |
608 DrawTreeContour(tree, New, CONTOUR_COLOR, FALSE, FALSE, FALSE); | 581 DrawTreeContour(tree, New, CONTOUR_COLOR, FALSE, FALSE, FALSE); |
609 EndFrame(); | 582 EndFrame(); |
610 | 583 |
611 StatusMsg("Zip: attach parents", FALSE); | 584 StatusMsg("Zip: attach parents", FALSE); |
612 Pause(); | 585 Pause(); |
613 } | 586 } |
614 | 587 |
615 tree->on_path = FALSE; | 588 tree->on_path = FALSE; |
616 | 589 |
617 if (tree->parent) | 590 if (tree->parent) |
618 AnimateZip(tree->parent); | 591 AnimateZip(tree->parent); |
619 else { | 592 else { |
620 tree->on_path = FALSE; | 593 tree->on_path = FALSE; |
621 BeginFrame(); | 594 BeginFrame(); |
622 DrawTree(TheTree, New); | 595 DrawTree(TheTree, New); |
623 DrawTreeContour(TheTree, New, CONTOUR_COLOR, FALSE, FALSE, FALSE); | 596 DrawTreeContour(TheTree, New, CONTOUR_COLOR, FALSE, FALSE, FALSE); |
624 EndFrame(); | 597 EndFrame(); |
625 StatusMsg("Zip: reassemble entire contour", FALSE); | 598 StatusMsg("Zip: reassemble entire contour", FALSE); |
626 Pause(); | 599 Pause(); |
627 } | 600 } |
628 } | 601 } |
629 | 602 |
630 | 603 |
631 /* ---------------------------------------------------------------------------- | 604 /* ---------------------------------------------------------------------------- |
632 * | 605 * |
633 * CountNodes() returns the number of nodes in the specified tree. | 606 * CountNodes() returns the number of nodes in the specified tree. |
634 * Nodes below a node that has been collapsed are ignored. | 607 * Nodes below a node that has been collapsed are ignored. |
635 * | 608 * |
636 * ---------------------------------------------------------------------------- | 609 * ---------------------------------------------------------------------------- |
637 */ | 610 */ |
638 | 611 |
639 int | 612 static int |
640 CountNodes(tree) | 613 CountNodes(Tree *tree) |
641 Tree *tree; | |
642 { | 614 { |
643 int num_nodes = 1; /* count root of subtree */ | 615 int num_nodes = 1; /* count root of subtree */ |
644 Tree *child; | 616 Tree *child; |
645 | 617 |
646 if (!tree->elision) { | 618 if (!tree->elision) { |
647 FOREACH_CHILD(child, tree) | 619 FOREACH_CHILD(child, tree) |
648 num_nodes += CountNodes(child); | 620 num_nodes += CountNodes(child); |
649 } | 621 } |
650 return (num_nodes); | 622 return (num_nodes); |
651 } | 623 } |
652 | 624 |
653 | 625 |
654 /* ---------------------------------------------------------------------------- | 626 /* ---------------------------------------------------------------------------- |
655 * | 627 * |
656 * CollectNodeRectangles() is a recursive function used by | 628 * CollectNodeRectangles() is a recursive function used by |
657 * GetSubTreeRectangles() to collect the rectangles of descendant nodes | 629 * GetSubTreeRectangles() to collect the rectangles of descendant nodes |
658 * into the pre-allocated storage passed to this function. | 630 * into the pre-allocated storage passed to this function. |
659 * | 631 * |
660 * ---------------------------------------------------------------------------- | 632 * ---------------------------------------------------------------------------- |
661 */ | 633 */ |
662 | 634 |
663 void | 635 static void |
664 CollectNodeRectangles(node, rectangles, fill) | 636 CollectNodeRectangles(Tree *node, XRectangle **rectangles, int fill) |
665 Tree *node; | |
666 XRectangle **rectangles; | |
667 int fill; | |
668 { | 637 { |
669 Tree *child; | 638 Tree *child; |
670 | 639 |
671 (*rectangles)->x = node->pos.x; | 640 (*rectangles)->x = node->pos.x; |
672 (*rectangles)->y = node->pos.y; | 641 (*rectangles)->y = node->pos.y; |
673 if (fill) { | 642 if (fill) { |
674 (*rectangles)->width = node->width + 1; | 643 (*rectangles)->width = node->width + 1; |
675 (*rectangles)->height = node->height + 1; | 644 (*rectangles)->height = node->height + 1; |
676 } else { | 645 } else { |
677 (*rectangles)->width = node->width; | 646 (*rectangles)->width = node->width; |
678 (*rectangles)->height = node->height; | 647 (*rectangles)->height = node->height; |
679 } | 648 } |
680 (*rectangles)++; | 649 (*rectangles)++; |
681 | 650 |
682 if (!node->elision) | 651 if (!node->elision) |
683 FOREACH_CHILD(child, node) | 652 FOREACH_CHILD(child, node) |
684 CollectNodeRectangles(child, rectangles, fill); | 653 CollectNodeRectangles(child, rectangles, fill); |
685 } | 654 } |
686 | 655 |
687 | 656 |
688 /* ---------------------------------------------------------------------------- | 657 /* ---------------------------------------------------------------------------- |
689 * | 658 * |
690 * GetSubTreeRectangles() builds an array of XRectangles that contain | 659 * GetSubTreeRectangles() builds an array of XRectangles that contain |
691 * all the node rectangles in the tree, except the root node itself. | 660 * all the node rectangles in the tree, except the root node itself. |
692 * The array is returned in 'rectangles' and the number of rectangles | 661 * The array is returned in 'rectangles' and the number of rectangles |
693 * is returned in 'nrectangles.' Storage for the rectangles is allocated | 662 * is returned in 'nrectangles.' Storage for the rectangles is allocated |
694 * in this function. This function is used by PickAction to determine | 663 * in this function. This function is used by PickAction to determine |
695 * what rectangles need to be dissolved away. 'fill', if True, specifies | 664 * what rectangles need to be dissolved away. 'fill', if True, specifies |
696 * that the rectangles should be 1 pixel larger in each dimension to | 665 * that the rectangles should be 1 pixel larger in each dimension to |
697 * compensate for FillRectangle behavior. | 666 * compensate for FillRectangle behavior. |
698 * | 667 * |
699 * ---------------------------------------------------------------------------- | 668 * ---------------------------------------------------------------------------- |
700 */ | 669 */ |
701 | 670 |
702 void | 671 static void |
703 GetSubTreeRectangles(tree, rectangles, nrectangles, fill) | 672 GetSubTreeRectangles(Tree *tree, XRectangle **rectangles, |
704 Tree *tree; | 673 int *nrectangles, int fill) |
705 XRectangle **rectangles; | |
706 int *nrectangles, fill; | |
707 { | 674 { |
708 Tree *child; | 675 Tree *child; |
709 XRectangle *crect; /* current rectangle */ | 676 XRectangle *crect; /* current rectangle */ |
710 | 677 |
711 *nrectangles = CountNodes(tree) - 1; /* don't count root node */ | 678 *nrectangles = CountNodes(tree) - 1; /* don't count root node */ |
712 *rectangles = (XRectangle *) malloc(sizeof(XRectangle) * *nrectangles); | 679 *rectangles = (XRectangle *) malloc(sizeof(XRectangle) * *nrectangles); |
713 ASSERT(*rectangles, "could not allocate memory for rectangles"); | 680 ASSERT(*rectangles, "could not allocate memory for rectangles"); |
714 | 681 |
715 crect = *rectangles; | 682 crect = *rectangles; |
716 if (!tree->elision) | 683 if (!tree->elision) |
717 FOREACH_CHILD(child, tree) | 684 FOREACH_CHILD(child, tree) |
718 CollectNodeRectangles(child, &crect, fill); | 685 CollectNodeRectangles(child, &crect, fill); |
719 } | 686 } |
720 | 687 |
721 | 688 |
722 /* ---------------------------------------------------------------------------- | 689 /* ---------------------------------------------------------------------------- |
723 * | 690 * |
724 * CollectNodeSegments() is a recursive function used by GetSubTreeSegments() | 691 * CollectNodeSegments() is a recursive function used by GetSubTreeSegments() |
725 * to collect the line segments connecting nodes into the pre-allocated | 692 * to collect the line segments connecting nodes into the pre-allocated |
726 * storage passed to this function. | 693 * storage passed to this function. |
727 * | 694 * |
728 * ---------------------------------------------------------------------------- | 695 * ---------------------------------------------------------------------------- |
729 */ | 696 */ |
730 | 697 |
731 void | 698 static void |
732 CollectNodeSegments(node, segments) | 699 CollectNodeSegments(Tree *node, XSegment **segments) |
733 Tree *node; | |
734 XSegment **segments; | |
735 { | 700 { |
736 Tree *child; | 701 Tree *child; |
737 | 702 |
738 (*segments)->x1 = node->pos.x - 1; | 703 (*segments)->x1 = node->pos.x - 1; |
739 (*segments)->y1 = node->pos.y + (node->height / 2), | 704 (*segments)->y1 = node->pos.y + (node->height / 2), |
740 (*segments)->x2 = node->parent->pos.x + node->parent->width + 1; | 705 (*segments)->x2 = node->parent->pos.x + node->parent->width + 1; |
741 (*segments)->y2 = node->parent->pos.y + (node->parent->height / 2); | 706 (*segments)->y2 = node->parent->pos.y + (node->parent->height / 2); |
742 (*segments)++; | 707 (*segments)++; |
743 | 708 |
744 if (!node->elision) | 709 if (!node->elision) |
745 FOREACH_CHILD(child, node) | 710 FOREACH_CHILD(child, node) |
746 CollectNodeSegments(child, segments); | 711 CollectNodeSegments(child, segments); |
747 } | 712 } |
748 | 713 |
749 | 714 |
750 /* ---------------------------------------------------------------------------- | 715 /* ---------------------------------------------------------------------------- |
751 * | 716 * |
752 * GetSubTreeSegments() builds an array of XSegments that contain | 717 * GetSubTreeSegments() builds an array of XSegments that contain |
753 * all the line segments connecting the nodes in the tree. The array is | 718 * all the line segments connecting the nodes in the tree. The array is |
754 * returned in 'segments' and the number of segments is returned in | 719 * returned in 'segments' and the number of segments is returned in |
755 * 'nsegments.' Storage for the segments is allocated in this function. | 720 * 'nsegments.' Storage for the segments is allocated in this function. |
756 * This function is used by PickAction to determine what line segments | 721 * This function is used by PickAction to determine what line segments |
757 * rectangles need to be dissolved away. | 722 * rectangles need to be dissolved away. |
758 * | 723 * |
759 * ---------------------------------------------------------------------------- | 724 * ---------------------------------------------------------------------------- |
760 */ | 725 */ |
761 | 726 |
762 void | 727 static void |
763 GetSubTreeSegments(tree, segments, nsegments) | 728 GetSubTreeSegments(Tree *tree, XSegment **segments, int *nsegments) |
764 Tree *tree; | |
765 XSegment **segments; | |
766 int *nsegments; | |
767 { | 729 { |
768 Tree *child; | 730 Tree *child; |
769 XSegment *cseg; /* current segment */ | 731 XSegment *cseg; /* current segment */ |
770 | 732 |
771 *nsegments = CountNodes(tree) - 1; | 733 *nsegments = CountNodes(tree) - 1; |
772 *segments = (XSegment *) malloc(sizeof(XSegment) * *nsegments); | 734 *segments = (XSegment *) malloc(sizeof(XSegment) * *nsegments); |
773 ASSERT(*segments, "could not allocate memory for segments"); | 735 ASSERT(*segments, "could not allocate memory for segments"); |
774 | 736 |
775 cseg = *segments; | 737 cseg = *segments; |
776 if (!tree->elision) | 738 if (!tree->elision) |
777 FOREACH_CHILD(child, tree) | 739 FOREACH_CHILD(child, tree) |
778 CollectNodeSegments(child, &cseg); | 740 CollectNodeSegments(child, &cseg); |
779 } | 741 } |
780 | 742 |
781 | 743 |
782 /* ---------------------------------------------------------------------------- | 744 /* ---------------------------------------------------------------------------- |
783 * | 745 * |
784 * ComputeSubTreeExtent() computes the extent of a subtree. This is | 746 * ComputeSubTreeExtent() computes the extent of a subtree. This is |
785 * easily computed based on the tree's contour, as in ComputeTreeSize(). | 747 * easily computed based on the tree's contour, as in ComputeTreeSize(). |
786 * This extent is stored in the node, and used by SearchTree for | 748 * This extent is stored in the node, and used by SearchTree for |
787 * pick-correlation. | 749 * pick-correlation. |
788 * | 750 * |
789 * This function assumes that the given tree has at least one child; do not | 751 * This function assumes that the given tree has at least one child; do not |
790 * pass a leaf node to this function. | 752 * pass a leaf node to this function. |
791 * | 753 * |
792 * ---------------------------------------------------------------------------- | 754 * ---------------------------------------------------------------------------- |
793 */ | 755 */ |
794 | 756 |
795 void | 757 void |
796 ComputeSubTreeExtent(tree) | 758 ComputeSubTreeExtent(Tree *tree) |
797 Tree *tree; | |
798 { | 759 { |
799 int width, height; | 760 int width, height; |
800 int x_offset, y_offset; | 761 int x_offset, y_offset; |
801 | 762 |
802 ComputeTreeSize(tree, &width, &height, &x_offset, &y_offset); | 763 ComputeTreeSize(tree, &width, &height, &x_offset, &y_offset); |
806 tree->subextent.height = height - 1; | 767 tree->subextent.height = height - 1; |
807 } | 768 } |
808 | 769 |
809 | 770 |
810 /* ---------------------------------------------------------------------------- | 771 /* ---------------------------------------------------------------------------- |
811 * | 772 * |
812 * SearchTree() determines if a node's rectangular region encloses the | 773 * SearchTree() determines if a node's rectangular region encloses the |
813 * specified point in (x,y). Rather than using a brute-force search | 774 * specified point in (x,y). Rather than using a brute-force search |
814 * through all node rectangles of a given tree, the subtree extents | 775 * through all node rectangles of a given tree, the subtree extents |
815 * are used in a recursive fashion to drive the search as long as the | 776 * are used in a recursive fashion to drive the search as long as the |
816 * given point is enclosed in an extent. In the worst case, the search | 777 * given point is enclosed in an extent. In the worst case, the search |
817 * time would be on the order of a brute-force search, but with complex | 778 * time would be on the order of a brute-force search, but with complex |
818 * trees, this method reduces the number of visits. | 779 * trees, this method reduces the number of visits. |
819 * | 780 * |
820 * The extent of a subtree is computed by ComputeSubTreeExtent() and is | 781 * The extent of a subtree is computed by ComputeSubTreeExtent() and is |
821 * stored in each node of the tree. | 782 * stored in each node of the tree. |
822 * | 783 * |
823 * ---------------------------------------------------------------------------- | 784 * ---------------------------------------------------------------------------- |
824 */ | 785 */ |
825 | 786 |
826 int | 787 int |
827 SearchTree(tree, x, y, node) | 788 SearchTree(Tree *tree, int x, int y, Tree **node) |
828 Tree *tree, **node; | |
829 int x, y; | |
830 { | 789 { |
831 Tree *child; | 790 Tree *child; |
832 | 791 |
833 if (tree == NULL) | 792 if (tree == NULL) |
834 return (FALSE); | 793 return (FALSE); |
835 | 794 |
836 if (PT_IN_RECT(x, y, tree->pos.x, tree->pos.y, | 795 if (PT_IN_RECT(x, y, tree->pos.x, tree->pos.y, |
837 tree->pos.x + tree->width, | 796 tree->pos.x + tree->width, |
838 tree->pos.y + tree->height)) { | 797 tree->pos.y + tree->height)) { |
839 *node = tree; | 798 *node = tree; |
840 return (TRUE); | 799 return (TRUE); |
841 } | 800 } |
842 if (tree->child && (PT_IN_EXTENT(x, y, tree->subextent))) | 801 if (tree->child && (PT_IN_EXTENT(x, y, tree->subextent))) |
843 FOREACH_CHILD(child, tree) { | 802 FOREACH_CHILD(child, tree) { |
844 if (SearchTree(child, x, y, node)) | 803 if (SearchTree(child, x, y, node)) |
845 return (TRUE); | 804 return (TRUE); |
846 } | 805 } |
847 return (FALSE); | 806 return (FALSE); |
848 } | 807 } |
849 | 808 |
850 | 809 |
851 /* ---------------------------------------------------------------------------- | 810 /* ---------------------------------------------------------------------------- |
852 * | 811 * |
853 * ExposeHandler() handles expose events in the TreeDrawingArea. This | 812 * ExposeHandler() handles expose events in the TreeDrawingArea. This |
854 * function is not intelligent; it just redraws the entire contents. | 813 * function is not intelligent; it just redraws the entire contents. |
855 * | 814 * |
856 * ---------------------------------------------------------------------------- | 815 * ---------------------------------------------------------------------------- |
857 */ | 816 */ |
858 | 817 |
859 void | 818 void |
860 ExposeHandler(w, client_data, event) | 819 ExposeHandler(Widget w, XtPointer closure, |
861 Widget w; | 820 XEvent *event, Boolean *continue_to_dispatch) |
862 caddr_t client_data; | 821 { |
863 XExposeEvent *event; | 822 if (event->xexpose.count == 0) { |
864 { | |
865 | |
866 if (event->count == 0) { | |
867 BeginFrame(); | 823 BeginFrame(); |
868 SetContours(TreeShowContourOption); | 824 SetContours(TreeShowContourOption); |
869 DrawTree(TheTree, New); | 825 DrawTree(TheTree, New); |
870 EndFrame(); | 826 EndFrame(); |
871 } | 827 } |
872 } | 828 } |
873 | 829 |
874 | 830 |
875 /* ---------------------------------------------------------------------------- | 831 /* ---------------------------------------------------------------------------- |
876 * | 832 * |
877 * ExpandCollapseNode is called to expand or collapse a node in the tree. | 833 * ExpandCollapseNode is called to expand or collapse a node in the tree. |
878 * | 834 * |
879 * ---------------------------------------------------------------------------- | 835 * ---------------------------------------------------------------------------- |
880 */ | 836 */ |
881 | 837 |
882 void | 838 void |
883 ExpandCollapseNode(node) | 839 ExpandCollapseNode(Tree *node) |
884 Tree *node; | |
885 { | 840 { |
886 int width, height; | 841 int width, height; |
887 int old_width, old_height; | 842 int old_width, old_height; |
888 int x_offset, y_offset; | 843 int x_offset, y_offset; |
889 XRectangle *rectangles; | 844 XRectangle *rectangles; |
890 XSegment *segments; | 845 XSegment *segments; |
891 int nrectangles, nsegments; | 846 int nrectangles, nsegments; |
892 int expand = FALSE; | 847 int expand = FALSE; |
893 Widget w = TreeDrawingArea; | 848 Widget w = TreeDrawingArea; |
894 | 849 |
895 StatusMsg("", TRUE); | 850 StatusMsg("", TRUE); |
896 | 851 |
897 /* hilite node so that we know where we are */ | 852 /* hilite node so that we know where we are */ |
898 /* DrawTree will hilite it as a side effect */ | 853 /* DrawTree will hilite it as a side effect */ |
899 if (TreeShowSteps) | 854 if (TreeShowSteps) |
900 node->on_path = TRUE; | 855 node->on_path = TRUE; |
901 | 856 |
902 /* erase the contour before changing in the tree */ | 857 /* erase the contour before changing in the tree */ |
903 if ((TreeShowContourOption != NoContours) || TreeShowSteps) { | 858 if ((TreeShowContourOption != NoContours) || TreeShowSteps) { |
904 BeginFrame(); | 859 BeginFrame(); |
905 DrawTree(TheTree, New); | 860 DrawTree(TheTree, New); |
906 EndFrame(); | 861 EndFrame(); |
907 } | 862 } |
908 | 863 |
909 sprintf(strbuf, "Node `%s' selected for %s", node->label.text, | 864 sprintf(strbuf, "Node `%s' selected for %s", node->label.text, |
910 node->elision ? "expansion" : "collapse"); | 865 node->elision ? "expansion" : "collapse"); |
911 StatusMsg(strbuf, FALSE); | 866 StatusMsg(strbuf, FALSE); |
912 Pause(); | 867 Pause(); |
913 | 868 |
914 if (node->parent) | 869 if (node->parent) |
915 Unzip(node->parent); | 870 Unzip(node->parent); |
916 else { | 871 else { |
917 StatusMsg("Show entire contour", FALSE); | 872 StatusMsg("Show entire contour", FALSE); |
918 if (TreeShowSteps) { | 873 if (TreeShowSteps) { |
919 BeginFrame(); | 874 BeginFrame(); |
920 DrawTreeContour(TheTree, New, CONTOUR_COLOR, FALSE, FALSE, FALSE); | 875 DrawTreeContour(TheTree, New, CONTOUR_COLOR, FALSE, FALSE, FALSE); |
921 DrawTree(TheTree, New); | 876 DrawTree(TheTree, New); |
922 EndFrame(); | 877 EndFrame(); |
923 Pause(); | 878 Pause(); |
924 } | 879 } |
925 } | 880 } |
926 | 881 |
927 /* are we collapsing a subtree? */ | 882 /* are we collapsing a subtree? */ |
928 if (!node->elision) { | 883 if (!node->elision) { |
932 DissolveTree(XtDisplay(w), XtWindow(w), | 887 DissolveTree(XtDisplay(w), XtWindow(w), |
933 rectangles, nrectangles, | 888 rectangles, nrectangles, |
934 segments, nsegments, TRUE); | 889 segments, nsegments, TRUE); |
935 free(rectangles); | 890 free(rectangles); |
936 free(segments); | 891 free(segments); |
937 Pause(); | 892 Pause(); |
938 | 893 |
939 StatusMsg("Replace subtree contour with leaf contour", FALSE); | 894 StatusMsg("Replace subtree contour with leaf contour", FALSE); |
940 node->elision = TRUE; | 895 node->elision = TRUE; |
941 if (TreeShowSteps) | 896 if (TreeShowSteps) |
942 node->split = TRUE; /* turned off in AnimateZip */ | 897 node->split = TRUE; /* turned off in AnimateZip */ |
943 node->old_contour = node->contour; | 898 node->old_contour = node->contour; |
945 LayoutLeaf(node); | 900 LayoutLeaf(node); |
946 BeginFrame(); | 901 BeginFrame(); |
947 SetContours(TreeShowContourOption); | 902 SetContours(TreeShowContourOption); |
948 DrawTree(TheTree, New); | 903 DrawTree(TheTree, New); |
949 EndFrame(); | 904 EndFrame(); |
950 Pause(); | 905 Pause(); |
951 } else { | 906 } else { |
952 StatusMsg("Replace leaf contour with old subtree contour", FALSE); | 907 StatusMsg("Replace leaf contour with old subtree contour", FALSE); |
953 if (TreeShowSteps) | 908 if (TreeShowSteps) |
954 node->split = TRUE; /* turned off in AnimateZip */ | 909 node->split = TRUE; /* turned off in AnimateZip */ |
955 RuboutLeaf(node); | 910 RuboutLeaf(node); |
956 node->contour = node->old_contour; | 911 node->contour = node->old_contour; |
957 expand = TRUE; | 912 expand = TRUE; |
958 } | 913 } |
959 | 914 |
960 if (node->parent) | 915 if (node->parent) |
961 Zip(node->parent); | 916 Zip(node->parent); |
962 | 917 |
963 ComputeTreeSize(TheTree, &width, &height, &x_offset, &y_offset); | 918 ComputeTreeSize(TheTree, &width, &height, &x_offset, &y_offset); |
964 PetrifyTree(TheTree, x_offset + MAT_SIZE, y_offset + MAT_SIZE); | 919 PetrifyTree(TheTree, x_offset + MAT_SIZE, y_offset + MAT_SIZE); |
965 GetDrawingSize(&old_width, &old_height); | 920 GetDrawingSize(&old_width, &old_height); |
966 | 921 |
967 if (expand) { | 922 if (expand) { |
968 SetDrawingSize(width + (2 * MAT_SIZE), height + (2 * MAT_SIZE)); | 923 SetDrawingSize(width + (2 * MAT_SIZE), height + (2 * MAT_SIZE)); |
969 BeginFrame(); | 924 BeginFrame(); |
970 DrawTree(TheTree, Old); | 925 DrawTree(TheTree, Old); |
971 EndFrame(); | 926 EndFrame(); |
972 Pause(); | 927 Pause(); |
973 StatusMsg("Move tree to new configuration", FALSE); | 928 StatusMsg("Move tree to new configuration", FALSE); |
974 AnimateTree(TheTree); | 929 AnimateTree(TheTree); |
975 } else { | 930 } else { |
976 /* we are shrinking or staying the same */ | 931 /* we are shrinking or staying the same */ |
977 StatusMsg("Move tree to new configuration", FALSE); | 932 StatusMsg("Move tree to new configuration", FALSE); |
980 } | 935 } |
981 | 936 |
982 if (expand) { | 937 if (expand) { |
983 StatusMsg("Expand subtree", FALSE); | 938 StatusMsg("Expand subtree", FALSE); |
984 node->elision = FALSE; | 939 node->elision = FALSE; |
985 | 940 |
986 /* erase elision marker */ | 941 /* erase elision marker */ |
987 XSetFunction(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, | 942 XSetFunction(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, |
988 GXclear); | 943 GXclear); |
989 XFillRectangle(XtDisplay(w), XtWindow(w), TreeDrawingAreaDB->gc, | 944 XFillRectangle(XtDisplay(w), XtWindow(w), TreeDrawingAreaDB->gc, |
990 node->pos.x + node->width - ELISION_WIDTH + 1, | 945 node->pos.x + node->width - ELISION_WIDTH + 1, |
991 node->pos.y, ELISION_WIDTH, node->height + 1); | 946 node->pos.y, ELISION_WIDTH, node->height + 1); |
992 XSetFunction(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, | 947 XSetFunction(TreeDrawingAreaDB->display, TreeDrawingAreaDB->gc, |
993 GXcopy); | 948 GXcopy); |
994 node->width -= ELISION_WIDTH; | 949 node->width -= ELISION_WIDTH; |
995 | 950 |
996 GetSubTreeRectangles(node, &rectangles, &nrectangles, FALSE); | 951 GetSubTreeRectangles(node, &rectangles, &nrectangles, FALSE); |
997 GetSubTreeSegments(node, &segments, &nsegments); | 952 GetSubTreeSegments(node, &segments, &nsegments); |
998 /* dissolve the tree back in */ | 953 /* dissolve the tree back in */ |
999 DissolveTree(XtDisplay(w), XtWindow(w), | 954 DissolveTree(XtDisplay(w), XtWindow(w), |
1000 rectangles, nrectangles, | 955 rectangles, nrectangles, |
1001 segments, nsegments, FALSE); | 956 segments, nsegments, FALSE); |
1002 free(rectangles); | 957 free(rectangles); |
1003 free(segments); | 958 free(segments); |
1004 | 959 |
1005 /* draw text of nodes */ | 960 /* draw text of nodes */ |
1006 BeginFrame(); | 961 BeginFrame(); |
1007 SetContours(TreeShowContourOption); | 962 SetContours(TreeShowContourOption); |
1008 DrawTree(TheTree, New); | 963 DrawTree(TheTree, New); |
1009 EndFrame(); | 964 EndFrame(); |
1010 Pause(); | 965 Pause(); |
1011 } | 966 } |
1012 | 967 |
1013 if (TreeShowSteps) { | 968 if (TreeShowSteps) { |
1014 node->on_path = FALSE; | 969 node->on_path = FALSE; |
1015 if (node->parent) | 970 if (node->parent) |
1016 AnimateZip(node->parent); | 971 AnimateZip(node->parent); |
1017 else | 972 else |
1018 node->split = FALSE; | 973 node->split = FALSE; |
1019 } | 974 } |
1020 | 975 |
1021 /* BUG: the display isn't properly updated here! */ | 976 /* BUG: the display isn't properly updated here! */ |
1022 /* There should probably be some code here that | 977 /* There should probably be some code here that |
1023 clears the tree below the node currently being | 978 clears the tree below the node currently being |
1024 collapsed or expanded. Hack added 20.03.95 (torgeir@ii.uib.no). | 979 collapsed or expanded. Hack added 20.03.95 (torgeir@ii.uib.no). |
1025 I'll try to fix this later. */ | 980 I'll try to fix this later. */ |
1026 | 981 |
1027 XClearArea(TreeDisplay, XtWindow(TreeDrawingArea), 0, 0, 0, 0, FALSE); | 982 XClearArea(TreeDisplay, XtWindow(TreeDrawingArea), 0, 0, 0, 0, FALSE); |
1028 | 983 |
1029 BeginFrame(); | 984 BeginFrame(); |
1030 SetContours(TreeShowContourOption); | 985 SetContours(TreeShowContourOption); |
1031 DrawTree(TheTree, New); | 986 DrawTree(TheTree, New); |
1032 EndFrame(); | 987 EndFrame(); |
1033 | 988 |
1034 StatusMsg("Ready", TRUE); | 989 StatusMsg("Ready", TRUE); |
1035 } | 990 } |
1036 | 991 |
1037 /* ---------------------------------------------------------------------------- | 992 /* ---------------------------------------------------------------------------- |
1038 * | 993 * |
1039 * InsertNode() handles the task of inserting a new node in the tree, | 994 * InsertNode() handles the task of inserting a new node in the tree, |
1040 * at the given position with respect to 'base_node'. When 'node_pos' is | 995 * at the given position with respect to 'base_node'. When 'node_pos' is |
1041 * either Before or After, it is assumed that 'base_node' has a parent. | 996 * either Before or After, it is assumed that 'base_node' has a parent. |
1042 * | 997 * |
1043 * ---------------------------------------------------------------------------- | 998 * ---------------------------------------------------------------------------- |
1044 */ | 999 */ |
1045 | 1000 |
1046 void | 1001 void |
1047 InsertNode(base_node, node_pos, new_node_text) | 1002 InsertNode(Tree *base_node, NodePosition node_pos, char *new_node_text) |
1048 Tree *base_node; | |
1049 NodePosition node_pos; | |
1050 char *new_node_text; | |
1051 { | 1003 { |
1052 Tree *new_node; | 1004 Tree *new_node; |
1053 Tree *parent; | 1005 Tree *parent; |
1054 Tree *sibling = NULL; | 1006 Tree *sibling = NULL; |
1055 Tree *child; | 1007 Tree *child; |
1077 FOREACH_CHILD(child, parent) | 1029 FOREACH_CHILD(child, parent) |
1078 if (child->sibling == base_node) { | 1030 if (child->sibling == base_node) { |
1079 sibling = child; | 1031 sibling = child; |
1080 break; | 1032 break; |
1081 } | 1033 } |
1034 } else { | |
1035 parent = NULL; | |
1036 abort(); | |
1082 } | 1037 } |
1083 | 1038 |
1084 if (TreeShowSteps) | 1039 if (TreeShowSteps) |
1085 parent->on_path = TRUE; | 1040 parent->on_path = TRUE; |
1086 | 1041 |
1087 if ((TreeShowContourOption != NoContours) || | 1042 if ((TreeShowContourOption != NoContours) || |
1088 TreeShowSteps) { | 1043 TreeShowSteps) { |
1089 BeginFrame(); | 1044 BeginFrame(); |
1090 DrawTree(TheTree, New); | 1045 DrawTree(TheTree, New); |
1091 EndFrame(); | 1046 EndFrame(); |
1092 } | 1047 } |
1093 | 1048 |
1094 sprintf(strbuf, "Inserting `%s' as child of node `%s'", | 1049 sprintf(strbuf, "Inserting `%s' as child of node `%s'", |
1095 new_node_text, parent->label.text); | 1050 new_node_text, parent->label.text); |
1096 StatusMsg(strbuf, FALSE); | 1051 StatusMsg(strbuf, FALSE); |
1097 Pause(); | 1052 Pause(); |
1098 | 1053 |
1099 /* erase the contour before changing in the tree */ | 1054 /* erase the contour before changing in the tree */ |
1100 | 1055 |
1101 Insert(parent, new_node, sibling); | 1056 Insert(parent, new_node, sibling); |
1102 | 1057 |
1103 ComputeTreeSize(TheTree, &width, &height, &x_offset, &y_offset); | 1058 ComputeTreeSize(TheTree, &width, &height, &x_offset, &y_offset); |
1104 PetrifyTree(TheTree, x_offset + MAT_SIZE, y_offset + MAT_SIZE); | 1059 PetrifyTree(TheTree, x_offset + MAT_SIZE, y_offset + MAT_SIZE); |
1105 | 1060 |
1106 if (sibling) | 1061 if (sibling) |
1107 new_node->old_pos = sibling->old_pos; | 1062 new_node->old_pos = sibling->old_pos; |
1108 else if (new_node->sibling) | 1063 else if (new_node->sibling) |
1109 new_node->old_pos = new_node->sibling->old_pos; | 1064 new_node->old_pos = new_node->sibling->old_pos; |
1110 else { | 1065 else { |
1111 new_node->old_pos.x = new_node->pos.x; | 1066 new_node->old_pos.x = new_node->pos.x; |
1112 new_node->old_pos.y = parent->old_pos.y; | 1067 new_node->old_pos.y = parent->old_pos.y; |
1113 } | 1068 } |
1114 | 1069 |
1115 if (TreeShowSteps) | 1070 if (TreeShowSteps) |
1116 new_node->split = TRUE; | 1071 new_node->split = TRUE; |
1117 | 1072 |
1118 SetDrawingSize(width + (2 * MAT_SIZE), height + (2 * MAT_SIZE)); | 1073 SetDrawingSize(width + (2 * MAT_SIZE), height + (2 * MAT_SIZE)); |
1119 BeginFrame(); | 1074 BeginFrame(); |
1120 DrawTree(TheTree, Old); | 1075 DrawTree(TheTree, Old); |
1121 EndFrame(); | 1076 EndFrame(); |
1122 StatusMsg("Insert: add new node and contour", FALSE); | 1077 StatusMsg("Insert: add new node and contour", FALSE); |
1123 Pause(); | 1078 Pause(); |
1124 | 1079 |
1125 StatusMsg("Move tree to new configuration", FALSE); | 1080 StatusMsg("Move tree to new configuration", FALSE); |
1126 AnimateTree(TheTree); | 1081 AnimateTree(TheTree); |
1127 | 1082 |
1128 if (TreeShowSteps) { | 1083 if (TreeShowSteps) { |
1129 if (parent) | 1084 if (parent) |
1134 SetContours(TreeShowContourOption); | 1089 SetContours(TreeShowContourOption); |
1135 DrawTree(TheTree, New); | 1090 DrawTree(TheTree, New); |
1136 EndFrame(); | 1091 EndFrame(); |
1137 | 1092 |
1138 StatusMsg("Ready", TRUE); | 1093 StatusMsg("Ready", TRUE); |
1139 } | 1094 } |
1140 | 1095 |
1141 /* ---------------------------------------------------------------------------- | 1096 /* ---------------------------------------------------------------------------- |
1142 * | 1097 * |
1143 * DeleteNode() handles the task of deleting a given node in the tree. | 1098 * DeleteNode() handles the task of deleting a given node in the tree. |
1144 * | 1099 * |
1145 * ---------------------------------------------------------------------------- | 1100 * ---------------------------------------------------------------------------- |
1146 */ | 1101 */ |
1147 | 1102 |
1148 void | 1103 void |
1149 DeleteNode(node) | 1104 DeleteNode(Tree *node) |
1150 Tree *node; | |
1151 { | 1105 { |
1152 Tree *parent; | 1106 Tree *parent; |
1153 | 1107 |
1154 XRectangle *rectangles; | 1108 XRectangle *rectangles; |
1155 XSegment *segments; | 1109 XSegment *segments; |
1156 int nrectangles, nsegments; | 1110 int nrectangles, nsegments; |
1157 Widget w = TreeDrawingArea; | 1111 Widget w = TreeDrawingArea; |
1158 int width, height; | 1112 int width, height; |
1159 int x_offset, y_offset; | 1113 int x_offset, y_offset; |
1160 | 1114 |
1161 StatusMsg("", TRUE); | 1115 StatusMsg("", TRUE); |
1162 | 1116 |
1163 if (TreeShowSteps) | 1117 if (TreeShowSteps) |
1164 node->on_path = TRUE; | 1118 node->on_path = TRUE; |
1165 | 1119 |
1166 /* erase the contour before changing in the tree */ | 1120 /* erase the contour before changing in the tree */ |
1167 if ((TreeShowContourOption != NoContours) || | 1121 if ((TreeShowContourOption != NoContours) || |
1168 TreeShowSteps) { | 1122 TreeShowSteps) { |
1169 BeginFrame(); | 1123 BeginFrame(); |
1170 DrawTree(TheTree, New); | 1124 DrawTree(TheTree, New); |
1171 EndFrame(); | 1125 EndFrame(); |
1172 } | 1126 } |
1173 | 1127 |
1174 sprintf(strbuf, "Node `%s' selected for deletion", node->label.text); | 1128 sprintf(strbuf, "Node `%s' selected for deletion", node->label.text); |
1175 StatusMsg(strbuf, FALSE); | 1129 StatusMsg(strbuf, FALSE); |
1176 Pause(); | 1130 Pause(); |
1177 | 1131 |
1178 parent = node->parent; | 1132 parent = node->parent; |
1179 | 1133 |
1180 if (parent) | 1134 if (parent) |
1181 Unzip(parent); | 1135 Unzip(parent); |
1182 else | 1136 else |
1183 TheTree = NULL; /* delete root of tree */ | 1137 TheTree = NULL; /* delete root of tree */ |
1184 | 1138 |
1193 free(segments); | 1147 free(segments); |
1194 | 1148 |
1195 Delete(node); | 1149 Delete(node); |
1196 | 1150 |
1197 BeginFrame(); | 1151 BeginFrame(); |
1198 if (TheTree) | 1152 if (TheTree) |
1199 DrawTree(TheTree, New); | 1153 DrawTree(TheTree, New); |
1200 EndFrame(); | 1154 EndFrame(); |
1201 Pause(); | 1155 Pause(); |
1202 | 1156 |
1203 if (parent) | 1157 if (parent) |
1204 Zip(parent); | 1158 Zip(parent); |
1205 | 1159 |
1206 if (TheTree) { | 1160 if (TheTree) { |
1207 ComputeTreeSize(TheTree, &width, &height, &x_offset, &y_offset); | 1161 ComputeTreeSize(TheTree, &width, &height, &x_offset, &y_offset); |
1208 PetrifyTree(TheTree, x_offset + MAT_SIZE, y_offset + MAT_SIZE); | 1162 PetrifyTree(TheTree, x_offset + MAT_SIZE, y_offset + MAT_SIZE); |
1209 StatusMsg("Move tree to new configuration", FALSE); | 1163 StatusMsg("Move tree to new configuration", FALSE); |
1210 AnimateTree(TheTree); | 1164 AnimateTree(TheTree); |
1211 SetDrawingSize(width + (2 * MAT_SIZE), height + (2 * MAT_SIZE)); | 1165 SetDrawingSize(width + (2 * MAT_SIZE), height + (2 * MAT_SIZE)); |
1212 Pause(); | 1166 Pause(); |
1213 | 1167 |
1214 if (TreeShowSteps) { | 1168 if (TreeShowSteps) { |
1215 if (parent) | 1169 if (parent) |
1216 AnimateZip(parent); | 1170 AnimateZip(parent); |
1217 } | 1171 } |
1226 StatusMsg("Ready", TRUE); | 1180 StatusMsg("Ready", TRUE); |
1227 } | 1181 } |
1228 | 1182 |
1229 | 1183 |
1230 /* ---------------------------------------------------------------------------- | 1184 /* ---------------------------------------------------------------------------- |
1231 * | 1185 * |
1232 * ResetLabels() is called when the TreeAlignNodes mode is changed. | 1186 * ResetLabels() is called when the TreeAlignNodes mode is changed. |
1233 * When TreeParentDistance changes, the node width changes, so this | 1187 * When TreeParentDistance changes, the node width changes, so this |
1234 * function forces each node's width to be recomputed. | 1188 * function forces each node's width to be recomputed. |
1235 * | 1189 * |
1236 * ---------------------------------------------------------------------------- | 1190 * ---------------------------------------------------------------------------- |
1237 */ | 1191 */ |
1238 | 1192 |
1239 ResetLabels(tree) | 1193 void |
1240 Tree *tree; | 1194 ResetLabels(Tree *tree) |
1241 { | 1195 { |
1242 Tree *child; | 1196 Tree *child; |
1243 | 1197 |
1244 SetNodeLabel(tree, tree->label.text); | 1198 SetNodeLabel(tree, tree->label.text); |
1245 FOREACH_CHILD(child, tree) | 1199 FOREACH_CHILD(child, tree) |
1246 ResetLabels(child); | 1200 ResetLabels(child); |
1247 } | 1201 } |
1248 | 1202 |
1249 | 1203 |
1250 /* ---------------------------------------------------------------------------- | 1204 /* ---------------------------------------------------------------------------- |
1251 * | 1205 * |
1252 * SetupTree() handles the task of setting up the specified tree in | 1206 * SetupTree() handles the task of setting up the specified tree in |
1253 * the drawing area. | 1207 * the drawing area. |
1254 * | 1208 * |
1255 * ---------------------------------------------------------------------------- | 1209 * ---------------------------------------------------------------------------- |
1256 */ | 1210 */ |
1257 | 1211 |
1258 void | 1212 void |
1259 SetupTree(tree) | 1213 SetupTree(Tree *tree) |
1260 Tree *tree; | |
1261 { | 1214 { |
1262 int width, height; | 1215 int width, height; |
1263 int x_offset, y_offset; | 1216 int x_offset, y_offset; |
1264 | 1217 |
1265 LayoutTree(tree); | 1218 LayoutTree(tree); |
1266 ComputeTreeSize(tree, &width, &height, &x_offset, &y_offset); | 1219 ComputeTreeSize(tree, &width, &height, &x_offset, &y_offset); |
1267 PetrifyTree(tree, x_offset + MAT_SIZE, y_offset + MAT_SIZE); | 1220 PetrifyTree(tree, x_offset + MAT_SIZE, y_offset + MAT_SIZE); |
1268 SetDrawingTree(tree); | 1221 SetDrawingTree(tree); |
1269 SetDrawingSize(width + (2 * MAT_SIZE), height + (2 * MAT_SIZE)); | 1222 SetDrawingSize(width + (2 * MAT_SIZE), height + (2 * MAT_SIZE)); |
1270 BeginFrame(); | 1223 BeginFrame(); |
1271 SetContours(TreeShowContourOption); | 1224 SetContours(TreeShowContourOption); |
1272 DrawTree(tree, New); | 1225 DrawTree(tree, New); |
1273 EndFrame(); | 1226 EndFrame(); |
1274 } | 1227 } |
1275 | |
1276 | |
1277 | |
1278 | |
1279 | |
1280 |