Commit | Line | Data |
---|---|---|
1cd0e254 C |
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 |