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

« back to all changes in this revision

Viewing changes to dotty/dotty.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
 
3
#
 
4
dotty = [
 
5
    'keys' = [
 
6
        'nid'    = 'nid';
 
7
        'eid'    = 'eid';
 
8
        'gid'    = 'gid';
 
9
        'name'   = 'name';
 
10
        'attr'   = 'attr';
 
11
        'gattr'  = 'graphattr';
 
12
        'eattr'  = 'edgeattr';
 
13
        'nattr'  = 'nodeattr';
 
14
        'edges'  = 'edges';
 
15
        'tail'   = 'tail';
 
16
        'tport'  = 'tport';
 
17
        'head'   = 'head';
 
18
        'hport'  = 'hport';
 
19
        'pos'    = 'pos';
 
20
        'size'   = 'size';
 
21
        'points' = 'points';
 
22
        'fname'  = 'fontname';
 
23
        'fsize'  = 'fontsize';
 
24
        'fcolor' = 'fontcolor';
 
25
        'color'  = 'color';
 
26
    ];
 
27
    'maps' = [
 
28
        'X11' = [
 
29
            'fontmap' = [
 
30
                'Times-Roman' =
 
31
                        '-*-times-medium-r-*--%d-*-*-*-*-*-*-1';
 
32
                'Times-Italic' =
 
33
                        '-*-times-medium-i-*--%d-*-*-*-*-*-*-1';
 
34
                'Times-Bold' =
 
35
                        '-*-times-bold-r-*--%d-*-*-*-*-*-*-1';
 
36
                'Courier' =
 
37
                        '-*-courier-bold-r-*--%d-*-*-*-*-*-*-1';
 
38
                'Courier-Bold' =
 
39
                        '-*-courier-bold-r-*--%d-*-*-*-*-*-*-1';
 
40
                'Helvetica' =
 
41
                        '-*-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1';
 
42
                'Helvetica-Bold' =
 
43
                        '-*-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1';
 
44
            ];
 
45
            'psfontmap' = [
 
46
                'Times-Roman'    = 'Times-Roman';
 
47
                'Times-Italic'   = 'Times-Italic';
 
48
                'Times-Bold'     = 'Times-Bold';
 
49
                'Courier'        = 'Courier';
 
50
                'Courier-Bold'   = 'Courier-Bold';
 
51
                'Helvetica'      = 'Helvetica';
 
52
                'Helvetica-Bold' = 'Helvetica-Bold';
 
53
            ];
 
54
        ];
 
55
        'mswin' = [
 
56
            'fontmap' = [
 
57
                'Times-Roman'    = 'Times New Roman';
 
58
                'Times-Italic'   = 'Times New Roman Italic';
 
59
                'Times-Bold'     = 'Times New Roman Bold';
 
60
                'Courier'        = 'Courier New';
 
61
                'Courier-Bold'   = 'Courier New Bold';
 
62
                'Helvetica'      = 'Arial';
 
63
                'Helvetica-Bold' = 'Arial Bold';
 
64
            ];
 
65
            'psfontmap' = [
 
66
                'Times-Roman'    = 'Times New Roman';
 
67
                'Times-Italic'   = 'Times New Roman Italic';
 
68
                'Times-Bold'     = 'Times New Roman Bold';
 
69
                'Courier'        = 'Courier New';
 
70
                'Courier-Bold'   = 'Courier New Bold';
 
71
                'Helvetica'      = 'Arial';
 
72
                'Helvetica-Bold' = 'Arial Bold';
 
73
            ];
 
74
        ];
 
75
    ];
 
76
    'protogt' = [
 
77
        'graph' = [
 
78
            'graphattr' = [
 
79
                'fontsize' = '14';
 
80
                'fontname' = 'Times-Roman';
 
81
                'fontcolor' = 'black';
 
82
                'color' = 'black';
 
83
            ];
 
84
            'nodeattr' = [
 
85
                'shape' = 'ellipse';
 
86
                'fontsize' = '14';
 
87
                'fontname' = 'Times-Roman';
 
88
                'fontcolor' = 'black';
 
89
                'color' = 'black';
 
90
            ];
 
91
            'edgeattr' = [
 
92
                'fontsize' = '14';
 
93
                'fontname' = 'Times-Roman';
 
94
                'fontcolor' = 'black';
 
95
                'color' = 'black';
 
96
            ];
 
97
            'graphdict' = [];
 
98
            'nodedict' = [];
 
99
            'graphs' = [];
 
100
            'nodes' = [];
 
101
            'edges' = [];
 
102
            'maxgid' = 0;
 
103
            'maxnid' = 0;
 
104
            'maxeid' = 0;
 
105
            'type' = 'digraph';
 
106
        ];
 
107
        'layoutmode' = 'sync';
 
108
        'lserver' = 'dot';
 
109
        'edgehandles' = 1;
 
110
        'noundo' = 0;
 
111
    ];
 
112
    'lservers' = [];
 
113
    'mlevel' = 0;
 
114
    'graphs' = [];
 
115
    'views' = [];
 
116
    'protovt' = [
 
117
        'normal' = [
 
118
            'name' = 'DOTTY';
 
119
            'orig' = ['x' = 1; 'y' = 1;];
 
120
            'size' = ['x' = 420; 'y' = 520;];
 
121
            'wrect' = [
 
122
                0 = ['x' = 0; 'y' = 0;];
 
123
                1 = ['x' = 400; 'y' = 500;];
 
124
            ];
 
125
            'vsize' = ['x' = 400; 'y' = 500;];
 
126
            'w2v' = 1;
 
127
        ];
 
128
        'birdseye' = [
 
129
            'type' = 'birdseye';
 
130
            'name' = 'DOTTY birdseye view';
 
131
            'orig' = ['x' = 1; 'y' = 1;];
 
132
            'size' = ['x' = 220; 'y' = 260;];
 
133
            'wrect' = [
 
134
                0 = ['x' = 0; 'y' = 0;];
 
135
                1 = ['x' = 200; 'y' = 250;];
 
136
            ];
 
137
            'vsize' = ['x' = 200; 'y' = 250;];
 
138
            'w2v' = 1;
 
139
        ];
 
140
    ];
 
141
    'pagesizes' = [
 
142
        '8.5x11' = ['x' =    8; 'y' = 10.5;];
 
143
        '11x17'  = ['x' = 10.5; 'y' = 16.5;];
 
144
        '36x50'  = ['x' = 35.5; 'y' = 49.5;];
 
145
    ];
 
146
];
 
