11#include "../tcl-compat.h"
20 int argc,
char *argv[]) {
31 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
32 " option ?arg arg ...?\"",
NULL);
37 Tcl_AppendResult(interp,
"graph \"", argv[0],
"\" not found",
NULL);
41 if (
streq(
"addedge", argv[1])) {
42 if (argc < 4 || argc % 2 != 0) {
44 interp,
"wrong # args: should be \"", argv[0],
45 " addedge tail head ?attributename attributevalue? ?...?\"",
NULL);
48 tail =
cmd2n(argv[2]);
51 Tcl_AppendResult(interp,
"tail node \"", argv[2],
"\" not found.",
57 Tcl_AppendResult(interp,
"tail node ", argv[2],
" is not in the graph.",
64 Tcl_AppendResult(interp,
"head node \"", argv[3],
"\" not found.",
70 Tcl_AppendResult(interp,
"head node ", argv[3],
" is not in the graph.",
79 }
else if (
streq(
"addnode", argv[1])) {
93 }
else if (
streq(
"addsubgraph", argv[1])) {
97 interp,
"wrong # args: should be \"", argv[0],
98 "\" addsubgraph ?name? ?attributename attributevalue? ?...?",
NULL);
102 sg =
agsubg(g, argv[2], 1);
112 }
else if (
streq(
"countnodes", argv[1])) {
116 }
else if (
streq(
"countedges", argv[1])) {
120 }
else if (
streq(
"delete", argv[1])) {
124 }
else if (
streq(
"findedge", argv[1])) {
126 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
127 " findedge tailnodename headnodename\"",
NULL);
131 Tcl_AppendResult(interp,
"tail node \"", argv[2],
"\" not found.",
NULL);
135 Tcl_AppendResult(interp,
"head node \"", argv[3],
"\" not found.",
NULL);
139 Tcl_AppendResult(interp,
"edge \"", argv[2],
" - ", argv[3],
140 "\" not found.",
NULL);
143 Tcl_AppendElement(interp,
obj2cmd(e));
146 }
else if (
streq(
"findnode", argv[1])) {
148 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
149 " findnode nodename\"",
NULL);
153 Tcl_AppendResult(interp,
"node not found.",
NULL);
159 }
else if (
streq(
"layout", argv[1])) {
161 if (!
aggetrec(g,
"Agraphinfo_t", 0))
165 }
else if (
streq(
"listattributes", argv[1])) {
169 }
else if (
streq(
"listedgeattributes", argv[1])) {
173 }
else if (
streq(
"listnodeattributes", argv[1])) {
177 }
else if (
streq(
"listedges", argv[1])) {
180 Tcl_AppendElement(interp,
obj2cmd(e));
185 }
else if (
streq(
"listnodes", argv[1])) {
187 Tcl_AppendElement(interp,
obj2cmd(n));
191 }
else if (
streq(
"listnodesrev", argv[1])) {
193 Tcl_AppendElement(interp,
obj2cmd(n));
197 }
else if (
streq(
"listsubgraphs", argv[1])) {
199 Tcl_AppendElement(interp,
obj2cmd(sg));
203 }
else if (
streq(
"queryattributes", argv[1])) {
204 for (
int i = 2; i < argc; i++) {
206 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
208 for (
Tcl_Size j = 0; j < argc2; j++) {
209 char *arg = strdup(argv2[j]);
211 Tcl_Free((
char *)argv2);
215 Tcl_AppendElement(interp,
agxget(g, a));
217 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
219 Tcl_Free((
char *)argv2);
224 Tcl_Free((
char *)argv2);
228 }
else if (
streq(
"queryattributevalues", argv[1])) {
229 for (
int i = 2; i < argc; i++) {
231 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
233 for (
Tcl_Size j = 0; j < argc2; j++) {
234 char *arg = strdup(argv2[j]);
236 Tcl_Free((
char *)argv2);
240 Tcl_AppendElement(interp, arg);
241 Tcl_AppendElement(interp,
agxget(g, a));
243 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
245 Tcl_Free((
char *)argv2);
250 Tcl_Free((
char *)argv2);
254 }
else if (
streq(
"queryedgeattributes", argv[1])) {
255 for (
int i = 2; i < argc; i++) {
257 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
259 for (
Tcl_Size j = 0; j < argc2; j++) {
260 char *arg = strdup(argv2[j]);
262 Tcl_Free((
char *)argv2);
266 Tcl_AppendElement(interp,
agxget(g, a));
268 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
270 Tcl_Free((
char *)argv2);
275 Tcl_Free((
char *)argv2);
279 }
else if (
streq(
"queryedgeattributevalues", argv[1])) {
280 for (
int i = 2; i < argc; i++) {
282 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
284 for (
Tcl_Size j = 0; j < argc2; j++) {
285 char *arg = strdup(argv2[j]);
287 Tcl_Free((
char *)argv2);
291 Tcl_AppendElement(interp, arg);
292 Tcl_AppendElement(interp,
agxget(g, a));
294 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
296 Tcl_Free((
char *)argv2);
301 Tcl_Free((
char *)argv2);
305 }
else if (
streq(
"querynodeattributes", argv[1])) {
306 for (
int i = 2; i < argc; i++) {
308 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
310 for (
Tcl_Size j = 0; j < argc2; j++) {
311 char *arg = strdup(argv2[j]);
313 Tcl_Free((
char *)argv2);
317 Tcl_AppendElement(interp,
agxget(g, a));
319 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
321 Tcl_Free((
char *)argv2);
326 Tcl_Free((
char *)argv2);
330 }
else if (
streq(
"querynodeattributevalues", argv[1])) {
331 for (
int i = 2; i < argc; i++) {
333 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
335 for (
Tcl_Size j = 0; j < argc2; j++) {
336 char *arg = strdup(argv2[j]);
338 Tcl_Free((
char *)argv2);
342 Tcl_AppendElement(interp, arg);
343 Tcl_AppendElement(interp,
agxget(g, a));
345 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
347 Tcl_Free((
char *)argv2);
352 Tcl_Free((
char *)argv2);
356 }
else if (
streq(
"render", argv[1])) {
370 if (!
aggetrec(g,
"Agraphinfo_t", 0) || argc > 3)
381 }
else if (
streq(
"setattributes", argv[1])) {
384 if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
386 if (argc2 == 0 || argc2 % 2 != 0) {
387 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
388 "\" setattributes attributename attributevalue "
389 "?attributename attributevalue? ?...?",
391 Tcl_Free((
char *)argv2);
397 Tcl_Free((
char *)argv2);
399 if (argc == 4 &&
streq(argv[2],
"viewport")) {
403 if (argc < 4 || argc % 2 != 0) {
404 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
405 "\" setattributes attributename attributevalue "
406 "?attributename attributevalue? ?...?",
414 }
else if (
streq(
"setedgeattributes", argv[1])) {
417 if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
419 if (argc2 == 0 || argc2 % 2 != 0) {
420 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
421 "\" setedgeattributes attributename attributevalue "
422 "?attributename attributevalue? ?...?",
424 Tcl_Free((
char *)argv2);
430 Tcl_Free((
char *)argv2);
432 if (argc < 4 || argc % 2 != 0) {
433 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
434 "\" setedgeattributes attributename attributevalue "
435 "?attributename attributevalue? ?...?",
442 }
else if (
streq(
"setnodeattributes", argv[1])) {
445 if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
447 if (argc2 == 0 || argc2 % 2 != 0) {
448 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
449 "\" setnodeattributes attributename attributevalue "
450 "?attributename attributevalue? ?...?",
452 Tcl_Free((
char *)argv2);
458 Tcl_Free((
char *)argv2);
460 if (argc < 4 || argc % 2 != 0) {
461 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
462 "\" setnodeattributes attributename attributevalue "
463 "?attributename attributevalue? ?...?",
470 }
else if (
streq(
"showname", argv[1])) {
471 Tcl_SetResult(interp,
agnameof(g), TCL_STATIC);
473 }
else if (
streq(
"write", argv[1])) {
477 interp,
"wrong # args: should be \"", argv[0],
478 " write fileHandle ?language ?DOT|NEATO|TWOPI|FDP|CIRCO|NOP??\"",
489 chan = Tcl_GetChannel(interp, argv[2], &
mode);
492 Tcl_AppendResult(interp,
"channel not open: \"", argv[2],
NULL);
495 if (!(
mode & TCL_WRITABLE)) {
496 Tcl_AppendResult(interp,
"channel not writable: \"", argv[2],
NULL);
502 if (!
aggetrec(g,
"Agraphinfo_t", 0) || argc > 4)
506 if (
gvRender(
gvc, g, argc < 4 ?
"dot" : argv[3], (FILE *)chan) != 0) {
513 interp,
"bad option \"", argv[1],
"\": must be one of:",
514 "\n\taddedge, addnode, addsubgraph, countedges, countnodes,",
515 "\n\tlayout, listattributes, listedgeattributes, listnodeattributes,",
516 "\n\tlistedges, listnodes, listsubgraphs, render, rendergd,",
517 "\n\tqueryattributes, queryedgeattributes, querynodeattributes,",
518 "\n\tqueryattributevalues, queryedgeattributevalues, "
519 "querynodeattributevalues,",
520 "\n\tsetattributes, setedgeattributes, setnodeattributes,",
521 "\n\tshowname, write.",
NULL);
526int graphcmd(ClientData clientData, Tcl_Interp *interp,
int argc,
527 const char *argv[]) {
int agnedges(Agraph_t *g)
int agnnodes(Agraph_t *g)
char * agxget(void *obj, Agsym_t *sym)
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
#define agfindedgeattr(g, a)
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
#define agfindedge(g, t, h)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
#define agfindgraphattr(g, a)
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agprvnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
Agnode_t * aglstnode(Agraph_t *g)
#define agfindnodeattr(g, a)
Agraph_t * agraphof(void *obj)
char * agnameof(void *)
returns a string descriptor for the object.
Agraph_t * agroot(void *obj)
Agrec_t * aggetrec(void *obj, const char *name, int move_to_front)
find record in circular list and do optional move-to-front and lock
Agraph_t * agfstsubg(Agraph_t *g)
Agraph_t * agnxtsubg(Agraph_t *subg)
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
int gvRender(GVC_t *gvc, graph_t *g, const char *format, FILE *out)
int gvRenderContext(GVC_t *gvc, graph_t *g, const char *format, void *context)
static bool streq(const char *a, const char *b)
are a and b equal?
int viewNum
rendering state
size_t(* write_fn)(GVJ_t *job, const char *s, size_t len)
context used to convey information between commands and a renderer
const char * canvas
TCL canvas to render to.
int graphcmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
static int graphcmd_internal(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
void tcldot_layout(GVC_t *gvc, Agraph_t *g, const char *engine)
void tcldot_argv_free(Tcl_Size argc, char *argv[])
free the strings pointed to by argv
void listNodeAttrs(Tcl_Interp *interp, Agraph_t *g)
void listGraphAttrs(Tcl_Interp *interp, Agraph_t *g)
void setgraphattributes(Agraph_t *g, char *argv[], Tcl_Size argc)
size_t Tcldot_channel_writer(GVJ_t *job, const char *s, size_t len)
char * obj2cmd(void *obj)
Agraph_t * cmd2g(const char *cmd)
void deleteGraph(gctx_t *gctx, Agraph_t *g)
size_t Tcldot_string_writer(GVJ_t *job, const char *s, size_t len)
void listEdgeAttrs(Tcl_Interp *interp, Agraph_t *g)
void setnodeattributes(Agraph_t *g, Agnode_t *n, char *argv[], Tcl_Size argc)
char ** tcldot_argv_dup(Tcl_Size argc, const char *argv[])
duplicate the strings pointed to by argv as non-const strings
void setedgeattributes(Agraph_t *g, Agedge_t *e, char *argv[], Tcl_Size argc)
Agnode_t * cmd2n(const char *cmd)