00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <string.h>
00018 #include "gvc.h"
00019
00020 extern void gv_binding_init(GVC_t *gvc);
00021
00022 static GVC_t *gvc;
00023
00024 static void gv_init(void) {
00025 gvc = gvContext();
00026 gv_binding_init(gvc);
00027 }
00028
00029 Agraph_t *graph(char *name)
00030 {
00031 if (!gvc) gv_init();
00032 return agopen(name, AGRAPH);
00033 }
00034
00035 Agraph_t *digraph(char *name)
00036 {
00037 if (!gvc) gv_init();
00038 return agopen(name, AGDIGRAPH);
00039 }
00040
00041 Agraph_t *strictgraph(char *name)
00042 {
00043 if (!gvc) gv_init();
00044 return agopen(name, AGRAPHSTRICT);
00045 }
00046
00047 Agraph_t *strictdigraph(char *name)
00048 {
00049 if (!gvc) gv_init();
00050 return agopen(name, AGDIGRAPHSTRICT);
00051 }
00052
00053 Agraph_t *readstring(char *string)
00054 {
00055 if (!gvc) gv_init();
00056 return agmemread(string);
00057 }
00058
00059 Agraph_t *read(FILE *f)
00060 {
00061 if (!gvc) gv_init();
00062 return agread(f);
00063 }
00064
00065 Agraph_t *read(char *filename)
00066 {
00067 FILE *f;
00068 Agraph_t *g;
00069
00070 f = fopen(filename, "r");
00071 if (!f) return NULL;
00072 if (!gvc) gv_init();
00073 g = agread(f);
00074 fclose(f);
00075 return g;
00076 }
00077
00078
00079 Agraph_t *graph(Agraph_t *g, char *name)
00080 {
00081 if (!gvc) gv_init();
00082 return agsubg(g, name);
00083 }
00084
00085 Agnode_t *node(Agraph_t *g, char *name)
00086 {
00087
00088 if (!gvc || (name[0] == '\001' && strcmp (name, "\001proto") == 0))
00089 return NULL;
00090 return agnode(g, name);
00091 }
00092
00093 Agedge_t *edge(Agnode_t *t, Agnode_t *h)
00094 {
00095
00096 if (!gvc || !t || !h
00097 || (t->name[0] == '\001' && strcmp (t->name, "\001proto") == 0)
00098 || (h->name[0] == '\001' && strcmp (h->name, "\001proto") == 0))
00099 return NULL;
00100 return agedge(t->graph, t, h);
00101 }
00102
00103
00104 Agedge_t *edge(char *tname, Agnode_t *h)
00105 {
00106 return edge(node(h->graph, tname), h);
00107 }
00108
00109
00110 Agedge_t *edge(Agnode_t *t, char *hname)
00111 {
00112 return edge(t, node(t->graph, hname));
00113 }
00114
00115
00116 Agedge_t *edge(Agraph_t *g, char *tname, char *hname)
00117 {
00118 return edge(node(g, tname), node(g, hname));
00119 }
00120
00121
00122 static char* myagxget(void *obj, Agsym_t *a)
00123 {
00124 int len;
00125 char *val, *hs;
00126
00127 if (!obj || !a)
00128 return "";
00129 val = agxget(obj, a->index);
00130 if (!val)
00131 return "";
00132 if (a->name[0] == 'l' && strcmp(a->name, "label") == 0 && aghtmlstr(val)) {
00133 len = strlen(val);
00134 hs = (char*)malloc(len + 3);
00135 hs[0] = '<';
00136 strcpy(hs+1, val);
00137 hs[len+1] = '>';
00138 hs[len+2] = '\0';
00139 return hs;
00140 }
00141 return val;
00142 }
00143 char *getv(Agraph_t *g, Agsym_t *a)
00144 {
00145 return myagxget(g, a);
00146 }
00147 char *getv(Agraph_t *g, char *attr)
00148 {
00149 Agsym_t *a;
00150
00151 if (!g || !attr)
00152 return NULL;
00153 a = agfindattr(g->root, attr);
00154 return myagxget(g, a);
00155 }
00156 static void myagxset(void *obj, Agsym_t *a, char *val)
00157 {
00158 int len;
00159 char *hs;
00160
00161 if (a->name[0] == 'l' && val[0] == '<' && strcmp(a->name, "label") == 0) {
00162 len = strlen(val);
00163 if (val[len-1] == '>') {
00164 hs = strdup(val+1);
00165 *(hs+len-2) = '\0';
00166 val = agstrdup_html(hs);
00167 free(hs);
00168 }
00169 }
00170 agxset(obj, a->index, val);
00171 }
00172 char *setv(Agraph_t *g, Agsym_t *a, char *val)
00173 {
00174 if (!g || !a || !val)
00175 return NULL;
00176 myagxset(g, a, val);
00177 return val;
00178 }
00179 char *setv(Agraph_t *g, char *attr, char *val)
00180 {
00181 Agsym_t *a;
00182
00183 if (!g || !attr || !val)
00184 return NULL;
00185 a = agfindattr(g->root, attr);
00186 if (!a)
00187 a = agraphattr(g->root, attr, "");
00188 myagxset(g, a, val);
00189 return val;
00190 }
00191
00192 char *getv(Agnode_t *n, Agsym_t *a)
00193 {
00194 return myagxget(n, a);
00195 }
00196 char *getv(Agnode_t *n, char *attr)
00197 {
00198 Agraph_t *g;
00199 Agsym_t *a;
00200
00201 if (!n || !attr)
00202 return NULL;
00203 g = n->graph->root;
00204 a = agfindattr(g->proto->n, attr);
00205 return myagxget(n, a);
00206 }
00207 char *setv(Agnode_t *n, Agsym_t *a, char *val)
00208 {
00209 if (!n || !a || !val)
00210 return NULL;
00211 myagxset(n, a, val);
00212 return val;
00213 }
00214 char *setv(Agnode_t *n, char *attr, char *val)
00215 {
00216 Agraph_t *g;
00217 Agsym_t *a;
00218
00219 if (!n || !attr || !val)
00220 return NULL;
00221 g = n->graph->root;
00222 a = agfindattr(g->proto->n, attr);
00223 if (!a)
00224 a = agnodeattr(g, attr, "");
00225 myagxset(n, a, val);
00226 return val;
00227 }
00228
00229 char *getv(Agedge_t *e, Agsym_t *a)
00230 {
00231 return myagxget(e, a);
00232 }
00233 char *getv(Agedge_t *e, char *attr)
00234 {
00235 Agraph_t *g;
00236 Agsym_t *a;
00237
00238 if (!e || !attr)
00239 return NULL;
00240 g = e->tail->graph;
00241 a = agfindattr(g->proto->e, attr);
00242 return myagxget(e, a);
00243 }
00244 char *setv(Agedge_t *e, Agsym_t *a, char *val)
00245 {
00246 if (!e || !a || !val)
00247 return NULL;
00248 myagxset(e, a, val);
00249 return val;
00250 }
00251 char *setv(Agedge_t *e, char *attr, char *val)
00252 {
00253 Agraph_t *g;
00254 Agsym_t *a;
00255
00256 if (!e || !attr || !val)
00257 return NULL;
00258 g = e->tail->graph->root;
00259 a = agfindattr(g->proto->e, attr);
00260 if (!a)
00261 a = agedgeattr(g, attr, "");
00262 myagxset(e, a, val);
00263 return val;
00264 }
00265
00266 Agraph_t *findsubg(Agraph_t *g, char *name)
00267 {
00268 if (!g || !name)
00269 return NULL;
00270 return agfindsubg(g, name);
00271 }
00272
00273 Agnode_t *findnode(Agraph_t *g, char *name)
00274 {
00275 if (!g || !name)
00276 return NULL;
00277 return agfindnode(g, name);
00278 }
00279
00280 Agedge_t *findedge(Agnode_t *t, Agnode_t *h)
00281 {
00282 if (!t || !h)
00283 return NULL;
00284 return agfindedge(t->graph, t, h);
00285 }
00286
00287 Agsym_t *findattr(Agraph_t *g, char *name)
00288 {
00289 if (!g || !name)
00290 return NULL;
00291 return agfindattr(g, name);
00292 }
00293
00294 Agsym_t *findattr(Agnode_t *n, char *name)
00295 {
00296 if (!n || !name)
00297 return NULL;
00298 return agfindattr(n, name);
00299 }
00300
00301 Agsym_t *findattr(Agedge_t *e, char *name)
00302 {
00303 if (!e || !name)
00304 return NULL;
00305 return agfindattr(e, name);
00306 }
00307
00308
00309
00310 Agnode_t *headof(Agedge_t *e)
00311 {
00312 if (!e)
00313 return NULL;
00314 return e->head;
00315 }
00316
00317 Agnode_t *tailof(Agedge_t *e)
00318 {
00319 if (!e)
00320 return NULL;
00321 return e->tail;
00322 }
00323
00324 Agraph_t *graphof(Agraph_t *g)
00325 {
00326 if (!g || g == g->root)
00327 return NULL;
00328 return g->root;
00329 }
00330
00331 Agraph_t *graphof(Agedge_t *e)
00332 {
00333 if (!e)
00334 return NULL;
00335 return e->tail->graph;
00336 }
00337
00338 Agraph_t *graphof(Agnode_t *n)
00339 {
00340 if (!n)
00341 return NULL;
00342 return n->graph;
00343 }
00344
00345 Agraph_t *rootof(Agraph_t *g)
00346 {
00347 if (!g)
00348 return NULL;
00349 return g->root;
00350 }
00351
00352
00353 Agnode_t *protonode(Agraph_t *g)
00354 {
00355 if (!g)
00356 return NULL;
00357 return g->proto->n;
00358 }
00359
00360 Agedge_t *protoedge(Agraph_t *g)
00361 {
00362 if (!g)
00363 return NULL;
00364 return g->proto->e;
00365 }
00366
00367
00368 char *nameof(Agraph_t *g)
00369 {
00370 if (!g)
00371 return NULL;
00372 return g->name;
00373 }
00374 char *nameof(Agnode_t *n)
00375 {
00376 if (!n)
00377 return NULL;
00378 return n->name;
00379 }
00380
00381
00382
00383
00384
00385
00386 char *nameof(Agsym_t *a)
00387 {
00388 if (!a)
00389 return NULL;
00390 return a->name;
00391 }
00392
00393
00394 bool ok(Agraph_t *g)
00395 {
00396 if (!g)
00397 return false;
00398 return true;
00399 }
00400 bool ok(Agnode_t *n)
00401 {
00402 if (!n)
00403 return false;
00404 return true;
00405 }
00406 bool ok(Agedge_t *e)
00407 {
00408 if (!e)
00409 return false;
00410 return true;
00411 }
00412 bool ok(Agsym_t *a)
00413 {
00414 if (!a)
00415 return false;
00416 return true;
00417 }
00418
00419 Agraph_t *firstsubg(Agraph_t *g)
00420 {
00421 Agraph_t *mg;
00422 Agnode_t *n;
00423 Agedge_t *e;
00424
00425 if (!g)
00426 return NULL;
00427 n = g->meta_node;
00428 if (!n)
00429 return NULL;
00430 mg = n->graph;
00431 if (!mg)
00432 return NULL;
00433 e = agfstout(mg, n);
00434 if (!e)
00435 return NULL;
00436 return agusergraph(e->head);
00437 }
00438
00439 Agraph_t *nextsubg(Agraph_t *g, Agraph_t *sg)
00440 {
00441 Agraph_t *mg;
00442 Agnode_t *ng, *nsg;
00443 Agedge_t *e;
00444
00445 if (!g || !sg)
00446 return NULL;
00447 ng = g->meta_node;
00448 nsg = sg->meta_node;
00449 if (!ng || !nsg)
00450 return NULL;
00451 mg = ng->graph;
00452 if (!mg)
00453 return NULL;
00454 e = agfindedge(mg, ng, nsg);
00455 if (!e)
00456 return NULL;
00457 e = agnxtout(mg, e);
00458 if (!e)
00459 return NULL;
00460 return agusergraph(e->head);
00461 }
00462
00463 Agraph_t *firstsupg(Agraph_t *g)
00464 {
00465 Agraph_t *mg;
00466 Agnode_t *n;
00467 Agedge_t *e;
00468
00469 if (!g)
00470 return NULL;
00471 n = g->meta_node;
00472 if (!n)
00473 return NULL;
00474 mg = n->graph;
00475 if (!mg)
00476 return NULL;
00477 e = agfstin(mg, n);
00478 if (!e)
00479 return NULL;
00480 return agusergraph(e->tail);
00481 }
00482
00483 Agraph_t *nextsupg(Agraph_t *g, Agraph_t *sg)
00484 {
00485 Agraph_t *mg;
00486 Agnode_t *ng, *nsg;
00487 Agedge_t *e;
00488
00489 if (!g || !sg)
00490 return NULL;
00491 ng = g->meta_node;
00492 nsg = sg->meta_node;
00493 if (!ng || !nsg)
00494 return NULL;
00495 mg = ng->graph;
00496 if (!mg)
00497 return NULL;
00498 e = agfindedge(mg, nsg, ng);
00499 if (!e)
00500 return NULL;
00501 e = agnxtin(mg, e);
00502 if (!e)
00503 return NULL;
00504 return agusergraph(e->tail);
00505 }
00506
00507 Agedge_t *firstout(Agraph_t *g)
00508 {
00509 Agnode_t *n;
00510
00511 if (!g)
00512 return NULL;
00513 n = agfstnode(g);
00514 if (!n)
00515 return NULL;
00516 return agfstout(g, n);
00517 }
00518
00519 Agedge_t *nextout(Agraph_t *g, Agedge_t *e)
00520 {
00521 Agnode_t *n;
00522 Agedge_t *ne;
00523
00524 if (!g || !e)
00525 return NULL;
00526 ne = agnxtout(g, e);
00527 if (ne)
00528 return (ne);
00529 n = agnxtnode(g, e->tail);
00530 if (!n)
00531 return NULL;
00532 return agfstout(g, n);
00533 }
00534
00535 Agedge_t *firstedge(Agraph_t *g)
00536 {
00537 if (!g)
00538 return NULL;
00539 return firstout(g);
00540 }
00541
00542 Agedge_t *nextedge(Agraph_t *g, Agedge_t *e)
00543 {
00544 if (!g || !e)
00545 return NULL;
00546 return nextout(g, e);
00547 }
00548
00549 Agedge_t *firstout(Agnode_t *n)
00550 {
00551 if (!n)
00552 return NULL;
00553 return agfstout(n->graph, n);
00554 }
00555
00556 Agedge_t *nextout(Agnode_t *n, Agedge_t *e)
00557 {
00558 if (!n || !e)
00559 return NULL;
00560 return agnxtout(n->graph, e);
00561 }
00562
00563 Agnode_t *firsthead(Agnode_t *n)
00564 {
00565 Agedge_t *e;
00566
00567 if (!n)
00568 return NULL;
00569 e = agfstout(n->graph, n);
00570 if (!e)
00571 return NULL;
00572 return e->head;
00573 }
00574
00575 Agnode_t *nexthead(Agnode_t *n, Agnode_t *h)
00576 {
00577 Agedge_t *e;
00578
00579 if (!n || !h)
00580 return NULL;
00581 e = agfindedge(n->graph, n, h);
00582 if (!e)
00583 return NULL;
00584 do {
00585 e = agnxtout(n->graph, e);
00586 if (!e)
00587 return NULL;
00588 } while (e->head == h);
00589 return e->head;
00590 }
00591
00592 Agedge_t *firstedge(Agnode_t *n)
00593 {
00594 if (!n)
00595 return NULL;
00596 return agfstedge(n->graph, n);
00597 }
00598
00599 Agedge_t *nextedge(Agnode_t *n, Agedge_t *e)
00600 {
00601 if (!n || !e)
00602 return NULL;
00603 return agnxtedge(n->graph, e, n);
00604 }
00605
00606 Agedge_t *firstin(Agraph_t *g)
00607 {
00608 Agnode_t *n;
00609
00610 if (!g)
00611 return NULL;
00612 n = agfstnode(g);
00613 if (!n)
00614 return NULL;
00615 return agfstin(g, n);
00616 }
00617
00618 Agedge_t *nextin(Agraph_t *g, Agedge_t *e)
00619 {
00620 Agnode_t *n;
00621 Agedge_t *ne;
00622
00623 if (!g || !e)
00624 return NULL;
00625 ne = agnxtin(g, e);
00626 if (ne)
00627 return (ne);
00628 n = agnxtnode(g, e->head);
00629 if (!n)
00630 return NULL;
00631 return agfstin(g, n);
00632 }
00633
00634 Agedge_t *firstin(Agnode_t *n)
00635 {
00636 if (!n)
00637 return NULL;
00638 return agfstin(n->graph, n);
00639 }
00640
00641 Agedge_t *nextin(Agnode_t *n, Agedge_t *e)
00642 {
00643 if (!n || !e)
00644 return NULL;
00645 return agnxtin(n->graph, e);
00646 }
00647
00648 Agnode_t *firsttail(Agnode_t *n)
00649 {
00650 Agedge_t *e;
00651
00652 if (!n)
00653 return NULL;
00654 e = agfstin(n->graph, n);
00655 if (!e)
00656 return NULL;
00657 return e->tail;
00658 }
00659
00660 Agnode_t *nexttail(Agnode_t *n, Agnode_t *t)
00661 {
00662 Agedge_t *e;
00663
00664 if (!n || !t)
00665 return NULL;
00666 e = agfindedge(n->graph, t, n);
00667 if (!e)
00668 return NULL;
00669 do {
00670 e = agnxtout(n->graph, e);
00671 if (!e)
00672 return NULL;
00673 } while (e->tail == t);
00674 return e->tail;
00675 }
00676
00677 Agnode_t *firstnode(Agraph_t *g)
00678 {
00679 if (!g)
00680 return NULL;
00681 return agfstnode(g);
00682 }
00683
00684 Agnode_t *nextnode(Agraph_t *g, Agnode_t *n)
00685 {
00686 if (!g || !n)
00687 return NULL;
00688 return agnxtnode(g, n);
00689 }
00690
00691 Agnode_t *firstnode(Agedge_t *e)
00692 {
00693 if (!e)
00694 return NULL;
00695 return e->tail;
00696 }
00697
00698 Agnode_t *nextnode(Agedge_t *e, Agnode_t *n)
00699 {
00700 if (!e || n != e->tail)
00701 return NULL;
00702 return e->head;
00703 }
00704
00705 Agsym_t *firstattr(Agraph_t *g)
00706 {
00707 if (!g)
00708 return NULL;
00709 g = g->root;
00710 if (dtsize(g->univ->globattr->dict) == 0)
00711 return NULL;
00712 return g->univ->globattr->list[0];
00713 }
00714
00715 Agsym_t *nextattr(Agraph_t *g, Agsym_t *a)
00716 {
00717 int i;
00718
00719 if (!g || !a)
00720 return NULL;
00721 g = g->root;
00722 for (i = 0; i < dtsize(g->univ->globattr->dict); i++)
00723 if (a == g->univ->globattr->list[i])
00724 break;
00725 i++;
00726 if (i > dtsize(g->univ->globattr->dict))
00727 return NULL;
00728 return g->univ->globattr->list[i];
00729 }
00730
00731 Agsym_t *firstattr(Agnode_t *n)
00732 {
00733 Agraph_t *g;
00734
00735 if (!n)
00736 return NULL;
00737 g = n->graph;
00738 if (dtsize(g->univ->nodeattr->dict) == 0)
00739 return NULL;
00740 return g->univ->nodeattr->list[0];
00741 }
00742
00743 Agsym_t *nextattr(Agnode_t *n, Agsym_t *a)
00744 {
00745 Agraph_t *g;
00746 int i;
00747
00748 if (!n || !a)
00749 return NULL;
00750 g = n->graph;
00751 for (i = 0; i < dtsize(g->univ->nodeattr->dict); i++)
00752 if (a == g->univ->nodeattr->list[i])
00753 break;
00754 i++;
00755 if (i > dtsize(g->univ->nodeattr->dict))
00756 return NULL;
00757 return g->univ->nodeattr->list[i];
00758 }
00759
00760 Agsym_t *firstattr(Agedge_t *e)
00761 {
00762 Agraph_t *g;
00763
00764 if (!e)
00765 return NULL;
00766 g = e->tail->graph;
00767 if (dtsize(g->univ->edgeattr->dict) == 0)
00768 return NULL;
00769 return g->univ->edgeattr->list[0];
00770 }
00771
00772 Agsym_t *nextattr(Agedge_t *e, Agsym_t *a)
00773 {
00774 Agraph_t *g;
00775 int i;
00776
00777 if (!e || !a)
00778 return NULL;
00779 g = e->tail->graph;
00780 for (i = 0; i < dtsize(g->univ->edgeattr->dict); i++)
00781 if (a == g->univ->edgeattr->list[i])
00782 break;
00783 i++;
00784 if (i > dtsize(g->univ->edgeattr->dict))
00785 return NULL;
00786 return g->univ->edgeattr->list[i];
00787 }
00788
00789 bool rm(Agraph_t *g)
00790 {
00791 Agedge_t *e;
00792
00793 if (g->meta_node) {
00794 for (e = agfstout(g->meta_node->graph, g->meta_node); e;
00795 e = agnxtout(g->meta_node->graph, e)) {
00796 rm(agusergraph(e->head));
00797 }
00798 if (g == g->root) {
00799 agclose(g);
00800 } else {
00801 agdelete(g->meta_node->graph, g->meta_node);
00802 }
00803 return true;
00804 }
00805 fprintf(stderr, "subgraph has no meta_node\n");
00806 return false;
00807 }
00808
00809 bool rm(Agnode_t *n)
00810 {
00811
00812 if (n->name[0] == '\001' && strcmp (n->name, "\001proto") ==0)
00813 return false;
00814 agdelete(n->graph, n);
00815 return true;
00816 }
00817
00818 bool rm(Agedge_t *e)
00819 {
00820
00821 if ((e->head->name[0] == '\001' && strcmp (e->head->name, "\001proto") == 0)
00822 || (e->tail->name[0] == '\001' && strcmp (e->tail->name, "\001proto") == 0))
00823 return false;
00824 agdelete(e->head->graph->root, e);
00825 return true;
00826 }
00827
00828 bool layout(Agraph_t *g, char *engine)
00829 {
00830 int err;
00831
00832 err = gvFreeLayout(gvc, g);
00833 err = gvLayout(gvc, g, engine);
00834 return (! err);
00835 }
00836
00837
00838 bool render(Agraph_t *g)
00839 {
00840 attach_attrs(g);
00841 return true;
00842 }
00843
00844
00845 bool render(Agraph_t *g, char *format, char *filename)
00846 {
00847 int err;
00848
00849 err = gvRenderFilename(gvc, g, format, filename);
00850 return (! err);
00851 }
00852
00853
00854 bool render(Agraph_t *g, char *format)
00855 {
00856 int err;
00857
00858 err = gvRender(gvc, g, format, stdout);
00859 return (! err);
00860 }
00861
00862
00863 bool render(Agraph_t *g, char *format, FILE *f)
00864 {
00865 int err;
00866
00867 err = gvRender(gvc, g, format, f);
00868 return (! err);
00869 }
00870
00871
00872 char* renderdata(Agraph_t *g, char *format)
00873 {
00874 int err;
00875 char *data;
00876 unsigned int length;
00877
00878 err = gvRenderData(gvc, g, format, &data, &length);
00879 if (err) return NULL;
00880 data = (char*)realloc(data, length + 1);
00881 if (data) data[length] = '\0';
00882 return data;
00883 }
00884
00885 bool write(Agraph_t *g, FILE *f)
00886 {
00887 int err;
00888
00889 err = agwrite(g, f);
00890 return (! err);
00891 }
00892
00893 bool write(Agraph_t *g, char *filename)
00894 {
00895 FILE *f;
00896 int err;
00897
00898 f = fopen(filename, "w");
00899 if (!f) return false;
00900 err = agwrite(g, f);
00901 fclose(f);
00902 return (! err);
00903 }