147
load ('dotty_draw.lefty');
 
148
load ('dotty_edit.lefty');
 
149
load ('dotty_layout.lefty');
 
150
load ('dotty_ui.lefty');
 
151
#
 
152
# initialization functions
 
153
#
 
154
dotty.init = function () {
 
155
    dotty.outlinecolor = 1;
 
156
    dotty.fontmap = dotty.maps[getenv ('LEFTYWINSYS')].fontmap;
 
157
    dotty.clipgt = dotty.protogt.creategraph (['noundo' = 1;]);
 
158
    dotty.inited = 1;
 
159
};
 
160
dotty.simple = function (file) {
 
161
    if (dotty.inited ~= 1)
 
162
        dotty.init ();
 
163
    dotty.createviewandgraph (file, 'file', null, null);
 
164
    txtview ('off');
 
165
};
 
166
#
 
167
# main operations
 
168
#
 
169
dotty.protogt.creategraph = function (protogt) {
 
170
    local gt, id, gtid;
 
171
 
 
172
    if (~protogt)
 
173
        protogt = dotty.protogt;
 
174
    for (gtid = 0; dotty.graphs[gtid]; gtid = gtid + 1)
 
175
        ;
 
176
    gt = (dotty.graphs[gtid] = []);
 
177
    if (protogt.mode ~= 'replace') {
 
178
        for (id in dotty.protogt)
 
179
            gt[id] = copy (dotty.protogt[id]);
 
180
    }
 
181
    for (id in protogt)
 
182
        gt[id] = copy (protogt[id]);
 
183
    gt.gtid = gtid;
 
184
    gt.views = [];
 
185
    gt.undoarray = ['level' = 0; 'entries' = [];];
 
186
    gt.busy = 0;
 
187
    return gt;
 
188
};
 
189
dotty.protogt.copygraph = function (ogt) {
 
190
    local gt, gtid, id;
 
191
 
 
192
    for (gtid = 0; dotty.graphs[gtid]; gtid = gtid + 1)
 
193
        ;
 
194
    gt = (dotty.graphs[gtid] = []);
 
195
    for (id in ogt)
 
196
        gt[id] = copy (ogt[id]);
 
197
    gt.gtid = gtid;
 
198
    gt.views = [];
 
199
    gt.undoarray = ['level' = 0; 'entries' = [];];
 
200
    gt.busy = 0;
 
201
    return gt;
 
202
};
 
