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