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