Mini Shell
#
# 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;
};
Zerion Mini Shell 1.0