203
dotty.protogt.destroygraph = function (gt) {
 
204
    local vid, vlist;
 
205
 
 
206
    if (gt.layoutpending > 0)
 
207
        gt.cancellayout (gt);
 
208
    for (vid in gt.views)
 
209
        vlist[vid] = gt.views[vid];
 
210
    for (vid in gt.views)
 
211
        gt.destroyview (gt, vlist[vid]);
 
212
    remove (gt.gtid, dotty.graphs);
 
213
};
 
214
dotty.protogt.loadgraph = function (gt, name, type, protograph, layoutflag) {
 
215
    local vid, vt, fd, graph, nid, eid, gid;
 
216
 
 
217
    if (gt.layoutpending > 0)
 
218
        gt.cancellayout (gt);
 
219
    if (~name)
 
220
        if (~(name = ask ('file name:', 'file', '')))
 
221
            return;
 
222
    dotty.pushbusy (gt, gt.views);
 
223
    dotty.message (1, 'loading');
 
224
    if (~protograph)
 
225
        protograph = dotty.protogt.graph;
 
226
    if (~((fd = dotty.openio (name, type, 'r')) >= 0) |
 
227
            ~(graph = readgraph (fd, protograph))) {
 
228
        dotty.message (0, 'cannot load graph');
 
229
        dotty.popbusy (gt, gt.views);
 
230
        return;
 
231
    }
 
232
    for (vid in gt.views) {
 
233
        vt = gt.views[vid];
 
234
        vt.colors = [];
 
235
        vt.colorn = 2;
 
236
    }
 
237
    gt.graph = graph;
 
238
    gt.name = name;
 
239
    gt.type = type;
 
240
    gt.undoarray = ['level' = 0; 'entries' = [];];
 
241
    if (~(type == 'file' & name == '-'))
 
242
        closeio (fd);
 
243
    graph.maxgid = tablesize (graph.graphs);
 
244
    graph.maxnid = tablesize (graph.nodes);
 
245
    graph.maxeid = tablesize (graph.edges);
 
246
    for (nid in graph.nodes)
 
247
        graph.nodes[nid][dotty.keys.nid] = nid;
 
248
    for (eid in graph.edges)
 
249
        graph.edges[eid][dotty.keys.eid] = eid;
 
250
    for (gid in graph.graphs)
 
251
        graph.graphs[gid][dotty.keys.gid] = gid;
 
252
    gt.unpackattr (gt);
 
253
    if (layoutflag) {
 
254
        dotty.message (1, 'generating layout');
 
255
        gt.layoutgraph (gt);
 
256
    }
 
257
    dotty.popbusy (gt, gt.views);
 
258
    return gt.graph;
 
259
};
 
