2
# dotty_layout: layout functions and data structures
4
dotty.grablserver = function (lserver) {
7
if (~dotty.lservers[lserver] | tablesize (dotty.lservers[lserver]) == 0) {
8
if (~((fd = openio ('pipe', lserver, 'r+')) >= 0)) {
9
dotty.message (0, concat ('cannot start ', lserver));
12
dotty.lservers[lserver][fd] = [
17
for (fd in dotty.lservers[lserver]) {
18
dotty.lservers[lserver][fd].count =
19
dotty.lservers[lserver][fd].count + 1;
20
dotty.lservers.inuse[fd] = dotty.lservers[lserver][fd];
21
remove (fd, dotty.lservers[lserver]);
25
dotty.releaselserver = function (lserver, fd, state) {
26
if (state == 'bad' | dotty.lservers.inuse[fd].count > 40) {
28
remove (fd, dotty.lservers.inuse);
31
dotty.lservers[lserver][fd] = dotty.lservers.inuse[fd];
32
remove (fd, dotty.lservers.inuse);
34
dotty.protogt.startlayout = function (gt) {
37
if (gt.layoutpending >= 1) {
38
lpt = dotty.layoutpending[gt.gtid];
39
if (gt.layoutmode == 'async')
40
monitor ('off', lpt.fd);
41
dotty.releaselserver (gt.lserver, lpt.fd, 'bad');
42
remove (gt.gtid, dotty.layoutpending);
45
dotty.popbusy (gt, gt.views);
47
if (~((fd = dotty.grablserver (gt.lserver)) >= 0))
49
dotty.pushbusy (gt, gt.views);
50
writegraph (fd, gt.graph, 1);
52
dotty.layoutpending[gt.gtid] = [
56
if (gt.layoutmode == 'async')
60
dotty.protogt.finishlayout = function (gt) {
63
if (~(gt.layoutpending >= 1)) {
64
dotty.message (0, concat ('no layout pending for graph ', gt.gtid));
67
lpt = dotty.layoutpending[gt.gtid];
68
if (~(graph = readgraph (lpt.fd))) {
69
if (gt.layoutmode == 'async')
70
monitor ('off', lpt.fd);
71
dotty.releaselserver (gt.lserver, lpt.fd, 'bad');
72
if (gt.layoutpending == 2) {
73
dotty.message (0, concat ('giving up on ', gt.lserver));
74
if ((fd = openio ('file', 'dottybug.dot', 'w+')) >= 0) {
75
writegraph (fd, gt.graph, 0);
78
concat ('graph that causes ', gt.lserver));
80
'to fail has been saved in file dottybug.dot');
82
'please forward this file to ek@research.att.com');
84
dotty.popbusy (gt, gt.views);
90
concat ('lost connection to ', gt.lserver, ', restarting...'));
91
lpt.fd = dotty.grablserver (gt.lserver);
92
writegraph (lpt.fd, gt.graph, 1);
93
if (gt.layoutmode == 'async')
94
monitor ('on', lpt.fd);
99
if (gt.layoutmode == 'async')
100
monitor ('off', lpt.fd);
101
dotty.releaselserver (gt.lserver, lpt.fd, null);
102
remove (gt.gtid, dotty.layoutpending);
103
gt.layoutpending = 0;
105
gt.unpacklayout (gt, graph);
106
dotty.popbusy (gt, gt.views);
109
dotty.protogt.cancellayout = function (gt) {
112
if (gt.layoutpending >= 1) {
113
lpt = dotty.layoutpending[gt.gtid];
114
if (gt.layoutmode == 'async')
115
monitor ('off', lpt.fd);
116
dotty.releaselserver (gt.lserver, lpt.fd, 'bad');
117
remove (gt.gtid, dotty.layoutpending);
118
gt.layoutpending = 0;
120
dotty.popbusy (gt, gt.views);
123
dotty.protogt.unpacklayout = function (gt, graph2) {
124
local graph, gid, sgraph1, sgraph2, nid, node1, node2;
125
local t1, t2, t3, n2, i, j, k, l, m, eid, edge1, edge2, points;
126
local pa1, pa2, pb1, pb2, la, lb;
129
for (gid in graph2.graphdict) {
130
if (~(sgraph1 = graph.graphs[graph.graphdict[gid]]))
132
sgraph2 = graph2.graphs[graph2.graphdict[gid]];
133
if (sgraph2.graphattr.bb & sgraph2.graphattr.bb ~= '') {
134
t1 = split (sgraph2.graphattr.bb, ',');
136
0 = ['x' = ston (t1[0]); 'y' = ston (t1[1]);];
137
1 = ['x' = ston (t1[2]); 'y' = ston (t1[3]);];
141
if (sgraph2.graphattr.lp & sgraph2.graphattr.lp ~= '') {
142
t1 = split (sgraph2.graphattr.lp, ',');
143
sgraph1.lp = ['x' = ston (t1[0]); 'y' = ston (t1[1]);];
147
for (nid in graph2.nodedict) {
148
if (~(node1 = graph.nodes[graph.nodedict[nid]]))
150
node2 = graph2.nodes[graph2.nodedict[nid]];
151
t1 = split (node2.attr.pos, ',');
152
node1.pos = ['x' = ston (t1[0]); 'y' = ston (t1[1]);];
153
node1.size.x = ston (node2.attr.width) * 72;
154
node1.size.y = ston (node2.attr.height) * 72;
155
if (node2.attr.rects)
156
node1.fields = parsegraphlabel (node2.attr.label, node2.attr.rects);
158
for (eid in graph2.edges) {
159
edge2 = graph2.edges[eid];
161
if (~(edge1 = graph.edges[ston (edge2.attr.id)]))
163
} else if (graph == graph2)
165
if (edge2.attr.pos) {
167
remove ('sp', edge1);
168
remove ('ep', edge1);
169
t2 = split (edge2.attr.pos, ';');
170
for (k = 0; t2[k]; k = k + 1) {
171
t3 = split (t2[k], ' ');
175
t1 = split (t3[0], ',');
176
while (t1[0] == 's' | t1[0] == 'e') {
178
edge1.sp = ['x' = ston (t1[1]); 'y' = ston (t1[2]);];
179
else # (t1[0] == 'e')
180
edge1.ep = ['x' = ston (t1[1]); 'y' = ston (t1[2]);];
182
t1 = split (t3[i], ',');
184
points[k][j] = ['x' = ston (t1[0]); 'y' = ston (t1[1]);];
188
t1 = split (t3[i], ',');
189
points[k][j] = ['x' = ston (t1[0]); 'y' = ston (t1[1]);];
194
if (k > 1) { # concentrators
197
la = tablesize (points[0]);
199
pa2 = points[0][la - 1];
200
for (k = 1; points[k]; k = k + 1) {
201
lb = tablesize (points[k]);
203
pb2 = points[k][lb - 1];
204
if (pa1.x == pb2.x & pa1.y == pb2.y) {
205
for (m = 1; m < la; m = m + 1) {
206
points[k][lb] = points[0][m];
209
points[0] = points[l - 1];
210
remove (l - 1, points);
212
} else if (pa2.x == pb1.x & pa2.y == pb1.y) {
213
for (m = 1; m < lb; m = m + 1) {
214
points[0][la] = points[k][m];
217
points[k] = points[l - 1];
218
remove (l - 1, points);
223
dotty.message (1, 'failed to match edge points');
229
edge1.points = points[0];
232
t1 = split (edge2.attr.lp, ',');
233
edge1.lp = ['x' = ston (t1[0]); 'y' = ston (t1[1]);];
236
t1 = split (graph2.graphattr.bb, ',');
237
graph.rect[0].x = ston (t1[0]);
238
graph.rect[0].y = ston (t1[1]);
239
graph.rect[1].x = ston (t1[2]);
240
graph.rect[1].y = ston (t1[3]);
241
if (graph2.graphattr.lp & graph2.graphattr.lp ~= '') {
242
t1 = split (graph2.graphattr.lp, ',');
243
graph.lp = ['x' = ston (t1[0]); 'y' = ston (t1[1]);];
246
if (gt.graph ~= graph2)
248
# strip position and size info from the attributes
249
for (gid in graph2.graphdict) {
250
sgraph2 = graph2.graphs[graph2.graphdict[gid]];
251
if (sgraph2.graphattr.bb)
252
remove ('bb', sgraph2.graphattr);
254
for (nid in graph2.nodedict) {
255
node2 = graph2.nodes[graph2.nodedict[nid]];
256
if (node2.attr.rects)
257
remove ('rects', node2.attr);
258
remove ('pos', node2.attr);
259
remove ('width', node2.attr);
260
remove ('height', node2.attr);
262
for (eid in graph2.edges) {
263
edge2 = graph2.edges[eid];
265
remove ('pos', edge2.attr);
267
remove ('lp', edge2.attr);
269
remove ('bb', graph2.graphattr);
270
if (graph2.graphattr.lp)
271
remove ('lp', graph2.graphattr);