|
|
1.1 root 1: /* $Header: ng.c,v 4.3.1.3 85/05/16 16:48:09 lwall Exp $
2: *
3: * $Log: ng.c,v $
4: * Revision 4.3.1.3 85/05/16 16:48:09 lwall
5: * Fixed unsubsubscribe.
6: *
7: * Revision 4.3.1.2 85/05/13 09:29:28 lwall
8: * Added CUSTOMLINES option.
9: *
10: * Revision 4.3.1.1 85/05/10 11:36:00 lwall
11: * Branch for patches.
12: *
13: * Revision 4.3 85/05/01 11:43:43 lwall
14: * Baseline for release with 4.3bsd.
15: *
16: */
17:
18: #include "EXTERN.h"
19: #include "common.h"
20: #include "rn.h"
21: #include "term.h"
22: #include "final.h"
23: #include "util.h"
24: #include "artsrch.h"
25: #include "cheat.h"
26: #include "help.h"
27: #include "kfile.h"
28: #include "rcstuff.h"
29: #include "head.h"
30: #include "artstate.h"
31: #include "bits.h"
32: #include "art.h"
33: #include "artio.h"
34: #include "ngstuff.h"
35: #include "intrp.h"
36: #include "respond.h"
37: #include "ngdata.h"
38: #include "backpage.h"
39: #include "rcln.h"
40: #include "last.h"
41: #include "search.h"
42: #include "server.h"
43: #include "INTERN.h"
44: #include "ng.h"
45: #include "artstate.h" /* somebody has to do it */
46:
47: /* art_switch() return values */
48:
49: #define AS_NORM 0
50: #define AS_INP 1
51: #define AS_ASK 2
52: #define AS_CLEAN 3
53:
54: ART_NUM recent_art = 0; /* previous article # for '-' command */
55: ART_NUM curr_art = 0; /* current article # */
56: int exit_code = NG_NORM;
57:
58: void
59: ng_init()
60: {
61:
62: #ifdef KILLFILES
63: open_kfile(KF_GLOBAL);
64: #endif
65: #ifdef CUSTOMLINES
66: init_compex(&hide_compex);
67: init_compex(&page_compex);
68: #endif
69: }
70:
71: /* do newsgroup on line ng with name ngname */
72:
73: /* assumes that we are chdir'ed to SPOOL, and assures that that is
74: * still true upon return, but chdirs to SPOOL/ngname in between
75: *
76: * If you can understand this routine, you understand most of the program.
77: * The basic structure is:
78: * for each desired article
79: * for each desired page
80: * for each line on page
81: * if we need another line from file
82: * get it
83: * if it's a header line
84: * do special things
85: * for each column on page
86: * put out a character
87: * end loop
88: * end loop
89: * end loop
90: * end loop
91: *
92: * (Actually, the pager is in another routine.)
93: *
94: * The chief problem is deciding what is meant by "desired". Most of
95: * the messiness of this routine is due to the fact that people want
96: * to do unstructured things all the time. I have used a few judicious
97: * goto's where I thought it improved readability. The rest of the messiness
98: * arises from trying to be both space and time efficient. Have fun.
99: */
100:
101: int
102: do_newsgroup(start_command)
103: char *start_command; /* command to fake up first */
104: {
105: #ifdef SERVER
106: char ser_line[256];
107: char artname[32];
108: static long our_pid;
109: #endif
110: char oldmode = mode;
111: register long i; /* scratch */
112: int skipstate; /* how many unavailable articles */
113: /* have we skipped already? */
114:
115: char *whatnext = "%sWhat next? [%s]";
116:
117: #ifdef SERVER
118: if (our_pid == 0) /* Agreed, this is gross */
119: our_pid = getpid();
120: #endif
121:
122: #ifdef ARTSEARCH
123: srchahead = (scanon && ((ART_NUM)toread[ng]) >= scanon ? -1 : 0);
124: /* did they say -S? */
125: #endif
126:
127: mode = 'a';
128: recent_art = curr_art = 0;
129: exit_code = NG_NORM;
130: #ifndef SERVER
131: if (eaccess(ngdir,5)) { /* directory read protected? */
132: if (eaccess(ngdir,0)) {
133: #ifdef VERBOSE
134: IF(verbose)
135: printf("\nNewsgroup %s does not have a spool directory!\n",
136: ngname) FLUSH;
137: ELSE
138: #endif
139: #ifdef TERSE
140: printf("\nNo spool for %s!\n",ngname) FLUSH;
141: #endif
142: #ifdef CATCHUP
143: catch_up(ng);
144: #endif
145: toread[ng] = TR_NONE;
146: }
147: else {
148: #ifdef VERBOSE
149: IF(verbose)
150: printf("\nNewsgroup %s is not currently accessible.\n",
151: ngname) FLUSH;
152: ELSE
153: #endif
154: #ifdef TERSE
155: printf("\n%s not readable.\n",ngname) FLUSH;
156: #endif
157: toread[ng] = TR_NONE; /* make this newsgroup invisible */
158: /* (temporarily) */
159: }
160: mode = oldmode;
161: return -1;
162: }
163:
164: /* chdir to newsgroup subdirectory */
165:
166: if (chdir(ngdir)) {
167: printf(nocd,ngdir) FLUSH;
168: mode = oldmode;
169: return -1;
170: }
171: #else /* SERVER */
172: sprintf(ser_line, "GROUP %s", ngname);
173: put_server(ser_line);
174: if (get_server(ser_line, sizeof(ser_line)) < 0) {
175: fprintf(stderr, "rrn: Unexpected close of server socket.\n");
176: finalize(1);
177: }
178: if (*ser_line != CHAR_OK)
179: return (-1);
180: #endif /* SERVER */
181:
182: #ifdef CACHESUBJ
183: subj_list = Null(char **); /* no subject list till needed */
184: #endif
185:
186: /* initialize control bitmap */
187:
188: if (initctl()) {
189: mode = oldmode;
190: return -1;
191: }
192:
193: /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */
194:
195: in_ng = TRUE; /* tell the world we are here */
196: forcelast = TRUE; /* if 0 unread, do not bomb out */
197: art=firstart;
198:
199: /* remember what newsgroup we were in for sake of posterity */
200:
201: writelast();
202:
203: /* see if there are any special searches to do */
204:
205: #ifdef KILLFILES
206: open_kfile(KF_LOCAL);
207: #ifdef VERBOSE
208: IF(verbose)
209: kill_unwanted(firstart,"Looking for articles to kill...\n\n",TRUE);
210: ELSE
211: #endif
212: #ifdef TERSE
213: kill_unwanted(firstart,"Killing...\n\n",TRUE);
214: #endif
215: #endif
216:
217: /* do they want a special top line? */
218:
219: firstline = getval("FIRSTLINE",Nullch);
220:
221: /* custom line suppression, custom page ending */
222:
223: #ifdef CUSTOMLINES
224: if (hideline = getval("HIDELINE",Nullch))
225: compile(&hide_compex,hideline,TRUE,TRUE);
226: if (pagestop = getval("PAGESTOP",Nullch))
227: compile(&page_compex,pagestop,TRUE,TRUE);
228: #endif
229:
230: /* now read each unread article */
231:
232: rc_changed = doing_ng = TRUE; /* enter the twilight zone */
233: skipstate = 0; /* we have not skipped anything (yet) */
234: checkcount = 0; /* do not checkpoint for a while */
235: do_fseek = FALSE; /* start 1st article at top */
236: if (art > lastart)
237: art=firstart; /* init the for loop below */
238: for (; art<=lastart+1; ) { /* for each article */
239:
240: /* do we need to "grow" the newsgroup? */
241:
242: if (art > lastart || forcegrow)
243: grow_ctl();
244: check_first(art); /* make sure firstart is still 1st */
245: if (start_command) { /* fake up an initial command? */
246: prompt = whatnext;
247: strcpy(buf,start_command);
248: free(start_command);
249: start_command = Nullch;
250: art = lastart+1;
251: goto article_level;
252: }
253: if (art>lastart) { /* are we off the end still? */
254: ART_NUM ucount = 0; /* count of unread articles left */
255:
256: for (i=firstart; i<=lastart; i++)
257: if (!(ctl_read(i)))
258: ucount++; /* count the unread articles */
259: #ifdef DEBUGGING
260: /*NOSTRICT*/
261: if (debug && ((ART_NUM)toread[ng]) != ucount)
262: printf("(toread=%ld sb %ld)",(long)toread[ng],(long)ucount)
263: FLUSH;
264: #endif
265: /*NOSTRICT*/
266: toread[ng] = (ART_UNREAD)ucount; /* this is perhaps pointless */
267: art = lastart + 1; /* keep bitmap references sane */
268: if (art != curr_art) {
269: recent_art = curr_art;
270: /* remember last article # (for '-') */
271: curr_art = art; /* remember this article # */
272: }
273: if (erase_screen)
274: clear(); /* clear the screen */
275: else
276: fputs("\n\n",stdout) FLUSH;
277: #ifdef VERBOSE
278: IF(verbose)
279: printf("End of newsgroup %s.",ngname);
280: /* print pseudo-article */
281: ELSE
282: #endif
283: #ifdef TERSE
284: printf("End of %s",ngname);
285: #endif
286: if (ucount) {
287: printf(" (%ld article%s still unread)",
288: (long)ucount,ucount==1?nullstr:"s");
289: }
290: else {
291: if (!forcelast)
292: goto cleanup; /* actually exit newsgroup */
293: }
294: prompt = whatnext;
295: #ifdef ARTSEARCH
296: srchahead = 0; /* no more subject search mode */
297: #endif
298: fputs("\n\n",stdout) FLUSH;
299: skipstate = 0; /* back to none skipped */
300: }
301: else if (!reread && was_read(art)) {
302: /* has this article been read? */
303: art++; /* then skip it */
304: continue;
305: }
306: else if
307: (!reread && !was_read(art)
308: && artopen(art) == Nullfp) { /* never read it, & cannot find it? */
309: if (errno != ENOENT) { /* has it not been deleted? */
310: #ifdef VERBOSE
311: IF(verbose)
312: printf("\n(Article %ld exists but is unreadable.)\n",
313: (long)art) FLUSH;
314: ELSE
315: #endif
316: #ifdef TERSE
317: printf("\n(%ld unreadable.)\n",(long)art) FLUSH;
318: #endif
319: skipstate = 0;
320: sleep(2);
321: }
322: switch(skipstate++) {
323: case 0:
324: clear();
325: #ifdef VERBOSE
326: IF(verbose)
327: fputs("Skipping unavailable article",stdout);
328: ELSE
329: #endif
330: #ifdef TERSE
331: fputs("Skipping",stdout);
332: #endif
333: for (i = just_a_sec/3; i; --i)
334: putchar(PC);
335: fflush(stdout);
336: sleep(1);
337: break;
338: case 1:
339: fputs("..",stdout);
340: fflush(stdout);
341: break;
342: default:
343: putchar('.');
344: fflush(stdout);
345: #ifndef SERVER
346: #define READDIR
347: #ifdef READDIR
348: { /* fast skip patch */
349: ART_NUM newart;
350:
351: if (! (newart=getngmin(".",art)))
352: newart = lastart+1;
353: for (i=art; i<newart; i++)
354: oneless(i);
355: art = newart - 1;
356: }
357: #endif
358: #endif
359: break;
360: }
361: oneless(art); /* mark deleted as read */
362: art++; /* try next article */
363: continue;
364: }
365: else { /* we have a real live article */
366: skipstate = 0; /* back to none skipped */
367: if (art != curr_art) {
368: recent_art = curr_art;
369: /* remember last article # (for '-') */
370: curr_art = art; /* remember this article # */
371: }
372: if (!do_fseek) { /* starting at top of article? */
373: artline = 0; /* start at the beginning */
374: topline = -1; /* and remember top line of screen */
375: /* (line # within article file) */
376: }
377: clear(); /* clear screen */
378: artopen(art); /* make sure article file is open */
379: if (artfp == Nullfp) { /* could not find article? */
380: printf("Article %ld of %s is not available.\n\n",
381: (long)art,ngname) FLUSH;
382: prompt = whatnext;
383: #ifdef ARTSEARCH
384: srchahead = 0;
385: #endif
386: }
387: else { /* found it, so print it */
388: switch (do_article()) {
389: case DA_CLEAN: /* quit newsgroup */
390: goto cleanup;
391: case DA_TOEND: /* do not mark as read */
392: goto reask_article;
393: case DA_RAISE: /* reparse command at end of art */
394: goto article_level;
395: case DA_NORM: /* normal end of article */
396: break;
397: }
398: }
399: mark_as_read(art); /* mark current article as read */
400: reread = FALSE;
401: do_hiding = TRUE;
402: #ifdef ROTATION
403: rotate = FALSE;
404: #endif
405: }
406:
407: /* if these gotos bother you, think of this as a little state machine */
408:
409: reask_article:
410: #ifdef MAILCALL
411: setmail();
412: #endif
413: setdfltcmd();
414: #ifdef CLEAREOL
415: if (erase_screen && can_home_clear) /* PWP was here */
416: clear_rest();
417: #endif CLEAREOL
418: unflush_output(); /* disable any ^O in effect */
419: standout(); /* enter standout mode */
420: printf(prompt,mailcall,dfltcmd);/* print prompt, whatever it is */
421: un_standout(); /* leave standout mode */
422: putchar(' ');
423: fflush(stdout);
424: reinp_article:
425: eat_typeahead();
426: #ifdef PENDING
427: look_ahead(); /* see what we can do in advance */
428: if (!input_pending())
429: collect_subjects(); /* loads subject cache until */
430: /* input is pending */
431: #endif
432: getcmd(buf);
433: if (errno || *buf == '\f') {
434: if (LINES < 100 && !int_count)
435: *buf = '\f'; /* on CONT fake up refresh */
436: else {
437: putchar('\n') FLUSH; /* but only on a crt */
438: goto reask_article;
439: }
440: }
441: article_level:
442:
443: /* parse and process article level command */
444:
445: switch (art_switch()) {
446: case AS_INP: /* multichar command rubbed out */
447: goto reinp_article;
448: case AS_ASK: /* reprompt "End of article..." */
449: goto reask_article;
450: case AS_CLEAN: /* exit newsgroup */
451: goto cleanup;
452: case AS_NORM: /* display article art */
453: break;
454: }
455: } /* end of article selection loop */
456:
457: /* shut down newsgroup */
458:
459: cleanup:
460: #ifdef KILLFILES
461: kill_unwanted(firstart,"\nCleaning up...\n\n",FALSE);
462: /* do cleanup from KILL file, if any */
463: #endif
464: in_ng = FALSE; /* leave newsgroup state */
465: if (artfp != Nullfp) { /* article still open? */
466: fclose(artfp); /* close it */
467: artfp = Nullfp; /* and tell the world */
468: #ifdef SERVER
469: sprintf(artname, "/tmp/rrn%ld.%ld", (long) openart, our_pid);
470: UNLINK(artname);
471: #endif
472: openart = 0;
473: }
474: putchar('\n') FLUSH;
475: yankback(); /* do a Y command */
476: restore_ng(); /* reconstitute .newsrc line */
477: doing_ng = FALSE; /* tell sig_catcher to cool it */
478: free(ctlarea); /* return the control area */
479: #ifdef CACHESUBJ
480: if (subj_list) {
481: for (i=OFFSET(lastart); i>=0; --i)
482: if (subj_list[i])
483: free(subj_list[i]);
484: #ifndef lint
485: free((char*)subj_list);
486: #endif lint
487: }
488: #endif
489: write_rc(); /* and update .newsrc */
490: rc_changed = FALSE; /* tell sig_catcher it is ok */
491: if (chdir(spool)) {
492: printf(nocd,spool) FLUSH;
493: sig_catcher(0);
494: }
495: #ifdef KILLFILES
496: if (localkfp) {
497: fclose(localkfp);
498: localkfp = Nullfp;
499: }
500: #endif
501: mode = oldmode;
502: return exit_code;
503: } /* Whew! */
504:
505: /* decide what to do at the end of an article */
506:
507: int
508: art_switch()
509: {
510: register ART_NUM i;
511:
512: setdef(buf,dfltcmd);
513: #ifdef VERIFY
514: printcmd();
515: #endif
516: switch (*buf) {
517: case 'p': /* find previous unread article */
518: do {
519: if (art <= firstart)
520: break;
521: art--;
522: } while (was_read(art) || artopen(art) == Nullfp);
523: #ifdef ARTSEARCH
524: srchahead = 0;
525: #endif
526: return AS_NORM;
527: case 'P': /* goto previous article */
528: if (art > absfirst)
529: art--;
530: else {
531: #ifdef VERBOSE
532: IF(verbose)
533: fputs("\n\
534: There are no articles prior to this one.\n\
535: ",stdout) FLUSH;
536: ELSE
537: #endif
538: #ifdef TERSE
539: fputs("\nNo previous articles\n",stdout) FLUSH;
540: #endif
541: return AS_ASK;
542: }
543: reread = TRUE;
544: #ifdef ARTSEARCH
545: srchahead = 0;
546: #endif
547: return AS_NORM;
548: case '-':
549: if (recent_art) {
550: art = recent_art;
551: reread = TRUE;
552: #ifdef ARTSEARCH
553: srchahead = -(srchahead != 0);
554: #endif
555: return AS_NORM;
556: }
557: else {
558: exit_code = NG_MINUS;
559: return AS_CLEAN;
560: }
561: case 'n': /* find next unread article? */
562: if (art > lastart) {
563: if (toread[ng])
564: art = firstart;
565: else
566: return AS_CLEAN;
567: }
568: #ifdef ARTSEARCH
569: else if (scanon && srchahead) {
570: *buf = Ctl('n');
571: goto normal_search;
572: }
573: #endif
574: else
575: art++;
576: #ifdef ARTSEARCH
577: srchahead = 0;
578: #endif
579: return AS_NORM;
580: case 'N': /* goto next article */
581: if (art > lastart)
582: art = absfirst;
583: else
584: art++;
585: if (art <= lastart)
586: reread = TRUE;
587: #ifdef ARTSEARCH
588: srchahead = 0;
589: #endif
590: return AS_NORM;
591: case '$':
592: art = lastart+1;
593: forcelast = TRUE;
594: #ifdef ARTSEARCH
595: srchahead = 0;
596: #endif
597: return AS_NORM;
598: case '1': case '2': case '3': /* goto specified article */
599: case '4': case '5': case '6': /* or do something with a range */
600: case '7': case '8': case '9': case '.':
601: forcelast = TRUE;
602: switch (numnum()) {
603: case NN_INP:
604: return AS_INP;
605: case NN_ASK:
606: return AS_ASK;
607: case NN_REREAD:
608: reread = TRUE;
609: #ifdef ARTSEARCH
610: if (srchahead)
611: srchahead = -1;
612: #endif
613: break;
614: case NN_NORM:
615: if (was_read(art)) {
616: art = firstart;
617: pad(just_a_sec/3);
618: }
619: else
620: return AS_ASK;
621: break;
622: }
623: return AS_NORM;
624: case Ctl('k'):
625: edit_kfile();
626: return AS_ASK;
627: case 'K':
628: case 'k':
629: case Ctl('n'): case Ctl('p'):
630: case '/': case '?':
631: #ifdef ARTSEARCH
632: normal_search:
633: { /* search for article by pattern */
634: char cmd = *buf;
635:
636: reread = TRUE; /* assume this */
637: switch (art_search(buf, (sizeof buf), TRUE)) {
638: case SRCH_ERROR:
639: return AS_ASK;
640: case SRCH_ABORT:
641: return AS_INP;
642: case SRCH_INTR:
643: #ifdef VERBOSE
644: IF(verbose)
645: printf("\n(Interrupted at article %ld)\n",(long)art) FLUSH;
646: ELSE
647: #endif
648: #ifdef TERSE
649: printf("\n(Intr at %ld)\n",(long)art) FLUSH;
650: #endif
651: art = curr_art;
652: /* restore to current article */
653: return AS_ASK;
654: case SRCH_DONE:
655: fputs("done\n",stdout) FLUSH;
656: pad(just_a_sec/3); /* 1/3 second */
657: if (srchahead)
658: art = firstart;
659: else
660: art = curr_art;
661: reread = FALSE;
662: return AS_NORM;
663: case SRCH_SUBJDONE:
664: #ifdef UNDEF
665: fputs("\n\n\n\nSubject not found.\n",stdout) FLUSH;
666: pad(just_a_sec/3); /* 1/3 second */
667: #endif
668: art = firstart;
669: reread = FALSE;
670: return AS_NORM;
671: case SRCH_NOTFOUND:
672: fputs("\n\n\n\nNot found.\n",stdout) FLUSH;
673: art = curr_art; /* restore to current article */
674: return AS_ASK;
675: case SRCH_FOUND:
676: if (cmd == Ctl('n') || cmd == Ctl('p'))
677: oldsubject = TRUE;
678: break;
679: }
680: return AS_NORM;
681: }
682: #else
683: buf[1] = '\0';
684: notincl(buf);
685: return AS_ASK;
686: #endif
687: case 'u': /* unsubscribe from this newsgroup? */
688: rcchar[ng] = NEGCHAR;
689: return AS_CLEAN;
690: case 'M':
691: #ifdef DELAYMARK
692: if (art <= lastart) {
693: delay_unmark(art);
694: printf("\nArticle %ld will return.\n",(long)art) FLUSH;
695: }
696: #else
697: notincl("M");
698: #endif
699: return AS_ASK;
700: case 'm':
701: if (art <= lastart) {
702: unmark_as_read(art);
703: printf("\nArticle %ld marked as still unread.\n",(long)art) FLUSH;
704: }
705: return AS_ASK;
706: case 'c': /* catch up */
707: reask_catchup:
708: #ifdef VERBOSE
709: IF(verbose)
710: in_char("\nDo you really want to mark everything as read? [yn] ");
711: ELSE
712: #endif
713: #ifdef TERSE
714: in_char("\nReally? [ynh] ");
715: #endif
716: putchar('\n') FLUSH;
717: setdef(buf,"y");
718: #ifdef VERIFY
719: printcmd();
720: #endif
721: if (*buf == 'h') {
722: #ifdef VERBOSE
723: IF(verbose)
724: fputs("\
725: Type y or SP to mark all articles as read.\n\
726: Type n to leave articles marked as they are.\n\
727: Type u to mark everything read and unsubscribe.\n\
728: ",stdout) FLUSH;
729: ELSE
730: #endif
731: #ifdef TERSE
732: fputs("\
733: y or SP to mark all read.\n\
734: n to forget it.\n\
735: u to mark all and unsubscribe.\n\
736: ",stdout) FLUSH;
737: #endif
738: goto reask_catchup;
739: }
740: else if (*buf == 'n' || *buf == 'q') {
741: return AS_ASK;
742: }
743: else if (*buf != 'y' && *buf != 'u') {
744: fputs(hforhelp,stdout) FLUSH;
745: settle_down();
746: goto reask_catchup;
747: }
748: for (i = firstart; i <= lastart; i++) {
749: ctl_set(i); /* mark as read */
750: }
751: #ifdef DELAYMARK
752: if (dmfp)
753: yankback();
754: #endif
755: if (*buf == 'u') {
756: rcchar[ng] = NEGCHAR;
757: return AS_CLEAN;
758: }
759: art = lastart+1;
760: forcelast = FALSE;
761: return AS_NORM;
762: case 'Q':
763: exit_code = NG_ASK;
764: /* FALL THROUGH */
765: case 'q': /* go back up to newsgroup level? */
766: return AS_CLEAN;
767: case 'j':
768: putchar('\n') FLUSH;
769: if (art <= lastart)
770: mark_as_read(art);
771: return AS_ASK;
772: case 'h': { /* help? */
773: int cmd;
774:
775: if ((cmd = help_art()) > 0)
776: pushchar(cmd);
777: return AS_ASK;
778: }
779: case '&':
780: if (switcheroo()) /* get rest of command */
781: return AS_INP; /* if rubbed out, try something else */
782: return AS_ASK;
783: case '#':
784: #ifdef VERBOSE
785: IF(verbose)
786: printf("\nThe last article is %ld.\n",(long)lastart) FLUSH;
787: ELSE
788: #endif
789: #ifdef TERSE
790: printf("\n%ld\n",(long)lastart) FLUSH;
791: #endif
792: return AS_ASK;
793: case '=': {
794: char tmpbuf[256];
795: ART_NUM oldart = art;
796: int cmd;
797: char *subjline = getval("SUBJLINE",Nullch);
798: #ifndef CACHESUBJ
799: char *s;
800: #endif
801:
802: page_init();
803: #ifdef CACHESUBJ
804: if (!subj_list)
805: fetchsubj(art,TRUE,FALSE);
806: #endif
807: for (i=firstart; i<=lastart && !int_count; i++) {
808: #ifdef CACHESUBJ
809: if (!was_read(i) &&
810: (subj_list[OFFSET(i)] != Nullch || fetchsubj(i,FALSE,FALSE)) &&
811: *subj_list[OFFSET(i)] ) {
812: sprintf(tmpbuf,"%5ld ", i);
813: if (subjline) {
814: art = i;
815: interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
816: }
817: else
818: safecpy(tmpbuf + 6, subj_list[OFFSET(i)],
819: (sizeof tmpbuf) - 6);
820: if (cmd = print_lines(tmpbuf,NOMARKING)) {
821: if (cmd > 0)
822: pushchar(cmd);
823: break;
824: }
825: }
826: #else
827: if (!was_read(i) && (s = fetchsubj(i,FALSE,FALSE)) && *s) {
828: sprintf(tmpbuf,"%5ld ", i);
829: if (subjline) { /* probably fetches it again! */
830: art = i;
831: interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
832: }
833: else
834: safecpy(tmpbuf + 6, s, (sizeof tmpbuf) - 6);
835: if (cmd = print_lines(tmpbuf,NOMARKING)) {
836: if (cmd > 0)
837: pushchar(cmd);
838: break;
839: }
840: }
841: #endif
842: }
843: int_count = 0;
844: art = oldart;
845: return AS_ASK;
846: }
847: case '^':
848: art = firstart;
849: #ifdef ARTSEARCH
850: srchahead = 0;
851: #endif
852: return AS_NORM;
853: #if defined(CACHESUBJ) && defined(DEBUGGING)
854: case 'D':
855: printf("\nFirst article: %ld\n",(long)firstart) FLUSH;
856: if (!subj_list)
857: fetchsubj(art,TRUE,FALSE);
858: if (subj_list != Null(char **)) {
859: for (i=1; i<=lastart && !int_count; i++) {
860: if (subj_list[OFFSET(i)])
861: printf("%5ld %c %s\n",
862: i, (was_read(i)?'y':'n'), subj_list[OFFSET(i)]) FLUSH;
863: }
864: }
865: int_count = 0;
866: return AS_ASK;
867: #endif
868: case 'v':
869: if (art <= lastart) {
870: reread = TRUE;
871: do_hiding = FALSE;
872: }
873: return AS_NORM;
874: #ifdef ROTATION
875: case Ctl('x'):
876: #endif
877: case Ctl('r'):
878: #ifdef ROTATION
879: rotate = (*buf==Ctl('x'));
880: #endif
881: if (art <= lastart)
882: reread = TRUE;
883: return AS_NORM;
884: #ifdef ROTATION
885: case 'X':
886: rotate = !rotate;
887: /* FALL THROUGH */
888: #else
889: case Ctl('x'):
890: case 'x':
891: case 'X':
892: notincl("x");
893: return AS_ASK;
894: #endif
895: case 'l': case Ctl('l'): /* refresh screen */
896: if (art <= lastart) {
897: reread = TRUE;
898: clear();
899: do_fseek = TRUE;
900: artline = topline;
901: if (artline < 0)
902: artline = 0;
903: }
904: return AS_NORM;
905: case 'b': case Ctl('b'): /* back up a page */
906: if (art <= lastart) {
907: ART_LINE target;
908:
909: reread = TRUE;
910: clear();
911: do_fseek = TRUE;
912: target = topline - (LINES - 2);
913: artline = topline;
914: do {
915: artline--;
916: } while (artline >= 0 && artline > target &&
917: vrdary(artline-1) >= 0);
918: topline = artline;
919: if (artline < 0)
920: artline = 0;
921: }
922: return AS_NORM;
923: case '!': /* shell escape */
924: if (escapade())
925: return AS_INP;
926: return AS_ASK;
927: case 'C': {
928: cancel_article();
929: return AS_ASK;
930: }
931: case 'R':
932: case 'r': { /* reply? */
933: reply();
934: return AS_ASK;
935: }
936: case 'F':
937: case 'f': { /* followup command */
938: followup();
939: forcegrow = TRUE; /* recalculate lastart */
940: return AS_ASK;
941: }
942: case '|':
943: case 'w': case 'W':
944: case 's': case 'S': /* save command */
945: if (save_article() == SAVE_ABORT)
946: return AS_INP;
947: return AS_ASK;
948: #ifdef DELAYMARK
949: case 'Y': /* yank back M articles */
950: yankback();
951: art = firstart; /* from the beginning */
952: return AS_NORM; /* pretend nothing happened */
953: #endif
954: #ifdef STRICTCR
955: case '\n':
956: fputs(badcr,stdout) FLUSH;
957: return AS_ASK;
958: #endif
959: default:
960: printf("\n%s",hforhelp) FLUSH;
961: settle_down();
962: return AS_ASK;
963: }
964: }
965:
966: #ifdef MAILCALL
967: /* see if there is any mail */
968:
969: void
970: setmail()
971: {
972: if (! (mailcount++)) {
973: char *mailfile = filexp(getval("MAILFILE",MAILFILE));
974:
975: if (stat(mailfile,&filestat) < 0 || !filestat.st_size
976: || filestat.st_atime > filestat.st_mtime)
977: mailcall = nullstr;
978: else
979: mailcall = "(Mail) ";
980: }
981: mailcount %= 10; /* check every 10 articles */
982: }
983: #endif
984:
985: void
986: setdfltcmd()
987: {
988: if (toread[ng]) {
989: #ifdef ARTSEARCH
990: if (srchahead)
991: dfltcmd = "^Nnpq";
992: else
993: #endif
994: dfltcmd = "npq";
995: }
996: else {
997: if (art > lastart)
998: dfltcmd = "qnp";
999: else
1000: dfltcmd = "npq";
1001: }
1002: }
1003:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.