?? rthread.c
字號:
/* $Id: rthread.c,v 3.0 1992/12/14 00:14:13 davison Trn $*/#include "EXTERN.h"#include "common.h"#include "intrp.h"#include "trn.h"#include "cache.h"#include "bits.h"#include "ng.h"#include "rcln.h"#include "search.h"#include "artstate.h"#include "rcstuff.h"#include "ngdata.h"#include "kfile.h"#include "head.h"#include "util.h"#include "hash.h"#include "nntp.h"#include "rt-mt.h"#include "rt-ov.h"#include "rt-page.h"#include "rt-process.h"#include "rt-select.h"#include "rt-wumpus.h"#include "INTERN.h"#include "rthread.h"HASHTABLE *msgid_hash = 0;bool try_ov = FALSE;bool try_mt = FALSE;voidthread_init(){#ifdef USE_OV try_ov = ov_init();#endif#ifdef USE_MT try_mt = mt_init();#endif}/* Generate the thread data we need for this group. We must call** thread_close() before calling this again.*/voidthread_open(){ if (!msgid_hash) msgid_hash = hashcreate(201, msgid_cmp); /*TODO: pick a better size */ if (ThreadedGroup) { /* Parse input and use msgid_hash for quick article lookups. */ /* If cached but not threaded articles exist, set up to thread them. */ if (first_subject) { first_cached = firstart; last_cached = firstart - 1; parsed_art = 0; } } if (sel_mode == SM_ARTICLE) set_selector(sel_mode, sel_artsort); else set_selector(sel_threadmode, sel_threadsort);#ifdef USE_MT if (try_mt && !first_subject) if (!mt_data()) return;#endif#ifdef USE_OV if (try_ov && first_cached > last_cached) if (thread_always) (void) ov_data(absfirst, lastart, FALSE); else if (firstart > lastart) { /* If no unread articles, see if ov. exists as quick as possible */ (void) ov_data(absfirst, absfirst, FALSE); first_cached = last_cached+1; } else (void) ov_data(firstart, lastart, FALSE);#endif#ifdef USE_NNTP if (!ov_opened) setmissingbits();#endif if (last_cached > lastart) { toread[ng] += (ART_UNREAD)(last_cached-lastart); /* ensure getngsize() knows the new maximum */ ngmax[ng] = lastart = last_cached; } thread_grow(); /* thread any new articles not yet in the database */ added_articles = 0; sel_page_sp = 0; sel_page_app = 0;}/* Update the group's thread info.*/voidthread_grow(){ added_articles = lastart - last_cached; if (added_articles > 0 && thread_always) cache_range(last_cached + 1, lastart); count_subjects(CS_NORM); if (artptr_list) sort_articles(); else sort_subjects();}static voidkill_tmp_arts(data, extra)HASHDATUM *data;int extra;{ register ARTICLE *ap = (ARTICLE*)data->dat_ptr; if (ap) free((char*)ap);}voidthread_close(){ curr_artp = artp = Nullart; init_tree(); /* free any tree lines */ if (msgid_hash) { hashwalk(msgid_hash, kill_tmp_arts, 0); hashdestroy(msgid_hash); msgid_hash = 0; } sel_page_sp = 0; sel_page_app = 0; sel_last_ap = 0; sel_last_sp = 0; selected_only = FALSE;#ifdef USE_OV ov_close();#endif}ARTICLE *find_article(artnum)ART_NUM artnum;{ if (artp && (artp->flags & AF_TMPMEM) == AF_TMPMEM && !artnum) return artp; if (artnum < absfirst || artnum > lastart) return (artp = Nullart); return (artp = article_ptr(artnum));}voidtop_article(){ art = lastart+1; artp = Nullart; inc_art(selected_only, FALSE);}ARTICLE *first_art(sp)register SUBJECT *sp;{ register ARTICLE *ap = (ThreadedGroup? sp->thread : sp->articles); if (ap && (ap->flags & AF_MISSING)) ap = next_art(ap); return ap;}ARTICLE *last_art(sp)register SUBJECT *sp;{ register ARTICLE *ap; if (!ThreadedGroup) { ap = sp->articles; while (ap->subj_next) ap = ap->subj_next; return ap; } ap = sp->thread; if (ap) { for (;;) { if (ap->sibling) ap = ap->sibling; else if (ap->child1) ap = ap->child1; else break; } if (ap->flags & AF_MISSING) ap = prev_art(ap); } return ap;}/* Bump art/artp to the next article, wrapping from thread to thread.** If sel_flag is TRUE, only stops at selected articles.** If rereading is FALSE, only stops at unread articles.*/voidinc_art(sel_flag, rereading)bool_int sel_flag, rereading;{ register ARTICLE *ap = artp; int subj_mask = (sel_mode == SM_THREAD? (SF_THREAD|SF_VISIT) : SF_VISIT); /* Use the explicit article-order if it exists */ if (artptr_list) { ARTICLE **limit = artptr_list + article_count; if (!ap) artptr = artptr_list-1; else if (!artptr || *artptr != ap) { for (artptr = artptr_list; artptr < limit; artptr++) { if (*artptr == ap) break; } } do { if (++artptr >= limit) break; ap = *artptr; } while ((!rereading && (ap->flags & AF_READ)) || (sel_flag && !(ap->flags & AF_SEL))); if (artptr < limit) { artp = *artptr; art = article_num(artp); } else { artp = Nullart; art = lastart+1; artptr = artptr_list; } return; } /* Use subject- or thread-order when possible */ if (ThreadedGroup || srchahead) { register SUBJECT *sp; bool try_this_group_again = !rereading; if (ap) sp = ap->subj; else for (sp = first_subject; sp && (sp->flags&subj_mask) != subj_mask;) sp = sp->next; if (!sp) goto num_inc; do { if (ap) ap = next_art(ap); else ap = first_art(sp); while (!ap) { if (try_this_group_again) try_this_group_again = FALSE; else { while ((sp = sp->next) != Nullsubj && (sp->flags & subj_mask) != subj_mask) ; if (!sp) break; } ap = first_art(sp); } } while (ap && ((!rereading && (ap->flags & AF_READ)) || (sel_flag && !(ap->flags & AF_SEL)))); if ((artp = ap) != Nullart) art = article_num(ap); else art = lastart+1; return; } /* Otherwise, just increment through the art numbers */ num_inc: if (!ap) { art = firstart-1; ap = article_ptr(art); } do { if (++art > lastart) { ap = Nullart; break; } ap++; } while ((!rereading && (ap->flags & AF_READ)) || (sel_flag && !(ap->flags & AF_SEL)) || (ap->flags & AF_MISSING)); artp = ap;}/* Bump art/artp to the previous article, wrapping from thread to thread.** If sel_flag is TRUE, only stops at selected articles.** If rereading is FALSE, only stops at unread articles.*/voiddec_art(sel_flag, rereading)bool_int sel_flag, rereading;{ register ARTICLE *ap = artp; int subj_mask = (sel_mode == SM_THREAD? (SF_THREAD|SF_VISIT) : SF_VISIT); /* Use the explicit article-order if it exists */ if (artptr_list) { ARTICLE **limit = artptr_list + article_count; if (!ap) artptr = limit; else if (!artptr || *artptr != ap) { for (artptr = artptr_list; artptr < limit; artptr++) { if (*artptr == ap) break; } } do { if (artptr == artptr_list) break; ap = *--artptr; } while ((!rereading && (ap->flags & AF_READ)) || (sel_flag && !(ap->flags & AF_SEL))); artp = *artptr; art = article_num(artp); return; } /* Use subject- or thread-order when possible */ if (ThreadedGroup || srchahead) { register SUBJECT *sp; if (ap) sp = ap->subj; else for (sp = last_subject; sp && (sp->flags&subj_mask) != subj_mask;) sp = sp->prev; if (!sp) goto num_dec; do { if (ap) ap = prev_art(ap); else ap = last_art(sp); while (!ap) { while ((sp = sp->prev) != Nullsubj && (sp->flags & subj_mask) != subj_mask) ; if (!sp) break; ap = last_art(sp); } } while (ap && ((!rereading && (ap->flags & AF_READ)) || (sel_flag && !(ap->flags & AF_SEL)))); if ((artp = ap) != Nullart) art = article_num(ap); else art = absfirst-1; return; } /* Otherwise, just decrement through the art numbers */ num_dec: ap = article_ptr(art); do { if (--art < absfirst) { ap = Nullart; break; } ap--; } while ((!rereading && (ap->flags & AF_READ)) || (sel_flag && !(ap->flags & AF_SEL)) || (ap->flags & AF_MISSING)); artp = ap;}/* Bump the param to the next article in depth-first order.*/ARTICLE *bump_art(ap)register ARTICLE *ap;{ if (ap->child1) return ap->child1; while (!ap->sibling) { if (!(ap = ap->parent)) return Nullart; } return ap->sibling;}/* Bump the param to the next REAL article. Uses subject order in a** non-threaded group; honors the breadth_first flag in a threaded one.*/ARTICLE *next_art(ap)register ARTICLE *ap;{try_again: if (!ThreadedGroup) { ap = ap->subj_next; goto done; } if (breadth_first) { if (ap->sibling) { ap = ap->sibling; goto done; } if (ap->parent) ap = ap->parent->child1; else ap = ap->subj->thread; } do { if (ap->child1) { ap = ap->child1; goto done; } while (!ap->sibling) { if (!(ap = ap->parent)) return Nullart; } ap = ap->sibling; } while (breadth_first);done: if (ap && (ap->flags & AF_MISSING)) goto try_again; return ap;}/* Bump the param to the previous REAL article. Uses subject order in a** non-threaded group.*/ARTICLE *prev_art(ap)register ARTICLE *ap;{ register ARTICLE *initial_ap;try_again: initial_ap = ap; if (!ThreadedGroup) { if ((ap = ap->subj->articles) == initial_ap) ap = Nullart; else while (ap->subj_next != initial_ap) ap = ap->subj_next; goto done; } ap = (ap->parent ? ap->parent->child1 : ap->subj->thread); if (ap == initial_ap) { ap = ap->parent; goto done; } while (ap->sibling != initial_ap) ap = ap->sibling; while (ap->child1) { ap = ap->child1; while (ap->sibling) ap = ap->sibling; }done: if (ap && (ap->flags & AF_MISSING)) goto try_again; return ap;}/* Find the next art/artp with the same subject as this one. Returns** FALSE if no such article exists.*/boolnext_art_with_subj(){ register ARTICLE *ap = artp; register SUBJECT *sp; bool try_this_subj_again = TRUE; if (!ap) return FALSE; sp = ap->subj; do { ap = ap->subj_next; if (!ap) { if (try_this_subj_again) { ap = sp->articles; try_this_subj_again = FALSE; } else { if (!art) art = firstart; return FALSE; } } } while ((ap->flags & (AF_READ|AF_MISSING)) || (selected_only && !(ap->flags & AF_SEL))); artp = ap; art = article_num(ap);#ifdef ARTSEARCH srchahead = -1;#endif return TRUE;}/* Find the previous art/artp with the same subject as this one. Returns** FALSE if no such article exists.*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -