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

« back to all changes in this revision

Viewing changes to tcldgr/dgrutil.c

  • 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
 * Tcl extension for Dynamic Graphs by John Ellson (ellson@lucent.com)
 
3
 * 
 
4
 * Builds on libagraph by Stephen North (north@research.att.com)
 
5
 */
 
6
 
 
7
#include "dgr.h"
 
8
 
 
9
#ifdef DMALLOC
 
10
#include "dmalloc.h"
 
11
#endif
 
12
 
 
13
char * 
 
14
graph_to_handle(Agraph_t * g, char * buf)
 
15
{
 
16
        sprintf(buf, "dgG%lu", AGID(g));
 
17
        return buf;
 
18
}
 
19
 
 
20
char * 
 
21
edge_to_handle(Agedge_t * e, char * buf)
 
22
{
 
23
        sprintf(buf, "dgE%lu", AGID(e));
 
24
        return buf;
 
25
}
 
26
 
 
27
char * 
 
28
node_to_handle(Agnode_t * n, char * buf)
 
29
{
 
30
        sprintf(buf, "dgN%lu", AGID(n));
 
31
        return buf;
 
32
}
 
33
 
 
34
dgGraph_t * 
 
35
handle_to_graph(dgrInterp_t *dg, char *s)
 
36
{
 
37
        unsigned long           i;
 
38
        dgGraph_t  *g;
 
39
 
 
40
        if ((sscanf(s, "dgG%lu", &i)) != 1) {
 
41
                return NULL;
 
42
        }
 
43
        if (!(g = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, i))) {
 
44
                return NULL;
 
45
        }
 
46
        return g;
 
47
}
 
48
 
 
49
Agedge_t * 
 
50
handle_to_edge(dgrInterp_t *dg, char *s)
 
51
{
 
52
        unsigned long      i;
 
53
        Agedge_t  **ep;
 
54
 
 
55
        if ((sscanf(s, "dgE%lu", &i)) != 1)
 
56
                return NULL;
 
57
        if (!(ep = (Agedge_t **)tclhandleXlateIndex(dg->edgeTable, i)))
 
58
                return NULL;
 
59
        return *ep;
 
60
}
 
61
 
 
62
Agnode_t * 
 
63
handle_to_node(dgrInterp_t *dg, char *s)
 
64
{
 
65
        unsigned long      i;
 
66
        Agnode_t  **np;
 
67
 
 
68
        if ((sscanf(s, "dgN%lu", &i)) != 1)
 
69
                return NULL;
 
70
        if (!(np = (Agnode_t **)tclhandleXlateIndex(dg->nodeTable, i)))
 
71
                return NULL;
 
72
        return *np;
 
73
}
 
74
 
 
75
int 
 
76
attributematch(Tcl_Interp *interp, Agobj_t *obj, int argc, char **argv)
 
77
{
 
78
    int i = 0, j = 0;
 
79
    Agsym_t *sym;
 
80
    char buf[16], *val;
 
81
 
 
82
    if (argc % 2 ) {
 
83
        Tcl_AppendResult(interp, "invalid attribute pattern, should be \"",
 
84
            "?attributename attributevaluepattern? ...\"",
 
85
            (char *) NULL);
 
86
        return TCL_ERROR;;
 
87
    }
 
88
    while (i<argc) {
 
89
        if (!(sym = (Agsym_t *) agattrsym(obj, argv[i]))) {
 
90
            Tcl_AppendResult(interp, " No attribute named \"",
 
91
                argv[i], "\"", (char *) 0);
 
92
            return TCL_ERROR;
 
93
        }
 
94
        i++;
 
95
                val = agxget(obj, sym);
 
96
                if (!val) val = sym->defval;
 
97
        if (Tcl_StringMatch(val, argv[i])) {
 
98
            j = 1;
 
99
            break;
 
100
        }
 
101
        i++;
 
102
    }
 
103
    if (j || !argc) {
 
104
        switch (AGTYPE(obj)) {
 
105
            case AGRAPH: graph_to_handle((Agraph_t *)obj, buf); break;
 
106
            case AGNODE: node_to_handle((Agnode_t *)obj, buf); break;
 
107
            case AGINEDGE: case AGOUTEDGE: edge_to_handle((Agedge_t *)obj, buf); break;
 
108
            default: {
 
109
                Tcl_AppendResult(interp,
 
110
                    "invalid object tag (internal error)", (char *)NULL);
 
111
                return TCL_ERROR;
 
112
            }
 
113
        }
 
114
        Tcl_AppendElement(interp, buf);
 
115
    }
 
116
    return TCL_OK;
 
117
}
 
