~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to dotty/dotty_edit.lefty

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# dotty_edit: editing functions and data structures
 
3
#
 
4
dotty.protogt.getnodesbyattr = function (gt, key, val) {
 
5
    local nid, node, nlist;
 
6
 
 
7
    nlist = [];
 
8
    for (nid in gt.graph.nodes) {
 
9
        node = gt.graph.nodes[nid];
 
10
        if (node.attr[key] == val)
 
11
            nlist[nid] = node;
 
12
    }
 
13
    return nlist;
 
14
};
 
15
dotty.protogt.reachablenodes = function (gt, node) {
 
16
    local nlist, stack, eid, edge, i;
 
17
 
 
18
    stack[0] = node;
 
19
    i = 1;
 
20
    while (i > 0) {
 
21
        node = stack[i - 1];
 
22
        i = i - 1;
 
23
        nlist[node.nid] = node;
 
24
        for (eid in node.edges) {
 
25
            edge = node.edges[eid];
 
26
            if (~nlist[edge.head.nid]) {
 
27
                nlist[edge.head.nid] = edge.head;
 
28
                stack[i] = edge.head;
 
29
                i = i + 1;
 
30
            }
 
31
        }
 
32
    }
 
33
    return nlist;
 
34
};
 
35
dotty.protogt.mergegraph = function (gt, graph, show) {
 
36
    local nameid, onode, pos, size, eid, eid2, tnode, hnode, oedge;
 
37
 
 
38
    if (~gt.noundo)
 
39
        gt.startadd2undo (gt);
 
40
    for (nameid in graph.nodedict) {
 
41
        pos = null;
 
42
        size = null;
 
43
        onode = graph.nodes[graph.nodedict[nameid]];
 
44
        if (onode.pos)
 
45
            pos = node.pos;
 
46
        if (onode.size)
 
47
            size = node.size;
 
48
        if (~(gt.graph.nodedict[nameid] >= 0)) {
 
49
            pos = null;
 
50
            size = null;
 
51
            if (onode.pos)
 
52
                pos = node.pos;
 
53
            if (onode.size)
 
54
                size = node.size;
 
55
            gt.insertnode (gt, pos, size, nameid, onode.attr, show);
 
56
        }
 
57
    }
 
58
    for (eid in graph.edges) {
 
59
        oedge = graph.edges[eid];
 
60
        tnode = gt.graph.nodes[gt.graph.nodedict[oedge.tail.name]];
 
61
        hnode = gt.graph.nodes[gt.graph.nodedict[oedge.head.name]];
 
62
        for (eid2 in tnode.edges)
 
63
            if (tnode.edges[eid2].tail == tnode &
 
64
                    tnode.edges[eid2].head == hnode) {
 
65
                oedge = null;
 
66
                break;
 
67
            }
 
68
        if (oedge)
 
69
            gt.insertedge (gt, tnode, null, hnode, null, oedge.attr, show);
 
70
    }
 
71
    if (~gt.noundo)
 
72
        gt.endadd2undo (gt);
 
73
};
 
74
dotty.protogt.insertsgraph = function (gt, name, attr, show) {
 
75
    local gid, sgraph, aid;
 
76
 
 
77
    if (~gt)
 
78
        return null;
 
79
    gid = gt.graph.maxgid;
 
80
    if (~name) {
 
81
        while (gt.graph.graphdict[(name = concat ('g', gid))] >= 0)
 
82
            gid = gid + 1;
 
83
    } else if (gt.graph.graphdict[name]) {
 
84
        dotty.message (0, concat ('graph: ', name, ' exists'));
 
85
        return null;
 
86
    }
 
87
    gt.graph.graphdict[name] = gid;
 
88
    gt.graph.maxgid = gid + 1;
 
89
    gt.graph.graphs[gid] = [
 
90
        dotty.keys.gid   = gid;
 
91
        dotty.keys.name  = name;
 
92
        dotty.keys.gattr = copy (gt.graph.graphattr);
 
93
        dotty.keys.nattr = copy (gt.graph.nodeattr);
 
94
        dotty.keys.eattr = copy (gt.graph.edgeattr);
 
95
    ];
 
96
    sgraph = gt.graph.graphs[gid];
 
97
    if (~attr)
 
98
        attr = [];
 
99
    if (~attr.label)
 
100
        attr.label = '\N';
 
101
    for (aid in attr)
 
102
        sgraph.graphattr[aid] = attr[aid];
 
103
    gt.unpacksgraphattr (gt, sgraph);
 
104
    if (show)
 
105
        gt.drawsgraph (gt, gt.views, sgraph);
 
106
    return sgraph;
 
107
};
 
