]> granicus.if.org Git - graphviz/commitdiff
Make the tcl and swig stuff work with cgraph
authorEmden Gansner <erg@research.att.com>
Wed, 30 Nov 2011 22:29:15 +0000 (17:29 -0500)
committerEmden Gansner <erg@research.att.com>
Wed, 30 Nov 2011 22:29:15 +0000 (17:29 -0500)
tclpkg/gv/Makefile.am
tclpkg/gv/gv.cpp
tclpkg/gv/gv.i
tclpkg/tcldot/tcldot.c

index f724588294d3a88b9bb860fc0848f445343dd776..981e74b2a980901534bcf4749061c1a998bbd89c 100644 (file)
@@ -83,7 +83,7 @@ libgv_java_la_LDFLAGS = -module -avoid-version
 libgv_java_la_CPPFLAGS = $(BASECPPFLAGS) $(JAVA_INCLUDES)
 $(JAVA_data): gv_java.cpp
 gv_java.cpp: gv.i
-       $(SWIG) -package org.graphviz -c++ -java -o gv_java.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -package org.graphviz -c++ -java -o gv_java.cpp $(srcdir)/gv.i
 
 pkgluadir = $(pkglibdir)/lua
 LUA_data = 
@@ -94,7 +94,7 @@ libgv_lua_la_LDFLAGS = -module -avoid-version
 libgv_lua_la_CPPFLAGS = $(BASECPPFLAGS) $(LUA_INCLUDES)
 # $(LUA_data): gv_lua.cpp
 gv_lua.cpp: gv.i
-       $(SWIG) -c++ -lua -o gv_lua.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -lua -o gv_lua.cpp $(srcdir)/gv.i
        mv $@ $@.orig
        sed '/include/s/malloc\.h/cstdlib/' $@.orig > $@
 
@@ -110,7 +110,7 @@ libgv_ocaml_la_LDFLAGS = -module -avoid-version
 libgv_ocaml_la_CPPFLAGS = $(BASECPPFLAGS) $(OCAML_INCLUDES)
 gv.ml gv.mli: gv_ocaml.cpp
 gv_ocaml.cpp: gv.i
-       $(SWIG) -c++ -ocaml -o gv_ocaml.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -ocaml -o gv_ocaml.cpp $(srcdir)/gv.i
 swig.mli:
        $(SWIG) -ocaml -co swig.mli
 swig.ml:
@@ -145,7 +145,7 @@ libgv_perl_la_LDFLAGS = -module -avoid-version $(PERL_LD)
 libgv_perl_la_CPPFLAGS = $(BASECPPFLAGS) $(PERL_CC)
 $(PERL_data): gv_perl.cpp
 gv_perl.cpp: gv.i
-       $(SWIG) -c++ -perl -o gv_perl.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -perl -o gv_perl.cpp $(srcdir)/gv.i
 
 pkgphpdir = $(pkglibdir)/php
 PHP_data = gv.php
@@ -157,7 +157,7 @@ libgv_php_la_CPPFLAGS = $(BASECPPFLAGS) $(PHP_INCLUDES)
 gv.php: gv_php.cpp
 php_gv.h: gv_php.cpp
 gv_php.cpp: gv.i
-       $(SWIG) -c++ -php5 -o gv_php.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -php5 -o gv_php.cpp $(srcdir)/gv.i
 
 pkgpythondir = $(pkglibdir)/python
 PYTHON_data = gv.py
@@ -168,7 +168,7 @@ libgv_python_la_LDFLAGS = -module -avoid-version
 libgv_python_la_CPPFLAGS = $(BASECPPFLAGS) $(PYTHON_INCLUDES)
 $(PYTHON_data): gv_python.cpp
 gv_python.cpp: gv.i
-       $(SWIG) -c++ -python -o gv_python.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -python -o gv_python.cpp $(srcdir)/gv.i
 
 pkgpython23dir = $(pkglibdir)/python23
 PYTHON23_data = gv.py
@@ -179,7 +179,7 @@ libgv_python23_la_LDFLAGS = -module -avoid-version
 libgv_python23_la_CPPFLAGS = $(BASECPPFLAGS) $(PYTHON23_INCLUDES)
 # $(PYTHON23_data): gv_python23.cpp
 gv_python23.cpp: gv.i
-       $(SWIG) -c++ -python -classic -o gv_python23.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -python -classic -o gv_python23.cpp $(srcdir)/gv.i
 
 pkgpython24dir = $(pkglibdir)/python24
 PYTHON24_data = gv.py
@@ -190,7 +190,7 @@ libgv_python24_la_LDFLAGS = -module -avoid-version
 libgv_python24_la_CPPFLAGS = $(BASECPPFLAGS) $(PYTHON24_INCLUDES)
 # $(PYTHON24_data): gv_python24.cpp
 gv_python24.cpp: gv.i
-       $(SWIG) -c++ -python -classic -o gv_python24.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -python -classic -o gv_python24.cpp $(srcdir)/gv.i
 
 pkgpython25dir = $(pkglibdir)/python25
 PYTHON25_data = gv.py
@@ -201,7 +201,7 @@ libgv_python25_la_LDFLAGS = -module -avoid-version
 libgv_python25_la_CPPFLAGS = $(BASECPPFLAGS) $(PYTHON25_INCLUDES)
 # $(PYTHON25_data): gv_python25.cpp
 gv_python25.cpp: gv.i
-       $(SWIG) -c++ -python -classic -o gv_python25.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -python -classic -o gv_python25.cpp $(srcdir)/gv.i
 
 pkgpython26dir = $(pkglibdir)/python26
 PYTHON26_data = gv.py
@@ -212,7 +212,7 @@ libgv_python26_la_LDFLAGS = -module -avoid-version
 libgv_python26_la_CPPFLAGS = $(BASECPPFLAGS) $(PYTHON26_INCLUDES)
 # $(PYTHON26_data): gv_python26.cpp
 gv_python26.cpp: gv.i
-       $(SWIG) -c++ -python -o gv_python26.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -python -o gv_python26.cpp $(srcdir)/gv.i
 
 pkgpython27dir = $(pkglibdir)/python27
 PYTHON27_data = gv.py
@@ -223,7 +223,7 @@ libgv_python27_la_LDFLAGS = -module -avoid-version
 libgv_python27_la_CPPFLAGS = $(BASECPPFLAGS) $(PYTHON27_INCLUDES)
 # $(PYTHON27_data): gv_python27.cpp
 gv_python27.cpp: gv.i
-       $(SWIG) -c++ -python -o gv_python27.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -python -o gv_python27.cpp $(srcdir)/gv.i
 
 pkgRdir = $(pkglibdir)/R
 R_data = 