118
 
 
119
/********************************************************************/
 
120
/* evaluate bindings after % substitutions                                                */
 
121
 
 
122
char *
 
123
dgrExpandPercentsEval(
 
124
        Tcl_Interp * interp,     /* interpreter context */
 
125
        register char *before,   /* Command with percent expressions */
 
126
        char *g,         /* graphHandle string to substitute for "%g" */
 
127
        char *n,         /* nodeHandle string to substitute for "%n"
 
128
                                        or tailnode in insert_edge
 
129
                                        or "node" in modify_graph */
 
130
        char *e,         /* edgeHandle string to substitute for "%e"
 
131
                                        or "edge" in modify_graph */
 
132
        char *A,         /* attributeName/Value list for inserts or modifies
 
133
                                        or headnode in insert_edge */
 
134
        char *a          /* attributeName for modify
 
135
                                        or arglist string to substitute for "%a" */
 
136
)
 
137
{
 
138
        register char  *string;
 
139
        Tcl_DString      scripts;
 
140
                                
 
141
        Tcl_DStringInit(&scripts);
 
142
        while (1) {
 
143
                /*
 
144
                * Find everything up to the next % character and append it to the
 
145
                * result string.
 
146
                */
 
147
 
 
148
                for (string = before; (*string != 0) && (*string != '%'); string++) {
 
149
                        /* Empty loop body. */
 
150
                }
 
151
                if (string != before) {
 
152
                        Tcl_DStringAppend(&scripts, before, string - before);
 
153
                        before = string;
 
154
                }
 
155
                if (*before == 0) {
 
156
                        break;
 
157
                }
 
158
                /*
 
159
                * There's a percent sequence here.  Process it.
 
160
                */
 
161
        
 
162
                switch (before[1]) {
 
163
                case 'g':
 
164
                        Tcl_DStringAppend(&scripts, g, strlen(g));      /* graphHandle */
 
165
                        break;
 
166
                case 'n':
 
167
                case 't':
 
168
                        Tcl_DStringAppend(&scripts, n, strlen(n));      /* nodeHandle */
 
169
                        break;
 
170
                case 'e':
 
171
                        Tcl_DStringAppend(&scripts, e, strlen(e));      /* edgeHandle */
 
172
                        break;
 
173
                case 'A':
 
174
                case 'h':
 
175
                        Tcl_DStringAppend(&scripts, A, strlen(A));      /* attributeName */
 
176
                        break;
 
177
                case 'a':
 
178
                        Tcl_DStringAppend(&scripts, a, strlen(a)); /* attributeValue */
 
179
                        break;
 
180
                default:
 
181
                        Tcl_DStringAppend(&scripts, before+1, 1);
 
182
                        break;
 
183
                }
 
184
                before += 2;
 
185
        }
 
186
        if (Tcl_GlobalEval(interp, Tcl_DStringValue(&scripts)) != TCL_OK)
 
187
                fprintf(stderr, "%s while in binding: %s\n\n",
 
188
                        interp->result, Tcl_DStringValue(&scripts));
 
189
        Tcl_DStringFree(&scripts);
 
190
        return interp->result;
 
191
}
 
192
 
 
193
static void 
 
194
insert_graph_cb(Agobj_t *obj, void *arg)
 
195
{
 
196
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
197
        char            gbuf[16];
 
198
        dgGraph_t         *gp;
 
199
 
 
200
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable,
 
201
                        AGID(agroot((Agraph_t *)obj)));
 
202
        if (gp->insert_graph_cmd) {
 
203
                dgrExpandPercentsEval(dg->interp, gp->insert_graph_cmd,
 
204
                        graph_to_handle((Agraph_t *)obj, gbuf),
 
205
                        "", "", "", "");
 
206
        }
 
207
}
 
208
 
 
209
static void
 
210
insert_node_cb(Agobj_t *obj, void *arg)
 
211
{
 
212
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
213
        char            gbuf[16], nbuf[16];
 
214
        Agraph_t           *g;
 
215
        dgGraph_t         *gp;
 
216
 
 
217
        g = agraphof((Agnode_t *)obj);
 
218
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, AGID(agroot(g)));
 