260
dotty.protogt.savegraph = function (gt, name, type, savecoord) {
 
261
    local fd, graph, gid, sgraph, nid, node, eid, edge, pointi, attr;
 
262
 
 
263
    if (~name)
 
264
        if (~(name = ask ('file name:', 'file', '')))
 
265
            return;
 
266
    if (savecoord) {
 
267
        graph = copy (gt.graph);
 
268
        for (gid in graph.graphs) {
 
269
            sgraph = graph.graphs[gid];
 
270
            if (sgraph.rect)
 
271
                sgraph.graphattr.bb = concat (sgraph.rect[0].x, ',',
 
272
                        sgraph.rect[0].y, ',', sgraph.rect[1].x, ',',
 
273
                        sgraph.rect[1].y);
 
274
            if (sgraph.lp & tablesize (sgraph.lp) > 0)
 
275
                sgraph.graphattr.lp = concat (sgraph.lp.x, ',', sgraph.lp.y);
 
276
            else if (sgraph.lp)
 
277
                sgraph.graphattr.lp = "";
 
278
        }
 
279
        for (nid in graph.nodes) {
 
280
            node = graph.nodes[nid];
 
281
            if (~node.attr.label)
 
282
                node.attr.label = '\N';
 
283
            if (node.pos)
 
284
                node.attr.pos = concat (node.pos.x, ',', node.pos.y);
 
285
            if (node.size) {
 
286
                node.attr.width = node.size.x / 72;
 
287
                node.attr.height = node.size.y / 72;
 
288
            }
 
289
            if (node.fields)
 
290
                node.attr.rects = gt.packrecordfields (gt, node.fields);
 
291
        }
 
292
        for (eid in graph.edges) {
 
293
            edge = graph.edges[eid];
 
294
            if (edge.points) {
 
295
                attr = '';
 
296
                if (edge.sp)
 
297
                    attr = concat ('s,', edge.sp.x, ',', edge.sp.y, ' ');
 
298
                if (edge.ep)
 
299
                    attr = concat (attr, 'e,', edge.ep.x, ',', edge.ep.y, ' ');
 
300
                for (pointi = 0; edge.points[pointi]; pointi = pointi + 1)
 
301
                    attr = concat (attr, ' ', edge.points[pointi].x, ',',
 
302
                        edge.points[pointi].y);
 
303
                edge.attr.pos = attr;
 
304
            }
 
305
            if (edge.lp)
 
306
                edge.attr.lp = concat (edge.lp.x, ',', edge.lp.y);
 
307
        }
 
308
        if (~graph.rect) {
 
309
            graph.rect = [
 
310
                0 = ['x' = 0; 'y' = 0; ]; 1 = ['x' = 1; 'y' = 1; ];
 
311
            ];
 
312
            for (nid in graph.nodes) {
 
313
                node = graph.nodes[nid];
 
314
                if (graph.rect[1].x < node.pos.x + node.size.x / 2)
 
315
                    graph.rect[1].x = node.pos.x + node.size.x / 2;
 
316
                if (graph.rect[1].y < node.pos.y + node.size.y / 2)
 
317
                    graph.rect[1].y = node.pos.y + node.size.y / 2;
 
318
            }
 
319
        }
 
320
            graph.graphattr.bb = concat (graph.rect[0].x, ',',
 
321
                    graph.rect[0].y, ',', graph.rect[1].x, ',',
 
322
                    graph.rect[1].y);
 
323
        if (graph.lp & tablesize (graph.lp) > 0)
 
324
            graph.graphattr.lp = concat (graph.lp.x, ',', graph.lp.y);
 
325
    } else
 
326
        graph = gt.graph;
 
327
    if (~((fd = dotty.openio (name, type, 'w')) >= 0) |
 
328
            ~writegraph (fd, graph, 0)) {
 
329
        dotty.message (0, 'cannot save graph');
 
330
        return;
 
331
    }
 
332
    if (~(type == 'file' & name == '-'))
 
333
        closeio (fd);
 
334
};
 
335
dotty.protogt.packrecordfields = function (gt, fields) {
 
336
    local attrs, attr, fid, field;
 
337
 
 
338
    for (fid = 0; fields[fid]; fid = fid + 1) {
 
339
        field = fields[fid];
 
340
        if (field.fields)
 
341
            attr = gt.packrecordfields (gt, field.fields);
 
342
        else
 
343
            attr = concat (field.rect[0].x, ',', field.rect[0].y,
 
344
                    ',', field.rect[1].x, ',', field.rect[1].y);
 
345
        if (attrs)
 
346
            attrs = concat (attrs, ' ', attr);
 
347
        else
 
348
            attrs = attr;
 
349
    }
 
350
    return attrs;
 
351
};
 
352
dotty.protogt.setgraph = function (gt, graph) {
 
353
    local vid, vt, nid, eid, gid;
 
354
 
 
355
    if (gt.layoutpending > 0)
 
356
        gt.cancellayout (gt);
 
357
    for (vid in gt.views) {
 
358
        vt = gt.views[vid];
 
359
        vt.colors = [];
 
360
        vt.colorn = 2;
 
361
    }
 
362
    gt.graph = copy (graph);
 
363
    gt.undoarray = ['level' = 0; 'entries' = [];];
 
364
    gt.unpackattr (gt);
 
365
    gt.graph.maxgid = tablesize (graph.graphs);
 
366
    gt.graph.maxnid = tablesize (graph.nodes);
 
367
    gt.graph.maxeid = tablesize (graph.edges);
 
368
    for (nid in gt.graph.nodes)
 
369
        gt.graph.nodes[nid][dotty.keys.nid] = nid;
 
370
    for (eid in gt.graph.edges)
 
371
        gt.graph.edges[eid][dotty.keys.eid] = eid;
 
372
    for (gid in gt.graph.graphs)
 
373
        gt.graph.graphs[gid][dotty.keys.gid] = gid;
 
374
    gt.unpackattr (gt);
 
375
    dotty.message (1, 'generating layout');
 
376
    gt.layoutgraph (gt);
 
377
    return gt.graph;
 
378
};
 
