📄 ng.c
字号:
/* $Id: ng.c,v 3.0 1992/02/01 03:09:32 davison Trn $ *//* This software is Copyright 1991 by Stan Barber. * * Permission is hereby granted to copy, reproduce, redistribute or otherwise * use this software as long as: there is no monetary profit gained * specifically from the use or reproduction of this software, it is not * sold, rented, traded or otherwise marketed, and this copyright notice is * included prominently in any copy made. * * The author make no claims as to the fitness or correctness of this software * for any use whatsoever, and it is provided as is. Any use of this software * is at the user's own risk. */#include "EXTERN.h"#include "common.h"#include "trn.h"#include "term.h"#include "final.h"#include "util.h"#include "cache.h"#include "bits.h"#include "artsrch.h"#include "help.h"#include "kfile.h"#include "rcstuff.h"#include "head.h"#include "art.h"#include "artio.h"#include "ngstuff.h"#include "intrp.h"#include "respond.h"#include "ngdata.h"#include "backpage.h"#include "rcln.h"#include "last.h"#include "search.h"#include "nntp.h"#include "rthread.h"#include "rt-select.h"#include "rt-wumpus.h"#include "decode.h"#include "INTERN.h"#include "ng.h"#include "artstate.h" /* somebody has to do it *//* art_switch() return values */#define AS_NORM 0#define AS_INP 1#define AS_ASK 2#define AS_CLEAN 3int exit_code = NG_NORM;voidng_init(){#ifdef KILLFILES open_kfile(KF_GLOBAL);#endif#ifdef CUSTOMLINES init_compex(&hide_compex); init_compex(&page_compex);#endif}/* do newsgroup on line ng with name ngname *//* assumes that we are chdir'ed to NEWSSPOOL, and assures that that is * still true upon return, but chdirs to NEWSSPOOL/ngname in between * * If you can understand this routine, you understand most of the program. * The basic structure is: * for each desired article * for each desired page * for each line on page * if we need another line from file * get it * if it's a header line * do special things * for each column on page * put out a character * end loop * end loop * end loop * end loop * * (Actually, the pager is in another routine.) * * The chief problem is deciding what is meant by "desired". Most of * the messiness of this routine is due to the fact that people want * to do unstructured things all the time. I have used a few judicious * goto's where I thought it improved readability. The rest of the messiness * arises from trying to be both space and time efficient. Have fun. */intdo_newsgroup(start_command)char *start_command; /* command to fake up first */{ char oldmode = mode; char *whatnext = "%sWhat next? [%s]";#ifdef ARTSEARCH srchahead = (scanon && !ThreadedGroup /* did they say -S? */ && ((ART_NUM)toread[ng]) >= scanon ? -1 : 0);#endif exit_code = NG_NORM; save_ids = FALSE; killfirst = 0; if (extractdest) { free(extractdest); extractdest = Nullch; } if (extractprog) { free(extractprog); extractprog = Nullch; } /* initialize the newsgroup data structures */ if (!access_ng()) return -1; /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */ in_ng = TRUE; /* tell the world we are here */ forcelast = TRUE; /* if 0 unread, do not bomb out */ recent_artp = curr_artp = Nullart; recent_art = curr_art = lastart+1; prompt = whatnext; /* remember what newsgroup we were in for sake of posterity */ writelast(); /* see if there are any special searches to do */ has_normal_kills = FALSE;#ifdef KILLFILES open_kfile(KF_LOCAL);# ifdef VERBOSE IF(verbose) kill_unwanted(firstart,"Processing memorized commands...\n\n",TRUE); ELSE# endif# ifdef TERSE kill_unwanted(firstart,"Auto-processing...\n\n",TRUE);# endif#endif if (!selected_count) selected_only = FALSE; top_article(); /* do they want a special top line? */ firstline = getval("FIRSTLINE",Nullch); /* custom line suppression, custom page ending */#ifdef CUSTOMLINES if (hideline = getval("HIDELINE",Nullch)) compile(&hide_compex,hideline,TRUE,TRUE); if (pagestop = getval("PAGESTOP",Nullch)) compile(&page_compex,pagestop,TRUE,TRUE);#endif /* now read each unread article */ rc_changed = doing_ng = TRUE; /* enter the twilight zone */ checkcount = 0; /* do not checkpoint for a while */ do_fseek = FALSE; /* start 1st article at top */ for (; art<=lastart+1; ) { /* for each article */ mode = 'a'; /* do we need to "grow" the newsgroup? */ if (art > lastart || forcegrow) { ART_NUM oldlast = lastart;#ifdef USE_NNTP ART_NUM newlast = lastart; while (nntp_stat(newlast+1)) newlast++; if (newlast > oldlast) { ngmax[ng] = newlast; grow_ng(newlast); }#else grow_ng(getngsize(ng));#endif if (forcelast && art > oldlast) art = lastart+1; } find_article(art); /* sets artp */ if (start_command) { /* do we have an initial command? */ pushstring(start_command, 0); free(start_command); start_command = Nullch; art = curr_art = lastart+1; artp = curr_artp = Nullart; if (input_pending()) goto reinp_article; } if (art>lastart) { /* are we off the end still? */ ARTICLE *ap; ART_NUM i; art = lastart + 1; /* keep pointer references sane */ if (!forcelast && toread[ng] && selected_only && !selected_count) { art = curr_art; artp = curr_artp; strcpy(buf, "+"); goto article_level; } count_subjects(CS_NORM); for (i=last_cached+1, ap=article_ptr(i); i<=lastart; i++, ap++) if (!(ap->flags & AF_READ)) article_count++; toread[ng] = (ART_UNREAD)article_count; if (artp != curr_artp) { recent_art = curr_art; /* remember last article # (for '-') */ curr_art = art; /* set current article # */ recent_artp = curr_artp; curr_artp = artp; } if (erase_screen) clear(); /* clear the screen */ else fputs("\n\n",stdout) FLUSH;#ifdef VERBOSE IF(verbose) printf("End of newsgroup %s.",ngname); /* print pseudo-article */ ELSE#endif#ifdef TERSE printf("End of %s",ngname);#endif if (article_count) { if (selected_only) printf(" (%ld + %ld articles still unread)", (long)selected_count, (long)article_count-selected_count); else printf(" (%ld article%s still unread)", (long)article_count,article_count==1?nullstr:"s"); } else if (!forcelast) goto cleanup; /* actually exit newsgroup */ mode = 'e'; prompt = whatnext;#ifdef ARTSEARCH srchahead = 0; /* no more subject search mode */#endif fputs("\n\n",stdout) FLUSH; } else if (!reread && (was_read(art) || (artp->flags & AF_MISSING) || (selected_only && !(artp->flags & AF_SEL)))) { /* has this article been read? */ inc_art(selected_only,FALSE);/* then skip it */ continue; } else if (!reread && !parseheader(art)) { oneless(artp); /* mark deleted as read */ ng_skip(); } else { /* we have a real live article */ if (artp != curr_artp) { recent_art = curr_art; /* remember last article # (for '-') */ curr_art = art; /* set current article # */ recent_artp = curr_artp; curr_artp = artp; } if (!do_fseek) { /* starting at top of article? */ artline = 0; /* start at the beginning */ topline = -1; /* and remember top line of screen */ /* (line # within article file) */ } clear(); /* clear screen */ if (!artopen(art)) { /* make sure article is found & open */ char tmpbuf[256]; /* see if we have tree data for this article anyway */ init_tree(); sprintf(tmpbuf,"%s: article is not available.",ngname); if (artp && !(artp->flags & AF_CACHED)) { if (absfirst < first_cached || last_cached < lastart || !cached_all_in_range) sprintf(tmpbuf,"%s: article may show up in a moment.", ngname); } tree_puts(tmpbuf,0,0); vwtary((ART_LINE)0,(ART_POS)0); finish_tree(1); prompt = whatnext;#ifdef ARTSEARCH srchahead = 0;#endif } else { /* found it, so print it */ switch (do_article()) { case DA_CLEAN: /* quit newsgroup */ goto cleanup; case DA_TOEND: /* do not mark as read */ goto reask_article; case DA_RAISE: /* reparse command at end of art */ goto article_level; case DA_NORM: /* normal end of article */ break; } } if (art >= absfirst) /* don't mark non-existant articles */ mark_as_read(); /* mark current article as read */ do_hiding = TRUE;#ifdef ROTATION rotate = FALSE;#endif }/* if these gotos bother you, think of this as a little state machine */reask_article:#ifdef MAILCALL setmail(FALSE);#endif setdfltcmd();#ifdef CLEAREOL if (erase_screen && can_home_clear) clear_rest();#endif /* CLEAREOL */ unflush_output(); /* disable any ^O in effect */ standout(); /* enter standout mode */ printf(prompt,mailcall,dfltcmd);/* print prompt, whatever it is */ un_standout(); /* leave standout mode */ putchar(' '); fflush(stdout);reinp_article: reread = FALSE; forcelast = FALSE; eat_typeahead();#ifdef PENDING look_ahead(); /* see what we can do in advance */ cache_until_key();#endif art = curr_art; artp = curr_artp; getcmd(buf); if (errno || *buf == '\f') { if (LINES < 100 && !int_count) *buf = '\f'; /* on CONT fake up refresh */ else { putchar('\n') FLUSH; /* but only on a crt */ goto reask_article; } }article_level: output_chase_phrase = TRUE; /* parse and process article level command */ switch (art_switch()) { case AS_INP: /* multichar command rubbed out */ goto reinp_article; case AS_ASK: /* reprompt "End of article..." */ goto reask_article; case AS_CLEAN: /* exit newsgroup */ goto cleanup; case AS_NORM: /* display article art */ break; } } /* end of article selection loop */ /* shut down newsgroup */cleanup: decode_end();#ifdef KILLFILES kill_unwanted(firstart,"\nCleaning up...\n\n",FALSE); /* do cleanup from KILL file, if any */#endif in_ng = FALSE; /* leave newsgroup state */ if (artfp != Nullfp) { /* article still open? */ fclose(artfp); /* close it */ artfp = Nullfp; /* and tell the world */ openart = 0; } putchar('\n') FLUSH; deselect_all(); yankback(); /* do a Y command */ bits_to_rc(); /* reconstitute .newsrc line */ doing_ng = FALSE; /* tell sig_catcher to cool it */ write_rc(); /* and update .newsrc */ rc_changed = FALSE; /* tell sig_catcher it is ok */ if (chdir(spool)) { printf(nocd,spool) FLUSH; sig_catcher(0); }#ifdef KILLFILES if (localkfp) { fclose(localkfp); localkfp = Nullfp; }#endif mode = oldmode; return exit_code;} /* Whew! *//* decide what to do at the end of an article */intart_switch(){ register ART_NUM i; setdef(buf,dfltcmd);#ifdef VERIFY printcmd();#endif switch (*buf) { case '<': /* goto previous subject/thread */ prev_subject(); return AS_NORM; case '>': /* goto next subject/thread */ next_subject(); return AS_NORM; case 'U': { /* unread some articles */ char *u_prompt, *u_help_thread; dfltcmd = "+"; if (!artp) { u_help_thread = nullstr;#ifdef VERBOSE IF(verbose) u_prompt = "\nSet unread: +select or all? [+an] "; ELSE#endif#ifdef TERSE u_prompt = "\nSet unread? [+an] ";#endif } else {#ifdef VERBOSE IF(verbose) { u_prompt = "\n\Set unread: +select, thread, subthread, or all? [+tsan] "; u_help_thread = "\Type t or SP to mark this thread's articles as unread.\n\Type s to mark the current article and its descendants as unread.\n"; } ELSE#endif#ifdef TERSE { u_prompt = "\nSet unread? [+tsan] "; u_help_thread = "\t or SP to mark thread unread.\n\s to mark subthread unread.\n"; }#endif } reask_unread: in_char(u_prompt,'u'); setdef(buf,dfltcmd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -