Tidy tree plotting.
April Gillam
gillam at aero.ARPA
Tue Nov 11 01:05:28 AEST 1986
The following programs draw a series of nodes with connecting ports
between them. It was written for the Apollo DN300. The graphics is
specific to that, however the tidy_tree() algorithm is general.
Tidy_tree() is expanded from the following 2 papers which only deal
with binary trees. Mine works with multiple parents and children, but
can only have one node at the top.
Tidy Drawing of Trees by C. Wetherell & A. Shannon IEEE Vol. SE-5 #5
Sept 79 pp. 514-520
Tidier Drawings of Trees by E. Reingold & J. Tilford IEEE Vol. SE-7 #2
Mar '81 pp. 223-228
I tried to separate out all the Apollo routines into "ifdef APOLLO",
but I haven't run it on anything else yet, so I'm not sure how well that
goes. I will be getting this up on the Sun eventually. In 'trlib.c', the
library routines, there are many Apollo calls, which I haven't put into
ifdef's. However to run elsewhere, you'll probably need to rewrite these
anyway.
There are 3 input files:
acglimits.data has window sizes, labels, spacing of nodes & the name
of the files containing node and port data
acgnode.data in this eg. has the node data
acgport.data in this eg. has the port data
I hope the code is readable & understandable. It works as is.
To run type: tr
On the Apollo you can scroll using the regular boxed arrow keys & type q to
quit. If you make any enhancements, please post them or let me know.
acgnode.data format:
node# . 0 . children node#'s . 0 . name of node . level . nth on that lvl . total # on that lvl . BOX or CIRCLE .
acgport.data format:
port name . from node# . to node# .
-----Cut Here-----Cut Here-----Cut Here-----Cut Here-----
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# acgnode.data
# acgport.data
# acglimits.data
# maketr
# tr.incl.h
# tr.c
# trlib.c
sed 's/^X//' << 'SHAR_EOF' > acgnode.data
X500 . 0 . 400 402 . 0 . the event is valid [false high] . 1 . 1 . 1 . BOX .
X400 . 0 . 705 . 0 . mission processing is credible [true high] . 7 . 1 . 2 . BOX .
X402 . 0 . 700 . 0 . the technical evaluation of the event is good [false high] . 2 . 1 . 1 . BOX .
X705 . 0 . 0 . 0 . system and display are normal [true high] . 5 . 1 . 1 . BOX .
X700 . 0 . 410 424 . 0 . the pattern is a good signature [false high] . 3 . 1 . 1 . BOX .
X410 . 0 . 707 . 0 . attitude is the only suspected system error [false high] . 6 . 1 . 2 . BOX .
X424 . 0 . 451 120 . 0 . there are enough clean points in the event [false high] . 4 . 1 . 1 . BOX .
X707 . 0 . 705 . 0 . defaults are set for identified anomalies which affect processing [true high] . 7 . 2 . 2 . BOX .
X451 . 0 . 707 . 0 . some of the points in the event are lost [false high] . 6 . 2 . 2 . BOX .
X120 . 0 . 118 . 0 . event is free of transient noise bursts [false high] . 8 . 1 . 1 . BOX .
X118 . 0 . 0 . 0 . number of points passing transient noise test [2] . 9 . 1 . 1 . BOX .
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > acgport.data
Xrule250 . 400 . 500 .
Xrule250 . 402 . 500 .
Xrule490 . 705 . 400 .
Xrule320 . 700 . 402 .
Xrule450 . 410 . 700 .
Xrule450 . 424 . 700 .
Xrule412 . 707 . 410 .
Xrule470 . 451 . 424 .
Xrule470 . 120 . 424 .
Xrule447 . 705 . 707 .
Xrule706 . 707 . 451 .
Xrule131 . 118 . 120 .
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > acglimits.data
X,GRAPH_TITLE Dynamic Logic Trace
X,NODE_FILE acgnode.data
X,PORT_FILE acgport.data
X,BOX_HALF_WIDTH 45
X,BOX_HALF_HEIGHT 25
X,RADIUS 30
X,NODE_LABEL 1
X,MAXX_WINDOW 1000
X,MAXY_WINDOW 750
X,MINX_WINDOW 0
X,MINY_WINDOW 0
X,MIN_X_SPACE 30
X,MIN_Y_SPACE 40
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > maketr
Xtr: tr.o trlib.o tr.incl.h
X cc -o tr tr.o trlib.o
Xtr.o: tr.c trlib.o tr.incl.h
X cc tr.c trlib.o -c -g -DAPOLLO
Xtrlib.o: trlib.c tr.incl.h
X cc trlib.c -c -DAPOLLO
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > tr.incl.h
X#include <stdio.h>
X#include <ctype.h>
X#include <math.h>
X#ifdef APOLLO
X#include </sys/ins/base.ins.c>
X#include </sys/ins/pad.ins.c>
X#include </sys/ins/gpr.ins.c>
X#include </sys/ins/kbd.ins.c>
X#endif APOLLO
X
X#define MAXNODE 300
X#define MAXPORT 600
X#define PI 3.1415926536
X
X#define TOP 1
X#define RHS 2
X#define BOT 3
X#define LHS 4
X#define MID 5
X
X#ifdef APOLLO
Xgpr_$keyset_t buttons = {0,0,0,0};
Xgpr_$keyset_t btn = {0,0,0,0};
Xgpr_$keyset_t keys = {0,0,0,0};
Xchar keystroke;
X
Xgpr_$bitmap_desc_t mem_bm,init_bitmap;
Xgpr_$event_t event_type;
X
Xstatus_$t st;
X#endif APOLLO
X
Xchar GRAPH_TITLE[128],NODE_FILE[128],PORT_FILE[128];
X
Xfloat mnx,mny,scl;
Xfloat xx[1000], yy[1000];
Xfloat char_size, char_sz_sml; /* char_size is half character width */
X
Xshort x[1000],y[1000];
Xshort len, font_id, font_id_small;
Xshort delta_x, delta_y; /* distance between nodes */
Xshort char_width;
X
Xint node_max, port_max;
Xint char_height_text,char_width_text;
Xint MAXX_WINDOW[5], MAXY_WINDOW[5], MINX_WINDOW[5], MINY_WINDOW[5],
X MIN_Y_SPACE, MIN_X_SPACE,BOXWIDTH,BOXHT,RADIUS,NODE_LABEL;
X
Xstruct node_data
X {
X int node;
X char name[128];
X int target[5];
X int source[40];
X struct node_data *src[40];
X int cohort[5];
X int lvl; /* level of node 0=highest at top of graph
X 1=lower
X ...
X n=lowest at bottom of graph */
X int nth; /* order 1=first 2=second ... */
X int of; /* total # on this lvl */
X short x0; /* x0.y0 - center of node */
X short y0;
X int shape; /* 0=circle 1=box 2=rect ... */
X short wide; /* size of shape in x - radius or width */
X short ht; /* size of shape in y - radius or height */
X/* int inport[20]; */ /* ports into this node */
X/* int outport[20]; */ /* ports leaving this node */
X int pop; /* parent position */
X int flg; /* flag whether to write name or blank it out */
X } nodes[MAXNODE];
X
Xstruct node_data *nod[MAXNODE],*tmpnod;
X
Xstruct port_data
X {
X char name[128];
X int from_node; /* node# of source */
X int to_node; /* node# of target */
X int nth_from; /* nodes[nth_from].node = ports[].from_node */
X int nth_to; /* nodes[nth_to].node = ports[].to_node */
X short x0; /* x0,y0 - from port location */
X short y0;
X short xf; /* xf,yf - to port location */
X short yf;
X int side_from; /* TOP RHS BOT LHS MID */
X int side_to;
X int angle; /* angle of arrow from side, +angle=cw -angle=ccw */
X } ports[MAXPORT];
X
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > tr.c
X#include "tr.incl.h"
X/*
X tidy tree drawing routines expanded from :
XTidy Drawing of Trees by C. Wetherell & A. Shannon IEEE Vol. SE-5 #5
X Sept 79 pp. 514-520
XTidier Drawings of Trees by E. Reingold & J. Tilford IEEE Vol. SE-7 #2
X Mar '81 pp. 223-228
X
X program written by April Gillam (gillam at aerospace.arpa)
X Aerospace Corp.
X 2350 El Segundo Blvd. M1-102
X El Segundo, Ca. 90245
X*/
Xint tidy_tree(),text(),check(),setbutton(),clearbutton(),closest(),edge(),
X circle(),set_node_locs(),prnt_in_box(),
X where_port(),set_port(),rectangle(),arrow2(),init();
Xint askacg,lvlstart[20];
X
Xmain(argc,argv)
Xchar *argv[];
Xint argc;
X{
Xint loop, j;
Xshort position[2];
X#ifdef APOLLO
Xgpr_$window_t src_wind;
Xgpr_$position_t dest_orig,cursor_pos;
X#endif APOLLO
X
X read_limits();
X
X init(); /* initialize graphics */
X
X/*
X askacg == 1 ask user for acgnode.data & acgport.data file names
X < 0 use small boxes & don't print words in box
X*/
X if(argc > 1) askacg = atoi(argv[1]);
X else askacg = 0;
X if(askacg < 0){
X BOXWIDTH = 20; BOXHT = 15; RADIUS = 15; MIN_X_SPACE = 10;
X MIN_Y_SPACE = 10;
X printf("enter BOXWIDTH BOXHT: ");
X scanf("%d %d",&BOXWIDTH,&BOXHT);
X }
X
X node_max = read_node_data(askacg);
X
X len = node_max;
X
X tidy_tree(node_max);
X
X port_max = read_port_data(askacg);
X
X#ifdef APOLLO
X gpr_$set_bitmap(mem_bm,st); check(st);
X
X set_node_locs();
X
X src_wind.x_coord = (short)0;
X src_wind.y_coord = (short)0;
X src_wind.x_size = MAXX_WINDOW[0] - MINX_WINDOW[0];
X src_wind.y_size = MAXY_WINDOW[0] - MINY_WINDOW[0];
X
X dest_orig.x_coord = (short) 0;
X dest_orig.y_coord = (short) 0;
X
X gpr_$set_bitmap(init_bitmap,st); check(st);
Xgpr_$acquire_display(st); check(st);
X gpr_$pixel_blt(mem_bm,src_wind,dest_orig,st); check(st);
X gpr_$set_cursor_active(true,st); check(st);
X for(loop=1;loop;) {
X for(loop=1;loop==1;){
X gpr_$event_wait(event_type,keystroke,position,st);check(st);
X switch(event_type){
X case gpr_$locator: gpr_$set_cursor_position(position,st);break;
X case gpr_$keystroke:
X/* case gpr_$buttons: */
X switch(255&keystroke){
X/* case 'c': closest(position);loop=2;break;
X case 'b': edge(position); loop=2;break;
X*/
X case 'q': loop=0;break;
X case KBD_$L4:
X src_wind.x_coord = (short) 0;
X cursor_pos.x_coord = 0;
X cursor_pos.y_coord = position[1];
X gpr_$set_cursor_position(cursor_pos,st);check(st);
X break;
X case KBD_$L6:
X src_wind.x_coord = MAXX_WINDOW[1] - src_wind.x_size;
X cursor_pos.x_coord = src_wind.x_coord;
X cursor_pos.y_coord = position[1];
X gpr_$set_cursor_position(cursor_pos,st);check(st);
X break;
X case KBD_$L7:
X src_wind.x_coord = src_wind.x_coord - 100;
X if(src_wind.x_coord < 0)
X src_wind.x_coord = 0;
X break;
X case KBD_$L8S:
X src_wind.y_coord = src_wind.y_coord - 10;
X if(src_wind.y_coord < 0)
X src_wind.y_coord = 0;
X break;
X case KBD_$L9:
X src_wind.x_coord = src_wind.x_coord + 100;
X if(src_wind.x_coord > (MAXX_WINDOW[1] - src_wind.x_size))
X src_wind.x_coord = MAXX_WINDOW[1] - src_wind.x_size;
X break;
X case KBD_$LAS:
X src_wind.x_coord = src_wind.x_coord - 10;
X if(src_wind.x_coord < 0)
X src_wind.x_coord = 0;
X break;
X case KBD_$LCS:
X src_wind.x_coord = src_wind.x_coord + 10;
X if(src_wind.x_coord > (MAXX_WINDOW[1] - src_wind.x_size))
X src_wind.x_coord = MAXX_WINDOW[1] - src_wind.x_size;
X break;
X case KBD_$LD:
X src_wind.y_coord = src_wind.y_coord - 100;
X if(src_wind.y_coord < 0)
X src_wind.y_coord = 0;
X break;
X case KBD_$LES:
X src_wind.y_coord = src_wind.y_coord + 10;
X if(src_wind.y_coord > MAXY_WINDOW[1] - src_wind.y_size)
X src_wind.y_coord = MAXY_WINDOW[1] - src_wind.y_size;
X break;
X case KBD_$LF:
X src_wind.y_coord = src_wind.y_coord + 100;
X if(src_wind.y_coord > MAXY_WINDOW[1] - src_wind.y_size)
X src_wind.y_coord = MAXY_WINDOW[1] - src_wind.y_size;
X break;
X default:
X break;
X } /* switch keystroke */
X gpr_$pixel_blt(mem_bm,src_wind,dest_orig,st); check(st);
X break;
X } /* switch event_type */
X } /* loop */
X } /* loop */
X
Xgpr_$release_display(st);check(st);
X gpr_$terminate(true,st);check(st);
X#endif APOLLO
X}
X/* ************************************************************ */
X/* nmax = # of nodes
X*/
Xtidy_tree(nmax)
Xint nmax;
X{
Xint j,k,m,nlvl,lvl,oldlvl,maxlvl,xdelta,ydelta,pop,jth,j0,jf;
Xint n_per_lvl[20],next_pos,xmin,xmax,xchild,xparent,mostx,cnt,l,jj;
X
Xxdelta=120; ydelta = 100;
Xfor(j=0;j<20;j++)
X n_per_lvl[j]=0;
Xmaxlvl = 0;
Xfor(j=0;j<nmax;j++){
X nod[j] = &nodes[j];
X if(nodes[j].lvl > maxlvl) maxlvl = nodes[j].lvl;
X }
X/*
X set lvls
X*/
X/* find top assertion assuming there is only one at the top */
Xfor(j=0;j<nmax;j++){
X if(nodes[j].lvl > 1) nodes[j].lvl = 0;
X nodes[j].pop = 0;
X }
Xfor(lvl = 1; lvl <= maxlvl; lvl++) {
X for(j = 0; j<nmax; j++){
X if(nodes[j].lvl != lvl) continue;
X k = 0;
X while(nodes[j].source[k] != 0){
X for(m=0; m<nmax; m++)
X if(nodes[m].node == nodes[j].source[k]) {
X nodes[m].lvl = lvl + 1;
X break;
X }
X k++;
X }
X }
X }
X/*
X sort by lvl
X*/
Xfor(k=0;k<nmax-1;k++){
Xfor(j=k;j<nmax-1;j++){
X if(nod[j]->lvl > nod[j+1]->lvl){
X tmpnod = nod[j];
X nod[j] = nod[j+1];
X nod[j+1] = tmpnod;
X }
X }
X }
X/*
X find where each lvl begins
X*/
Xfor(j=1; j<=maxlvl; j++) lvlstart[j] = nmax;
Xlvl = 1;
Xfor(j=0; j<nmax; j++){
X lvl = nod[j]->lvl;
X if(j < lvlstart[lvl]) lvlstart[lvl] = j;
X }
Xwhile(lvlstart[maxlvl] == nmax) maxlvl--;
X/*
X set src ptr to nod source
X*/
Xfor(j=nmax-1;j>=0;j--){
X m = 0;
X if(nod[j]->source[0] == 0) nod[j]->src[0] = NULL;
X else while(nod[j]->source[m] != 0){
X for(k=j+1; k<nmax;k++)
X if(nod[k]->node == nod[j]->source[m]){
X nod[j]->src[m] = nod[k];
X break;
X }
X m++;
X }
X }
Xfor(j=0;j<nmax;j++){
X lvl = nodes[j].lvl;
X ++n_per_lvl[lvl];
X }
X/*
X make sure children of same parents are next to each other
X pop only keeps track of one of parents, what if multiple parents???
X*/
Xfor(lvl = 1; lvl < maxlvl; lvl++) {
X pop = 0;
X printf("lvl=%d: ",lvl);
X j0 = lvlstart[lvl]; jf = lvlstart[lvl+1];
X for(j=j0; j<jf; j++){
X if(nod[j]->source[0] == 0) continue;
X pop++;
X m = 0;
X while(nod[j]->source[m] != 0){
X (nod[j]->src[m])->pop = pop;
X printf("src[%d]pop(%d) ",nod[j]->source[m],pop);
X m++;
X }
X }
Xprintf("\n");
X/* for each lvl exchange children positions so siblings are together */
X j0 = lvlstart[lvl+1]; jf = lvlstart[lvl+2];
X for(jj=j0; jj<jf-1; jj++){
X if(nod[jj]->pop == 0) continue;
X k = jj;
X while(k+1 < nmax && nod[++k]->lvl == lvl+1){
X if(nod[jj]->pop <= nod[k]->pop) continue;
X tmpnod = nod[jj];
X nod[jj] = nod[k];
X nod[k] = tmpnod;
X }
X }
Xprintf("\t\t");
X for(jj = j0; jj < jf; jj++)
X printf("%d(%d) ",nod[jj]->node,nod[jj]->pop);
X printf("\n");
X }
X/* x spacing - initial values */
Xfor(lvl = 1; lvl <= maxlvl; lvl++) {
X printf("lvl %d) ",lvl);
X next_pos = xdelta;
X j0 = lvlstart[lvl]; jf = lvlstart[lvl+1];
X for(j = j0; j<jf; j++){
X nod[j]->x0 = next_pos;
X next_pos = next_pos + xdelta;
Xprintf("%d<%d> ",nod[j]->node,nod[j]->x0);
X }
Xprintf("\n");
X }
X/*
X assign ycoord
X*/
X ydelta = (MAXY_WINDOW[0] - MINY_WINDOW[0]) / maxlvl;
X if(ydelta < 3.5*BOXHT)
X ydelta = 3.5*BOXHT;
X if(ydelta > (MAXY_WINDOW[1] - MINY_WINDOW[1]) / maxlvl)
X ydelta = (MAXY_WINDOW[1] - MINY_WINDOW[1]) / maxlvl;
Xfor(j=0;j<nmax;j++){
X lvl = nodes[j].lvl;
X nodes[j].y0 = lvl * ydelta;
X }
X/*
X algorithm to assign xcoord
X*/
X x_space(maxlvl,nmax,xdelta);
X
Xprintf("node x0 y0 lvl\n");
Xfor(j=0;j<nmax;j++){
X printf("%d %5d %5d %3d\n",nod[j]->node,nod[j]->x0,nod[j]->y0,nod[j]->lvl);
X }
X
X}
X/* ************************************************************ */
Xx_space(maxlvl,nmax,xdelta)
Xint maxlvl,nmax,xdelta;
X{
Xint m,oldlvl,next_pos,jj,j,k,imin,xmin,xmax,lvl,new,xshift,j0,jf;
X/*
X algorithm to assign xcoord
X*/
Xnext_pos=xdelta;
Xm=0; oldlvl=maxlvl;
Xfor(j=nmax-1;j>=0;j--){
X lvl = nod[j]->lvl;
X if(lvl == oldlvl) m++;
X else{
X/* make sure nodes are not on top of one another */
X next_pos=xdelta;
X j0 = lvlstart[oldlvl]; jf = lvlstart[oldlvl+1];
X for(jj = jf-1; jj>=j0; jj--){
X for(k = jf-1; k >=j0; k--){
X if(k == jj) continue;
X if(abs(nod[jj]->x0 - nod[k]->x0) < xdelta)
X nod[k]->x0 = nod[jj]->x0 + xdelta;
X }
X }
X m=1;
X oldlvl = lvl;
X } /* else */
X/* leaf */
X if(nod[j]->source[0] == 0){
X nod[j]->x0 = next_pos;
X same_spot(xdelta,nmax,lvl,nod[j]->x0,nod[j]->node);
X next_pos = next_pos+xdelta;
X }
X/* children */
X else{
X k = 0; xmax=0; xmin=4096;
X while(nod[j]->source[k] != 0){
X if(xmin > (nod[j]->src[k])->x0)
X xmin = (nod[j]->src[k])->x0;
X if(xmax < (nod[j]->src[k])->x0)
X xmax = (nod[j]->src[k])->x0;
X k++;
X }
X new = (xmax+xmin)/2;
X if(new < next_pos) new = next_pos;
X nod[j]->x0 = new;
X same_spot(xdelta,nmax,lvl,nod[j]->x0,nod[j]->node);
X next_pos = new + xdelta;
X } /* else */
X } /* for j=nmax-1 */
Xprintf("Phase I\n");
Xfor(lvl = 1; lvl <= maxlvl; lvl++) {
X printf("lvl %d) ",lvl);
X j0 = lvlstart[lvl]; jf = lvlstart[lvl+1];
X for(j = j0; j<jf; j++)
X printf("%d<%d> ",nod[j]->node,nod[j]->x0);
X printf("\n");
X }
X/* put children beneath parents:
X one parent
X leaf: directly beneath
X bros: equidistant
X multi parents
X leaf: equidistant
X bros: ???
X*/
X/* lvl 1 only has 1 node, so don't need to check if one
X node obscures another
X*/
Xfor(j=1;j<nmax;j++)
X same_spot(xdelta,nmax,nod[j]->lvl,nod[j]->x0,nod[j]->node);
X
Xfor(lvl=1; lvl<maxlvl; lvl++){
X j0 = lvlstart[lvl]; jf = lvlstart[lvl+1];
X for(j = jf-1; j>=j0; j--){
X m = 0; k = 0;
X while(nod[j]->source[k++] != 0) m++;
X/* one parent leaf */
X if(m == 1){
X xshift = nod[j]->x0 - nod[j]->src[0]->x0;
X if(xshift > xdelta/2) {
X printf("parent %d at %d xshift=%d xdelta=%d\n",nod[j]->node,nod[j]->x0,xshift,xdelta);
X printf("\tchild=%d at %d\n",nod[j]->source[0],nod[j]->src[0]->x0);
X shift_rt(nod[j]->src[0]->lvl,nod[j]->source[0],xshift,nmax,xdelta);
X }
X } /* m = 1 */
X/* one parent >1 child */
X else if(m > 1){
X k = 0; xmax=0; xmin=4096;
X while(nod[j]->source[k] != 0){
X if(xmin > (nod[j]->src[k])->x0) {
X xmin = (nod[j]->src[k])->x0; imin = k; }
X if(xmax < (nod[j]->src[k])->x0)
X xmax = (nod[j]->src[k])->x0;
X k++;
X }
X if((nod[j]->x0 - xmin) - (xmax - nod[j]->x0) <= xdelta) continue;
X xshift = nod[j]->x0 - (xmax+xmin)/2;
X if(xshift > xdelta/2) {
X printf("parent %d at %d xshift=%d xdelta=%d\n",nod[j]->node,nod[j]->x0,xshift,xdelta);
X for(jj=0;jj<m;jj++)
X printf("\tchildren=%d at %d\n",nod[j]->source[jj],nod[j]->src[jj]->x0);
X shift_rt(nod[j]->src[0]->lvl,nod[j]->source[imin],xshift,nmax,xdelta);
X }
X } /* else m>1 */
X } /* for j=jf-1 ... */
X
X } /* lvl */
X}
X/* ************************************************************ */
X/* shift lvl nodes, starting with nbro, to the right by xshift
X*/
Xshift_rt(lvl,nbro,xshift,nmax,xdelta)
Xint lvl,nbro,xshift,nmax,xdelta;
X{
Xint i,flag,old_x,j0,jf,xdif;
X flag = 0;
X printf("lvl=%d\n",lvl);
X j0 = lvlstart[lvl]; jf = lvlstart[lvl+1];
X for(i=j0; i<jf; i++)
X if(nod[i]->node == nbro) old_x = nod[i]->x0;
X
X for(i=j0; i<jf; i++){
X printf("\t(%d)x=%d->",nod[i]->node,nod[i]->x0);
X if(nod[i]->x0 >= old_x) nod[i]->x0 += xshift;
X printf("%d\n",nod[i]->x0);
X }
X old_x += xshift;
X for(i=j0; i<jf; i++){
X if(nod[i]->node == nbro) continue;
X if(abs(xdif = nod[i]->x0 - old_x) < xdelta) {
X printf("\t**** %d is at %d oops! (%d at %d)\n",nod[i]->node,nod[i]->x0,nbro,old_x);
X
X }
X }
X}
X/* ************************************************************ */
X/*
X check that node=nmbr at xspot is the only one there
X*/
Xsame_spot(xdelta,nmax,lvl,xspot,nmbr)
Xint xdelta,nmax,lvl,xspot,nmbr;
X{
Xint jj,k,xshift,j0,jf,j;
X j0 = lvlstart[lvl]; jf = lvlstart[lvl+1];
X for(j=j0; j<jf; j++){
X if(nod[j]->node == nmbr) continue;
X if(abs(nod[j]->x0 - xspot) >= xdelta) continue;
X
X xshift = nod[j]->x0 - xspot;
X
X if(xshift < xdelta && xshift > 0)
X shift_rt(lvl,nod[j]->node,xdelta-xshift,nmax,xdelta);
X
X else if(abs((double)xshift) < xdelta && xshift < 0)
X shift_rt(lvl,nod[k]->node,xdelta+xshift,nmax);
X }
X}
X/*
X************************* node locations ********************************
X*/
Xset_node_locs()
X{
Xint nlvl, i, j, k, n_per_lvl[20], label_node;
Xchar str[128];
Xshort del_x,del_y,xcenter, ycenter;
Xshort xpt, ypt,xxx[5],yyy[5],xmid,ymid;
Xshort box_w,box_h,box_w_fr,box_w_to;
X /* read from acglimits.data file */
Xshort MIN_BOX_W,MIN_BOX_H,MAX_BOX_W,MAX_BOX_H;
X
XFILE *datafile, *fopen();
Xint nn,nx,ny;
X MIN_BOX_W = 20;
X MIN_BOX_H = 20;
X MAX_BOX_W = 120;
X MAX_BOX_H = 120;
X
X for(j = 0; j < 20; j++) n_per_lvl[j] = 0;
X nlvl = 0;
X for(i = 0; i < node_max; i++){
X j = nodes[i].lvl;
X if(j > nlvl) nlvl = j;
X n_per_lvl[j]++;
X }
X nlvl++;
X label_node = NODE_LABEL;
X/* y spacing */
X del_y = (MAXY_WINDOW[0] - MINY_WINDOW[0]) / nlvl;
X/* assumes have a box & not a circle -- fix so handles circles too */
X if( del_y < 2*BOXHT)
X del_y = (MAXY_WINDOW[1] - MINY_WINDOW[1]) / nlvl;
X/* title for graph */
X/* fix so center of memory_bm ??? */
X/* xpt = (MAXX_WINDOW[0] - MINX_WINDOW[0]) / 2 - char_size*strlen(GRAPH_TITLE); */
X/* assuming only one node at the top */
X xpt = nodes[0].x0 - char_size*strlen(GRAPH_TITLE);
X ypt = del_y/3;
X text(xpt,ypt,GRAPH_TITLE);
X/* x spacing */
X for(i = 1; i < nlvl; i++){ /* # of levels */
X for(k = 0; k < node_max; k++){ /* actual node data */
X if(nodes[k].lvl == i) {/* weed out those not on this lvl */
X
X del_x = (MAXX_WINDOW[0] - MINX_WINDOW[0]) / (n_per_lvl[i] + 1);
X/* assumes have a box & not a circle -- fix so handles circles too */
X if( del_x < 2*BOXWIDTH)
X del_x = (MAXX_WINDOW[1] - MINX_WINDOW[1]) / (n_per_lvl[i] + 1);
X/* if(RADIUS >= del_x && BOXWIDTH >= del_x){ */
X if(nodes[k].shape == 0) { box_h = 2*RADIUS;
X box_w = 2*RADIUS; }
X else { box_h = 2*BOXHT;
X box_w = 2*BOXWIDTH; }
X if(box_h > MAX_BOX_H) box_h = MAX_BOX_H;
X if(box_h < MIN_BOX_H){
X printf("Box height( = %ld) is too small\n\tEither increase window size in acglimits.data\n\tor decrease the # of node levels!\n",(long) box_h);
X exit(0);
X }
X if(box_w > MAX_BOX_W) box_w = MAX_BOX_W;
X if(box_w < MIN_BOX_W){
X printf("Box width( = %ld) is too small\n\tEither increase window size in acgdefs\n\tor decrease the # of node levels!\n",(long) box_w);
X exit(0);
X }
X/* } */ /* comparison to del_x */
X/* else {
X box_w = del_x;
X box_h = 0.5*del_y;
X }
X*/
X nodes[k].wide = box_w;
X nodes[k].ht = box_h;
X/* from tidy_tree */
X xcenter = nodes[k].x0;
X ycenter = nodes[k].y0;
X/* offset should be set here
X xcenter += xoffset;
X*/
X
X/* shape 0 = circle 1 = box */
X if(nodes[k].shape == 0) circle(xcenter,ycenter,RADIUS);
X else rectangle(xcenter,ycenter,box_w,box_h);
X
X/* print node# */
X#ifdef APOLLO
X gpr_$set_text_font(font_id,st);check(st);
X#endif APOLLO
X sprintf(str,"%d",nodes[k].node);
X xpt = xcenter - char_size*strlen(str);
X ypt = ycenter - nodes[k].ht/2 + 2*char_size;
X text(xpt, ypt,str);
X
X#ifdef APOLLO
X gpr_$set_text_font(font_id_small,st);check(st);
X#endif APOLLO
X/* print name */
X ypt = ycenter - nodes[k].ht/2 + 4*char_size;
X if(label_node == 1 && askacg >= 0)
X prnt_in_box(k,xcenter,ypt,del_x);
X
X } /* nodes.lvl ok */
X } /* for k < node_max */
X } /* for nlvl */
X/* arrows */
X where_port(port_max);
X for(i = 0; i < port_max; i++){
X box_w_fr = nodes[ports[i].nth_from].wide;
X box_w_to = nodes[ports[i].nth_to].wide;
X if(ports[i].side_from == BOT && ports[i].side_to == BOT) {
X xmid = ports[i].x0 + (ports[i].xf - ports[i].x0)/2;
X ymid = ports[i].y0 + (del_y - box_h)/4;
X#ifdef APOLLO
X gpr_$set_text_font(font_id,st);check(st);
X arrow(ports[i].x0,ports[i].y0,ports[i].xf,ports[i].yf,xmid,ymid,ports[i].name);
X gpr_$set_text_font(font_id_small,st);check(st);
X#endif APOLLO
X }
X else {
X#ifdef APOLLO
X gpr_$set_text_font(font_id,st);check(st);
X arrow(ports[i].x0,ports[i].y0,ports[i].xf,ports[i].yf,0,0,ports[i].name);
X gpr_$set_text_font(font_id_small,st);check(st);
X#endif APOLLO
X }
X
X }
X}
X/* ************************** set port sides *********************** */
Xwhere_port(pmax)
Xint pmax;
X{
Xint i, j, port_n, n, nthfr, nthto, jfr, jto;
X/*
X
X set from_node & to_node values to the subscript, nth, for nodes[nth]
X this is slow & cumbersome - find a faster way
X
X set x0,y0 xf,yf
X*/
X for(i = 0; i < pmax; i++){ /* ports */
X nthfr = -1;
X nthto = -1;
X for(j = 0; j < node_max; j++){ /* nodes */
X if(ports[i].from_node == nodes[j].node) {
X nthfr = ports[i].nth_from = j;
X }
X if(ports[i].to_node == nodes[j].node) {
X nthto = ports[i].nth_to = j;
X }
X } /* nodes */
Xif(nthfr < 0 || nthto < 0) printf("read_port_data: %d to %d missing node\n",
X ports[i].from_node,ports[i].to_node);
X/*
X check level to decide where to put port
X*/
X if(nodes[nthfr].lvl > nodes[nthto].lvl) {
X jfr = ports[i].side_from = TOP;
X jto = ports[i].side_to = BOT;
X }
X else if(nodes[nthfr].lvl < nodes[nthto].lvl) {
X jfr = ports[i].side_from = BOT;
X jto = ports[i].side_to = TOP; }
X else { /* same lvl so see if next to each other */
X if(nodes[nthfr].nth == nodes[nthto].nth + 1) {
X jfr = ports[i].side_from = LHS;
X jto = ports[i].side_to = RHS;
X }
X else if(nodes[nthfr].nth == nodes[nthto].nth - 1) {
X jfr = ports[i].side_from = RHS;
X jto = ports[i].side_to = LHS;
X }
X else { /* not next to each other -- oh no! */
X/*
X don't know how to deal with if not next to each other - do later
X for now put port on bottom
X*/
X jfr = ports[i].side_from = BOT;
X jto = ports[i].side_to = BOT;
X }
X } /* else same lvl */
X/*
X now find coordinates of the port
X*/
X set_port(jfr,nthfr,jto,nthto,i);
X
X /* later decide on angle depending on # of ports & other criteria */
X ports[nthto].angle = 0;
X } /* for i -- ports */
X}
X/* ************************** set port coordinates *********************** */
X/*
X nside1,nthnode1 - from
X 2 2 - to
X*/
Xset_port(nside1,nthnode1,nside2,nthnode2,ithport)
Xint nside1,nthnode1,nside2,nthnode2,ithport;
X{
Xint i,nside,nthnode;
Xshort xfr,yfr;
X/*
X now find coordinates of the port
X*/
X for(i=0; i < 2; i++){ /* i=0:from i=1:to */
X if(i == 0){
X nside = nside1;
X nthnode = nthnode1;
X }
X else{
X nside = nside2;
X nthnode = nthnode2;
X }
X if(nside == TOP){
X xfr = 0;
X yfr = -nodes[nthnode].ht/2;
X }
X else if(nside == BOT){
X xfr = 0;
X yfr = nodes[nthnode].ht/2;
X }
X else if(nside == RHS){
X xfr = nodes[nthnode].wide/2;
X yfr = 0;
X }
X else { /* LHS */
X xfr = -nodes[nthnode].wide/2;
X yfr = 0;
X }
X if(i == 0) {
X ports[ithport].x0 = nodes[nthnode].x0 + xfr;
X ports[ithport].y0 = nodes[nthnode].y0 + yfr;
X/* clipping */
X/* if(ports[ithport].x0 < MINX_WINDOW)
X ports[ithport].x0 = MINX_WINDOW;
X else if(ports[ithport].x0 > MAXX_WINDOW)
X ports[ithport].x0 = MAXX_WINDOW;
X if(ports[ithport].y0 < MINY_WINDOW)
X ports[ithport].y0 = MINY_WINDOW;
X else if(ports[ithport].y0 > MAXY_WINDOW)
X ports[ithport].y0 = MAXY_WINDOW;
X*/
X }
X else {
X ports[ithport].xf = nodes[nthnode].x0 + xfr;
X ports[ithport].yf = nodes[nthnode].y0 + yfr;
X/* clipping */
X/* if(ports[ithport].xf < MINX_WINDOW)
X ports[ithport].xf = MINX_WINDOW;
X else if(ports[ithport].xf > MAXX_WINDOW)
X ports[ithport].xf = MAXX_WINDOW;
X if(ports[ithport].yf < MINY_WINDOW)
X ports[ithport].yf = MINY_WINDOW;
X else if(ports[ithport].yf > MAXY_WINDOW)
X ports[ithport].yf = MAXY_WINDOW;
X*/
X }
X }
X}
X
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > trlib.c
X#include "tr.incl.h"
X/*
Xprnt_in_box(k,xcenter,ycenter,del_x)
Xrectangle(xcenter,ycenter,horiz_side_length,vert_side_length)
Xarrow2(x0,y0,xf,yf,xmid,ymid,label)
Xinit()
Xtext(x0,y0,titles)
Xcheck(st)
Xsetbutton(c,buttons)
Xclearbutton(buttons)
Xclosest(position)
Xedge(position)
Xcircle(xcenter,ycenter,radius)
Xarrow(x0,y0,xf,yf,xmid,ymid,label)
Xint read_port_data(askacg)
Xint read_node_data(askacg)
Xint read_limits()
X*/
X/* ************************************************************ */
Xprnt_in_box(k,xcenter,ycenter,del_x)
Xint k;
Xshort xcenter,ycenter,del_x;
X{
Xchar str[128],strip[128];
Xshort xpt,ypt,xspacing;
Xint nchars,j,j0,line,nlines,l,i,iflg;
Xfloat frac_nlines,length;
X/* print name */
X sprintf(str,"%s",nodes[k].name);
X length = strlen(str) - 1;
X i = 0;
X while(i< length && ispunct(str[i]) == 0) i++;
X/* while(i< length && strncmp(str[i],"[",1) != 0) i++; */
X nchars = nodes[k].wide/char_width_text;
X frac_nlines = i/nchars;
X nlines = frac_nlines;
X if (nlines < frac_nlines)
X nlines++;
X if(i < length) nlines++;
X iflg = 0;
X line = 0;
X j0 = 0;
X/* while(j0 < length){ */
X while(j0 < i){
X for(l=0;l<nchars+1;l++) strip[l] = '\0';
X/* if(j0+nchars > length) nchars = length - j0; */
X if(j0+nchars > i) nchars = i - j0;
X for(j=j0;j<j0+nchars; j++)
X strip[j-j0] = str[j];
X xpt = xcenter - (char_width_text*strlen(strip) - 2)/2;
X if(iflg == 1) line++;
X if (nodes[k].node < 100)
X ypt = ycenter + char_height_text/2 - ((nlines-1)*char_height_text)/2 + line*char_height_text;
X else
X ypt = ycenter + line*char_height_text;
X if(xpt < 0) xpt = 20;
X if(xpt > MAXX_WINDOW[1])
X printf("xpt = %ld is out of window\nCannot print: %s\n",(long) xpt,str);
X else {
X gpr_$move(xpt,ypt,st);check(st);
X gpr_$text(strip,(short) nchars,st);check(st);
X }
X line++;
X j0 += nchars;
X if(j0 >= i){
X nchars = length - i;
X i = length;
X iflg = 1;
X }
X } /* while */
X}
X/* ************************************************************ */
Xrectangle(xcenter,ycenter,horiz_side_length,vert_side_length)
Xshort xcenter, ycenter, horiz_side_length,vert_side_length;
X{
Xshort lenx, leny, xxx[10],yyy[10];
X lenx = horiz_side_length;
X leny = vert_side_length;
X
X xxx[3] = xxx[4] = xxx[0] = xcenter - lenx/2;
X yyy[4] = yyy[1] = yyy[0] = ycenter - leny/2;
X xxx[2] = xxx[1] = xcenter + lenx/2;
X yyy[3] = yyy[2] = ycenter + leny/2;
X
X gpr_$move(xxx[0],yyy[0],st); check(st);
X gpr_$polyline(xxx,yyy,(short)5,st); check(st);
X}
X
X/* ************************************************************ */
X/*
X arrow2 double lined arrow from x0,y0 to xf,yf
X angle is half-angle of arrowhead
X
X*/
Xarrow2(x0,y0,xf,yf,xmid,ymid,label)
Xshort x0,y0,xf,yf,xmid,ymid;
Xchar label[128];
X{
Xint quadrant, isignx, isigny, flgmidpt;
Xfloat angle,phi,r,tmp,tmpx,tmpy,rtip;
Xshort xxx[100], yyy[100], xpt, ypt, npt, savex0, savey0;
Xint length,i,j;
Xchar strip[40];
X
X angle = PI/12.0; /* head of arrow = 2 * angle = 30 degrees */
X/* phi = angle betw line & x-axis */
X flgmidpt = 0; /* flag = 1 if there's a midpoint */
X/* if there's a midpoint arrows has direction of xmid,ymid to xf,yf
X instead of x0,y0 to xf,yf
X*/
X if(xmid > 0 && ymid > 0){
X flgmidpt = 1;
X savex0 = x0;
X savey0 = y0;
X x0 = xmid;
X y0 = ymid;
X }
X tmpy = yf-y0;
X tmpx = xf-x0;
X if(fabs(tmpx) > 0.001) phi = atan(fabs(tmpy/tmpx));
X else phi = PI/2.0;
X quadrant = 1; /* xf < x0 & yf > y0 */
X if(xf < x0 && yf < y0) quadrant = 2;
X else if(xf > x0 && yf < y0) quadrant = 3;
X else if(xf > x0 && yf > y0) quadrant = 4;
X else if(xf > x0 && y0 == yf) quadrant = 3;
X else if(xf < x0 && y0 == yf) quadrant = 1;
X else if(xf == x0 && y0 < yf) quadrant = 1;
X else if(xf == x0 && y0 > yf) quadrant = 3;
X
X r = 10;
X rtip = 14;
X if(quadrant == 1) phi = - phi;
X else if(quadrant == 3){
X phi = -phi;
X r = -r; rtip = -rtip;
X }
X else if(quadrant == 4){
X r = -r; rtip = -rtip; }
X
X if(flgmidpt == 1){
X x0 = savex0;
X y0 = savey0;
X }
Xif(flgmidpt == 0){
X xxx[2] = xf + r*cos(phi+angle);
X yyy[2] = yf + r*sin(phi+angle);
X xxx[3] = xf + r*cos(phi-angle);
X yyy[3] = yf + r*sin(phi-angle);
X xxx[4] = xxx[0] = xxx[3] + x0 - xf;
X ypt = yyy[3] + y0 - yf;
Xif(yf == y0 || (yf < y0 && ypt <= y0) || (yf > y0 && ypt >= y0))
X yyy[4] = yyy[0] = ypt;
X/* else if(yf > y0 && ypt >= y0)
X yyy[4] = yyy[0] = ypt;
X*/
Xelse yyy[4] = yyy[0] = y0;
X xxx[1] = xxx[2] + x0 - xf;
X ypt = yyy[2] + y0 - yf;
Xif(yf == y0 || (yf < y0 && ypt <= y0) || (yf > y0 && ypt >= y0))
X yyy[1] = ypt;
X/* else if(yf > y0 && ypt >= y0)
X yyy[1] = ypt;
X*/
Xelse yyy[1] = y0;
X npt = 5;
X }
Xelse {
X xxx[2] = xmid + r*cos(phi+angle);
X yyy[2] = ymid + r*sin(phi+angle);
X xxx[3] = xf + r*cos(phi+angle);
X yyy[3] = yf + r*sin(phi+angle);
X xxx[4] = xf + r*cos(phi-angle);
X yyy[4] = yf + r*sin(phi-angle);
X xxx[6] = xxx[0] = xxx[4] + x0 - xf;
X yyy[6] = yyy[0] = yyy[4] + y0 - yf;
X xxx[1] = xxx[3] + x0 - xf;
X yyy[1] = yyy[3] + y0 - yf;
X xxx[5] = xmid + r*cos(phi-angle);
X yyy[5] = ymid + r*sin(phi-angle);
X npt = 7;
X }
X gpr_$move(xxx[0],yyy[0],st); check(st);
X gpr_$polyline(xxx,yyy,npt,st); check(st);
X
X angle = PI/4.0;
X/* arrowhead */
X if(flgmidpt == 0){
X xxx[3] = xxx[0] = xf; yyy[3] = yyy[0] = yf;
X xxx[1] = xf + rtip*cos(phi-angle);
X yyy[1] = yf + rtip*sin(phi-angle);
X xxx[2] = xf + rtip*cos(phi+angle);
X yyy[2] = yf + rtip*sin(phi+angle);
X npt = 4;
X }
X else{
X xxx[5] = xxx[2] =xf; yyy[5] = yyy[2] = yf;
X xxx[1] = xmid; yyy[1] = ymid;
X xxx[3] = xf + r*cos(phi-angle);
X yyy[3] = yf + r*sin(phi-angle);
X xxx[4] = xf + r*cos(phi+angle);
X yyy[4] = yf + r*sin(phi+angle);
X npt = 6;
X }
X
X gpr_$move(xxx[0],yyy[0],st); check(st);
X gpr_$polyline(xxx,yyy,npt,st); check(st);
X/* 2 lines of port label if there's a [...] phrase */
X if(yf == y0){
X if(xf <= x0){
X xpt = x0 - 2 * (strlen(label) - 1) * char_size;
X ypt = y0 + char_size;
X }
X else {
X xpt = x0 + 3 * char_size;
X ypt = y0 + char_size;
X }
X }
X else {
X ypt = y0 - char_size; /* BOXHT/2; */
X xpt = x0 - (strlen(label) - 1) * char_size;
X }
X text(xpt,ypt,label);
X/*
X for(j=0;j<i; j++)
X strip i = 0;
X while(ispunct(label[i]) == 0 && i< length) i++;
X for(j=0;j<length;j++) strip[j] = '\0';
X for(j=0;j<i; j++)
X strip[j] = label[j];
X*/
X/*
X if(flgmidpt == 0){
X xpt = x0 + (xf-x0)/5 - (strlen(strip) - 1) * char_size;
X if(yf > y0) ypt = y0 + 3*char_size;
X else ypt = y0 - BOXHT/2 - 3*char_size;
X }
X else{
X xpt = xmid - (strlen(strip) -1) * char_size;
X ypt = ymid -3;
X }
X text(xpt,ypt,strip);
X if(i < length - 1){
X for(j=0;j<length;j++) strip[j] = '\0';
X for(j=i;j<length; j++)
X strip[j-i] = label[j];
X if(flgmidpt == 0){
X xpt = x0 + (xf-x0)/5 - (strlen(strip) - 1) * char_size;
X if(yf > y0) ypt = y0 + 6*char_size;
X else ypt = y0 - BOXHT/2;
X }
X else{
X xpt = xmid - (strlen(strip) - 1) * char_size;
X ypt = ymid -3 + 3*char_size;
X }
X text(xpt,ypt,strip);
X }
X*/
X/*
X if(flgmidpt == 0){ */ /* no midpoint */
X/* xpt = x0 + (xf-x0)/2 - strlen(label-1) * char_size;
X ypt = y0 + 4*(yf-y0)/5 -3;
X }
X else{
X xpt = xmid - strlen(label) * char_size;
X ypt = ymid -3;
X }
X text(xpt,ypt,label);
X*/
X}
X/* ************************************************************ */
Xinit()
X{
X gpr_$offset_t disp_bm_size,mem_size;
X/* gpr_$bitmap_desc_t init_bitmap,mem_bm; */
X gpr_$attribute_desc_t attrib_bl_desc;
X short position[2];
X pad_$window_desc_t local_graphic_window_desc;
X stream_$id_t local_stream;
X
X local_graphic_window_desc.top = MINY_WINDOW[0];
X local_graphic_window_desc.left = MINX_WINDOW[0];
X local_graphic_window_desc.width = MAXX_WINDOW[0];
X local_graphic_window_desc.height = MAXY_WINDOW[0];
X disp_bm_size.x_size = MAXX_WINDOW[0] - MINX_WINDOW[0];
X disp_bm_size.y_size = MAXY_WINDOW[0] - MINY_WINDOW[0];
X
X scl = 1.0; mnx = MINX_WINDOW[0]; mny = MINY_WINDOW[0];
X
X pad_$create_window("",0,pad_$transcript,1,
X local_graphic_window_desc,local_stream,st);
X
X pad_$set_auto_close(local_stream,1,true,st); check(st);
X/* memory bitmap size */
X MINX_WINDOW[1] = 0;
X MINY_WINDOW[1] = 0;
X MAXX_WINDOW[1] = mem_size.x_size = (short) 4096;
X MAXY_WINDOW[1] = mem_size.y_size = (short) 2048;
X
X/* setbutton('q',btn);
X setbutton('c',buttons);
X setbutton('b',buttons);
X setbutton('B',buttons);
X*/
X setbutton('q',keys);
X setbutton(KBD_$L4,keys);
X setbutton(KBD_$L6,keys);
X setbutton(KBD_$L7,keys);
X setbutton(KBD_$L8S,keys);
X setbutton(KBD_$L9,keys);
X setbutton(KBD_$LAS,keys);
X setbutton(KBD_$LCS,keys);
X setbutton(KBD_$LD,keys);
X setbutton(KBD_$LES,keys);
X setbutton(KBD_$LF,keys);
X
X gpr_$init(gpr_$direct,local_stream,disp_bm_size,0,init_bitmap,st);check(st);
X gpr_$set_obscured_opt(gpr_$block_if_obs,st);
X gpr_$set_auto_refresh(true,st);
X
X gpr_$enable_input(gpr_$keystroke,keys,st); check(st);
X/* gpr_$enable_input(gpr_$buttons,buttons,st);check(st); */
X gpr_$enable_input(gpr_$locator,0,st);check(st);
X gpr_$set_cursor_active(true,st); check(st);
X
X gpr_$allocate_attribute_block(attrib_bl_desc,st); check(st);
X gpr_$allocate_bitmap(mem_size,(short) 0,attrib_bl_desc,mem_bm,st); check(st);
X gpr_$set_bitmap(mem_bm,st); check(st);
X
X/* fonts */
X gpr_$load_font_file("/sys/dm/fonts/f5x7",18,font_id_small,st); check(st);
X gpr_$set_text_font(font_id_small,st);check(st);
X gpr_$inq_character_width(font_id_small,"R",char_width,st); check(st);
X char_sz_sml = (long) char_width/2.0;
X gpr_$load_font_file("/sys/dm/fonts/scvc5x10.r.b",26,font_id,st); check(st);
X gpr_$set_text_font(font_id,st);check(st);
X gpr_$inq_character_width(font_id,"u",char_width,st); check(st);
X char_size = (long) char_width/2.0;
X
X char_width_text = 5 + 2;
X char_height_text = 7 + 1;
X}
X/* ************************************************************ */
Xtext(x0,y0,titles)
Xshort x0,y0;
Xgpr_$string_t titles;
X{
X gpr_$move(x0,y0,st);check(st);
X gpr_$text(titles,(short) strlen(titles),st);check(st);
X}
X/* ************************************************************ */
Xcheck(st)
Xstatus_$t st;
X{ if(st.all != status_$ok) error_$print(st);
X}
X/* ************************************************************ */
Xsetbutton(c,buttons)
Xchar c; int *buttons;
X{int j;
X j=c&255; buttons[7-j/32] |= 1<<(j%32);
X}
X/* ************************************************************ */
Xclearbutton(buttons)
Xint *buttons;
X{int i;
X for(i=0;i<4;i++) buttons[i]=0;
X};
X/* ************************************************************ */
Xclosest(position)
Xshort *position;
X{
Xint i, imin, dmin, d, s, t, namesz;
Xchar str[128];
Xshort where[2];
X
X dmin=4000000; /*arbitrary large number*/
X for(i=0;i<node_max;i++){
X s=position[0]-x[i];
X t=position[1]-y[i];
X d=s*s+t*t;
X if(dmin>d) {imin=i;dmin=d;};
X }
X sprintf(str,"%s",nodes[imin].name);
X
X/* see if name can fit on one line, else go to 2 or more lines */
X namesz = strlen(nodes[imin].name);
X delta_x = (MAXX_WINDOW[0] - MINX_WINDOW[0])/(nodes[imin].of + 1);
X if(char_size *namesz <= delta_x){
X s = x[imin] - char_size * namesz;
X if (s < 0) s = 0;
X }
X else{ /* split line up */
X s = x[imin] - char_size * namesz;
X if (s < 0) s = 0;
X }
X t = y[imin] + 2*RADIUS/3;
X if(t > MAXY_WINDOW[0]) t = y[imin];
X
X gpr_$set_cursor_active(false,st); check(st);
X
X if(nodes[imin].flg == 0) {
X gpr_$set_draw_value(gpr_$black,st);
X nodes[imin].flg = 1;
X }
X else {
X gpr_$set_draw_value(gpr_$white,st);
X nodes[imin].flg = 0;
X }
X where[0] = s; where[1] = t;
X gpr_$set_cursor_position(where,st);
X
X gpr_$move((short) s,(short) t,st);check(st);
X gpr_$text(str,(short) strlen(str),st);check(st);
X
X gpr_$set_cursor_active(true,st); check(st);
X
X gpr_$event_wait(event_type,keystroke,position,st);check(st);
X}
X/* ************************************************************ */
Xedge(position)
Xshort position[2];
X{int i,ip; float s,t,u,v,dd,d,e,dmin;
X short x1[3],y1[3],l;
X ip= -1;
X dmin=40000000.; /*arbitrary large number*/
X for(i=0;i<len;i++)
X { s=x[i+1]-x[i]; t=y[i+1]-y[i]; dd=sqrt(s*s+t*t);
X if(dd<=0) fprintf(stderr,"distance=0\n");
X s/=dd; t/=dd;
X u=position[0]-x[i]; v=position[1]-y[i];
X d=u*t-v*s; d=d*d; e=u*s+v*t;
X if((dmin>d)&&(e>0)&&(e<dd)) {dmin=d; ip=i+1;};
X };
X if(ip<0) return;
X
X len++;
X for(i=len;i>ip;i--)
X { x[i]=x[i-1];
X y[i]=y[i-1];
X }
X/* { x[i]=x[i-1]; xx[i]=xx[i-1];
X y[i]=y[i-1]; yy[i]=yy[i-1];
X }
X*/
Xgpr_$set_cursor_active(false,st); check(st);
Xi=ip-1; x1[0]=x[i];x1[2]=x[i+2];y1[0]=y[i];y1[2]=y[i+2];
Xx1[1]=(x1[0]+x1[2])/2;y1[1]=(y1[0]+y1[2])/2;
Xl=3;
Xfor(;;)
X{
X gpr_$set_draw_value(gpr_$black,st);
X gpr_$move(x[i],y[i],st);check(st);
X gpr_$polyline(x1,y1,l,st);
X x[ip] =x1[1] =position[0]; /* xx[ip] = (position[0]-10)/scl + mnx; */
X y[ip] =y1[1] =position[1]; /* yy[ip] = (position[1]-10)/scl + mny; */
X gpr_$set_draw_value(gpr_$white,st);
X gpr_$move(x[i],y[i],st);check(st);
X gpr_$polyline(x1,y1,l,st);
X
X gpr_$event_wait(event_type,keystroke,position,st);check(st);
X switch(event_type)
X {case gpr_$locator: break;
X case gpr_$buttons:
X if(keystroke=='B'){ gpr_$set_cursor_active(true,st); check(st);
X gpr_$set_cursor_position(position,st);
X return;}
X }
X}
X}
X
X/* ************************************************************ */
Xcircle(xcenter,ycenter,radius)
Xshort xcenter,ycenter,radius;
X{
Xgpr_$position_t center;
X
X center.x_coord = xcenter; center.y_coord = ycenter;
X gpr_$circle(center,radius,st);
X check(st);
X}
X/* ************************************************************ */
X/*
X arrow from x0,y0 to xf,yf ; angle is half-angle of arrowhead
X*/
Xarrow(x0,y0,xf,yf,xmid,ymid,label)
Xshort x0,y0,xf,yf,xmid,ymid;
Xchar label[128];
X{
Xint quadrant, isignx, isigny, flgmidpt;
Xfloat angle,phi,r,tmp,tmpx,tmpy;
Xshort xxx[100], yyy[100], xpt, ypt, npt, savex0, savey0;
X
X angle = PI/12.0; /* head of arrow = 2 * angle = 30 degrees */
X/* phi = angle betw line & x-axis */
X flgmidpt = 0; /* flag = 1 if there's a midpoint */
X/* if there's a midpoint arrows has direction of xmid,ymid to xf,yf
X instead of x0,y0 to xf,yf
X*/
X if(xmid > 0 && ymid > 0){
X flgmidpt = 1;
X savex0 = x0;
X savey0 = y0;
X x0 = xmid;
X y0 = ymid;
X }
X tmpy = yf-y0;
X tmpx = xf-x0;
X if(fabs(tmpx) > 0.001) phi = atan(fabs(tmpy/tmpx));
X else phi = PI/2.0;
X quadrant = 1; /* xf < x0 & yf > y0 */
X if(xf < x0 && yf < y0) quadrant = 2;
X else if(xf > x0 && yf < y0) quadrant = 3;
X else if(xf > x0 && yf > y0) quadrant = 4;
X else if(xf > x0 && y0 == yf) quadrant = 3;
X else if(xf < x0 && y0 == yf) quadrant = 1;
X else if(xf == x0 && y0 < yf) quadrant = 1;
X else if(xf == x0 && y0 > yf) quadrant = 3;
X
X r = 10;
X if(quadrant == 1) phi = - phi;
X else if(quadrant == 3){
X phi = -phi;
X r = -r;
X }
X else if(quadrant == 4) r = -r;
X
X if(flgmidpt == 1){
X x0 = savex0;
X y0 = savey0;
X }
X
X xxx[0] = x0; yyy[0] = y0;
X if(flgmidpt == 0){
X xxx[4] = xxx[1] =xf; yyy[4] = yyy[1] = yf;
X xxx[2] = xf + r*cos(phi-angle);
X yyy[2] = yf + r*sin(phi-angle);
X xxx[3] = xf + r*cos(phi+angle);
X yyy[3] = yf + r*sin(phi+angle);
X npt = 5;
X }
X else{
X xxx[5] = xxx[2] =xf; yyy[5] = yyy[2] = yf;
X xxx[1] = xmid; yyy[1] = ymid;
X xxx[3] = xf + r*cos(phi-angle);
X yyy[3] = yf + r*sin(phi-angle);
X xxx[4] = xf + r*cos(phi+angle);
X yyy[4] = yf + r*sin(phi+angle);
X npt = 6;
X }
X
X gpr_$move(xxx[0],yyy[0],st); check(st);
X gpr_$polyline(xxx,yyy,npt,st); check(st);
X
X if(yf == y0){
X if(xf <= x0){
X xpt = x0 - 2 * (strlen(label) - 1) * char_size;
X ypt = y0 + char_size;
X }
X else {
X xpt = x0 + 3 * char_size;
X ypt = y0 + char_size;
X }
X }
X else {
X ypt = y0 - char_size; /* BOXHT/2; */
X xpt = x0 - (strlen(label) - 1) * char_size;
X }
X text(xpt,ypt,label);
X
X
X
X/* if(flgmidpt == 0){ */ /* no midpoint */
X/* xpt = x0 + (xf-x0)/2 - strlen(label) * char_size;
X ypt = y0 + (yf-y0)/2 + 3;
X }
X else{
X xpt = xmid - strlen(label) * char_size;
X ypt = ymid + 3;
X }
X*/
X/* printf("\t\txpt=%ld ypt=%ld name=%s\n",(long)xpt,(long)ypt,label); */
X text(xpt,ypt,label);
X}
X/*
X ************************* read port data ***********************************
X*/
Xint read_port_data(askacg)
Xint askacg;
X{
XFILE *datafile, *fopen();
Xchar str[128],file[40];
Xint i, j, port_n, n, pmax, nthfr, nthto, jfr, jto;
X/* start with node already in correct order, later do sorting */
X
X i = 0;
X port_n = 0;
X pmax = 0;
X if(askacg > 0 || askacg == -1){
X printf("enter port file name: ");
X scanf("%s",file);
X if((datafile = fopen(file,"r")) == NULL)
X printf("can't open port file: %s\n",file);
X }
X else if((datafile = fopen(PORT_FILE,"r")) == NULL)
X printf("can't open %s\n",PORT_FILE);
X/* else if((datafile = fopen("acgport.data","r")) == NULL)
X printf("can't open acgport.data\n");
X*/
X while ( fscanf(datafile,"%s",str) != EOF) {
X if(strncmp(str,".",1) != 0){
X switch(i){
X case 0:
X strcat(ports[port_n].name,str);
X strcat(ports[port_n].name," ");
X break;
X case 1: ports[port_n].from_node = atoi(str);
X break;
X case 2: ports[port_n].to_node = atoi(str);
X pmax++;
X break;
X default:
X printf("error in reading ports - hit default\n");
X break;
X } /*switch */
X } /* if strncmp */
X else i++; /* incr i when find a period */
X if(i > 2){
X n = port_n;
X port_n++;
X i = 0;
X }
X } /* while fscanf */
X fclose(datafile);
Xreturn(pmax);
X}
X/*
X ************************ read node data ****************************
X*/
Xint read_node_data(askacg)
Xint askacg;
X{
XFILE *datafile, *fopen();
Xchar str[128],file[40];
Xint i, j, node_n, n, nmax, l, m;
X/* start with node already in correct order, later do sorting */
X
X i = 0; j = 0; nmax = 0;
X node_n = 0;
X if(askacg > 0 || askacg == -1){
X printf("enter node file name: ");
X scanf("%s",file);
X if((datafile = fopen(file,"r")) == NULL)
X printf("can't open node file: %s\n",file);
X }
X else if((datafile = fopen(NODE_FILE,"r")) == NULL)
X printf("can't open %s\n",NODE_FILE);
X/* else if((datafile = fopen("acgnode.data","r")) == NULL)
X printf("can't open acgnode.data\n");
X*/
X while ( fscanf(datafile,"%s",str) != EOF) {
X if(strncmp(str,".",1) == 0) {
X j = 0;
X i++;
X }
X else {
X switch(i){
X case 0:
X for(m=0;m<5;m++)
X nodes[node_n].target[m] = 0;
X nodes[node_n].node = atoi(str); break;
X case 1: nodes[node_n].target[j] = atoi(str);
X j++; break;
X case 2: nodes[node_n].source[j] = atoi(str);
X j++; break;
X case 3: nodes[node_n].cohort[j] = atoi(str);
X j++; break;
X case 4: strcat(nodes[node_n].name,str);
X strcat(nodes[node_n].name," ");
X break;
X case 5: nodes[node_n].lvl = atoi(str);
X break;
X case 6: nodes[node_n].nth = atoi(str);
X break;
X case 7: nodes[node_n].of = atoi(str);
X break;
X case 8: if(strncmp(str,"B",1) == 0) { /* box */
X nodes[node_n].shape = 1;
X nodes[node_n].wide = (short) BOXWIDTH;
X nodes[node_n].ht = (short) BOXHT;
X }
X else { /* circle */
X nodes[node_n].shape = 0;
X nodes[node_n].wide = (short) RADIUS;
X nodes[node_n].ht = (short) RADIUS;
X }
X nmax++;
X break;
X default:
X nodes[node_n].flg = 0;
X node_n++;
X nodes[node_n].node = atoi(str);
X i = 0; j = 0;
X break;
X } /*switch */
X } /* else switch */
X } /* while fscanf */
Xn = node_n;
X fclose(datafile);
X/* set target */
Xfor(j=0;j<nmax;j++){
X i=0;
X while(nodes[j].source[i] != 0){
X m = 0; /* find subscript(m) of node which is the source */
X while(nodes[j].source[i] != nodes[m].node && m < nmax) m++;
X/* printf("node=%d source=%d node[%d]=%d\n",nodes[j].node, nodes[j].source[i],m,nodes[m].node); */
X l = 0; /* find first free target */
X while(nodes[m].target[l] != 0) l++;
X nodes[m].target[l] = nodes[j].node;
X/*
Xprintf("child nodes[%d]=%d target[%d]=%d parent=%d\n",m,nodes[m].node,l,
X nodes[m].target[l],nodes[j].node);
X*/
X i++;
X }
X }
X return(nmax);
X}
X/* ************************************************************ */
X/*
X read limits from data file acglimits
X*/
Xint read_limits()
X{
XFILE *datafile, *fopen();
Xchar str[128];
Xint i,j,j0;
X i = -1;
X if((datafile = fopen("acglimits.data","r")) == NULL)
X printf("can't open acglimits\n");
X while ( fscanf(datafile,"%s",str) != EOF) {
X if(ispunct(str[0]) == 0) { /* ==0 false !=0 true */
X/* if(isalpha(str[0]) == 0) { */
X i++;
X switch(i){
X case 0:
X j = 0;
X while((GRAPH_TITLE[j]=str[j]) != '\0')
X j++;
X j0 = j+1;
X strncat(GRAPH_TITLE," ",1);
X while(fscanf(datafile,"%s",str) != 0 && ispunct(str[0]) == 0) {
X j = 0;
X while((GRAPH_TITLE[j0+j]=str[j]) != '\0')
X j++;
X j0 = j0+j+1;
X strncat(GRAPH_TITLE," ",1);
X }
X break;
X case 1:
X j = 0;
X while((NODE_FILE[j]=str[j]) != '\0')
X j++;
X break;
X case 2:
X j = 0;
X while((PORT_FILE[j]=str[j]) != '\0')
X j++;
X break;
X case 3: BOXWIDTH = atoi(str);
X break;
X case 4: BOXHT = atoi(str);
X break;
X case 5: RADIUS = atoi(str);
X break;
X case 6: NODE_LABEL = atoi(str);
X break;
X case 7: MAXX_WINDOW[0] = atoi(str);
X break;
X case 8: MAXY_WINDOW[0] = atoi(str);
X break;
X case 9: MINX_WINDOW[0] = atoi(str);
X break;
X case 10: MINY_WINDOW[0] = atoi(str);
X break;
X case 11: MIN_X_SPACE = atoi(str);
X break;
X case 12: MIN_Y_SPACE = atoi(str);
X break;
X default:
X printf("read_limits: reached default. bah!\n");
X break;
X } /*switch */
X } /* if isalpha */
X } /* while fscanf */
X
X fclose(datafile);
X return;
X}
X
SHAR_EOF
exit
More information about the Comp.sources.unix
mailing list