379
dotty.protogt.erasegraph = function (gt, protogt, protovt) {
 
380
    local vid, vt;
 
381
 
 
382
    if (gt.layoutpending > 0)
 
383
        gt.cancellayout (gt);
 
384
    for (vid in gt.views) {
 
385
        vt = gt.views[vid];
 
386
        vt.colors = [];
 
387
        vt.colorn = 2;
 
388
        clear (vt.canvas);
 
389
    }
 
390
    if (~protogt)
 
391
        protogt = dotty.protogt;
 
392
    gt.graph = copy (protogt.graph);
 
393
    gt.undoarray = ['level' = 0; 'entries' = [];];
 
394
};
 
395
dotty.protogt.layoutgraph = function (gt) {
 
396
    if (gt.graph.graphattr.bb) {
 
397
        gt.unpacklayout (gt, gt.graph);
 
398
        gt.setviewsize (gt.views, gt.graph.rect);
 
399
        gt.redrawgraph (gt, gt.views);
 
400
        return;
 
401
    }
 
402
    if (gt.layoutmode == 'async') {
 
403
        if (~gt.haveinput) {
 
404
            gt.startlayout (gt);
 
405
            return;
 
406
        }
 
407
        if (~gt.finishlayout (gt))
 
408
            return;
 
409
        gt.setviewsize (gt.views, gt.graph.rect);
 
410
        gt.redrawgraph (gt, gt.views);
 
411
    } else {
 
412
        if (~gt.startlayout (gt))
 
413
            return;
 
414
        else
 
415
            while (~gt.finishlayout (gt))
 
416
                ;
 
417
        gt.setviewsize (gt.views, gt.graph.rect);
 
418
        gt.redrawgraph (gt, gt.views);
 
419
    }
 
420
};
 
421
dotty.protogt.createview = function (gt, protovt) {
 
422
    local vt, ovt, id, t;
 
423
 
 
424
    vt = [];
 
425
    vt.colors = [];
 
426
    vt.colorn = 2;
 
427
    if (~protovt)
 
428
        protovt = dotty.protovt.normal;
 
429
    if (protovt.mode ~= 'replace') {
 
430
        for (id in dotty.protovt[protovt.type])
 
431
            vt[id] = copy (dotty.protovt[protovt.type][id]);
 
432
    }
 
433
    for (id in protovt)
 
434
        vt[id] = copy (protovt[id]);
 
435
    if (~(vt.parent >= 0)) {
 
436
        vt.view = createwidget (-1, [
 
437
            'type'   = 'view';
 
438
            'name'   = vt.name;
 
439
            'origin' = vt.orig;
 
440
            'size'   = vt.size;
 
441
        ]);
 
442
        vt.scroll = createwidget (vt.view, ['type' = 'scroll';]);
 
443
    } else {
 
444
        vt.view = -1;
 
445
        vt.scroll = createwidget (vt.parent, [
 
446
            'type' = 'scroll';
 
447
            'size' = vt.size;
 
448
        ]);
 
449
    }
 
450
    vt.canvas = createwidget (vt.scroll, [
 
451
        'type' = 'canvas';
 
452
        'color' = [0 = protovt.bgcolor; 1 = protovt.fgcolor;];
 
453
    ]);
 
454
    setwidgetattr (vt.canvas, [
 
455
        'window' = vt.wrect;
 
456
        'viewport' = vt.vsize;
 
457
    ]);
 
458
    clear (vt.canvas);
 
459
    dotty.views[vt.canvas] = vt;
 
460
    vt.vtid = vt.canvas;
 
461
    vt.gtid = gt.gtid;
 
462
    gt.views[vt.vtid] = vt;
 
463
    dotty.views[vt.scroll] = vt;
 
464
    if (vt.view ~= -1)
 
465
        dotty.views[vt.view] = vt;
 
466
    if (protovt.colors & tablesize (protovt.colors) > 0) {
 
467
        for (id in protovt.colors)
 
468
            if (setwidgetattr (vt.canvas, ['color' = [
 
469
                protovt.colors[id] = id;
 
470
            ];]) ~= 1) {
 
471
                t = split (id, ' ');
 
472
                if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, [
 
473
                    'color' = [protovt.colors[id] = [
 
474
                        'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]);
 
475
                    ];];
 
476
                ]) ~= 1) {
 
477
                    dotty.message (0,
 
478
                            concat ('unknown color ', id, ' using #1'));
 
479
                }
 
480
            }
 
