Annotation of libwww/Library/src/HTNDir.c, revision 2.3
2.1 frystyk 1: /* HTNDir.c
2: ** GENERIC NEWS LISTINGS
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
6: **
7: ** Creates listings for all kind of News output.
8: **
9: ** Authors:
10: ** HF Henrik Frystyk, MIT, <frystyk@w3.org>
11: ** History:
12: ** Oct 95 HFN written
13: */
14:
15: /* Library include files */
16: #include "tcp.h"
17: #include "HTUtils.h"
18: #include "HTString.h"
19: #include "HTMLPDTD.h"
20: #include "HTMLGen.h"
21: #include "HTEscape.h"
22: #include "HTParse.h"
23: #include "HTFormat.h"
24: #include "HTReq.h"
25: #include "HTStruct.h"
26: #include "HTArray.h"
27: #include "HTError.h"
28: #include "HTNews.h"
29: #include "HTNDir.h" /* Implemented here */
30:
31: /* Macros and other defines */
32: #define PUTC(c) (*target->isa->put_character)(target, c)
33: #define PUTS(s) (*target->isa->put_string)(target, s)
34: #define START(e) (*target->isa->start_element)(target, e, 0, 0)
35: #define END(e) (*target->isa->end_element)(target, e)
36: #define FREE_TARGET (*target->isa->_free)(target)
37:
38: #define DEFAULT_MAXW 80 /* Default line width */
39:
40: /* Type definitions and global variables etc. local to this module */
41: struct _HTStructured {
42: CONST HTStructuredClass * isa;
43: /* ... */
44: };
45:
46: struct _HTNewsDir {
47: HTStructured * target;
48: HTRequest * request;
49: HTArray * array; /* Array for sorted listings */
50: BOOL top; /* YES if first line */
51: HTNewsDirKey key; /* Key for sorting */
52: };
53:
54: typedef struct _HTNewsNode {
55: int index;
56: char * name;
57: char * subject;
58: char * from;
2.3 ! frystyk 59: time_t date;
2.1 frystyk 60: int refs; /* Number of references */
61: BOOL filter; /* Is this entry filtered out? */
62: } HTNewsNode;
63:
64: PRIVATE int MaxLineW = DEFAULT_MAXW;
65:
66: /* ------------------------------------------------------------------------- */
67: /* NODE MANAGEMENT */
68: /* ------------------------------------------------------------------------- */
69:
70: /*
71: ** Create a sort key node
72: */
73: PRIVATE HTNewsNode * HTNewsNode_new (void)
74: {
75: HTNewsNode *node;
76: if ((node = (HTNewsNode *) calloc(1, sizeof(HTNewsNode))) == NULL)
77: outofmem(__FILE__, "HTNewsNode_new");
78: return node;
79: }
80:
81: /*
82: ** Free a sort key node
83: */
84: PRIVATE BOOL HTNewsNode_free (HTNewsNode *node)
85: {
86: if (node) {
87: FREE(node->name);
88: FREE(node->subject);
89: FREE(node->from);
90: free(node);
91: return YES;
92: }
93: return NO;
94: }
95:
96: /*
97: ** Output an element in HTML
98: ** Returns YES if OK, else NO
99: */
100: PRIVATE BOOL HTNewsNode_print (HTNewsDir *dir, HTNewsNode *node)
101: {
102: HTStructured *target = dir->target;
2.3 ! frystyk 103: START(HTML_LI);
2.1 frystyk 104:
2.3 ! frystyk 105: /* Start the anchor and put the subject as anchor text */
! 106: if (node->name && node->subject) {
! 107: char *escaped = HTEscape(node->name, URL_XPALPHAS);
! 108: HTStartAnchor(target, NULL, escaped);
! 109: PUTS(node->subject);
2.1 frystyk 110: END(HTML_A);
2.3 ! frystyk 111: free(escaped);
2.1 frystyk 112: }
113:
2.3 ! frystyk 114: /* From field */
! 115: if (node->from) {
! 116: PUTC(' ');
! 117: PUTS(node->from);
2.1 frystyk 118: }
119: return YES;
120: }
121:
122: /* ------------------------------------------------------------------------- */
123: /* DIRECTORY MANAGEMENT */
124: /* ------------------------------------------------------------------------- */
125:
126: /* HTNewsDir_headLine
127: ** ---------------
128: ** Puts out the header line of the list itself
129: ** Returns YES if OK, else NO
130: */
131: PRIVATE BOOL HTNewsDir_headLine (HTNewsDir *dir)
132: {
133: if (dir) {
134: HTStructured *target = dir->target;
2.3 ! frystyk 135: PUTS("HERE WE CAN PUT INFORMATION AND EXTRA LINKS\n");
2.1 frystyk 136: return YES;
2.3 ! frystyk 137: START(HTML_UL);
2.1 frystyk 138: }
139: return NO;
140: }
141:
142: /* HTNewsDir_setWidth
143: ** ------------------
144: ** The module automatically ajusts the width of the directory listing as
145: ** a function of the file name. The width can flows dynamically between
146: ** an upper and a lower limit.
147: */
148: PUBLIC BOOL HTNewsDir_setWidth (int max_width)
149: {
150: MaxLineW = (max_width > 0) ? max_width : DEFAULT_MAXW;
151: return YES;
152: }
153:
154: /* HTNewsDir_new
155: ** ----------
156: ** Creates a structured stream object and sets up the initial HTML stuff
157: ** Returns the newsdir object if OK, else NULL
158: */
159: PUBLIC HTNewsDir * HTNewsDir_new (HTRequest * request, CONST char * title,
160: HTNewsDirKey key)
161: {
162: HTNewsDir *dir;
163: if (!request) return NULL;
164:
165: /* Create object */
2.3 ! frystyk 166: if ((dir = (HTNewsDir *) calloc(1, sizeof (HTNewsDir))) == NULL)
2.1 frystyk 167: outofmem(__FILE__, "HTNewsDir_new");
168: dir->target = HTMLGenerator(request, NULL, WWW_HTML,
169: HTRequest_outputFormat(request),
170: HTRequest_outputStream(request));
171: dir->request = request;
172: dir->top = YES;
173: dir->key = key;
2.3 ! frystyk 174: if (key != HT_NDK_NONE) { /* Thread is unsorted */
2.1 frystyk 175: int total = HTNews_maxArticles();
176: dir->array = HTArray_new(total > 0 ? total : 128);
177: }
178:
179: /* Start the HTML stuff */
180: {
181: HTStructured *target = dir->target;
2.3 ! frystyk 182: CONST char *msg = title ? title : "News Listing";
2.1 frystyk 183: START(HTML_HTML);
184: START(HTML_HEAD);
185: START(HTML_TITLE);
186: PUTS(msg);
187: END(HTML_TITLE);
188: END(HTML_HEAD);
189: START(HTML_BODY);
190: START(HTML_H1);
191: PUTS(msg);
192: END(HTML_H1);
193: }
194: return dir;
195: }
196:
197: /* HTNewsDir_addElement
198: ** --------------------
2.3 ! frystyk 199: ** This function accepts a news line. Everything except dir and name can
2.1 frystyk 200: ** can be 0 or NULL.
201: ** Returns YES if OK, else NO
202: */
2.3 ! frystyk 203: PUBLIC BOOL HTNewsDir_addElement (HTNewsDir * dir, int index, char * subject,
! 204: char * from, time_t date, char * name,
! 205: int refs)
2.1 frystyk 206: {
207: HTNewsNode *node = HTNewsNode_new();
208: if (!dir || !name) return NO;
209: StrAllocCopy(node->name, name); /* Mandatory */
210: if (subject) StrAllocCopy(node->subject, subject);
211: if (from) StrAllocCopy(node->from, from);
2.3 ! frystyk 212: node->date = date;
! 213: if (dir->key == HT_NDK_NONE) {
2.1 frystyk 214: if (dir->top) {
215: HTNewsDir_headLine(dir);
216: dir->top = NO;
217: }
218: HTNewsNode_print(dir, node);
219: HTNewsNode_free(node);
220: } else
221: HTArray_addObject(dir->array, (void *) node);
222: return YES;
223: }
224:
2.3 ! frystyk 225: PRIVATE int NDirIndexSort (CONST void *a, CONST void *b)
! 226: {
! 227: int aa = (*((HTNewsNode **)a))->index;
! 228: int bb = (*((HTNewsNode **)b))->index;
! 229: return aa-bb;
! 230: }
! 231:
! 232: PRIVATE int NDirSubjectSort (CONST void *a, CONST void *b)
2.1 frystyk 233: {
234: #if 0
2.3 ! frystyk 235: char *aa = (*((HTNewsNode **)a))->subject;
! 236: char *bb = (*((HTNewsNode **)b))->subject;
2.1 frystyk 237: #endif
2.3 ! frystyk 238: return 0;
2.1 frystyk 239: }
240:
2.3 ! frystyk 241: PRIVATE int NDirFromSort (CONST void *a, CONST void *b)
2.1 frystyk 242: {
2.3 ! frystyk 243: #if 0
2.1 frystyk 244: HTNewsNode *aa = *(HTNewsNode **) a;
245: HTNewsNode *bb = *(HTNewsNode **) b;
246: return strcasecomp(aa->fname, bb->fname);
247: return strcasecomp((*(HTNewsNode**)a)->fname, (*(HTNewsNode**)a)->fname);
2.3 ! frystyk 248:
! 249: char *aa = (*((HTNewsNode **)a))->name;
! 250: char *bb = (*((HTNewsNode **)b))->name;
2.1 frystyk 251: #endif
2.3 ! frystyk 252: return 1;
! 253: }
! 254:
! 255: PRIVATE int NDirDateSort (CONST void *a, CONST void *b)
! 256: {
! 257: time_t aa = (*((HTNewsNode **)a))->date;
! 258: time_t bb = (*((HTNewsNode **)b))->date;
! 259: return bb-aa;
! 260: }
! 261:
! 262: PRIVATE int NDirGroupSort (CONST void *a, CONST void *b)
! 263: {
! 264: char *aa = (*((HTNewsNode **)a))->name;
! 265: char *bb = (*((HTNewsNode **)b))->name;
! 266: while (*aa && *bb && TOLOWER(*aa)==TOLOWER(*bb)) aa++, bb++;
! 267: return (*aa=='.' && *bb) ? -1 : (*aa && *bb=='.') ?
! 268: 1 : TOLOWER(*aa)-TOLOWER(*bb);
2.1 frystyk 269: }
270:
271: /* HTNewsDir_free
272: ** --------------
273: ** If we are sorting then do the sorting and put out the list,
274: ** else just append the end of the list.
275: */
276: PUBLIC BOOL HTNewsDir_free (HTNewsDir * dir)
277: {
278: if (!dir) return NO;
2.3 ! frystyk 279: if (dir->key != HT_NDK_NONE) {
2.1 frystyk 280: HTArray *array = dir->array;
2.3 ! frystyk 281: HTComparer * comp = NULL;
2.1 frystyk 282: HTNewsDir_headLine(dir);
2.3 ! frystyk 283: if (dir->key == HT_NDK_INDEX) /* Sort by Message Number */
! 284: comp = NDirIndexSort;
! 285: if (dir->key == HT_NDK_DATE) /* Sort by Date */
! 286: comp = NDirDateSort;
! 287: if (dir->key == HT_NDK_SUBJECT) /* Sort after Subject */
! 288: comp = NDirSubjectSort;
! 289: else if (dir->key == HT_NDK_FROM) /* Sort after From */
! 290: comp = NDirFromSort;
! 291: else if (dir->key == HT_NDK_GROUP) /* Sort as group hierarchi */
! 292: comp = NDirGroupSort;
! 293: else {
! 294: if (STREAM_TRACE) TTYPrint(TDEST,"NewsListing. Invalid sortkey\n");
! 295: return NO;
! 296: }
! 297: HTArray_sort(array, comp);
! 298: {
! 299: void **data;
! 300: HTNewsNode *node = (HTNewsNode *) HTArray_firstObject(array, data);
! 301: while (node) {
! 302: HTNewsNode_print(dir, node);
! 303: HTNewsNode_free(node);
! 304: node = (HTNewsNode *) HTArray_nextObject(array, data);
! 305: }
2.1 frystyk 306: }
307: HTArray_delete(array);
308: }
309:
310: /* Put out the end of the HTML stuff */
311: {
312: HTStructured *target = dir->target;
2.3 ! frystyk 313: END(HTML_UL);
2.1 frystyk 314: START(HTML_HR);
315: END(HTML_BODY);
316: END(HTML_HTML);
317: FREE_TARGET;
318: }
319: free(dir);
320: return YES;
321: }
Webmaster