108
dotty.protogt.removesgraph = function (gt, sgraph) {
 
109
    gt.undrawsgraph (gt, gt.views, sgraph);
 
110
    remove (sgraph.name, gt.graph.graphdict);
 
111
    remove (sgraph.gid, gt.graph.graphs);
 
112
};
 
113
dotty.protogt.insertnode = function (gt, pos, size, name, attr, show) {
 
114
    local nid, node, aid;
 
115
 
 
116
    nid = gt.graph.maxnid;
 
117
    if (~name) {
 
118
        while (gt.graph.nodedict[(name = concat ('n', nid))] >= 0)
 
119
            nid = nid + 1;
 
120
    } else if (gt.graph.nodedict[name] >= 0) {
 
121
        dotty.message (0, concat ('node: ', name, ' exists'));
 
122
        return null;
 
123
    }
 
124
    gt.graph.nodedict[name] = nid;
 
125
    gt.graph.maxnid = nid + 1;
 
126
    gt.graph.nodes[nid] = [
 
127
        dotty.keys.nid   = nid;
 
128
        dotty.keys.name  = name;
 
129
        dotty.keys.attr  = copy (gt.graph.nodeattr);
 
130
        dotty.keys.edges = [];
 
131
    ];
 
132
    node = gt.graph.nodes[nid];
 
133
    if (~attr)
 
134
        attr = [];
 
135
    if (~attr.label)
 
136
        attr.label = '\N';
 
137
    for (aid in attr)
 
138
        node.attr[aid] = attr[aid];
 
139
    gt.unpacknodeattr (gt, node);
 
140
    if (~pos)
 
141
        pos = ['x' = 10; 'y' = 10;];
 
142
    node[dotty.keys.pos] = copy (pos);
 
143
    if (~size)
 
144
        size = ['x' = strlen (attr.label) * 30; 'y' = 30;];
 
145
    if (size.x == 0)
 
146
        size.x = 30;
 
147
    node[dotty.keys.size] = copy (size);
 
148
    if (show)
 
149
        gt.drawnode (gt, gt.views, node);
 
150
    if (~gt.noundo) {
 
151
        gt.startadd2undo (gt);
 
152
        gt.currundo.inserted.nodes[nid] = node;
 
153
        gt.endadd2undo (gt);
 
154
    }
 
155
    return node;
 
156
};
 
157
dotty.protogt.removenode = function (gt, node) {
 
158
    local eid, list, edge, gid;
 
159
 
 
160
    if (~gt.noundo)
 
161
        gt.startadd2undo (gt);
 
162
    for (eid in node.edges)
 
163
        list[eid] = node.edges[eid];
 
164
    for (eid in list)
 
165
        gt.removeedge (gt, list[eid]);
 
166
    gt.undrawnode (gt, gt.views, node);
 
167
    for (gid in gt.graph.graphs)
 
168
        remove (node.nid, gt.graph.graphs[gid].nodes);
 
169
    remove (node.name, gt.graph.nodedict);
 
170
    remove (node.nid, gt.graph.nodes);
 
171
    if (~gt.noundo) {
 
172
        gt.currundo.deleted.nodes[node.nid] = node;
 
173
        gt.endadd2undo (gt);
 
174
    }
 
175
};
 
176
dotty.protogt.insertedge =
 