481
        vt.colors = copy (protovt.colors);
 
482
        vt.colorn = protovt.colorn;
 
483
    } else if (tablesize (gt.views) > 1) {
 
484
        for (id in gt.views)
 
485
            if (gt.views[id] ~= vt)
 
486
                break;
 
487
        ovt = gt.views[id];
 
488
        for (id in ovt.colors)
 
489
            if (setwidgetattr (vt.canvas, ['color' = [
 
490
                ovt.colors[id] = id;
 
491
            ];]) ~= 1) {
 
492
                t = split (id, ' ');
 
493
                if (tablesize (t) ~= 3 | setwidgetattr (vt.canvas, [
 
494
                    'color' = [ovt.colors[id] = [
 
495
                        'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]);
 
496
                    ];];
 
497
                ]) ~= 1) {
 
498
                    dotty.message (0,
 
499
                            concat ('unknown color ', id, ' using #1'));
 
500
                }
 
501
            }
 
502
        vt.colors = copy (ovt.colors);
 
503
        vt.colorn = ovt.colorn;
 
504
    }
 
505
    if (gt.graph.rect)
 
506
        gt.setviewsize ([vt.vtid = vt;], gt.graph.rect);
 
507
    gt.drawgraph (gt, [vt.vtid = vt;]);
 
508
    for (id in vt.uifuncs)
 
509
        if (id == 'closeview')
 
510
            widgets[vt.view][id] = vt.uifuncs[id];
 
511
        else
 
512
            widgets[vt.canvas][id] = vt.uifuncs[id];
 
513
    return vt;
 
514
};
 
515
dotty.protogt.destroyview = function (gt, vt) {
 
516
    destroywidget (vt.canvas);
 
517
    destroywidget (vt.scroll);
 
518
    if (vt.view ~= -1) {
 
519
        destroywidget (vt.view);
 
520
        remove (vt.view, dotty.views);
 
521
    }
 
522
    remove (vt.scroll, dotty.views);
 
523
    remove (vt.canvas, dotty.views);
 
524
    if (vt.gtid >= 0)
 
525
        remove (vt.vtid, gt.views);
 
526
    if (tablesize (dotty.views) == 0)
 
527
        exit ();
 
528
};
 
529
dotty.protogt.zoom = function (gt, vt, factor, pos) {
 
530
    gt.setviewscale ([vt.vtid = vt;], factor);
 
531
    if (pos)
 
532
        gt.setviewcenter ([vt.vtid = vt;], pos);
 
533
    gt.redrawgraph (gt, [vt.vtid = vt;]);
 
534
};
 
535
dotty.protogt.findnode = function (gt, vt) {
 
536
    local key, node, node1, nid;
 
537
 
 
538
    if (~(key = ask ('give node name or label')))
 
539
        return;
 
540
    if (gt.graph.nodedict[key] >= 0)
 
541
        node = gt.graph.nodes[gt.graph.nodedict[key]];
 
542
    else if (gt.graph.nodedict[ston (key)] >= 0)
 
543
        node = gt.graph.nodes[gt.graph.nodedict[ston (key)]];
 
544
    else {
 
545
        for (nid in gt.graph.nodes) {
 
546
            node1 = gt.graph.nodes[nid];
 
547
            if (node1.attr.label == key | node1.attr.label == ston (key)) {
 
548
                node = node1;
 
549
                break;
 
550
            }
 
551
        }
 
552
    }
 
553
    if (~node) {
 
554
        dotty.message (0, concat ('cannot find node: ', key));
 
555
        return;
 
556
    }
 
557
    gt.setviewcenter ([vt.vtid = vt;], node.pos);
 
558
};
 
559
dotty.protogt.setattr = function (gt, obj) {
 
560
    local kv, t, attr, value;
 
561
 
 
562
    if (~(kv = ask ('give attr/value, eg. color=blue')))
 
563
        return;
 
564
    t = split (kv, '=');
 
565
    attr = t[0];
 
566
    value = t[1];
 
567
    if (
 
568
        obj.attr == gt.graph.graphattr |
 
569
        obj.attr == gt.graph.edgeattr |
 
570
        obj.attr == gt.graph.nodeattr
 
571
    ) {
 
572
        obj.attr[attr] = value;
 
573
        return;
 
574
    }
 
575
    if (obj.nid >= 0) {
 
576
        gt.undrawnode (gt, gt.views, obj);
 
577
        obj.attr[attr] = value;
 
578
        gt.unpacknodeattr (gt, obj);
 
579
        gt.drawnode (gt, gt.views, obj);
 
580
    } else if (obj.eid >= 0) {
 
581
        gt.undrawedge (gt, gt.views, obj);
 
582
        obj.attr[attr] = value;
 
583
        gt.unpackedgeattr (gt, obj);
 
584
        gt.drawedge (gt, gt.views, obj);
 
585
    }
 
586
};
 
