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

📄 htanchor.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, lynx比elinks早的多, 目前好像停止开发, 这是lynx源代码
💻 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 <HTString.h>#include <UCAux.h>#include <UCMap.h>#include <GridText.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 *//* Table of lists of all parents */PRIVATE 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.*/PRIVATE HTParentAnchor0 * HTParentAnchor0_new ARGS2(	CONST char *,	address,	short,		hash){    HTParentAnchor0 *newAnchor = typecalloc(HTParentAnchor0);    if (newAnchor == NULL)	outofmem(__FILE__, "HTParentAnchor0_new");    newAnchor->parent = newAnchor;	/* self */    StrAllocCopy(newAnchor->address, address);    newAnchor->adult_hash = hash;    return(newAnchor);}PRIVATE HTParentAnchor * HTParentAnchor_new ARGS1(	HTParentAnchor0 *,	parent){    HTParentAnchor *newAnchor = typecalloc(HTParentAnchor);    if (newAnchor == NULL)	outofmem(__FILE__, "HTParentAnchor_new");    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);}PRIVATE HTChildAnchor * HTChildAnchor_new ARGS1(	HTParentAnchor0 *,	parent){    HTChildAnchor *p = typecalloc(HTChildAnchor);    if (p == NULL)	outofmem(__FILE__, "HTChildAnchor_new");    p->parent = parent;		/* parent reference */    return p;}PRIVATE HTChildAnchor * HText_pool_ChildAnchor_new ARGS1(	HTParentAnchor *,	parent){    HTChildAnchor *p = (HTChildAnchor *)HText_pool_calloc((HText*)(parent->document),						sizeof(HTChildAnchor));    if (p == NULL)	outofmem(__FILE__, "HText_pool_ChildAnchor_new");    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.*/PRIVATE BOOL HTSEquivalent ARGS2(	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(HT_EQUIV(*s, *t));    } else {	return(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.*/PRIVATE BOOL HTBEquivalent ARGS2(	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(s == t);		/* Two NULLs are equivalent, aren't they ? */    }}/* *  Three-way compare function */PRIVATE int compare_anchors ARGS2(	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.*/PRIVATE HTChildAnchor * HTAnchor_findNamedChild ARGS2(	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).*/PRIVATE HTChildAnchor * HTAnchor_addChild ARGS1(	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);}PRIVATE HTParentAnchor0 * HTAnchor_findAddress_in_adult_table PARAMS((	CONST DocAddress *	newdoc));PRIVATE BOOL HTAnchor_link PARAMS((	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)*/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;    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'",			   child, tag));		if ((HTAnchor *)dest != child->dest || ltype != child->type) {		    CTRACE((tfp,			   ", different dest %p or type, creating unnamed child\n",			   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.*/PUBLIC HTParentAnchor * HTAnchor_findAddress ARGS1(	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;	HTChildAnchor * foundAnchor;	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);	foundAnchor = 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. */PRIVATE HTParentAnchor0 * HTAnchor_findAddress_in_adult_table ARGS1(	CONST DocAddress *,	newdoc){    /*    **  Check whether we have this node.    */    int hash;    HTList * adults;    HTList *grownups;    HTParentAnchor0 * foundAnchor;    BOOL need_extra_info = (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);

⌨️ 快捷键说明

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