/* ** HYPERTEXT LINK CLASS ** ** (c) COPYRIGHT MIT 1995. ** Please first read the full copyright statement in the file COPYRIGH. ** @(#) $Id: HTLink.c,v 2.2 1998/05/04 19:36:49 frystyk Exp $ ** ** An anchor represents a region of a hypertext document which is ** linked to another anchor in the same or a different document. ** ** History ** Nov 1990 Written in Objective-C for the NeXT browser (TBL) ** 24-Oct-1991 (JFG), written in C, browser-independant ** 21-Nov-1991 (JFG), first complete version ** 3-May-1995 (HF), Added a lot of methods and other stuff made an object ** HF - moved all Link stuff to HTLink */ /* Library include files */ #include "wwwsys.h" #include "WWWUtil.h" #include "HTFormat.h" #include "HTParse.h" #include "HTMethod.h" #include "HTAncMan.h" #include "HTLink.h" /* Implemented here */ /* ------------------------------------------------------------------------- */ PUBLIC HTLink * HTLink_new (void) { HTLink * link; if ((link = (HTLink *) HT_CALLOC(1, sizeof (HTLink))) == NULL) HT_OUTOFMEM("HTLink_new"); return link; } PUBLIC BOOL HTLink_delete (HTLink * me) { HT_FREE(me); return YES; } /* Link me Anchor to another given one ** ------------------------------------- */ PUBLIC BOOL HTLink_add (HTAnchor * source, HTAnchor * destination, HTLinkType type, HTMethod method) { if (source && destination) { if (ANCH_TRACE) HTTrace("Link create. from anchor %p to %p with type %s, method %s\n", (void *) source, (void *) destination, type ? HTAtom_name(type) : "NONE", method != METHOD_INVALID ? HTMethod_name(method) : "NONE"); if (!source->mainLink.dest) { source->mainLink.dest = destination; source->mainLink.type = type; source->mainLink.method = method; } else { HTLink * newLink = HTLink_new(); newLink->dest = destination; newLink->type = type; newLink->method = method; if (!source->links) source->links = HTList_new(); HTList_addObject (source->links, newLink); } if (!destination->parent->sources) destination->parent->sources = HTList_new(); HTList_addObject (destination->parent->sources, source); return YES; } else if (ANCH_TRACE) HTTrace("Link........ Bad argument\n"); return NO; } /* ** Removes link information from one anchor to another. ** Returns YES if OK, else NO */ PUBLIC BOOL HTLink_remove (HTAnchor * source, HTAnchor * destination) { if (!source || !destination) return NO; if (ANCH_TRACE) HTTrace("Link delete. from anchor %p to anchor %p\n", (void *) source, (void *) destination); /* Remove if dest is the main link */ if (source->mainLink.dest == destination) { source->mainLink.dest = NULL; source->mainLink.type = NULL; source->mainLink.method = METHOD_INVALID; source->mainLink.result = HT_LINK_INVALID; return YES; } /* Remove link information for other links */ if (destination->links) { HTList *cur = destination->links; HTLink *pres; while ((pres = (HTLink *) HTList_nextObject(cur))) { if (pres->dest == destination) { HTList_removeObject(destination->links, pres); HT_FREE(pres); return YES; } } } return NO; } /* ** Removes all link information ** Returns YES if OK, else NO */ PUBLIC BOOL HTLink_removeAll (HTAnchor * me) { if (!me) return NO; if (ANCH_TRACE) HTTrace("Link delete. from anchor %p\n", (void *) me); /* Remove if dest is the main link */ me->mainLink.dest = NULL; me->mainLink.type = NULL; me->mainLink.method = METHOD_INVALID; me->mainLink.result = HT_LINK_INVALID; /* Remove link information for other links */ if (me->links) { HTList *cur = me->links; HTLink *pres; while ((pres = (HTLink *) HTList_nextObject(cur))) HT_FREE(pres); HTList_delete(me->links); me->links = NULL; } return YES; } /* ** Moves all link information from one anchor to another. ** This is used in redirection etc. ** Returns YES if OK, else NO */ PUBLIC BOOL HTLink_moveAll (HTAnchor * src, HTAnchor * dest) { if (!src || !dest) return NO; if (ANCH_TRACE) HTTrace("Link move... all from anchor %p to anchor %p\n", (void *) src, (void *) dest); /* Move main link information */ dest->mainLink.dest = src->mainLink.dest; dest->mainLink.type = src->mainLink.type; dest->mainLink.method = src->mainLink.method; dest->mainLink.result = src->mainLink.result; src->mainLink.dest = NULL; src->mainLink.type = NULL; src->mainLink.method = METHOD_INVALID; src->mainLink.result = HT_LINK_INVALID; /* Move link information for other links */ if (dest->links) { HTList *cur = dest->links; HTLink *pres; while ((pres = (HTLink *) HTList_nextObject(cur))) HT_FREE(pres); HTList_delete(dest->links); } dest->links = src->links; src->links = NULL; return YES; } /* ** Find the anchor object between a destination and a source ancher. ** Return link object if any, else NULL */ PUBLIC HTLink * HTLink_find (HTAnchor * src, HTAnchor * dest) { if (src && dest) { if (src->mainLink.dest == dest) return &(src->mainLink); if (src->links) { HTList *cur = src->links; HTLink *pres; while ((pres = (HTLink *) HTList_nextObject(cur)) != NULL) { if (pres->dest == dest) return pres; } } } return NULL; } /* ** Returns a link with a given link type or NULL if nothing found */ PUBLIC HTLink * HTLink_findType (HTAnchor * me, HTLinkType type) { if (me) { HTLink * link = HTAnchor_mainLink(me); HTList * sublinks = HTAnchor_subLinks(me); if (link && link->type==type) return link; else if (sublinks) { while ((link = (HTLink *) HTList_nextObject (sublinks))) if (link->type == type) return link; } } return NULL; } /* ** Link destinations */ PUBLIC BOOL HTLink_setDestination (HTLink * link, HTAnchor * dest) { if (link) { link->dest = dest; return YES; } return NO; } PUBLIC HTAnchor * HTLink_destination (HTLink * link) { return link ? link->dest : NULL; } PUBLIC BOOL HTLink_setType (HTLink * link, HTLinkType type) { if (link) { link->type = type; return YES; } return NO; } PUBLIC HTLinkType HTLink_type (HTLink * link) { return link ? link->type : NULL; } /* ** When a link has been used for posting an object from a source to a ** destination link, the result of the operation is stored as part of the ** link information. */ PUBLIC BOOL HTLink_setResult (HTLink * link, HTLinkResult result) { if (link) { link->result = result; return YES; } return NO; } PUBLIC HTLinkResult HTLink_result (HTLink * link) { return link ? link->result : HT_LINK_INVALID; } PUBLIC BOOL HTLink_setMethod (HTLink * link, HTMethod method) { if (link) { link->method = method; return YES; } return NO; } PUBLIC HTMethod HTLink_method (HTLink * link) { return link ? link->method : METHOD_INVALID; }