@@ -234,7 +234,7 @@ libgv_R_la_LDFLAGS = -module -avoid-version
 libgv_R_la_CPPFLAGS = $(BASECPPFLAGS) $(R_CFLAGS)
 # $(R_data): gv_R.cpp
 gv_R.cpp: gv.i
-       $(SWIG) -c++ -r -o gv_R.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -r -o gv_R.cpp $(srcdir)/gv.i
 
 pkgrubydir = $(pkglibdir)/ruby
 RUBY_data = 
@@ -245,7 +245,7 @@ libgv_ruby_la_LDFLAGS = -module -avoid-version
 libgv_ruby_la_CPPFLAGS = $(BASECPPFLAGS) $(RUBY_INCLUDES)
 # $(RUBY_data): gv_ruby.cpp
 gv_ruby.cpp: gv.i
-       $(SWIG) -c++ -ruby -o gv_ruby.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -ruby -o gv_ruby.cpp $(srcdir)/gv.i
 
 pkgtcldir = $(pkglibdir)/tcl
 TCL_data = 
@@ -256,7 +256,7 @@ libgv_tcl_la_LDFLAGS = -module -avoid-version
 libgv_tcl_la_CPPFLAGS = $(BASECPPFLAGS) $(TCL_INCLUDES)
 # $(TCL_data): gv_tcl.cpp
 gv_tcl.cpp: gv.i
-       $(SWIG) -c++ -tcl -namespace -o gv_tcl.cpp $(srcdir)/gv.i
+       $(SWIG) $(DEFS) -c++ -tcl -namespace -o gv_tcl.cpp $(srcdir)/gv.i
 
 pkginclude_DATA = gv.i gv.cpp
 pkglib_LTLIBRARIES = 
index 87b4d12c0e9b9e054beac42fa3f302dde2def8c8..f847874ef9656e7ba4e42cb64fa921851a9d31e1 100644 (file)
@@ -20,6 +20,13 @@ extern void gv_string_writer_init(GVC_t *gvc);
 extern void gv_channel_writer_init(GVC_t *gvc);
 }
 
+#ifdef WITH_CGRAPH
+#define agfindattr(x,s) agattrsym(x,s)
+#define agraphattr(g,n,s) agattr(g,AGRAPH,n,s)
+#define agnodeattr(g,n,s) agattr(g,AGNODE,n,s)
+#define agedgeattr(g,n,s) agattr(g,AGEDGE,n,s)
+#endif
+
 static char emptystring[] = {'\0'};
 
 static GVC_t *gvc;
@@ -33,28 +40,44 @@ Agraph_t *graph(char *name)
 {
     if (!gvc)
         gv_init();
+#ifdef WITH_CGRAPH
+    return agopen(name, Agundirected, 0);
+#else
     return agopen(name, AGRAPH);
+#endif
 }
 
 Agraph_t *digraph(char *name)
 {
     if (!gvc)
         gv_init();
+#ifdef WITH_CGRAPH
+    return agopen(name, Agdirected, 0);
+#else
     return agopen(name, AGDIGRAPH);
+#endif
 }
 
 Agraph_t *strictgraph(char *name)
 {
     if (!gvc)
         gv_init();
+#ifdef WITH_CGRAPH
+    return agopen(name, Agstrictundirected, 0);
+#else
     return agopen(name, AGRAPHSTRICT);
+#endif
 }
 
 Agraph_t *strictdigraph(char *name)
 {
     if (!gvc)
         gv_init();
+#ifdef WITH_CGRAPH
+    return agopen(name, Agstrictdirected, 0);
+#else
     return agopen(name, AGDIGRAPHSTRICT);
+#endif
 }
 
 Agraph_t *readstring(char *string)
@@ -68,7 +91,11 @@ Agraph_t *read(FILE *f)
 {
     if (!gvc)
         gv_init();
+#ifdef WITH_CGRAPH
+    return agread(f, NULL);
+#else
     return agread(f);
+#endif
 }
 
 Agraph_t *read(const char *filename)
@@ -81,7 +108,11 @@ Agraph_t *read(const char *filename)
         return NULL;
     if (!gvc)
         gv_init();
+#ifdef WITH_CGRAPH
+    g = agread(f, NULL);
+#else
     g = agread(f);
+#endif
     fclose(f);
     return g;
 }
@@ -91,7 +122,11 @@ Agraph_t *graph(Agraph_t *g, char *name)
 {
     if (!gvc)
         gv_init();
+#ifdef WITH_CGRAPH
+    return agsubg(g, name, 1);
+#else
     return agsubg(g, name);
+#endif
 }
 
 Agnode_t *node(Agraph_t *g, char *name)
@@ -99,7 +134,11 @@ Agnode_t *node(Agraph_t *g, char *name)
     // creating a protonode is not permitted
     if (!gvc || (name[0] == '\001' && strcmp (name, "\001proto") == 0))
         return NULL;
+#ifdef WITH_CGRAPH
+    return agnode(g, name, 1);
+#else
     return agnode(g, name);
+#endif
 }
 
 Agedge_t *edge(Agnode_t *t, Agnode_t *h)
@@ -109,19 +148,31 @@ Agedge_t *edge(Agnode_t *t, Agnode_t *h)
       || (agnameof(t)[0] == '\001' && strcmp (agnameof(t), "\001proto") == 0)
       || (agnameof(h)[0] == '\001' && strcmp (agnameof(h), "\001proto") == 0))
         return NULL;
+#ifdef WITH_CGRAPH
+    return agedge(agraphof(t), t, h, NULL, 1);
+#else
     return agedge(t->graph, t, h);
+#endif
 }
 
 // induce tail if necessary
 Agedge_t *edge(char *tname, Agnode_t *h)
 {
+#ifdef WITH_CGRAPH
+    return edge(node(agraphof(h), tname), h);
+#else
     return edge(node(h->graph, tname), h);
+#endif
 }
 
 // induce head if necessary
 Agedge_t *edge(Agnode_t *t, char *hname)
 {
+#ifdef WITH_CGRAPH
+    return edge(t, node(agraphof(t), hname));
+#else
     return edge(t, node(t->graph, hname));
+#endif
 }
 
 // induce tail/head if necessary
@@ -179,7 +230,11 @@ static void myagxset(void *obj, Agsym_t *a, char *val)
         if (val[len-1] == '>') {
             hs = strdup(val+1);
                 *(hs+len-2) = '\0';
+#ifdef WITH_CGRAPH
+            val = agstrdup_html(agraphof(obj),hs);
+#else
             val = agstrdup_html(hs);
+#endif
             free(hs);
         }
     }
@@ -221,7 +276,11 @@ char *getv(Agnode_t *n, char *attr)
     if (!n || !attr)
         return NULL;
     g = agroot(agraphof(n));
+#ifdef WITH_CGRAPH
+    a = agattr(g, AGNODE, attr, NULL);
+#else
     a = agfindattr(g->proto->n, attr);