219
        if (gp->insert_node_cmd) {
 
220
                dgrExpandPercentsEval(dg->interp, gp->insert_node_cmd,
 
221
                        graph_to_handle(g, gbuf),
 
222
                        node_to_handle((Agnode_t *)obj, nbuf),
 
223
                        "", "", "");
 
224
        }
 
225
}
 
226
 
 
227
static void
 
228
insert_edge_cb(Agobj_t *obj, void *arg)
 
229
{
 
230
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
231
        char            gbuf[16], ebuf[16], tbuf[16], hbuf[16];
 
232
        Agraph_t           *g;
 
233
        dgGraph_t         *gp;
 
234
 
 
235
        g = agraphof((Agedge_t *)obj);
 
236
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, AGID(agroot(g)));
 
237
        if (gp->insert_edge_cmd) {
 
238
                dgrExpandPercentsEval(dg->interp, gp->insert_edge_cmd,
 
239
                        graph_to_handle(g, gbuf),
 
240
                        node_to_handle(agtail((Agedge_t *)obj), tbuf),
 
241
                        edge_to_handle((Agedge_t *)obj, ebuf),
 
242
                        node_to_handle(aghead((Agedge_t *)obj), hbuf),
 
243
                        "");
 
244
        }
 
245
}
 
246
 
 
247
static void
 
248
delete_graph_cb(Agobj_t *obj, void *arg)
 
249
{
 
250
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
251
        char            gbuf[16];
 
252
        dgGraph_t         *gp;
 
253
 
 
254
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, 
 
255
                        AGID(agroot((Agraph_t *)obj)));
 
256
        if (gp->delete_graph_cmd) {
 
257
                dgrExpandPercentsEval(dg->interp, gp->delete_graph_cmd,
 
258
                        graph_to_handle((Agraph_t *)obj, gbuf),
 
259
                        "", "", "", "");
 
260
        }
 
261
}
 
262
 
 
263
static void
 
264
delete_node_cb(Agobj_t *obj, void *arg)
 
265
{
 
266
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
267
        char            gbuf[16], nbuf[16];
 
268
        Agraph_t           *g;
 
269
        dgGraph_t         *gp;
 
270
 
 
271
        g = agraphof((Agnode_t *)obj);
 
272
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, AGID(agroot(g)));
 
273
        if (gp->delete_node_cmd) {
 
274
                dgrExpandPercentsEval(dg->interp, gp->delete_node_cmd,
 
275
                        graph_to_handle(g, gbuf),
 
276
                        node_to_handle((Agnode_t *)obj, nbuf), 
 
277
                        "", "", "");
 
278
        }
 
279
}
 
280
 
 
281
static void
 
282
delete_edge_cb(Agobj_t *obj, void *arg)
 
283
{
 
284
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
285
        char            gbuf[16], ebuf[16];
 
286
        Agraph_t           *g;
 
287
        dgGraph_t         *gp;
 
288
 
 
289
        g = agraphof((Agedge_t *)obj);
 
290
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, AGID(agroot(g)));
 
291
        if (gp->delete_edge_cmd) {
 
292
                dgrExpandPercentsEval(dg->interp, gp->delete_edge_cmd,
 
293
                        graph_to_handle(g, gbuf),
 
294
                        "", edge_to_handle((Agedge_t *)obj, ebuf),
 
295
                        "", "");
 
296
        }
 
297
}
 
298
 
 
299
static void
 
300
modify_graph_cb(Agobj_t *obj, void *arg, Agsym_t *sym)
 
301
{
 
302
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
303
        char            gbuf[16], *val, *node="", *edge="";
 
304
        dgGraph_t         *gp;
 
305
 
 
306
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, 
 
307
                        AGID(agroot((Agraph_t *)obj)));
 
308
        if (gp->modify_graph_cmd) {
 
309
                assert(sym);
 
310
                val = agxget((Agraph_t *)obj, sym);
 
311
                if (!val) val = sym->defval;
 
312
                if (sym->kind == AGNODE) node = "node";
 
313
                if (sym->kind == AGINEDGE || sym->kind == AGOUTEDGE) edge = "edge";
 
314
                dgrExpandPercentsEval(dg->interp, gp->modify_graph_cmd,
 
315
                        graph_to_handle((Agraph_t *)obj, gbuf),
 
316
                        node, edge, sym->name, val);
 
317
        }
 
318
}
 
319
 
 
320
static void
 
