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

📄 htndir.c

📁 www工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/*							       	     HTNDir.c**	GENERIC NEWS LISTINGS****	(c) COPYRIGHT MIT 1995.**	Please first read the full copyright statement in the file COPYRIGH.**	@(#) $Id: HTNDir.c,v 2.12 1999/02/22 22:10:11 frystyk Exp $****	Creates listings for all kind of News output.**** Authors:**	HF	Henrik Frystyk, MIT, <frystyk@w3.org>**	MP	Maciej Puzio <puzio@zodiac1.mimuw.edu.pl>** History:**	   Oct 95  HFN	written**	   Mar 96  MP	modified heavily     *//* Library include files */#include "wwwsys.h"#include "WWWUtil.h"#include "WWWCore.h"#include "WWWHTML.h"#include "HTNews.h"#include "HTNewsLs.h"#include "HTNDir.h"					 /* Implemented here *//* Macros and other defines */#define PUTC(c)		(*target->isa->put_character)(target, c)#define PUTS(s)		(*target->isa->put_string)(target, s)#define START(e)	(*target->isa->start_element)(target, e, 0, 0)#define END(e)		(*target->isa->end_element)(target, e)#define FREE_TARGET	(*target->isa->_free)(target)#define DEFAULT_MAXW	80			       /* Default line width *//* Type definitions and global variables etc. local to this module */struct _HTStructured {    const HTStructuredClass *	isa;    /* ... */};struct _HTNewsNode {    int		index;    char *	name;    char *	subject;    char *	from;    time_t	date;    int		refs;			 /* Number of references */    BOOL	is_tmplate;    /* Added by MP: */    HTList* refNames;        /*  referee names list */    HTList* refObjects;      /*  referee objects list */    HTNewsNode * refParent;  /* direct parent (referee) */    HTNewsNode * lastChild;  /* last child (referer) */    BOOL    show;            /* show this node on the list? */    BOOL    fake;            /* create anchor with this node? */    int     refChildren;     /* number of referers */    int     refLevel;        /* reference level - to speed sorting */    int     minRefIndex;     /* minimal index in reference subtree */    int     maxRefIndex;     /* maximal index in reference subtree */    time_t  minRefDate;      /* minimal date in reference subtree */    time_t  maxRefDate;      /* maximal date in reference subtree */};struct _HTNewsDir {    HTStructured *	target;    HTRequest *		request;    HTNewsDirKey	key;				  /* Key for sorting */    char *   	        name;        /* Name of the newsgroup(s) Added by MP */    char *		tmplate;    HTNewsNode *	tmplate_node;    int 	        lastLevel;    /* Last printed ref level Added by MP. */    HTArray *		array;			/* Array for sorted listings */    HTArray *		cache;			  /* Only created on request */};PRIVATE int MaxLineW = DEFAULT_MAXW;/*  Forward references - added by MP. */PRIVATE void HTNewsDir_addLevelTags (HTNewsDir* dir, int level);PRIVATE HTNewsNode* HTNewsDir_addFakeElement (HTNewsDir* dir, char* subject,    char* name);PRIVATE HTNewsNode* HTNewsDir_findNodeNamed (HTNewsDir* dir, char* name);#define FNWS_ANY       0x0000/* Date */#define FNWS_MIN       0x0001#define FNWS_MAX       0x0002/* Fake/not-fake */#define FNWS_ONLYFAKE  0x0010#define FNWS_NOTFAKE   0x0020/* Fake or not-fake with references */#define FNWS_NOTORPHAN 0x0040PRIVATE HTNewsNode* HTNewsDir_findNodeWithSubject (HTNewsDir* dir,     char* subject, int which, HTNewsNode* avoidNode);/* ------------------------------------------------------------------------- *//*				NODE  MANAGEMENT 			     *//* ------------------------------------------------------------------------- */PRIVATE HTNewsNode * HTNewsNode_new (int index, char * subject, char * from,				     time_t date, char * name,				     int refs, HTList * refNames){    HTNewsNode * node;    if ((node = (HTNewsNode *) HT_CALLOC(1, sizeof(HTNewsNode))) == NULL)        HT_OUTOFMEM("HTNewsNode_new");    if (name) StrAllocCopy(node->name, name);    if (subject) {	StrAllocCopy(node->subject, subject);	node->subject = HTStrip(node->subject);    }    if (from) StrAllocCopy(node->from, from);    node->index = index;    node->date = date;    node->refs = refs;    node->refNames = refNames;    node->show = (name != NULL);    node->fake = (name == NULL);    node->minRefIndex = index;    node->maxRefIndex = index;    node->minRefDate = date;    node->maxRefDate = date;    return node;}PRIVATE BOOL HTNewsNode_delete (HTNewsNode * node, BOOL cache){    if (node) {    	if (!cache || node->is_tmplate) HT_FREE(node->name);	HT_FREE(node->subject);	HT_FREE(node->from);        if (node->refNames) {	    HTList * cur = node->refNames;	    char * pres;	                while ((pres = (char *) HTList_nextObject(cur))) HT_FREE(pres);            HTList_delete(node->refNames);        }        if (node->refObjects) HTList_delete(node->refObjects);	HT_FREE(node);	return YES;    }    return NO;}/* Added by MP. */PRIVATE BOOL HTNewsNode_isAncestor (HTNewsNode* node, HTNewsNode* refered){    HTNewsNode* p;    for (p = refered; p; p = p->refParent)        if (p == node) return YES;    return NO;}/* Added by MP. */PRIVATE BOOL HTNewsNode_linkRef (HTNewsNode* node, HTNewsNode* referer){    if (node && referer) {	node->refChildren++;	node->lastChild = referer;	node->minRefIndex = (node->minRefIndex != 0 ? 			     HTMIN(node->minRefIndex, referer->index) :			     referer->index);	node->maxRefIndex = (node->maxRefIndex != 0 ? 			     HTMAX(node->maxRefIndex, referer->index) :			     referer->index);	node->minRefDate = (node->minRefDate != 0 ? 			    HTMIN(node->minRefDate, referer->date) :			    referer->date);	node->maxRefDate = (node->maxRefDate != 0 ? 			    HTMAX(node->maxRefDate, referer->date) :			    referer->date);	referer->refParent = node;	return YES;    }    return NO;}/* Added by MP. */PRIVATE int HTNewsNode_refLevel (HTNewsNode* node){    int cnt = 0;    HTNewsNode* p;    for (p = node->refParent; p && p->show; p = p->refParent)        cnt++;    return cnt;}/* Added by MP. *//* Returns index field for non-fake nodes, minimal or maximal subtreee *//* index for fake nodes. */PRIVATE time_t HTNewsNode_getIndex (HTNewsNode* node, BOOL minimal){    if (node->index != 0)        return node->index;    else if (minimal)        return node->minRefIndex;    else        return node->maxRefIndex;}/* Added by MP. *//* Returns date field for non-fake nodes, minimal or maximal subtreee *//* date for fake nodes. */PRIVATE time_t HTNewsNode_getDate (HTNewsNode* node, BOOL minimal){    if (node->date != 0)        return node->date;    else if (minimal)        return node->minRefDate;    else        return node->maxRefDate;}/* Helper function - added by MP. */PRIVATE char* UnReSubject (char* subject){    if (strlen(subject) >= 3 && strncasecomp(subject, "re:", 3) == 0)    {        char* p = subject + 3;  /* "Re:XXX" */        if (*p == ' ')  p ++;   /* "Re: XXX" */        return p;    }    return subject;}/* Added by MP. */PRIVATE void HTNewsNode_setRefInfo_pass1 (HTNewsDir* dir, HTNewsNode* node){    HTList* ptr = node->refNames;    char* name = NULL;    if (node->fake)        return;    if (ptr != NULL)        name = (char*) HTList_nextObject(ptr);    while (ptr != NULL)    {        HTNewsNode* parent;        parent = HTNewsDir_findNodeNamed(dir, name);        if (parent)        {            if (!node->refObjects)  node->refObjects = HTList_new();            HTList_addObject (node->refObjects, parent);        }        name = (char*) HTList_nextObject(ptr);    }}/* Added by MP. */PRIVATE void HTNewsNode_setRefInfo_pass2 (HTNewsDir* dir, HTNewsNode* node){    HTNewsNode* maxParent = NULL;    HTList* ptr = node->refObjects;    HTNewsNode* parent = NULL;    if (node->fake)        return;    if (ptr != NULL)        parent = (HTNewsNode*) HTList_nextObject(ptr);    while (ptr != NULL)    {        if (!maxParent || maxParent->date < parent->date)            maxParent = parent;        parent = (HTNewsNode*) HTList_nextObject(ptr);    }    if (maxParent)    {        if (!HTNewsNode_isAncestor(node, maxParent))  /* better be careful */            HTNewsNode_linkRef (maxParent, node);    }    else    {        char* refSubject;        BOOL re;        /* Here is the only place we REALLY have to check for circular */        /* references. It is normally possible that a node refers to */        /* orphan node and both have the same subject. In this situation */        /* we can't make the orphan to refer to it's child. Without checking */        /* for circular references this is likely to happen here. */        refSubject = UnReSubject(node->subject);        re = (strcasecomp(refSubject, node->subject) != 0);        if (re)            parent = HTNewsDir_findNodeWithSubject(dir, refSubject,                 FNWS_MIN | FNWS_NOTFAKE, node);        if (!parent || HTNewsNode_isAncestor(node, parent))            parent = HTNewsDir_findNodeWithSubject(dir, refSubject,                FNWS_MIN | FNWS_ONLYFAKE, node);        if (!parent && re)        {            parent = HTNewsDir_findNodeWithSubject(dir, node->subject,                 FNWS_MIN | FNWS_ONLYFAKE, node);        }            if (!parent) parent = HTNewsDir_addFakeElement (dir, refSubject, NULL);	if (parent) {	    HTNewsNode_linkRef (parent, node);	    if (parent->refChildren > 1) /* Multi-children fake node visible */		parent->show = YES;	}    }}/*** Added by MP.*/#if 0PRIVATE void HTNewsNode_setRefInfo_pass3 (HTNewsDir* dir, HTNewsNode* node){    HTNewsNode* parent = NULL;    char* refSubject;    BOOL re;    if (node->fake || node->refParent)        return;  /* This is only for nodes not handled in pass 2 */        /* Here is the only place we REALLY have to check for circular */    /* references. It is normally possible that a node refers to */    /* orphan node and both have the same subject. In this situation */    /* we can't make the orphan to refer to it's child. Without checking */    /* for circular references this is likely to happen here. */    refSubject = UnReSubject(node->subject);    re = (strcasecomp(refSubject, node->subject) != 0);    if (re)        parent = HTNewsDir_findNodeWithSubject(dir, refSubject,             FNWS_MIN | FNWS_NOTFAKE, node);    if (!parent || HTNewsNode_isAncestor(node, parent))        parent = HTNewsDir_findNodeWithSubject(dir, refSubject,            FNWS_MIN | FNWS_ONLYFAKE, node);    if (!parent && re)    {        parent = HTNewsDir_findNodeWithSubject(dir, node->subject,             FNWS_MIN | FNWS_ONLYFAKE, node);    }        if (!parent) parent = HTNewsDir_addFakeElement (dir, refSubject, NULL);    if (parent) {	HTNewsNode_linkRef (parent, node);	if (parent->refChildren > 1)  	 /* multi-children fake node visible */	    parent->show = YES;    }}#elsePRIVATE void HTNewsNode_setRefInfo_pass3 (HTNewsDir* dir, HTNewsNode* node){    if (!node->fake)        node->refLevel = HTNewsNode_refLevel(node);}#endif/* Added by MP. */PRIVATE int HTNewsNode_compareRefThread (HTNewsNode* node1, HTNewsNode* node2){    int level1 = node1->refLevel;    int level2 = node2->refLevel;    int level = HTMAX(level1, level2);    int i;    HTNewsNode* parent1;    HTNewsNode* parent2;    int diff = 0;    for (i = level; i >= 0; i--)    {        parent1 = (i < level1 ? parent1->refParent : node1);        parent2 = (i < level2 ? parent2->refParent : node2);        if (parent1 == parent2)            return diff;  /* related messages (in same subtree) */        else        {            time_t date1 = (i > level1 ? 0 : HTNewsNode_getDate(parent1, YES));            time_t date2 = (i > level2 ? 0 : HTNewsNode_getDate(parent2, YES));            diff = date1 - date2;            if (diff == 0)            {                int idx1 = (i > level1 ? 0 : HTNewsNode_getIndex(parent1, YES));                int idx2 = (i > level2 ? 0 : HTNewsNode_getIndex(parent2, YES));                diff = idx1 - idx2;            }        }    }    return diff;  /* completely unrelated messages */}/***	Output an element in HTML**	Returns YES if OK, else NO*/PRIVATE BOOL HTNewsNode_print (HTNewsDir * dir, HTNewsNode * node){    if (node && node->show) {	HTStructured *target = dir->target;	char  * escaped;    	HTNewsDir_addLevelTags (dir, node->refLevel);  /* Added by MP. */	START(HTML_LI);	/* Start the anchor and put the subject as anchor text */	/*  Changed by MP to allow nodes without names */	if (!node->fake && node->name && node->subject)  {	    escaped = HTEscape(node->name, URL_XPALPHAS);	    HTStartAnchor(target, NULL, escaped);	}	if (node->subject) PUTS(node->subject);	if (!node->fake && node->name && node->subject) {	    END(HTML_A);	    HT_FREE(escaped);	}	/* From field */	if (node->from)  {	    PUTS (" by ");  /* Changed by MP. */	    PUTS(node->from);	}	/*  In group listing, put number of groups in the set; added by MP. */	if (node->name && strrchr(node->name, '*')) {	    char buf[16];	    sprintf (buf, " (%d groups)", node->refChildren);	    PUTS (buf);	}    }    return YES;}/* ------------------------------------------------------------------------- *//*				DIRECTORY MANAGEMENT 			     *//* ------------------------------------------------------------------------- */

⌨️ 快捷键说明

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