+#endif
     return myagxget(n, a);
 }
 char *setv(Agnode_t *n, Agsym_t *a, char *val)
@@ -239,7 +298,11 @@ char *setv(Agnode_t *n, char *attr, char *val)
     if (!n || !attr || !val)
         return NULL;
     g = agroot(agraphof(n));
+#ifdef WITH_CGRAPH
+    a = agattr(g, AGNODE, attr, NULL);
+#else
     a = agfindattr(g->proto->n, attr);
+#endif
     if (!a)
         a = agnodeattr(g, attr, emptystring);
     myagxset(n, a, val);
@@ -388,6 +451,7 @@ Agraph_t *rootof(Agraph_t *g)
 }
 
 //-------------------------------------------------
+#ifndef WITH_CGRAPH
 Agnode_t *protonode(Agraph_t *g)
 {
     if (!g)
@@ -401,6 +465,7 @@ Agedge_t *protoedge(Agraph_t *g)
         return NULL;
     return g->proto->e;
 }
+#endif
 
 //-------------------------------------------------
 char *nameof(Agraph_t *g)
@@ -456,12 +521,17 @@ bool ok(Agsym_t *a)
 //-------------------------------------------------
 Agraph_t *firstsubg(Agraph_t *g)
 {
+#ifndef WITH_CGRAPH
     Agraph_t *mg;
     Agnode_t *n;
     Agedge_t *e;
+#endif
 
     if (!g)
         return NULL;
+#ifdef WITH_CGRAPH
+    return agfstsubg(g);
+#else
     n = g->meta_node;
     if (!n) 
         return NULL;
@@ -472,16 +542,22 @@ Agraph_t *firstsubg(Agraph_t *g)
     if (!e) 
         return NULL;
     return agusergraph(aghead(e));
+#endif
 }
 
 Agraph_t *nextsubg(Agraph_t *g, Agraph_t *sg)
 {
+#ifndef WITH_CGRAPH
     Agraph_t *mg;
     Agnode_t *ng, *nsg;
     Agedge_t *e;
+#endif
 
     if (!g || !sg)
         return NULL;
+#ifdef WITH_CGRAPH
+    return agnxtsubg(sg);
+#else
     ng = g->meta_node;
     nsg = sg->meta_node;
     if (!ng || !nsg) 
@@ -496,8 +572,20 @@ Agraph_t *nextsubg(Agraph_t *g, Agraph_t *sg)
     if (!e) 
         return NULL;
     return agusergraph(aghead(e));
+#endif
+}
+
+#ifdef WITH_CGRAPH
+Agraph_t *firstsupg(Agraph_t *g)
+{
+    return g->parent;
 }
 
+Agraph_t *nextsupg(Agraph_t *g, Agraph_t *sg)
+{
+    return NULL;
+}
+#else
 Agraph_t *firstsupg(Agraph_t *g)
 {
     Agraph_t *mg;
@@ -541,6 +629,7 @@ Agraph_t *nextsupg(Agraph_t *g, Agraph_t *sg)
         return NULL;
     return agusergraph(agtail(e));
 }
+#endif
 
 Agedge_t *firstout(Agraph_t *g)
 {
@@ -748,9 +837,13 @@ Agsym_t *firstattr(Agraph_t *g)
     if (!g)
         return NULL;
     g = agroot(g);
+#ifdef WITH_CGRAPH
+    return agnxtattr(g,AGRAPH,NULL);
+#else
     if (dtsize(g->univ->globattr->dict) == 0)
         return NULL;
     return g->univ->globattr->list[0];
+#endif
 }
 
 Agsym_t *nextattr(Agraph_t *g, Agsym_t *a)
@@ -760,6 +853,9 @@ Agsym_t *nextattr(Agraph_t *g, Agsym_t *a)
     if (!g || !a)
         return NULL;
     g = agroot(g);
+#ifdef WITH_CGRAPH
+    return agnxtattr(g,AGRAPH,a);
+#else
     for (i = 0; i < dtsize(g->univ->globattr->dict); i++)
         if (a == g->univ->globattr->list[i])
             break;
@@ -767,6 +863,7 @@ Agsym_t *nextattr(Agraph_t *g, Agsym_t *a)
     if (i > dtsize(g->univ->globattr->dict))
         return NULL;
     return g->univ->globattr->list[i];
+#endif
 }
 
 Agsym_t *firstattr(Agnode_t *n)
@@ -776,9 +873,13 @@ Agsym_t *firstattr(Agnode_t *n)
     if (!n)
         return NULL;
     g = agraphof(n);
+#ifdef WITH_CGRAPH
+    return agnxtattr(g,AGNODE,NULL);
+#else
     if (dtsize(g->univ->nodeattr->dict) == 0)
         return NULL;
     return g->univ->nodeattr->list[0];
+#endif
 }
 
 Agsym_t *nextattr(Agnode_t *n, Agsym_t *a)
@@ -789,6 +890,9 @@ Agsym_t *nextattr(Agnode_t *n, Agsym_t *a)
     if (!n || !a)
         return NULL;
     g = agraphof(n);
+#ifdef WITH_CGRAPH
+    return agnxtattr(g,AGNODE,a);
+#else
     for (i = 0; i < dtsize(g->univ->nodeattr->dict); i++)
         if (a == g->univ->nodeattr->list[i])
             break;
@@ -796,6 +900,7 @@ Agsym_t *nextattr(Agnode_t *n, Agsym_t *a)
     if (i > dtsize(g->univ->nodeattr->dict))
         return NULL;
     return g->univ->nodeattr->list[i];
+#endif
 }
 
 Agsym_t *firstattr(Agedge_t *e)
@@ -805,9 +910,13 @@ Agsym_t *firstattr(Agedge_t *e)
     if (!e)
         return NULL;
     g = agraphof(agtail(e));
+#ifdef WITH_CGRAPH
+    return agnxtattr(g,AGEDGE,NULL);
+#else
     if (dtsize(g->univ->edgeattr->dict) == 0)
         return NULL;
     return g->univ->edgeattr->list[0];
+#endif
 }
 
 Agsym_t *nextattr(Agedge_t *e, Agsym_t *a)
@@ -818,6 +927,9 @@ Agsym_t *nextattr(Agedge_t *e, Agsym_t *a)
     if (!e || !a)
         return NULL;
     g = agraphof(agtail(e));
+#ifdef WITH_CGRAPH
+    return agnxtattr(g,AGEDGE,a);
+#else
     for (i = 0; i < dtsize(g->univ->edgeattr->dict); i++)
         if (a == g->univ->edgeattr->list[i])
             break;