321
modify_node_cb(Agobj_t *obj, void *arg, Agsym_t *sym)
 
322
{
 
323
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
324
        char            gbuf[16], nbuf[16], *val;
 
325
        Agraph_t           *g;
 
326
        dgGraph_t         *gp;
 
327
 
 
328
        g = agraphof((Agnode_t *)obj);
 
329
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, AGID(agroot(g)));
 
330
        if (gp->modify_node_cmd) {
 
331
                val = agxget((Agnode_t *)obj, sym);
 
332
                if (!val) val = sym->defval;
 
333
                dgrExpandPercentsEval(dg->interp, gp->modify_node_cmd,
 
334
                        graph_to_handle(g, gbuf),
 
335
                        node_to_handle((Agnode_t *)obj, nbuf), "", sym->name, val);
 
336
        }
 
337
}
 
338
 
 
339
static void
 
340
modify_edge_cb(Agobj_t *obj, void *arg, Agsym_t *sym)
 
341
{
 
342
        dgrInterp_t *dg = (dgrInterp_t *)arg;
 
343
        char            gbuf[16], ebuf[16], *val;
 
344
        Agraph_t           *g;
 
345
        dgGraph_t         *gp;
 
346
 
 
347
        g = agraphof((Agedge_t *)obj);
 
348
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, AGID(agroot(g)));
 
349
        if (gp->modify_edge_cmd) {
 
350
                val = agxget((Agedge_t *)obj, sym);
 
351
                if (!val) val = sym->defval;
 
352
                dgrExpandPercentsEval(dg->interp, gp->modify_edge_cmd,
 
353
                        graph_to_handle(g, gbuf),
 
354
                        "", edge_to_handle((Agedge_t *)obj, ebuf), sym->name, val);
 
355
        }
 
356
}
 
357
 
 
358
void
 
359
deleteEdges(dgrInterp_t *dg, Agnode_t * n)
 
360
{
 
361
        char            ebuf[16];
 
362
        Agedge_t           *e, *prev_e;
 
363
 
 
364
        e = agfstedge(n);
 
365
        while (e) {
 
366
                prev_e = e;
 
367
                edge_to_handle(prev_e, ebuf);
 
368
                e = agnxtedge(prev_e, n);
 
369
                agdeledge(prev_e);
 
370
                if (dg->object_commands) {
 
371
                        Tcl_DeleteCommand(dg->interp, ebuf);
 
372
                }
 
373
        }
 
374
}
 
375
 
 
376
void
 
377
deleteNodes(dgrInterp_t *dg, Agraph_t * g)
 
378
{
 
379
        Agnode_t           *n, *prev_n;
 
380
        char            nbuf[16];
 
381
 
 
382
        n = agfstnode(g);
 
383
        while (n) {
 
384
                prev_n = n;
 
385
                deleteEdges(dg, prev_n);
 
386
                node_to_handle(prev_n, nbuf);
 
387
                n = agnxtnode(prev_n);
 
388
                agdelnode(prev_n);
 
389
                if (dg->object_commands) {
 
390
                        Tcl_DeleteCommand(dg->interp, nbuf);
 
391
                }
 
392
        }
 
393
}
 
394
 
 
395
/* recursively delete subgraphs */
 
396
void
 
397
deleteSubgraphs(dgrInterp_t *dg, Agraph_t * g)
 
398
{
 
399
        Agraph_t           *sg, *prev_sg;
 
400
        char            gbuf[16];
 
401
 
 
402
        sg = agfstsubg(g);
 
403
        while (sg) {
 
404
                prev_sg = sg;
 
405
                deleteSubgraphs(dg, sg);
 
406
                graph_to_handle(sg, gbuf);
 
407
                sg = agnxtsubg(prev_sg);
 
408
                agclose(prev_sg);
 
409
                if (dg->object_commands) {
 
410
                        Tcl_DeleteCommand(dg->interp, gbuf);
 
411
                }
 
412
        }
 
413
}
 
414
 
 
415
/* recursively register all subgraphs as tcl commands */
 
416
static void
 
417
registerSubgraphs(dgrInterp_t *dg, Agraph_t *g)
 
418
{
 
419
        Agraph_t           *sg;
 
420
        char                    gbuf[16];
 
421
 
 
422
        for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) {
 
423
                Tcl_CreateCommand(dg->interp, graph_to_handle(sg, gbuf),
 
424
                        graphcmd, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
 
425
                registerSubgraphs(dg, sg);
 
426
        }
 
427
}
 
