comparison pkg-src/tree-x/tree.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
7 #include "defs.h" 7 #include "defs.h"
8 #include "tree.h" 8 #include "tree.h"
9 #include "dbl.h" 9 #include "dbl.h"
10 #include "intf.h" 10 #include "intf.h"
11 #include <string.h> 11 #include <string.h>
12 #include <stdlib.h>
12 13
13 /* ------------------------------------------------------------------------- */ 14 /* ------------------------------------------------------------------------- */
14 /* Global Variables */ 15 /* Global Variables */
15 /* ------------------------------------------------------------------------- */ 16 /* ------------------------------------------------------------------------- */
16 17
17 int NumLines = 0; 18 static int NumLines = 0;
18 int NumNodes = 0; 19 static int NumNodes = 0;
19 20
20 21
21 /* ---------------------------------------------------------------------------- 22 /* ----------------------------------------------------------------------------
22 * 23 *
23 * MakeLine() allocates the memory required for a Polyline and 24 * MakeLine() allocates the memory required for a Polyline and
24 * initializes the fields of a Polyline to the arguments. The 25 * initializes the fields of a Polyline to the arguments. The
25 * newly-allocated Polyline is returned by the function. 26 * newly-allocated Polyline is returned by the function.
26 * 27 *
27 * ---------------------------------------------------------------------------- 28 * ----------------------------------------------------------------------------
28 */ 29 */
29 30
30 Polyline* 31 Polyline*
31 MakeLine(dx, dy, link) 32 MakeLine(short dx, short dy, Polyline *line)
32 short dx; 33 {
33 short dy; 34 Polyline *new_line = (Polyline *) malloc(sizeof(Polyline));
34 Polyline *link; 35
35 { 36 NASSERT(new_line, "could not allocate memory for polyline");
36 Polyline *new;
37
38 new = (Polyline *) malloc(sizeof(Polyline));
39 NASSERT(new, "could not allocate memory for polyline");
40 NumLines++; 37 NumLines++;
41 38
42 new->dx = dx; 39 new_line->dx = dx;
43 new->dy = dy; 40 new_line->dy = dy;
44 new->link = link; 41 new_line->link = line;
45 42
46 return (new); 43 return new_line;
47 } 44 }
48 45
49 /* ---------------------------------------------------------------------------- 46 /* ----------------------------------------------------------------------------
50 * 47 *
51 * MakeNode() allocates the memory required for a tree node, and 48 * MakeNode() allocates the memory required for a tree node, and
52 * zeros out all the fields in the Node. It returns a pointer to the 49 * zeros out all the fields in the Node. It returns a pointer to the
53 * tree node upon success, and NULL upon failure. 50 * tree node upon success, and NULL upon failure.
54 * 51 *
55 * ---------------------------------------------------------------------------- 52 * ----------------------------------------------------------------------------
56 */ 53 */
57 54
58 Tree* 55 Tree*
59 MakeNode() 56 MakeNode(void)
60 { 57 {
61 Tree *node; 58 Tree *node = (Tree *) malloc(sizeof(Tree));
62 59
63 node = (Tree *) malloc(sizeof(Tree));
64 NASSERT(node, "could not allocate memory for node"); 60 NASSERT(node, "could not allocate memory for node");
65 NumNodes++; 61 NumNodes++;
66 62
67 if (node == NULL) 63 if (node == NULL)
68 return (NULL); 64 return (NULL);
69 else { 65 else {
70 #ifdef SYSV 66 memset((char *) node, 0, sizeof(Tree));
71 memset((char *) node, 0, sizeof(Tree)); 67 return (node);
72 #else 68 }
73 bzero((char *) node, sizeof(Tree)); 69 }
74 #endif 70
75 return (node); 71 /* ----------------------------------------------------------------------------
76 } 72 *
77 }
78
79 /* ----------------------------------------------------------------------------
80 *
81 * MakeBridge() 73 * MakeBridge()
82 * 74 *
83 * ---------------------------------------------------------------------------- 75 * ----------------------------------------------------------------------------
84 */ 76 */
85 77
86 Polyline* 78 static Polyline*
87 MakeBridge(line1, x1, y1, line2, x2, y2) 79 MakeBridge(Polyline *line1, int x1, int y1, Polyline *line2, int x2, int y2)
88 Polyline *line1, *line2;
89 int x1, x2, y1, y2;
90 { 80 {
91 int dx, dy, s; 81 int dx, dy, s;
92 Polyline *r; 82 Polyline *r;
93 83
94 dx = x2 + line2->dx - x1; 84 dx = x2 + line2->dx - x1;
103 93
104 return (r); 94 return (r);
105 } 95 }
106 96
107 /* ---------------------------------------------------------------------------- 97 /* ----------------------------------------------------------------------------
108 * 98 *
109 * Offset() computes the necessary offset that prevents two line segments 99 * Offset() computes the necessary offset that prevents two line segments
110 * from intersecting each other. This is the "heart" of the merge step 100 * from intersecting each other. This is the "heart" of the merge step
111 * that computes how two subtree contours should be separated. 101 * that computes how two subtree contours should be separated.
112 * 102 *
113 * The code is taken directly from Sven Moen's paper, with changes in 103 * The code is taken directly from Sven Moen's paper, with changes in
114 * some variable names to give more meaning: 104 * some variable names to give more meaning:
115 * 105 *
116 * - px,py indicate the x- and y-coordinates of the point on the longer 106 * - px,py indicate the x- and y-coordinates of the point on the longer
117 * segment if the previous Offset() call had two unequal segments 107 * segment if the previous Offset() call had two unequal segments
118 * 108 *
119 * - lx,ly indicate the dx and dy values of the "lower" line segment 109 * - lx,ly indicate the dx and dy values of the "lower" line segment
120 * 110 *
121 * - ux,uy indicate the dx and dy values of the "upper" line segment 111 * - ux,uy indicate the dx and dy values of the "upper" line segment
122 * 112 *
123 * ---------------------------------------------------------------------------- 113 * ----------------------------------------------------------------------------
124 */ 114 */
125 115
126 int 116 static int
127 Offset(px, py, lx, ly, ux, uy) 117 Offset(int px, int py, int lx, int ly, int ux, int uy)
128 int px, py, lx, ly, ux, uy;
129 { 118 {
130 int d, s, t; 119 int d, s, t;
131 120
132 if (ux <= px || px+lx <= 0) 121 if (ux <= px || px+lx <= 0)
133 return 0; 122 return 0;
163 152
164 return MAX(0, d); 153 return MAX(0, d);
165 } 154 }
166 155
167 /* ---------------------------------------------------------------------------- 156 /* ----------------------------------------------------------------------------
168 * 157 *
169 * Merge() 158 * Merge()
170 * 159 *
171 * ---------------------------------------------------------------------------- 160 * ----------------------------------------------------------------------------
172 */ 161 */
173 162
174 int 163 static int
175 Merge(c1, c2) 164 Merge(Polygon *c1, Polygon *c2)
176 Polygon *c1, *c2;
177 { 165 {
178 int x, y, total, d; 166 int x, y, total, d;
179 Polyline *lower, *upper, *bridge; 167 Polyline *lower, *upper, *bridge;
180 168
181 x = y = total = 0; 169 x = y = total = 0;
182 170
183 /* compare lower part of upper child's contour 171 /* compare lower part of upper child's contour
184 * with upper part of lower child's contour 172 * with upper part of lower child's contour
185 */ 173 */
186 upper = c1->lower.head; 174 upper = c1->lower.head;
187 lower = c2->upper.head; 175 lower = c2->upper.head;
188 176
200 x -= upper->dx; 188 x -= upper->dx;
201 y -= upper->dy; 189 y -= upper->dy;
202 upper = upper->link; 190 upper = upper->link;
203 } 191 }
204 } 192 }
205 193
206 if (lower) { 194 if (lower) {
207 bridge = MakeBridge(c1->upper.tail, 0, 0, lower, x, y); 195 bridge = MakeBridge(c1->upper.tail, 0, 0, lower, x, y);
208 c1->upper.tail = (bridge->link) ? c2->upper.tail : bridge; 196 c1->upper.tail = (bridge->link) ? c2->upper.tail : bridge;
209 c1->lower.tail = c2->lower.tail; 197 c1->lower.tail = c2->lower.tail;
210 } 198 }
211 else { 199 else {
212 bridge = MakeBridge(c2->lower.tail, x, y, upper, 0, 0); 200 bridge = MakeBridge(c2->lower.tail, x, y, upper, 0, 0);
213 if (!bridge->link) 201 if (!bridge->link)
214 c1->lower.tail = bridge; 202 c1->lower.tail = bridge;
215 } 203 }
216 c1->lower.head = c2->lower.head; 204 c1->lower.head = c2->lower.head;
217 205
218 return (total); 206 return (total);
219 } 207 }
220 208
221 /* ---------------------------------------------------------------------------- 209 /* ----------------------------------------------------------------------------
222 * 210 *
223 * DetachParent() reverses the effects of AttachParent by removing 211 * DetachParent() reverses the effects of AttachParent by removing
224 * the four line segments that connect the subtree contour to the 212 * the four line segments that connect the subtree contour to the
225 * node specified by 'tree'. 213 * node specified by 'tree'.
226 * 214 *
227 * ---------------------------------------------------------------------------- 215 * ----------------------------------------------------------------------------
228 */ 216 */
229 217
230 void 218 static void
231 DetachParent(tree) 219 DetachParent(Tree *tree)
232 Tree *tree;
233 { 220 {
234 free(tree->contour.upper.head->link); 221 free(tree->contour.upper.head->link);
235 free(tree->contour.upper.head); 222 free(tree->contour.upper.head);
236 tree->contour.upper.head = NULL; 223 tree->contour.upper.head = NULL;
237 tree->contour.upper.tail = NULL; 224 tree->contour.upper.tail = NULL;
243 230
244 NumLines -= 4; 231 NumLines -= 4;
245 } 232 }
246 233
247 /* ---------------------------------------------------------------------------- 234 /* ----------------------------------------------------------------------------
248 * 235 *
249 * AttachParent() 236 * AttachParent()
250 * This function also establishes the position of the first child 237 * This function also establishes the position of the first child
251 * The code follows Sven Moen's version, with slight modification to 238 * The code follows Sven Moen's version, with slight modification to
252 * support varying borders at different levels. 239 * support varying borders at different levels.
253 * 240 *
254 * ---------------------------------------------------------------------------- 241 * ----------------------------------------------------------------------------
255 */ 242 */
256 243
257 void 244 static void
258 AttachParent(tree, h) 245 AttachParent(Tree *tree, int h)
259 Tree *tree;
260 int h;
261 { 246 {
262 int x, y1, y2; 247 int x, y1, y2;
263 248
264 if (TreeAlignNodes) 249 if (TreeAlignNodes)
265 x = tree->border + (TreeParentDistance * 2) + 250 x = tree->border + (TreeParentDistance * 2) +
266 (TreeParentDistance - tree->width); 251 (TreeParentDistance - tree->width);
267 else 252 else
268 x = tree->border + TreeParentDistance; 253 x = tree->border + TreeParentDistance;
269 y2 = (h - tree->height)/2 - tree->border; 254 y2 = (h - tree->height)/2 - tree->border;
270 y1 = y2 + tree->height + (2 * tree->border) - h; 255 y1 = y2 + tree->height + (2 * tree->border) - h;
271 tree->child->offset.x = x + tree->width; 256 tree->child->offset.x = x + tree->width;
272 tree->child->offset.y = y1; 257 tree->child->offset.y = y1;
273 tree->contour.upper.head = MakeLine(tree->width, 0, 258 tree->contour.upper.head = MakeLine(tree->width, 0,
274 MakeLine(x, y1, 259 MakeLine(x, y1,
275 tree->contour.upper.head)); 260 tree->contour.upper.head));
277 MakeLine(x, y2, 262 MakeLine(x, y2,
278 tree->contour.lower.head)); 263 tree->contour.lower.head));
279 } 264 }
280 265
281 /* ---------------------------------------------------------------------------- 266 /* ----------------------------------------------------------------------------
282 * 267 *
283 * Split() 268 * Split()
284 * The tree passed to Split() must have at least 1 child, because 269 * The tree passed to Split() must have at least 1 child, because
285 * it doesn't make sense to split a leaf (there are no bridges) 270 * it doesn't make sense to split a leaf (there are no bridges)
286 * 271 *
287 * ---------------------------------------------------------------------------- 272 * ----------------------------------------------------------------------------
288 */ 273 */
289 274
290 void 275 static void
291 Split(tree) 276 Split(Tree *tree)
292 Tree *tree;
293 { 277 {
294 Tree *child; 278 Tree *child;
295 Polyline *link; 279 Polyline *link;
296 280
297 FOREACH_CHILD(child, tree) { 281 FOREACH_CHILD(child, tree) {
298 if (link = child->contour.upper.tail->link) { 282 if ((link = child->contour.upper.tail->link)) {
299 free(link->link); 283 free(link->link);
300 free(link); 284 free(link);
301 child->contour.upper.tail->link = NULL; 285 child->contour.upper.tail->link = NULL;
302 NumLines -= 2; 286 NumLines -= 2;
303 } 287 }
304 if (link = child->contour.lower.tail->link) { 288 if ((link = child->contour.lower.tail->link)) {
305 free(link->link); 289 free(link->link);
306 free(link); 290 free(link);
307 NumLines -= 2; 291 NumLines -= 2;
308 child->contour.lower.tail->link = NULL; 292 child->contour.lower.tail->link = NULL;
309 } 293 }
310 } 294 }
311 } 295 }
312 296
313 /* ---------------------------------------------------------------------------- 297 /* ----------------------------------------------------------------------------
314 * 298 *
315 * Join() merges all subtree contours of the given tree and returns the 299 * Join() merges all subtree contours of the given tree and returns the
316 * height of the entire tree contour. 300 * height of the entire tree contour.
317 * 301 *
318 * ---------------------------------------------------------------------------- 302 * ----------------------------------------------------------------------------
319 */ 303 */
320 304
321 int 305 static int
322 Join(tree) 306 Join(Tree *tree)
323 Tree *tree;
324 { 307 {
325 Tree *child; 308 Tree *child;
326 int d, h, sum; 309 int d, h, sum;
327 310
328 /* to start, set the parent's contour and height 311 /* to start, set the parent's contour and height
329 * to contour and height of first child 312 * to contour and height of first child
330 */ 313 */
331 child = tree->child; 314 child = tree->child;
332 tree->contour = child->contour; 315 tree->contour = child->contour;
333 sum = h = child->height + (2 * child->border); 316 sum = h = child->height + (2 * child->border);
334 317
343 } 326 }
344 return sum; 327 return sum;
345 } 328 }
346 329
347 /* ---------------------------------------------------------------------------- 330 /* ----------------------------------------------------------------------------
348 * 331 *
349 * RuboutLeaf() accepts a single node (leaf) and removes its contour. 332 * RuboutLeaf() accepts a single node (leaf) and removes its contour.
350 * The memory associated with the contour is deallocated. 333 * The memory associated with the contour is deallocated.
351 * 334 *
352 * ---------------------------------------------------------------------------- 335 * ----------------------------------------------------------------------------
353 */ 336 */
354 337
355 void 338 void
356 RuboutLeaf(tree) 339 RuboutLeaf(Tree *tree)
357 Tree *tree;
358 { 340 {
359 free(tree->contour.upper.head); 341 free(tree->contour.upper.head);
360 free(tree->contour.lower.tail); 342 free(tree->contour.lower.tail);
361 free(tree->contour.lower.head); 343 free(tree->contour.lower.head);
362 tree->contour.upper.head = NULL; 344 tree->contour.upper.head = NULL;
363 tree->contour.upper.tail = NULL; 345 tree->contour.upper.tail = NULL;
364 tree->contour.lower.head = NULL; 346 tree->contour.lower.head = NULL;
365 tree->contour.lower.tail = NULL; 347 tree->contour.lower.tail = NULL;
366 NumLines -= 3; 348 NumLines -= 3;
367 } 349 }
368 350
369 /* ---------------------------------------------------------------------------- 351 /* ----------------------------------------------------------------------------
370 * 352 *
371 * LayoutLeaf() accepts a single node (leaf) and forms its contour. This 353 * LayoutLeaf() accepts a single node (leaf) and forms its contour. This
372 * function assumes that the width, height, and border fields of the 354 * function assumes that the width, height, and border fields of the
373 * node have been assigned meaningful values. 355 * node have been assigned meaningful values.
374 * 356 *
375 * ---------------------------------------------------------------------------- 357 * ----------------------------------------------------------------------------
376 */ 358 */
377 359
378 void 360 void
379 LayoutLeaf(tree) 361 LayoutLeaf(Tree *tree)
380 Tree *tree;
381 { 362 {
382 tree->node_height = 0; 363 tree->node_height = 0;
383 tree->border = TreeBorderSize; 364 tree->border = TreeBorderSize;
384 365
385 tree->contour.upper.tail = MakeLine(tree->width + 2 * tree->border, 0, 366 tree->contour.upper.tail = MakeLine(tree->width + 2 * tree->border, 0,
386 NULL); 367 NULL);
387 tree->contour.upper.head = tree->contour.upper.tail; 368 tree->contour.upper.head = tree->contour.upper.tail;
388 369
389 tree->contour.lower.tail = MakeLine(0, -tree->height - 2 * tree->border, 370 tree->contour.lower.tail = MakeLine(0, -tree->height - 2 * tree->border,
390 NULL); 371 NULL);
391 tree->contour.lower.head = MakeLine(tree->width + 2 * tree->border, 0, 372 tree->contour.lower.head = MakeLine(tree->width + 2 * tree->border, 0,
392 tree->contour.lower.tail); 373 tree->contour.lower.tail);
393 374
394 } 375 }
395 376
396 /* ---------------------------------------------------------------------------- 377 /* ----------------------------------------------------------------------------
397 * 378 *
398 * LayoutTree() traverses the given tree (in depth-first order), and forms 379 * LayoutTree() traverses the given tree (in depth-first order), and forms
399 * subtree or leaf contours at each node as needed. Each node's contour is 380 * subtree or leaf contours at each node as needed. Each node's contour is
400 * stored in its "contour" field. Elision is also supported by generating 381 * stored in its "contour" field. Elision is also supported by generating
401 * the contour for both the expanded and collapsed node. This routine 382 * the contour for both the expanded and collapsed node. This routine
402 * also computes the tree height of each node in the tree, so that variable 383 * also computes the tree height of each node in the tree, so that variable
403 * density layout can be demonstrated. 384 * density layout can be demonstrated.
404 * 385 *
405 * ---------------------------------------------------------------------------- 386 * ----------------------------------------------------------------------------
406 */ 387 */
407 388
408 void 389 void
409 LayoutTree(tree) 390 LayoutTree(Tree *tree)
410 Tree *tree;
411 { 391 {
412 Tree *child; 392 Tree *child;
413 int height = 0; 393 int height = 0;
414 394
415 FOREACH_CHILD(child, tree) { 395 FOREACH_CHILD(child, tree) {
422 402
423 } 403 }
424 404
425 if (tree->child) { 405 if (tree->child) {
426 406
427 FOREACH_CHILD(child, tree) 407 FOREACH_CHILD(child, tree)
428 height = MAX(child->node_height, height); 408 height = MAX(child->node_height, height);
429 tree->node_height = height + 1; 409 tree->node_height = height + 1;
430 410
431 if (TreeLayoutDensity == Fixed) 411 if (TreeLayoutDensity == Fixed)
432 tree->border = TreeBorderSize; 412 tree->border = TreeBorderSize;
441 } 421 }
442 422
443 /* ------------------------------------------------------------------------- */ 423 /* ------------------------------------------------------------------------- */
444 424
445 void 425 void
446 Unzip(tree) 426 Unzip(Tree *tree)
447 Tree *tree;
448 { 427 {
449 Tree *child; 428 Tree *child;
450 429
451 #ifdef INTF 430 #ifdef INTF
452 if (TreeShowSteps) { 431 if (TreeShowSteps) {
453 HiliteNode(tree, New); 432 HiliteNode(tree, New);
454 tree->on_path = TRUE; 433 tree->on_path = TRUE;
455 StatusMsg("Unzip: follow parent links up to root"); 434 StatusMsg("Unzip: follow parent links up to root", 0);
456 Pause(); 435 Pause();
457 } 436 }
458 #endif 437 #endif
459 438
460 if (tree->parent) 439 if (tree->parent)
461 Unzip(tree->parent); 440 Unzip(tree->parent);
462 441
463 if (tree->child) { 442 if (tree->child) {
464 443
465 #ifdef INTF 444 #ifdef INTF
466 /* draw entire contour; do it only for root, because the last 445 /* draw entire contour; do it only for root, because the last
467 * frame drawn in this function will have already drawn the 446 * frame drawn in this function will have already drawn the
468 * contour for the most recently split subtree. 447 * contour for the most recently split subtree.
469 */ 448 */
470 if (TreeShowSteps) { 449 if (TreeShowSteps) {
471 if (tree->parent == NULL) { 450 if (tree->parent == NULL) {
472 BeginFrame(); 451 BeginFrame();
473 DrawTreeContour(tree, New, CONTOUR_COLOR, FALSE, FALSE, FALSE); 452 DrawTreeContour(tree, New, CONTOUR_COLOR, FALSE, FALSE, FALSE);
474 DrawTree(TheTree, New); 453 DrawTree(TheTree, New);
475 EndFrame(); 454 EndFrame();
476 StatusMsg("Unzip: disassemble entire contour"); 455 StatusMsg("Unzip: disassemble entire contour", 0);
477 Pause(); 456 Pause();
478 } 457 }
479 } 458 }
480 #endif 459 #endif
481 460
482 #ifdef INTF 461 #ifdef INTF
483 /* draw contour as it would appear after DetachParent() */ 462 /* draw contour as it would appear after DetachParent() */
484 if (TreeShowSteps) { 463 if (TreeShowSteps) {
485 BeginFrame(); 464 BeginFrame();
465 #if 0 /* mrb */
486 DrawTreeContour(tree, New, CONTOUR_COLOR, TRUE, 466 DrawTreeContour(tree, New, CONTOUR_COLOR, TRUE,
487 FALSE, FALSE, FALSE); 467 FALSE, FALSE, FALSE);
468 #endif
469 DrawTreeContour(tree, New, CONTOUR_COLOR, TRUE,
470 FALSE, FALSE);
488 DrawTree(TheTree, New); 471 DrawTree(TheTree, New);
489 EndFrame(); 472 EndFrame();
490 StatusMsg("Unzip: detach parent"); 473 StatusMsg("Unzip: detach parent", 0);
491 Pause(); 474 Pause();
492 } 475 }
493 #endif 476 #endif
494 477
495 DetachParent(tree); 478 DetachParent(tree);
499 if (TreeShowSteps) { 482 if (TreeShowSteps) {
500 BeginFrame(); 483 BeginFrame();
501 /* mark other subtree contours as split, and */ 484 /* mark other subtree contours as split, and */
502 /* draw only the contour on path in full */ 485 /* draw only the contour on path in full */
503 FOREACH_CHILD(child, tree) { 486 FOREACH_CHILD(child, tree) {
504 if (!child->on_path) 487 if (!child->on_path)
505 child->split = TRUE; 488 child->split = TRUE;
506 else 489 else
507 DrawTreeContour(child, New, CONTOUR_COLOR, 490 DrawTreeContour(child, New, CONTOUR_COLOR,
508 FALSE, FALSE, FALSE); 491 FALSE, FALSE, FALSE);
509 } 492 }
510 DrawTree(TheTree, New); 493 DrawTree(TheTree, New);
511 EndFrame(); 494 EndFrame();
512 StatusMsg("Unzip: split tree"); 495 StatusMsg("Unzip: split tree", 0);
513 Pause(); 496 Pause();
514 } 497 }
515 #endif 498 #endif
516 499
517 } 500 }
520 } 503 }
521 504
522 /* ------------------------------------------------------------------------- */ 505 /* ------------------------------------------------------------------------- */
523 506
524 void 507 void
525 Zip(tree) 508 Zip(Tree *tree)
526 Tree *tree;
527 { 509 {
528 if (tree->child) 510 if (tree->child)
529 AttachParent(tree, Join(tree)); 511 AttachParent(tree, Join(tree));
530 else 512 else
531 LayoutLeaf(tree); 513 LayoutLeaf(tree);
533 if (tree->parent) 515 if (tree->parent)
534 Zip(tree->parent); 516 Zip(tree->parent);
535 } 517 }
536 518
537 /* ---------------------------------------------------------------------------- 519 /* ----------------------------------------------------------------------------
538 * 520 *
539 * Insert() adds the specified child to parent, just after the specified 521 * Insert() adds the specified child to parent, just after the specified
540 * sibling. If 'sibling' is Null, the child is added as the first child. 522 * sibling. If 'sibling' is Null, the child is added as the first child.
541 * 523 *
542 * ---------------------------------------------------------------------------- 524 * ----------------------------------------------------------------------------
543 */ 525 */
544 526
545 void 527 void
546 Insert(parent, child, sibling) 528 Insert(Tree *parent, Tree *child, Tree *sibling)
547 Tree *parent, *child, *sibling;
548 { 529 {
549 Unzip(parent); 530 Unzip(parent);
550 child->parent = parent; 531 child->parent = parent;
551 if (sibling) { 532 if (sibling) {
552 child->sibling = sibling->sibling; 533 child->sibling = sibling->sibling;
561 542
562 543
563 544
564 545
565 /* ---------------------------------------------------------------------------- 546 /* ----------------------------------------------------------------------------
566 * 547 *
567 * Delete() traverses the specified tree and frees all storage 548 * Delete() traverses the specified tree and frees all storage
568 * allocated to the subtree, including contours and bridges. 549 * allocated to the subtree, including contours and bridges.
569 * If the tree had a preceding sibling, the preceding sibling is 550 * If the tree had a preceding sibling, the preceding sibling is
570 * modified to point to the tree's succeeding sibling, if any. 551 * modified to point to the tree's succeeding sibling, if any.
571 * 552 *
572 * ---------------------------------------------------------------------------- 553 * ----------------------------------------------------------------------------
573 */ 554 */
574 555
575 Delete(tree) 556 void
576 Tree *tree; 557 Delete(Tree *tree)
577 { 558 {
578 Tree *sibling = NULL; 559 Tree *sibling = NULL;
579 Tree *parent, *child; 560 Tree *parent, *child;
580 561
581 /* find sibling */ 562 /* find sibling */
589 } 570 }
590 if (sibling) 571 if (sibling)
591 sibling->sibling = tree->sibling; 572 sibling->sibling = tree->sibling;
592 else if (parent) 573 else if (parent)
593 parent->child = tree->sibling; 574 parent->child = tree->sibling;
594 575
595 DeleteTree(tree, FALSE); 576 DeleteTree(tree, FALSE);
596 } 577 }
597 578
598 579
599 /* ---------------------------------------------------------------------------- 580 /* ----------------------------------------------------------------------------
600 * 581 *
601 * DeleteTree() is the recursive function that supports Delete(). 582 * DeleteTree() is the recursive function that supports Delete().
602 * If 'contour' is True, then only the contours are recursively deleted. 583 * If 'contour' is True, then only the contours are recursively deleted.
603 * This flag should be True when you are regenerating a tree's layout 584 * This flag should be True when you are regenerating a tree's layout
604 * and still want to preserve the nodes. Since contours would be deleted 585 * and still want to preserve the nodes. Since contours would be deleted
605 * only due to a change in sibling or level distance, each node's border 586 * only due to a change in sibling or level distance, each node's border
606 * value is updated with the current value of TreeBorderSize; 587 * value is updated with the current value of TreeBorderSize;
607 * 588 *
608 * ---------------------------------------------------------------------------- 589 * ----------------------------------------------------------------------------
609 */ 590 */
610 591
611 DeleteTree(tree, contour) 592 void
612 Tree *tree; 593 DeleteTree(Tree *tree, int contour)
613 int contour;
614 { 594 {
615 Tree *child; 595 Tree *child;
616 596
617 if (tree->elision) { 597 if (tree->elision) {
618 RuboutLeaf(tree); 598 RuboutLeaf(tree);
628 DeleteTree(child, contour); 608 DeleteTree(child, contour);
629 } 609 }
630 else 610 else
631 RuboutLeaf(tree); 611 RuboutLeaf(tree);
632 612
633 if (contour) 613 if (contour)
634 tree->border = TreeBorderSize; 614 tree->border = TreeBorderSize;
635 else { 615 else {
636 free(tree->label.text); 616 free(tree->label.text);
637 free(tree); 617 free(tree);
638 NumNodes--; 618 NumNodes--;
639 } 619 }
640 } 620 }
641 621
642 622
643 /* ---------------------------------------------------------------------------- 623 /* ----------------------------------------------------------------------------
644 * 624 *
645 * ComputeTreeSize() 625 * ComputeTreeSize()
646 * This function should be called after tree layout. 626 * This function should be called after tree layout.
647 * 627 *
648 * ---------------------------------------------------------------------------- 628 * ----------------------------------------------------------------------------
649 */ 629 */
650 630
651 void 631 void
652 ComputeTreeSize(tree, width, height, x_offset, y_offset) 632 ComputeTreeSize(Tree *tree,
653 Tree *tree; 633 int *width, int *height,
654 int *width, *height; 634 int *x_offset, int *y_offset)
655 int *x_offset, *y_offset;
656 { 635 {
657 Polyline *contour, *tail; 636 Polyline *contour, *tail;
658 int upper_min_y = 0, lower_max_y = 0; 637 int upper_min_y = 0, lower_max_y = 0;
659 int upper_abs_y = 0, lower_abs_y = 0; 638 int upper_abs_y = 0, lower_abs_y = 0;
660 int x = 0; 639 int x = 0;
661 640
662 /* do upper contour */ 641 /* do upper contour */
663 contour = tree->contour.upper.head; 642 contour = tree->contour.upper.head;
664 tail = tree->contour.upper.tail; 643 tail = tree->contour.upper.tail;
665 while (contour) { 644 while (contour) {
666 if ((contour->dy + upper_abs_y) < upper_min_y) 645 if ((contour->dy + upper_abs_y) < upper_min_y)
667 upper_min_y = contour->dy + upper_abs_y; 646 upper_min_y = contour->dy + upper_abs_y;
668 upper_abs_y += contour->dy; 647 upper_abs_y += contour->dy;
669 if (contour == tail) 648 if (contour == tail)
670 contour = NULL; 649 contour = NULL;
671 else 650 else
694 if (y_offset) 673 if (y_offset)
695 *y_offset = - upper_min_y + tree->border; 674 *y_offset = - upper_min_y + tree->border;
696 } 675 }
697 676
698 /* ---------------------------------------------------------------------------- 677 /* ----------------------------------------------------------------------------
699 * 678 *
700 * PetrifyTree() 679 * PetrifyTree()
701 * 680 *
702 * ---------------------------------------------------------------------------- 681 * ----------------------------------------------------------------------------
703 */ 682 */
704 683
705 void 684 void
706 PetrifyTree(tree, x, y) 685 PetrifyTree(Tree *tree, int x, int y)
707 Tree *tree;
708 int x, y;
709 { 686 {
710 int width, height; 687 int width, height;
711 int x_offset, y_offset; 688 int x_offset, y_offset;
712 689
713 tree->old_pos = tree->pos; /* used by AnimateTree */ 690 tree->old_pos = tree->pos; /* used by AnimateTree */
714 691
715 /* fix position of each node */ 692 /* fix position of each node */
716 tree->pos.x = x + tree->offset.x; 693 tree->pos.x = x + tree->offset.x;
717 tree->pos.y = y + tree->offset.y; 694 tree->pos.y = y + tree->offset.y;
718 695
719 if (tree->child) { 696 if (tree->child) {
720 PetrifyTree(tree->child, tree->pos.x, tree->pos.y); 697 PetrifyTree(tree->child, tree->pos.x, tree->pos.y);
721 ComputeSubTreeExtent(tree); /* for benefit of interface picking */ 698 ComputeSubTreeExtent(tree); /* for benefit of interface picking */
722 } 699 }
723 if (tree->sibling) 700 if (tree->sibling)