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