📄 htndir.c
字号:
/* 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, BOOL cache){ HTNewsDir *dir; if (!request) return NULL; /* Create object */ if ((dir = (HTNewsDir *) HT_CALLOC(1, sizeof (HTNewsDir))) == NULL) HT_OUTOFMEM("HTNewsDir_new"); dir->target = HTMLGenerator(request, NULL, WWW_HTML, HTRequest_outputFormat(request), HTRequest_outputStream(request)); HTAnchor_setFormat(HTRequest_anchor(request), WWW_HTML); dir->request = request; dir->key = key; dir->lastLevel = -1; /* Added by MP. */ /* Get the newsgroup(s) name; added by MP. */ { char* url = HTAnchor_physical(HTRequest_anchor(request)); char* p = url+strlen(url); while (p > url && p[-1] != ':' && p[-1] != '/' && p[-1] != '\\') p--; StrAllocCopy (dir->name, p); } if (key != HT_NDK_NONE) { /* Thread is unsorted */ int total = HTNews_maxArticles(); dir->array = HTArray_new(total > 0 ? total : 128); } /* If we are asked to prepare a cache entry then create the cache array */ if (cache) { int total = HTNews_maxArticles(); dir->cache = HTArray_new(total > 0 ? total : 128); } /* Start the HTML stuff */ { HTStructured *target = dir->target; const 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 name can** can be 0 or NULL.** Returns new node pointer if OK, else NULL** Changed by MP: reference list added.** Note: Unlike other parameters, refNames is not copied, but assigned, so** it has to contain copies of message names, not the originals.*/PUBLIC HTNewsNode* HTNewsDir_addElement (HTNewsDir * dir, int index, char * subject, char * from, time_t date, char * name, int refs, HTList * refNames){ if (dir && name) { HTNewsNode * node = HTNewsNode_new(index, subject, from, date, name, refs, refNames); if (dir->key == HT_NDK_NONE) { HTNewsNode_print(dir, node); HTNewsNode_delete(node, (dir->cache!=NULL)); } else HTArray_addObject(dir->array, (void *) node); return node; } return NULL;}/* Helper function - added by MP. */PRIVATE HTNewsNode* HTNewsDir_addFakeElement (HTNewsDir * dir, char * subject, char * name){ HTNewsNode * node = HTNewsDir_addElement(dir, 0, subject, NULL, 0, name, 0, NULL); if (node) { node->show = NO; node->fake = YES; } return node;}/* Helper function - added by MP. */PUBLIC HTNewsNode * HTNewsDir_addGroupElement (HTNewsDir * dir, char * group, BOOL tmplate){ HTNewsNode * node = NULL; if (dir && group) { if (HTNewsDir_belongsToSet(dir, group)) node=HTNewsDir_addElement (dir, 0, group, NULL, 0, group, 0, NULL); /* If we are building a cache object then add the entry */ if (dir->cache && !tmplate) { char * name = node ? node->name : NULL; if (!name) StrAllocCopy(name, group); HTArray_addObject(dir->cache, name); } } return node;}/* Added by MP. */PUBLIC BOOL HTNewsDir_belongsToSet (HTNewsDir* dir, char* group){ char* p; if (!dir->name || !*(dir->name)) return YES; p = strrchr(dir->name, '*'); if (!p) return strcasecomp(group, dir->name) == 0; else { int len = p - dir->name; return strncasecomp(group, dir->name, len) == 0; }}/* Added by MP. */PRIVATE void HTNewsDir_addLevelTags (HTNewsDir* dir, int level){ HTStructured *target = dir->target; int i = level; while (i > dir->lastLevel) { START(HTML_UL); i--; } while (i < dir->lastLevel) { END(HTML_UL); i++; } dir->lastLevel = level;}/* Added by MP. */PRIVATE HTNewsNode* HTNewsDir_findNodeNamed (HTNewsDir* dir, char* name){ int i; for (i = 0; i < HTArray_size(dir->array); i++) { HTNewsNode* node = (HTNewsNode*)(HTArray_data(dir->array)[i]); if (node->name && strcasecomp(node->name, name) == 0) return node; } return NULL;}/* Added by MP. */PRIVATE HTNewsNode* HTNewsDir_findNodeWithSubject (HTNewsDir* dir, char* subject, int which, HTNewsNode* avoidNode){ int i; int whichDate = (which & FNWS_MIN ? -1 : (which & FNWS_MAX ? 1 : 0)); HTNewsNode* foundNode = NULL; for (i = 0; i < HTArray_size(dir->array); i++) { HTNewsNode* node = (HTNewsNode*)(HTArray_data(dir->array)[i]); if (!(which & FNWS_ONLYFAKE && !node->fake) && !(which & FNWS_NOTFAKE && node->fake) && !(which & FNWS_NOTORPHAN && !node->fake && !node->refNames) && node != avoidNode && node->subject && strcasecomp(node->subject, subject) == 0) { if (which == FNWS_ANY) return node; else if (!foundNode || (node->date != 0 && (node->date - foundNode->date) * (long)whichDate > 0)) foundNode = node; } } return foundNode;}/* Added by MP. */PRIVATE void HTNewsDir_setRefInfo (HTNewsDir* dir){ /* Array grows when fake elements are added. */ /* We don't want to set reference info for fake elements. */ int size = HTArray_size(dir->array); int i; for (i = 0; i < size; i++) HTNewsNode_setRefInfo_pass1 (dir, (HTNewsNode*)(HTArray_data(dir->array)[i])); for (i = 0; i < size; i++) HTNewsNode_setRefInfo_pass2 (dir, (HTNewsNode*)(HTArray_data(dir->array)[i])); for (i = 0; i < size; i++) HTNewsNode_setRefInfo_pass3 (dir, (HTNewsNode*)(HTArray_data(dir->array)[i]));}PRIVATE void make_template (HTNewsDir * dir, HTNewsNode * node){ HT_FREE(dir->tmplate); if ((dir->tmplate = (char *) HT_MALLOC(strlen(node->name) + 3)) == NULL) HT_OUTOFMEM("HTNewsNode_setGroupInfo"); { char * p1 = dir->name; char * p2 = dir->tmplate; strcpy(p2, node->name); while (*p1 && *p2 && *p1 == *p2) p1++, p2++; while (*p2 && *p2 != '.') p2++; if (*p2) { strcpy(p2, ".*"); dir->tmplate_node=HTNewsDir_addGroupElement(dir, dir->tmplate,YES); dir->tmplate_node->is_tmplate = YES; } else { HT_FREE(dir->tmplate); dir->tmplate_node = node; } dir->tmplate_node->show = YES; }}/*** Runs through a sorted list of news groups and identifies the group** hierarchy. Template groups are added to the list, for example as** "alt.*"*/PRIVATE void HTNewsDir_setGroupInfo (HTNewsDir * dir){ HTArray * array = dir->array; HTNewsNode * node; int cur_size = HTArray_size(array); int cnt; /* ** If we don't have a template to test against then create one ** A template can be something like "alt.*" for example */ for (cnt=0; cnt<cur_size; cnt++) { node = (HTNewsNode *) HTArray_data(array)[cnt]; /* ** Make a template if we don't have any */ if (!dir->tmplate) make_template(dir, node); /* ** Now, if we do have a template then test the node name against ** it to see if we have this group already or it is a new group ** at this level in the hierarchy */ if (dir->tmplate) { if (HTStrCaseMatch(dir->tmplate, node->name) == NULL) { make_template(dir, node); } else { HTNewsNode * tmp_node = dir->tmplate_node; /* Should we show this element in the list? */ if (tmp_node->lastChild) { tmp_node->lastChild->show = NO; node->show = NO; } } HTNewsNode_linkRef(dir->tmplate_node, node); } }}PRIVATE int NDirIndexSort (const void *a, const void *b){ int aa = (*((HTNewsNode **)a))->index; int bb = (*((HTNewsNode **)b))->index; return aa-bb;}PRIVATE int NDirSubjectSort (const void *a, const void *b){ char *aa = (*((HTNewsNode **)a))->subject; char *bb = (*((HTNewsNode **)b))->subject; return strcasecomp(aa?aa:"", bb?bb:"");}PRIVATE int NDirFromSort (const void *a, const void *b){ char *aa = (*((HTNewsNode **)a))->from; char *bb = (*((HTNewsNode **)b))->from; return strcasecomp(aa?aa:"", bb?bb:"");}PRIVATE int NDirDateSort (const void *a, const void *b){ time_t aa = (*((HTNewsNode **)a))->date; time_t bb = (*((HTNewsNode **)b))->date; return bb-aa;}PRIVATE int NDirGroupSort (const void *a, const void *b){ char *aa = (*((HTNewsNode **)a))->name; char *bb = (*((HTNewsNode **)b))->name; while (*aa && *bb && TOLOWER(*aa)==TOLOWER(*bb)) aa++, bb++; return (*aa=='.' && *bb) ? -1 : (*aa && *bb=='.') ? 1 : TOLOWER(*aa)-TOLOWER(*bb);}/* Added by MP. */PRIVATE int NDirRefThreadSort (const void* a, const void* b){ HTNewsNode* aa = *((HTNewsNode**)a); HTNewsNode* bb = *((HTNewsNode**)b); return HTNewsNode_compareRefThread(aa,bb);}/* 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 (dir->key != HT_NDK_NONE) { HTArray * array = dir->array; HTArray * cache = NULL; HTComparer * comp = NULL; /* ** Find a suitable sort key for this listing. The sort function ** depends on the type of new listing we have received. */ if (dir->key == HT_NDK_INDEX) /* Sort by Message Number */ comp = NDirIndexSort; else if (dir->key == HT_NDK_DATE) /* Sort by Date */ comp = NDirDateSort; else if (dir->key == HT_NDK_SUBJECT) /* Sort after Subject */ comp = NDirSubjectSort; else if (dir->key == HT_NDK_FROM) /* Sort after From */ comp = NDirFromSort; else if (dir->key == HT_NDK_GROUP) { /* Sort as group hierarchi */ comp = NDirGroupSort; } else if (dir->key == HT_NDK_REFTHREAD) { /* Added by MP. */ HTNewsDir_setRefInfo (dir); comp = NDirRefThreadSort; } else { HTTRACE(STREAM_TRACE, "NewsListing. Invalid sortkey\n"); return NO; } /* ** Now sort the array of news items that we have read with the sort ** function defined by the sort key above. */ HTArray_sort(array, comp); /* ** If we are showing a group listing then run through the list and ** identify group hierarchy. We have to sort the thing again in order ** to get the new template groups included */ if (dir->key == HT_NDK_GROUP) { HTNewsDir_setGroupInfo(dir); HTArray_sort(array, comp); } /* ** After we have sorted the listing, we can write out the result and ** free the array. */ { void ** data; HTNewsNode *node = (HTNewsNode *) HTArray_firstObject(array, data); while (node) { HTNewsNode_print(dir, node); /* ** Create a special array for the cache containing the group ** names only and no templates */ if (dir->key == HT_NDK_GROUP && !node->is_tmplate) HTArray_addObject(cache, node->name); HTNewsNode_delete(node, (dir->cache!=NULL)); node = (HTNewsNode *) HTArray_nextObject(array, data); } HTArray_delete(array); } /* Update the cache */ if (dir->cache) HTNewsCache_after(dir->request, NULL, dir->cache, 0); } /* Put out the end of the HTML stuff */ { HTStructured *target = dir->target; /* END(HTML_UL); */ HTNewsDir_addLevelTags (dir, -1); START(HTML_HR); END(HTML_BODY); END(HTML_HTML); FREE_TARGET; } /* Clean up the dir object */ HT_FREE(dir->name); HT_FREE(dir->tmplate); HT_FREE(dir); return YES;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -