File:  [Public] / libwww / Library / src / HTNDir.c
Revision 2.2: download - view: text, annotated - select for diffs
Sun Nov 5 20:13:26 1995 UTC (28 years, 7 months ago) by frystyk
Branches: MAIN
CVS tags: v4/0pre5, HEAD
fprintf replaced with TTYPrint for windows

/*							       	     HTNDir.c
**	GENERIC NEWS LISTINGS
**
**	(c) COPYRIGHT MIT 1995.
**	Please first read the full copyright statement in the file COPYRIGH.
**
**	Creates listings for all kind of News output.
**
** Authors:
**	HF	Henrik Frystyk, MIT, <frystyk@w3.org>
** History:
**	   Oct 95  HFN	written
*/

/* Library include files */
#include "tcp.h"
#include "HTUtils.h"
#include "HTString.h"
#include "HTMLPDTD.h"
#include "HTMLGen.h"
#include "HTEscape.h"
#include "HTParse.h"
#include "HTFormat.h"
#include "HTReq.h"
#include "HTStruct.h"
#include "HTArray.h"
#include "HTError.h"
#include "HTNews.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 _HTNewsDir {
    HTStructured *	target;
    HTRequest *		request;
    HTArray *		array;			/* Array for sorted listings */
    char *		line;
    BOOL		top;				/* YES if first line */
    HTNewsDirKey	key;				  /* Key for sorting */
};

typedef struct _HTNewsNode {
    char *	key;
    int		index;
    char *	name;
    char *	subject;
    char *	from;
    int		refs;				     /* Number of references */
    BOOL	filter;			      /* Is this entry filtered out? */
} HTNewsNode;

PRIVATE int MaxLineW = DEFAULT_MAXW;

/* ------------------------------------------------------------------------- */
/*				NODE  MANAGEMENT 			     */
/* ------------------------------------------------------------------------- */

/*
**	Create a sort key node
*/
PRIVATE HTNewsNode * HTNewsNode_new (void)
{
    HTNewsNode *node;
    if ((node = (HTNewsNode *) calloc(1, sizeof(HTNewsNode))) == NULL)
	outofmem(__FILE__, "HTNewsNode_new");
    return node;
}

/*
**	Free a sort key node
*/
PRIVATE BOOL HTNewsNode_free (HTNewsNode *node)
{
    if (node) {
	FREE(node->name);
	FREE(node->subject);
	FREE(node->from);
	free(node);
	return YES;
    }
    return NO;
}