177
        function (gt, nodea, porta, nodeb, portb, attr, show) {
 
178
    local eid, edge, aid, tport, hport;
 
179
 
 
180
    if (~nodea | ~nodeb)
 
181
        return null;
 
182
    if (porta)
 
183
        tport = porta;
 
184
    if (portb)
 
185
        hport = portb;
 
186
    eid = gt.graph.maxeid;
 
187
    while (gt.graph.edges[eid])
 
188
        eid = eid + 1;
 
189
    gt.graph.maxeid = eid + 1;
 
190
    gt.graph.edges[eid] = [
 
191
        dotty.keys.eid   = eid;
 
192
        dotty.keys.tail  = nodea;
 
193
        dotty.keys.tport = porta;
 
194
        dotty.keys.head  = nodeb;
 
195
        dotty.keys.hport = portb;
 
196
        dotty.keys.attr  = copy (gt.graph.edgeattr);
 
197
    ];
 
198
    edge = gt.graph.edges[eid];
 
199
    if (~attr)
 
200
        attr = [];
 
201
    for (aid in attr)
 
202
        edge.attr[aid] = attr[aid];
 
203
    nodea.edges[eid] = edge;
 
204
    nodeb.edges[eid] = edge;
 
205
    edge[dotty.keys.points] = [
 
206
        0 = copy (nodea.pos);
 
207
        1 = copy (nodea.pos);
 
208
        2 = copy (nodeb.pos);
 
209
        3 = copy (nodeb.pos);
 
210
    ];
 
211
    gt.unpackedgeattr (gt, edge);
 
212
    if (show)
 
213
        gt.drawedge (gt, gt.views, edge);
 
214
    if (~gt.noundo) {
 
215
        gt.startadd2undo (gt);
 
216
        gt.currundo.inserted.edges[eid] = edge;
 
217
        gt.endadd2undo (gt);
 
218
    }
 
219
    return edge;
 
220
};
 
221
dotty.protogt.removeedge = function (gt, edge) {
 
222
    local head, tail;
 
223
 
 
224
    if (~gt.noundo)
 
225
        gt.startadd2undo (gt);
 
226
    if (edge.head.attr.support == 1)
 
227
        head = edge.head;
 
228
    if (edge.tail.attr.support == 1)
 
229
        if (head ~= edge.tail)
 
230
            tail = edge.tail;
 
231
    gt.undrawedge (gt, gt.views, edge);
 
232
    remove (edge.eid, edge.head.edges);
 
233
    remove (edge.eid, edge.tail.edges);
 
234
    remove (edge.eid, gt.graph.edges);
 
235
    if (head & tablesize (head.edges) == 0)
 
236
        gt.removenode (gt, head);
 
237
    if (tail & tablesize (tail.edges) == 0)
 
238
        gt.removenode (gt, tail);
 
239
    if (~gt.noundo) {
 
240
        gt.currundo.deleted.edges[edge.eid] = edge;
 
241
        gt.endadd2undo (gt);
 
242
    }
 
243
};
 
244
dotty.protogt.swapedgeids = function (gt, edge1, edge2) {
 
245
    local eid1, eid2;
 
246
 
 
247
    if (edge1.eid == edge2.eid)
 
248
        return;
 
249
    if (~gt.noundo)
 
250
        gt.startadd2undo (gt);
 
251
    eid1 = edge1.eid;
 
252
    eid2 = edge2.eid;
 
253
    gt.graph.edges[eid1] = edge2;
 
254
    gt.graph.edges[eid2] = edge1;
 
255
    remove (eid1, edge1.tail.edges);
 
256
    remove (eid1, edge1.head.edges);
 
257
    remove (eid2, edge2.tail.edges);
 
258
    remove (eid2, edge2.head.edges);
 
259
    edge1.tail.edges[eid2] = edge1;
 
260
    edge1.head.edges[eid2] = edge1;
 
261
    edge2.tail.edges[eid1] = edge2;
 
262
    edge2.head.edges[eid1] = edge2;
 
263
    edge1.eid = eid2;
 
264
    edge2.eid = eid1;
 
265
    if (~gt.noundo) {
 
266
        gt.currundo.swapped.edges[eid1] = edge1;
 
267
        gt.currundo.swapped.edges[eid2] = edge2;
 
268
        gt.endadd2undo (gt);
 
269
    }
 
270
};
 