428
 
 
429
void dg_gpstruct_init (dgrInterp_t *dg, Agraph_t *g)  {
 
430
        char gbuf[16];
 
431
        dgGraph_t       *gp;
 
432
 
 
433
    gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable, AGID(g));
 
434
    gp->g = g;
 
435
    gp->callbacks_enabled = TRUE;
 
436
    gp->batch_cmd = (char *) NULL;
 
437
    gp->insert_graph_cmd = (char *) NULL;
 
438
    gp->modify_graph_cmd = (char *) NULL;
 
439
    gp->delete_graph_cmd = (char *) NULL;
 
440
    gp->insert_node_cmd = (char *) NULL;
 
441
    gp->modify_node_cmd = (char *) NULL;
 
442
    gp->delete_node_cmd = (char *) NULL;
 
443
    gp->insert_edge_cmd = (char *) NULL;
 
444
    gp->modify_edge_cmd = (char *) NULL;
 
445
    gp->delete_edge_cmd = (char *) NULL;
 
446
    agpushdisc(g, &gcbdisc, (void *)dg);
 
447
    graph_to_handle(g, gbuf);
 
448
    if (dg->object_commands) {
 
449
        Tcl_CreateCommand(dg->interp, gbuf, graphcmd, (ClientData) dg,
 
450
            (Tcl_CmdDeleteProc *) NULL);
 
451
        }
 
452
        Tcl_AppendResult(dg->interp, gbuf, (char *) NULL);
 
453
}
 
454
 
 
455
void dg_gpfromdot_init (dgrInterp_t *dg, Agraph_t *g) {
 
456
        char buf[16];
 
457
        Agnode_t *n, **np;
 
458
        Agedge_t *e, **ep;
 
459
 
 
460
        if (dg->object_commands) {
 
461
        for (n = agfstnode(g); n; n = agnxtnode(n)) {
 
462
                np = (Agnode_t **)tclhandleXlateIndex(dg->nodeTable, AGID(n));
 
463
                *np = n;
 
464
                Tcl_CreateCommand(dg->interp, node_to_handle(n, buf),
 
465
                nodecmd, (ClientData)dg, (Tcl_CmdDeleteProc *) NULL);
 
466
                for (e = agfstout(n); e; e = agnxtout(e)) {
 
467
                ep = (Agedge_t **)tclhandleXlateIndex(dg->edgeTable, AGID(e));
 
468
                *ep = e;
 
469
                Tcl_CreateCommand(dg->interp, edge_to_handle(e, buf),
 
470
                        edgecmd, (ClientData)dg, (Tcl_CmdDeleteProc *) NULL);
 
471
                }
 
472
        }
 
473
                registerSubgraphs(dg, g);
 
474
        }
 
475
        else {
 
476
        for (n = agfstnode(g); n; n = agnxtnode(n)) {
 
477
                np = (Agnode_t **)tclhandleXlateIndex(dg->nodeTable, AGID(n));
 
478
                *np = n;
 
479
                for (e = agfstout(n); e; e = agnxtout(e)) {
 
480
                ep = (Agedge_t **)tclhandleXlateIndex(dg->edgeTable, AGID(e));
 
481
                *ep = e;
 
482
                }
 
483
        }
 
484
        }
 
485
}
 
486
 
 
487
/********************************************************************/
 
488
/* event batching                                                   */
 
489
 
 
490
int dgrCallbacks (dgrInterp_t *dg, Agraph_t *g, int flag) {
 
491
        char            gbuf[16];
 
492
        dgGraph_t       *gp;
 
493
 
 
494
        gp = (dgGraph_t *)tclhandleXlateIndex(dg->graphTable,AGID(agroot(g)));
 
495
        if (gp->callbacks_enabled) {
 
496
                if (! flag) {
 
497
                        gp->callbacks_enabled = FALSE;
 
498
                agcallbacks(g, FALSE);
 
499
                }
 
500
                return TRUE;
 
501
        }
 
502
        if (flag) { /* && NOT gp->callbacks_enabled */
 
503
                if (gp->batch_cmd) {
 
504
                        dgrExpandPercentsEval(dg->interp, gp->batch_cmd,
 
505
                                graph_to_handle(g, gbuf),"", "", "", "1");
 
506
                }   
 
507
                agcallbacks(g, TRUE);
 
508
                if (gp->batch_cmd) {
 
509
                        dgrExpandPercentsEval(dg->interp, gp->batch_cmd,
 
510
                                graph_to_handle(g, gbuf),"", "", "", "0");
 
511
                }   
 
512
                gp->callbacks_enabled = TRUE;
 
513
        }   
 
514
        return FALSE;
 
515
}
 
