11#include "../tcl-compat.h"
19 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)) {
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])) {
113 snprintf(buf,
sizeof(buf),
"%d",
agnnodes(g));
114 Tcl_AppendResult(interp, buf,
NULL);
117 }
else if (
streq(
"countedges", argv[1])) {
118 snprintf(buf,
sizeof(buf),
"%d",
agnedges(g));
119 Tcl_AppendResult(interp, buf,
NULL);
122 }
else if (
streq(
"delete", argv[1])) {
126 }
else if (
streq(
"findedge", argv[1])) {
128 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
129 " findedge tailnodename headnodename\"",
NULL);
133 Tcl_AppendResult(interp,
"tail node \"", argv[2],
"\" not found.",
NULL);
137 Tcl_AppendResult(interp,
"head node \"", argv[3],
"\" not found.",
NULL);
141 Tcl_AppendResult(interp,
"edge \"", argv[2],
" - ", argv[3],
142 "\" not found.",
NULL);
145 Tcl_AppendElement(interp,
obj2cmd(e));
148 }
else if (
streq(
"findnode", argv[1])) {
150 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
151 " findnode nodename\"",
NULL);
155 Tcl_AppendResult(interp,
"node not found.",
NULL);
161 }
else if (
streq(
"layoutedges", argv[1])) {
163 if (!
aggetrec(g,
"Agraphinfo_t", 0))
167 }
else if (
streq(
"layoutnodes", argv[1])) {
169 if (!
aggetrec(g,
"Agraphinfo_t", 0))
173 }
else if (
streq(
"listattributes", argv[1])) {
177 }
else if (
streq(
"listedgeattributes", argv[1])) {
181 }
else if (
streq(
"listnodeattributes", argv[1])) {
185 }
else if (
streq(
"listedges", argv[1])) {
188 Tcl_AppendElement(interp,
obj2cmd(e));
193 }
else if (
streq(
"listnodes", argv[1])) {
195 Tcl_AppendElement(interp,
obj2cmd(n));
199 }
else if (
streq(
"listnodesrev", argv[1])) {
201 Tcl_AppendElement(interp,
obj2cmd(n));
205 }
else if (
streq(
"listsubgraphs", argv[1])) {
207 Tcl_AppendElement(interp,
obj2cmd(sg));
211 }
else if (
streq(
"queryattributes", argv[1])) {
212 for (
int i = 2; i < argc; i++) {
214 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
216 for (
Tcl_Size j = 0; j < argc2; j++) {
217 char *arg = strdup(argv2[j]);
219 Tcl_Free((
char *)argv2);
223 Tcl_AppendElement(interp,
agxget(g, a));
225 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
227 Tcl_Free((
char *)argv2);
232 Tcl_Free((
char *)argv2);
236 }
else if (
streq(
"queryattributevalues", argv[1])) {
237 for (
int i = 2; i < argc; i++) {
239 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
241 for (
Tcl_Size j = 0; j < argc2; j++) {
242 char *arg = strdup(argv2[j]);
244 Tcl_Free((
char *)argv2);
248 Tcl_AppendElement(interp, arg);
249 Tcl_AppendElement(interp,
agxget(g, a));
251 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
253 Tcl_Free((
char *)argv2);
258 Tcl_Free((
char *)argv2);
262 }
else if (
streq(
"queryedgeattributes", argv[1])) {
263 for (
int i = 2; i < argc; i++) {
265 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
267 for (
Tcl_Size j = 0; j < argc2; j++) {
268 char *arg = strdup(argv2[j]);
270 Tcl_Free((
char *)argv2);
274 Tcl_AppendElement(interp,
agxget(g, a));
276 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
278 Tcl_Free((
char *)argv2);
283 Tcl_Free((
char *)argv2);
287 }
else if (
streq(
"queryedgeattributevalues", argv[1])) {
288 for (
int i = 2; i < argc; i++) {
290 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
292 for (
Tcl_Size j = 0; j < argc2; j++) {
293 char *arg = strdup(argv2[j]);
295 Tcl_Free((
char *)argv2);
299 Tcl_AppendElement(interp, arg);
300 Tcl_AppendElement(interp,
agxget(g, a));
302 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
304 Tcl_Free((
char *)argv2);
309 Tcl_Free((
char *)argv2);
313 }
else if (
streq(
"querynodeattributes", argv[1])) {
314 for (
int i = 2; i < argc; i++) {
316 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
318 for (
Tcl_Size j = 0; j < argc2; j++) {
319 char *arg = strdup(argv2[j]);
321 Tcl_Free((
char *)argv2);
325 Tcl_AppendElement(interp,
agxget(g, a));
327 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
329 Tcl_Free((
char *)argv2);
334 Tcl_Free((
char *)argv2);
338 }
else if (
streq(
"querynodeattributevalues", argv[1])) {
339 for (
int i = 2; i < argc; i++) {
341 if (Tcl_SplitList(interp, argv[i], &argc2, &argv2) != TCL_OK)
343 for (
Tcl_Size j = 0; j < argc2; j++) {
344 char *arg = strdup(argv2[j]);
346 Tcl_Free((
char *)argv2);
350 Tcl_AppendElement(interp, arg);
351 Tcl_AppendElement(interp,
agxget(g, a));
353 Tcl_AppendResult(interp,
" No attribute named \"", arg,
"\"",
NULL);
355 Tcl_Free((
char *)argv2);
360 Tcl_Free((
char *)argv2);
364 }
else if (
streq(
"render", argv[1])) {
378 if (!
aggetrec(g,
"Agraphinfo_t", 0) || argc > 3)
389 }
else if (
streq(
"setattributes", argv[1])) {
392 if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
394 if ((argc2 == 0) || (argc2 % 2)) {
395 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
396 "\" setattributes attributename attributevalue "
397 "?attributename attributevalue? ?...?",
399 Tcl_Free((
char *)argv2);
405 Tcl_Free((
char *)argv2);
407 if (argc == 4 &&
streq(argv[2],
"viewport")) {
411 if ((argc < 4) || (argc % 2)) {
412 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
413 "\" setattributes attributename attributevalue "
414 "?attributename attributevalue? ?...?",
422 }
else if (
streq(
"setedgeattributes", argv[1])) {
425 if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
427 if ((argc2 == 0) || (argc2 % 2)) {
428 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
429 "\" setedgeattributes attributename attributevalue "
430 "?attributename attributevalue? ?...?",
432 Tcl_Free((
char *)argv2);
438 Tcl_Free((
char *)argv2);
440 if ((argc < 4) || (argc % 2)) {
441 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
442 "\" setedgeattributes attributename attributevalue "
443 "?attributename attributevalue? ?...?",
450 }
else if (
streq(
"setnodeattributes", argv[1])) {
453 if (Tcl_SplitList(interp, argv[2], &argc2, &argv2) != TCL_OK)
455 if ((argc2 == 0) || (argc2 % 2)) {
456 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
457 "\" setnodeattributes attributename attributevalue "
458 "?attributename attributevalue? ?...?",
460 Tcl_Free((
char *)argv2);
466 Tcl_Free((
char *)argv2);
468 if ((argc < 4) || (argc % 2)) {
469 Tcl_AppendResult(interp,
"wrong # args: should be \"", argv[0],
470 "\" setnodeattributes attributename attributevalue "
471 "?attributename attributevalue? ?...?",
478 }
else if (
streq(
"showname", argv[1])) {
479 Tcl_SetResult(interp,
agnameof(g), TCL_STATIC);
481 }
else if (
streq(
"write", argv[1])) {
485 interp,
"wrong # args: should be \"", argv[0],
486 " write fileHandle ?language ?DOT|NEATO|TWOPI|FDP|CIRCO|NOP??\"",
497 chan = Tcl_GetChannel(interp, argv[2], &
mode);
500 Tcl_AppendResult(interp,
"channel not open: \"", argv[2],
NULL);
503 if (!(
mode & TCL_WRITABLE)) {
504 Tcl_AppendResult(interp,
"channel not writable: \"", argv[2],
NULL);
510 if (!
aggetrec(g,
"Agraphinfo_t", 0) || argc > 4)
514 if (
gvRender(
gvc, g, argc < 4 ?
"dot" : argv[3], (FILE *)chan) != 0) {
521 interp,
"bad option \"", argv[1],
"\": must be one of:",
522 "\n\taddedge, addnode, addsubgraph, countedges, countnodes,",
523 "\n\tlayout, listattributes, listedgeattributes, listnodeattributes,",
524 "\n\tlistedges, listnodes, listsubgraphs, render, rendergd,",
525 "\n\tqueryattributes, queryedgeattributes, querynodeattributes,",
526 "\n\tqueryattributevalues, queryedgeattributevalues, "
527 "querynodeattributevalues,",
528 "\n\tsetattributes, setedgeattributes, setnodeattributes,",
529 "\n\tshowname, write.",
NULL);
534int graphcmd(ClientData clientData, Tcl_Interp *interp,
int argc,
535 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 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)
void setedgeattributes(Agraph_t *g, Agedge_t *e, char *argv[], Tcl_Size argc)
void tcldot_argv_free(int argc, char *argv[])
free the strings pointed to by argv
char ** tcldot_argv_dup(int argc, const char *argv[])
duplicate the strings pointed to by argv as non-const strings
Agnode_t * cmd2n(const char *cmd)