/*
This software may only be used by you under license from AT&T Corp.
("AT&T"). A copy of AT&T's Source Code Agreement is available at
AT&T's Internet website having the URL:
<http://www.research.att.com/sw/tools/graphviz/license/source.html>
If you received this software without first entering into a license
with AT&T, you have an infringing copy of this software and cannot use
it without violating AT&T's intellectual property rights.
*/
#pragma prototyped
#include "libgraph.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
static void graphs_of_e(Agedge_t* e, Dict_t* g_e, Agraph_t* g)
{
Agedge_t *sub;
if (dtsearch(g->inedges,e) == NULL) return;
if (dtsearch(g_e,g->meta_node)) return;
dtinsert(g_e,g->meta_node);
for (sub = agfstin(g->meta_node->graph,g->meta_node); sub;
sub = agnxtin(g->meta_node->graph,sub))
graphs_of_e(e,g_e,agusergraph(sub->head));
}
static Agedge_t *esearch(Agraph_t* g, Agnode_t* tail, Agnode_t* head, char *usrkey)
{
Agedge_t key,*e;
char *attr[KEYX+1];
attr[KEYX] = usrkey;
key.tail = tail;
key.head = head;
key.attr = (usrkey?attr:0);
if (usrkey) e = (Agedge_t*)dtsearch(g->inedges,&key);
else {
e = (Agedge_t*)dtnext(g->inedges,&key);
if (e && ((e->tail != tail) || (e->head != head))) e = NULL;
}
return e;
}
Agedge_t *agfindedge(Agraph_t* g, Agnode_t* tail, Agnode_t* head)
{
Agedge_t *e;
e = esearch(g,tail,head,NULL);
if ((e == NULL) && !(AG_IS_DIRECTED(g))) e = esearch(g,head,tail,NULL);
return e;
}
static void
install_edge(Agraph_t* g, Agedge_t* e)
{
Agraph_t *meta;
Agedge_t *f;
if (dtsearch(g->inedges,e)) return;
agINSnode(g,e->tail);
agINSnode(g,e->head);
dtinsert(g->outedges,e);
dtinsert(g->inedges,e);
f = (Agedge_t *) dtprev(g->outedges,e);
if (f && (f->tail == e->tail) && (f->head == e->head) && (e->printkey == NOPRINT)) e->printkey = MULTIPLE;
if (AG_IS_METAGRAPH(g) == FALSE) {
meta = g->meta_node->graph;
for (f = agfstin(meta,g->meta_node); f; f = agnxtin(meta,f)) {
install_edge(agusergraph(f->tail),e);
}
}
}
void agINSedge(Agraph_t* g, Agedge_t* e)
{
if (e->printkey == MULTIPLE) e->printkey = MUSTPRINT;
install_edge(g,e);
}
static int printedge(Dict_t* d, void* p, void* ignored)
{
Agedge_t *e = (Agedge_t*)p;
agerr (AGPREV, "\t%p %s,%s\n",e,e->tail->name,e->head->name);
return 0;
}
Agedge_t * agfstedge(Agraph_t* g, Agnode_t* n)
{
Agedge_t *e;
e = NULL;
if ((g != NULL) && (n != NULL)) {
e = agfstout(g,n);
if (e == NULL) e = agfstin(g,n);
}
return e;
}
Agedge_t * agnxtedge(Agraph_t* g, Agedge_t* e, Agnode_t* n)
{
Agedge_t *f;
f = NULL;
if ((g != NULL) && (e != NULL) && (n != NULL)) {
if (e->tail == n) {
f = (Agedge_t*)dtnext(g->outedges,e);
if ((f != NULL) && (f->tail == n)) return f;
f = agfstin(g,n);
while (f && (f->head == f->tail) && (f->head == n))
f = (Agedge_t*)dtnext(g->inedges,f);
}
else {
if (e->head != n) return NULL;
else f = (Agedge_t*) dtnext(g->inedges,e);
}
while (f && (f->head == f->tail) && (f->head == n))
f = (Agedge_t*)dtnext(g->inedges,f);
if (f && (f->head != n)) f = NULL;
}
return f;
}
Agedge_t * agfstout(Agraph_t* g, Agnode_t* n)
{
Agedge_t *f,key;
f = NULL;
if ((g != NULL) && (n != NULL)) {
key.tail = n;
key.head = NULL;
key.attr = NULL;
f = (Agedge_t*) dtnext(g->outedges,&key);
if (f && (f->tail != n)) f = NULL;
}
return f;
}
Agedge_t * agnxtout(Agraph_t* g, Agedge_t* e)
{
Agedge_t *f;
f = (Agedge_t*) dtnext(g->outedges,e);
if (f && (f->tail != e->tail)) f = NULL;
return f;
}
Agedge_t *agfstin(Agraph_t* g, Agnode_t* n)
{
Agedge_t *f,key;
f = NULL;
if ((g != NULL) && (n != NULL)) {
key.head = n;
key.tail = NULL;
key.attr = NULL;
f = (Agedge_t*) dtnext(g->inedges,&key);
if (f && (f->head != n)) f = NULL;
}
return f;
}
Agedge_t *
agnxtin(Agraph_t* g, Agedge_t* e)
{
Agedge_t *f;
f = (Agedge_t*) dtnext(g->inedges,e);
if (f && (f->head != e->head)) f = NULL;
return f;
}
Agedge_t *
agNEWedge(Agraph_t* subg, Agnode_t* tail, Agnode_t* head, Agedge_t* proto)
{
int i, nobj;
Agedge_t *e;
e = (Agedge_t*) calloc(1,AG.edge_nbytes);
e->tag = TAG_EDGE;
e->tail = tail;
e->head = head;
e->id = subg->univ->max_edge_id++;
nobj = dtsize(subg->univ->edgeattr->dict);
if (nobj)
e->attr = N_NEW(nobj,char*);
else
e->attr = NULL;
for (i = 0; i < nobj; i++) e->attr[i] =
agstrdup(proto? proto->attr[i] : subg->univ->edgeattr->list[i]->value);
return e;
}
Agedge_t *agedge(Agraph_t* g, Agnode_t* tail, Agnode_t* head)
{
Agedge_t *e;
char *keystr,key[SMALLBUF],printkey = NOPRINT;
static int ctr;
keystr = g->proto->e->attr[KEYX]; /* temporarily set aside */
e = NULL;
g->proto->e->head = head;
g->proto->e->tail = tail;
if (AG_IS_STRICT(g)) {
e = esearch(g,tail,head,NULL);
if (!e && !AG_IS_DIRECTED(g))
e = esearch(g,head,tail,NULL);
if (e) install_edge(g,e);
}
else {
if (keystr[0]) {
e = esearch(g,tail,head,keystr);
if (!e && !AG_IS_DIRECTED(g))
e = esearch(g,head,tail,keystr);
if (e) agINSedge(g,e);
else printkey = MUSTPRINT;
}
else {
sprintf(key,"%d",ctr++);
g->proto->e->attr[KEYX] = key;
}
}
if (e == NULL) {
e = agNEWedge(g,tail,head,g->proto->e);
install_edge(g,e);
g->proto->e->head = g->proto->e->tail = g->proto->n;
e->printkey = printkey;
}
g->proto->e->attr[KEYX] = keystr;
return e;
}
void agFREEedge(Agedge_t* e)
{
int i, nobj;
Agdict_t *dict = agdictof(e);
dict = dict;
TAG_OF(e) = -1;
nobj = dtsize(e->tail->graph->univ->edgeattr->dict);
for (i = 0; i < nobj; i++)
agstrfree(e->attr[i]);
free(e->attr);
free(e);
}
void agDELedge(Agraph_t* g, Agedge_t* e)
{
Agraph_t* meta;
Agraph_t* g0;
Agedge_t* f;
if (dtsearch(g->inedges,e) == NULL) {
agerr (AGERR, "...was not found\n");
dtwalk(g->inedges,printedge,NIL(void*));
return;
}
if (AG_IS_METAGRAPH(g) == FALSE) {
meta = g->meta_node->graph;
for (f = agfstout(meta,g->meta_node);
f; f = agnxtout(meta,f)) {
g0 = agusergraph(f->head);
if (dtsearch(g0->inedges,e)) agDELedge(g0,e);
}
}
dtdelete(g->inedges,e);
dtdelete(g->outedges,e);
if (g == g->root) agFREEedge(e);
}
|