@@ -825,6 +937,7 @@ Agsym_t *nextattr(Agedge_t *e, Agsym_t *a)
     if (i > dtsize(g->univ->edgeattr->dict))
         return NULL;
     return g->univ->edgeattr->list[i];
+#endif
 }
 
 bool rm(Agraph_t *g)
@@ -833,6 +946,16 @@ bool rm(Agraph_t *g)
 
     if (!g)
         return false;
+#ifdef WITH_CGRAPH
+    Agraph_t* sg;
+    for (sg = agfstsubg (g); sg; sg = agnxtsubg (sg))
+       rm(sg);
+    if (g == agroot(g))
+       agclose(g);
+    else
+        agdelete(agroot(g), g);
+    return true;
+#else
     if (g->meta_node) {
         for (e = agfstout(g->meta_node->graph, g->meta_node); e;
                        e = agnxtout(g->meta_node->graph, e)) {
@@ -841,12 +964,13 @@ bool rm(Agraph_t *g)
         if (g == agroot(g)) {
             agclose(g);
         } else {
-            agdelete(g->meta_node->graph, g->meta_node);
+            agdelete(g->meta_node->graph, g);
         }
         return true;
     }
     fprintf(stderr, "subgraph has no meta_node\n");
     return false;
+#endif
 }
 
 bool rm(Agnode_t *n)
index 20b8ab4101e135e45e74505aff77e67b630d5153..fa80c78461e4000b18b70ae596be0316156939f5 100644 (file)
@@ -119,8 +119,10 @@ extern Agraph_t *graphof(Agnode_t *n);
 extern Agraph_t *rootof(Agraph_t *g);
 
 /** Obtain handles of proto node/edge for setting default attribute values */
+#ifndef WITH_CGRAPH
 extern Agnode_t *protonode(Agraph_t *g);
 extern Agedge_t *protoedge(Agraph_t *g);
+#endif
 
 /** Iterators */
 /*** Iteration termination tests */
@@ -299,8 +301,10 @@ extern Agraph_t *graphof(Agnode_t *n);
 extern Agraph_t *rootof(Agraph_t *g);
 
 /** Obtain handles of proto node/edge for setting default attribute values */
+#ifndef WITH_CGRAPH
 extern Agnode_t *protonode(Agraph_t *g);
 extern Agedge_t *protoedge(Agraph_t *g);
+#endif
 
 /** Iterators */
 /*** Iteration termination tests */
index d449324d55f7305891e2e2e3ad84174f5175c77b..6be52d960e3f5ec33742ad1c9ad98a2f8bbf40c0 100644 (file)
@@ -40,6 +40,10 @@ Tcl_GetString(Tcl_Obj *obj) {
 #endif
 ********* */
 
+#ifndef WITH_CGRAPH
+#define AGID(x) ((x)->handle)
+#endif
+
 #if HAVE_LIBGD
 extern void *GDHandleTable;
 extern int Gdtclft_Init(Tcl_Interp *);
@@ -75,12 +79,12 @@ static void deleteEdges(Tcl_Interp * interp, Agraph_t * g, Agnode_t * n)
 
     e = agfstedge(g, n);
     while (e) {
-       tclhandleString(edgeTblPtr, buf, e->handle);
+       tclhandleString(edgeTblPtr, buf, AGID(e));
        Tcl_DeleteCommand(interp, buf);
-       ep = (Agedge_t **) tclhandleXlateIndex(edgeTblPtr, e->handle);
+       ep = (Agedge_t **) tclhandleXlateIndex(edgeTblPtr, AGID(e));
        if (!ep)
            fprintf(stderr, "Bad entry in edgeTbl\n");
-       tclhandleFreeIndex(edgeTblPtr, e->handle);
+       tclhandleFreeIndex(edgeTblPtr, AGID(e));
        e1 = agnxtedge(g, e, n);
        agdelete(agroot(g), e);
        e = e1;
@@ -94,12 +98,12 @@ static void deleteNodes(Tcl_Interp * interp, Agraph_t * g)
 
     n = agfstnode(g);
     while (n) {
-       tclhandleString(nodeTblPtr, buf, n->handle);
+       tclhandleString(nodeTblPtr, buf, AGID(n));
        Tcl_DeleteCommand(interp, buf);
-       np = (Agnode_t **) tclhandleXlateIndex(nodeTblPtr, n->handle);
+       np = (Agnode_t **) tclhandleXlateIndex(nodeTblPtr, AGID(n));
        if (!np)
            fprintf(stderr, "Bad entry in nodeTbl\n");
-       tclhandleFreeIndex(nodeTblPtr, n->handle);
+       tclhandleFreeIndex(nodeTblPtr, AGID(n));
        deleteEdges(interp, agroot(g), n);
        n1 = agnxtnode(g, n);
        agdelete(agroot(g), n);
@@ -107,6 +111,29 @@ static void deleteNodes(Tcl_Interp * interp, Agraph_t * g)
     }
 }
 
+#ifdef WITH_CGRAPH
+static void deleteGraph(Tcl_Interp * interp, Agraph_t * g)
+{
+    Agraph_t **sgp;
+    Agraph_t *sg;
+    char buf[16];
+
+    for (sg = agfstsubg (g); sg; sg = agnxtsubg (sg)) {
+       deleteGraph(interp, sg);
+    }
+    tclhandleString(graphTblPtr, buf, AGID(g));
+    Tcl_DeleteCommand(interp, buf);
+    sgp = (Agraph_t **) tclhandleXlateIndex(graphTblPtr, AGID(g));
+    if (!sgp)
+       fprintf(stderr, "Bad entry in graphTbl\n");
+    tclhandleFreeIndex(graphTblPtr, AGID(g));
+    if (g == agroot(g)) {
+       agclose(g);
+    } else {
+       agdelsubg(agroot(g), g);
+    }
+}
+#else
 static void deleteGraph(Tcl_Interp * interp, Agraph_t * g)
 {
     Agraph_t **sgp;
@@ -118,12 +145,12 @@ static void deleteGraph(Tcl_Interp * interp, Agraph_t * g)
             e = agnxtout(g->meta_node->graph, e)) {
            deleteGraph(interp, agusergraph(aghead(e)));
        }
-       tclhandleString(graphTblPtr, buf, g->handle);
+       tclhandleString(graphTblPtr, buf, AGID(g));
        Tcl_DeleteCommand(interp, buf);
-       sgp = (Agraph_t **) tclhandleXlateIndex(graphTblPtr, g->handle);
+       sgp = (Agraph_t **) tclhandleXlateIndex(graphTblPtr, AGID(g));
        if (!sgp)
            fprintf(stderr, "Bad entry in graphTbl\n");
-       tclhandleFreeIndex(graphTblPtr, g->handle);
+       tclhandleFreeIndex(graphTblPtr, AGID(g));
        if (g == agroot(g)) {
            agclose(g);
        } else {
@@ -133,6 +160,7 @@ static void deleteGraph(Tcl_Interp * interp, Agraph_t * g)
        fprintf(stderr, "Subgraph has no meta_node\n");
     }
 }
