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