/*
**	Output an element in HTML
**	Returns YES if OK, else NO
*/
PRIVATE BOOL HTNewsNode_print (HTNewsDir *dir, HTNewsNode *node)
{
    char *tp = NULL;
    HTStructured *target = dir->target;
#if 1
    TTYPrint(TDEST, "%s\n", node->name);
#else
    if (dir->show & HT_DS_ICON) {
	HTFormat format = NULL;
	HTEncoding encoding = NULL;
	double q=1.0;
	HTIconNode *icon;
	HTHrefNode *href;
	if (node->mode == HT_IS_FILE)
	    HTBind_getFormat(node->fname, &format, &encoding, NULL, &q);
	icon = HTGetIcon(node->mode, format, encoding);
	href = HTGetHref(node->fname);

	/* Are we having a hot or a cold icon? */
	if (!(dir->show & HT_DS_HOTI)) {
	    HTMLPutImg(target, icon->icon_url,
		       HTIcon_alt_string(icon->icon_alt, YES), NULL);
	    PUTC(' ');
	}

	/* Start the anchor element */
	if (dir->base) {
	    char *escaped = HTEscape(node->fname, URL_XPALPHAS);
	    char *full = malloc(strlen(escaped)+strlen(dir->base)+1);
	    if (!full) outofmem(__FILE__, "HTNewsNode_print");
	    strcpy(full, dir->base);
	    strcat(full, escaped);
	    HTStartAnchor(target, NULL, full);
	    free(escaped);
	    free(full);
	} else {
	    char *escaped = HTEscape(node->fname, URL_XPALPHAS);
	    HTStartAnchor(target, NULL, escaped);
	    free(escaped);
	}

	if (dir->show & HT_DS_HOTI) {
	    HTMLPutImg(target, icon->icon_url,
		       HTIcon_alt_string(icon->icon_alt, YES), NULL);
	    PUTC(' ');
	}
    } else {
	if (dir->base) {
	    char *escaped = HTEscape(node->fname, URL_XPALPHAS);
	    char *full = malloc(strlen(escaped)+strlen(dir->base)+1);
	    if (!full) outofmem(__FILE__, "HTNewsNode_print");
	    strcpy(full, dir->base);
	    strcat(full, escaped);
	    HTStartAnchor(target, NULL, escaped);
	    free(escaped);
	    free(full);
	} else {
	    char *escaped = HTEscape(node->fname, URL_XPALPHAS);
	    HTStartAnchor(target, NULL, escaped);
	    free(escaped);
	}
    }
    
    /* Insert the anchor text and end anchor */
    {
	char *in = node->fname;
	char *out = dir->fnbuf;
	int l = dir->curfw;
	while (l-- > 0 && *in && (*out++ = *in++));
	if (*in)
	    *(out-1) = '>';
	else if (node->mode == HT_IS_DIR) {
	    *out++ = '/';
	    l--;
	}
	*out = '\0';
	PUTS(dir->fnbuf);
	END(HTML_A);
	out = dir->fnbuf;
	while (l-- >= 0) *out++ = ' ';
	LeftStr(&out, " ", HT_DLEN_SPACE);
	*out = '\0';
	PUTS(dir->fnbuf);
    }

    /* Print the rest of it */
    tp = dir->lnbuf;
    if (node->date) {
	RightStr(&tp, node->date, HT_DLEN_DATE);
	LeftStr(&tp, " ", HT_DLEN_SPACE);
    }
    if (node->size) {
	RightStr(&tp, node->size, HT_DLEN_SIZE);
	LeftStr(&tp, " ", HT_DLEN_SPACE);
    }
    if (node->note) {
	LeftStr(&tp, node->note, HT_DLEN_DES);
	LeftStr(&tp, " ", HT_DLEN_SPACE);
    }
    *tp = '\0';
    PUTS(dir->lnbuf);
    PUTC('\n');
#endif
    return YES;
}

/* ------------------------------------------------------------------------- */
/*				DIRECTORY MANAGEMENT 			     */
/* ------------------------------------------------------------------------- */

/*	HTNewsDir_headLine
**	---------------
**    	Puts out the header line of the list itself
**	Returns YES if OK, else NO
*/
PRIVATE BOOL HTNewsDir_headLine (HTNewsDir *dir)
{
    if (dir) {
	char *tp;
	HTStructured *target = dir->target;
#if 0
	START(HTML_PRE);
	if (dir->show & HT_DS_ICON) {
	    HTIconNode *icon = HTGetIcon(HT_IS_BLANK, NULL, NULL);
	    HTMLPutImg(target, icon->icon_url,
		       HTIcon_alt_string(icon->icon_alt, YES), NULL);
	    PUTC(' ');
	}

	tp = dir->fnbuf;
	LeftStr(&tp, "Name", dir->curfw);
	LeftStr(&tp, " ", HT_DLEN_SPACE);
	*tp = '\0';
	PUTS(dir->fnbuf);

	tp = dir->lnbuf;
	if (dir->show & HT_DS_DATE) {
	    LeftStr(&tp, "Last Modified", HT_DLEN_DATE);
	    LeftStr(&tp, " ", HT_DLEN_SPACE);
	}
	if (dir->show & HT_DS_SIZE) {
	    RightStr(&tp, "Size", HT_DLEN_SIZE);
	    LeftStr(&tp, " ", HT_DLEN_SPACE);
	}
	if (dir->show & HT_DS_DES) {
	    LeftStr(&tp, "Description", HT_DLEN_DATE);
	    LeftStr(&tp, " ", HT_DLEN_SPACE);
	}
	*tp = '\0';
	PUTS(dir->lnbuf);
	START(HTML_HR);
	PUTC('\n');
#endif
	return YES;
    }
    return NO;
}

/*	HTNewsDir_setWidth
**	------------------
**	The module automatically ajusts the width of the directory listing as
**	a function of the file name. The width can flows dynamically between
**	an upper and a lower limit.
*/
PUBLIC BOOL HTNewsDir_setWidth (int max_width)
{
    MaxLineW = (max_width > 0) ? max_width : DEFAULT_MAXW;
    return YES;
}