+#endif
 
 static void setgraphattributes(Agraph_t * g, char *argv[], int argc)
 {
@@ -192,6 +220,61 @@ setnodeattributes(Agraph_t * g, Agnode_t * n, char *argv[], int argc)
     }
 }
 
+#ifdef WITH_CGRAPH
+static void listGraphAttrs (Tcl_Interp * interp, Agraph_t* g)
+{
+    Agsym_t *a = NULL;
+    while ((a = agnxtattr(g, AGRAPH, a))) {
+       Tcl_AppendElement(interp, a->name);
+    }
+}
+static void listNodeAttrs (Tcl_Interp * interp, Agraph_t* g)
+{
+    Agsym_t *a = NULL;
+    while ((a = agnxtattr(g, AGNODE, a))) {
+       Tcl_AppendElement(interp, a->name);
+    }
+}
+static void listEdgeAttrs (Tcl_Interp * interp, Agraph_t* g)
+{
+    Agsym_t *a = NULL;
+    while ((a = agnxtattr(g, AGEDGE, a))) {
+       Tcl_AppendElement(interp, a->name);
+    }
+}
+#else
+static void listGraphAttrs (Tcl_Interp * interp, Agraph_t* g)
+{
+    int i;
+    Agsym_t *a;
+
+    for (i = 0; i < dtsize(g->univ->globattr->dict); i++) {
+       a = g->univ->globattr->list[i];
+       Tcl_AppendElement(interp, a->name);
+    }
+}
+static void listNodeAttrs (Tcl_Interp * interp, Agraph_t* g)
+{
+    int i;
+    Agsym_t *a;
+
+    for (i = 0; i < dtsize(g->univ->nodeattr->dict); i++) {
+       a = g->univ->nodeattr->list[i];
+       Tcl_AppendElement(interp, a->name);
+    }
+}
+static void listEdgeAttrs (Tcl_Interp * interp, Agraph_t* g)
+{
+    int i;
+    Agsym_t *a;
+
+    for (i = 0; i < dtsize(g->univ->edgeattr->dict); i++) {
+       a = g->univ->edgeattr->list[i];
+       Tcl_AppendElement(interp, a->name);
+    }
+}
+#endif
+
 static int edgecmd(ClientData clientData, Tcl_Interp * interp,
 #ifndef TCLOBJ
                   int argc, char *argv[]
@@ -224,7 +307,7 @@ static int edgecmd(ClientData clientData, Tcl_Interp * interp,
     length = strlen(argv[1]);
 
     if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
-       tclhandleFreeIndex(edgeTblPtr, e->handle);
+       tclhandleFreeIndex(edgeTblPtr, AGID(e));
        Tcl_DeleteCommand(interp, argv[0]);
        agdelete(g, e);
        reset_layout(gvc, g);
@@ -232,16 +315,13 @@ static int edgecmd(ClientData clientData, Tcl_Interp * interp,
 
     } else if ((c == 'l')
               && (strncmp(argv[1], "listattributes", length) == 0)) {
-       for (i = 0; i < dtsize(g->univ->edgeattr->dict); i++) {
-           a = g->univ->edgeattr->list[i];
-           Tcl_AppendElement(interp, a->name);
-       }
+       listEdgeAttrs (interp, g);
        return TCL_OK;
 
     } else if ((c == 'l') && (strncmp(argv[1], "listnodes", length) == 0)) {
-       tclhandleString(nodeTblPtr, buf, agtail(e)->handle);
+       tclhandleString(nodeTblPtr, buf, AGID(agtail(e)));
        Tcl_AppendElement(interp, buf);
-       tclhandleString(nodeTblPtr, buf, aghead(e)->handle);
+       tclhandleString(nodeTblPtr, buf, AGID(aghead(e)));
        Tcl_AppendElement(interp, buf);
        return TCL_OK;
 
@@ -356,11 +436,8 @@ static int nodecmd(ClientData clientData, Tcl_Interp * interp,
     Agraph_t *g;
     Agnode_t **np, *n, *head;
     Agedge_t **ep, *e;
-#ifndef WITH_CGRAPH
     Agsym_t *a;
-#else
-    Agattr_t *a;
-#endif
+
     GVC_t *gvc = (GVC_t *) clientData;
 
     if (argc < 2) {
@@ -403,14 +480,18 @@ static int nodecmd(ClientData clientData, Tcl_Interp * interp,
                return TCL_ERROR;
            }
        }
+#ifdef WITH_CGRAPH
+       e = agedge(g, n, head, NULL, 1);
+#else
        e = agedge(g, n, head);
+#endif
        if (!
-           (ep = (Agedge_t **) tclhandleXlateIndex(edgeTblPtr, e->handle))
+           (ep = (Agedge_t **) tclhandleXlateIndex(edgeTblPtr, AGID(e)))
            || *ep != e) {
            ep = (Agedge_t **) tclhandleAlloc(edgeTblPtr, Tcl_GetStringResult(interp),
                                              &id);
            *ep = e;
-           e->handle = id;
+           AGID(e) = id;
 #ifndef TCLOBJ
            Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), edgecmd,
                              (ClientData) gvc,
@@ -421,7 +502,7 @@ static int nodecmd(ClientData clientData, Tcl_Interp * interp,
                                 (Tcl_CmdDeleteProc *) NULL);
 #endif                         /* TCLOBJ */
        } else {
-           tclhandleString(edgeTblPtr, Tcl_GetStringResult(interp), e->handle);
+           tclhandleString(edgeTblPtr, Tcl_GetStringResult(interp), AGID(e));
        }
        setedgeattributes(agroot(g), e, &argv[3], argc - 3);
        reset_layout(gvc, g);
@@ -429,7 +510,7 @@ static int nodecmd(ClientData clientData, Tcl_Interp * interp,
 
     } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
        deleteEdges(interp, g, n);
-       tclhandleFreeIndex(nodeTblPtr, n->handle);
+       tclhandleFreeIndex(nodeTblPtr, AGID(n));
        Tcl_DeleteCommand(interp, argv[0]);
        agdelete(g, n);
        reset_layout(gvc, g);
@@ -448,26 +529,23 @@ static int nodecmd(ClientData clientData, Tcl_Interp * interp,
            return TCL_ERROR;
        }
        if (!(e = agfindedge(g, n, head))) {
-           tclhandleString(nodeTblPtr, buf, head->handle);
+           tclhandleString(nodeTblPtr, buf, AGID(head));
            Tcl_AppendResult(interp, "Edge \"", argv[0],
                             " - ", buf, "\" not found.", NULL);
            return TCL_ERROR;
        }
-       tclhandleString(edgeTblPtr, buf, e->handle);
+       tclhandleString(edgeTblPtr, buf, AGID(e));
        Tcl_AppendElement(interp, buf);
        return TCL_OK;
 
     } else if ((c == 'l')
               && (strncmp(argv[1], "listattributes", length) == 0)) {
-       for (i = 0; i < dtsize(g->univ->nodeattr->dict); i++) {
-           a = g->univ->nodeattr->list[i];
-           Tcl_AppendElement(interp, a->name);
-       }
+       listNodeAttrs (interp, g);
        return TCL_OK;
 
     } else if ((c == 'l') && (strncmp(argv[1], "listedges", length) == 0)) {
        for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
-           tclhandleString(edgeTblPtr, buf, e->handle);
+           tclhandleString(edgeTblPtr, buf, AGID(e));
            Tcl_AppendElement(interp, buf);
        }
        return TCL_OK;
@@ -475,7 +553,7 @@ static int nodecmd(ClientData clientData, Tcl_Interp * interp,
     } else if ((c == 'l')
               && (strncmp(argv[1], "listinedges", length) == 0)) {
        for (e = agfstin(g, n); e; e = agnxtin(g, e)) {
-           tclhandleString(edgeTblPtr, buf, e->handle);
+           tclhandleString(edgeTblPtr, buf, AGID(e));
            Tcl_AppendElement(interp, buf);
        }
        return TCL_OK;
@@ -483,7 +561,7 @@ static int nodecmd(ClientData clientData, Tcl_Interp * interp,
     } else if ((c == 'l')
               && (strncmp(argv[1], "listoutedges", length) == 0)) {
        for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
-           tclhandleString(edgeTblPtr, buf, e->handle);
+           tclhandleString(edgeTblPtr, buf, AGID(e));
            Tcl_AppendElement(interp, buf);
        }
        return TCL_OK;
@@ -628,11 +706,13 @@ static void tcldot_layout(GVC_t *gvc, Agraph_t * g, char *engine)
        sprintf(buf, "%d %d %d %d",
                ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).LL.y),
                ROUND(GD_bb(g).UR.x), ROUND(GD_bb(g).UR.y));
+#ifndef WITH_CGRAPH
     if (!(a = agfindgraphattr(g, "bb"))) 
        a = agraphattr(g, "bb", "");
-#ifndef WITH_CGRAPH
     agxset(g, a->index, buf);
 #else
+    if (!(a = agattr(g, AGRAPH, "bb", NULL))) 
+       a = agattr(g, AGRAPH, "bb", "");
     agxset(g, a, buf);
 #endif
 }