516
 
 
517
/********************************************************************/
 
518
/* id discipline                                                                                                        */
 
519
 
 
520
static void * 
 
521
dgidopen(Agraph_t *g)
 
522
{
 
523
/* This is taken care of in Tcldg_Init */
 
524
        return (void *) NULL;
 
525
}
 
526
 
 
527
static long 
 
528
dgidmap(void *state, int objtype, char *str, unsigned long *id, int createflag)
 
529
{
 
530
        /* tcldg doesn't support string names in handle table */
 
531
        if (str) return FALSE;
 
532
 
 
533
        if (createflag) {
 
534
                switch (objtype) {
 
535
                        case AGRAPH:
 
536
                                return (long)tclhandleAlloc(dgrInterp.graphTable, (char *)NULL, id);
 
537
                        case AGNODE:
 
538
                                return (long)tclhandleAlloc(dgrInterp.nodeTable, (char *)NULL, id);
 
539
                        case AGINEDGE:
 
540
                        case AGOUTEDGE:
 
541
                                return (long)tclhandleAlloc(dgrInterp.edgeTable, (char *)NULL, id);
 
542
                }
 
543
        }
 
544
        else {
 
545
                switch (objtype) {
 
546
                        case AGRAPH:
 
547
                                return (long)tclhandleXlateIndex(dgrInterp.graphTable, *id);
 
548
                        case AGNODE:
 
549
                                return (long)tclhandleXlateIndex(dgrInterp.nodeTable, *id);
 
550
                        case AGINEDGE:
 
551
                        case AGOUTEDGE:
 
552
                                return (long)tclhandleXlateIndex(dgrInterp.edgeTable, *id);
 
553
                }
 
554
        }
 
555
        return FALSE;
 
556
}
 
557
 
 
558
static long 
 
559
dgidalloc(void *state, int objtype, unsigned long id)
 
560
{
 
561
        /* id should already be allocated by map.  check only. */
 
562
        switch (objtype) {
 
563
                case AGRAPH:
 
564
                        return (long)tclhandleXlateIndex(dgrInterp.graphTable, id);
 
565
                case AGNODE:
 
566
                        return (long)tclhandleXlateIndex(dgrInterp.nodeTable, id);
 
567
                case AGINEDGE:
 
568
                case AGOUTEDGE:
 
569
                        return (long)tclhandleXlateIndex(dgrInterp.edgeTable, id);
 
570
        }
 
571
        return FALSE;
 
572
}
 
573
 
 
574
static void 
 
575
dgidfree(void *state, int objtype, unsigned long id)
 
576
{
 
577
        void *rv = (void *)NULL;
 
578
 
 
579
        switch (objtype) {
 
580
                case AGRAPH:
 
581
                        rv = tclhandleFreeIndex(dgrInterp.graphTable, id);
 
582
                        break;
 
583
                case AGNODE:
 
584
                        rv = tclhandleFreeIndex(dgrInterp.nodeTable, id);
 
585
                        break;
 
586
                case AGINEDGE:
 
587
                case AGOUTEDGE:
 
588
                        rv = tclhandleFreeIndex(dgrInterp.edgeTable, id);
 
589
                        break;
 
590
                default:
 
591
                        rv = 0;
 
592
        }
 
593
        if (!rv) agerror(AGERROR_BADOBJ,"dgidfree");
 
594
}
 
595
 
 
596
static char * 
 
597
dgidprint(void *state, int objtype, unsigned long id)
 
598
{
 
599
/* we don't support string names in handle table */
 
600
        return (char *) NULL;
 
601
}
 
602
 
 
603
static void 
 
604
dgidclose(void *state)
 
605
{
 
606
/* Nothing to do in Tcldg */
 
607
}
 
608
 
 
609
Agiddisc_t iddisc = { dgidopen, dgidmap, dgidalloc,
 
610
                          dgidfree, dgidprint, dgidclose };
 
611
 
 
612
/********************************************************************/
 
613
/* io disciplines - files                                                                                       */
 