/*	HTNewsDir_new
**	----------
**    	Creates a structured stream object and sets up the initial HTML stuff
**	Returns the newsdir object if OK, else NULL
*/
PUBLIC HTNewsDir * HTNewsDir_new (HTRequest * request, CONST char * title,
				  HTNewsDirKey key)
{
    HTNewsDir *dir;
    if (!request) return NULL;

    /* Create object */
    if ((dir = (HTNewsDir *) calloc(1, sizeof (HTNewsDir))) == NULL ||
	(dir->line = (char *) malloc(MaxLineW)) == NULL)
	outofmem(__FILE__, "HTNewsDir_new");
    dir->target = HTMLGenerator(request, NULL, WWW_HTML,
				HTRequest_outputFormat(request),
				HTRequest_outputStream(request));
    dir->request = request;
    dir->top = YES;
    dir->key = key;
    if (key != HT_NDK_THREAD) {
	int total = HTNews_maxArticles();
	dir->array = HTArray_new(total > 0 ? total : 128);
    }

    /* Start the HTML stuff */
    {
	HTStructured *target = dir->target;
	char *msg = title ? title : "News Listing";
	START(HTML_HTML);
	START(HTML_HEAD);
	START(HTML_TITLE);
	PUTS(msg);
	END(HTML_TITLE);
	END(HTML_HEAD);
	START(HTML_BODY);
	START(HTML_H1);
	PUTS(msg);
	END(HTML_H1);
    }
    return dir;
}

/*	HTNewsDir_addElement
**	--------------------
**    	This function accepts a news line. Everything except dir and nama can
**	can be 0 or NULL.
**	Returns YES if OK, else NO
*/
PUBLIC BOOL HTNewsDir_addElement (HTNewsDir * dir, char * name, int  index,
				  char * subject, char * from, int refs)
{
    HTNewsNode *node = HTNewsNode_new();
    if (!dir || !name) return NO;
    StrAllocCopy(node->name, name);				/* Mandatory */
    if (subject) StrAllocCopy(node->subject, subject);
    if (from) StrAllocCopy(node->from, from);
    if (dir->key == HT_NDK_THREAD) {
	if (dir->top) {
	    HTNewsDir_headLine(dir);
	    dir->top = NO;
	}
	HTNewsNode_print(dir, node);
	HTNewsNode_free(node);
    } else
	HTArray_addObject(dir->array, (void *) node);
    return YES;
}

#if 0
PRIVATE int DirSort (CONST void *a, CONST void *b)
{
    HTNewsNode *aa = *(HTNewsNode **) a;
    HTNewsNode *bb = *(HTNewsNode **) b;
    return strcmp(aa->fname, bb->fname);
#if 0
    return strcmp((*(HTNewsNode**)a)->fname, (*(HTNewsNode**)a)->fname);
#endif
}

PRIVATE int DirCaseSort (CONST void *a, CONST void *b)
{
    HTNewsNode *aa = *(HTNewsNode **) a;
    HTNewsNode *bb = *(HTNewsNode **) b;
    return strcasecomp(aa->fname, bb->fname);
#if 0
    return strcasecomp((*(HTNewsNode**)a)->fname, (*(HTNewsNode**)a)->fname);
#endif
}
#endif

/*	HTNewsDir_free
**	--------------
**    	If we are sorting then do the sorting and put out the list,
**	else just append the end of the list.
*/
PUBLIC BOOL HTNewsDir_free (HTNewsDir * dir)
{
    if (!dir) return NO;
#if 0
    if (dir->key != HT_DK_THREAD) {
	HTArray *array = dir->array;
	void **data;
	HTNewsNode *node;
	HTNewsDir_headLine(dir);	
	HTArray_sort(array, (dir->key==HT_DK_CINS ? DirCaseSort : DirSort));
	node = (HTNewsNode *) HTArray_firstObject(array, data);
	while (node) {
	    HTNewsNode_print(dir, node);
	    HTNewsNode_free(node);
	    node = (HTNewsNode *) HTArray_nextObject(array, data);
	}
	dir->size = HTArray_size(array);
    	HTArray_delete(array);	
    }
#endif

    /* Put out the end of the HTML stuff */
    {
	HTStructured *target = dir->target;
	START(HTML_HR);
	END(HTML_BODY);
	END(HTML_HTML);
	FREE_TARGET;
    }

    FREE(dir->line);
    free(dir);
    return YES;
}

Webmaster