1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
/*************************************************************************
* Copyright (c) 2011 AT&T Intellectual Property
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Details at https://graphviz.org
*************************************************************************/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <util/alloc.h>
#include <util/unreachable.h>
#include "tcldot.h"
// Agiddisc functions
static void *myiddisc_open(Agraph_t *g, Agdisc_t *disc) {
ictx_t *const ictx = (ictx_t *)((char *)disc - offsetof(ictx_t, mydisc));
gctx_t *const gctx = gv_alloc(sizeof(gctx_t));
gctx->g = g;
gctx->ictx = ictx;
return gctx;
}
static long myiddisc_map(void *state, int objtype, char *str, uint64_t *id, int createflag) {
(void)objtype;
gctx_t *gctx = state;
ictx_t *ictx = gctx->ictx;
char *s;
if (str) {
if (createflag)
s = agstrdup(gctx->g, str);
else
s = agstrbind(gctx->g, str);
*id = (uint64_t)(uintptr_t)s;
} else {
*id = ictx->ctr; /* counter maintained in per-interp space, so that
ids are unique across all graphs in the interp */
ictx->ctr += 2;
}
return 1;
}
static void myiddisc_free(void *state, int objtype, uint64_t id) {
(void)objtype;
gctx_t *gctx = state;
/* FIXME no obj* available
ictx_t *ictx = gctx->ictx;
char buf[32] = "";
switch (objtype) {
case AGRAPH: sprintf(buf,"graph%lu",id); break;
case AGNODE: sprintf(buf,"node%lu",id); break;
case AGINEDGE:
case AGOUTEDGE: sprintf(buf,"edge%lu",id); break;
}
Tcl_DeleteCommand(ictx->interp, buf);
*/
if (id % 2 == 0)
agstrfree(gctx->g, (char *)(uintptr_t)id, false);
}
static char *myiddisc_print(void *state, int objtype, uint64_t id) {
(void)state;
(void)objtype;
if (id % 2 == 0)
return (char *)(uintptr_t)id;
else
return "";
}
static void myiddisc_idregister(void *state, int objtype, void *obj) {
gctx_t *gctx = state;
ictx_t *ictx = gctx->ictx;
Tcl_Interp *interp = ictx->interp;
Tcl_CmdProc *proc = NULL;
switch (objtype) {
case AGRAPH: proc=graphcmd; break;
case AGNODE: proc=nodecmd; break;
case AGINEDGE:
case AGOUTEDGE: proc=edgecmd; break;
default: UNREACHABLE();
}
Tcl_CreateCommand(interp, obj2cmd(obj), proc, (ClientData) gctx, NULL);
}
Agiddisc_t myiddisc = {
myiddisc_open,
myiddisc_map,
myiddisc_free,
myiddisc_print,
free,
myiddisc_idregister
};
|