@@ -707,14 +787,18 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
                return TCL_ERROR;
            }
        }
+#ifdef WITH_CGRAPH
+       e = agedge(g, tail, head, NULL, 1);
+#else
        e = agedge(g, tail, head);
+#endif
        if (!
-           (ep = (Agedge_t **) tclhandleXlateIndex(edgeTblPtr, e->handle))
+           (ep = (Agedge_t **) tclhandleXlateIndex(edgeTblPtr, AGID(e)))
            || *ep != e) {
            ep = (Agedge_t **) tclhandleAlloc(edgeTblPtr, Tcl_GetStringResult(interp),
                                              &id);
            *ep = e;
-           e->handle = id;
+           AGID(e) = id;
 #ifndef TCLOBJ
            Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), edgecmd,
                              (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
@@ -723,7 +807,7 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
                                 (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
 #endif                         /* TCLOBJ */
        } else {
-           tclhandleString(edgeTblPtr, Tcl_GetStringResult(interp), e->handle);
+           tclhandleString(edgeTblPtr, Tcl_GetStringResult(interp), AGID(e));
        }
        setedgeattributes(agroot(g), e, &argv[4], argc - 4);
        reset_layout(gvc, g);
@@ -732,15 +816,19 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
     } else if ((c == 'a') && (strncmp(argv[1], "addnode", length) == 0)) {
        if (argc % 2) {
            /* if odd number of args then argv[2] is name */
+#ifdef WITH_CGRAPH
+           n = agnode(g, argv[2], 1);
+#else
            n = agnode(g, argv[2]);
+#endif
            i = 3;
            if (!
                (np =
-                (Agnode_t **) tclhandleXlateIndex(nodeTblPtr, n->handle))
+                (Agnode_t **) tclhandleXlateIndex(nodeTblPtr, AGID(n)))
                || *np != n) {
                np = (Agnode_t **) tclhandleAlloc(nodeTblPtr, Tcl_GetStringResult(interp), &id);
                *np = n;
-               n->handle = id;
+               AGID(n) = id;
 #ifndef TCLOBJ
                Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), nodecmd,
                                  (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
@@ -749,16 +837,20 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
                                     (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
 #endif                         /* TCLOBJ */
            } else {
-               tclhandleString(nodeTblPtr, Tcl_GetStringResult(interp), n->handle);
+               tclhandleString(nodeTblPtr, Tcl_GetStringResult(interp), AGID(n));
            }
        } else {
            /* else use handle as name */
            np = (Agnode_t **) tclhandleAlloc(nodeTblPtr, Tcl_GetStringResult(interp),
                                              &id);
+#ifdef WITH_CGRAPH
+           n = agnode(g, Tcl_GetStringResult(interp), 1);
+#else
            n = agnode(g, Tcl_GetStringResult(interp));
+#endif
            i = 2;
            *np = n;
-           n->handle = id;
+           AGID(n) = id;
 #ifndef TCLOBJ
            Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), nodecmd,
                              (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
@@ -780,12 +872,16 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
        }
        if (argc % 2) {
            /* if odd number of args then argv[2] is name */
+#ifdef WITH_CGRAPH
+           sg = agsubg(g, argv[2], 1);
+#else
            sg = agsubg(g, argv[2]);
+#endif
            i = 3;
-           if (!  (sgp = (Agraph_t **) tclhandleXlateIndex(graphTblPtr, sg->handle)) || *sgp != sg) {
+           if (!  (sgp = (Agraph_t **) tclhandleXlateIndex(graphTblPtr, AGID(sg))) || *sgp != sg) {
                sgp = (Agraph_t **) tclhandleAlloc(graphTblPtr, Tcl_GetStringResult(interp), &id);
                *sgp = sg;
-               sg->handle = id;
+               AGID(sg) = id;
 #ifndef TCLOBJ
                Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), graphcmd,
                                  (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
@@ -794,15 +890,19 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
                                     (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
 #endif                         /* TCLOBJ */
            } else {
-               tclhandleString(graphTblPtr, Tcl_GetStringResult(interp), sg->handle);
+               tclhandleString(graphTblPtr, Tcl_GetStringResult(interp), AGID(sg));
            }
        } else {
            /* else use handle as name */
            sgp = (Agraph_t **) tclhandleAlloc(graphTblPtr, Tcl_GetStringResult(interp), &id);
+#ifdef WITH_CGRAPH
+           sg = agsubg(g, Tcl_GetStringResult(interp), 1);
+#else
            sg = agsubg(g, Tcl_GetStringResult(interp));
+#endif
            i = 2;
            *sgp = sg;
-           sg->handle = id;
+           AGID(sg) = id;
 #ifndef TCLOBJ
            Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), graphcmd,
                              (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
@@ -849,7 +949,7 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
            Tcl_AppendResult(interp, "Edge \"", argv[2], " - ", argv[3], "\" not found.", NULL);
            return TCL_ERROR;
        }
-       tclhandleString(edgeTblPtr, buf, e->handle);
+       tclhandleString(edgeTblPtr, buf, AGID(e));
        Tcl_AppendElement(interp, buf);
        return TCL_OK;
 
@@ -862,7 +962,7 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
            Tcl_AppendResult(interp, "Node not found.", NULL);
            return TCL_ERROR;
        }
-       tclhandleString(nodeTblPtr, buf, n->handle);
+       tclhandleString(nodeTblPtr, buf, AGID(n));
        Tcl_AppendResult(interp, buf, NULL);
        return TCL_OK;
 
@@ -882,32 +982,23 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
 
     } else if ((c == 'l')
               && (strncmp(argv[1], "listattributes", length) == 0)) {
-       for (i = 0; i < dtsize(g->univ->globattr->dict); i++) {
-           a = g->univ->globattr->list[i];
-           Tcl_AppendElement(interp, a->name);
-       }
+       listGraphAttrs(interp, g);
        return TCL_OK;
 
     } else if ((c == 'l')
               && (strncmp(argv[1], "listedgeattributes", length) == 0)) {
-       for (i = 0; i < dtsize(g->univ->edgeattr->dict); i++) {
-           a = g->univ->edgeattr->list[i];
-           Tcl_AppendElement(interp, a->name);
-       }
+       listEdgeAttrs (interp, g);
        return TCL_OK;
 
     } else if ((c == 'l')
               && (strncmp(argv[1], "listnodeattributes", length) == 0)) {
-       for (i = 0; i < dtsize(g->univ->nodeattr->dict); i++) {
-           a = g->univ->nodeattr->list[i];
-           Tcl_AppendElement(interp, a->name);
-       }
+       listNodeAttrs (interp, g);
        return TCL_OK;
 
     } else if ((c == 'l') && (strncmp(argv[1], "listedges", length) == 0)) {
        for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
            for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
-               tclhandleString(edgeTblPtr, buf, e->handle);
+               tclhandleString(edgeTblPtr, buf, AGID(e));
                Tcl_AppendElement(interp, buf);
            }
        }