271
dotty.protogt.removesubtree = function (gt, obj) {
 
272
    local nlist, node, head, nid, edge, eid;
 
273
 
 
274
    if (~gt.noundo)
 
275
        gt.startadd2undo (gt);
 
276
    if (obj.nid >= 0)
 
277
        node = obj;
 
278
    else if (obj.eid >= 0) {
 
279
        node = obj.head;
 
280
        gt.removeedge (gt, obj);
 
281
        if (~gt.graph.nodes[node.nid]) {
 
282
            if (~gt.noundo)
 
283
                gt.endadd2undo (gt);
 
284
            return;
 
285
        }
 
286
        for (eid in node.edges) {
 
287
            edge = node.edges[eid];
 
288
            if (edge.head == node & edge.tail ~= node) {
 
289
                if (~gt.noundo)
 
290
                    gt.endadd2undo (gt);
 
291
                return;
 
292
            }
 
293
        }
 
294
    } else {
 
295
        dotty.message (0, 'bad object type in gt.removesubtree');
 
296
        return;
 
297
    }
 
298
    nlist = [node.nid = node;];
 
299
    while (node) {
 
300
        for (eid in node.edges) {
 
301
            head = node.edges[eid].head;
 
302
            if (head ~= node)
 
303
                nlist[head.nid] = head;
 
304
        }
 
305
        gt.removenode (gt, node);
 
306
        remove (node.nid, nlist);
 
307
        node = null;
 
308
        for (nid in nlist) {
 
309
            node = nlist[nid];
 
310
            for (eid in node.edges) {
 
311
                edge = node.edges[eid];
 
312
                if (edge.head == node & edge.tail ~= node) {
 
313
                    node = null;
 
314
                    break;
 
315
                }
 
316
            }
 
317
            if (node)
 
318
                break;
 
319
        }
 
320
    }
 
321
    if (~gt.noundo)
 
322
        gt.endadd2undo (gt);
 
323
};
 
324
dotty.protogt.removenodesbyattr = function (gt, key, val) {
 
325
    local nlist, nid;
 
326
 
 
327
    if (~gt.noundo)
 
328
        gt.startadd2undo (gt);
 
329
    nlist = gt.getnodesbyattr (gt, key, val);
 
330
    for (nid in nlist)
 
331
        gt.removenode (gt, nlist[nid]);
 
332
    if (~gt.noundo)
 
333
        gt.endadd2undo (gt);
 
334
};
 
335
dotty.protogt.removesubtreesbyattr = function (gt, key, val) {
 
336
    local nlist, nid;
 
337
 
 
338
    if (~gt.noundo)
 
339
        gt.startadd2undo (gt);
 
340
    nlist = gt.getnodesbyattr (gt, key, val);
 
341
    for (nid in nlist)
 
342
        if (gt.graph.nodes[nid])
 
343
            gt.removesubtree (gt, nlist[nid]);
 
344
    if (~gt.noundo)
 
345
        gt.endadd2undo (gt);
 
346
};
 
347
dotty.protogt.groupnodes = function (gt, nlist, gnode, pos, size, attr,
 
348
        keepmulti, show) {
 
349
    local nid, node, elist, eid, edge, nodea, nodeb, inlist, outlist;
 
350
 
 
351
    if (~nlist | tablesize (nlist) == 0)
 
352
        return;
 
353
    if (gnode.attr.support) {
 
354
        dotty.message (0, 'cannot group nodes in a support node');
 
355
        return;
 
356
    }
 
357
    if (~gt.noundo)
 
358
        gt.startadd2undo (gt);
 
359
    if (~gnode)
 
360
        gnode = gt.insertnode (gt, pos, size, null, attr, show);
 
361
    inlist = [];
 
362
    outlist = [];
 
363
    for (nid in nlist) {
 
364
        if ((node = nlist[nid]) == gnode)
 
365
            continue;
 
366
        elist = [];
 
367
        for (eid in node.edges)
 
368
            elist[eid] = node.edges[eid];
 
369
        for (eid in elist) {
 
370
            edge = elist[eid];
 
371
            if (edge.head == node) {
 
372
                nodea = edge.tail;
 
373
                nodeb = gnode;
 
374
                if (~keepmulti) {
 
375
                    if (inlist[nodea.nid])
 
376
                        continue;
 
377
                    inlist[nodea.nid] = nodea;
 
378
                    if (nodea == gnode)
 
379
                        outlist[nodea.nid] = nodea;
 
380
                }
 
381
            } else {
 
382
                nodea = gnode;
 
383
                nodeb = edge.head;
 
384
                if (~keepmulti) {
 
385
                    if (outlist[nodeb.nid])
 
386
                        continue;
 
387
                    outlist[nodeb.nid] = nodeb;
 
388
                    if (nodeb == gnode)
 
389
                        inlist[nodeb.nid] = nodeb;
 
390
                }
 
391
            }
 
392
            gt.insertedge (gt, nodea, null, nodeb, null, edge.attr, show);
 
393
        }
 
394
        gt.removenode (gt, node);
 
395
    }
 
396
    if (~gt.noundo)
 
397
        gt.endadd2undo (gt);
 
398
    return gnode;
 
399
};
 
400
dotty.protogt.groupnodesbyattr =
 