614
 
 
615
#ifdef TCL_CHANNELS
 
616
 
 
617
static int
 
618
fileiofread(void *chan, char *buf, int bufsize)
 
619
{
 
620
        return Tcl_Read((Tcl_Channel)chan, buf, bufsize);
 
621
}
 
622
 
 
623
static int 
 
624
fileioputstr(void *chan, char *str)
 
625
{
 
626
        return Tcl_Write((Tcl_Channel)chan, str, -1);
 
627
}
 
628
 
 
629
static int 
 
630
fileioflush(void *chan)
 
631
{
 
632
        return Tcl_Flush((Tcl_Channel)chan);
 
633
}
 
634
 
 
635
Agiodisc_t file_iodisc = {fileiofread, fileioputstr, fileioflush};
 
636
 
 
637
#else 
 
638
/* no TCL_CHANNELS so use libgraph default io routines */
 
639
 
 
640
Agiodisc_t file_iodisc = {NULL, NULL, NULL};
 
641
 
 
642
#endif
 
643
 
 
644
/********************************************************************/
 
645
/* io disciplines - strings                                                                                     */
 
646
 
 
647
static int
 
648
stringiofread(void *chan, char *buf, int bufsize)
 
649
{
 
650
        char *s = *(char **)chan;
 
651
        int len = strlen(s);
 
652
 
 
653
        strncpy(buf, s, bufsize);
 
654
        if (len>bufsize) {
 
655
                *(char **)chan += bufsize;
 
656
                return bufsize;
 
657
        } else {
 
658
                return len;
 
659
        }
 
660
}
 
661
 
 
662
static int 
 
663
stringioputstr(void *chan, char *str)
 
664
{
 
665
        int len = strlen(str);
 
666
 
 
667
        Tcl_DStringAppend((Tcl_DString *)chan, str, len);
 
668
        return len;
 
669
}
 
670
 
 
671
static int 
 
672
stringioflush(void *chan)
 
673
{
 
674
        return TCL_OK;
 
675
}
 
676
 
 
677
Agiodisc_t string_iodisc = {stringiofread, stringioputstr, stringioflush};
 
678
 
 
679
/********************************************************************/
 
680
 
 
681
char               *
 
682
buildBindings(char *s1, char *s2)
 
683
/*
 
684
 * previous binding in s1 binding to be added in s2 result in s3
 
685
 *
 
686
 * if s2 begins with + then append (separated by \n) else s2 replaces if
 
687
 * resultant string is null then bindings are deleted
 
688
 */
 
689
{
 
690
        char               *s3;
 
691
        int                      l;
 
692
 
 
693
        if (s2[0] == '+') {
 
694
                if (s1) {
 
695
                        l = strlen(s2) - 1;
 
696
                        if (l) {
 
697
                                s3 = Tcl_Alloc(strlen(s1) + l + 2);
 
698
                                assert (s3);
 
699
                                strcpy(s3, s1);
 
700
                                strcat(s3, "\n");
 
701
                                strcat(s3, s2 + 1);
 
702
                                Tcl_Free(s1);
 
703
                        } else {
 
704
                                s3 = s1;
 
705
                        }
 
706
                } else {
 
707
                        l = strlen(s2) - 1;
 
708
                        if (l) {
 
709
                                s3 = Tcl_Alloc(l + 2);
 
710
                                assert (s3);
 
711
                                strcpy(s3, s2 + 1);
 
712
                        } else {
 
713
                                s3 = (char *) NULL;
 
714
                        }
 
715
                }
 
716
        } else {
 
717
                if (s1)
 
718
                        Tcl_Free(s1);
 
719
                l = strlen(s2);
 
720
                if (l) {
 
721
                        s3 = Tcl_Alloc(l + 2);
 
722
                        assert (s3);
 
723
                        strcpy(s3, s2);
 
724
                } else {
 
725
                        s3 = (char *) NULL;
 
726
                }
 
727
        }
 
728
        return s3;
 
729
}
 
730
 
 
731
Agcbdisc_t gcbdisc = {
 
732
        {insert_graph_cb, modify_graph_cb, delete_graph_cb},
 
733
        {insert_node_cb, modify_node_cb, delete_node_cb},
 
734
        {insert_edge_cb, modify_edge_cb, delete_edge_cb}
 
735
};
 
736
 
 
737
Agdisc_t gdisc = {(Agmemdisc_t *)NULL, &iddisc, &file_iodisc};