1/* struct::tree - critcl - layer 1 declarations
2 * (b) Arc operations.
3 */
4
5#include <arc.h>
6#include <attr.h>
7#include <graph.h>
8#include <util.h>
9
10/* .................................................. */
11
12static GL*  gla_link   (GA* a, GL* i, GN* n, GLA* na);
13static void gla_unlink (GL* i, GLA* na);
14
15/* .................................................. */
16
17GA*
18ga_new (G* g, const char* name, GN* src, GN* dst)
19{
20    GA* a;
21
22    if (Tcl_FindHashEntry (g->arcs.map, name) != NULL) {
23	Tcl_Panic ("struct::graph(c) ga_new - tried to use duplicate name for new arc");
24    }
25
26    a = ALLOC (GA);
27
28    gc_setup ((GC*) a, &g->arcs, name, g);
29    gc_add   ((GC*) a, &g->arcs);
30
31    ga_shimmer_self (a);
32
33    /* node / arc linkage */
34
35    a->start  = gla_link (a, ALLOC (GL), src, &src->out);
36    a->end    = gla_link (a, ALLOC (GL), dst, &dst->in);
37    a->weight = NULL; /* New arcs have no weight */
38
39    return a;
40}
41
42/* .................................................. */
43
44void
45ga_delete (GA* a)
46{
47    gc_remove ((GC*) a, &a->base.graph->arcs);
48    gc_delete ((GC*) a);
49
50    /* interlink removal */
51
52    gla_unlink (a->start, &a->start->n->out);
53    gla_unlink (a->end,   &a->end->n->in);
54
55    ckfree ((char*) a->start); a->start = NULL;
56    ckfree ((char*) a->end);   a->end   = NULL;
57
58    if (a->weight) {
59	Tcl_DecrRefCount (a->weight);
60	a->weight = NULL;
61    }
62
63    ckfree ((char*) a);
64}
65
66/* .................................................. */
67
68void
69ga_mv_src (GA* a, GN* nsrc)
70{
71    GN* src = a->start->n;
72
73    if (src == nsrc) return;
74
75    gla_unlink (a->start, &src->out);
76    gla_link   (a, a->start, nsrc, &nsrc->out);
77}
78
79/* .................................................. */
80
81void
82ga_mv_dst (GA* a, GN* ndst)
83{
84    GN* dst = a->end->n;
85
86    if (dst == ndst) return;
87
88    gla_unlink (a->end, &dst->in);
89    gla_link   (a, a->end, ndst, &ndst->in);
90}
91
92/* .................................................. */
93
94Tcl_Obj*
95ga_serial (GA* a, Tcl_Obj* empty, int nodeId)
96{
97    Tcl_Obj* lv [4];
98
99    lv [0] = a->base.name;
100    lv [1] = Tcl_NewIntObj (nodeId);
101    lv [2] = g_attr_serial (a->base.attr, empty);
102
103    if (a->weight) {
104	lv [3] = a->weight;
105	return Tcl_NewListObj (4, lv);
106    } else {
107	return Tcl_NewListObj (3, lv);
108    }
109}
110
111/* .................................................. */
112
113void
114ga_err_duplicate (Tcl_Interp* interp, Tcl_Obj* a, Tcl_Obj* g)
115{
116    Tcl_Obj* err = Tcl_NewObj ();
117
118    Tcl_AppendToObj    (err, "arc \"", -1);
119    Tcl_AppendObjToObj (err, a);
120    Tcl_AppendToObj    (err, "\" already exists in graph \"", -1);
121    Tcl_AppendObjToObj (err, g);
122    Tcl_AppendToObj    (err, "\"", -1);
123
124    Tcl_SetObjResult (interp, err);
125}
126
127/* .................................................. */
128
129void
130ga_err_missing (Tcl_Interp* interp, Tcl_Obj* a, Tcl_Obj* g)
131{
132    Tcl_Obj* err = Tcl_NewObj ();
133
134    /* Keep any prefix ... */
135    Tcl_AppendObjToObj (err, Tcl_GetObjResult (interp));
136    Tcl_AppendToObj    (err, "arc \"", -1);
137    Tcl_AppendObjToObj (err, a);
138    Tcl_AppendToObj    (err, "\" does not exist in graph \"", -1);
139    Tcl_AppendObjToObj (err, g);
140    Tcl_AppendToObj    (err, "\"", -1);
141
142    Tcl_SetObjResult (interp, err);
143}
144
145/* .................................................. */
146
147static GL*
148gla_link (GA* a, GL* il, GN* n, GLA* na)
149{
150    il->n    = n;
151    il->a    = a;
152
153    if (na->first) {
154	na->first->prev = il;
155    }
156
157    il->prev = NULL;
158    il->next = na->first;
159
160    na->first = il;
161    na->n ++;
162
163    return il;
164}
165
166/* .................................................. */
167
168static void
169gla_unlink (GL* il, GLA* na)
170{
171    if (na->first == il) {
172	na->first = il->next;
173    }
174    if (il->next) {
175	il->next->prev = il->prev;
176    }
177    if (il->prev) {
178	il->prev->next = il->next;
179    }
180
181    il->n    = NULL;
182    il->a    = NULL;
183    il->prev = NULL;
184    il->next = NULL;
185
186    na->n --;
187}
188
189/* .................................................. */
190
191/*
192 * Local Variables:
193 * mode: c
194 * c-basic-offset: 4
195 * fill-column: 78
196 * End:
197 */
198