401
        function (gt, key, val, attr, keepmulti, show) {
 
402
    local nlist, nid, pos, size;
 
403
 
 
404
    pos = null;
 
405
    size = null;
 
406
    nlist = gt.getnodesbyattr (gt, key, val);
 
407
    if (show)
 
408
        for (nid in nlist) {
 
409
            pos = nlist[nid].pos;
 
410
            size = nlist[nid].size;
 
411
            break;
 
412
        }
 
413
    return gt.groupnodes (gt, nlist, null, pos, size, attr, keepmulti, show);
 
414
};
 
415
dotty.protogt.cut = function (gt, obj, set, mode, op) {
 
416
    local clipgt, list, node, nid, edge, eid, clipnode;
 
417
 
 
418
    clipgt = dotty.clipgt;
 
419
    clipgt.graph = copy (dotty.protogt.graph);
 
420
    if (obj.eid >= 0) { # it's an edge
 
421
        list.edges[obj.eid] = obj;
 
422
        node = obj.head;
 
423
    } else if (obj.nid >= 0) {
 
424
        list.nodes[obj.nid] = obj;
 
425
        node = obj;
 
426
        for (eid in node.edges)
 
427
            list.edges[eid] = node.edges[eid];
 
428
    } else {
 
429
        dotty.message (0, 'unknown object type in gt.cut');
 
430
        return;
 
431
    }
 
432
    if (set == 'reachable') {
 
433
        list.nodes = gt.reachablenodes (gt, node);
 
434
        for (nid in list.nodes) {
 
435
            node = list.nodes[nid];
 
436
            for (eid in node.edges) {
 
437
                edge = node.edges[eid];
 
438
                list.edges[edge.eid] = edge;
 
439
            }
 
440
        }
 
441
    }
 
442
    if (mode == 'support') {
 
443
        for (eid in list.edges) {
 
444
            edge = list.edges[eid];
 
445
            if (~list.nodes[edge.tail.nid]) {
 
446
                list.support[edge.tail.nid] = edge.tail;
 
447
                list.nodes[edge.tail.nid] = edge.tail;
 
448
            }
 
449
            if (~list.nodes[edge.head.nid]) {
 
450
                list.support[edge.head.nid] = edge.head;
 
451
                list.nodes[edge.head.nid] = edge.head;
 
452
            }
 
453
        }
 
454
    }
 
455
    for (nid = 0; nid < gt.graph.maxnid; nid = nid + 1) {
 
456
        if (~list.nodes[nid])
 
457
            continue;
 
458
        node = list.nodes[nid];
 
459
        clipnode = gt.insertnode (clipgt, null, null, node.name, node.attr, 0);
 
460
        if (list.support[nid])
 
461
            clipnode.support = 1;
 
462
        list.clipnodes[nid] = clipnode;
 
463
    }
 
464
    for (eid = 0; eid < gt.graph.maxeid; eid = eid + 1) {
 
465
        if (~list.edges[eid])
 
466
            continue;
 
467
        edge = list.edges[eid];
 
468
        if (~list.nodes[edge.tail.nid] | ~list.nodes[edge.head.nid])
 
469
            continue;
 
470
        gt.insertedge (clipgt, list.clipnodes[edge.tail.nid], null,
 
471
                list.clipnodes[edge.head.nid], null, edge.attr, 0);
 
472
    }
 
473
    if (op ~= 'cut')
 
474
        return;
 
475
    if (~gt.noundo)
 
476
        gt.startadd2undo (gt);
 
477
    for (eid in list.edges)
 
478
        gt.removeedge (gt, list.edges[eid]);
 
479
    for (nid in list.nodes)
 
480
        if (~list.support[nid] & gt.graph.nodes[nid])
 
481
            gt.removenode (gt, list.nodes[nid]);
 
482
    if (~gt.noundo)
 
483
        gt.endadd2undo (gt);
 
484
};
 
