⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htanchor.c

📁 用于linux和其他unix下面的
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	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 101		/* Arbitrary prime.  Memory/speed tradeoff */#include <HTUtils.h>#include <HTAnchor.h>#include <HTParse.h>#include <UCAux.h>#include <UCMap.h>#include <LYUtils.h>#include <LYCharSets.h>#include <LYLeaks.h>#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) ((unsigned short int)strlen(cp_address) *\	(unsigned short int)TOUPPER(*cp_address) % HASH_SIZE)#endif /* NOT_DEFINED *//* *	This is the original function.	We'll use it again. - FM */PRIVATE int HASH_FUNCTION ARGS1(	CONST char *,	cp_address){    int hash;    CONST unsigned char *p;    for (p = (CONST unsigned char *)cp_address, hash = 0; *p; p++)	hash = (int) (hash * 3 + (*(CONST unsigned char *)p)) % HASH_SIZE;    return(hash);}typedef struct _HyperDoc Hyperdoc;#ifdef VMSstruct _HyperDoc {	int junk;	/* VMS cannot handle pointers to undefined structs */};#endif /* VMS */PRIVATE HTList **adult_table = 0;  /* Point to table of lists of all parents *//*				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.*/PRIVATE HTParentAnchor * HTParentAnchor_new NOARGS{    HTParentAnchor *newAnchor = typecalloc(HTParentAnchor);    if (newAnchor == NULL)	outofmem(__FILE__, "HTParentAnchor_new");    newAnchor->parent = newAnchor;    newAnchor->bookmark = NULL;		/* Bookmark filename. - FM */    newAnchor->isISMAPScript = FALSE;	/* Lynx appends ?0,0 if TRUE. - FM */    newAnchor->isHEAD = FALSE;		/* HEAD request if TRUE. - FM */    newAnchor->safe = FALSE;		/* Safe. - FM */#ifdef SOURCE_CACHE    newAnchor->source_cache_file = NULL;    newAnchor->source_cache_chunk = NULL;#endif    newAnchor->FileCache = NULL;	/* Path to a disk-cached copy. - FM */    newAnchor->SugFname = NULL;		/* Suggested filename. - FM */    newAnchor->RevTitle = NULL;		/* TITLE for a LINK with REV. - FM */    newAnchor->citehost = NULL;		/* LINK REL=citehost - RDC */    newAnchor->cache_control = NULL;	/* Cache-Control. - FM */    newAnchor->no_cache = FALSE;	/* no-cache? - FM */    newAnchor->content_type = NULL;	/* Content-Type. - FM */    newAnchor->content_language = NULL; /* Content-Language. - FM */    newAnchor->content_encoding = NULL; /* Compression algorithm. - FM */    newAnchor->content_base = NULL;	/* Content-Base. - FM */    newAnchor->content_disposition = NULL; /* Content-Disposition. - FM */    newAnchor->content_location = NULL; /* Content-Location. - FM */    newAnchor->content_md5 = NULL;	/* Content-MD5. - FM */    newAnchor->content_length = 0;	/* Content-Length. - FM */    newAnchor->date = NULL;		/* Date. - FM */    newAnchor->expires = NULL;		/* Expires. - FM */    newAnchor->last_modified = NULL;	/* Last-Modified. - FM */    newAnchor->ETag = NULL;		/* ETag (HTTP/1.1 cache validator) */    newAnchor->server = NULL;		/* Server. - FM */    return(newAnchor);}PRIVATE HTChildAnchor * HTChildAnchor_new NOARGS{    HTChildAnchor *p;    p = typecalloc(HTChildAnchor);    if (p == NULL)	outofmem(__FILE__, "HTChildAnchor_new");    return p;}#ifdef CASE_INSENSITIVE_ANCHORS/*	Case insensitive 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 ignoring case**		NO if they differ in more than	their case.*/PRIVATE BOOL HTEquivalent ARGS2(	CONST char *,	s,	CONST char *,	t){    if (s && t) {  /* Make sure they point to something */	for (; *s && *t; s++, t++) {	    if (TOUPPER(*s) != TOUPPER(*t)) {		return(NO);	    }	}	return( TOUPPER(*s) == TOUPPER(*t));    } else {	return(s == t);		/* Two NULLs are equivalent, aren't they ? */    }}#else/*	Case sensitive string comparison**	----------------------------------** On entry,**	s	Points to one string, null terminated**	t	points to the other.** On exit,**	returns YES if the strings are identical or both NULL**		NO if they differ.*/PRIVATE BOOL HTIdentical ARGS2(	CONST char *,	s,	CONST char *,	t){    if (s && t) {  /* Make sure they point to something */#ifdef SH_EX	/* 1998/04/28 (Tue) 22:02:58 */	if (*s == 'P' || *t == 'P') {	    if (strcmp(s + 1, "Name") == 0 || strcmp(t + 1, "Name") == 0)		return NO;	}#endif	for (; *s && *t; s++, t++) {	    if (*s != *t) {		return(NO);	    }	}	return (BOOL) (*s == *t);    } else {	return (BOOL) (s == t);  /* Two NULLs are identical, aren't they ? */    }}#endif /* CASE_INSENSITIVE_ANCHORS *//*	Create new or find old sub-anchor**	---------------------------------****	Me one is for a new anchor being edited into an existing**	document.  The parent anchor must already exist.*/PUBLIC HTChildAnchor * HTAnchor_findChild ARGS2(	HTParentAnchor *,	parent,	CONST char *,		tag){    HTChildAnchor *child;    HTList *kids;    if (!parent) {	CTRACE((tfp, "HTAnchor_findChild called with NULL parent.\n"));	return(NULL);    }    if ((kids = parent->children) != 0) {	/*	**  Parent has children.  Search them.	*/	if (tag && *tag) {		/* TBL */	    while (NULL != (child=(HTChildAnchor *)HTList_nextObject(kids))) {#ifdef CASE_INSENSITIVE_ANCHORS		if (HTEquivalent(child->tag, tag)) /* Case insensitive */#else		if (HTIdentical(child->tag, tag)) /* Case sensitive - FM */#endif /* CASE_INSENSITIVE_ANCHORS */		{		    CTRACE((tfp, "Child anchor %p of parent %p with name `%s' already exists.\n",				(void *)child, (void *)parent, tag));		    return(child);		}	    }	}  /*  end if tag is void */    } else {  /* parent doesn't have any children yet : create family */	parent->children = HTList_new();    }    child = HTChildAnchor_new();    CTRACE((tfp, "HTAnchor: New Anchor %p named `%s' is child of %p\n",		(void *)child,		tag ? tag : (CONST char *)"",		(void *)parent)); /* int for apollo */    HTList_addObject (parent->children, child);    child->parent = parent;    StrAllocCopy(child->tag, tag);    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);    CTRACE((tfp,"Entered HTAnchor_findChildAndLink\n"));    if (href && *href) {	char *relative_to = HTAnchor_address((HTAnchor *)parent);	DocAddress parsed_doc;	HTAnchor * dest;	parsed_doc.address = HTParse(href, relative_to, PARSE_ALL);#ifndef DONT_TRACK_INTERNAL_LINKS	if (ltype && parent->post_data && ltype == LINK_INTERNAL) {	    /* for internal links, find a destination with the same	       post data if the source of the link has post data. - kw */	    parsed_doc.post_data = parent->post_data;	    parsed_doc.post_content_type = parent->post_content_type;	} else#endif	{	    parsed_doc.post_data = NULL;	    parsed_doc.post_content_type = NULL;	}	parsed_doc.bookmark = NULL;	parsed_doc.isHEAD = FALSE;	parsed_doc.safe = FALSE;	dest = HTAnchor_findAddress(&parsed_doc);#define DUPLICATE_ANCHOR_NAME_WORKAROUND#ifdef DUPLICATE_ANCHOR_NAME_WORKAROUND	if (tag && *tag) {	    HTAnchor *testdest1;	    int child_links;	    testdest1 = child->mainLink.dest;	    if (testdest1) {		child_links = 1 + HTList_count(child->links);		CTRACE((tfp,		       "*** Duplicate ChildAnchor %p named `%s' with %d links",		       child, tag, child_links));		if (dest == testdest1 && ltype == child->mainLink.type) {		    CTRACE((tfp,", same dest %p and type, keeping it\n",			   testdest1));		} else {		    CTRACE((tfp,", different dest %p, creating unnamed child\n",			   testdest1));		    child = HTAnchor_findChild(parent, 0);		}	    }	}#endif	HTAnchor_link((HTAnchor *)child, dest, ltype);	FREE(parsed_doc.address);	FREE(relative_to);    }    return(child);}#ifdef LY_FIND_LEAKS/***  Function for freeing the adult hash table. - FM*/PRIVATE void free_adult_table NOARGS{    int i_counter;    HTList * HTAp_freeme;    HTParentAnchor * parent;    /*     *	Loop through all lists.     */    for (i_counter = 0; i_counter < HASH_SIZE; i_counter++) {	/*	**  Loop through the list.	*/	while (adult_table[i_counter] != NULL) {	    /*	    **	Free off items - FM	    */	    HTAp_freeme = adult_table[i_counter];	    adult_table[i_counter] = HTAp_freeme->next;	    if (HTAp_freeme->object) {		parent = (HTParentAnchor *)HTAp_freeme->object;		CTRACE((tfp, "delete anchor:%d/%d,%d,%d %s\n",		       i_counter, HTList_count(HTAp_freeme) + 1,		       (parent->physical ? 1 : 0),		       (int)parent->underway,		       (parent->address ? parent->address : "(no address)")));		parent->underway = FALSE;		HTAnchor_delete(parent);	    }	    FREE(HTAp_freeme);	}    }    FREE(adult_table);}#endif /* LY_FIND_LEAKS *//*	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 ARGS1(	CONST DocAddress *,	newdoc){    /* Anchor tag specified ? */    char *tag = HTParse(newdoc->address, "", PARSE_ANCHOR);    CTRACE((tfp,"Entered HTAnchor_findAddress\n"));    /*    **	If the address represents a sub-anchor, we recursively load its    **	parent, then we create a child anchor within that document.    */    if (*tag) {	DocAddress parsed_doc;	HTParentAnchor * foundParent;	HTChildAnchor * foundAnchor;	parsed_doc.address = HTParse(newdoc->address, "",		PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);	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 = (HTParentAnchor *)HTAnchor_findAddress(&parsed_doc);	foundAnchor = HTAnchor_findChild (foundParent, tag);	FREE(parsed_doc.address);	FREE(tag);	return (HTAnchor *)foundAnchor;    } else {	/*	**  If the address has no anchor tag,	**  check whether we have this node.	*/	int hash;	HTList * adults;	HTList *grownups;	HTParentAnchor * foundAnchor;	FREE(tag);	/*	**  Select list from hash table,	*/	hash = HASH_FUNCTION(newdoc->address);	if (!adult_table) {	    adult_table = typecallocn(HTList *, HASH_SIZE);	    if (!adult_table)		outofmem(__FILE__, "HTAnchor_findAddress");#ifdef LY_FIND_LEAKS	    atexit(free_adult_table);#endif	}	if (!adult_table[hash])	    adult_table[hash] = HTList_new();	adults = adult_table[hash];	/*	**  Search list for anchor.	*/	grownups = adults;	while (NULL != (foundAnchor =			(HTParentAnchor *)HTList_nextObject(grownups))) {#ifdef CASE_INSENSITIVE_ANCHORS	    if (HTEquivalent(foundAnchor->address, newdoc->address) &&		HTEquivalent(foundAnchor->post_data, newdoc->post_data) &&		foundAnchor->isHEAD == newdoc->isHEAD)#else	    if (HTIdentical(foundAnchor->address, newdoc->address) &&		HTIdentical(foundAnchor->post_data, newdoc->post_data) &&		foundAnchor->isHEAD == newdoc->isHEAD)#endif /* CASE_INSENSITIVE_ANCHORS */	    {		CTRACE((tfp, "Anchor %p with address `%s' already exists.\n",			    (void *)foundAnchor, newdoc->address));		 return (HTAnchor *)foundAnchor;	     }	}	/*	**  Node not found: create new anchor.	*/	foundAnchor = HTParentAnchor_new();	CTRACE((tfp, "New anchor %p has hash %d and address `%s'\n",		    (void *)foundAnchor, hash, newdoc->address));	StrAllocCopy(foundAnchor->address, newdoc->address);	if (newdoc->post_data)	    StrAllocCopy(foundAnchor->post_data, newdoc->post_data);	if (newdoc->post_content_type)	    StrAllocCopy(foundAnchor->post_content_type,			 newdoc->post_content_type);	if (newdoc->bookmark)	    StrAllocCopy(foundAnchor->bookmark, newdoc->bookmark);	foundAnchor->isHEAD = newdoc->isHEAD;	foundAnchor->safe = newdoc->safe;	HTList_addObject (adults, foundAnchor);	return (HTAnchor *)foundAnchor;    }}/*	Create new or find old named anchor - simple form**	-------------------------------------------------****	Like the previous one, but simpler to use for simple cases.**	No post data etc. can be supplied. - kw*/PUBLIC HTAnchor * HTAnchor_findSimpleAddress ARGS1(	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);}/*	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 parent and children are deleted, and this anchor**	is removed from the sources list of all its targets.**	We also try to delete the targets whose documents are not loaded.**	If this anchor's source list is empty, we delete it and its children.*/PRIVATE void deleteLinks ARGS1(	HTAnchor *,	me){    /*     *	Memory leaks fixed.     *	05-27-94 Lynx 2-3-1 Garrett Arch Blythe     */    /*     *	Anchor is NULL, do nothing.     */    if (!me) {	return;    }    /*     *	Unregister me with our mainLink destination anchor's parent.     */    if (me->mainLink.dest) {	HTParentAnchor *parent = me->mainLink.dest->parent;	/*	 *  Set the mainLink pointer to zero NOW.  If we don't,	 *  and we get somehow called recursively again for this	 *  same old me during the HTAnchor_delete below, weird	 *  things can occasionally happen. - kw	 */	 me->mainLink.dest = NULL;	/*	 *  Remove me from the parent's sources so that the	 *  parent knows one less anchor is it's dest.	 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -