Graphviz  2.41.20170921.2350
tcldot-util.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 
15 #include "tcldot.h"
16 
17 size_t Tcldot_string_writer(GVJ_t *job, const char *s, size_t len)
18 {
19  Tcl_AppendResult((Tcl_Interp*)(job->context), s, NULL);
20  return len;
21 }
22 
23 size_t Tcldot_channel_writer(GVJ_t *job, const char *s, size_t len)
24 {
25  return Tcl_Write((Tcl_Channel)(job->output_file), s, len);
26 }
27 
28 /* handles (tcl commands) to obj* */
29 
30 Agraph_t *cmd2g(char *cmd) {
31  Agraph_t *g = NULL;
32 
33  if (sscanf(cmd, "graph%p", &g) != 1 || !g)
34  return NULL;
35  return g;
36 }
37 Agnode_t *cmd2n(char *cmd) {
38  Agnode_t *n = NULL;
39 
40  if (sscanf(cmd, "node%p", &n) != 1 || !n)
41  return NULL;
42  return n;
43 }
44 Agedge_t *cmd2e(char *cmd) {
45  Agedge_t *e = NULL;
46 
47  if (sscanf(cmd, "edge%p", &e) != 1 || !e)
48  return NULL;
49  return e;
50 }
51 
52 
53 /* obj* to handles (tcl commands) */
54 
55 char *obj2cmd (void *obj) {
56  static char buf[32];
57 
58  switch (AGTYPE(obj)) {
59  case AGRAPH: sprintf(buf,"graph%p",obj); break;
60  case AGNODE: sprintf(buf,"node%p",obj); break;
61  case AGINEDGE:
62  case AGOUTEDGE: sprintf(buf,"edge%p",obj); break;
63  }
64  return buf;
65 }
66 
67 
68 void deleteEdge(gctx_t *gctx, Agraph_t * g, Agedge_t *e)
69 {
70  char *hndl;
71 
72  hndl = obj2cmd(e);
73  agdelete(gctx->g, e); /* delete edge from root graph */
74  Tcl_DeleteCommand(gctx->ictx->interp, hndl);
75 }
76 static void deleteNodeEdges(gctx_t *gctx, Agraph_t *g, Agnode_t *n)
77 {
78  Agedge_t *e, *e1;
79 
80  e = agfstedge(g, n);
81  while (e) {
82  e1 = agnxtedge(g, e, n);
83  deleteEdge(gctx, g, e);
84  e = e1;
85  }
86 }
87 void deleteNode(gctx_t * gctx, Agraph_t *g, Agnode_t *n)
88 {
89  char *hndl;
90 
91  deleteNodeEdges(gctx, gctx->g, n); /* delete all edges to/from node in root graph */
92 
93  hndl = obj2cmd(n);
94  agdelete(gctx->g, n); /* delete node from root graph */
95  Tcl_DeleteCommand(gctx->ictx->interp, hndl);
96 }
97 static void deleteGraphNodes(gctx_t * gctx, Agraph_t *g)
98 {
99  Agnode_t *n, *n1;
100 
101  n = agfstnode(g);
102  while (n) {
103  n1 = agnxtnode(g, n);
104  deleteNode(gctx, g, n);
105  n = n1;
106  }
107 }
108 void deleteGraph(gctx_t * gctx, Agraph_t *g)
109 {
110  Agraph_t *sg;
111  char *hndl;
112 
113  for (sg = agfstsubg (g); sg; sg = agnxtsubg (sg)) {
114  deleteGraph(gctx, sg);
115  }
116  deleteGraphNodes(gctx, g);
117 
118  hndl = obj2cmd(g);
119  if (g == agroot(g)) {
120  agclose(g);
121  } else {
122  agdelsubg(agroot(g), g);
123  }
124  Tcl_DeleteCommand(gctx->ictx->interp, hndl);
125 }
126 
127 static void myagxset(void *obj, Agsym_t *a, char *val)
128 {
129  int len;
130  char *hs;
131 
132  if (a->name[0] == 'l' && val[0] == '<' && strcmp(a->name, "label") == 0) {
133  len = strlen(val);
134  if (val[len-1] == '>') {
135  hs = strdup(val+1);
136  *(hs+len-2) = '\0';
137  val = agstrdup_html(agraphof(obj),hs);
138  free(hs);
139  }
140  }
141  agxset(obj, a, val);
142 }
143 void setgraphattributes(Agraph_t * g, char *argv[], int argc)
144 {
145  int i;
146  Agsym_t *a;
147 
148  for (i = 0; i < argc; i++) {
149  if (!(a = agfindgraphattr(agroot(g), argv[i])))
150  a = agattr(agroot(g), AGRAPH, argv[i], "");
151  myagxset(g, a, argv[++i]);
152  }
153 }
154 
155 void setedgeattributes(Agraph_t * g, Agedge_t * e, char *argv[], int argc)
156 {
157  int i;
158  Agsym_t *a;
159 
160  for (i = 0; i < argc; i++) {
161  /* silently ignore attempts to modify "key" */
162  if (strcmp(argv[i], "key") == 0) {
163  i++;
164  continue;
165  }
166  if (e) {
167  if (!(a = agfindedgeattr(g, argv[i])))
168  a = agattr(agroot(g), AGEDGE, argv[i], "");
169  myagxset(e, a, argv[++i]);
170  }
171  else {
172  agattr(g, AGEDGE, argv[i], argv[i+1]);
173  i++;
174  }
175  }
176 }
177 
178 void setnodeattributes(Agraph_t * g, Agnode_t * n, char *argv[], int argc)
179 {
180  int i;
181  Agsym_t *a;
182 
183  for (i = 0; i < argc; i++) {
184  if (n) {
185  if (!(a = agfindnodeattr(g, argv[i])))
186  a = agattr(agroot(g), AGNODE, argv[i], "");
187  myagxset(n, a, argv[++i]);
188  }
189  else {
190  agattr(g, AGNODE, argv[i], argv[i+1]);
191  i++;
192  }
193  }
194 }
195 
196 void listGraphAttrs (Tcl_Interp * interp, Agraph_t* g)
197 {
198  Agsym_t *a = NULL;
199  while ((a = agnxtattr(g, AGRAPH, a))) {
200  Tcl_AppendElement(interp, a->name);
201  }
202 }
203 void listNodeAttrs (Tcl_Interp * interp, Agraph_t* g)
204 {
205  Agsym_t *a = NULL;
206  while ((a = agnxtattr(g, AGNODE, a))) {
207  Tcl_AppendElement(interp, a->name);
208  }
209 }
210 void listEdgeAttrs (Tcl_Interp * interp, Agraph_t* g)
211 {
212  Agsym_t *a = NULL;
213  while ((a = agnxtattr(g, AGEDGE, a))) {
214  Tcl_AppendElement(interp, a->name);
215  }
216 }
217 
218 void tcldot_layout(GVC_t *gvc, Agraph_t * g, char *engine)
219 {
220  char buf[256];
221  Agsym_t *a;
222  int rc;
223 
224  gvFreeLayout(gvc, g); /* in case previously drawn */
225 
226 /* support old behaviors if engine isn't specified*/
227  if (!engine || *engine == '\0') {
228  if (agisdirected(g))
229  rc = gvlayout_select(gvc, "dot");
230  else
231  rc = gvlayout_select(gvc, "neato");
232  }
233  else {
234  if (strcasecmp(engine, "nop") == 0) {
235  Nop = 2;
237  rc = gvlayout_select(gvc, "neato");
238  }
239  else {
240  rc = gvlayout_select(gvc, engine);
241  }
242  if (rc == NO_SUPPORT)
243  rc = gvlayout_select(gvc, "dot");
244  }
245  if (rc == NO_SUPPORT) {
246  fprintf(stderr, "Layout type: \"%s\" not recognized. Use one of:%s\n",
247  engine, gvplugin_list(gvc, API_layout, engine));
248  return;
249  }
250  gvLayoutJobs(gvc, g);
251 
252 /* set bb attribute for basic layout.
253  * doesn't yet include margins, scaling or page sizes because
254  * those depend on the renderer being used. */
255  if (GD_drawing(g)->landscape)
256  sprintf(buf, "%d %d %d %d",
257  ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).LL.x),
258  ROUND(GD_bb(g).UR.y), ROUND(GD_bb(g).UR.x));
259  else
260  sprintf(buf, "%d %d %d %d",
261  ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).LL.y),
262  ROUND(GD_bb(g).UR.x), ROUND(GD_bb(g).UR.y));
263  if (!(a = agattr(g, AGRAPH, "bb", NULL)))
264  a = agattr(g, AGRAPH, "bb", "");
265  agxset(g, a, buf);
266 }
Agraph_t * cmd2g(char *cmd)
Definition: tcldot-util.c:30
Agraph_t * g
Definition: tcldot.h:58
Agsym_t * agattr(Agraph_t *g, int kind, char *name, char *value)
Definition: attr.c:324
void listNodeAttrs(Tcl_Interp *interp, Agraph_t *g)
Definition: tcldot-util.c:203
Agnode_t * cmd2n(char *cmd)
Definition: tcldot-util.c:37
Agsym_t * agnxtattr(Agraph_t *g, int kind, Agsym_t *attr)
Definition: attr.c:340
void * context
Definition: gvcjob.h:304
void setgraphattributes(Agraph_t *g, char *argv[], int argc)
Definition: tcldot-util.c:143
int agxset(void *obj, Agsym_t *sym, char *value)
Definition: attr.c:468
char * name
Definition: cgraph.h:326
EXTERN int Nop
Definition: globals.h:70
char * obj2cmd(void *obj)
Definition: tcldot-util.c:55
#define ROUND(f)
Definition: arith.h:84
CGRAPH_API int agisdirected(Agraph_t *g)
Definition: graph.c:182
CGRAPH_API long agdelsubg(Agraph_t *g, Agraph_t *sub)
Definition: subg.c:93
void listGraphAttrs(Tcl_Interp *interp, Agraph_t *g)
Definition: tcldot-util.c:196
CGRAPH_API Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Definition: edge.c:86
CGRAPH_API int agdelete(Agraph_t *g, void *obj)
Definition: obj.c:16
int gvFreeLayout(GVC_t *gvc, graph_t *g)
Definition: gvlayout.c:102
CGRAPH_API Agraph_t * agfstsubg(Agraph_t *g)
Definition: subg.c:72
Definition: gvcjob.h:271
CGRAPH_API Agraph_t * agroot(void *obj)
Definition: obj.c:169
#define AGOUTEDGE
Definition: cgraph.h:102
#define POINTS_PER_INCH
Definition: geom.h:62
#define NO_SUPPORT
Definition: const.h:151
CGRAPH_API char * agstrdup_html(Agraph_t *, char *)
Definition: refstr.c:123
#define AGTYPE(obj)
Definition: cgraph.h:113
void listEdgeAttrs(Tcl_Interp *interp, Agraph_t *g)
Definition: tcldot-util.c:210
int gvlayout_select(GVC_t *gvc, const char *str)
Definition: gvlayout.c:33
CGRAPH_API Agraph_t * agraphof(void *obj)
Definition: obj.c:185
CGRAPH_API Agraph_t * agnxtsubg(Agraph_t *subg)
Definition: subg.c:77
size_t Tcldot_channel_writer(GVJ_t *job, const char *s, size_t len)
Definition: tcldot-util.c:23
int gvLayoutJobs(GVC_t *gvc, graph_t *g)
Definition: gvlayout.c:55
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition: node.c:45
Definition: gvcint.h:70
CGRAPH_API int agclose(Agraph_t *g)
Definition: graph.c:93
size_t Tcldot_string_writer(GVJ_t *job, const char *s, size_t len)
Definition: tcldot-util.c:17
Agedge_t * cmd2e(char *cmd)
Definition: tcldot-util.c:44
void deleteEdge(gctx_t *gctx, Agraph_t *g, Agedge_t *e)
Definition: tcldot-util.c:68
#define agfindedgeattr(g, a)
Definition: types.h:614
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
Definition: node.c:38
Definition: grammar.c:79
#define AGNODE
Definition: cgraph.h:101
Tcl_Interp * interp
Definition: tcldot.h:50
ictx_t * ictx
Definition: tcldot.h:59
#define NULL
Definition: logic.h:39
Definition: tcldot.h:57
CGRAPH_API Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Definition: edge.c:95
#define agfindgraphattr(g, a)
Definition: types.h:612
GVC_t * gvc
Definition: htmlparse.c:87
void setedgeattributes(Agraph_t *g, Agedge_t *e, char *argv[], int argc)
Definition: tcldot-util.c:155
int strcasecmp(const char *s1, const char *s2)
Definition: strcasecmp.c:21
char * gvplugin_list(GVC_t *gvc, api_t api, const char *str)
Definition: gvplugin.c:342
void deleteNode(gctx_t *gctx, Agraph_t *g, Agnode_t *n)
Definition: tcldot-util.c:87
#define AGINEDGE
Definition: cgraph.h:103
void setnodeattributes(Agraph_t *g, Agnode_t *n, char *argv[], int argc)
Definition: tcldot-util.c:178
void deleteGraph(gctx_t *gctx, Agraph_t *g)
Definition: tcldot-util.c:108
#define GD_bb(g)
Definition: types.h:357
EXTERN double PSinputscale
Definition: globals.h:71
#define GD_drawing(g)
Definition: types.h:356
#define AGEDGE
Definition: cgraph.h:104
void tcldot_layout(GVC_t *gvc, Agraph_t *g, char *engine)
Definition: tcldot-util.c:218
FILE * output_file
Definition: gvcjob.h:286
#define agfindnodeattr(g, a)
Definition: types.h:613
#define AGRAPH
Definition: cgraph.h:100