@@ -915,7 +1006,7 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
 
     } else if ((c == 'l') && (strncmp(argv[1], "listnodes", length) == 0)) {
        for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
-           tclhandleString(nodeTblPtr, buf, n->handle);
+           tclhandleString(nodeTblPtr, buf, AGID(n));
            Tcl_AppendElement(interp, buf);
        }
        return TCL_OK;
@@ -923,21 +1014,28 @@ static int graphcmd(ClientData clientData, Tcl_Interp * interp,
     } else if ((c == 'l')
               && (strncmp(argv[1], "listnodesrev", length) == 0)) {
        for (n = aglstnode(g); n; n = agprvnode(g, n)) {
-           tclhandleString(nodeTblPtr, buf, n->handle);
+           tclhandleString(nodeTblPtr, buf, AGID(n));
            Tcl_AppendElement(interp, buf);
        }
        return TCL_OK;
 
     } else if ((c == 'l')
               && (strncmp(argv[1], "listsubgraphs", length) == 0)) {
+#ifdef WITH_CGRAPH
+       for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) {
+           tclhandleString(graphTblPtr, buf, AGID(sg));
+           Tcl_AppendElement(interp, buf);
+       }
+#else
        if (g->meta_node) {
            for (e = agfstout(g->meta_node->graph, g->meta_node); e;
                 e = agnxtout(g->meta_node->graph, e)) {
                sg = agusergraph(aghead(e));
-               tclhandleString(graphTblPtr, buf, sg->handle);
+               tclhandleString(graphTblPtr, buf, AGID(sg));
                Tcl_AppendElement(interp, buf);
            }
        }
+#endif
        return TCL_OK;
 
     } else if ((c == 'q')
@@ -1434,7 +1532,7 @@ static int dotnew(ClientData clientData, Tcl_Interp * interp,
        return TCL_ERROR;
     }
     *gp = g;
-    g->handle = id;
+    AGID(g) = id;
 
 #ifndef TCLOBJ
     Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), graphcmd,
@@ -1451,6 +1549,30 @@ static int dotnew(ClientData clientData, Tcl_Interp * interp,
     return TCL_OK;
 }
 
