1
/* $Id: obj.c,v 1.2 2006/07/08 17:33:49 ellson Exp $ $Revision: 1.2 $ */
2
/* vim:set shiftwidth=4 ts=8: */
4
/**********************************************************
5
* This software is part of the graphviz package *
6
* http://www.graphviz.org/ *
8
* Copyright (c) 1994-2004 AT&T Corp. *
9
* and is licensed under the *
10
* Common Public License, Version 1.0 *
13
* Information and Software Systems Research *
14
* AT&T Research, Florham Park NJ *
15
**********************************************************/
20
int agobjidcmpf(Dict_t * dict, void *arg0, void *arg1, Dtdisc_t * disc)
28
return AGID(obj0) - AGID(obj1);
31
int agobjseqcmpf(Dict_t * dict, void *arg0, void *arg1, Dtdisc_t * disc)
39
return AGSEQ(obj0) - AGSEQ(obj1);
42
Agobj_t *agrebind(Agraph_t * g, Agobj_t * obj)
51
switch (AGTYPE(obj)) {
53
nobj = (Agobj_t *) agsubnode(g, (Agnode_t *) obj, FALSE);
57
nobj = (Agobj_t *) agsubedge(g, (Agedge_t *) obj, FALSE);
64
agerror(AGERROR_BADOBJ, "agrebind");
69
int agdelete(Agraph_t * g, void *obj)
75
&& ((AGTYPE((Agobj_t *) obj) != AGRAPH) || (g != agparent(h))))
76
agerror(AGERROR_WRONGGRAPH, "agdelete");
78
switch (AGTYPE((Agobj_t *) obj)) {
80
return agdelnode(obj);
83
return agdeledge(obj);
87
agerror(AGERROR_BADOBJ, "agdelete");
89
return SUCCESS; /* not reached */
92
int agrename(Agobj_t * obj, char *newname)
95
unsigned long old_id, new_id;
97
switch (AGTYPE(obj)) {
101
/* can we reserve the id corresponding to newname? */
102
if (agmapnametoid(agroot(g), AGTYPE(obj), newname,
103
&new_id, FALSE) == 0)
105
if (new_id == old_id)
107
if (agmapnametoid(agroot(g), AGTYPE(obj), newname,
110
if (agparent(g) && agidsubg(agparent(g), new_id, 0))
112
agfreeid(g, AGRAPH, old_id);
116
return agrelabel_node((Agnode_t *) obj, newname);
124
/* perform initialization/update/finalization method invocation.
125
* skip over nil pointers to next method below.
128
void agmethod_init(Agraph_t * g, void *obj)
130
if (g->clos->callbacks_enabled)
131
aginitcb(obj, g->clos->cb);
133
agrecord_callback(obj, CB_INITIALIZE, NILsym);
136
void aginitcb(void *obj, Agcbstack_t * cbstack)
140
if (cbstack == NIL(Agcbstack_t *))
142
aginitcb(obj, cbstack->prev);
144
switch (AGTYPE(obj)) {
146
fn = cbstack->f->graph.ins;
149
fn = cbstack->f->node.ins;
152
fn = cbstack->f->edge.ins;
156
fn(obj, cbstack->state);
159
void agmethod_upd(Agraph_t * g, void *obj, Agsym_t * sym)
161
if (g->clos->callbacks_enabled)
162
agupdcb(obj, sym, g->clos->cb);
164
agrecord_callback(obj, CB_UPDATE, sym);
167
void agupdcb(void *obj, Agsym_t * sym, Agcbstack_t * cbstack)
171
if (cbstack == NIL(Agcbstack_t *))
173
agupdcb(obj, sym, cbstack->prev);
174
fn = NIL(agobjupdfn_t);
175
switch (AGTYPE(obj)) {
177
fn = cbstack->f->graph.mod;
180
fn = cbstack->f->node.mod;
183
fn = cbstack->f->edge.mod;
187
fn(obj, cbstack->state, sym);
190
void agmethod_delete(Agraph_t * g, void *obj)
192
if (g->clos->callbacks_enabled)
193
agdelcb(obj, g->clos->cb);
195
agrecord_callback(obj, CB_DELETION, NILsym);
198
void agdelcb(void *obj, Agcbstack_t * cbstack)
202
if (cbstack == NIL(Agcbstack_t *))
204
agdelcb(obj, cbstack->prev);
206
switch (AGTYPE(obj)) {
208
fn = cbstack->f->graph.del;
211
fn = cbstack->f->node.del;
214
fn = cbstack->f->edge.del;
218
fn(obj, cbstack->state);
221
Agraph_t *agraphof(void *obj)
223
switch (AGTYPE(obj)) {
226
return ((Agedge_t *) obj)->node->g;
228
return ((Agnode_t *) obj)->g;
230
return (Agraph_t *) obj;
231
default: /* actually can't occur if only 2 bit tags */
232
agerror(AGERROR_BADOBJ, "agraphof");
237
int agisarootobj(void *obj)
239
return (agraphof(obj)->desc.maingraph);
242
/* to manage disciplines */
244
void agpushdisc(Agraph_t * g, Agcbdisc_t * cbd, void *state)
246
Agcbstack_t *stack_ent;
248
stack_ent = AGNEW(g, Agcbstack_t);
250
stack_ent->state = state;
251
stack_ent->prev = g->clos->cb;
252
g->clos->cb = stack_ent;
255
int agpopdisc(Agraph_t * g, Agcbdisc_t * cbd)
257
Agcbstack_t *stack_ent;
259
stack_ent = g->clos->cb;
261
if (stack_ent->f == cbd)
262
g->clos->cb = stack_ent->prev;
264
while (stack_ent && (stack_ent->prev->f != cbd))
265
stack_ent = stack_ent->prev;
266
if (stack_ent && stack_ent->prev)
267
stack_ent->prev = stack_ent->prev->prev;
270
agfree(g, stack_ent);
277
void *aggetuserptr(Agraph_t * g, Agcbdisc_t * cbd)
279
Agcbstack_t *stack_ent;
281
for (stack_ent = g->clos->cb; stack_ent; stack_ent = stack_ent->prev)
282
if (stack_ent->f == cbd)
283
return stack_ent->state;
287
Dtdisc_t Ag_obj_id_disc = {
288
0, /* pass object ptr */
289
0, /* size (ignored) */
290
offsetof(Agobj_t, id_link), /* link offset */
299
Dtdisc_t Ag_obj_seq_disc = {
300
0, /* pass object ptr */
301
0, /* size (ignored) */
302
offsetof(Agobj_t, seq_link), /* link offset */