587
dotty.protogt.getattr = function (gt, node) {
 
588
    local kv;
 
589
 
 
590
    if (~(kv.key = ask ('give attr name')))
 
591
        return null;
 
592
    if ((kv.val = node.attr[kv.key]))
 
593
        return kv;
 
594
    return null;
 
595
};
 
596
#
 
597
# utilities
 
598
#
 
599
dotty.createviewandgraph = function (name, type, protogt, protovt) {
 
600
    local vt, gt;
 
601
 
 
602
    if (~protogt)
 
603
        protogt = dotty.protogt;
 
604
    if (protogt.creategraph)
 
605
        gt = protogt.creategraph (protogt);
 
606
    else
 
607
        gt = dotty.protogt.creategraph (protogt);
 
608
    vt = gt.createview (gt, protovt);
 
609
    if (~protogt.graph)
 
610
        protogt.graph = copy (dotty.protogt.graph);
 
611
    if (name)
 
612
        gt.loadgraph (gt, name, type, protogt.graph, 1);
 
613
    return ['gt' = gt; 'vt' = vt;];
 
614
};
 
615
dotty.openio = function (name, type, mode) {
 
616
    local fd;
 
617
 
 
618
    if (~name)
 
619
        return null;
 
620
    if (type == 'file') {
 
621
        if (name == '-') {
 
622
            if (mode == 'r' | mode == 'r+')
 
623
                fd = 0;
 
624
            else
 
625
                fd = 1;
 
626
        } else if (~((fd = openio ('file', name, mode)) >= 0)) {
 
627
            dotty.message (0, concat ('cannot open file: ', name));
 
628
            return null;
 
629
        }
 
630
    } else if (type == 'pipe') {
 
631
        if (~((fd = openio ('pipe', 'ksh', mode,
 
632
                concat ("%e ", name))) >= 0)) {
 
633
            dotty.message (0, concat ('cannot run command: ', name));
 
634
            return null;
 
635
        }
 
636
    } else
 
637
        return null;
 
638
    return fd;
 
639
};
 
640
dotty.pushbusy = function (gt, views) {
 
641
    local vid;
 
642
 
 
643
    if (gt.busy == 0)
 
644
        for (vid in gt.views)
 
645
            setwidgetattr (vid, ['cursor' = 'watch';]);
 
646
    gt.busy = gt.busy + 1;
 
647
};
 
648
dotty.popbusy = function (gt, views) {
 
649
    local vid;
 
650
 
 
651
    gt.busy = gt.busy - 1;
 
652
    if (gt.busy == 0)
 
653
        for (vid in gt.views)
 
654
            setwidgetattr (vid, ['cursor' = 'default';]);
 
655
};
 
656
dotty.message = function (level, text) {
 
657
    if (level <= dotty.mlevel)
 
658
        echo ('dotty.lefty: ', text);
 
659
};
 
660
#
 
661
# printing or saving to file
 
662
#
 