+#ifdef WITH_CGRAPH
+static void
+init_graphs (Tcl_Interp * interp, GVC_t * gvc, graph_t* g)
+{
+    Agraph_t *sg, **sgp;
+    unsigned long id;
+    char buf[16];
+
+    for (sg = agfstsubg (g); sg; sg = agnxtsubg (sg))
+       init_graphs (interp, gvc, sg);
+
+    sgp = (Agraph_t **) tclhandleAlloc(graphTblPtr, buf, &id);
+    *sgp = g;
+    AGID(g) = id;
+#ifndef TCLOBJ
+    Tcl_CreateCommand(interp, buf, graphcmd, (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
+#else                          /* TCLOBJ */
+    Tcl_CreateObjCommand(interp, buf, graphcmd, (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
+#endif                         /* TCLOBJ */
+    if (agroot(g) == g)
+       Tcl_SetResult(interp, buf, TCL_VOLATILE);
+}
+#endif
+
 /*
  * when a graph is read in from a file or string we need to walk
  * it to create the handles and tcl commands for each 
@@ -1458,19 +1580,24 @@ static int dotnew(ClientData clientData, Tcl_Interp * interp,
  */
 static int tcldot_fixup(Tcl_Interp * interp, GVC_t * gvc, graph_t * g)
 {
+#ifndef WITH_CGRAPH
     Agraph_t **gp, *sg, **sgp;
+#endif
     Agnode_t *n, **np;
     Agedge_t *e, **ep;
     char buf[16];
     unsigned long id;
 
+#ifdef WITH_CGRAPH
+    init_graphs (interp, gvc, g);
+#else
     if (g->meta_node) {
        for (n = agfstnode(g->meta_node->graph); n;
             n = agnxtnode(g->meta_node->graph, n)) {
            sg = agusergraph(n);
            sgp = (Agraph_t **) tclhandleAlloc(graphTblPtr, buf, &id);
            *sgp = sg;
-           sg->handle = id;
+           AGID(sg) = id;
 #ifndef TCLOBJ
            Tcl_CreateCommand(interp, buf, graphcmd, (ClientData) gvc,
                              (Tcl_CmdDeleteProc *) NULL);
@@ -1484,7 +1611,7 @@ static int tcldot_fixup(Tcl_Interp * interp, GVC_t * gvc, graph_t * g)
     } else {
        gp = (Agraph_t **) tclhandleAlloc(graphTblPtr, Tcl_GetStringResult(interp), &id);
        *gp = g;
-       g->handle = id;
+       AGID(g) = id;
 #ifndef TCLOBJ
        Tcl_CreateCommand(interp, Tcl_GetStringResult(interp), graphcmd,
                          (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
@@ -1493,10 +1620,11 @@ static int tcldot_fixup(Tcl_Interp * interp, GVC_t * gvc, graph_t * g)
                             (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
 #endif                         /* TCLOBJ */
     }
+#endif /* WITH_CGRAPH */
     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
        np = (Agnode_t **) tclhandleAlloc(nodeTblPtr, buf, &id);
        *np = n;
-       n->handle = id;
+       AGID(n) = id;
 #ifndef TCLOBJ
        Tcl_CreateCommand(interp, buf, nodecmd,
                          (ClientData) gvc, (Tcl_CmdDeleteProc *) NULL);
@@ -1507,7 +1635,7 @@ static int tcldot_fixup(Tcl_Interp * interp, GVC_t * gvc, graph_t * g)
        for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
            ep = (Agedge_t **) tclhandleAlloc(edgeTblPtr, buf, &id);
            *ep = e;
-           e->handle = id;
+           AGID(e) = id;
 #ifndef TCLOBJ
            Tcl_CreateCommand(interp, buf, edgecmd, (ClientData) gvc,
                              (Tcl_CmdDeleteProc *) NULL);
@@ -1521,7 +1649,7 @@ static int tcldot_fixup(Tcl_Interp * interp, GVC_t * gvc, graph_t * g)
 }
 
 /*
- * mygets - same api as gets
+ * mygets - same api as gets for libgraph, or read for libcgraph
  *
  * gets one line at a time from a Tcl_Channel and places it in a user buffer
  *    up to a maximum of n characters
@@ -1534,10 +1662,65 @@ static int tcldot_fixup(Tcl_Interp * interp, GVC_t * gvc, graph_t * g)
  * but it is needed so that we can take full advantage
  * of the Tcl_Channel mechanism.
  */
+#ifdef WITH_CGRAPH
+static int mygets(void* channel, char *ubuf, int n)
+{
+    static Tcl_DString dstr;
+    static int strpos;
+    int nput;
+
+    if (!n) {                  /* a call with n==0 (from aglexinit) resets */
+       *ubuf = '\0';
+       strpos = 0;
+       return 0;
+    }
+
+    /* 
+     * the user buffer might not be big enough to hold the line.
+     */
+    if (strpos) {
+       nput = Tcl_DStringLength(&dstr) - strpos;
+       if (nput > n) {
+           /* chunk between first and last */
+           memcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), n);
+           strpos += n;
+           nput = n;
+           ubuf[n] = '\0';
+       } else {
+           /* last chunk */
+           memcpy(ubuf, (strpos + Tcl_DStringValue(&dstr)), nput);
+           strpos = 0;
+       }
+    } else {
+       Tcl_DStringFree(&dstr);
+       Tcl_DStringInit(&dstr);
+       if (Tcl_Gets((Tcl_Channel) channel, &dstr) < 0) {
+           /* probably EOF, but could be other read errors */
+           *ubuf = '\0';
+           return 0;
+       }
+       /* linend char(s) were stripped off by Tcl_Gets,
+        * append a canonical linenend. */
+       Tcl_DStringAppend(&dstr, "\n", 1);
+       if (Tcl_DStringLength(&dstr) > n) {
+           /* first chunk */
+           nput = n;
+           memcpy(ubuf, Tcl_DStringValue(&dstr), n);
+           strpos = n;
+       } else {
+           /* single chunk */
+           nput = Tcl_DStringLength(&dstr);
+           memcpy(ubuf, Tcl_DStringValue(&dstr),nput);
+       }
+    }
+    return nput;
+}
+#else
 static char *mygets(char *ubuf, int n, FILE * channel)
 {
     static Tcl_DString dstr;
     static int strpos;
+    int nput;
 
     if (!n) {                  /* a call with n==0 (from aglexinit) resets */
        *ubuf = '\0';
@@ -1570,7 +1753,7 @@ static char *mygets(char *ubuf, int n, FILE * channel)
        /* linend char(s) were stripped off by Tcl_Gets,
         * append a canonical linenend. */
        Tcl_DStringAppend(&dstr, "\n", 1);
-       if (Tcl_DStringLength(&dstr) > n) {
+       if (Tcl_DStringLength(&dstr) >= n) {
            /* first chunk */
            strncpy(ubuf, Tcl_DStringValue(&dstr), n - 1);
            strpos = n - 1;
@@ -1608,6 +1791,27 @@ static char *mygets(char *ubuf, int n, FILE * channel)
     return clp;
 #endif
 }
+#endif /* WITH_CGRAPH */
+
+#ifdef WITH_CGRAPH
+
+Agraph_t *agread_usergets (FILE * fp, int (*usergets)(void *chan, char *buf, int bufsize))
+{
+    Agraph_t* g;
+    Agdisc_t disc;
+    Agiodisc_t ioDisc;
+
+    ioDisc.afread = usergets;
+    ioDisc.putstr = AgIoDisc.putstr;
+    ioDisc.flush = AgIoDisc.flush;
+
+    disc.mem = &AgMemDisc;
+    disc.id = &AgIdDisc;
+    disc.io = &ioDisc;
+    g = agread (fp, &disc);
+    return g;
+}
+#endif
 
 static int dotread(ClientData clientData, Tcl_Interp * interp,
 #ifndef TCLOBJ
@@ -1718,10 +1922,15 @@ int Tcldot_Init(Tcl_Interp * interp)
     Gdtclft_Init(interp);
 #endif
 
+#ifdef WITH_CGRAPH
+    /* set persistent attributes here */
+    agattr(NULL, AGNODE, "label", NODENAME_ESC);
+#else
     aginit();
     agsetiodisc(NULL, gvfwrite, gvferror);
     /* set persistent attributes here */
     agnodeattr(NULL, "label", NODENAME_ESC);
+#endif
 
     /* create a GraphViz Context and pass a pointer to it in clientdata */
     gvc = gvNEWcontext(lt_preloaded_symbols, DEMAND_LOADING);