-+-+-+-+-+-+-+-+ START OF PART 256 -+-+-+-+-+-+-+-+ X/*-------------------------------------------------------------------------- V*/ X Xstatic void setkey(C(Pchar *) v, C(Pchar *) k) XPreANSI(Pchar *v) XPreANSI(Pchar *k) X/* X** \parambegin X** \param`7B`7D`7Bv`7D`7Bstring to allocate a key for`7D`7BIN`7D X** \param`7B`7D`7Bk`7D`7Bkey allocated to string ( a, b etc.)`7D`7BIN`7D X** \paramend X** \blurb`7BAllocates a key to string 'v', and records the correspondence X** in the key table.`7D X*/ X`7B X ptkskeytable *keyptr; X X topptr->keyno++; X keyptr = &topptr->keytablelst`5Btopptr->keyno - 1`5D; X keyptr->key`5B1`5D = '\0'; X keyptr->key`5B0`5D = (Pchar)(topptr->keyno + 96); X X /* keys are labelled from 'a' upwards */ X strcpy(k, keyptr->key); /* return the key allocated */ X strcpy(keyptr->an, v); X`7D /* setkey */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic void drawkeys(C(void)) X/* X** \blurb`7BStart the list of keys at xmin, and drop a node's X** worth below the minimum y.`7D X*/ X`7B X Pint i; X Ppoint tp; X ptkskeytable *keyptr; X Pchar str`5B256`5D; X X if (topptr->keyno > 0) X `7B X tp = ptk_point(topptr->extent.xmin, X topptr->extent.ymin - topptr->nodeheight); X for (i = 0; i < topptr->keyno; i++)`20 X `7B X keyptr = &topptr->keytablelst`5Bi`5D; X sprintf(str, "%s %s", keyptr->key, keyptr->an); X tp.y -= topptr->annotextheight * 1.5; X ptext(&tp, str); X `7D X /* Record the limits of the keytable */ X note(tp.x, tp.y);`20 X `7D X`7D /* drawkeys */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic void setscaling(C(void)) X/* X** \blurb`7BComputes the transformation to scale the picture X** into `5B0,1`5D, and inserts a setglobaltran at the start of the picture.` V7D X*/ X`7B X Ppoint3 sc, sh; X Pint err, el; X Pfloat height, width, scale; X Ppoint3 topshift, topscale; X X topptr->extent.xmin -= topptr->nodewidth; X topptr->extent.xmax += topptr->nodewidth; X topptr->extent.ymin -= topptr->nodeheight; X topptr->extent.ymax += topptr->nodeheight; X height = topptr->extent.ymax - topptr->extent.ymin; X width = topptr->extent.xmax - topptr->extent.xmin; X scale = 1.0/MAX(height, width); X topshift = ptk_point3(-topptr->extent.xmin - (width / 2.0), X -topptr->extent.ymin - (height / 2.0), 0.0),`20 X ptk_shift3(&topshift, PREPLACE, topptr->globaltran);`20 X topscale = ptk_point3(scale, scale, scale); X ptk_scale3(&topscale, PPOSTCONCATENATE, topptr->globaltran); X topshift = ptk_point3(0.5, 0.5, 0.0); X ptk_shift3(&topshift, PPOSTCONCATENATE, topptr->globaltran);`20 X /* Squeeze in a global transformation at the X top of the structure */ X psetelemptr(0); X psetelemptrlabel(ptk_stringtoint("label", "globaltran")); X psetglobaltran3(topptr->globaltran); X`7D /* setscaling */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic ptkboolean overlap(C(Ppoint *) p, C(Pfloat) stringw, C(Pfloat) string Vh) XPreANSI(Ppoint *p) XPreANSI(Pfloat stringw) XPreANSI(Pfloat stringh) X/* X** \parambegin X** \param`7B`7D`7Bp`7D`7Bpoint to check for overlapping nodes`7D`7BIN`7D X** \param`7B`7D`7Bstringw`7D`7Bcharacter string width`7D`7BIN`7D X** \param`7B`7D`7Bstringh`7D`7Bcharacter string height`7D`7BIN`7D X** \paramend X** \blurb`7BGiven a point p, checks against all the positioned nodes`20 X** to see if any lie between p and and another point q, 'stringw'`20 X** horizontally away from p. X** Returns TRUE if there is an overlapping node, otherwise FALSE.`7D X*/ X`7B X ptksstruct *sp; X ptkboolean over; X X over = FALSE; X sp = topptr->structlist; X while (sp != NULL && !over)`20 X `7B `20 X /* look at each node */ X if ((p->y <= sp->pos.y + topptr->nodeheight / 2.0) && X`09(p->y + stringh >= sp->pos.y - topptr->nodeheight / 2.0))`20 X `7B X /* it overlaps the node vertically, so now test if the X node lies somewhere inside the extent */ X if ((p->x < sp->pos.x + topptr->nodewidth / 2.0) && X`09 (p->x + stringw > sp->pos.x - topptr->nodewidth / 2.0)) X`09over = TRUE; X `7D X sp = sp->next; X `7D X return over; X`7D /* overlap */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic void setnode(C(Pfloat) w, C(Pfloat) h) XPreANSI(Pfloat w) XPreANSI(Pfloat h) X/* X** \parambegin X** \param`7B`7D`7Bw`7D`7Bnode width`7D`7BIN`7D X** \param`7B`7D`7Bh`7D`7Bnode height`7D`7BIN`7D X** \paramend X** \blurb`7BEstablishes the size of a node, centred.`7D X*/ X`7B X topptr->nodebounds = 5; X topptr->nodepoints`5B0`5D = ptk_point(w/-2.0, h/-2.0); X topptr->nodepoints`5B1`5D = ptk_point(w/2.0, h/-2.0); X topptr->nodepoints`5B2`5D = ptk_point(w/2.0, h/2.0); X topptr->nodepoints`5B3`5D = ptk_point(w/-2.0, h/2.0); X topptr->nodepoints`5B4`5D = ptk_point(w/-2.0, h/-2.0); X psetcharheight(h/2.0); X topptr->annotextheight = h / 2.0; X`7D /* setnode */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic void initialise(C(void)) X/* X** \blurb`7BInitialise topdraw values.`7D X*/ X`7B X Pint k; X X topptr->structlist = NULL; /* no structures to start with */ X topptr->rowlist = NULL; /* and no rows */ X topptr->keyno = 0; /* no debugging printing, no keys */ X for (k = 0; k <= 254; k++) X topptr->rowmaxx`5Bk`5D = -32768.0; X topptr->maxlevel = 1; X`7D /* initialise */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic ptkboolean lookupstructure(C(Pint) sn, C(ptkboolean) create,`20 X C(ptksstruct **) sp) XPreANSI(Pint sn) XPreANSI(ptkboolean create) XPreANSI(ptksstruct **sp) X/* X** \parambegin X** \param`7B`7D`7Bsn`7D`7Bstructure identifier to look up`7D`7BIN`7D X** \param`7B`7D`7Bcreate`7D`7Badd to structlist if TRUE, do nothing if FALSE V`7D`7BIN`7D X** \param`7B`7D`7Bsp`7D`7Bpointer to structure record`7D`7BIN`7D X** \paramend X** \blurb`7BLooks for a structure in the namelist, and inserts it X** if it's not there, and create=TRUE. Returns a pointer to the name X** record, or NIL if it wasn't found and not created. The result is`20 X** TRUE if it was created. X** Returns TRUE if new record created, otherwise FALSE.`7D X*/ X`7B X ptkboolean found; X ptksstruct *last, *s, *news; X X s = topptr->structlist; X found = FALSE; X *sp = NULL; X while (!found && s != NULL)`20 X `7B X found = (sn == s->name); X if (found) X break; X last = s; X s = s->next; X `7D X if (found)`20 X `7B X *sp = s; X return (!found && create); X `7D X if (!create)`20 X `7B X return (!found && create); X `7D /* not found and created */ X news = (ptksstruct *)malloc(sizeof(ptksstruct)); X *sp = news; X if (topptr->structlist == NULL) /* initialise the record */ X topptr->structlist = news; X else X last->next = news; X news->name = sn; X news->level = 0; X news->next = NULL; X news->numchildren = ptk_countchildren(sn); X news->numunique = ptk_countuniqchildren(sn); X news->firstchild = NULL; X news->lastchild = NULL; X news->firstparent = NULL; X news->lastparent = NULL; X news->placed = FALSE; X news->pos = ptk_point(0.0, 0.0); X return (!found && create); X`7D /* lookupstructure */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic void drawnames(C(void)) X/* X** \blurb`7BDraws the name of the structure next to its node. X** First we'll try and draw the string to the right of the node, which X** seems like a good place. If that would splash over another node X** nearby,we'll try the left instead. If both are no good, give up,and X** use a key instead.`7D X*/ X`7B X Ppoint tp; X ptksstruct *sp; X Pmatrix3 mat; X Pint textrep; X Pchar k`5B256`5D, annot`5B256`5D; X Ptxalign a; X Pint lenstr; X ptkboolean donames; X X ptk_unitmatrix3(mat); X psetlocaltran3(mat, PREPLACE); X a.hor = PAH_NORMAL; X a.ver = PAV_HALF; X psettextalign(&a); X donames = ptk_hashtableused("structureid"); X sp = topptr->structlist; /* going to scan the structure list */ X while (sp != NULL)`20 X `7B X /* place text to the right of the node */ X tp = ptk_point(sp->pos.x + 3.0 * WIDTH / 4.0, sp->pos.y); X if (donames) X `7B X ptk_inttostring("structureid", sp->name, 256, annot, &lenstr); X if (lenstr == 0) X sprintf(annot, "%d\0", sp->name);`20 X `7D X else X sprintf(annot, "%d\0", sp->name);`20 X /* should use inqtextextent to get width of string */ X if (overlap(&tp, (Pfloat)strlen(annot) * topptr->annotextheight, X`09`09topptr->annotextheight))`20 X `7B X /* no good. now try to place it to the left of the node */ X tp.x = sp->pos.x - topptr->nodewidth / 2.0 - X`09 (Pfloat)strlen(annot) * topptr->annotextheight; X if (overlap(&tp, strlen(annot) * topptr->annotextheight, X`09`09 topptr->annotextheight))`20 X `7B X`09/* Need to resort to a key here. Reset the text position X`09 to inside the node, and get a key */ X tp = ptk_point(sp->pos.x + 3.0 * WIDTH / 4.0, sp->pos.y); X`09setkey(annot, k); X note(tp.x + topptr->annotextheight, tp.y); X`09ptext(&tp, k); X `7D`20 X else`20 X `7B `20 X /* place text to the left */ X`09note(tp.x, tp.y); X`09tp.x = sp->pos.x - topptr->nodeheight * 3.0 / 4.0; X`09a.hor = PAH_RIGHT; X`09a.ver = PAV_HALF; X`09psettextalign(&a); X`09ptext(&tp, annot); X`09a.hor = PAH_NORMAL; X`09a.ver = PAV_HALF; X`09psettextalign(&a); X `7D X `7D`20 X else`20 X `7B `20 X /* no overlap */ X note(tp.x + (Pfloat)strlen(annot) * topptr->annotextheight, tp.y); X ptext(&tp, annot); X `7D X sp = sp->next; X `7D X`7D /* drawnames */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic Pint findlowestchild(C(ptksstruct *) root) XPreANSI(ptksstruct *root) X/* X** \parambegin X** \param`7B`7D`7Broot`7D`7Bpointer to root structure record`7D`7BIN`7D X** \paramend X** \blurb`7BLooks at all the immediate children of 'root', and X** returns the level of the deepest one. X** Returns level of lowest child of root.`7D X*/ X`7B X ptksref *r; X Pint l; X X l = 0; X r = root->firstchild; X while (r != NULL)`20 X `7B X if (r->structptr->level > l) X l = r->structptr->level; X r = r->next; X `7D X return l; X`7D /* findlowestchild */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic void placetree(C(ptksstruct *) root, C(Pfloat *) x, C(Pfloat) y) XPreANSI(ptksstruct *root) XPreANSI(Pfloat *x) XPreANSI(Pfloat y) X/* X** \parambegin X** \param`7B`7D`7Broot`7D`7Bpointer to root structure record.`7D`7BIN`7D X** \param`7B`7D`7Bx`7D`7Bx coordinate of node`7D`7BIN`7D X** \param`7B`7D`7By`7D`7By coordinate of node`7D`7BIN`7D X** \paramend X** \blurb`7BPlaces a subtree.`7D X*/ X`7B X Pint n, fudge; X ptksref *r; X Pfloat fuzz, finetune, xx, xxinc; X X if (root->placed) X return; X X n = root->numunique; X X fudge = findlowestchild(root) - root->level; X X finetune = 1.0; X xxinc = topptr->xinc * fudge * finetune; X X xx = *x - ((Pfloat)n - 1.0) * xxinc / 2.0; X fuzz = topptr->nodewidth * 1.5; X X if (n > 1)`20 X `7B `20 X /* at least one child */ X if (xx <= topptr->rowmaxx`5Broot->level`5D + fuzz)`20 X `7B X printf("adjusting for overlap at level %ld\n", root->level + 1); X /* compute x pos of leftmost child */ X xx = topptr->rowmaxx`5Broot->level`5D + xxinc; X /* now readjust x to center node over its children */ X *x = xx + ((Pfloat)n - 1.0) * xxinc / 2.0; X `7D X `7D X X y = 0.0 - root->level * topptr->yinc; X X root->pos = ptk_point(*x, y); X X topptr->rowmaxx`5Broot->level - 1`5D = *x; X X root->placed = TRUE; X X r = root->firstchild; X while (r != NULL)`20 X `7B X placetree(r->structptr, &xx, y); X r = r->next; X xx += xxinc; X `7D X`7D /* placetree */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic void placenodes(C(void)) X/* X** \blurb`7BDraws all the nodes for the structures in the hierarchy.`7D X*/ X`7B X topptr->topx = 0.0; X topptr->topy = 0.0; X topptr->nodeheight = 1.0; X topptr->nodewidth = 1.0; X setnode(1.0, 1.0); X topptr->xinc = topptr->nodewidth * 2.0; X topptr->yinc = topptr->nodeheight * 2.0; X `20 X /* start it off with a silly value */ X X topptr->extent = ptk_limit3(1000000.0, -10000000.0, 10000000.0, X -10000000.0, 0.0, 1.0); X X /* Recursively place all the nodes, starting at 0,0. The diagram X ** will grow downwards, and its ultimate extent will be in `60extent'. X ** Everytime a new bit is drawn, its position is noted with `60note', X ** which updates the extent.`20 X */ X X placetree(topptr->structlist, &topptr->topx, topptr->topy); X`7D /* placenodes */ X X/*-------------------------------------------------------------------------- V*/ X Xstatic void drawnode(C(ptksstruct *) sp) XPreANSI(ptksstruct *sp) X/* X** \parambegin X** \param`7B`7D`7Bsp`7D`7Bpointer to structure record`7D`7BIN`7D X** \paramend X** \blurb`7BDraws a node to represent the structure at sp in the X** structure list, and the node will go into the diagram at xx, yy.`7D X*/ X`7B X Ppoint3 sh; X Ppointlst sets; X Pint err, elptr; X X sh = ptk_point3(sp->pos.x, sp->pos.y, 0.0); X ptk_shift3(&sh, PREPLACE, topptr->mat); X sets.number = topptr->nodebounds; X sets.points = topptr->nodepoints; X if (nodeidcount == topptr->highlightnode) X `7B X /* jump to `60highlightnode' label */ X pinqelemptr(&err, &elptr); X psetelemptr(0); X psetelemptrlabel(ptk_stringtoint("label", "highlightnode")); X psetpickid(sp->name); X psetlocaltran3(topptr->mat, PREPLACE); X ptk_fillareaset(1, &sets); X /* jump back */ X psetelemptr(elptr + 3); X `7D X else X `7B X psetpickid(sp->name); X psetlocaltran3(topptr->mat, PREPLACE); X ptk_fillareaset(1, &sets); X `7D X note(sp->pos.x, sp->pos.y); X`7D /* drawnode */ X +-+-+-+-+-+-+-+- END OF PART 256 +-+-+-+-+-+-+-+-