1 /*
2 ** HYPERTEXT LINK CLASS
3 **
4 ** (c) COPYRIGHT MIT 1995.
5 ** Please first read the full copyright statement in the file COPYRIGH.
6 ** @(#) $Id$
7 **
8 ** An anchor represents a region of a hypertext document which is
9 ** linked to another anchor in the same or a different document.
10 **
11 ** History
12 ** Nov 1990 Written in Objective-C for the NeXT browser (TBL)
13 ** 24-Oct-1991 (JFG), written in C, browser-independant
14 ** 21-Nov-1991 (JFG), first complete version
15 ** 3-May-1995 (HF), Added a lot of methods and other stuff made an object
16 ** HF - moved all Link stuff to HTLink
17 */
18
19 /* Library include files */
20 #include "wwwsys.h"
21 #include "WWWUtil.h"
22 #include "HTFormat.h"
23 #include "HTParse.h"
24 #include "HTMethod.h"
25 #include "HTAncMan.h"
26 #include "HTLink.h" /* Implemented here */
27
28 /* ------------------------------------------------------------------------- */
29
HTLink_new(void)30 PUBLIC HTLink * HTLink_new (void)
31 {
32 HTLink * link;
33 if ((link = (HTLink *) HT_CALLOC(1, sizeof (HTLink))) == NULL)
34 HT_OUTOFMEM("HTLink_new");
35 return link;
36 }
37
HTLink_delete(HTLink * me)38 PUBLIC BOOL HTLink_delete (HTLink * me)
39 {
40 HT_FREE(me);
41 return YES;
42 }
43
44 /* Link me Anchor to another given one
45 ** -------------------------------------
46 */
HTLink_add(HTAnchor * source,HTAnchor * destination,HTLinkType type,HTMethod method)47 PUBLIC BOOL HTLink_add (HTAnchor * source,
48 HTAnchor * destination,
49 HTLinkType type,
50 HTMethod method)
51 {
52 if (source && destination) {
53 HTTRACE(ANCH_TRACE, "Link create. from anchor %p to %p with type %s, method %s\n" _
54 (void *) source _ (void *) destination _
55 type ? HTAtom_name(type) : "NONE" _
56 method != METHOD_INVALID ? HTMethod_name(method) : "NONE");
57 if (!source->mainLink.dest) {
58 source->mainLink.dest = destination;
59 source->mainLink.type = type;
60 source->mainLink.method = method;
61 } else {
62 HTLink * newLink = HTLink_new();
63 newLink->dest = destination;
64 newLink->type = type;
65 newLink->method = method;
66 if (!source->links) source->links = HTList_new();
67 HTList_addObject (source->links, newLink);
68 }
69 if (!destination->parent->sources)
70 destination->parent->sources = HTList_new();
71 HTList_addObject (destination->parent->sources, source);
72 return YES;
73 } else
74 HTTRACE(ANCH_TRACE, "Link........ Bad argument\n");
75 return NO;
76 }
77
78 /*
79 ** Removes link information from one anchor to another.
80 ** Returns YES if OK, else NO
81 */
HTLink_remove(HTAnchor * source,HTAnchor * destination)82 PUBLIC BOOL HTLink_remove (HTAnchor * source, HTAnchor * destination)
83 {
84 if (!source || !destination) return NO;
85 HTTRACE(ANCH_TRACE, "Link delete. from anchor %p to anchor %p\n" _
86 (void *) source _ (void *) destination);
87
88 /* Remove if dest is the main link */
89 if (source->mainLink.dest == destination) {
90 source->mainLink.dest = NULL;
91 source->mainLink.type = NULL;
92 source->mainLink.method = METHOD_INVALID;
93 source->mainLink.result = HT_LINK_INVALID;
94 return YES;
95 }
96
97 /* Remove link information for other links */
98 if (source->links) {
99 HTList *cur = source->links;
100 HTLink *pres;
101 while ((pres = (HTLink *) HTList_nextObject(cur))) {
102 if (pres->dest == destination) {
103 HTList_removeObject(source->links, pres);
104 HT_FREE(pres);
105 return YES;
106 }
107 }
108 }
109 return NO;
110 }
111
112 /*
113 ** Removes all link information
114 ** Returns YES if OK, else NO
115 */
HTLink_removeAll(HTAnchor * me)116 PUBLIC BOOL HTLink_removeAll (HTAnchor * me)
117 {
118 if (!me) return NO;
119 HTTRACE(ANCH_TRACE, "Link delete. from anchor %p\n" _ (void *) me);
120
121 /* Remove if dest is the main link */
122 me->mainLink.dest = NULL;
123 me->mainLink.type = NULL;
124 me->mainLink.method = METHOD_INVALID;
125 me->mainLink.result = HT_LINK_INVALID;
126
127 /* Remove link information for other links */
128 if (me->links) {
129 HTList *cur = me->links;
130 HTLink *pres;
131 while ((pres = (HTLink *) HTList_nextObject(cur)))
132 HT_FREE(pres);
133 HTList_delete(me->links);
134 me->links = NULL;
135 }
136 return YES;
137 }
138
139 /*
140 ** Moves all link information from one anchor to another.
141 ** This is used in redirection etc.
142 ** Returns YES if OK, else NO
143 */
HTLink_moveAll(HTAnchor * src,HTAnchor * dest)144 PUBLIC BOOL HTLink_moveAll (HTAnchor * src, HTAnchor * dest)
145 {
146 if (!src || !dest) return NO;
147 HTTRACE(ANCH_TRACE, "Link move... all from anchor %p to anchor %p\n" _
148 (void *) src _ (void *) dest);
149
150 /* Move main link information */
151 dest->mainLink.dest = src->mainLink.dest;
152 dest->mainLink.type = src->mainLink.type;
153 dest->mainLink.method = src->mainLink.method;
154 dest->mainLink.result = src->mainLink.result;
155
156 src->mainLink.dest = NULL;
157 src->mainLink.type = NULL;
158 src->mainLink.method = METHOD_INVALID;
159 src->mainLink.result = HT_LINK_INVALID;
160
161 /* Move link information for other links */
162 if (dest->links) {
163 HTList *cur = dest->links;
164 HTLink *pres;
165 while ((pres = (HTLink *) HTList_nextObject(cur)))
166 HT_FREE(pres);
167 HTList_delete(dest->links);
168 }
169 dest->links = src->links;
170 src->links = NULL;
171 return YES;
172 }
173
174 /*
175 ** Find the anchor object between a destination and a source ancher.
176 ** Return link object if any, else NULL
177 */
HTLink_find(HTAnchor * src,HTAnchor * dest)178 PUBLIC HTLink * HTLink_find (HTAnchor * src, HTAnchor * dest)
179 {
180 if (src && dest) {
181 if (src->mainLink.dest == dest)
182 return &(src->mainLink);
183 if (src->links) {
184 HTList *cur = src->links;
185 HTLink *pres;
186 while ((pres = (HTLink *) HTList_nextObject(cur)) != NULL) {
187 if (pres->dest == dest)
188 return pres;
189 }
190 }
191 }
192 return NULL;
193 }
194
195 /*
196 ** Returns a link with a given link type or NULL if nothing found
197 */
HTLink_findType(HTAnchor * me,HTLinkType type)198 PUBLIC HTLink * HTLink_findType (HTAnchor * me, HTLinkType type)
199 {
200 if (me) {
201 HTLink * link = HTAnchor_mainLink(me);
202 HTList * sublinks = HTAnchor_subLinks(me);
203 if (link && link->type==type)
204 return link;
205 else if (sublinks) {
206 while ((link = (HTLink *) HTList_nextObject (sublinks)))
207 if (link->type == type) return link;
208 }
209 }
210 return NULL;
211 }
212
213 /*
214 ** Link destinations
215 */
HTLink_setDestination(HTLink * link,HTAnchor * dest)216 PUBLIC BOOL HTLink_setDestination (HTLink * link, HTAnchor * dest)
217 {
218 if (link) {
219 link->dest = dest;
220 return YES;
221 }
222 return NO;
223 }
224
HTLink_destination(HTLink * link)225 PUBLIC HTAnchor * HTLink_destination (HTLink * link)
226 {
227 return link ? link->dest : NULL;
228 }
229
HTLink_setType(HTLink * link,HTLinkType type)230 PUBLIC BOOL HTLink_setType (HTLink * link, HTLinkType type)
231 {
232 if (link) {
233 link->type = type;
234 return YES;
235 }
236 return NO;
237 }
238
HTLink_type(HTLink * link)239 PUBLIC HTLinkType HTLink_type (HTLink * link)
240 {
241 return link ? link->type : NULL;
242 }
243
244 /*
245 ** When a link has been used for posting an object from a source to a
246 ** destination link, the result of the operation is stored as part of the
247 ** link information.
248 */
HTLink_setResult(HTLink * link,HTLinkResult result)249 PUBLIC BOOL HTLink_setResult (HTLink * link, HTLinkResult result)
250 {
251 if (link) {
252 link->result = result;
253 return YES;
254 }
255 return NO;
256 }
257
HTLink_result(HTLink * link)258 PUBLIC HTLinkResult HTLink_result (HTLink * link)
259 {
260 return link ? link->result : HT_LINK_INVALID;
261 }
262
HTLink_setMethod(HTLink * link,HTMethod method)263 PUBLIC BOOL HTLink_setMethod (HTLink * link, HTMethod method)
264 {
265 if (link) {
266 link->method = method;
267 return YES;
268 }
269 return NO;
270 }
271
HTLink_method(HTLink * link)272 PUBLIC HTMethod HTLink_method (HTLink * link)
273 {
274 return link ? link->method : METHOD_INVALID;
275 }
276