diff options
Diffstat (limited to 'WWW/Library/Implementation/HTAnchor.c')
-rw-r--r-- | WWW/Library/Implementation/HTAnchor.c | 1468 |
1 files changed, 0 insertions, 1468 deletions
diff --git a/WWW/Library/Implementation/HTAnchor.c b/WWW/Library/Implementation/HTAnchor.c deleted file mode 100644 index a3ebaeb7..00000000 --- a/WWW/Library/Implementation/HTAnchor.c +++ /dev/null @@ -1,1468 +0,0 @@ -/* - * $LynxId: HTAnchor.c,v 1.71 2012/02/03 01:52:50 tom Exp $ - * - * Hypertext "Anchor" Object HTAnchor.c - * ========================== - * - * 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-independent - * 21-Nov-1991 (JFG), first complete version - * - * (c) Copyright CERN 1991 - See Copyright.html - */ - -#define HASH_SIZE 1001 /* Arbitrary prime. Memory/speed tradeoff */ - -#include <HTUtils.h> -#include <HTAnchor.h> -#include <HTParse.h> -#include <HTString.h> -#include <UCAux.h> -#include <UCMap.h> - -#include <GridText.h> -#include <LYUtils.h> -#include <LYCharSets.h> -#include <LYUtils.h> -#include <LYLeaks.h> - -#define HASH_TYPE unsigned short - -#ifdef NOT_DEFINED -/* - * This is the hashing function used to determine which list in the - * adult_table a parent anchor should be put in. This is a - * much simpler function than the original used. - */ -#define HASH_FUNCTION(cp_address) \ - ( (HASH_TYPE)strlen(cp_address) *\ - (HASH_TYPE)TOUPPER(*cp_address) % HASH_SIZE ) -#endif /* NOT_DEFINED */ - -/* - * This is the original function. We'll use it again. - FM - */ -static HASH_TYPE HASH_FUNCTION(const char *cp_address) -{ - HASH_TYPE hash; - const unsigned char *p; - - for (p = (const unsigned char *) cp_address, hash = 0; *p; p++) - hash = (HASH_TYPE) (hash * 3 + (*(const unsigned char *) p)) % HASH_SIZE; - - return (hash); -} - -typedef struct _HyperDoc Hyperdoc; - -#ifdef VMS -struct _HyperDoc { - int junk; /* VMS cannot handle pointers to undefined structs */ -}; -#endif /* VMS */ - -/* Table of lists of all parents */ -static HTList adult_table[HASH_SIZE] = -{ - {NULL, NULL}}; - -/* Creation Methods - * ================ - * - * Do not use "new" by itself outside this module. In order to enforce - * consistency, we insist that you furnish more information about the - * anchor you are creating : use newWithParent or newWithAddress. - */ -static HTParentAnchor0 *HTParentAnchor0_new(const char *address, - unsigned hash) -{ - HTParentAnchor0 *newAnchor = typecalloc(HTParentAnchor0); - - if (newAnchor == NULL) - outofmem(__FILE__, "HTParentAnchor0_new"); - - assert(newAnchor != NULL); - - newAnchor->parent = newAnchor; /* self */ - StrAllocCopy(newAnchor->address, address); - newAnchor->adult_hash = (HASH_TYPE) hash; - - return (newAnchor); -} - -static HTParentAnchor *HTParentAnchor_new(HTParentAnchor0 *parent) -{ - HTParentAnchor *newAnchor = typecalloc(HTParentAnchor); - - if (newAnchor == NULL) - outofmem(__FILE__, "HTParentAnchor_new"); - - assert(newAnchor != NULL); - - newAnchor->parent = parent; /* cross reference */ - parent->info = newAnchor; /* cross reference */ - newAnchor->address = parent->address; /* copy pointer */ - - newAnchor->isISMAPScript = FALSE; /* Lynx appends ?0,0 if TRUE. - FM */ - newAnchor->isHEAD = FALSE; /* HEAD request if TRUE. - FM */ - newAnchor->safe = FALSE; /* Safe. - FM */ - newAnchor->no_cache = FALSE; /* no-cache? - FM */ - newAnchor->inBASE = FALSE; /* duplicated from HTML.c/h */ - newAnchor->content_length = 0; /* Content-Length. - FM */ - return (newAnchor); -} - -static HTChildAnchor *HTChildAnchor_new(HTParentAnchor0 *parent) -{ - HTChildAnchor *p = typecalloc(HTChildAnchor); - - if (p == NULL) - outofmem(__FILE__, "HTChildAnchor_new"); - - assert(p != NULL); - - p->parent = parent; /* parent reference */ - return p; -} - -static HTChildAnchor *HText_pool_ChildAnchor_new(HTParentAnchor *parent) -{ - HTChildAnchor *p = (HTChildAnchor *) HText_pool_calloc((HText *) (parent->document), - (unsigned) sizeof(HTChildAnchor)); - - if (p == NULL) - outofmem(__FILE__, "HText_pool_ChildAnchor_new"); - - assert(p != NULL); - - p->parent = parent->parent; /* parent reference */ - return p; -} - -#ifdef CASE_INSENSITIVE_ANCHORS -/* Case insensitive string comparison */ -#define HT_EQUIV(a,b) (TOUPPER(a) == TOUPPER(b)) -#else -/* Case sensitive string comparison */ -#define HT_EQUIV(a,b) ((a) == (b)) -#endif - -/* Null-terminated string comparison - * --------------------------------- - * On entry, - * s Points to one string, null terminated - * t points to the other. - * On exit, - * returns YES if the strings are equivalent - * NO if they differ. - */ -static BOOL HTSEquivalent(const char *s, - const char *t) -{ - if (s && t) { /* Make sure they point to something */ - for (; *s && *t; s++, t++) { - if (!HT_EQUIV(*s, *t)) { - return (NO); - } - } - return (BOOL) (HT_EQUIV(*s, *t)); - } else { - return (BOOL) (s == t); /* Two NULLs are equivalent, aren't they ? */ - } -} - -/* Binary string comparison - * ------------------------ - * On entry, - * s Points to one bstring - * t points to the other. - * On exit, - * returns YES if the strings are equivalent - * NO if they differ. - */ -static BOOL HTBEquivalent(const bstring *s, - const bstring *t) -{ - if (s && t && BStrLen(s) == BStrLen(t)) { - int j; - int len = BStrLen(s); - - for (j = 0; j < len; ++j) { - if (!HT_EQUIV(BStrData(s)[j], BStrData(t)[j])) { - return (NO); - } - } - return (YES); - } else { - return (BOOL) (s == t); /* Two NULLs are equivalent, aren't they ? */ - } -} - -/* - * Three-way compare function - */ -static int compare_anchors(void *l, - void *r) -{ - const char *a = ((HTChildAnchor *) l)->tag; - const char *b = ((HTChildAnchor *) r)->tag; - - /* both tags are not NULL */ - -#ifdef CASE_INSENSITIVE_ANCHORS - return strcasecomp(a, b); /* Case insensitive */ -#else - return strcmp(a, b); /* Case sensitive - FM */ -#endif /* CASE_INSENSITIVE_ANCHORS */ -} - -/* Create new or find old sub-anchor - * --------------------------------- - * - * This one is for a named child. - * The parent anchor must already exist. - */ -static HTChildAnchor *HTAnchor_findNamedChild(HTParentAnchor0 *parent, - const char *tag) -{ - HTChildAnchor *child; - - if (parent && tag && *tag) { /* TBL */ - if (parent->children) { - /* - * Parent has children. Search them. - */ - HTChildAnchor sample; - - sample.tag = (char *) tag; /* for compare_anchors() only */ - - child = (HTChildAnchor *) HTBTree_search(parent->children, &sample); - if (child != NULL) { - CTRACE((tfp, - "Child anchor %p of parent %p with name `%s' already exists.\n", - (void *) child, (void *) parent, tag)); - return (child); - } - } else { /* parent doesn't have any children yet : create family */ - parent->children = HTBTree_new(compare_anchors); - } - - child = HTChildAnchor_new(parent); - CTRACE((tfp, "HTAnchor: New Anchor %p named `%s' is child of %p\n", - (void *) child, - NonNull(tag), - (void *) child->parent)); - - StrAllocCopy(child->tag, tag); /* should be set before HTBTree_add */ - HTBTree_add(parent->children, child); - return (child); - - } else { - CTRACE((tfp, "HTAnchor_findNamedChild called with NULL parent.\n")); - return (NULL); - } - -} - -/* - * This one is for a new unnamed child being edited into an existing - * document. The parent anchor and the document must already exist. - * (Just add new unnamed child). - */ -static HTChildAnchor *HTAnchor_addChild(HTParentAnchor *parent) -{ - HTChildAnchor *child; - - if (!parent) { - CTRACE((tfp, "HTAnchor_addChild called with NULL parent.\n")); - return (NULL); - } - - child = HText_pool_ChildAnchor_new(parent); - CTRACE((tfp, "HTAnchor: New unnamed Anchor %p is child of %p\n", - (void *) child, - (void *) child->parent)); - - child->tag = 0; - HTList_linkObject(&parent->children_notag, child, &child->_add_children_notag); - - return (child); -} - -static HTParentAnchor0 *HTAnchor_findAddress_in_adult_table(const DocAddress *newdoc); - -static BOOL HTAnchor_link(HTChildAnchor *child, - HTAnchor * destination, - HTLinkType *type); - -/* Create or find a child anchor with a possible link - * -------------------------------------------------- - * - * Create new anchor with a given parent and possibly - * a name, and possibly a link to a _relatively_ named anchor. - * (Code originally in ParseHTML.h) - */ -HTChildAnchor *HTAnchor_findChildAndLink(HTParentAnchor *parent, /* May not be 0 */ - const char *tag, /* May be "" or 0 */ - const char *href, /* May be "" or 0 */ - HTLinkType *ltype) /* May be 0 */ -{ - HTChildAnchor *child; - - CTRACE((tfp, "Entered HTAnchor_findChildAndLink: tag=`%s',%s href=`%s'\n", - NonNull(tag), - (ltype == HTInternalLink) ? " (internal link)" : "", - NonNull(href))); - - if (tag && *tag) { - child = HTAnchor_findNamedChild(parent->parent, tag); - } else { - child = HTAnchor_addChild(parent); - } - - if (href && *href) { - const char *fragment = NULL; - HTParentAnchor0 *dest; - - if (ltype == HTInternalLink && *href == '#') { - dest = parent->parent; - } else { - const char *relative_to = ((parent->inBASE && *href != '#') - ? parent->content_base - : parent->address); - DocAddress parsed_doc; - - parsed_doc.address = HTParse(href, relative_to, - PARSE_ALL_WITHOUT_ANCHOR); - - parsed_doc.post_data = NULL; - parsed_doc.post_content_type = NULL; - if (ltype && parent->post_data && ltype == HTInternalLink) { - /* for internal links, find a destination with the same - post data if the source of the link has post data. - kw - Example: LYNXIMGMAP: */ - parsed_doc.post_data = parent->post_data; - parsed_doc.post_content_type = parent->post_content_type; - } - parsed_doc.bookmark = NULL; - parsed_doc.isHEAD = FALSE; - parsed_doc.safe = FALSE; - - dest = HTAnchor_findAddress_in_adult_table(&parsed_doc); - FREE(parsed_doc.address); - } - - /* - * [from HTAnchor_findAddress()] - * If the address represents a sub-anchor, we load its parent (above), - * then we create a named child anchor within that parent. - */ - fragment = (*href == '#') ? href + 1 : HTParseAnchor(href); - - if (*fragment) - dest = (HTParentAnchor0 *) HTAnchor_findNamedChild(dest, fragment); - - if (tag && *tag) { - if (child->dest) { /* DUPLICATE_ANCHOR_NAME_WORKAROUND - kw */ - CTRACE((tfp, - "*** Duplicate ChildAnchor %p named `%s'", - (void *) child, tag)); - if ((HTAnchor *) dest != child->dest || ltype != child->type) { - CTRACE((tfp, - ", different dest %p or type, creating unnamed child\n", - (void *) child->dest)); - child = HTAnchor_addChild(parent); - } - } - } - HTAnchor_link(child, (HTAnchor *) dest, ltype); - } - return child; -} - -/* Create new or find old parent anchor - * ------------------------------------ - * - * Me one is for a reference which is found in a document, and might - * not be already loaded. - * Note: You are not guaranteed a new anchor -- you might get an old one, - * like with fonts. - */ -HTParentAnchor *HTAnchor_findAddress(const DocAddress *newdoc) -{ - /* Anchor tag specified ? */ - const char *tag = HTParseAnchor(newdoc->address); - - CTRACE((tfp, "Entered HTAnchor_findAddress\n")); - - /* - * If the address represents a sub-anchor, we load its parent, then we - * create a named child anchor within that parent. - */ - if (*tag) { - DocAddress parsed_doc; - HTParentAnchor0 *foundParent; - - parsed_doc.address = HTParse(newdoc->address, "", - PARSE_ALL_WITHOUT_ANCHOR); - parsed_doc.post_data = newdoc->post_data; - parsed_doc.post_content_type = newdoc->post_content_type; - parsed_doc.bookmark = newdoc->bookmark; - parsed_doc.isHEAD = newdoc->isHEAD; - parsed_doc.safe = newdoc->safe; - - foundParent = HTAnchor_findAddress_in_adult_table(&parsed_doc); - (void) HTAnchor_findNamedChild(foundParent, tag); - FREE(parsed_doc.address); - return HTAnchor_parent((HTAnchor *) foundParent); - } - return HTAnchor_parent((HTAnchor *) HTAnchor_findAddress_in_adult_table(newdoc)); -} - -/* The address has no anchor tag, for sure. - */ -static HTParentAnchor0 *HTAnchor_findAddress_in_adult_table(const DocAddress *newdoc) -{ - /* - * Check whether we have this node. - */ - HASH_TYPE hash; - HTList *adults; - HTList *grownups; - HTParentAnchor0 *foundAnchor; - BOOL need_extra_info = (BOOL) (newdoc->post_data || - newdoc->post_content_type || - newdoc->bookmark || - newdoc->isHEAD || - newdoc->safe); - - /* - * We need not free adult_table[] atexit - it should be perfectly empty - * after free'ing all HText's. (There is an error if it is not empty at - * exit). -LP - */ - - /* - * Select list from hash table, - */ - hash = HASH_FUNCTION(newdoc->address); - adults = &(adult_table[hash]); - - /* - * Search list for anchor. - */ - grownups = adults; - while (NULL != (foundAnchor = - (HTParentAnchor0 *) HTList_nextObject(grownups))) { - if (HTSEquivalent(foundAnchor->address, newdoc->address) && - - ((!foundAnchor->info && !need_extra_info) || - (foundAnchor->info && - HTBEquivalent(foundAnchor->info->post_data, newdoc->post_data) && - foundAnchor->info->isHEAD == newdoc->isHEAD))) { - CTRACE((tfp, "Anchor %p with address `%s' already exists.\n", - (void *) foundAnchor, newdoc->address)); - return foundAnchor; - } - } - - /* - * Node not found: create new anchor. - */ - foundAnchor = HTParentAnchor0_new(newdoc->address, hash); - CTRACE((tfp, "New anchor %p has hash %d and address `%s'\n", - (void *) foundAnchor, hash, newdoc->address)); - - if (need_extra_info) { - /* rare case, create a big structure */ - HTParentAnchor *p = HTParentAnchor_new(foundAnchor); - - if (newdoc->post_data) - BStrCopy(p->post_data, newdoc->post_data); - if (newdoc->post_content_type) - StrAllocCopy(p->post_content_type, - newdoc->post_content_type); - if (newdoc->bookmark) - StrAllocCopy(p->bookmark, newdoc->bookmark); - p->isHEAD = newdoc->isHEAD; - p->safe = newdoc->safe; - } - HTList_linkObject(adults, foundAnchor, &foundAnchor->_add_adult); - - return foundAnchor; -} - -/* Create new or find old named anchor - simple form - * ------------------------------------------------- - * - * Like HTAnchor_findAddress, but simpler to use for simple cases. - * No post data etc. can be supplied. - kw - */ -HTParentAnchor *HTAnchor_findSimpleAddress(const char *url) -{ - DocAddress urldoc; - - urldoc.address = (char *) url; /* ignore warning, it IS treated like const - kw */ - urldoc.post_data = NULL; - urldoc.post_content_type = NULL; - urldoc.bookmark = NULL; - urldoc.isHEAD = FALSE; - urldoc.safe = FALSE; - return HTAnchor_findAddress(&urldoc); -} - -/* Link me Anchor to another given one - * ------------------------------------- - */ -static BOOL HTAnchor_link(HTChildAnchor *child, - HTAnchor * destination, - HTLinkType *type) -{ - if (!(child && destination)) - return (NO); /* Can't link to/from non-existing anchor */ - - CTRACE((tfp, "Linking child %p to anchor %p\n", (void *) child, (void *) destination)); - if (child->dest) { - CTRACE((tfp, "*** child anchor already has destination, exiting!\n")); - return (NO); - } - - child->dest = destination; - child->type = type; - - if (child->parent != destination->parent) - /* link only foreign children */ - HTList_linkObject(&destination->parent->sources, child, &child->_add_sources); - - return (YES); /* Success */ -} - -/* Delete an anchor and possibly related things (auto garbage collection) - * -------------------------------------------- - * - * The anchor is only deleted if the corresponding document is not loaded. - * All outgoing links from children are deleted, and children are - * removed from the sources lists of theirs targets. - * We also try to delete the targets whose documents are not loaded. - * If this anchor's sources list is empty, we delete it and its children. - */ - -/* - * Recursively try to delete destination anchor of this child. - * In any event, this will tell destination anchor that we - * no longer consider it a destination. - */ -static void deleteLinks(HTChildAnchor *me) -{ - /* - * Unregister me with our destination anchor's parent. - */ - if (me->dest) { - HTParentAnchor0 *parent = me->dest->parent; - - /* - * Start. Set the dest pointer to zero. - */ - me->dest = NULL; - - /* - * Remove me from the parent's sources so that the parent knows one - * less anchor is its dest. - */ - if ((me->parent != parent) && !HTList_isEmpty(&parent->sources)) { - /* - * Really should only need to deregister once. - */ - HTList_unlinkObject(&parent->sources, (void *) me); - } - - /* - * Recursive call. Test here to avoid calling overhead. Don't delete - * if document is loaded or being loaded. - */ - if ((me->parent != parent) && - parent != NULL && - !parent->underway && - (!parent->info || !parent->info->document)) { - HTAnchor_delete(parent); - } - - /* - * At this point, we haven't a destination. Set it to be so. Leave - * the HTAtom pointed to by type up to other code to handle (reusable, - * near static). - */ - me->type = NULL; - } -} - -static void HTParentAnchor_free(HTParentAnchor *me); - -BOOL HTAnchor_delete(HTParentAnchor0 *me) -{ - /* - * Memory leaks fixed. - * 05-27-94 Lynx 2-3-1 Garrett Arch Blythe - */ - HTBTElement *ele; - HTChildAnchor *child; - - /* - * Do nothing if nothing to do. - */ - if (!me) { - return (NO); - } - - /* - * Don't delete if document is loaded or being loaded. - */ - if (me->underway || (me->info && me->info->document)) { - return (NO); - } - - /* - * Mark ourselves busy, so that recursive calls of this function on this - * HTParentAnchor0 will not free it from under our feet. - kw - */ - me->underway = TRUE; - - { - /* - * Delete all outgoing links from named children. Do not delete named - * children itself (may have incoming links). - */ - if (me->children) { - ele = HTBTree_next(me->children, NULL); - while (ele != NULL) { - child = (HTChildAnchor *) HTBTree_object(ele); - if (child->dest) - deleteLinks(child); - ele = HTBTree_next(me->children, ele); - } - } - } - me->underway = FALSE; - - /* - * There are still incoming links to this one (we are the - * destination of another anchor). - */ - if (!HTList_isEmpty(&me->sources)) { - /* - * Can't delete parent, still have sources. - */ - return (NO); - } - - /* - * No more incoming and outgoing links : kill everything First, delete - * named children. - */ - if (me->children) { - ele = HTBTree_next(me->children, NULL); - while (ele != NULL) { - child = (HTChildAnchor *) HTBTree_object(ele); - FREE(child->tag); - FREE(child); - ele = HTBTree_next(me->children, ele); - } - HTBTree_free(me->children); - } - - /* - * Delete the ParentAnchor, if any. (Document was already deleted). - */ - if (me->info) { - HTParentAnchor_free(me->info); - FREE(me->info); - } - - /* - * Remove ourselves from the hash table's list. - */ - HTList_unlinkObject(&(adult_table[me->adult_hash]), (void *) me); - - /* - * Free the address. - */ - FREE(me->address); - - /* - * Finally, kill the parent anchor passed in. - */ - FREE(me); - - return (YES); -} - -/* - * Unnamed children (children_notag) have no sence without HText - delete them - * and their links if we are about to free HText. Document currently exists. - * Called within HText_free(). - */ -void HTAnchor_delete_links(HTParentAnchor *me) -{ - HTList *cur; - HTChildAnchor *child; - - /* - * Do nothing if nothing to do. - */ - if (!me || !me->document) { - return; - } - - /* - * Mark ourselves busy, so that recursive calls on this HTParentAnchor0 - * will not free it from under our feet. - kw - */ - me->parent->underway = TRUE; - - /* - * Delete all outgoing links from unnamed children. - */ - if (!HTList_isEmpty(&me->children_notag)) { - cur = &me->children_notag; - while ((child = - (HTChildAnchor *) HTList_unlinkLastObject(cur)) != 0) { - deleteLinks(child); - /* child allocated in HText pool, HText_free() will free it later */ - } - } - me->parent->underway = FALSE; -} - -static void HTParentAnchor_free(HTParentAnchor *me) -{ - /* - * Delete the methods list. - */ - if (me->methods) { - /* - * Leave what the methods point to up in memory for other code (near - * static stuff). - */ - HTList_delete(me->methods); - me->methods = NULL; - } - - /* - * Free up all allocated members. - */ - FREE(me->charset); - FREE(me->isIndexAction); - FREE(me->isIndexPrompt); - FREE(me->title); - FREE(me->physical); - BStrFree(me->post_data); - FREE(me->post_content_type); - FREE(me->bookmark); - FREE(me->owner); - FREE(me->RevTitle); - FREE(me->citehost); -#ifdef USE_SOURCE_CACHE - HTAnchor_clearSourceCache(me); -#endif - if (me->FileCache) { - FILE *fd; - - if ((fd = fopen(me->FileCache, "r")) != NULL) { - fclose(fd); - remove(me->FileCache); - } - FREE(me->FileCache); - } - FREE(me->SugFname); - FREE(me->cache_control); -#ifdef EXP_HTTP_HEADERS - HTChunkClear(&(me->http_headers)); -#endif - FREE(me->content_type_params); - FREE(me->content_type); - FREE(me->content_language); - FREE(me->content_encoding); - FREE(me->content_base); - FREE(me->content_disposition); - FREE(me->content_location); - FREE(me->content_md5); - FREE(me->message_id); - FREE(me->subject); - FREE(me->date); - FREE(me->expires); - - FREE(me->last_modified); - FREE(me->ETag); - FREE(me->server); -#ifdef USE_COLOR_STYLE - FREE(me->style); -#endif - - /* - * Original code wanted a way to clean out the HTFormat if no longer needed - * (ref count?). I'll leave it alone since those HTAtom objects are a - * little harder to know where they are being referenced all at one time. - * (near static) - */ - - FREE(me->UCStages); - ImageMapList_free(me->imaps); -} - -#ifdef USE_SOURCE_CACHE -void HTAnchor_clearSourceCache(HTParentAnchor *me) -{ - /* - * Clean up the source cache, if any. - */ - if (me->source_cache_file) { - CTRACE((tfp, "SourceCache: Removing file %s\n", - me->source_cache_file)); - LYRemoveTemp(me->source_cache_file); - FREE(me->source_cache_file); - } - if (me->source_cache_chunk) { - CTRACE((tfp, "SourceCache: Removing memory chunk %p\n", - (void *) me->source_cache_chunk)); - HTChunkFree(me->source_cache_chunk); - me->source_cache_chunk = NULL; - } -} -#endif /* USE_SOURCE_CACHE */ - -/* Data access functions - * --------------------- - */ -HTParentAnchor *HTAnchor_parent(HTAnchor * me) -{ - if (!me) - return NULL; - - if (me->parent->info) - return me->parent->info; - - /* else: create a new structure */ - return HTParentAnchor_new(me->parent); -} - -void HTAnchor_setDocument(HTParentAnchor *me, - HyperDoc *doc) -{ - if (me) - me->document = doc; -} - -HyperDoc *HTAnchor_document(HTParentAnchor *me) -{ - return (me ? me->document : NULL); -} - -char *HTAnchor_address(HTAnchor * me) -{ - char *addr = NULL; - - if (me) { - if (((HTParentAnchor0 *) me == me->parent) || - ((HTParentAnchor *) me == me->parent->info) || - !((HTChildAnchor *) me)->tag) { /* it's an adult or no tag */ - StrAllocCopy(addr, me->parent->address); - } else { /* it's a named child */ - HTSprintf0(&addr, "%s#%s", - me->parent->address, ((HTChildAnchor *) me)->tag); - } - } - return (addr); -} - -void HTAnchor_setFormat(HTParentAnchor *me, - HTFormat form) -{ - if (me) - me->format = form; -} - -HTFormat HTAnchor_format(HTParentAnchor *me) -{ - return (me ? me->format : NULL); -} - -void HTAnchor_setIndex(HTParentAnchor *me, - const char *address) -{ - if (me) { - me->isIndex = YES; - StrAllocCopy(me->isIndexAction, address); - } -} - -void HTAnchor_setPrompt(HTParentAnchor *me, - const char *prompt) -{ - if (me) { - StrAllocCopy(me->isIndexPrompt, prompt); - } -} - -BOOL HTAnchor_isIndex(HTParentAnchor *me) -{ - return (BOOL) (me - ? me->isIndex - : NO); -} - -/* Whether Anchor has been designated as an ISMAP link - * (normally by presence of an ISMAP attribute on A or IMG) - KW - */ -BOOL HTAnchor_isISMAPScript(HTAnchor * me) -{ - return (BOOL) ((me && me->parent->info) - ? me->parent->info->isISMAPScript - : NO); -} - -#if defined(USE_COLOR_STYLE) -/* Style handling. -*/ -const char *HTAnchor_style(HTParentAnchor *me) -{ - return (me ? me->style : NULL); -} - -void HTAnchor_setStyle(HTParentAnchor *me, - const char *style) -{ - if (me) { - StrAllocCopy(me->style, style); - } -} -#endif - -/* Title handling. -*/ -const char *HTAnchor_title(HTParentAnchor *me) -{ - return (me ? me->title : NULL); -} - -void HTAnchor_setTitle(HTParentAnchor *me, - const char *title) -{ - int i; - - if (me) { - if (title) { - StrAllocCopy(me->title, title); - for (i = 0; me->title[i]; i++) { - if (UCH(me->title[i]) == 1 || - UCH(me->title[i]) == 2) { - me->title[i] = ' '; - } - } - } else { - CTRACE((tfp, "HTAnchor_setTitle: New title is NULL! ")); - if (me->title) { - CTRACE((tfp, "Old title was \"%s\".\n", me->title)); - FREE(me->title); - } else { - CTRACE((tfp, "Old title was NULL.\n")); - } - } - } -} - -void HTAnchor_appendTitle(HTParentAnchor *me, - const char *title) -{ - int i; - - if (me) { - StrAllocCat(me->title, title); - for (i = 0; me->title[i]; i++) { - if (UCH(me->title[i]) == 1 || - UCH(me->title[i]) == 2) { - me->title[i] = ' '; - } - } - } -} - -/* Bookmark handling. -*/ -const char *HTAnchor_bookmark(HTParentAnchor *me) -{ - return (me ? me->bookmark : NULL); -} - -void HTAnchor_setBookmark(HTParentAnchor *me, - const char *bookmark) -{ - if (me) - StrAllocCopy(me->bookmark, bookmark); -} - -/* Owner handling. -*/ -const char *HTAnchor_owner(HTParentAnchor *me) -{ - return (me ? me->owner : NULL); -} - -void HTAnchor_setOwner(HTParentAnchor *me, - const char *owner) -{ - if (me) { - StrAllocCopy(me->owner, owner); - } -} - -/* TITLE handling in LINKs with REV="made" or REV="owner". - FM -*/ -const char *HTAnchor_RevTitle(HTParentAnchor *me) -{ - return (me ? me->RevTitle : NULL); -} - -void HTAnchor_setRevTitle(HTParentAnchor *me, - const char *title) -{ - int i; - - if (me) { - StrAllocCopy(me->RevTitle, title); - for (i = 0; me->RevTitle[i]; i++) { - if (UCH(me->RevTitle[i]) == 1 || - UCH(me->RevTitle[i]) == 2) { - me->RevTitle[i] = ' '; - } - } - } -} - -#ifndef DISABLE_BIBP -/* Citehost for bibp links from LINKs with REL="citehost". - RDC -*/ -const char *HTAnchor_citehost(HTParentAnchor *me) -{ - return (me ? me->citehost : NULL); -} - -void HTAnchor_setCitehost(HTParentAnchor *me, - const char *citehost) -{ - if (me) { - StrAllocCopy(me->citehost, citehost); - } -} -#endif /* !DISABLE_BIBP */ - -/* Suggested filename handling. - FM - * (will be loaded if we had a Content-Disposition - * header or META element with filename=name.suffix) - */ -const char *HTAnchor_SugFname(HTParentAnchor *me) -{ - return (me ? me->SugFname : NULL); -} - -#ifdef EXP_HTTP_HEADERS -/* HTTP Headers. -*/ -const char *HTAnchor_http_headers(HTParentAnchor *me) -{ - return (me ? me->http_headers.data : NULL); -} -#endif - -/* Content-Type handling (parameter list). -*/ -const char *HTAnchor_content_type_params(HTParentAnchor *me) -{ - return (me ? me->content_type_params : NULL); -} - -/* Content-Encoding handling. - FM - * (will be loaded if we had a Content-Encoding - * header.) - */ -const char *HTAnchor_content_encoding(HTParentAnchor *me) -{ - return (me ? me->content_encoding : NULL); -} - -/* Content-Type handling. - FM -*/ -const char *HTAnchor_content_type(HTParentAnchor *me) -{ - return (me ? me->content_type : NULL); -} - -/* Last-Modified header handling. - FM -*/ -const char *HTAnchor_last_modified(HTParentAnchor *me) -{ - return (me ? me->last_modified : NULL); -} - -/* Date header handling. - FM -*/ -const char *HTAnchor_date(HTParentAnchor *me) -{ - return (me ? me->date : NULL); -} - -/* Server header handling. - FM -*/ -const char *HTAnchor_server(HTParentAnchor *me) -{ - return (me ? me->server : NULL); -} - -/* Safe header handling. - FM -*/ -BOOL HTAnchor_safe(HTParentAnchor *me) -{ - return (BOOL) (me ? me->safe : FALSE); -} - -/* Content-Base header handling. - FM -*/ -const char *HTAnchor_content_base(HTParentAnchor *me) -{ - return (me ? me->content_base : NULL); -} - -/* Content-Location header handling. - FM -*/ -const char *HTAnchor_content_location(HTParentAnchor *me) -{ - return (me ? me->content_location : NULL); -} - -/* Message-ID, used for mail replies - kw -*/ -const char *HTAnchor_messageID(HTParentAnchor *me) -{ - return (me ? me->message_id : NULL); -} - -BOOL HTAnchor_setMessageID(HTParentAnchor *me, - const char *messageid) -{ - if (!(me && messageid && *messageid)) { - return FALSE; - } - StrAllocCopy(me->message_id, messageid); - return TRUE; -} - -/* Subject, used for mail replies - kw -*/ -const char *HTAnchor_subject(HTParentAnchor *me) -{ - return (me ? me->subject : NULL); -} - -BOOL HTAnchor_setSubject(HTParentAnchor *me, - const char *subject) -{ - if (!(me && subject && *subject)) { - return FALSE; - } - StrAllocCopy(me->subject, subject); - return TRUE; -} - -/* Manipulation of links - * --------------------- - */ -HTAnchor *HTAnchor_followLink(HTChildAnchor *me) -{ - return (me->dest); -} - -HTAnchor *HTAnchor_followTypedLink(HTChildAnchor *me, - HTLinkType *type) -{ - if (me->type == type) - return (me->dest); - return (NULL); /* No link of me type */ -} - -/* Methods List - * ------------ - */ -HTList *HTAnchor_methods(HTParentAnchor *me) -{ - if (!me->methods) { - me->methods = HTList_new(); - } - return (me->methods); -} - -/* Protocol - * -------- - */ -void *HTAnchor_protocol(HTParentAnchor *me) -{ - return (me->protocol); -} - -void HTAnchor_setProtocol(HTParentAnchor *me, - void *protocol) -{ - me->protocol = protocol; -} - -/* Physical Address - * ---------------- - */ -char *HTAnchor_physical(HTParentAnchor *me) -{ - return (me->physical); -} - -void HTAnchor_setPhysical(HTParentAnchor *me, - char *physical) -{ - if (me) { - StrAllocCopy(me->physical, physical); - } -} - -#ifdef DEBUG -static void show_stages(HTParentAnchor *me, const char *tag, int which_stage) -{ - int j; - - CTRACE((tfp, "Stages %s*%s", NonNull(me->charset), tag)); - for (j = 0; j < UCT_STAGEMAX; j++) { - CTRACE((tfp, " ")); - if (j == which_stage) - CTRACE((tfp, "(")); - CTRACE((tfp, "%d:%d:%s", - j, - me->UCStages->s[j].LYhndl, - NonNull(me->UCStages->s[j].C.MIMEname))); - if (j == which_stage) - CTRACE((tfp, ")")); - } - CTRACE((tfp, "\n")); -} -#else -#define show_stages(me,tag,which_stage) /* nothing */ -#endif - -/* - * We store charset info in the HTParentAnchor object, for several - * "stages". (See UCDefs.h) - * A stream method is supposed to know what stage in the model it is. - * - * General model MIME -> parser -> structured -> HText - * e.g., text/html - * from HTTP: HTMIME.c -> SGML.c -> HTML.c -> GridText.c - * text/plain - * from file: HTFile.c -> HTPlain.c -> GridText.c - * - * The lock/set_by is used to lock e.g. a charset set by an explicit - * HTTP MIME header against overriding by a HTML META tag - the MIME - * header has higher priority. Defaults (from -assume_.. options etc.) - * will not override charset explicitly given by server. - * - * Some advantages of keeping this in the HTAnchor: - * - Global variables are bad. - * - Can remember a charset given by META tag when toggling to SOURCE view. - * - Can remember a charset given by <A CHARSET=...> href in another doc. - * - * We don't modify the HTParentAnchor's charset element - * here, that one will only be set when explicitly given. - */ -LYUCcharset *HTAnchor_getUCInfoStage(HTParentAnchor *me, - int which_stage) -{ - LYUCcharset *result = NULL; - - if (me) { - if (!me->UCStages) { - int i; - int chndl = UCLYhndl_for_unspec; /* always >= 0 */ - UCAnchorInfo *stages = typecalloc(UCAnchorInfo); - - if (stages == NULL) - outofmem(__FILE__, "HTAnchor_getUCInfoStage"); - - assert(stages != NULL); - - for (i = 0; i < UCT_STAGEMAX; i++) { - stages->s[i].C.MIMEname = ""; - stages->s[i].LYhndl = -1; - } - if (me->charset) { - chndl = UCGetLYhndl_byMIME(me->charset); - if (chndl < 0) - chndl = UCLYhndl_for_unrec; - if (chndl < 0) - /* - * UCLYhndl_for_unrec not defined :-( - * fallback to UCLYhndl_for_unspec which always valid. - */ - chndl = UCLYhndl_for_unspec; /* always >= 0 */ - } - MemCpy(&stages->s[UCT_STAGE_MIME].C, &LYCharSet_UC[chndl], - sizeof(LYUCcharset)); - - stages->s[UCT_STAGE_MIME].lock = UCT_SETBY_DEFAULT; - stages->s[UCT_STAGE_MIME].LYhndl = chndl; - me->UCStages = stages; - } - result = (&me->UCStages->s[which_stage].C); - show_stages(me, "_getUCInfoStage", which_stage); - } - return (result); -} - -int HTAnchor_getUCLYhndl(HTParentAnchor *me, - int which_stage) -{ - if (me) { - if (!me->UCStages) { - /* - * This will allocate and initialize, if not yet done. - */ - (void) HTAnchor_getUCInfoStage(me, which_stage); - } - if (me->UCStages->s[which_stage].lock > UCT_SETBY_NONE) { - return (me->UCStages->s[which_stage].LYhndl); - } - } - return (-1); -} - -#ifdef CAN_SWITCH_DISPLAY_CHARSET -static void setup_switch_display_charset(HTParentAnchor *me, int h) -{ - if (!Switch_Display_Charset(h, SWITCH_DISPLAY_CHARSET_MAYBE)) - return; - HTAnchor_setUCInfoStage(me, current_char_set, - UCT_STAGE_HTEXT, UCT_SETBY_MIME); /* highest priorty! */ - HTAnchor_setUCInfoStage(me, current_char_set, - UCT_STAGE_STRUCTURED, UCT_SETBY_MIME); /* highest priorty! */ - CTRACE((tfp, - "changing UCInfoStage: HTEXT/STRUCTURED stages charset='%s'.\n", - LYCharSet_UC[current_char_set].MIMEname)); -} -#endif - -LYUCcharset *HTAnchor_setUCInfoStage(HTParentAnchor *me, - int LYhndl, - int which_stage, - int set_by) -{ - if (me) { - /* - * This will allocate and initialize, if not yet done. - */ - LYUCcharset *p = HTAnchor_getUCInfoStage(me, which_stage); - - /* - * Can we override? - */ - if (set_by >= me->UCStages->s[which_stage].lock) { -#ifdef CAN_SWITCH_DISPLAY_CHARSET - int ohandle = me->UCStages->s[which_stage].LYhndl; -#endif - me->UCStages->s[which_stage].lock = set_by; - me->UCStages->s[which_stage].LYhndl = LYhndl; - if (LYhndl >= 0) { - MemCpy(p, &LYCharSet_UC[LYhndl], sizeof(LYUCcharset)); - -#ifdef CAN_SWITCH_DISPLAY_CHARSET - /* Allow a switch to a more suitable display charset */ - if (LYhndl != ohandle && which_stage == UCT_STAGE_PARSER) - setup_switch_display_charset(me, LYhndl); -#endif - } else { - p->UChndl = -1; - } - show_stages(me, "_setUCInfoStage", which_stage); - return (p); - } - } - return (NULL); -} - -LYUCcharset *HTAnchor_resetUCInfoStage(HTParentAnchor *me, - int LYhndl, - int which_stage, - int set_by) -{ - LYUCcharset *result = NULL; - int ohandle; - - if (me && me->UCStages) { - me->UCStages->s[which_stage].lock = set_by; - ohandle = me->UCStages->s[which_stage].LYhndl; - me->UCStages->s[which_stage].LYhndl = LYhndl; -#ifdef CAN_SWITCH_DISPLAY_CHARSET - /* Allow a switch to a more suitable display charset */ - if (LYhndl >= 0 && LYhndl != ohandle - && which_stage == UCT_STAGE_PARSER) - setup_switch_display_charset(me, LYhndl); -#else - (void) ohandle; -#endif - show_stages(me, "_resetUCInfoStage", which_stage); - result = (&me->UCStages->s[which_stage].C); - } - return result; -} - -/* - * A set_by of (-1) means use the lock value from the from_stage. - */ -LYUCcharset *HTAnchor_copyUCInfoStage(HTParentAnchor *me, - int to_stage, - int from_stage, - int set_by) -{ - if (me) { - /* - * This will allocate and initialize, if not yet done. - */ - LYUCcharset *p_from = HTAnchor_getUCInfoStage(me, from_stage); - LYUCcharset *p_to = HTAnchor_getUCInfoStage(me, to_stage); - - /* - * Can we override? - */ - if (set_by == -1) - set_by = me->UCStages->s[from_stage].lock; - if (set_by == UCT_SETBY_NONE) - set_by = UCT_SETBY_DEFAULT; - if (set_by >= me->UCStages->s[to_stage].lock) { -#ifdef CAN_SWITCH_DISPLAY_CHARSET - int ohandle = me->UCStages->s[to_stage].LYhndl; -#endif - me->UCStages->s[to_stage].lock = set_by; - me->UCStages->s[to_stage].LYhndl = - me->UCStages->s[from_stage].LYhndl; -#ifdef CAN_SWITCH_DISPLAY_CHARSET - /* Allow a switch to a more suitable display charset */ - if (me->UCStages->s[to_stage].LYhndl >= 0 - && me->UCStages->s[to_stage].LYhndl != ohandle - && to_stage == UCT_STAGE_PARSER) - setup_switch_display_charset(me, - me->UCStages->s[to_stage].LYhndl); -#endif - if (p_to != p_from) - MemCpy(p_to, p_from, sizeof(LYUCcharset)); - - return (p_to); - } - } - return (NULL); -} |