Annotation of libwww/Library/src/HTNDir.c, revision 2.5
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;
2.5 ! frystyk 76: if ((node = (HTNewsNode *) HT_CALLOC(1, sizeof(HTNewsNode))) == NULL)
! 77: HT_OUTOFMEM("HTNewsNode_new");
2.1 frystyk 78: return node;
79: }
80:
81: /*
82: ** Free a sort key node
83: */
84: PRIVATE BOOL HTNewsNode_free (HTNewsNode *node)
85: {
86: if (node) {
2.5 ! frystyk 87: HT_FREE(node->name);
! 88: HT_FREE(node->subject);
! 89: HT_FREE(node->from);
! 90: HT_FREE(node);
2.1 frystyk 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.5 ! frystyk 111: HT_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.5 ! frystyk 166: if ((dir = (HTNewsDir *) HT_CALLOC(1, sizeof (HTNewsDir))) == NULL)
! 167: HT_OUTOFMEM("HTNewsDir_new");
2.1 frystyk 168: dir->target = HTMLGenerator(request, NULL, WWW_HTML,
169: HTRequest_outputFormat(request),
170: HTRequest_outputStream(request));
2.4 frystyk 171: HTAnchor_setFormat(HTRequest_anchor(request), WWW_HTML);
2.1 frystyk 172: dir->request = request;
173: dir->top = YES;
174: dir->key = key;
2.3 frystyk 175: if (key != HT_NDK_NONE) { /* Thread is unsorted */
2.1 frystyk 176: int total = HTNews_maxArticles();
177: dir->array = HTArray_new(total > 0 ? total : 128);
178: }
179:
180: /* Start the HTML stuff */
181: {
182: HTStructured *target = dir->target;
2.3 frystyk 183: CONST char *msg = title ? title : "News Listing";
2.1 frystyk 184: START(HTML_HTML);
185: START(HTML_HEAD);
186: START(HTML_TITLE);
187: PUTS(msg);
188: END(HTML_TITLE);
189: END(HTML_HEAD);
190: START(HTML_BODY);
191: START(HTML_H1);
192: PUTS(msg);
193: END(HTML_H1);
194: }
195: return dir;
196: }
197:
198: /* HTNewsDir_addElement
199: ** --------------------
2.3 frystyk 200: ** This function accepts a news line. Everything except dir and name can
2.1 frystyk 201: ** can be 0 or NULL.
202: ** Returns YES if OK, else NO
203: */
2.3 frystyk 204: PUBLIC BOOL HTNewsDir_addElement (HTNewsDir * dir, int index, char * subject,
205: char * from, time_t date, char * name,
206: int refs)
2.1 frystyk 207: {
208: HTNewsNode *node = HTNewsNode_new();
209: if (!dir || !name) return NO;
210: StrAllocCopy(node->name, name); /* Mandatory */
211: if (subject) StrAllocCopy(node->subject, subject);
212: if (from) StrAllocCopy(node->from, from);
2.3 frystyk 213: node->date = date;
214: if (dir->key == HT_NDK_NONE) {
2.1 frystyk 215: if (dir->top) {
216: HTNewsDir_headLine(dir);
217: dir->top = NO;
218: }
219: HTNewsNode_print(dir, node);
220: HTNewsNode_free(node);
221: } else
222: HTArray_addObject(dir->array, (void *) node);
223: return YES;
224: }
225:
2.3 frystyk 226: PRIVATE int NDirIndexSort (CONST void *a, CONST void *b)
227: {
228: int aa = (*((HTNewsNode **)a))->index;
229: int bb = (*((HTNewsNode **)b))->index;
230: return aa-bb;
231: }
232:
233: PRIVATE int NDirSubjectSort (CONST void *a, CONST void *b)
2.1 frystyk 234: {
235: #if 0
2.3 frystyk 236: char *aa = (*((HTNewsNode **)a))->subject;
237: char *bb = (*((HTNewsNode **)b))->subject;
2.1 frystyk 238: #endif
2.3 frystyk 239: return 0;
2.1 frystyk 240: }
241:
2.3 frystyk 242: PRIVATE int NDirFromSort (CONST void *a, CONST void *b)
2.1 frystyk 243: {
2.3 frystyk 244: #if 0
2.1 frystyk 245: HTNewsNode *aa = *(HTNewsNode **) a;
246: HTNewsNode *bb = *(HTNewsNode **) b;
247: return strcasecomp(aa->fname, bb->fname);
248: return strcasecomp((*(HTNewsNode**)a)->fname, (*(HTNewsNode**)a)->fname);
2.3 frystyk 249:
250: char *aa = (*((HTNewsNode **)a))->name;
251: char *bb = (*((HTNewsNode **)b))->name;
2.1 frystyk 252: #endif
2.3 frystyk 253: return 1;
254: }
255:
256: PRIVATE int NDirDateSort (CONST void *a, CONST void *b)
257: {
258: time_t aa = (*((HTNewsNode **)a))->date;
259: time_t bb = (*((HTNewsNode **)b))->date;
260: return bb-aa;
261: }
262:
263: PRIVATE int NDirGroupSort (CONST void *a, CONST void *b)
264: {
265: char *aa = (*((HTNewsNode **)a))->name;
266: char *bb = (*((HTNewsNode **)b))->name;
267: while (*aa && *bb && TOLOWER(*aa)==TOLOWER(*bb)) aa++, bb++;
268: return (*aa=='.' && *bb) ? -1 : (*aa && *bb=='.') ?
269: 1 : TOLOWER(*aa)-TOLOWER(*bb);
2.1 frystyk 270: }
271:
272: /* HTNewsDir_free
273: ** --------------
274: ** If we are sorting then do the sorting and put out the list,
275: ** else just append the end of the list.
276: */
277: PUBLIC BOOL HTNewsDir_free (HTNewsDir * dir)
278: {
279: if (!dir) return NO;
2.3 frystyk 280: if (dir->key != HT_NDK_NONE) {
2.1 frystyk 281: HTArray *array = dir->array;
2.3 frystyk 282: HTComparer * comp = NULL;
2.1 frystyk 283: HTNewsDir_headLine(dir);
2.3 frystyk 284: if (dir->key == HT_NDK_INDEX) /* Sort by Message Number */
285: comp = NDirIndexSort;
286: if (dir->key == HT_NDK_DATE) /* Sort by Date */
287: comp = NDirDateSort;
288: if (dir->key == HT_NDK_SUBJECT) /* Sort after Subject */
289: comp = NDirSubjectSort;
290: else if (dir->key == HT_NDK_FROM) /* Sort after From */
291: comp = NDirFromSort;
292: else if (dir->key == HT_NDK_GROUP) /* Sort as group hierarchi */
293: comp = NDirGroupSort;
294: else {
295: if (STREAM_TRACE) TTYPrint(TDEST,"NewsListing. Invalid sortkey\n");
296: return NO;
297: }
298: HTArray_sort(array, comp);
299: {
300: void **data;
301: HTNewsNode *node = (HTNewsNode *) HTArray_firstObject(array, data);
302: while (node) {
303: HTNewsNode_print(dir, node);
304: HTNewsNode_free(node);
305: node = (HTNewsNode *) HTArray_nextObject(array, data);
306: }
2.1 frystyk 307: }
308: HTArray_delete(array);
309: }
310:
311: /* Put out the end of the HTML stuff */
312: {
313: HTStructured *target = dir->target;
2.3 frystyk 314: END(HTML_UL);
2.1 frystyk 315: START(HTML_HR);
316: END(HTML_BODY);
317: END(HTML_HTML);
318: FREE_TARGET;
319: }
2.5 ! frystyk 320: HT_FREE(dir);
2.1 frystyk 321: return YES;
322: }
Webmaster