663
dotty.protogt.printorsave = function (gt, vt, otype, name, mode, ptype) {
 
664
    local pr, wrect, vsize, xy, psize, canvas, pscanvas, cid, cname, t;
 
665
    local graph, edgehandles, fontmap, eid, edge, nid, node, gid, sgraph;
 
666
 
 
667
    if (~otype)
 
668
        if (~(otype = ask ('print to', 'choice', 'file|printer')))
 
669
            return;
 
670
    if (otype == 'printer') {
 
671
        name = '/tmp/dottyout.ps';
 
672
        if (getenv ('LEFTYWINSYS') ~= 'mswin' & ~pr)
 
673
            if (~(pr = ask ('printer command', 'string', 'lpr')))
 
674
                return;
 
675
    }
 
676
    if (~name)
 
677
        if (~(name = ask ('postscript file', 'file', 'out.ps')))
 
678
            return;
 
679
    if (~ptype)
 
680
        if (~(ptype = ask ('page size', 'choice', '8.5x11|11x17|36x50')))
 
681
            return;
 
682
    if (~mode)
 
683
        if (~(mode = ask ('mode', 'choice', 'portrait|landscape|best fit')))
 
684
            return;
 
685
    wrect = copy (vt.wrect);
 
686
    wrect[0].x = wrect[0].x - 1;
 
687
    wrect[1].x = wrect[1].x + 1;
 
688
    wrect[0].y = wrect[0].y - 1;
 
689
    wrect[1].y = wrect[1].y + 1;
 
690
    vsize = copy (vt.vsize);
 
691
    if (vsize.x == 0)
 
692
        vsize.x = 1;
 
693
    if (vsize.y == 0)
 
694
        vsize.y = 1;
 
695
    xy = vsize.x / vsize.y;
 
696
    if (mode == 'best fit') {
 
697
        if (xy < 1)
 
698
            mode = 'portrait';
 
699
        else
 
700
            mode = 'landscape';
 
701
    }
 
702
    psize = dotty.pagesizes[ptype];
 
703
    if (mode == 'portrait') {
 
704
        if (xy < psize.x / psize.y) {
 
705
            vsize.y = psize.y * 300;
 
706
            vsize.x = vsize.y * xy;
 
707
        } else {
 
708
            vsize.x = psize.x * 300;
 
709
            vsize.y = vsize.x / xy;
 
710
        }
 
711
    } else {
 
712
        if (xy < psize.y / psize.x) {
 
713
            vsize.y = psize.x * 300;
 
714
            vsize.x = vsize.y * xy;
 
715
        } else {
 
716
            vsize.x = psize.y * 300;
 
717
            vsize.y = vsize.x / xy;
 
718
        }
 
719
    }
 
720
    if (~((pscanvas = createwidget (-1, [
 
721
        'type'   = 'ps';
 
722
        'origin' = ['x' = 0; 'y' = 0;];
 
723
        'size'   = vsize;
 
724
        'mode'   = mode;
 
725
        'name'   = name;
 
726
    ])) >= 0)) {
 
727
        dotty.message (0, 'cannot open printer device');
 
728
        return;
 
729
    }
 
730
    for (cname in vt.colors) {
 
731
        cid = vt.colors[cname];
 
732
        if (setwidgetattr (pscanvas, ['color' = [cid = cname;];]) ~= 1) {
 
733
            t = split (cname, ' ');
 
734
            if (tablesize (t) ~= 3 |
 
735
                    setwidgetattr (pscanvas, ['color' = [cid = [
 
736
                        'h' = ston (t[0]); 's' = ston (t[1]); 'v' = ston (t[2]);
 
737
                    ];];]) ~= 1) {
 
738
                dotty.message (0, concat ('unknown color ',
 
739
                        cname, ' using #1'));
 
740
            }
 
741
        }
 
742
    }
 
743
    setwidgetattr (pscanvas, ['window' = wrect;]);
 
744
    graph = copy (gt.graph);
 
745
    canvas = vt.canvas;
 
746
    vt.canvas = pscanvas;
 
747
    edgehandles = gt.edgehandles;
 
748
    gt.edgehandles = 0;
 
749
    fontmap = dotty.maps[getenv ('LEFTYWINSYS')].psfontmap;
 
750
    for (eid in graph.edges) {
 
751
        edge = graph.edges[eid];
 
752
        edge.fontname = fontmap[edge.attr.fontname];
 
753
        gt.drawedge (gt, [0 = vt;], edge);
 
754
    }
 
755
    for (nid in graph.nodes) {
 
756
        node = graph.nodes[nid];
 
757
        node.fontname = fontmap[node.attr.fontname];
 
758
        gt.drawnode (gt, [0 = vt;], node);
 
759
    }
 
760
    for (gid in graph.graphs) {
 
761
        sgraph = graph.graphs[gid];
 
762
        sgraph.fontname = fontmap[sgraph.graphattr.fontname];
 
763
        gt.drawsgraph (gt, [0 = vt;], sgraph);
 
764
    }
 
765
    gt.edgehandles = edgehandles;
 
766
    vt.canvas = canvas;
 
767
    destroywidget (pscanvas);
 
768
    if (otype == 'printer' & getenv ('LEFTYWINSYS') ~= 'mswin')
 
769
        system (concat (pr, ' /tmp/dottyout.ps; rm /tmp/dottyout.ps'));
 
770
};