uawdijnntqw1x1x1
IP : 216.73.216.110
Hostname : 6.87.74.97.host.secureserver.net
Kernel : Linux 6.87.74.97.host.secureserver.net 4.18.0-553.83.1.el8_10.x86_64 #1 SMP Mon Nov 10 04:22:44 EST 2025 x86_64
Disable Function : None :)
OS : Linux
PATH:
/
home
/
emeraadmin
/
www
/
Classes
/
..
/
node_modules
/
jquery
/
..
/
object.map
/
..
/
..
/
4d695
/
graphviz.zip
/
/
PKu�\�� �## gvpr/addedgesnu�[���/* Add edges from input graph to argument graph * Does not add nodes. */ BEGIN{ graph_t g = readG(ARGV[0]); node_t h, t; edge_t e; } E { if ((h = isNode(g,head.name)) && (t = isNode(g,tail.name))) { if (!isEdge(t,h,"")) { e = copy(g,$); } } } END { write(g); } PKu�\�#0 >> gvpr/addranksnu�[���/* Assuming nodes have been positioned by dot, this adds a rank * attribute by placing all nodes with the same y value on a specific * integer rank. * If the graph has rankdir=LR, x and y are flipped. */ BEG_G { double x,y; int lv[double]; int r, rk[double]; int flip; if (isAttr($,"G","rankdir") && $.rankdir=="LR") flip = 1; } N { sscanf($.pos,"%f,%f",&x,&y); if (flip) lv[x] = 1; else lv[y] = 1; } BEG_G { r = 0; if (flip) forr (lv[x]) { rk[x] = r++; /* printf (2, "rk[%f] = %d\n", y, rk[y]); */ } else forr (lv[y]) { rk[y] = r++; /* printf (2, "rk[%f] = %d\n", y, rk[y]); */ } } N { sscanf($.pos,"%f,%f",&x,&y); /* printf(2, "node %s y %f rk %d\n", $.name, y, rk[y]); */ if (flip) $.rank = sprintf("%d", rk[x]); else $.rank = sprintf("%d", rk[y]); } PKu�\�D�'' gvpr/addringsnu�[���/* Takes a graph laid out by twopi and adds rings. * Assumes ARGV[] = "root" "=" <rootname>, as output by twopi -v. * Usage: * twopi -v foo.dot > out 2> log * gvpr -f addrings.g -a"`grep root log`" out | neato -n2 ... */ BEG_G { graph_t og; edge_t e; node_t ctr = node($, ARGV[0]); double rs = 1.0; /* min. slack between the squares of two consecutive radii */ int cx, cy; int x, y; node_t n; int i, n_r; int d; int rads[int]; char* ctr_s = ctr.pos; sscanf (ctr_s, "%d,%d", &cx, &cy); if (hasAttr($, "ranksep")) { sscanf ($.ranksep, "%f", &rs); if (rs == 0.0) rs = 1.0; } rs *= 72; rs = 1.5*rs*rs; } N [$ != ctr] { sscanf ($.pos, "%d,%d", &x, &y); d = (x-cx)*(x-cx) + (y-cy)*(y-cy); for (rads[i]) { if ((rads[i]-rs <= d) && (d <= rads[i]+rs)) return; } n_r++; rads[n_r] = d; } END_G { og = copy (NULL, $); og.outputorder = "nodesfirst"; setDflt (og, "N", "label", "\\N"); for (rads[i]) { n = node(og, "ring_"+((string)i)); n.shape = "circle"; n.pos = ctr_s; n.style = ""; n.label = ""; d = rads[i]; n.width = sprintf("%f", sqrt(d)/36.0); } for (n=fstnode($);n;n = nxtnode(n)) clone (og, n); for (n=fstnode($);n;n = nxtnode(n)) for (e=fstedge(n);e;e = nxtedge(e,n)) clone (og, e); write(og); } PKu�\���Ϧ� gvpr/anonnu�[���/* anonymize the graph */ BEG_G { node_t map[node_t]; graph_t dup; int id = 0; char* gtype; node_t n; edge_t e; char* l; if ($.directed) gtype = "D"; else gtype = "U"; if ($.strict) gtype = gtype + "S"; dup = graph ($.name, gtype); $tvtype = TV_ne; } N { n = node(dup, (char*)id); n.label=$.name; map[$] = n; id++; } E { edge (map[$.tail],map[$.head],""); } END_G { write (dup); } PKu�\��� gvpr/attrnu�[���/* List known node attributes */ BEG_G { char* attr; for (attr = fstAttr($,"N"); attr != ""; attr = nxtAttr($,"N",attr)) { print (attr); } } PKu�\�h��gvpr/bbnu�[���/* computes the bounding box of a graph based on its nodes taking into account clusters and node sizes. */ BEGIN { double x, y, w2, h2; double llx, lly, urx, ury; double llx0, lly0, urx0, ury0; graph_t clustBB (graph_t G) { graph_t sg; for (sg = fstsubg(G); sg; sg = nxtsubg(sg)) { sg = clustBB(sg); } if (G.name == "cluster*") { sscanf (G.bb, "%lf,%lf,%lf,%lf", &llx0, &lly0, &urx0, &ury0); if (llx0 < llx) llx = llx0; if (lly0 < lly) lly = lly0; if (urx0 > urx) urx = urx0; if (ury0 > ury) ury = ury0; } return G; } } BEG_G { llx = 1000000; lly = 1000000; urx = -1000000; ury = -1000000; } N { sscanf ($.pos, "%lf,%lf", &x, &y); w2 = (36.0*(double)$.width); h2 = (36.0*(double)$.height); if ((x - w2) < llx) llx = x - w2; if ((x + w2) > urx) urx = x + w2; if ((y - h2) < lly) lly = y - h2; if ((y + h2) > ury) ury = y + h2; } END_G { clustBB ($); $.bb = sprintf ("%lf,%lf,%lf,%lf", llx, lly, urx, ury); } PKu�\�� gvpr/bboxnu�[���/* computes the bounding box of a graph based on node positions */ BEGIN { double xmin, ymin, xmax, ymax; xmin = ymin = 1.7976931348623157e+308; xmax = ymax = -ymin; double x, y; } N { if (sscanf ($.pos, "%f,%f", &x, &y) == 2) { if (x < xmin) xmin = x; if (y < ymin) ymin = y; if (x > xmax) xmax = x; if (y > ymax) ymax = y; } } END { printf ("(%f,%f) (%f,%f)\n", xmin, ymin, xmax, ymax); if (ARGC) printf ("area = %f aspect = %f\n", ((xmax-xmin)*(ymax-ymin))/1000000., (xmax-xmin)/(ymax-ymin)); } PKu�\Xoy��gvpr/binducenu�[���/* Given a bipartite graph, induce a non-bipartite graph. * argv[0]="name=value" This is used to identify the nodes used * to induce edges. If aget(n,name) == value, * if deg(n) == 1, delete * if deg(n) == 2, delete and connect to neighbor with edge * if deg(n) > 2, delete and add edge between all pairs of neighbors * Add weights to edge. */ BEGIN{ int i, cnt; int wt[edge_t]; string values[int]; node_t nbrs[int]; edge_t e; tokens(ARGV[0],values,"="); string aname = values[0]; string value = values[1]; printf(2, "%s=%s\n", aname, value); } N[aget($,aname)==value] { if ($.degree > 1) { cnt = 0; for (e = fstedge($); e; e = nxtedge(e, $)) nbrs[cnt++] = opp(e,$); for (i = 0; i < cnt-1; i++) { if ((e = isEdge(nbrs[i],nbrs[i+1],"")) != NULL) { wt[e] += 1; } else if ($G.directed && (e = isEdge(nbrs[i+1],nbrs[i],""))) { wt[e] += 1; } else if (nbrs[i] != nbrs[i+1]) { // avoid loops e = edge(nbrs[i],nbrs[i+1],""); wt[e] = 1; } } unset(nbrs); } delete($G,$); } END_G{ for (wt[e]) { e.multiplicity = sprintf ("%d", wt[e]); } } PKu�\[����gvpr/bipartnu�[���/* Determine if a graph is bipartite or not. */ BEG_G{ int vc, c, color[node_t]; node_t v; edge_t e; $tvtype = TV_dfs; $tvroot = fstnode($); } N{ if ($tvedge == NULL) color[$] = 1; if (color[$] == 1) c = 2; else c = 1; for (e = fstedge($); e; e = nxtedge(e,$)) { v = opp(e,$); vc = color[v]; if (vc == 0) color[v] = c; else if (vc != c) { printf(2, "Not bipartite\n"); exit(1); } } } PKu�\#K��gvpr/chkclustersnu�[���/* Report if graph has non-hierarchical clusters */ BEGIN { graph_t c[node_t]; node_t n; void proc (graph_t h, graph_t p, graph_t g) { if (h.name == "cluster*") { for (n = fstnode(h); n; n = nxtnode_sg(h,n)) { g = c[n]; if (g) { if (g != p) { printf(2,"node %s in %s and %s\n", n.name, h.name, g.name); exit(1); } } c[n] = h; } p = h; } for (g = fstsubg(h); g; g = nxtsubg(g)) { proc(g,p,NULL); } } } BEG_G { proc($,$,NULL); } PKu�\�|���� gvpr/chkedgesnu�[���/* Looks for multiedges and loops, and output * those found along with counts. If the -d flag * is given, edge direction is taken into account. */ BEGIN{ char* ename; char* n; int doDir, cnt[]; int loopcnt[]; int nloops, nmulti; if ((ARGC > 0) && (ARGV[0] == "-d")) doDir = 1; else doDir = 0; } BEG_G{unset(cnt); unset(loopcnt); nloops = nmulti = 0;} E{ if (doDir || (tail.name <= head.name)) ename=tail.name+"_"+head.name; else ename = head.name+"_"+tail.name; if (tail == head) { loopcnt[ename] += 1; if (loopcnt[ename] == 1) nloops += 1; } else { cnt[ename] += 1; if (cnt[ename] == 2) nmulti += 1; } } END_G{ printf ("graph %s: %d loops %d multiedges\n", $.name, nloops, nmulti); for (cnt[n]) { if (cnt[n] > 1) printf ("%s : %d\n", n, cnt[n]); } for (loopcnt[n]) { if (loopcnt[n] > 0) printf ("%s : %d\n", n, loopcnt[n]); } } PKu�\W/���� gvpr/cliptreenu�[���/* Construct subgraph reachable from node ARGV[0] by forward edges */ BEG_G { node_t r = node($,ARGV[0]); $tvroot = r; $tvtype = TV_fwd; } N{$tvroot=NULL; subnode($T,$);} PKu�\w�k`YYgvpr/colnu�[���# test /* color nodes using output of dijkstra */ BEG_G { double h, hn, hf, d, sat, md = maxdist; if (hue_near =="") hue_near = 0.8; if (hue_far =="") hue_far = 1.2; hn = hue_near; hf = hue_far; } # test N { d = dist; sat = (md - d + 1.0) /( md + 1.0); h = hn + ((hf - hn) * d)/md; while (h < 0.0) h = h + 1.0; while (h > 1.0) h = h - 1.0; color = sprintf("%lf %lf %lf",hue,sat,1.0); /* make sure the shape is filled */ if (!match(style,"filled")>=0) { if (style != "") style=sprintf("%s,filled",style); else style="filled"; } } PKu�\_zm8�� gvpr/collapsenu�[���/* Collapse all edges with same group attribute into a single edge */ BEG_G { int seen[string]; $O = $; // Use the input graph as output. } E { if (collapse == "") return; // If no collapse, ignore. if (seen[collapse]) delete ($G, $); // If already seen an edge with this collapse value, // delete the edge. else seen[collapse] = 1; // Else mark collapse value as seen and keep edge. } PKu�\/?%��� gvpr/colornu�[���/* color edges based on normalized length alpha. * If we have lim[i-1] <= alpha <= lim[i], the color * is linearly interpolated between color[i-1] and color[i]. * Edges already having a color attribute are left unchanged. */ BEGIN { double lens [edge_t]; double maxlen, len, minlen=1.7976931348623157e+308; double alpha, x0, y0, x1, y1; double h0, s0, v0; int i; int ncolors; /* number of colors: ncolors >= 2 */ /* start of color i. * lim[0]=0 < lim[1] < ... < lim[ncolors-1]=1 */ double lim[int]; /* HSV values for color i */ double h[int]; double s[int]; double v[int]; /* simple default */ ncolors = 2; lim[0] = 0; lim[1] = 1; h[0] = 0; h[1] = 0.67; s[0] = 1; s[1] = 1; v[0] = 1; v[1] = 1; } E{ sscanf ($.tail.pos, "%f,%f", &x0, &y0); sscanf ($.head.pos, "%f,%f", &x1, &y1); len = sqrt ((x0-x1)*(x0-x1) + (y0-y1)*(y0-y1)); lens[$] = len; if (len > maxlen) maxlen = len; if (len < minlen) minlen = len; } BEG_G { if (!isAttr($,"E","color")) setDflt($,"E","color",""); } E{ if ($.color != "") return; alpha = (lens[$]-minlen)/(maxlen-minlen); for (i = 1; i < ncolors; i++) { if (alpha < lim[i]) break; } alpha = (alpha - lim[i-1])/(lim[i] - lim[i-1]); h0 = (1-alpha)*h[i-1] + alpha*h[i]; s0 = (1-alpha)*s[i-1] + alpha*s[i]; v0 = (1-alpha)*v[i-1] + alpha*v[i]; $.color = sprintf ("%.02f %.02f %.02f", h0, s0, v0); } PKu�\Xv��00 gvpr/cyclenu�[���/* Detect directed cycle and print one if found */ BEG_G{ node_t tp, hp; node_t stk[node_t]; $tvtype = TV_prepostfwd; $tvroot = fstnode($); } N { if (stk[$]) { stk[$] = NULL; } else if ($tvedge == NULL) { /* current root */ stk[$] = $; } else { stk[$] = $tvedge.tail; } } E { if (stk[$.head]) { tp = $.tail; hp = $.head; while (tp != $.head) { printf ("%s -> %s\n", tp.name, hp.name); hp = tp; tp = stk[tp]; } printf ("%s -> %s\n", tp.name, hp.name); exit(0); } } PKu�\�W��gvpr/dechainnu�[���/* Remove peninsulas - chains hanging off the main graph */ BEGIN { edge_t e; node_t v, n; } N [degree == 1] { n = $; while (n.degree == 1) { e = fstedge (n); if (e.head == n) v = e.tail; else v = e.head; delete($G,n); n = v; } } PKu�\u��__gvpr/deghistnu�[���/* print histogram of node degrees */ BEGIN { int degrees[]; int maxd = 0; int i, d; char* maxn; } N{ degrees[degree]++; if (degree > maxd) { maxn = $.name; maxd = degree; } } END { printf ("max node %s (%d)\n", maxn, maxd); for (i = 1; i <= maxd; i++) { d = degrees[i]; if (d > 0) printf ("[%d] %d\n", i, d); } } PKu�\�a��tt gvpr/deledgesnu�[���/* delete all edges */ BEGIN { int map[edge_t]; edge_t e; } E {map[$]=1} END_G { for (map[e]) delete ($,e); } PKu�\*TU��� gvpr/delmultinu�[���/* create a copy of the input graph with no multiedges */ BEG_G { graph_t g = graph ("merge", "S"); } E { int wt; node_t h = node(g,$.head.name); node_t t = node(g,$.tail.name); edge_t e = isEdge(t,h,""); wt = $.weight; if (wt <= 0) wt = 1; if (e) { e.weight = e.weight + wt; } else if (h != t) { e = edge(t,h,""); e.weight = wt; } } END_G { fwriteG(g,1); } PKu�\�(���� gvpr/delnodesnu�[���/* Delete nodes whose names are given in ARGV */ BEG_G { int names[char*]; int nodes[node_t]; node_t n; int i; for (i = 0; i < ARGC; i++) names[ARGV[i]] = 1; } N[names[name]]{nodes[$] = 1} END_G { for (nodes[n]) delete ($,n); } PKu�\�߀N##gvpr/depathnu�[���/* Replace paths a -> b -> ... -> c with a -> c */ BEGIN { edge_t e; node_t n, prv, nxt; } N [(indegree == 1) && (outdegree == 1)] { e = fstin ($); prv = e.tail; e = fstout ($); nxt = e.head; delete ($G,$); while ((prv.indegree == 1) && (prv.outdegree == 0)) { e = fstin (prv); n = e.tail; delete ($G,prv); prv = n; } while ((nxt.indegree == 0) && (nxt.outdegree == 1)) { e = fstout (nxt); n = e.head; delete ($G,nxt); nxt = n; } if (!isEdge (prv,nxt,"")) edge (prv,nxt,""); } PKu�\��E �� gvpr/dijkstranu�[���/* Given graph processed by dijkstra, and node, * color shortest path * Assumes path has been computed by dijkstra */ BEG_G { node_t n = isNode($,ARGV[0]); node_t nxt; edge_t e; double d, totd = 0; if (n == NULL) { printf(2, "no node named \"%s\"\n", ARGV[0]); exit(1); } while (n.prev != "") { nxt = isNode($,n.prev); /* printf(2, "nxt \"%s\"\n", nxt.name); */ e = isEdge (n, nxt, ""); if (e == NULL) { printf(2, "no edge between %s and %s\n", n.name, nxt.name); } e.color = "blue"; /* printf(2, "len %s\n", e.len); */ /* sscanf (e.len, "%f", &d); */ /* totd += d; */ n = nxt; } } PKu�\���XXgvpr/flattennu�[���/* Wipe out any cluster structure */ BEG_G { $O = copy (NULL,$); } E { clone ($O, $); } PKu�\-f�gvpr/get-layers-listnu�[���BEG_G { char* larr[int]; int i; if (!isAttr($,"G","layers")) return; if (isAttr($,"G","layersep")) tokens($.layers,larr,$.layersep); else tokens($.layers,larr," :\t"); for (larr[i]) { if (i>0) printf(" %s",larr[i]); else printf("%s",larr[i]); } } PKu�\�+�{ gvpr/groupnu�[���/* Collapse all nodes with group = X into a single node */ BEG_G { node_t metaN; graph_t g = graph ("metagraph", "S"); $tvtype = TV_ne; $O = g; } /* create only one node with given name/value */ N[group == "X"] { if (!metaN) { metaN = node (g, $.name); } } /* duplicate all others */ N[group != "X"] { node (g, $.name); } /* Create an edge only if at least one of the nodes * is not a collapsed node */ E { node_t t; node_t h; if ($.tail.group == "X") { if ($.head.group == "X") return; t = metaN; h = node (g, $.head.name); } else if ($.head.group == "X") { t = node (g, $.tail.name); h = metaN; } else { t = node (g, $.tail.name); h = node (g, $.head.name); } edge (t, h, ""); } /* set g to be output graph */ PKu�\�{�N??gvpr/histogramnu�[���/* print histogram of integer attribute */ BEGIN { int count[]; int maxd = 0; int i, d, v; char* attrname = ARGV[0]; } N{ v = (int)(aget($,attrname)); count[v]++; if (v > maxd) { maxd = v; } } END { for (i = 1; i <= maxd; i++) { d = count[i]; if (d > 0) printf ("[%d] %d\n", i, d); } } PKu�\k��Qzzgvpr/indentnu�[���/* Print the depth-first traversal of nodes * as an indented list */ BEGIN { int i, indent; int seen[string]; void prInd () { for (i = 0; i < indent; i++) printf (" "); } } BEG_G { $tvtype = TV_prepostfwd; $tvroot = node($,ARGV[0]); } N { if (seen[$.name]) indent--; else { prInd(); print ($.name); seen[$.name] = 1; indent++; } } PKu�\������ gvpr/knbhdnu�[���/* knbhd - Return the k-neighborhood of a node, i.e., allnodes * whose path length from the given node is <= k. * ARGV[] = k node_name */ BEG_G { node_t ctr; int maxlen; graph_t comp = subg($, "kcomp"); int sid = 0, eid = 0; int curlen; node_t curnode; int nlen[node_t]; node_t stk[int]; node_t other; edge_t e; if (ARGC != 2) { printf (2, "Two arguments required\n"); exit(1); } if (!sscanf(ARGV[0],"%d",&maxlen)) { printf (2, "Improper length parameter \"%s\"\n", ARGV[0]); exit(1); } maxlen++; /* length of 0 means unset */ ctr = isNode ($, ARGV[1]); if (!ctr) { printf (2, "node %s not found\n", ARGV[1]); exit(1); } subnode (comp,ctr); nlen[ctr] = 1; curnode = ctr; while (curnode) { curlen = nlen[curnode]; if (curlen == maxlen) break; for (e = fstedge(curnode); e; e = nxtedge(e,curnode)) { other = e.head; if (other == curnode) other = e.tail; if (nlen[other]) continue; /* already seen */ subnode(comp,other); nlen[other] = curlen+1; stk[eid++] = other; } if (sid < eid) curnode = stk[sid++]; else curnode = NULL; } induce(comp); write(comp); } PKu�\.<��33gvpr/maxdegnu�[���/* find nodes of max and min degree */ BEG_G {node_t mxn, mnn; int maxd = -1; int mind = 1000000;} N { if (degree > maxd) {maxd = degree; mxn = $;} if (degree < mind) {mind = degree; mnn = $;} } END_G {printf ("max degree = %d, node %s, min degree = %d, node %s\n", maxd, mxn.name, mind, mnn.name)} PKu�\��v�� gvpr/pathnu�[���/* Report the distance from src = ARGV[0] to dst = ARGV[1] */ BEG_G { int dist[node_t]; node_t n, curn; node_t src = node($G, ARGV[0]); node_t dst = node($G, ARGV[1]); $tvroot = src; $tvtype = TV_bfs; } N { curn = $; if ($ == dst) { printf ("dist from %s to %s is %d\n", src.name, dst.name, dist[dst]); exit(0); } } E { if ($.head == curn) n = $.tail; else n = $.head; if (dist[n] == 0) dist[n] = dist[curn]+1; } PKu�\2w���gvpr/rotatenu�[���/* Given node name and angle, rotate a layout using the given * node as origin. */ BEGIN { double x,y; double x0,y0; double x1,y1; double angle, cosa, sina; int cnt, sz; void rotate (double a, double b) { a -= x0; b -= y0; x1 = a*cosa - b*sina; y1 = a*sina + b*cosa; } char* rotateE (char* p) { char* newpos = ""; cnt = sscanf (p, "e,%lf,%lf%n", &x, &y, &sz); if (cnt == 2) { rotate (x,y); newpos = newpos + sprintf ("e%lf,%lf ", x1, y1); p = substr(p, sz); } cnt = sscanf (p, "s,%lf,%lf%n", &x, &y, &sz); if (cnt == 2) { rotate (x,y); newpos = newpos + sprintf ("s%lf,%lf ", x1, y1); p = substr(p, sz); } while (sscanf (p, "%lf,%lf%n", &x, &y, &sz) == 2) { rotate (x,y); newpos = newpos + sprintf ("%lf,%lf ", x1, y1); p = substr(p, sz); } return newpos; } } BEG_G { node_t ctr = node ($, ARGV[0]); sscanf (ARGV[1], "%f", &angle); cosa = cos(angle); sina = sin(angle); sscanf (ctr.pos, "%f,%f", &x0, &y0); $.bb =""; } N { sscanf ($.pos, "%f,%f", &x, &y); rotate (x,y); $.pos = sprintf ("%f,%f", x1, y1); } E { $.pos = rotateE($.pos); } PKu�\�`�{{ gvpr/scalenu�[���/* finds node n with root attribute * finds distance minr of closest node * the layout is then scaled out from n so that * a node is put on the smallest circle of radius x*minr * containing n */ BEG_G { node_t ctr; int cx, cy; int x, y; double delx, dely; int newx, newy; node_t n; edge_t e; int i, sc, d, mind = -1; double fact, newr, ang, minr; ctr = node($,aget($,"root")); sscanf (ctr.pos, "%d,%d", &cx, &cy); for (e = fstedge(ctr); e; e = nxtedge(e, ctr)) { if (e.head == ctr) n = e.tail; else n = e.head; sscanf (n.pos, "%d,%d", &x, &y); d = (x-cx)*(x-cx) + (y-cy)*(y-cy); if ((mind == -1) || (d < mind)) mind = d; } minr = (int)sqrt((double)mind); } N [$ != ctr] { sscanf ($.pos, "%d,%d", &x, &y); dely = y - cy; delx = x - cx; d = delx*delx + dely*dely; sc = (int)sqrt((double)(d/mind)); if (sc > 1) { fact = 2.0; for (i=1; i<sc-1;i++) fact *= 2.0; newr = minr*(2.0 - (1.0/fact)); ang = atan2 (dely, delx); newx = newr*cos(ang) + cx; newy = newr*sin(ang) + cy; $.pos = sprintf ("%d,%d", newx, newy); } } PKu�\\�r�ccgvpr/scalexynu�[���/* finds root node of graph. * scales the x and y position of all other nodes using, first, * ARGV[0], or $G.scale. * * The expected syntax is "x,y" where at least one of x or y must * be given. If only one is given, the other is taken as 1. */ BEGIN { double scalex, scaley; int r, done; int setScale (char* s) { if ((sscanf (s, ",%f",&scaley))) { scalex = 1; return 1; } else { r = sscanf (s, "%f,%f",&scalex,&scaley); if (r) { if (r == 1) scaley = 1; return 1; } } return 0; } } BEG_G { node_t ctr = node($,aget($,"root")); double cx, cy, x, y, delx; /* get scale argument */ done = 0; if (ARGC == 1) done = setScale (ARGV[0]); if (!done && isAttr($,"G","scale")) done = setScale ($.scale); if (!done) scalex = scaley = 1.0; if ((scalex == 1.0) && (scaley == 1.0)) exit (0); $.bb = ""; sscanf (ctr.pos, "%f,%f", &cx, &cy); } N [$ != ctr] { sscanf ($.pos, "%f,%f", &x, &y); delx = scalex*(x - cx) + cx; dely = scaley*(y - cy) + cy; $.pos = sprintf ("%f,%f", delx, dely); } PKu�\V$ ��� gvpr/spannu�[���/* derive simple spanning tree */ BEG_G { $tvtype = TV_dfs; $tvroot = node($,ARGV[0]);} E [!isSubnode($T,$.head) || !isSubnode($T,$.tail)] PKu�\�M�c�� gvpr/toponnu�[���/* Generate copy of topology of input graph * Replace names with numbers */ BEGIN { int id = 0; char* names[char*]; char* mapn (char* inname) { char* s = names[inname]; if (s == "") { s = id++; names[inname] = s; } return s; } } BEG_G { graph_t g = graph ($.name, "U"); } N { node (g, mapn($.name)); } E { edge (node (g, mapn($.tail.name)), node (g, mapn($.head.name)), ""); } END_G { write (g); } PKu�\v Q���gvpr/treetoclustnu�[���/* Convert a rooted tree to a hierarchy of clusters for patchwork. * ARGV[0] is desired root */ BEG_G { node_t rt; node_t n; graph_t cg; graph_t sg; int depth; int mark[node_t]; graph_t stk[int]; if (! $.directed) { printf(2,"Input graph is not directed\n"); exit (1); } rt = isNode($,ARGV[0]); if (rt == NULL) { printf(2,"Root node \"%s\" not found\n", ARGV[0]); exit (1); } $tvroot = rt; $tvtype = TV_prepostfwd; cg = graph(rt.name,"U"); } N { if (mark[$]) { depth--; } else { mark[$] = 1; if (depth > 0) { if (fstout($)) { sg = subg(stk[depth-1], "cluster_" + $.name); if (($.style == "filled") && ($.fillcolor != "")) sg.bgcolor = $.fillcolor; } else { sg = NULL; n = node(stk[depth-1], $.name); n.style = "filled"; n.fillcolor = $.fillcolor; } } else sg = cg; stk[depth] = sg; depth++; } } END_G { write(cg); } PKu�\�q8�lefty/box.leftynu�[���load ('def.lefty'); definit (); # # initialize window data # canvas = defcanvas; wrect = [0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 400; 'y' = 500;];]; setwidgetattr (canvas, ['window' = wrect;]); # # data structures # objarray = []; objnum = 0; # # misc functions # min = function (a, b) { if (a <= b) return a; return b; }; max = function (a, b) { if (b <= a) return a; return b; }; rectof = function (p1, p2) { return [ 0 = ['x' = min (p1.x, p2.x); 'y' = min (p1.y, p2.y);]; 1 = ['x' = max (p1.x, p2.x); 'y' = max (p1.y, p2.y);]; ]; }; pointadd = function (p1, p2) { return ['x' = p2.x + p1.x; 'y' = p2.y + p1.y;]; }; pointsub = function (p1, p2) { return ['x' = p2.x - p1.x; 'y' = p2.y - p1.y;]; }; # # rendering functions # drawbox = function (obj, color) { box (canvas, obj, obj.rect, ['color' = color;]); }; redrawboxes = function () { local i; clear (canvas); for (i = 0; i < objnum; i = i + 1) drawbox (objarray[i], 1); }; redraw = function (canvas) { redrawboxes (); }; # # editing functions # new = function (rect) { objarray[objnum] = [ 'rect' = rect; 'id' = objnum; ]; objnum = objnum + 1; return objarray[objnum - 1]; }; reshape = function (obj, rect) { obj.rect = rect; return obj; }; move = function (obj, p) { obj.rect[0] = pointadd (obj.rect[0], p); obj.rect[1] = pointadd (obj.rect[1], p); return obj; }; delete = function (obj) { if (obj.id ~= objnum - 1) { objarray[obj.id] = objarray[objnum - 1]; objarray[obj.id].id = obj.id; } remove (objnum - 1, objarray); objnum = objnum - 1; }; # # user interface functions # # left mouse button creates new box # middle button moves a box # right button deletes a box # leftdown = function (data) { if (data.obj ~= null) return; leftbox = new (rectof (data.pos, data.pos)); drawbox (leftbox, 1); setgfxattr (canvas, ['mode' = 'xor';]); }; leftmove = function (data) { if (~leftbox) return; drawbox (leftbox, 1); clearpick (canvas, leftbox); reshape (leftbox, rectof (data.ppos, data.pos)); drawbox (leftbox, 1); }; leftup = function (data) { if (~leftbox) return; drawbox (leftbox, 1); clearpick (canvas, leftbox); reshape (leftbox, rectof (data.ppos, data.pos)); setgfxattr (canvas, ['mode' = 'src';]); drawbox (leftbox, 1); remove ('leftbox'); }; middledown = function (data) { if (data.obj == null) return; middlebox = data.obj; middlepos = data.pos; setgfxattr (canvas, ['mode' = 'xor';]); }; middlemove = function (data) { if (~middlebox) return; drawbox (middlebox, 1); clearpick (canvas, middlebox); move (middlebox, pointsub (middlepos, data.pos)); middlepos = data.pos; drawbox (middlebox, 1); }; middleup = function (data) { if (~middlebox) return; drawbox (middlebox, 1); clearpick (canvas, middlebox); move (middlebox, pointsub (middlepos, data.pos)); setgfxattr (canvas, ['mode' = 'src';]); drawbox (middlebox, 1); remove ('middlepos'); remove ('middlebox'); }; rightup = function (data) { if (data.pobj == null) return; drawbox (data.obj, 0); clearpick (canvas, data.obj); delete (data.obj); }; dops = function () { local s; s = ['x' = 8 * 300; 'y' = 10.5 * 300;]; canvas = createwidget (-1, ['type' = 'ps'; 'size' = s;]); setwidgetattr (canvas, ['window' = wrect;]); redraw (canvas); destroywidget (canvas); canvas=defcanvas; }; PKu�\`�Iw��lefty/def.leftynu�[���definit = function () { defview = createwidget (-1, [ 'type' = 'view'; 'name' = 'graphics view'; 'origin' = ['x' = 1; 'y' = 1;]; 'size' = ['x' = 400; 'y' = 500;]; ]); defscroll = createwidget (defview, ['type' = 'scroll';]); defcanvas = createwidget (defscroll, [ 'type' = 'canvas'; 'origin' = ['x' = 1; 'y' = 1;]; 'size' = ['x' = 400; 'y' = 500;]; 'borderwidth' = 1; ]); }; PKu�\*<��Y�Ylefty/dotty.leftynu�[���# # DOTTY # dotty = [ 'keys' = [ 'nid' = 'nid'; 'eid' = 'eid'; 'gid' = 'gid'; 'name' = 'name'; 'attr' = 'attr'; 'gattr' = 'graphattr'; 'eattr' = 'edgeattr'; 'nattr' = 'nodeattr'; 'edges' = 'edges'; 'tail' = 'tail'; 'tport' = 'tport'; 'head' = 'head'; 'hport' = 'hport'; 'pos' = 'pos'; 'size' = 'size'; 'rect' = 'rect'; 'fname' = 'fontname'; 'fsize' = 'fontsize'; 'fcolor' = 'fontcolor'; 'dcolor' = 'drawcolor'; 'bcolor' = 'fillcolor'; ]; 'maps' = [ 'X11' = [ 'fontmap' = [ 'Times-Roman' = '-*-times-medium-r-*--%d-*-*-*-*-*-*-1'; 'Times-Italic' = '-*-times-medium-i-*--%d-*-*-*-*-*-*-1'; 'Times-Bold' = '-*-times-bold-r-*--%d-*-*-*-*-*-*-1'; 'Courier' = '-*-courier-bold-r-*--%d-*-*-*-*-*-*-1'; 'Courier-Bold' = '-*-courier-bold-r-*--%d-*-*-*-*-*-*-1'; 'Helvetica' = ( '-*-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1' ); 'Helvetica-Bold' = ( '-*-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1' ); ]; 'psfontmap' = [ 'Times-Roman' = 'Times-Roman'; 'Times-Italic' = 'Times-Italic'; 'Times-Bold' = 'Times-Bold'; 'Courier' = 'Courier'; 'Courier-Bold' = 'Courier-Bold'; 'Helvetica' = 'Helvetica'; 'Helvetica-Bold' = 'Helvetica-Bold'; ]; ]; 'mswin' = [ 'fontmap' = [ 'Times-Roman' = 'Times New Roman'; 'Times-Italic' = 'Times New Roman Italic'; 'Times-Bold' = 'Times New Roman Bold'; 'Courier' = 'Courier New'; 'Courier-Bold' = 'Courier New Bold'; 'Helvetica' = 'Arial'; 'Helvetica-Bold' = 'Arial Bold'; ]; 'psfontmap' = [ 'Times-Roman' = 'Times New Roman'; 'Times-Italic' = 'Times New Roman Italic'; 'Times-Bold' = 'Times New Roman Bold'; 'Courier' = 'Courier New'; 'Courier-Bold' = 'Courier New Bold'; 'Helvetica' = 'Arial'; 'Helvetica-Bold' = 'Arial Bold'; ]; ]; ]; 'protogt' = [ 'graph' = [ 'graphattr' = [ 'fontsize' = '14'; 'fontname' = 'Times-Roman'; 'fontcolor' = 'black'; ]; 'nodeattr' = [ 'shape' = 'ellipse'; 'fontsize' = '14'; 'fontname' = 'Times-Roman'; 'fontcolor' = 'black'; 'style' = 'solid'; ]; 'edgeattr' = [ 'fontsize' = '14'; 'fontname' = 'Times-Roman'; 'fontcolor' = 'black'; 'style' = 'solid'; ]; 'graphdict' = []; 'nodedict' = []; 'graphs' = []; 'nodes' = []; 'edges' = []; 'maxgid' = 0; 'maxnid' = 0; 'maxeid' = 0; 'type' = 'digraph'; ]; 'layoutmode' = 'sync'; 'lserver' = 'dot'; 'edgehandles' = 1; 'noundo' = 0; ]; 'lservers' = []; 'mlevel' = 0; 'graphs' = []; 'views' = []; 'protovt' = [ 'normal' = [ 'name' = 'DOTTY'; 'orig' = ['x' = 1; 'y' = 1;]; 'size' = ['x' = 420; 'y' = 520;]; 'wrect' = [ 0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 400; 'y' = 500;]; ]; 'vsize' = ['x' = 400; 'y' = 500;]; 'w2v' = 1; ]; 'birdseye' = [ 'type' = 'birdseye'; 'name' = 'DOTTY birdseye view'; 'orig' = ['x' = 1; 'y' = 1;]; 'size' = ['x' = 220; 'y' = 260;]; 'wrect' = [ 0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 200; 'y' = 250;]; ]; 'vsize' = ['x' = 200; 'y' = 250;]; 'w2v' = 1; ]; ]; 'pagesizes' = [ '8.5x11' = ['x' = 8; 'y' = 10.5;]; '11x17' = ['x' = 10.5; 'y' = 16.5;]; '36x50' = ['x' = 35.5; 'y' = 49.5;]; ]; ]; load ('dotty_draw.lefty'); load ('dotty_edit.lefty'); load ('dotty_layout.lefty'); load ('dotty_ui.lefty'); # # initialization functions # dotty.init = function () { dotty.fontmap = dotty.maps[getenv ('LEFTYWINSYS')].fontmap; dotty.clipgt = dotty.protogt.creategraph (['noundo' = 1;]); dotty.inited = 1; }; dotty.simple = function (file) { if (dotty.inited ~= 1) dotty.init (); dotty.createviewandgraph (file, 'file', null, null); txtview ('off'); }; # # main operations # dotty.protogt.creategraph = function (protogt) { local gt, id, gtid; if (~protogt) protogt = dotty.protogt; for (gtid = 0; dotty.graphs[gtid]; gtid = gtid + 1) ; gt = (dotty.graphs[gtid] = []); if (protogt.mode ~= 'replace') { for (id in dotty.protogt) gt[id] = copy (dotty.protogt[id]); } for (id in protogt) gt[id] = copy (protogt[id]); gt.gtid = gtid; gt.views = []; gt.undoarray = ['level' = 0; 'entries' = [];]; gt.busy = 0; return gt; }; dotty.protogt.copygraph = function (ogt) { local gt, gtid, id; for (gtid = 0; dotty.graphs[gtid]; gtid = gtid + 1) ; gt = (dotty.graphs[gtid] = []); for (id in ogt) gt[id] = copy (ogt[id]); gt.gtid = gtid; gt.views = []; gt.undoarray = ['level' = 0; 'entries' = [];]; gt.busy = 0; return gt; }; dotty.protogt.destroygraph = function (gt) { local vid, vlist; if (gt.layoutpending > 0) gt.cancellayout (gt); for (vid in gt.views) vlist[vid] = gt.views[vid]; for (vid in gt.views) gt.destroyview (gt, vlist[vid]); remove (gt.gtid, dotty.graphs); }; dotty.protogt.loadgraph = function (gt, name, type, protograph, layoutflag) { local fd, vid, vt, graph, nid, eid, gid; if (gt.layoutpending > 0) gt.cancellayout (gt); if (~name) if (~(name = ask ('file name:', 'file', ''))) return; dotty.pushbusy (gt, gt.views); dotty.message (1, 'loading'); if (~protograph) protograph = dotty.protogt.graph; if ( ~((fd = dotty.openio (name, type, 'r')) >= 0) | ~(graph = readgraph (fd, protograph)) ) { dotty.message (0, 'cannot load graph'); dotty.popbusy (gt, gt.views); return; } for (vid in gt.views) { vt = gt.views[vid]; vt.colors = []; vt.colorn = 2; } gt.graph = graph; gt.name = name; gt.type = type; gt.undoarray = ['level' = 0; 'entries' = [];]; if (~(type == 'file' & name == '-')) closeio (fd); graph.maxgid = tablesize (graph.graphs); graph.maxnid = tablesize (graph.nodes); graph.maxeid = tablesize (graph.edges); for (nid in graph.nodes) graph.nodes[nid][dotty.keys.nid] = nid; for (eid in graph.edges) graph.edges[eid][dotty.keys.eid] = eid; for (gid in graph.graphs) graph.graphs[gid][dotty.keys.gid] = gid; gt.unpackattr (gt); if (layoutflag) { dotty.message (1, 'generating layout'); gt.layoutgraph (gt); } dotty.popbusy (gt, gt.views); return gt.graph; }; dotty.protogt.savegraph = function (gt, name, type) { local fd; if (~name) if (~(name = ask ('file name:', 'file', ''))) return; if ( ~((fd = dotty.openio (name, type, 'w')) >= 0) | ~writegraph (fd, gt.graph, 0) ) { dotty.message (0, 'cannot save graph'); return; } if (~(type == 'file' & name == '-')) closeio (fd); }; dotty.protogt.setgraph = function (gt, graph) { local vid, vt, nid, eid, gid; if (gt.layoutpending > 0) gt.cancellayout (gt); for (vid in gt.views) { vt = gt.views[vid]; vt.colors = []; vt.colorn = 2; } gt.graph = copy (graph); gt.undoarray = ['level' = 0; 'entries' = [];]; gt.unpackattr (gt); gt.graph.maxgid = tablesize (graph.graphs); gt.graph.maxnid = tablesize (graph.nodes); gt.graph.maxeid = tablesize (graph.edges); for (nid in gt.graph.nodes) gt.graph.nodes[nid][dotty.keys.nid] = nid; for (eid in gt.graph.edges) gt.graph.edges[eid][dotty.keys.eid] = eid; for (gid in gt.graph.graphs) gt.graph.graphs[gid][dotty.keys.gid] = gid; gt.unpackattr (gt); dotty.message (1, 'generating layout'); gt.layoutgraph (gt); return gt.graph; }; dotty.protogt.erasegraph = function (gt, protogt, protovt) { local vid, vt; if (gt.layoutpending > 0) gt.cancellayout (gt); for (vid in gt.views) { vt = gt.views[vid]; vt.colors = []; vt.colorn = 2; clear (vt.canvas); } if (~protogt) protogt = dotty.protogt; gt.graph = copy (protogt.graph); gt.undoarray = ['level' = 0; 'entries' = [];]; }; dotty.protogt.layoutgraph = function (gt) { if (gt.graph.graphattr.xdotversion) { gt.unpacklayout (gt, gt.graph); gt.setviewsize (gt.views, gt.graph.rect); gt.redrawgraph (gt, gt.views); return; } if (gt.layoutmode == 'async') { if (~gt.haveinput) { gt.startlayout (gt); return; } if (~gt.finishlayout (gt)) return; gt.setviewsize (gt.views, gt.graph.rect); gt.redrawgraph (gt, gt.views); } else { if (~gt.startlayout (gt)) return; else while (~gt.finishlayout (gt)) ; gt.setviewsize (gt.views, gt.graph.rect); gt.redrawgraph (gt, gt.views); } }; dotty.protogt.createview = function (gt, protovt) { local vt, ovt, id, t; vt = []; vt.colors = []; vt.colorn = 2; if (~protovt) protovt = dotty.protovt.normal; if (protovt.mode ~= 'replace') { for (id in dotty.protovt[protovt.type]) vt[id] = copy (dotty.protovt[protovt.type][id]); } for (id in protovt) vt[id] = copy (protovt[id]); if (~(vt.parent >= 0)) { vt.view = createwidget (-1, [ 'type' = 'view'; 'name' = vt.name; 'origin' = vt.orig; 'size' = vt.size; ]); vt.scroll = createwidget (vt.view, ['type' = 'scroll';]); } else { vt.view = -1; vt.scroll = createwidget (vt.parent, [ 'type' = 'scroll'; 'size' = vt.size; ]); } vt.canvas = createwidget (vt.scroll, [ 'type' = 'canvas'; 'color' = [0 = protovt.bgcolor; 1 = protovt.fgcolor;]; ]); setwidgetattr (vt.canvas, [ 'window' = vt.wrect; 'viewport' = vt.vsize; ]); clear (vt.canvas); dotty.views[vt.canvas] = vt; vt.vtid = vt.canvas; vt.gtid = gt.gtid; gt.views[vt.vtid] = vt; dotty.views[vt.scroll] = vt; if (vt.view ~= -1) dotty.views[vt.view] = vt; if (protovt.colors & tablesize (protovt.colors) > 0) { for (id in protovt.colors) if (id == '_bgcolor_') setwidgetattr (vt.canvas, [ 'color' = [0 = protovt.colors[id];]; ]); else if (setwidgetattr (vt.canvas, ['color' = [ protovt.colors[id] = id; ];]) ~= 1) { t = split (id, ' '); if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, [ 'color' = [protovt.colors[id] = [ 'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]); ];]; ]) ~= 1) { dotty.message ( 0, concat ('unknown color ', id, ' using #1') ); } } vt.colors = copy (protovt.colors); vt.colorn = protovt.colorn; } else if (tablesize (gt.views) > 1) { for (id in gt.views) if (gt.views[id] ~= vt) break; ovt = gt.views[id]; for (id in ovt.colors) if (id == '_bgcolor_') setwidgetattr (vt.canvas, ['color' = [0 = ovt.colors[id];];]); else if (setwidgetattr (vt.canvas, ['color' = [ ovt.colors[id] = id; ];]) ~= 1) { t = split (id, ' '); if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, [ 'color' = [ovt.colors[id] = [ 'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]); ];]; ]) ~= 1) { dotty.message ( 0, concat ('unknown color ', id, ' using #1') ); } } vt.colors = copy (ovt.colors); vt.colorn = ovt.colorn; } if (gt.graph.rect) gt.setviewsize ([vt.vtid = vt;], gt.graph.rect); gt.drawgraph (gt, [vt.vtid = vt;]); for (id in vt.uifuncs) if (id == 'closeview') widgets[vt.view][id] = vt.uifuncs[id]; else widgets[vt.canvas][id] = vt.uifuncs[id]; return vt; }; dotty.protogt.destroyview = function (gt, vt) { destroywidget (vt.canvas); destroywidget (vt.scroll); if (vt.view ~= -1) { destroywidget (vt.view); remove (vt.view, dotty.views); } remove (vt.scroll, dotty.views); remove (vt.canvas, dotty.views); if (vt.gtid >= 0) remove (vt.vtid, gt.views); if (tablesize (dotty.views) == 0) exit (); }; dotty.protogt.zoom = function (gt, vt, factor, pos) { gt.setviewscale ([vt.vtid = vt;], factor); if (pos) gt.setviewcenter ([vt.vtid = vt;], pos); gt.redrawgraph (gt, [vt.vtid = vt;]); }; dotty.protogt.findnode = function (gt, vt) { local key, node, node1, nid; if (~(key = ask ('give node name or label'))) return; if (gt.graph.nodedict[key] >= 0) node = gt.graph.nodes[gt.graph.nodedict[key]]; else if (gt.graph.nodedict[ston (key)] >= 0) node = gt.graph.nodes[gt.graph.nodedict[ston (key)]]; else { for (nid in gt.graph.nodes) { node1 = gt.graph.nodes[nid]; if (node1.attr.label == key | node1.attr.label == ston (key)) { node = node1; break; } } } if (~node) { dotty.message (0, concat ('cannot find node: ', key)); return; } gt.setviewcenter ([vt.vtid = vt;], node.pos); }; dotty.protogt.setattr = function (gt, obj) { local kv, t, attr, value, n, i, s; if (~(kv = ask ('give attr/value, eg. color=blue'))) return; t = split (kv, '='); attr = t[0]; value = t[1]; if ((n = tablesize (t)) > 2) for (i = 2; i < n; i = i + 1) value = concat (value, '=', t[i]); # Check for HTML string and convert using lefty convention s = split (value, ''); n = tablesize (s); if ((s[0] == '<') & (s[n-1] == '>')) { s[0] = '>'; s[n-1] = '<'; value = s[0]; for (i = 1; i < n; i = i + 1) value = concat (value, s[i]); } if ( obj.attr == gt.graph.graphattr | obj.attr == gt.graph.edgeattr | obj.attr == gt.graph.nodeattr ) { obj.attr[attr] = value; return; } if (obj.nid >= 0) { gt.undrawnode (gt, gt.views, obj); obj.attr[attr] = value; gt.unpacknodeattr (gt, obj); gt.drawnode (gt, gt.views, obj); } else if (obj.eid >= 0) { gt.undrawedge (gt, gt.views, obj); obj.attr[attr] = value; gt.unpackedgeattr (gt, obj); gt.drawedge (gt, gt.views, obj); } }; dotty.protogt.getattr = function (gt, node) { local kv; if (~(kv.key = ask ('give attr name'))) return null; if ((kv.val = node.attr[kv.key])) return kv; return null; }; # # utilities # dotty.createviewandgraph = function (name, type, protogt, protovt) { local vt, gt; if (~protogt) protogt = dotty.protogt; if (protogt.creategraph) gt = protogt.creategraph (protogt); else gt = dotty.protogt.creategraph (protogt); vt = gt.createview (gt, protovt); if (~protogt.graph) protogt.graph = copy (dotty.protogt.graph); if (name) gt.loadgraph (gt, name, type, protogt.graph, 1); return ['gt' = gt; 'vt' = vt;]; }; dotty.openio = function (name, type, mode) { local fd; if (~name) return null; if (type == 'file') { if (name == '-') { if (mode == 'r' | mode == 'r+') fd = 0; else fd = 1; } else if (~((fd = openio ('file', name, mode)) >= 0)) { dotty.message (0, concat ('cannot open file: ', name)); return null; } } else if (type == 'pipe') { if (~((fd = openio ( 'pipe', 'ksh', mode, concat ("%e ", name) )) >= 0)) { dotty.message (0, concat ('cannot run command: ', name)); return null; } } else return null; return fd; }; dotty.pushbusy = function (gt, views) { local vid; if (gt.busy == 0) for (vid in gt.views) setwidgetattr (vid, ['cursor' = 'watch';]); gt.busy = gt.busy + 1; }; dotty.popbusy = function (gt, views) { local vid; gt.busy = gt.busy - 1; if (gt.busy == 0) for (vid in gt.views) setwidgetattr (vid, ['cursor' = 'default';]); }; dotty.message = function (level, text) { if (level <= dotty.mlevel) echo ('dotty.lefty: ', text); }; # # printing or saving to file # dotty.protogt.printorsave = function (gt, vt, otype, name, mode, ptype) { local pr, wrect, vsize, xy, psize, canvas, pscanvas, cid, cname, t; local graph, edgehandles, fontmap, eid, edge, nid, node, gid, sgraph; local did, draw, i; if (~otype) if (~(otype = ask ('print to', 'choice', 'file|printer'))) return; if (otype == 'printer') { if (~getenv ('TMPDIR')) name = concat (getenv ('HOME'), '/.dottyout.ps'); else name = concat (getenv ('TMPDIR'), '/.dottyout.ps', random (10000)); if (getenv ('LEFTYWINSYS') ~= 'mswin' & ~pr) if (~(pr = ask ('printer command', 'string', 'lpr'))) return; } if (~name) if (~(name = ask ('postscript file', 'file', 'out.ps'))) return; if (~ptype) if (~(ptype = ask ('page size', 'choice', '8.5x11|11x17|36x50'))) return; if (~mode) if (~(mode = ask ('mode', 'choice', 'portrait|landscape|best fit'))) return; wrect = copy (vt.wrect); wrect[0].x = wrect[0].x - 1; wrect[1].x = wrect[1].x + 1; wrect[0].y = wrect[0].y - 1; wrect[1].y = wrect[1].y + 1; vsize = copy (vt.vsize); if (vsize.x == 0) vsize.x = 1; if (vsize.y == 0) vsize.y = 1; xy = vsize.x / vsize.y; if (mode == 'best fit') { if (xy < 1) mode = 'portrait'; else mode = 'landscape'; } psize = dotty.pagesizes[ptype]; if (mode == 'portrait') { if (xy < psize.x / psize.y) { vsize.y = psize.y * 300; vsize.x = vsize.y * xy; } else { vsize.x = psize.x * 300; vsize.y = vsize.x / xy; } } else { if (xy < psize.y / psize.x) { vsize.y = psize.x * 300; vsize.x = vsize.y * xy; } else { vsize.x = psize.y * 300; vsize.y = vsize.x / xy; } } if (~((pscanvas = createwidget (-1, [ 'type' = 'ps'; 'origin' = ['x' = 0; 'y' = 0;]; 'size' = vsize; 'mode' = mode; 'name' = name; ])) >= 0)) { dotty.message (0, 'cannot open printer device'); return; } for (cname in vt.colors) { cid = vt.colors[cname]; if (cname == '_bgcolor_') setwidgetattr (pscanvas, ['color' = [0 = cid;];]); else if (setwidgetattr (pscanvas, ['color' = [cid = cname;];]) ~= 1) { t = split (cname, ' '); if (tablesize (t) ~= 3 | setwidgetattr (pscanvas, [ 'color' = [cid = [ 'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]); ];]; ]) ~= 1) { dotty.message ( 0, concat ('unknown color ', cname, ' using #1') ); } } } setwidgetattr (pscanvas, ['window' = wrect;]); graph = copy (gt.graph); canvas = vt.canvas; vt.canvas = pscanvas; edgehandles = gt.edgehandles; gt.edgehandles = 0; fontmap = dotty.maps[getenv ('LEFTYWINSYS')].psfontmap; for (eid in graph.edges) { edge = graph.edges[eid]; edge.fontname = fontmap[edge.attr.fontname]; for (did in edge.draws) { if (did == 'ep') continue; draw = edge.draws[did]; for (i = 0; draw[i]; i = i + 1) if (draw[i].type == 'F') draw[i].fn = fontmap[draw[i].ofn]; } gt.drawedge (gt, [0 = vt;], edge); } for (nid in graph.nodes) { node = graph.nodes[nid]; node.fontname = fontmap[node.attr.fontname]; for (did in node.draws) { if (did == 'ep') continue; draw = node.draws[did]; for (i = 0; draw[i]; i = i + 1) if (draw[i].type == 'F') draw[i].fn = fontmap[draw[i].ofn]; } gt.drawnode (gt, [0 = vt;], node); } for (gid in graph.graphs) { sgraph = graph.graphs[gid]; sgraph.fontname = fontmap[sgraph.graphattr.fontname]; for (did in sgraph.draws) { if (did == 'ep') continue; draw = sgraph.draws[did]; for (i = 0; draw[i]; i = i + 1) if (draw[i].type == 'F') draw[i].fn = fontmap[draw[i].ofn]; } gt.drawsgraph (gt, [0 = vt;], sgraph); } graph.fontname = fontmap[graph.graphattr.fontname]; gt.drawsgraph (gt, [0 = vt;], graph); gt.edgehandles = edgehandles; vt.canvas = canvas; destroywidget (pscanvas); if (otype == 'printer' & getenv ('LEFTYWINSYS') ~= 'mswin') system (concat (pr, ' ', name, '; rm ',name)); }; PKu�\̨�^�M�Mlefty/dotty_draw.leftynu�[���# # dotty_draw: drawing functions and data structures # dotty.protogt.drawgraph = function (gt, views) { local gid, eid, nid, graph; graph = gt.graph; gt.drawsgraph (gt, views, graph); for (gid in graph.graphs) gt.drawsgraph (gt, views, graph.graphs[gid]); for (eid in graph.edges) gt.drawedge (gt, views, graph.edges[eid]); for (nid in graph.nodes) gt.drawnode (gt, views, graph.nodes[nid]); }; dotty.protogt.redrawgraph = function (gt, views) { local vid; for (vid in views) clear (views[vid].canvas); gt.drawgraph (gt, views); }; dotty.protogt.setviewsize = function (views, r) { local vid, vt, w2v, scale, attr; for (vid in views) { vt = views[vid]; vt.wrect = copy (r); if (r[1].x == 0 | r[1].y == 0) { attr = getwidgetattr (vt.scroll, [0 = 'size';]); vt.wrect[1] = copy (attr.size); } if (vt.type == 'birdseye') { attr = getwidgetattr (vt.scroll, [0 = 'size';]); scale.x = (vt.wrect[1].x - vt.wrect[0].x) / attr.size.x; scale.y = (vt.wrect[1].y - vt.wrect[0].y) / attr.size.y; if (scale.x > 1 & scale.x > scale.y) vt.w2v = scale.x; else if (scale.y > 1) vt.w2v = scale.y; else vt.w2v = 1; } w2v = vt.w2v; vt.vsize = [ 'x' = toint ((vt.wrect[1].x - vt.wrect[0].x) / w2v); 'y' = toint ((vt.wrect[1].y - vt.wrect[0].y) / w2v); ]; setwidgetattr (vt.canvas, [ 'window' = vt.wrect; 'viewport' = vt.vsize; ]); attr = getwidgetattr (vt.canvas, [0 = 'viewport';]); vt.vsize = copy (attr.viewport); } }; dotty.protogt.setviewscale = function (views, factor) { local vid, vt, w2v, attr; for (vid in views) { vt = views[vid]; if ((w2v = vt.w2v * factor) < 0.01) { dotty.message (0, 'cannot zoom any closer'); return; } vt.w2v = w2v; vt.vsize = [ 'x' = (vt.wrect[1].x - vt.wrect[0].x) / w2v; 'y' = (vt.wrect[1].y - vt.wrect[0].y) / w2v; ]; setwidgetattr (vt.canvas, ['viewport' = vt.vsize;]); attr = getwidgetattr (vt.canvas, [0 = 'viewport';]); vt.vsize = copy (attr.viewport); } }; dotty.protogt.setviewcenter = function (views, center) { local vid, vt, pos; for (vid in views) { vt = views[vid]; pos = [ 'x' = center.x * vt.vsize.x / (vt.wrect[1].x - vt.wrect[0].x); 'y' = ( (vt.wrect[1].y - center.y) * vt.vsize.y / (vt.wrect[1].y - vt.wrect[0].y) ); ]; setwidgetattr (vt.scroll, ['childcenter' = pos;]); } }; # # draw graph components # dotty.protogt.drawsgraph = function (gt, views, sgraph) { sgraph.draw = 1; if (~sgraph.draws) return; gt.execalldraw (gt, views, null, sgraph.draws, [ 'fontname' = sgraph.fontname; 'fontsize' = sgraph.fontsize; 'fontcolor' = sgraph.fontcolor; 'drawcolor' = sgraph.drawcolor; 'fillcolor' = sgraph.fillcolor; ]); }; dotty.protogt.undrawsgraph = function (gt, views, sgraph) { sgraph.drawn = 0; if (~sgraph.draws) return; gt.execalldraw (gt, views, null, sgraph.draws, [ 'fontname' = sgraph.fontname; 'fontsize' = sgraph.fontsize; 'fontcolor' = sgraph.fontcolor; 'drawcolor' = 0; 'fillcolor' = 0; ]); }; dotty.protogt.drawnode = function (gt, views, node) { local vid; node.drawn = 1; if (~node.draws) return; gt.execalldraw (gt, views, node, node.draws, [ 'fontname' = node.fontname; 'fontsize' = node.fontsize; 'fontcolor' = node.fontcolor; 'drawcolor' = node.drawcolor; 'fillcolor' = node.fillcolor; ]); for (vid in views) setpick (views[vid].canvas, node, node.rect); }; dotty.protogt.undrawnode = function (gt, views, node) { local vid; if (~node.drawn) return; node.drawn = 0; if (~node.pos) return; gt.execalldraw (gt, views, node, node.draws, [ 'nooverride' = 1; 'fontname' = node.fontname; 'fontsize' = node.fontsize; 'fontcolor' = 0; 'drawcolor' = 0; 'fillcolor' = 0; ]); for (vid in views) clearpick (views[vid].canvas, node); }; dotty.protogt.movenode = function (gt, node, pos) { local dp, eid, edge; dp.x = pos.x - node.pos.x; dp.y = pos.y - node.pos.y; gt.undrawnode (gt, gt.views, node); node.pos.x = pos.x; node.pos.y = pos.y; gt.movenodedraw (node.draws, dp); for (eid in node.edges) { edge = node.edges[eid]; gt.undrawedge (gt, gt.views, edge); gt.moveedgedraw (edge.draws, edge.tail.pos, edge.head.pos); gt.drawedge (gt, gt.views, edge); } gt.drawnode (gt, gt.views, node); }; dotty.protogt.drawedge = function (gt, views, edge) { local vid, canvas; edge.drawn = 1; if (~edge.draws) return; gt.execalldraw (gt, views, edge, edge.draws, [ 'fontname' = edge.fontname; 'fontsize' = edge.fontsize; 'fontcolor' = edge.fontcolor; 'drawcolor' = edge.drawcolor; 'fillcolor' = edge.fillcolor; ]); for (vid in views) { canvas = views[vid].canvas; if (gt.edgehandles == 0 | ~edge.draws.ep) continue; arc (canvas, edge, edge.draws.ep, ['x' = 5; 'y' = 5;], ['color' = 1;]); } }; dotty.protogt.undrawedge = function (gt, views, edge) { local vid, canvas; if (~edge.drawn) return; edge.drawn = 0; if (~edge.draws) return; gt.execalldraw (gt, views, edge, edge.draws, [ 'nooverride' = 1; 'fontname' = edge.fontname; 'fontsize' = edge.fontsize; 'fontcolor' = 0; 'drawcolor' = 0; 'fillcolor' = 0; ]); for (vid in views) { canvas = views[vid].canvas; if (gt.edgehandles == 0 | ~edge.draws.ep) continue; arc (canvas, edge, edge.draws.ep, ['x' = 5; 'y' = 5;], ['color' = 0;]); clearpick (canvas, edge); } }; # # draw directives # dotty.protogt.execalldraw = function (gt, views, obj, draws, gc) { local vid, vt, did, draw, i, func; for (vid in views) { vt = views[vid]; for (did in draws) { if (did == 'ep') continue; draw = draws[did]; for (i = 0; draw[i]; i = i + 1) if ((func = gt.drawfunc[draw[i].type])) func (gt, vt.canvas, obj, draw[i], gc); } } }; dotty.protogt.drawfunc.E = function (gt, canvas, obj, data, gc) { arc (canvas, obj, data.c, data.s, [ 'color' = gc.fillcolor; 'style' = gc.style; 'width' = gc.width; 'fill' = 'on'; ]); arc (canvas, obj, data.c, data.s, [ 'color' = gc.drawcolor; 'style' = gc.style; 'width' = gc.width; ]); }; dotty.protogt.drawfunc.e = function (gt, canvas, obj, data, gc) { arc (canvas, obj, data.c, data.s, [ 'color' = gc.drawcolor; 'style' = gc.style; 'width' = gc.width; ]); }; dotty.protogt.drawfunc.P = function (gt, canvas, obj, data, gc) { polygon (canvas, obj, data.ps, [ 'color' = gc.fillcolor; 'style' = gc.style; 'width' = gc.width; 'fill' = 'on'; ]); polygon (canvas, obj, data.ps, [ 'color' = gc.drawcolor; 'style' = gc.style; 'width' = gc.width; ]); }; dotty.protogt.drawfunc.p = function (gt, canvas, obj, data, gc) { polygon (canvas, obj, data.ps, [ 'color' = gc.drawcolor; 'style' = gc.style; 'width' = gc.width; ]); }; dotty.protogt.drawfunc.L = function (gt, canvas, obj, data, gc) { polygon (canvas, obj, data.ps, [ 'color' = gc.drawcolor; 'style' = gc.style; 'width' = gc.width; ]); }; dotty.protogt.drawfunc.b = function (gt, canvas, obj, data, gc) { splinegon (canvas, obj, data.ps, [ 'color' = gc.fillcolor; 'style' = gc.style; 'width' = gc.width; 'fill' = 'on'; ]); }; dotty.protogt.drawfunc.B = function (gt, canvas, obj, data, gc) { splinegon (canvas, obj, data.ps, [ 'color' = gc.drawcolor; 'style' = gc.style; 'width' = gc.width; ]); }; dotty.protogt.drawfunc.T = function (gt, canvas, obj, data, gc) { text (canvas, obj, data.p, data.s, gc.fontname, gc.fontsize, data.j, [ 'color' = gc.fontcolor; 'style' = gc.style; 'width' = gc.width; ]); }; dotty.protogt.drawfunc.C = function (gt, canvas, obj, data, gc) { if (gc.nooverride ~= 1) gc.fillcolor = data.fillcolor; }; dotty.protogt.drawfunc.c = function (gt, canvas, obj, data, gc) { if (gc.nooverride ~= 1) { gc.drawcolor = data.drawcolor; gc.fontcolor = data.drawcolor; } }; dotty.protogt.drawfunc.F = function (gt, canvas, obj, data, gc) { gc.fontname = data.fn; gc.fontsize = data.fs; }; dotty.protogt.drawfunc.S = function (gt, canvas, obj, data, gc) { gc.style = data.style; gc.width = data.width; }; dotty.protogt.movenodedraw = function (draws, dp) { local did, draw, i, j; for (did in draws) { if (did == 'ep') continue; draw = draws[did]; for (i = 0; draw[i]; i = i + 1) { if (draw[i].type == 'E' | draw[i].type == 'e') { draw[i].c.x = draw[i].c.x + dp.x; draw[i].c.y = draw[i].c.y + dp.y; } else if (draw[i].type == 'P' | draw[i].type == 'p') { for (j = 1; draw[i].ps[j]; j = j + 1) { draw[i].ps[j].x = draw[i].ps[j].x + dp.x; draw[i].ps[j].y = draw[i].ps[j].y + dp.y; } } else if (draw[i].type == 'L' | draw[i].type == 'B') { for (j = 0; draw[i].ps[j]; j = j + 1) { draw[i].ps[j].x = draw[i].ps[j].x + dp.x; draw[i].ps[j].y = draw[i].ps[j].y + dp.y; } } else if (draw[i].type == 'T') { draw[i].p.x = draw[i].p.x + dp.x; draw[i].p.y = draw[i].p.y + dp.y; } } } }; dotty.protogt.moveedgedraw = function (draws, tp, hp) { local draws2, did; for (did in draws) draws2[did] = draws[did]; for (did in draws2) remove (did, draws); draws[0] = [ 0 = [ 'type' = 'L'; 'n' = 2; 'ps' = [ 0 = copy (tp); 1 = copy (hp); ]; ]; 'ep' = ['x' = (tp.x + hp.x) / 2; 'y' = (tp.y + hp.y) / 2;]; ]; }; dotty.protogt.simplenodedraw = function (node, c, s) { local draws; if (node.attr.shape == 'ellipse') draws[0] = [ 0 = [ 'type' = 'e'; 'c' = copy (c); 's' = ['x' = s.x / 2; 'y' = s.y / 2;]; ]; ]; else draws[0] = [ 0 = [ 'type' = 'p'; 'n' = 5; 'ps' = [ 0 = ['x' = c.x - s.x / 2; 'y' = c.y - s.y / 2;]; 1 = ['x' = c.x + s.x / 2; 'y' = c.y - s.y / 2;]; 2 = ['x' = c.x + s.x / 2; 'y' = c.y + s.y / 2;]; 3 = ['x' = c.x - s.x / 2; 'y' = c.y + s.y / 2;]; 4 = ['x' = c.x - s.x / 2; 'y' = c.y - s.y / 2;]; ]; ]; ]; return draws; }; dotty.protogt.simpleedgedraw = function (edge, tp, hp) { local draws; draws[0] = [ 0 = [ 'type' = 'L'; 'n' = 2; 'ps' = [ 0 = copy (tp); 1 = copy (hp); ]; ]; 'ep' = ['x' = (tp.x + hp.x) / 2; 'y' = (tp.y + hp.y) / 2;]; ]; return draws; }; # # utilities # dotty.protogt.getcolor = function (views, name) { local vid, vt, color, t; for (vid in views) { vt = views[vid]; if (~(color >= 0)) { if (~(vt.colors[name] >= 0)) color = (vt.colors[name] = vt.colorn); else { color = vt.colors[name]; break; } } else if (~(vt.colors[name] >= 0)) vt.colors[name] = color; else if (vt.colors[name] ~= color) dotty.message (0, concat ('inconsistent color ids for ', name)); if (setwidgetattr (vt.canvas, ['color' = [color = name;];]) ~= 1) { t = split (name, ' '); if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, ['color' = [color = [ 'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]); ];];]) ~= 1) { dotty.message (0, concat ('unknown color ', name, ' using #1')); return 1; } } vt.colorn = color + 1; } return color; }; dotty.protogt.setbgcolor = function (views, name) { local vid, vt, t; for (vid in views) { vt = views[vid]; if (setwidgetattr (vt.canvas, ['color' = [0 = name;];]) ~= 1) { t = split (name, ' '); if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, ['color' = [0 = [ 'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]); ];];]) ~= 1) { dotty.message (0, concat ('unknown bgcolor ', name)); return; } } vt.colors['_bgcolor_'] = name; } }; dotty.protogt.unpacksgraphattr = function (gt, sgraph) { local attr; attr = sgraph.graphattr; if (dotty.fontmap[attr.fontname]) sgraph[dotty.keys.fname] = dotty.fontmap[attr.fontname]; else sgraph[dotty.keys.fname] = attr.fontname; sgraph[dotty.keys.fsize] = ston (attr.fontsize); sgraph[dotty.keys.fcolor] = gt.getcolor (gt.views, attr.fontcolor); if (attr.color) sgraph[dotty.keys.dcolor] = gt.getcolor (gt.views, attr.color); else sgraph[dotty.keys.dcolor] = gt.getcolor (gt.views, 'black'); if (attr.style == 'filled') { if (attr.fillcolor) sgraph[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.fillcolor); else if (attr.color) sgraph[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.color); else sgraph[dotty.keys.bcolor] = gt.getcolor (gt.views, 'lightgrey'); } }; dotty.protogt.unpacknodeattr = function (gt, node) { local attr; attr = node.attr; if (dotty.fontmap[attr.fontname]) node[dotty.keys.fname] = dotty.fontmap[attr.fontname]; else node[dotty.keys.fname] = attr.fontname; node[dotty.keys.fsize] = ston (attr.fontsize); node[dotty.keys.fcolor] = gt.getcolor (gt.views, attr.fontcolor); if (attr.color) node[dotty.keys.dcolor] = gt.getcolor (gt.views, attr.color); else node[dotty.keys.dcolor] = gt.getcolor (gt.views, 'black'); if (attr.style == 'filled') { if (attr.fillcolor) node[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.fillcolor); else if (attr.color) node[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.color); else node[dotty.keys.bcolor] = gt.getcolor (gt.views, 'lightgrey'); } }; dotty.protogt.unpackedgeattr = function (gt, edge) { local attr; attr = edge.attr; if (dotty.fontmap[attr.fontname]) edge[dotty.keys.fname] = dotty.fontmap[attr.fontname]; else edge[dotty.keys.fname] = attr.fontname; edge[dotty.keys.fsize] = ston (attr.fontsize); edge[dotty.keys.fcolor] = gt.getcolor (gt.views, attr.fontcolor); if (attr.color) edge[dotty.keys.dcolor] = gt.getcolor (gt.views, attr.color); else edge[dotty.keys.dcolor] = gt.getcolor (gt.views, 'black'); if (attr.style == 'filled') { if (attr.fillcolor) edge[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.fillcolor); else if (attr.color) edge[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.color); else edge[dotty.keys.bcolor] = gt.getcolor (gt.views, 'lightgrey'); } }; dotty.protogt.unpackattr = function (gt) { local gid, sgraph, nid, node, eid, edge, graph, attr; graph = gt.graph; attr = graph.graphattr; if (dotty.fontmap[attr.fontname]) graph[dotty.keys.fname] = dotty.fontmap[attr.fontname]; else graph[dotty.keys.fname] = attr.fontname; graph[dotty.keys.fsize] = ston (attr.fontsize); graph[dotty.keys.fcolor] = gt.getcolor (gt.views, attr.fontcolor); if (attr.color) graph[dotty.keys.dcolor] = gt.getcolor (gt.views, attr.color); else graph[dotty.keys.dcolor] = gt.getcolor (gt.views, 'black'); if (attr.style == 'filled') { if (attr.fillcolor) graph[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.fillcolor); else if (attr.color) graph[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.color); else graph[dotty.keys.bcolor] = gt.getcolor (gt.views, 'lightgrey'); } if (attr.bgcolor & attr.bgcolor ~= '') gt.setbgcolor (gt.views, attr.bgcolor); for (gid in graph.graphdict) { sgraph = graph.graphs[graph.graphdict[gid]]; attr = sgraph.graphattr; if (dotty.fontmap[attr.fontname]) sgraph[dotty.keys.fname] = dotty.fontmap[attr.fontname]; else sgraph[dotty.keys.fname] = attr.fontname; sgraph[dotty.keys.fsize] = ston (attr.fontsize); sgraph[dotty.keys.fcolor] = gt.getcolor (gt.views, attr.fontcolor); if (attr.color) sgraph[dotty.keys.dcolor] = gt.getcolor (gt.views, attr.color); else sgraph[dotty.keys.dcolor] = gt.getcolor (gt.views, 'black'); if (attr.style == 'filled') { if (attr.fillcolor) sgraph[dotty.keys.bcolor] = gt.getcolor ( gt.views, attr.fillcolor ); else if (attr.color) sgraph[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.color); else sgraph[dotty.keys.bcolor] = gt.getcolor (gt.views, 'lightgrey'); } } for (nid in graph.nodedict) { node = graph.nodes[graph.nodedict[nid]]; attr = node.attr; if (dotty.fontmap[attr.fontname]) node[dotty.keys.fname] = dotty.fontmap[attr.fontname]; else node[dotty.keys.fname] = attr.fontname; node[dotty.keys.fsize] = ston (attr.fontsize); node[dotty.keys.fcolor] = gt.getcolor (gt.views, attr.fontcolor); if (attr.color) node[dotty.keys.dcolor] = gt.getcolor (gt.views, attr.color); else node[dotty.keys.dcolor] = gt.getcolor (gt.views, 'black'); if (attr.style == 'filled') { if (attr.fillcolor) node[dotty.keys.bcolor] = gt.getcolor ( gt.views, attr.fillcolor ); else if (attr.color) node[dotty.keys.bcolor] = gt.getcolor (gt.views, attr.color); else node[dotty.keys.bcolor] = gt.getcolor (gt.views, 'lightgrey'); } } for (eid in graph.edges) { edge = graph.edges[eid]; attr = edge.attr; if (dotty.fontmap[attr.fontname]) edge[dotty.keys.fname] = dotty.fontmap[attr.fontname]; else edge[dotty.keys.fname] = attr.fontname; edge[dotty.keys.fsize] = ston (attr.fontsize); edge[dotty.keys.fcolor] = gt.getcolor (gt.views, attr.fontcolor); if (attr.color) edge[dotty.keys.dcolor] = gt.getcolor (gt.views, attr.color); else edge[dotty.keys.dcolor] = gt.getcolor (gt.views, 'black'); } }; PKu�\�!ϼ~F~Flefty/dotty_edit.leftynu�[���# # dotty_edit: editing functions and data structures # dotty.protogt.getnodesbyattr = function (gt, key, val) { local nid, node, nlist; nlist = []; for (nid in gt.graph.nodes) { node = gt.graph.nodes[nid]; if (node.attr[key] == val) nlist[nid] = node; } return nlist; }; dotty.protogt.reachablenodes = function (gt, node) { local nlist, stack, eid, edge, i; stack[0] = node; i = 1; while (i > 0) { node = stack[i - 1]; i = i - 1; nlist[node.nid] = node; for (eid in node.edges) { edge = node.edges[eid]; if (~nlist[edge.head.nid]) { nlist[edge.head.nid] = edge.head; stack[i] = edge.head; i = i + 1; } } } return nlist; }; dotty.protogt.mergegraph = function (gt, graph, show) { local nameid, onode, pos, size, eid, eid2, tnode, hnode, oedge; if (~gt.noundo) gt.startadd2undo (gt); for (nameid in graph.nodedict) { pos = null; size = null; onode = graph.nodes[graph.nodedict[nameid]]; if (onode.pos) pos = node.pos; if (onode.size) size = node.size; if (~(gt.graph.nodedict[nameid] >= 0)) { pos = null; size = null; if (onode.pos) pos = node.pos; if (onode.size) size = node.size; gt.insertnode (gt, pos, size, nameid, onode.attr, show); } } for (eid in graph.edges) { oedge = graph.edges[eid]; tnode = gt.graph.nodes[gt.graph.nodedict[oedge.tail.name]]; hnode = gt.graph.nodes[gt.graph.nodedict[oedge.head.name]]; for (eid2 in tnode.edges) if ( tnode.edges[eid2].tail == tnode & tnode.edges[eid2].head == hnode ) { oedge = null; break; } if (oedge) gt.insertedge (gt, tnode, null, hnode, null, oedge.attr, show); } if (~gt.noundo) gt.endadd2undo (gt); }; dotty.protogt.insertsgraph = function (gt, name, attr, show) { local gid, sgraph, aid; if (~gt) return null; gid = gt.graph.maxgid; if (~name) { while (gt.graph.graphdict[(name = concat ('g', gid))] >= 0) gid = gid + 1; } else if (gt.graph.graphdict[name]) { dotty.message (0, concat ('graph: ', name, ' exists')); return null; } gt.graph.graphdict[name] = gid; gt.graph.maxgid = gid + 1; gt.graph.graphs[gid] = [ dotty.keys.gid = gid; dotty.keys.name = name; dotty.keys.gattr = copy (gt.graph.graphattr); dotty.keys.nattr = copy (gt.graph.nodeattr); dotty.keys.eattr = copy (gt.graph.edgeattr); ]; sgraph = gt.graph.graphs[gid]; if (~attr) attr = []; if (~attr.label) attr.label = '\N'; for (aid in attr) sgraph.graphattr[aid] = attr[aid]; gt.unpacksgraphattr (gt, sgraph); if (show) gt.drawsgraph (gt, gt.views, sgraph); return sgraph; }; dotty.protogt.removesgraph = function (gt, sgraph) { gt.undrawsgraph (gt, gt.views, sgraph); remove (sgraph.name, gt.graph.graphdict); remove (sgraph.gid, gt.graph.graphs); }; dotty.protogt.insertnode = function (gt, pos, size, name, attr, show) { local nid, node, aid; nid = gt.graph.maxnid; if (~name) { while (gt.graph.nodedict[(name = concat ('n', nid))] >= 0) nid = nid + 1; } else if (gt.graph.nodedict[name] >= 0) { dotty.message (0, concat ('node: ', name, ' exists')); return null; } gt.graph.nodedict[name] = nid; gt.graph.maxnid = nid + 1; gt.graph.nodes[nid] = [ dotty.keys.nid = nid; dotty.keys.name = name; dotty.keys.attr = copy (gt.graph.nodeattr); dotty.keys.edges = []; ]; node = gt.graph.nodes[nid]; if (~attr) attr = []; if (~attr.label) attr.label = '\N'; for (aid in attr) node.attr[aid] = attr[aid]; gt.unpacknodeattr (gt, node); if (~pos) pos = ['x' = 10; 'y' = 10;]; node[dotty.keys.pos] = copy (pos); if (~size) size = ['x' = strlen (attr.label) * 30; 'y' = 30;]; if (size.x == 0) size.x = 30; node[dotty.keys.size] = copy (size); node[dotty.keys.rect] = [ 0 = ['x' = pos.x - size.x / 2; 'y' = pos.y - size.y / 2;]; 1 = ['x' = pos.x + size.x / 2; 'y' = pos.y + size.y / 2;]; ]; node.draws = gt.simplenodedraw (node, pos, size); if (show) gt.drawnode (gt, gt.views, node); if (~gt.noundo) { gt.startadd2undo (gt); gt.currundo.inserted.nodes[nid] = node; gt.endadd2undo (gt); } return node; }; dotty.protogt.removenode = function (gt, node) { local eid, list, edge, gid; if (~gt.noundo) gt.startadd2undo (gt); for (eid in node.edges) list[eid] = node.edges[eid]; for (eid in list) gt.removeedge (gt, list[eid]); gt.undrawnode (gt, gt.views, node); for (gid in gt.graph.graphs) remove (node.nid, gt.graph.graphs[gid].nodes); remove (node.name, gt.graph.nodedict); remove (node.nid, gt.graph.nodes); if (~gt.noundo) { gt.currundo.deleted.nodes[node.nid] = node; gt.endadd2undo (gt); } }; dotty.protogt.insertedge = function ( gt, nodea, porta, nodeb, portb, attr, show ) { local eid, edge, aid, tport, hport; if (~nodea | ~nodeb) return null; if (porta) tport = porta; if (portb) hport = portb; eid = gt.graph.maxeid; while (gt.graph.edges[eid]) eid = eid + 1; gt.graph.maxeid = eid + 1; gt.graph.edges[eid] = [ dotty.keys.eid = eid; dotty.keys.tail = nodea; dotty.keys.tport = porta; dotty.keys.head = nodeb; dotty.keys.hport = portb; dotty.keys.attr = copy (gt.graph.edgeattr); ]; edge = gt.graph.edges[eid]; if (~attr) attr = []; for (aid in attr) edge.attr[aid] = attr[aid]; nodea.edges[eid] = edge; nodeb.edges[eid] = edge; gt.unpackedgeattr (gt, edge); edge.draws = gt.simpleedgedraw (edge, nodea.pos, nodeb.pos); if (show) gt.drawedge (gt, gt.views, edge); if (~gt.noundo) { gt.startadd2undo (gt); gt.currundo.inserted.edges[eid] = edge; gt.endadd2undo (gt); } return edge; }; dotty.protogt.removeedge = function (gt, edge) { local head, tail; if (~gt.noundo) gt.startadd2undo (gt); if (edge.head.attr.support == 1) head = edge.head; if (edge.tail.attr.support == 1) if (head ~= edge.tail) tail = edge.tail; gt.undrawedge (gt, gt.views, edge); remove (edge.eid, edge.head.edges); remove (edge.eid, edge.tail.edges); remove (edge.eid, gt.graph.edges); if (head & tablesize (head.edges) == 0) gt.removenode (gt, head); if (tail & tablesize (tail.edges) == 0) gt.removenode (gt, tail); if (~gt.noundo) { gt.currundo.deleted.edges[edge.eid] = edge; gt.endadd2undo (gt); } }; dotty.protogt.swapedgeids = function (gt, edge1, edge2) { local eid1, eid2; if (edge1.eid == edge2.eid) return; if (~gt.noundo) gt.startadd2undo (gt); eid1 = edge1.eid; eid2 = edge2.eid; gt.graph.edges[eid1] = edge2; gt.graph.edges[eid2] = edge1; remove (eid1, edge1.tail.edges); remove (eid1, edge1.head.edges); remove (eid2, edge2.tail.edges); remove (eid2, edge2.head.edges); edge1.tail.edges[eid2] = edge1; edge1.head.edges[eid2] = edge1; edge2.tail.edges[eid1] = edge2; edge2.head.edges[eid1] = edge2; edge1.eid = eid2; edge2.eid = eid1; if (~gt.noundo) { gt.currundo.swapped.edges[eid1] = edge1; gt.currundo.swapped.edges[eid2] = edge2; gt.endadd2undo (gt); } }; dotty.protogt.removesubtree = function (gt, obj) { local nlist, node, head, nid, edge, eid; if (~gt.noundo) gt.startadd2undo (gt); if (obj.nid >= 0) node = obj; else if (obj.eid >= 0) { node = obj.head; gt.removeedge (gt, obj); if (~gt.graph.nodes[node.nid]) { if (~gt.noundo) gt.endadd2undo (gt); return; } for (eid in node.edges) { edge = node.edges[eid]; if (edge.head == node & edge.tail ~= node) { if (~gt.noundo) gt.endadd2undo (gt); return; } } } else { dotty.message (0, 'bad object type in gt.removesubtree'); return; } nlist = [node.nid = node;]; while (node) { for (eid in node.edges) { head = node.edges[eid].head; if (head ~= node) nlist[head.nid] = head; } gt.removenode (gt, node); remove (node.nid, nlist); node = null; for (nid in nlist) { node = nlist[nid]; for (eid in node.edges) { edge = node.edges[eid]; if (edge.head == node & edge.tail ~= node) { node = null; break; } } if (node) break; } } if (~gt.noundo) gt.endadd2undo (gt); }; dotty.protogt.removenodesbyattr = function (gt, key, val) { local nlist, nid; if (~gt.noundo) gt.startadd2undo (gt); nlist = gt.getnodesbyattr (gt, key, val); for (nid in nlist) gt.removenode (gt, nlist[nid]); if (~gt.noundo) gt.endadd2undo (gt); }; dotty.protogt.removesubtreesbyattr = function (gt, key, val) { local nlist, nid; if (~gt.noundo) gt.startadd2undo (gt); nlist = gt.getnodesbyattr (gt, key, val); for (nid in nlist) if (gt.graph.nodes[nid]) gt.removesubtree (gt, nlist[nid]); if (~gt.noundo) gt.endadd2undo (gt); }; dotty.protogt.groupnodes = function ( gt, nlist, gnode, pos, size, attr, keepmulti, show ) { local nid, node, elist, eid, edge, nodea, nodeb, inlist, outlist; if (~nlist | tablesize (nlist) == 0) return; if (gnode.attr.support) { dotty.message (0, 'cannot group nodes in a support node'); return; } if (~gt.noundo) gt.startadd2undo (gt); if (~gnode) gnode = gt.insertnode (gt, pos, size, null, attr, show); inlist = []; outlist = []; for (nid in nlist) { if ((node = nlist[nid]) == gnode) continue; elist = []; for (eid in node.edges) elist[eid] = node.edges[eid]; for (eid in elist) { edge = elist[eid]; if (edge.head == node) { nodea = edge.tail; nodeb = gnode; if (~keepmulti) { if (inlist[nodea.nid]) continue; inlist[nodea.nid] = nodea; if (nodea == gnode) outlist[nodea.nid] = nodea; } } else { nodea = gnode; nodeb = edge.head; if (~keepmulti) { if (outlist[nodeb.nid]) continue; outlist[nodeb.nid] = nodeb; if (nodeb == gnode) inlist[nodeb.nid] = nodeb; } } gt.insertedge (gt, nodea, null, nodeb, null, edge.attr, show); } gt.removenode (gt, node); } if (~gt.noundo) gt.endadd2undo (gt); return gnode; }; dotty.protogt.groupnodesbyattr = function ( gt, key, val, attr, keepmulti, show ) { local nlist, nid, pos, size; pos = null; size = null; nlist = gt.getnodesbyattr (gt, key, val); if (show) for (nid in nlist) { pos = nlist[nid].pos; size = nlist[nid].size; break; } return gt.groupnodes (gt, nlist, null, pos, size, attr, keepmulti, show); }; dotty.protogt.cut = function (gt, obj, set, mode, op) { local clipgt, list, node, nid, edge, eid, clipnode; clipgt = dotty.clipgt; clipgt.graph = copy (dotty.protogt.graph); if (obj.eid >= 0) { # it's an edge list.edges[obj.eid] = obj; node = obj.head; } else if (obj.nid >= 0) { list.nodes[obj.nid] = obj; node = obj; for (eid in node.edges) list.edges[eid] = node.edges[eid]; } else { dotty.message (0, 'unknown object type in gt.cut'); return; } if (set == 'reachable') { list.nodes = gt.reachablenodes (gt, node); for (nid in list.nodes) { node = list.nodes[nid]; for (eid in node.edges) { edge = node.edges[eid]; list.edges[edge.eid] = edge; } } } if (mode == 'support') { for (eid in list.edges) { edge = list.edges[eid]; if (~list.nodes[edge.tail.nid]) { list.support[edge.tail.nid] = edge.tail; list.nodes[edge.tail.nid] = edge.tail; } if (~list.nodes[edge.head.nid]) { list.support[edge.head.nid] = edge.head; list.nodes[edge.head.nid] = edge.head; } } } for (nid = 0; nid < gt.graph.maxnid; nid = nid + 1) { if (~list.nodes[nid]) continue; node = list.nodes[nid]; clipnode = gt.insertnode (clipgt, null, null, node.name, node.attr, 0); if (list.support[nid]) clipnode.support = 1; list.clipnodes[nid] = clipnode; } for (eid = 0; eid < gt.graph.maxeid; eid = eid + 1) { if (~list.edges[eid]) continue; edge = list.edges[eid]; if (~list.nodes[edge.tail.nid] | ~list.nodes[edge.head.nid]) continue; gt.insertedge ( clipgt, list.clipnodes[edge.tail.nid], null, list.clipnodes[edge.head.nid], null, edge.attr, 0 ); } if (op ~= 'cut') return; if (~gt.noundo) gt.startadd2undo (gt); for (eid in list.edges) gt.removeedge (gt, list.edges[eid]); for (nid in list.nodes) if (~list.support[nid] & gt.graph.nodes[nid]) gt.removenode (gt, list.nodes[nid]); if (~gt.noundo) gt.endadd2undo (gt); }; dotty.protogt.paste = function (gt, pos, show) { local clipgt, offset, center, nid, node, eid, edge, nodes; if (~gt.noundo) gt.startadd2undo (gt); clipgt = dotty.clipgt; if (clipgt.graph.rect) center = [ 'x' = (clipgt.graph.rect[1].x + clipgt.graph.rect[0].x) / 2; 'y' = (clipgt.graph.rect[1].y + clipgt.graph.rect[0].y) / 2; ]; else center = pos; offset = [ 'x' = center.x - pos.x; 'y' = center.y - pos.y; ]; for (nid = 0; clipgt.graph.nodes[nid]; nid = nid + 1) { node = clipgt.graph.nodes[nid]; if (node.attr.label == '\N' | ~node.attr.label) node.attr.label = node.name; if (node.support == 1) nodes[nid] = gt.insertnode (gt, [ 'x' = node.pos.x - offset.x; 'y' = node.pos.y - offset.y; ], null, null, [ 'support' = 1; 'shape' = 'circle'; 'label' = ''; 'width' = 0.2; ], show); else nodes[nid] = gt.insertnode (gt, [ 'x' = node.pos.x - offset.x; 'y' = node.pos.y - offset.y; ], node.size, null, node.attr, show); } for (eid = 0; clipgt.graph.edges[eid]; eid = eid + 1) { edge = clipgt.graph.edges[eid]; gt.insertedge ( gt, nodes[edge.tail.nid], null, nodes[edge.head.nid], null, edge.attr, show ); } if (~gt.noundo) gt.endadd2undo (gt); }; dotty.protogt.startadd2undo = function (gt) { if (~gt.undoarray.level) gt.currundo = ( gt.undoarray.entries[tablesize (gt.undoarray.entries)] = [] ); gt.undoarray.level = gt.undoarray.level + 1; }; dotty.protogt.endadd2undo = function (gt) { gt.undoarray.level = gt.undoarray.level - 1; }; dotty.protogt.undo = function (gt, show) { local entry, n, eid, edge, nid, node, edges; if ((n = tablesize (gt.undoarray.entries)) < 1) return; entry = gt.undoarray.entries[n - 1]; remove (n - 1, gt.undoarray.entries); remove ('currundo', gt); gt.noundo = 1; # hardwire nodes and edges back with the same id's as the originals for (nid in entry.deleted.nodes) { node = entry.deleted.nodes[nid]; gt.graph.nodedict[node.name] = node.nid; gt.graph.nodes[node.nid] = node; node.edges = []; if (show) gt.drawnode (gt, gt.views, node); } for (eid in entry.deleted.edges) { edge = entry.deleted.edges[eid]; gt.graph.edges[edge.eid] = edge; edge.head.edges[edge.eid] = edge; edge.tail.edges[edge.eid] = edge; if (show) gt.drawedge (gt, gt.views, edge); } if (entry.swapped.edges) { if (tablesize (entry.swapped.edges) == 2) { n = 0; for (eid in entry.swapped.edges) { edges[n] = entry.swapped.edges[eid]; n = n + 1; } gt.swapedgeids (gt, edges[0], edges[1]); } else dotty.message (0, 'cannot handle undoing swap of > 2 edges'); } for (eid in entry.inserted.edges) { edge = entry.inserted.edges[eid]; gt.removeedge (gt, edge); } for (nid in entry.inserted.nodes) { node = entry.inserted.nodes[nid]; gt.removenode (gt, node); } gt.noundo = 0; }; PKu�\L�8�8lefty/dotty_layout.leftynu�[���# # dotty_layout: layout functions and data structures # dotty.grablserver = function (lserver) { local fd; if (~dotty.lservers[lserver] | tablesize (dotty.lservers[lserver]) == 0) { if (~((fd = openio ('pipe', lserver, 'r+', '%e -Txdot1.2')) >= 0)) { dotty.message (0, concat ('cannot start ', lserver)); return null; } dotty.lservers[lserver][fd] = [ 'fd' = fd; 'count' = 0; ]; } for (fd in dotty.lservers[lserver]) { dotty.lservers[lserver][fd].count = dotty.lservers[ lserver ][fd].count + 1; dotty.lservers.inuse[fd] = dotty.lservers[lserver][fd]; remove (fd, dotty.lservers[lserver]); return fd; } }; dotty.releaselserver = function (lserver, fd, state) { if (state == 'bad' | dotty.lservers.inuse[fd].count > 40) { closeio (fd, 'kill'); remove (fd, dotty.lservers.inuse); return; } dotty.lservers[lserver][fd] = dotty.lservers.inuse[fd]; remove (fd, dotty.lservers.inuse); }; dotty.protogt.startlayout = function (gt) { local lpt, fd; if (gt.layoutpending >= 1) { lpt = dotty.layoutpending[gt.gtid]; if (gt.layoutmode == 'async') monitor ('off', lpt.fd); dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); remove (gt.gtid, dotty.layoutpending); gt.layoutpending = 0; gt.haveinput = 0; dotty.popbusy (gt, gt.views); } if (~((fd = dotty.grablserver (gt.lserver)) >= 0)) return null; dotty.pushbusy (gt, gt.views); writegraph (fd, gt.graph, 1); gt.layoutpending = 1; dotty.layoutpending[gt.gtid] = [ 'fd' = fd; 'gtid' = gt.gtid; ]; if (gt.layoutmode == 'async') monitor ('on', fd); return 1; }; dotty.protogt.finishlayout = function (gt) { local graph, lpt, fd; if (~(gt.layoutpending >= 1)) { dotty.message (0, concat ('no layout pending for graph ', gt.gtid)); return null; } lpt = dotty.layoutpending[gt.gtid]; if (~(graph = readgraph (lpt.fd))) { if (gt.layoutmode == 'async') monitor ('off', lpt.fd); dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); if (gt.layoutpending == 2) { dotty.message (0, concat ('giving up on ', gt.lserver)); if ((fd = openio ('file', 'dottybug.gv', 'w+')) >= 0) { writegraph (fd, gt.graph, 0); closeio (fd); dotty.message ( 0, concat ('graph that causes ', gt.lserver) ); dotty.message ( 0, 'to fail has been saved in file dottybug.gv' ); dotty.message ( 0, 'please fill out a bug report at' ); dotty.message ( 0, 'http://www.graphviz.org/bugs/bugform.html' ); } dotty.popbusy (gt, gt.views); gt.layoutpending = 0; gt.haveinput = 0; return 1; } dotty.message ( 1, concat ('lost connection to ', gt.lserver, ', restarting...') ); lpt.fd = dotty.grablserver (gt.lserver); writegraph (lpt.fd, gt.graph, 1); if (gt.layoutmode == 'async') monitor ('on', lpt.fd); gt.layoutpending = 2; gt.haveinput = 0; return null; } if (gt.layoutmode == 'async') monitor ('off', lpt.fd); dotty.releaselserver (gt.lserver, lpt.fd, null); remove (gt.gtid, dotty.layoutpending); gt.layoutpending = 0; gt.haveinput = 0; gt.unpacklayout (gt, graph); dotty.popbusy (gt, gt.views); return 1; }; dotty.protogt.cancellayout = function (gt) { local lpt, vid; if (gt.layoutpending >= 1) { lpt = dotty.layoutpending[gt.gtid]; if (gt.layoutmode == 'async') monitor ('off', lpt.fd); dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); remove (gt.gtid, dotty.layoutpending); gt.layoutpending = 0; gt.haveinput = 0; dotty.popbusy (gt, gt.views); } }; dotty.protogt.unpacklayout = function (gt, graph2) { local graph, gid, sgraph1, sgraph2, nid, node1, node2, eid, edge1, edge2; local t1, pos, size; graph = gt.graph; for (gid in graph2.graphdict) { if (~(sgraph1 = graph.graphs[graph.graphdict[gid]])) continue; sgraph2 = graph2.graphs[graph2.graphdict[gid]]; sgraph1.draws = gt.unpackalldraw (gt, sgraph2.graphattr); } for (nid in graph2.nodedict) { if (~(node1 = graph.nodes[graph.nodedict[nid]])) continue; node2 = graph2.nodes[graph2.nodedict[nid]]; node1.draws = gt.unpackalldraw (gt, node2.attr); t1 = split (node2.attr.pos, ','); pos = ['x' = ston (t1[0]); 'y' = ston (t1[1]);]; size = [ 'x' = ston (node2.attr.width) * 72; 'y' = ston (node2.attr.height) * 72; ]; node1.pos = pos; node1.size = size; node1.rect = [ 0 = ['x' = pos.x - size.x / 2; 'y' = pos.y - size.y / 2;]; 1 = ['x' = pos.x + size.x / 2; 'y' = pos.y + size.y / 2;]; ]; } for (eid in graph2.edges) { edge2 = graph2.edges[eid]; if (edge2.attr.id) { if (~(edge1 = graph.edges[ston (edge2.attr.id)])) continue; } else if (graph == graph2) edge1 = edge2; edge1.draws = gt.unpackalldraw (gt, edge2.attr); } graph.draws = gt.unpackalldraw (gt, graph2.graphattr); t1 = split (graph2.graphattr.bb, ','); graph.rect[0].x = ston (t1[0]); graph.rect[0].y = ston (t1[1]); graph.rect[1].x = ston (t1[2]); graph.rect[1].y = ston (t1[3]); if (gt.graph ~= graph2) return; # strip position and size info from the attributes for (gid in graph2.graphdict) { sgraph2 = graph2.graphs[graph2.graphdict[gid]]; gt.removealldraw (gt, sgraph2.graphattr); if (sgraph2.graphattr.bb) remove ('bb', sgraph2.graphattr); } for (nid in graph2.nodedict) { node2 = graph2.nodes[graph2.nodedict[nid]]; gt.removealldraw (gt, node2.attr); if (node2.attr.rects) remove ('rects', node2.attr); remove ('pos', node2.attr); remove ('width', node2.attr); remove ('height', node2.attr); } for (eid in graph2.edges) { edge2 = graph2.edges[eid]; gt.removealldraw (gt, edge2.attr); if (edge2.attr.pos) remove ('pos', edge2.attr); if (edge2.attr.lp) remove ('lp', edge2.attr); } gt.removealldraw (gt, graph2.graphattr); remove ('bb', graph2.graphattr); if (graph2.graphattr.lp) remove ('lp', graph2.graphattr); }; # # draw directive parsing # dotty.protogt.unpackalldraw = function (gt, attr) { local o, did; o = []; if (attr._draw_) o._draw_ = gt.unpackdraw (gt, attr._draw_); if (attr._background) o._background = gt.unpackdraw (gt, attr._background); if (attr._ldraw_) o._ldraw_ = gt.unpackdraw (gt, attr._ldraw_); if (attr._hdraw_) o._hdraw_ = gt.unpackdraw (gt, attr._hdraw_); if (attr._tdraw_) o._tdraw_ = gt.unpackdraw (gt, attr._tdraw_); if (attr._hldraw_) o._hldraw_ = gt.unpackdraw (gt, attr._hldraw_); if (attr._tldraw_) o._tldraw_ = gt.unpackdraw (gt, attr._tldraw_); for (did in o) if (o[did].ep) { o.ep = o[did].ep; break; } return o; }; dotty.protogt.removealldraw = function (gt, attr) { if (attr._draw_) remove ('_draw_', attr); if (attr._ldraw_) remove ('_ldraw_', attr); if (attr._hdraw_) remove ('_hdraw_', attr); if (attr._tdraw_) remove ('_tdraw_', attr); if (attr._hldraw_) remove ('_hldraw_', attr); if (attr._tldraw_) remove ('_tldraw_', attr); }; dotty.protogt.unpackdraw = function (gt, attr) { local oo, o, tt, t, n, i, j, s, l, ep; oo = []; t = split (attr, ' ', 0); n = tablesize (t); if (t[n - 1] == '') { remove (n - 1, t); n = n - 1; } i = 0; while (i < n) { o = []; if (t[i] == 'E') { o.type = t[i]; o.c.x = ston (t[i + 1]); o.c.y = ston (t[i + 2]); o.s.x = ston (t[i + 3]); o.s.y = ston (t[i + 4]); i = i + 5; } else if (t[i] == 'e') { o.type = t[i]; o.c.x = ston (t[i + 1]); o.c.y = ston (t[i + 2]); o.s.x = ston (t[i + 3]); o.s.y = ston (t[i + 4]); i = i + 5; } else if (t[i] == 'P') { o.type = t[i]; o.n = ston (t[i + 1]); for (j = 0; j < o.n; j = j + 1) { o.ps[j].x = ston (t[i + 2 + j * 2]); o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); } i = i + 2 + o.n * 2; o.ps[o.n] = o.ps[0]; o.n = o.n + 1; } else if (t[i] == 'p') { o.type = t[i]; o.n = ston (t[i + 1]); for (j = 0; j < o.n; j = j + 1) { o.ps[j].x = ston (t[i + 2 + j * 2]); o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); } i = i + 2 + o.n * 2; o.ps[o.n] = o.ps[0]; o.n = o.n + 1; } else if (t[i] == 'L') { o.type = t[i]; o.n = ston (t[i + 1]); for (j = 0; j < o.n; j = j + 1) { o.ps[j].x = ston (t[i + 2 + j * 2]); o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); } i = i + 2 + o.n * 2; if (~ep) ep = copy (o.ps[1]); } else if (t[i] == 'B') { o.type = t[i]; o.n = ston (t[i + 1]); for (j = 0; j < o.n; j = j + 1) { o.ps[j].x = ston (t[i + 2 + j * 2]); o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); } i = i + 2 + o.n * 2; if (~ep) ep = copy (o.ps[1]); } else if (t[i] == 'b') { o.type = t[i]; o.n = ston (t[i + 1]); for (j = 0; j < o.n; j = j + 1) { o.ps[j].x = ston (t[i + 2 + j * 2]); o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); } i = i + 2 + o.n * 2; if (~ep) ep = copy (o.ps[1]); } else if (t[i] == 'T') { o.type = t[i]; o.p.x = ston (t[i + 1]); o.p.y = ston (t[i + 2]); o.j = ston (t[i + 3]); if (o.j == -1) o.j = 'lb'; else if (o.j == 1) o.j = 'rb'; else if (o.j == 0) o.j = 'cb'; o.w = ston (t[i + 4]); o.n = ston (t[i + 5]); i = i + 6; s = t[i]; i = i + 1; l = strlen (s) - 1; while (l < o.n) { s = concat (s, ' ', t[i]); l = l + 1 + strlen (t[i]); i = i + 1; } tt = split (s, ''); l = tablesize (tt); s = ''; for (j = 1; j < l; j = j + 1) s = concat (s, tt[j]); o.s = s; } else if (t[i] == 'C') { o.type = t[i]; o.n = ston (t[i + 1]); i = i + 2; s = t[i]; i = i + 1; l = strlen (s) - 1; while (l < o.n) { s = concat (s, ' ', t[i]); l = l + 1 + strlen (t[i]); i = i + 1; } tt = split (s, ''); l = tablesize (tt); s = ''; for (j = 1; j < l; j = j + 1) s = concat (s, tt[j]); o.fillcolor = gt.getcolor (gt.views, s); } else if (t[i] == 'c') { o.type = t[i]; o.n = ston (t[i + 1]); i = i + 2; s = t[i]; i = i + 1; l = strlen (s) - 1; while (l < o.n) { s = concat (s, ' ', t[i]); l = l + 1 + strlen (t[i]); i = i + 1; } tt = split (s, ''); l = tablesize (tt); s = ''; for (j = 1; j < l; j = j + 1) s = concat (s, tt[j]); o.drawcolor = gt.getcolor (gt.views, s); } else if (t[i] == 'F') { o.type = t[i]; o.fs = ston (t[i + 1]); o.n = ston (t[i + 2]); i = i + 3; s = t[i]; i = i + 1; l = strlen (s) - 1; while (l < o.n) { s = concat (s, ' ', t[i]); l = l + 1 + strlen (t[i]); i = i + 1; } tt = split (s, ''); l = tablesize (tt); s = ''; for (j = 1; j < l; j = j + 1) s = concat (s, tt[j]); o.ofn = s; o.fn = dotty.fontmap[s]; } else if (t[i] == 'S') { o.type = t[i]; o.n = ston (t[i + 1]); i = i + 2; s = t[i]; i = i + 1; l = strlen (s) - 1; while (l < o.n) { s = concat (s, ' ', t[i]); l = l + 1 + strlen (t[i]); i = i + 1; } tt = split (s, ''); l = tablesize (tt); s = ''; for (j = 1; j < l; j = j + 1) s = concat (s, tt[j]); if ( s == 'solid' | s == 'dashed' | s == 'dotted' | s == 'longdashed' | s == 'shortdashed' ) o.style = s; else if (s == 'bold') o.width = 3; else { tt = split (s, '('); if (tt[0] == 'setlinewidth') { tt = split (tt[1], ')'); o.width = ston (tt[0]); } else continue; } } else if (t[i] == 'I') { i = i + 7; } else if (t[i] == 't') { i = i + 2; } else { dotty.message (0, concat ('draw language parser error: ', t[i])); return null; } oo[tablesize (oo)] = o; } oo.ep = ep; return oo; }; PKu�\��7�7lefty/dotty_ui.leftynu�[���# # dotty_ui: user interface functions and data structures # dotty.protogt.doaction = function (data, s) { local vt, gt; vt = dotty.views[data.widget]; gt = dotty.graphs[vt.gtid]; data.menuitem = s; if (data.obj.nid >= 0) { if (gt.actions.node[s]) { gt.actions.node[s] (gt, vt, data.obj, data); return; } } else if (data.obj.eid >= 0) { if (gt.actions.edge[s]) { gt.actions.edge[s] (gt, vt, data.obj, data); return; } } if (gt.actions.general[s]) gt.actions.general[s] (gt, vt, data); }; dotty.protogt.actions.general = [ "undo" = function (gt, vt, data) { gt.undo (gt, 1); }; "paste" = function (gt, vt, data) { gt.paste (gt, data.pos, 1); }; "do layout" = function (gt, vt, data) { gt.layoutgraph (gt); }; "cancel layout" = function (gt, vt, data) { gt.cancellayout (gt); }; "redraw" = function (gt, vt, data) { gt.redrawgraph (gt, [vt.vtid = vt;]); }; "new graph" = function (gt, vt, data) { gt.erasegraph (gt, null, null); }; "load graph" = function (gt, vt, data) { gt.loadgraph (gt, null, 'file', dotty.protogt.graph, 1); }; "reload graph" = function (gt, vt, data) { gt.loadgraph (gt, gt.name, gt.type, gt.graph, 1); }; "save graph" = function (gt, vt, data) { gt.savegraph (gt, gt.name, gt.type); }; "save graph as" = function (gt, vt, data) { gt.savegraph (gt, null, 'file'); }; "open view" = function (gt, vt, data) { gt = dotty.protogt.creategraph (null); gt.createview (gt, null); }; "copy view" = function (gt, vt, data) { gt = gt.copygraph (gt); gt.createview (gt, vt); }; "birdseye view" = function (gt, vt, data) { gt.createview (gt, dotty.protovt.birdseye); }; "clone view" = function (gt, vt, data) { gt.createview (gt, vt); }; "close view" = function (gt, vt, data) { gt.destroyview (gt, vt); if (tablesize (gt.views) == 0) gt.destroygraph (gt); }; "set graph attr" = function (gt, vt, data) { gt.setattr (gt, ['attr' = gt.graph.graphattr;]); }; "set node attr" = function (gt, vt, data) { gt.setattr (gt, ['attr' = gt.graph.nodeattr;]); }; "set edge attr" = function (gt, vt, data) { gt.setattr (gt, ['attr' = gt.graph.edgeattr;]); }; "zoom in" = function (gt, vt, data) { gt.zoom (gt, vt, 0.5, data.pos); }; "zoom out" = function (gt, vt, data) { gt.zoom (gt, vt, 2, data.pos); }; "zoom in slowly" = function (gt, vt, data) { gt.zoom (gt, vt, 0.9, data.pos); }; "zoom out slowly" = function (gt, vt, data) { gt.zoom (gt, vt, 1.1, data.pos); }; "scroll horizontally" = function (gt, vt, data) { vt.scrollmode = 'h'; }; "scroll vertically" = function (gt, vt, data) { vt.scrollmode = 'v'; }; "find node" = function (gt, vt, data) { gt.findnode (gt, vt); }; "print graph" = function (gt, vt, data) { gt.printorsave (gt, vt, null, null, null, null); }; "text view" = function (gt, vt, data) { if (dotty.txtview == 'on') dotty.txtview = 'off'; else dotty.txtview = 'on'; txtview (dotty.txtview); }; "quit" = function (gt, vt, data) { exit (); }; ]; dotty.protogt.actions.node = [ "cut" = function (gt, vt, obj, data) { gt.cut (gt, obj, 'one', 'support', 'cut'); dotty.clipgt.layoutgraph (dotty.clipgt); }; "Cut" = function (gt, vt, obj, data) { gt.cut (gt, obj, 'reachable', 'support', 'cut'); dotty.clipgt.layoutgraph (dotty.clipgt); }; "copy" = function (gt, vt, obj, data) { gt.cut (gt, obj, 'one', 'support', 'copy'); dotty.clipgt.layoutgraph (dotty.clipgt); }; "Copy" = function (gt, vt, obj, data) { gt.cut (gt, obj, 'reachable', 'support', 'copy'); dotty.clipgt.layoutgraph (dotty.clipgt); }; "group" = function (gt, vt, obj, data) { local kv; if ((kv = gt.getattr (gt, obj))) gt.groupnodesbyattr (gt, kv.key, kv.val, [ 'label' = kv.val; kv.key = kv.val; ], 1, 1); }; "Group" = function (gt, vt, obj, data) { local kv; if ((kv = gt.getattr (gt, obj))) gt.groupnodesbyattr (gt, kv.key, kv.val, [ 'label' = kv.val; kv.key = kv.val; ], 0, 1); }; "delete" = function (gt, vt, obj, data) { if (obj.eid >= 0) gt.removeedge (gt, obj); else gt.removenode (gt, obj); }; "Delete" = function (gt, vt, obj, data) { gt.removesubtree (gt, obj); }; "remove" = function (gt, vt, obj, data) { if (obj.nid >= 0) if ((kv = gt.getattr (gt, obj))) gt.removenodesbyattr (gt, kv.key, kv.val); }; "Remove" = function (gt, vt, obj, data) { if (obj.nid >= 0) if ((kv = gt.getattr (gt, obj))) gt.removesubtreesbyattr (gt, kv.key, kv.val); }; "set attr" = function (gt, vt, obj, data) { gt.setattr (gt, obj); }; "print attr" = function (gt, vt, obj, data) { if (obj.nid >= 0) echo ('node: ', obj.name); dump (obj.attr); }; ]; dotty.protogt.actions.edge = dotty.protogt.actions.node; dotty.protovt.normal.menus = [ 'general' = [ 0 = "undo"; 1 = "paste"; 2 = "do layout"; 3 = "cancel layout"; 4 = "redraw"; 5 = "new graph"; 6 = "load graph"; 7 = "reload graph"; 8 = "save graph"; 9 = "save graph as"; 10 = "open view"; 11 = "copy view"; 12 = "clone view"; 13 = "birdseye view"; 14 = "close view"; 15 = "set graph attr"; 16 = "set node attr"; 17 = "set edge attr"; 18 = "zoom in"; 19 = "zoom out"; 20 = "find node"; 21 = "print graph"; 22 = "text view"; 23 = "quit"; ]; 'node' = [ 0 = "cut"; 1 = "Cut"; 2 = "copy"; 3 = "Copy"; 4 = "group"; 5 = "Group"; 6 = "delete"; 7 = "Delete"; 8 = "remove"; 9 = "Remove"; 10 = "set attr"; 11 = "print attr"; ]; 'edge' = [ 0 = "cut"; 1 = "Cut"; 2 = "copy"; 3 = "Copy"; 4 = "delete"; 5 = "Delete"; 6 = "set attr"; 7 = "print attr"; ]; ]; dotty.protovt.normal.keys = [ 'general' = [ 'u' = "undo"; 'p' = "paste"; 'l' = "do layout"; 'k' = "cancel layout"; ' ' = "redraw"; 'L' = "reload graph"; 's' = "save graph"; 'Z' = "zoom in slowly"; 'z' = "zoom out slowly"; 'h' = "scroll horizontally"; 'v' = "scroll vertically"; ]; 'node' = [ 'c' = "copy"; 'C' = "Copy"; 'g' = "group"; 'G' = "Group"; 'd' = "delete"; 'D' = "Delete"; 'r' = "remove"; 'R' = "Remove"; 'a' = "set attr"; ]; 'edge' = [ 'c' = "copy"; 'C' = "Copy"; 'd' = "delete"; 'D' = "Delete"; 'a' = "set attr"; ]; ]; dotty.protovt.birdseye.menus = dotty.protovt.normal.menus; dotty.protovt.birdseye.keys = dotty.protovt.normal.keys; dotty.protovt.normal.uifuncs = [ 'leftdown' = function (data) { local gt; gt = dotty.graphs[dotty.views[data.widget].gtid]; if (data.obj.nid >= 0) { dotty.node2move = data.obj; dotty.movewidget = data.widget; dotty.rp2 = data.pos; } }; 'leftmove' = function (data) { local gt; gt = dotty.graphs[dotty.views[data.widget].gtid]; if (dotty.node2move & ( dotty.rp2.x ~= data.pos.x | dotty.rp2.y ~= data.pos.y )) { gt.movenode (gt, dotty.node2move, data.pos); dotty.rp2 = data.pos; } }; 'leftup' = function (data) { local gt; gt = dotty.graphs[dotty.views[data.widget].gtid]; if (dotty.node2move) { if (dotty.movewidget == data.widget) gt.movenode (gt, dotty.node2move, data.pos); dotty.node2move = 0; } else if (~data.obj) gt.insertnode (gt, data.pos, null, null, null, 1); }; 'middledown' = function (data) { if (~(data.obj.nid >= 0)) return; dotty.rubberband = 1; dotty.movewidget = data.widget; setgfxattr (data.widget, ['mode' = 'xor';]); dotty.rp1 = data.pos; dotty.rp2 = data.pos; line (data.widget, null, dotty.rp1, dotty.rp2, ['color' = 1;]); }; 'middlemove' = function (data) { if (dotty.rubberband ~= 1 | ( dotty.rp2.x == data.pos.x & dotty.rp2.y == data.pos.y )) return; line (data.widget, null, dotty.rp1, dotty.rp2, ['color' = 1;]); dotty.rp2 = data.pos; line (data.widget, null, dotty.rp1, dotty.rp2, ['color' = 1;]); }; 'middleup' = function (data) { local gt; gt = dotty.graphs[dotty.views[data.widget].gtid]; if (dotty.rubberband ~= 1) return; dotty.rubberband = 0; line (dotty.movewidget, null, dotty.rp1, dotty.rp2, ['color' = 1;]); setgfxattr (dotty.movewidget, ['mode' = 'src';]); if (dotty.movewidget ~= data.widget | ~( data.pobj.nid >= 0) | ~(data.obj.nid >= 0 )) return; if (data.pobj.attr.support) gt.groupnodes (gt, [ data.obj.nid = data.obj; data.pobj.nid = data.pobj; ], data.obj, null, null, null, 1, 1); else if (data.obj.attr.support) gt.groupnodes (gt, [ data.obj.nid = data.obj; data.pobj.nid = data.pobj; ], data.pobj, null, null, null, 1, 1); else gt.insertedge (gt, data.pobj, null, data.obj, null, null, 1); }; 'rightup' = function (data) { local vt, gt, menu, i; vt = dotty.views[data.widget]; gt = dotty.graphs[vt.gtid]; if (~data.obj) menu = vt.menus.general; else if (data.obj.nid >= 0) menu = vt.menus.node; else if (data.obj.eid >= 0) menu = vt.menus.edge; if ((i = displaymenu (data.widget, menu)) >= 0) gt.doaction (data, menu[i]); }; 'button3up' = function (data) { local vt, attr; vt = dotty.views[data.widget]; attr = getwidgetattr (vt.scroll, [0 = 'childcenter';]); if (vt.scrollmode == 'h') attr.childcenter.x = attr.childcenter.x - 40; else attr.childcenter.y = attr.childcenter.y - 40; setwidgetattr (vt.scroll, ['childcenter' = attr.childcenter;]); }; 'button4up' = function (data) { local vt, attr; vt = dotty.views[data.widget]; attr = getwidgetattr (vt.scroll, [0 = 'childcenter';]); if (vt.scrollmode == 'h') attr.childcenter.x = attr.childcenter.x + 40; else attr.childcenter.y = attr.childcenter.y + 40; setwidgetattr (vt.scroll, ['childcenter' = attr.childcenter;]); }; 'keyup' = function (data) { local vt, gt, action; vt = dotty.views[data.widget]; gt = dotty.graphs[vt.gtid]; if (data.obj.nid >= 0) { if (vt.keys.node[data.key]) action = vt.keys.node[data.key]; } else if (data.obj.eid >= 0) { if (vt.keys.edge[data.key]) action = vt.keys.edge[data.key]; } if (~action) if (vt.keys.general[data.key]) action = vt.keys.general[data.key]; if (action) gt.doaction (data, action); }; 'redraw' = function (data) { local vt, gt; vt = dotty.views[data.widget]; gt = dotty.graphs[vt.gtid]; gt.drawgraph (gt, [vt.vtid = vt;]); }; 'closeview' = function (data) { local vt, gt; vt = dotty.views[data.widget]; gt = dotty.graphs[vt.gtid]; gt.destroyview (gt, vt); if (tablesize (gt.views) == 0) gt.destroygraph (gt); }; ]; dotty.protovt.birdseye.uifuncs = [ 'leftdown' = function (data) { local gt, vid; gt = dotty.graphs[dotty.views[data.widget].gtid]; for (vid in gt.views) { vt = gt.views[vid]; if (vt.type ~= 'birdseye') gt.setviewcenter ([vid = vt;], data.pos); } }; 'leftmove' = function (data) { local gt, vid; gt = dotty.graphs[dotty.views[data.widget].gtid]; for (vid in gt.views) { vt = gt.views[vid]; if (vt.type ~= 'birdseye') gt.setviewcenter ([vid = vt;], data.pos); } }; 'leftup' = function (data) { local gt, vid; gt = dotty.graphs[dotty.views[data.widget].gtid]; for (vid in gt.views) { vt = gt.views[vid]; if (vt.type ~= 'birdseye') gt.setviewcenter ([vid = vt;], data.pos); } }; 'middledown' = dotty.protovt.normal.uifuncs.middledown; 'middlemove' = dotty.protovt.normal.uifuncs.middlemove; 'middleup' = dotty.protovt.normal.uifuncs.middleup; 'rightup' = dotty.protovt.normal.uifuncs.rightup; 'keyup' = dotty.protovt.normal.uifuncs.keyup; 'redraw' = dotty.protovt.normal.uifuncs.redraw; 'closeview' = dotty.protovt.normal.uifuncs.closeview; ]; dotty.monitorfile = function (data) { local gtid, gt, lpt; for (gtid in dotty.layoutpending) { lpt = dotty.layoutpending[gtid]; if (lpt.fd == data.fd) { gt = dotty.graphs[lpt.gtid]; gt.haveinput = 1; gt.layoutgraph (gt); return 1; } } return 0; }; PKu�\g�!� � lefty/fractal.leftynu�[���load ('def.lefty'); definit (); # # initialize window data # canvas = defcanvas; wrect = [0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 400; 'y' = 500;];]; setwidgetattr (canvas, ['window' = wrect;]); sq = function (x) { return x * x; }; # data structures # length = 300; center = ['x' = 200; 'y' = 250;]; radius = 2 * length / sqrt (12); fractalangle = 0; maxlevel = 2; # drawing functions # # draw a Koch curve (a ``snowflake'' fractal) # # start with a triangle and keep replacing edges # with the construct: _/\_ # until the recursion level reaches 'maxlevel' # fractal = function (level, length, angle) { local nlength, newpenpos; if (level >= maxlevel) { newpenpos.x = penpos.x + length * cos (angle); newpenpos.y = penpos.y + length * sin (angle); line (canvas, null, penpos, newpenpos, ['color' = 1;]); penpos = newpenpos; return; } nlength = length / 3; fractal (level + 1, nlength, angle); fractal (level + 1, nlength, angle + 60); fractal (level + 1, nlength, angle - 60); fractal (level + 1, nlength, angle); }; drawfractal = function () { clear (canvas); setpick (canvas, center, wrect); penpos = [ 'x' = center.x + cos (fractalangle + 210) * radius; 'y' = center.y + sin (fractalangle + 210) * radius; ]; fractal (0, length, fractalangle + 60); fractal (0, length, fractalangle - 60); fractal (0, length, fractalangle - 180); remove ('penpos'); }; # editing functions # # transform the fractal. # # map point 'prevpoint' to point 'currpoint' # with respect to the center of the fractal. # transformfractal = function (prevpoint, currpoint) { local prevtan, currtan, prevradius, currradius; prevtan = atan (prevpoint.y - center.y, prevpoint.x - center.x); currtan = atan (currpoint.y - center.y, currpoint.x - center.x); fractalangle = fractalangle + (currtan - prevtan); prevradius = sqrt ( sq (prevpoint.y - center.y) + sq (prevpoint.x - center.x) ); currradius = sqrt ( sq (currpoint.y - center.y) + sq (currpoint.x - center.x) ); radius = radius / prevradius * currradius; length = radius / 2 * sqrt (12); }; # user interface functions # # bind changes to the fractal to user actions # leftup = function (data) { transformfractal (data.ppos, data.pos); drawfractal (); }; dops = function () { local s; s = ['x' = 8 * 300; 'y' = 10.5 * 300;]; canvas = createwidget (-1, ['type' = 'ps'; 'size' = s;]); setwidgetattr (canvas, ['window' = wrect;]); drawfractal (); destroywidget (canvas); canvas=defcanvas; }; transformfractal (['x' = 0; 'y' = 0;], ['x' = 0; 'y' = 0;]); drawfractal (); PKu�\�3|�wwlefty/fractal2.leftynu�[���# # data structures # length = 300; center = ['x' = 200; 'y' = 250;]; radius = 2 * length / sqrt (12); fractalangle = 0; maxlevel = 2; sizes = [ 'button' = [ 'x' = 100; 'y' = 40; ]; 'canvas' = [ 'x' = 400; 'y' = 500; ]; 'view' = [ 'x' = 400; 'y' = 600; ]; ]; sq = function (x) { return x * x; }; # # create view and other widgets # init = function () { view = createwidget (-1, [ 'type' = 'view'; 'name' = 'fractal'; 'size' = sizes.view; ]); array1 = createwidget (view, [ 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'vertical'; ]); widgets[array1].resize = resize; array2 = createwidget (array1, [ 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'horizontal'; ]); widgets[array2].resize = resize; array3 = createwidget (array2, [ 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'vertical'; ]); widgets[array3].resize = resize; morebutton = createwidget (array3, [ 'type' = 'button'; 'text' = 'more'; ]); widgets[morebutton].pressed = pressed; lessbutton = createwidget (array3, [ 'type' = 'button'; 'text' = 'less'; ]); widgets[lessbutton].pressed = pressed; setwidgetattr (morebutton, ['size' = sizes.button;]); setwidgetattr (lessbutton, ['size' = sizes.button;]); atext = createwidget (array2, [ 'type' = 'text'; 'mode' = 'oneline'; ]); widgets[atext].oneline = oneline; setwidgetattr (atext, [ 'size' = ['x' = sizes.button.x; 'y' = sizes.button.y * 2;]; ]); scroll = createwidget (array1, ['type' = 'scroll';]); canvas = createwidget (scroll, ['type' = 'canvas';]); wrect = [0 = ['x' = 0; 'y' = 0;]; 1 = sizes.canvas;]; setwidgetattr (canvas, ['window' = wrect; 'viewport' = wrect[1];]); }; # # drawing functions # # draw a Koch curve (a ``snowflake'' fractal) # # start with a triangle and keep replacing edges # with the construct: _/\_ # until the recursion level reaches 'maxlevel' # fractal = function (level, length, angle) { local nlength, newpenpos; if (level >= maxlevel) { newpenpos.x = penpos.x + length * cos (angle); newpenpos.y = penpos.y + length * sin (angle); line (canvas, null, penpos, newpenpos, ['color' = 1;]); penpos = newpenpos; return; } nlength = length / 3; fractal (level + 1, nlength, angle); fractal (level + 1, nlength, angle + 60); fractal (level + 1, nlength, angle - 60); fractal (level + 1, nlength, angle); }; redrawfractal = function () { clear (canvas); setpick (canvas, center, wrect); penpos = [ 'x' = center.x + cos (fractalangle + 210) * radius; 'y' = center.y + sin (fractalangle + 210) * radius; ]; fractal (0, length, fractalangle + 60); fractal (0, length, fractalangle - 60); fractal (0, length, fractalangle - 180); remove ('penpos'); }; # # editing functions # # transform the fractal. # # map point 'prevpoint' to point 'currpoint' # with respect to the center of the fractal. # transformfractal = function (prevpoint, currpoint) { local prevtan, currtan, prevradius, currradius; prevtan = atan (prevpoint.y - center.y, prevpoint.x - center.x); currtan = atan (currpoint.y - center.y, currpoint.x - center.x); fractalangle = fractalangle + (currtan - prevtan); prevradius = sqrt ( sq (prevpoint.y - center.y) + sq (prevpoint.x - center.x) ); currradius = sqrt ( sq (currpoint.y - center.y) + sq (currpoint.x - center.x) ); radius = radius / prevradius * currradius; length = radius / 2 * sqrt (12); }; # # main actions # redraw = function (data) { redrawfractal (); }; changemaxlevel = function (dn) { maxlevel = maxlevel + dn; if (maxlevel < 0) maxlevel = 0; redrawfractal (); }; resize = function (data) { local ret; if (data.widget == array1) { ret = [ array2 = [ 'x' = data.size.x; 'y' = sizes.button.y * 2; ]; scroll = [ 'x' = data.size.x; 'y' = data.size.y - sizes.button.y * 2; ]; ]; } else if (data.widget == array2) { ret = [ array3 = [ 'x' = sizes.button.x; 'y' = 2 * sizes.button.y; ]; atext = [ 'x' = data.size.x - sizes.button.x; 'y' = 2 * sizes.button.y; ]; ]; } else if (data.widget == array3) { ret = [ morebutton = sizes.button; lessbutton = sizes.button; ]; } return ret; }; # # user interface functions # # bind changes to the fractal to user actions # leftup = function (data) { transformfractal (data.ppos, data.pos); redrawfractal (); }; menu = [ 0 = 'more'; 1 = 'less'; ]; domenu = function (i) { local s; s = menu[i]; if (s == 'more') changemaxlevel (1); else if (s == 'less') changemaxlevel (-1); }; rightdown = function (data) { domenu (displaymenu (canvas, menu)); }; pressed = function (data) { if (data.widget == morebutton) changemaxlevel (1); else if (data.widget == lessbutton) changemaxlevel (-1); }; oneline = function (data) { local dn; dn = ston (data.text); if (dn > 0 | dn < 0) changemaxlevel (dn - maxlevel); }; # # postscript generation # dops = function () { local r; r = [0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 8 * 300; 'y' = 10.5 * 300;];]; canvas = opencanvas ('pscanvas', '', r); setwidgetattr (canvas, ['window' = wrect;]); redraw (); closecanvas (canvas); canvas=defcanvas; }; init (); #txtview ('off'); PKu�\�n�?w w lefty/lefty.pspnu�[���/BOX { /boxy1 exch def /boxx1 exch def /boxy0 exch def /boxx0 exch def boxx0 boxy0 moveto boxx1 boxy0 lineto boxx1 boxy1 lineto boxx0 boxy1 lineto closepath } def /SCP { stroke initclip newpath BOX clip newpath } def /CL { stroke setrgbcolor } def /DO { stroke } def /NP { newpath } def /FI { fill } def /LI { moveto lineto } def /CT { curveto } def /AR { /ang2 exch def /ang1 exch def /radius exch def /y2x exch def /cy exch def /cx exch def gsave cx cy translate 1 y2x scale 0 0 radius ang1 ang2 arc stroke grestore } def /ARF { /ang2 exch def /ang1 exch def /radius exch def /y2x exch def /cy exch def /cx exch def gsave cx cy translate 1 y2x scale 0 0 radius ang1 ang2 arc fill grestore } def /TXT { /texth exch def /textf exch def /textn exch def /texts exch def /textyj exch def /texty exch def /textxj exch def /textx exch def textf findfont texth scalefont dup setfont /FontBBox get 1 get 1000 div texth mul /textbl exch def /textth texth textn mul def /texttw 0 def 0 1 textn 1 sub { texts exch get 0 get stringwidth pop dup texttw gt { /texttw exch def } { pop } ifelse } for textyj (b) eq { /ty texty textth add textbl add def } if textyj (d) eq { /ty texty textth add def } if textyj (c) eq { /ty texty textth 2 div add def } if textyj (u) eq { /ty texty def } if /ty ty textbl sub def textxj (l) eq { /tx textx def } if textxj (c) eq { /tx textx texttw 2 div sub def } if textxj (r) eq { /tx textx texttw sub def } if 0 1 textn 1 sub { /ty ty texth sub def texts exch get dup 0 get /ts exch def 1 get /tj exch def tj (l) eq { tx ty moveto ts show } if tj (n) eq { tx texttw ts stringwidth pop sub 2 div add ty moveto ts show } if tj (r) eq { tx texttw ts stringwidth pop sub add ty moveto ts show } if } for } def /colorimage where { pop } { /bwproc { rgbproc dup length 3 idiv string 0 3 0 5 -1 roll { add 2 1 roll 1 sub dup 0 eq { pop 3 idiv 3 -1 roll dup 4 -1 roll dup 3 1 roll 5 -1 roll put 1 add 3 0 } { 2 1 roll } ifelse } forall pop pop pop } def /colorimage { pop pop /rgbproc exch def {bwproc} image } bind def } ifelse PKu�\=�~~lefty/slides.leftynu�[���load ('def.lefty'); definit (); # # initialize window data # canvas = defcanvas; wrect = [0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 800; 'y' = 1000;];]; lmargin = 100; width = 800; height = 1000; setwidgetattr (canvas, ['window' = wrect;]); fonts = [ 'timr' = [ 14 = 'timr14'; 18 = 'timr18'; 24 = 'timr24'; ]; 'courr' = [ 14 = 'courr14'; 18 = 'courr18'; 24 = 'courr24'; ]; ]; x2ps = [ 'timr24' = 'Times-Roman'; 'timr18' = 'Times-Roman'; 'timr14' = 'Times-Roman'; 'courr24' = 'Courier'; 'courr18' = 'Courier'; 'courr14' = 'Courier'; ]; calc = function () { local i, j, cpos, tsiz, dist, slidep; tsiz = ['x' = 0; 'y' = 0;]; for (i = 0; slides[i]; i = i + 1) { slidep = slides[i]; if (slidep.skip) { tsiz.y = tsiz.y + slidep.skip; } else { for (j = 0; slidep.text[j]; j = j + 1) { if (j > 0) tsiz.y = tsiz.y + 5; if (~slidep.font) slidep.font = slides.font; if (~slidep.size) slidep.size = slides.size; if (~slidep.just) slidep.just = slides.just; slidep.tsiz[j] = textsize (canvas, slidep.text[j], fonts[slidep.font][slidep.size], 0); tsiz.y = tsiz.y + slidep.tsiz[j].y; } } } dist = (height - tsiz.y) / (i + 1); cpos = ['x' = lmargin; 'y' = height - dist;]; for (i = 0; slides[i]; i = i + 1) { slidep = slides[i]; if (slidep.skip) { cpos.y = cpos.y - slidep.skip - dist; } else { for (j = 0; slidep.text[j]; j = j + 1) { if (j > 0) cpos.y = cpos.y - 5; if (slidep.just == 0) slidep.tpos[j].x = cpos.x; else slidep.tpos[j].x = width / 2; cpos.y = cpos.y - slidep.tsiz[j].y; slidep.tpos[j].y = cpos.y; } cpos.y = cpos.y - dist; } } }; redraw = function () { local i, j, slidep; for (i = 0; slides[i]; i = i + 1) { slidep = slides[i]; if (~slidep.skip) for (j = 0; slidep.text[j]; j = j + 1) text (canvas, slidep, slidep.tpos[j], slidep.text[j], fonts[slidep.font][slidep.size], 0, slidep.just); } }; dops = function () { local i, j, slidep, r; r = [0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 8 * 300; 'y' = 10.5 * 300;];]; canvas = createwidget (-1, ['type' = 'ps'; 'origin' = r[0]; 'size' = r[1] ;]); setwidgetattr (canvas, ['window' = wrect;]); for (i = 0; slides[i]; i = i + 1) { slidep = slides[i]; if (~slidep.skip) for (j = 0; slidep.text[j]; j = j + 1) text (canvas, slidep, slidep.tpos[j], slidep.text[j], x2ps[fonts[slidep.font][slidep.size]], slidep.tsiz[j].y, slidep.just, 1); } destroywidget (canvas); canvas=defcanvas; }; doit = function () { calc (); redraw (); dops (); }; PKu�\�X_��lefty/tree.leftynu�[���load ('def.lefty'); definit (); # # initialize window data # canvas = defcanvas; wrect = [0 = ['x' = -5; 'y' = 0;]; 1 = ['x' = 410; 'y' = 500;];]; setwidgetattr (canvas, ['window' = wrect;]); # # data structures # nodearray = []; nodenum = 0; dist = ['x' = 40; 'y' = 40;]; defsize = ['x' = 10; 'y' = 10;]; fontname = 'fixed'; fontsize = 18; tree = null; # drawing functions # boxnode = function (node) { local center; box (canvas, node, node.rect, ['color' = 0; 'fill' = 'on';]); box (canvas, node, node.rect); center = [ 'x' = (node.rect[0].x + node.rect[1].x) / 2; 'y' = (node.rect[0].y + node.rect[1].y) / 2; ]; if (node.name) text (canvas, node, center, node.name, fontname, fontsize, 'cc'); }; circlenode = function (node) { local center, radius; center = [ 'x' = (node.rect[0].x + node.rect[1].x) / 2; 'y' = (node.rect[0].y + node.rect[1].y) / 2; ]; radius = [ 'x' = center.x - node.rect[0].x; 'y' = center.y - node.rect[0].y; ]; arc (canvas, node, center, radius, ['color' = 0; 'fill' = 'on';]); arc (canvas, node, center, radius); if (node.name) text (canvas, node, center, node.name, fontname, fontsize, 'cc'); }; drawnode = boxnode; drawedge = function (node1, node2) { line (canvas, null, [ 'x' = (node1.rect[1].x + node1.rect[0].x) / 2; 'y' = node1.rect[0].y; ], [ 'x' = (node2.rect[1].x + node2.rect[0].x) / 2; 'y' = node2.rect[1].y; ]); }; drawtree = function (node) { local i; for (i in nodearray) drawnode (nodearray[i]); drawtreerec (node); }; drawtreerec = function (node) { local i, n; if ((n = tablesize (node.ch)) > 0) { for (i = 0; i < n; i = i + 1) { drawedge (node, node.ch[i]); drawtreerec (node.ch[i]); } } }; redraw = function (c) { if (tree) drawtree (tree); }; # layout functions # complayout = function () { leafx = 0; leafrank = 0; dolayout (tree, wrect[1].y - 10); remove ('leafx'); remove ('leafrank'); }; dolayout = function (node, pary) { local r, n, i, size, lchp, rchp; size = nodesize (node); if (node.chn > 0) { for (i = 0; i < node.chn; i = i + 1) dolayout (node.ch[i], pary - size.y - dist.y); node.rank = (node.ch[0].rank + node.ch[node.chn - 1].rank) / 2; lchp = node.ch[0].rect; rchp = node.ch[node.chn - 1].rect; r[0].x = lchp[0].x + ((rchp[1].x - lchp[0].x) - size.x) / 2; r[0].y = pary - size.y; r[1].x = r[0].x + size.x; r[1].y = pary; node.rect = r; } else { node.rank = leafrank; r[0].x = leafx; r[0].y = pary - size.y; r[1].x = r[0].x + size.x; r[1].y = pary; leafrank = leafrank + 1; leafx = r[1].x + dist.x; node.rect = r; } }; # editing functions # inode = function (point, name) { local i, nnum, size; nnum = nodenum; if (~name) name = ask ('give name of node:'); nodearray[nnum].ch = []; nodearray[nnum].chn = 0; nodearray[nnum].name = name; size = nodesize (nodearray[nnum]); nodearray[nnum].rect[0] = point; nodearray[nnum].rect[1] = ['x' = point.x + size.x; 'y' = point.y + size.y;]; nodenum = nodenum + 1; if (~tree) { tree = nodearray[nnum]; tree.depth = 0; complayout (); drawtree (tree); } else drawtree (nodearray[nnum]); return nodearray[nnum]; }; iedge = function (node1, node2) { node1.ch[node1.chn] = node2; node1.chn = node1.chn + 1; node2.depth = node1.depth + 1; complayout (); clear (canvas); drawtree (tree); }; fix = function (node, op, np) { if (node.depth ~= 0) dist.y = dist.y + (op.y - np.y) / node.depth; if (node.rank ~= 0) dist.x = dist.x + (np.x - op.x) / node.rank; complayout (); clear (canvas); drawtree (tree); }; nodesize = function (node) { local siz; if (~(siz = textsize (canvas, node.name, fontname, fontsize))) siz = defsize; else { siz.x = siz.x + 8; siz.y = siz.y + 8; } return siz; }; changenode = function (nodestyle) { drawnode = nodestyle; clear (canvas); drawtree (tree); }; # user interface functions # leftdown = function (data) { if (~data.obj) inode (data.pos, null); }; leftup = function (data) { if (data.pobj) fix (data.pobj, data.ppos, data.pos); }; middleup = function (data) { if (data.pobj & data.obj) iedge (data.pobj, data.obj); }; dops = function () { local s; s = ['x' = 8 * 300; 'y' = 10.5 * 300;]; fontname = 'Times-Roman'; canvas = createwidget (-1, ['type' = 'ps'; 'size' = s;]); setwidgetattr (canvas, ['window' = wrect;]); drawtree (tree); destroywidget (canvas); canvas=defcanvas; fontname = 'fixed'; }; PKu�\�� �## gvpr/addedgesnu�[���PKu�\�#0 >> `gvpr/addranksnu�[���PKu�\�D�'' �gvpr/addringsnu�[���PKu�\���Ϧ� ? gvpr/anonnu�[���PKu�\��� gvpr/attrnu�[���PKu�\�h���gvpr/bbnu�[���PKu�\�� gvpr/bboxnu�[���PKu�\Xoy��Wgvpr/binducenu�[���PKu�\[����!gvpr/bipartnu�[���PKu�\#K��#gvpr/chkclustersnu�[���PKu�\�|���� wgvpr/chkedgesnu�[���PKu�\W/���� H gvpr/cliptreenu�[���PKu�\w�k`YY7!gvpr/colnu�[���PKu�\_zm8�� �#gvpr/collapsenu�[���PKu�\/?%��� �%gvpr/colornu�[���PKu�\Xv��00 �+gvpr/cyclenu�[���PKu�\�W��.gvpr/dechainnu�[���PKu�\u��__b/gvpr/deghistnu�[���PKu�\�a��tt �0gvpr/deledgesnu�[���PKu�\*TU��� �1gvpr/delmultinu�[���PKu�\�(���� x3gvpr/delnodesnu�[���PKu�\�߀N##�4gvpr/depathnu�[���PKu�\��E �� 7gvpr/dijkstranu�[���PKu�\���XX�9gvpr/flattennu�[���PKu�\-f�d:gvpr/get-layers-listnu�[���PKu�\�+�{ �;gvpr/groupnu�[���PKu�\�{�N???gvpr/histogramnu�[���PKu�\k��Qzz�@gvpr/indentnu�[���PKu�\������ @Bgvpr/knbhdnu�[���PKu�\.<��33DGgvpr/maxdegnu�[���PKu�\��v�� �Hgvpr/pathnu�[���PKu�\2w����Jgvpr/rotatenu�[���PKu�\�`�{{ �Ogvpr/scalenu�[���PKu�\\�r�ccFTgvpr/scalexynu�[���PKu�\V$ ��� �Xgvpr/spannu�[���PKu�\�M�c�� �Ygvpr/toponnu�[���PKu�\v Q����[gvpr/treetoclustnu�[���PKu�\�q8��_lefty/box.leftynu�[���PKu�\`�Iw��nlefty/def.leftynu�[���PKu�\*<��Y�Yplefty/dotty.leftynu�[���PKu�\̨�^�M�MO�lefty/dotty_draw.leftynu�[���PKu�\�!ϼ~F~Flefty/dotty_edit.leftynu�[���PKu�\L�8�8C_lefty/dotty_layout.leftynu�[���PKu�\��7�7u�lefty/dotty_ui.leftynu�[���PKu�\g�!� � ;�lefty/fractal.leftynu�[���PKu�\�3|�ww�lefty/fractal2.leftynu�[���PKu�\�n�?w w ��lefty/lefty.pspnu�[���PKu�\=�~~��lefty/slides.leftynu�[���PKu�\�X_��Klefty/tree.leftynu�[���PK11�!
/home/emeraadmin/www/Classes/../node_modules/jquery/../object.map/../../4d695/graphviz.zip