HTAnchor * HTAnchor_findAddress ARGS1 (CONST char *,address) { char *tag = HTParse (address, "", PARSE_ANCHOR); /* Anchor tag specified ? */ /* If the address represents a sub-anchor, we recursively load its parent, then we create a child anchor within that document. */ if (tag && *tag) { char *docAddress = HTParse(address, "", PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION); HTParentAnchor * foundParent = (HTParentAnchor *) HTAnchor_findAddress (docAddress); HTChildAnchor * foundAnchor = HTAnchor_findChild (foundParent, tag); free (docAddress); free (tag); return (HTAnchor *) foundAnchor; } else { /* If the address has no anchor tag, check whether we have this node */ int hash; CONST char *p; HTList * adults; HTList *grownups; HTParentAnchor * foundAnchor; if (tag && *tag) free (tag); /* Select list from hash table */ for(p=address, hash=0; *p; p++) hash = (hash * 3 + *p) % HASH_SIZE; if (!adult_table) adult_table = (HTList**) calloc(HASH_SIZE, sizeof(HTList*)); if (!adult_table[hash]) adult_table[hash] = HTList_new(); adults = adult_table[hash]; /* Search list for anchor */ grownups = adults; while (foundAnchor = HTList_nextObject (grownups)) { if (equivalent(foundAnchor->address, address)) { if (TRACE) fprintf(stderr, "Anchor %p with address `%s' already exists.\n", foundAnchor, address); return (HTAnchor *) foundAnchor; } } /* Node not found : create new anchor */ foundAnchor = HTParentAnchor_new (); if (TRACE) fprintf(stderr, "New anchor %p has hash %d and address `%s'\n", foundAnchor, hash, address); StrAllocCopy(foundAnchor->address, address); HTList_addObject (adults, foundAnchor); return (HTAnchor *) foundAnchor; } }
/* Create new or find old named 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. */ PUBLIC HTAnchor * HTAnchor_findAddress (const char * address) { char *tag = HTParse (address, "", PARSE_VIEW); /* Any tags? */ /* If the address represents a sub-anchor, we recursively load its parent, then we create a child anchor within that document. */ if (*tag) { char *addr = HTParse(address, "", PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION); HTParentAnchor * parent = (HTParentAnchor*) HTAnchor_findAddress(addr); HTChildAnchor * child = HTAnchor_findChild(parent, tag); HT_FREE(addr); HT_FREE(tag); return (HTAnchor *) child; } else { /* Else check whether we have this node */ int hash; const char *p; HTList * adults; HTList *grownups; HTParentAnchor * foundAnchor; char *newaddr = NULL; StrAllocCopy(newaddr, address); /* Get our own copy */ HT_FREE(tag); newaddr = HTSimplify(&newaddr); /* Select list from hash table */ for(p=newaddr, hash=0; *p; p++) hash = (int) ((hash * 3 + (*(unsigned char*)p)) % PARENT_HASH_SIZE); if (!adult_table) { if ((adult_table = (HTList* *) HT_CALLOC(PARENT_HASH_SIZE, sizeof(HTList*))) == NULL) HT_OUTOFMEM("HTAnchor_findAddress"); } if (!adult_table[hash]) adult_table[hash] = HTList_new(); adults = adult_table[hash]; /* Search list for anchor */ grownups = adults; while ((foundAnchor = (HTParentAnchor *) HTList_nextObject(grownups))){ if (!strcmp(foundAnchor->address, newaddr)) { HTTRACE(ANCH_TRACE, "Find Parent. %p with address `%s' already exists.\n" _ (void*) foundAnchor _ newaddr); HT_FREE(newaddr); /* We already have it */ return (HTAnchor *) foundAnchor; } } /* Node not found : create new anchor. */ foundAnchor = HTParentAnchor_new(); foundAnchor->address = newaddr; /* Remember our copy */ HTList_addObject (adults, foundAnchor); HTTRACE(ANCH_TRACE, "Find Parent. %p with hash %d and address `%s' created\n" _ (void*)foundAnchor _ hash _ newaddr); return (HTAnchor *) foundAnchor; } }
/* 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. ** All parameters EXCEPT parent can be NULL */ PUBLIC HTChildAnchor * HTAnchor_findChildAndLink (HTParentAnchor * parent, const char * tag, const char * href, HTLinkType ltype) { HTChildAnchor * child = HTAnchor_findChild(parent, tag); if (child && href && *href) { char * relative_to = HTAnchor_expandedAddress((HTAnchor *) parent); char * parsed_address = HTParse(href, relative_to, PARSE_ALL); HTAnchor * dest = HTAnchor_findAddress(parsed_address); HTLink_add((HTAnchor *) child, dest, ltype, METHOD_INVALID); HT_FREE(parsed_address); HT_FREE(relative_to); } return child; }
/* 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) */ PUBLIC HTChildAnchor * HTAnchor_findChildAndLink ARGS4( 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 = HTAnchor_findChild(parent, tag); if (href && *href) { char * parsed_address; HTAnchor * dest; parsed_address = HTParse(href, HTAnchor_address((HTAnchor *) parent), PARSE_ALL); dest = HTAnchor_findAddress(parsed_address); HTAnchor_link((HTAnchor *) child, dest, ltype); free(parsed_address); } return child; }