gillam@aero.ARPA (April Gillam) (11/10/86)
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@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