485
dotty.protogt.paste = function (gt, pos, show) {
 
486
    local clipgt, offset, center, nid, node, eid, edge, nodes;
 
487
 
 
488
    if (~gt.noundo)
 
489
        gt.startadd2undo (gt);
 
490
    clipgt = dotty.clipgt;
 
491
    if (clipgt.graph.rect)
 
492
        center = [
 
493
            'x' = (clipgt.graph.rect[1].x + clipgt.graph.rect[0].x) / 2;
 
494
            'y' = (clipgt.graph.rect[1].y + clipgt.graph.rect[0].y) / 2;
 
495
        ];
 
496
    else
 
497
        center = pos;
 
498
    offset = [
 
499
        'x' = center.x - pos.x;
 
500
        'y' = center.y - pos.y;
 
501
    ];
 
502
    for (nid = 0; clipgt.graph.nodes[nid]; nid = nid + 1) {
 
503
        node = clipgt.graph.nodes[nid];
 
504
        if (node.attr.label == '\N' | ~node.attr.label)
 
505
            node.attr.label = node.name;
 
506
        if (node.support == 1)
 
507
            nodes[nid] = gt.insertnode (gt, [
 
508
                'x' = node.pos.x - offset.x;
 
509
                'y' = node.pos.y - offset.y;
 
510
            ], null, null, [
 
511
                'support' = 1; 'shape' = 'circle';
 
512
                'label' = ''; 'width' = 0.2;
 
513
            ], show);
 
514
        else
 
515
            nodes[nid] = gt.insertnode (gt, [
 
516
                'x' = node.pos.x - offset.x;
 
517
                'y' = node.pos.y - offset.y;
 
518
            ], node.size, null, node.attr, show);
 
519
    }
 
520
    for (eid = 0; clipgt.graph.edges[eid]; eid = eid + 1) {
 
521
        edge = clipgt.graph.edges[eid];
 
522
        gt.insertedge (gt, nodes[edge.tail.nid], null,
 
523
                nodes[edge.head.nid], null, edge.attr, show);
 
524
    }
 
525
    if (~gt.noundo)
 
526
        gt.endadd2undo (gt);
 
527
};
 
528
dotty.protogt.startadd2undo = function (gt) {
 
529
    if (~gt.undoarray.level)
 
530
        gt.currundo =
 
531
                (gt.undoarray.entries[tablesize (gt.undoarray.entries)] = []);
 
532
    gt.undoarray.level = gt.undoarray.level + 1;
 
533
};
 
534
dotty.protogt.endadd2undo = function (gt) {
 
535
    gt.undoarray.level = gt.undoarray.level - 1;
 
536
};
 
537
dotty.protogt.undo = function (gt, show) {
 
538
    local entry, n, eid, edge, nid, node, edges;
 
539
 
 
540
    if ((n = tablesize (gt.undoarray.entries)) < 1)
 
541
        return;
 
542
    entry = gt.undoarray.entries[n - 1];
 
543
    remove (n - 1, gt.undoarray.entries);
 
544
    remove ('currundo', gt);
 
545
    gt.noundo = 1;
 
546
    # hardwire nodes and edges back with the same id's as the originals
 
547
    for (nid in entry.deleted.nodes) {
 
548
        node = entry.deleted.nodes[nid];
 
549
        gt.graph.nodedict[node.name] = node.nid;
 
550
        gt.graph.nodes[node.nid] = node;
 
551
        node.edges = [];
 
552
        if (show)
 
553
            gt.drawnode (gt, gt.views, node);
 
554
    }
 
555
    for (eid in entry.deleted.edges) {
 
556
        edge = entry.deleted.edges[eid];
 
557
        gt.graph.edges[edge.eid] = edge;
 
558
        edge.head.edges[edge.eid] = edge;
 
559
        edge.tail.edges[edge.eid] = edge;
 
560
        if (show)
 
561
            gt.drawedge (gt, gt.views, edge);
 
562
    }
 
563
    if (entry.swapped.edges) {
 
564
        if (tablesize (entry.swapped.edges) == 2) {
 
565
            n = 0;
 
566
            for (eid in entry.swapped.edges) {
 
567
                edges[n] = entry.swapped.edges[eid];
 
568
                n = n + 1;
 
569
            }
 
570
            gt.swapedgeids (gt, edges[0], edges[1]);
 
571
        } else
 
572
            dotty.message (0, 'cannot handle undoing swap of > 2 edges');
 
573
    }
 
574
    for (eid in entry.inserted.edges) {
 
575
        edge = entry.inserted.edges[eid];
 
576
        gt.removeedge (gt, edge);
 
577
    }
 
578
    for (nid in entry.inserted.nodes) {
 
579
        node = entry.inserted.nodes[nid];
 
580
        gt.removenode (gt, node);
 
581
    }
 
582
    gt.noundo = 0;
 
583
};