BSD 4_4 development
[unix-history] / usr / src / contrib / news / trn3 / art.c
CommitLineData
0dbe5c9b
C
1/* $Id: art.c,v 3.0 1992/02/01 03:09:32 davison Trn $
2 */
3/* This software is Copyright 1991 by Stan Barber.
4 *
5 * Permission is hereby granted to copy, reproduce, redistribute or otherwise
6 * use this software as long as: there is no monetary profit gained
7 * specifically from the use or reproduction of this software, it is not
8 * sold, rented, traded or otherwise marketed, and this copyright notice is
9 * included prominently in any copy made.
10 *
11 * The author make no claims as to the fitness or correctness of this software
12 * for any use whatsoever, and it is provided as is. Any use of this software
13 * is at the user's own risk.
14 */
15
16#include "EXTERN.h"
17#include "common.h"
18#include "trn.h"
19#include "ngstuff.h"
20#include "ngdata.h"
21#include "cache.h"
22#include "bits.h"
23#include "head.h"
24#include "help.h"
25#include "search.h"
26#include "artio.h"
27#include "ng.h"
28#include "final.h"
29#include "artstate.h"
30#include "rcstuff.h"
31#include "term.h"
32#include "sw.h"
33#include "util.h"
34#include "backpage.h"
35#include "intrp.h"
36#include "rthread.h"
37#include "rt-select.h"
38#include "rt-util.h"
39#include "rt-wumpus.h"
40#include "INTERN.h"
41#include "art.h"
42
43/* page_switch() return values */
44
45#define PS_NORM 0
46#define PS_ASK 1
47#define PS_RAISE 2
48#define PS_TOEND 3
49
50bool special = FALSE; /* is next page special length? */
51int slines = 0; /* how long to make page when special */
52ART_LINE highlight = -1; /* next line to be highlighted */
53char *restart = Nullch; /* if nonzero, the place where last */
54 /* line left off on line split */
55char *blinebeg; /* where in buffer current line began */
56ART_POS alinebeg; /* where in file current line began */
57
58#ifdef INNERSEARCH
59ART_POS innersearch = 0; /* artpos of end of line we found */
60 /* for 'g' command */
61ART_LINE isrchline = 0; /* last line to display */
62bool hide_everything = FALSE;
63 /* if set, do not write page now, */
64 /* but refresh when done with page */
65COMPEX gcompex; /* in article search pattern */
66#endif
67
68bool firstpage; /* is this the 1st page of article? */
69
70char art_buf[LBUFLEN]; /* place for article lines */
71
72void
73art_init()
74{
75 ;
76}
77
78#ifdef METAMAIL
79#define VERY_LONG_STRING 200
80int
81display_mime()
82{
83 if (!getenv("NOMETAMAIL")) {
84 int code;
85
86 interp(cmd_buf,(sizeof cmd_buf),getval("MIMESHOW",MIMESHOW));
87 termlib_reset();
88 resetty();
89 code = doshell(SH,cmd_buf);
90 noecho();
91 crmode();
92 termlib_init();
93 return code;
94 }
95 return 1;
96}
97#endif
98
99
100int
101do_article()
102{
103 register char *s;
104 ART_POS artsize; /* size in bytes of article */
105 bool hide_this_line = FALSE; /* hidden header line? */
106 ART_LINE linenum; /* line # on page, 1 origin */
107#ifdef ULSMARTS
108 bool under_lining = FALSE; /* are we underlining a word? */
109#endif
110 register char *bufptr = art_buf; /* pointer to input buffer */
111 register int outpos; /* column position of output */
112 static char prompt_buf[64]; /* place to hold prompt */
113 bool notesfiles = FALSE; /* might there be notesfiles junk? */
114 char oldmode = mode;
115 char *ctime();
116#ifdef METAMAIL
117 bool tried_display_mime = FALSE;
118#endif
119#ifdef INNERSEARCH
120 register int outputok;
121#endif
122
123#ifdef METAMAIL
124 mime_article = FALSE;
125#endif
126
127 if (fstat(fileno(artfp),&filestat)) /* get article file stats */
128 return DA_CLEAN;
129 if ((filestat.st_mode & S_IFMT) != S_IFREG)
130 return DA_NORM;
131 artsize = filestat.st_size; /* from that get article size */
132 sprintf(prompt_buf,
133 "%%sEnd of article %ld (of %ld) -- what next? [%%s]",
134 (long)art,(long)lastart); /* format prompt string */
135 prompt = prompt_buf;
136 int_count = 0; /* interrupt count is 0 */
137 if ((firstpage = (topline < 0)) != 0) {
138 parseheader(art);
139 fseek(artfp,htype[PAST_HEADER].ht_minpos,0);
140 }
141 for (;;) { /* for each page */
142 if (ThreadedGroup && max_tree_lines)
143 init_tree(); /* init tree display */
144 assert(art == openart);
145 if (do_fseek) {
146 parseheader(art); /* make sure header is ours */
147 artpos = vrdary(artline);
148 if (artpos < 0)
149 artpos = -artpos; /* labs(), anyone? */
150 if (firstpage)
151 artpos = (ART_POS)0;
152 if (artpos < htype[PAST_HEADER].ht_minpos) {
153 in_header = SOME_LINE;
154 fseek(artfp,htype[PAST_HEADER].ht_minpos,0);
155 } else
156 fseek(artfp,artpos,0);
157 do_fseek = FALSE;
158 restart = Nullch;
159 }
160 linenum = 1;
161 if (firstpage) {
162 if (firstline) {
163 interp(art_buf, (sizeof art_buf), firstline);
164 linenum += tree_puts(art_buf,linenum+topline,0);
165 artopen(art); /* rewind article in case interp */
166 /* forced a header parse */
167 } else
168 {
169 ART_NUM i;
170 int selected, unseen;
171
172 selected = (curr_artp->flags & AF_SEL);
173 unseen = !was_read(art);
174 sprintf(art_buf,"%s%s #%ld",ngname,moderated,(long)art);
175 if (selected_only) {
176 i = selected_count - (unseen && selected);
177 sprintf(art_buf+strlen(art_buf)," (%ld + %ld more)",
178 (long)i,(long)toread[ng] - selected_count
179 - (!selected && unseen));
180 }
181 else if ((i = (ART_NUM)(toread[ng] - unseen)) != 0
182 || (!ThreadedGroup && dmcount))
183 sprintf(art_buf+strlen(art_buf)," (%ld more)",(long)i);
184 if (!ThreadedGroup && dmcount)
185 sprintf(art_buf+strlen(art_buf)-1," + %ld Marked to return)",
186 (long)dmcount);
187 linenum += tree_puts(art_buf,linenum+topline,0);
188 }
189 start_header(art);
190 forcelast = FALSE; /* we will have our day in court */
191 restart = Nullch;
192 artline = 0; /* start counting lines */
193 artpos = 0;
194 vwtary(artline,artpos); /* remember pos in file */
195 }
196 for (; /* linenum already set */
197 in_header || (
198#ifdef INNERSEARCH
199 innersearch ? innermore() :
200#endif
201 linenum<(firstpage?initlines:(special?slines:LINES)) );
202 linenum++) { /* for each line on page */
203 if (int_count) { /* exit via interrupt? */
204 putchar('\n') FLUSH; /* get to left margin */
205 int_count = 0; /* reset interrupt count */
206 mode = oldmode;
207 special = FALSE;
208 return DA_NORM; /* skip out of loops */
209 }
210 if (restart) { /* did not finish last line? */
211 bufptr = restart; /* then start again here */
212 restart = Nullch; /* and reset the flag */
213 }
214 else if (in_header && headbuf[artpos] != '\0') {
215 bufptr = index(headbuf+artpos,'\n') + 1;
216 bcopy(headbuf+artpos,art_buf,bufptr-headbuf-artpos);
217 art_buf[bufptr-headbuf-artpos] = '\0';
218 bufptr = art_buf;
219 } else {
220 if (fgets(art_buf,LBUFLEN,artfp)==Nullch) {
221 /* if all done */
222 mode = oldmode;
223 special = FALSE;
224 return DA_NORM; /* skip out of loops */
225 }
226 bufptr = art_buf; /* so start at beginning */
227 art_buf[LBUFLEN-1] = '\0';
228 /* make sure string ends */
229 }
230 blinebeg = bufptr; /* remember where we began */
231 alinebeg = artpos; /* both in buffer and file */
232 if (in_header && bufptr == art_buf) {
233 hide_this_line =
234 parseline(art_buf,do_hiding,hide_this_line);
235 if (!in_header) {
236 linenum += finish_tree(linenum+topline);
237 end_header();
238 }
239 } else if (notesfiles && do_hiding &&
240 bufptr == art_buf && *art_buf == '#' &&
241 isupper(art_buf[1]) && art_buf[2] == ':' ) {
242 fgets(art_buf,sizeof(art_buf),artfp);
243 if (index(art_buf,'!') != Nullch)
244 fgets(art_buf,sizeof(art_buf),artfp);
245 htype[PAST_HEADER].ht_minpos = ftell(artfp);
246 /* exclude notesfiles droppings */
247 hide_this_line = TRUE; /* and do not print either */
248 notesfiles = FALSE;
249 }
250#ifdef CUSTOMLINES
251 if (hideline && bufptr == art_buf &&
252 execute(&hide_compex,art_buf) )
253 hide_this_line = TRUE;
254#endif
255 if (in_header && htype[in_header].ht_flags & HT_MAGIC) {
256 if (in_header == NGS_LINE) {
257 if ((s = index(art_buf,'\n')) != Nullch)
258 *s = '\0';
259 hide_this_line = (index(art_buf,',') == Nullch)
260 && strEQ(art_buf+12, ngname);
261 if (s != Nullch)
262 *s = '\n';
263 }
264 else if (in_header == EXPIR_LINE) {
265 if (!(htype[EXPIR_LINE].ht_flags & HT_HIDE))
266 hide_this_line = (strlen(art_buf) < 10);
267 }
268 else if (in_header == FROM_LINE) {
269 if (do_hiding && (s = extract_name(art_buf+6)) != Nullch)
270 strcpy(art_buf+6,s);
271 }
272 else if (in_header == DATE_LINE) {
273 if (do_hiding && curr_artp->date != -1)
274 strftime(art_buf+6, sizeof(art_buf)-6,
275 getval("LOCALTIMEFMT", LOCALTIMEFMT),
276 localtime(&curr_artp->date));
277 }
278#ifdef METAMAIL
279 else if (in_header == CONTENT_LINE) {
280 mime_article = nontext(art_buf+14);
281 }
282#endif
283 }
284 if (in_header == SUBJ_LINE &&
285 htype[SUBJ_LINE].ht_flags & HT_MAGIC) {
286 /* is this the subject? */
287 int length;
288
289 length = strlen(art_buf)-1;
290 artline++;
291 art_buf[length] = '\0'; /* wipe out newline */
292#ifdef NOFIREWORKS
293 no_ulfire();
294#endif
295 notesfiles =
296 (instr(&art_buf[length-10]," - (nf", TRUE) != Nullch);
297 /* tree_puts(, ,1) underlines subject */
298 linenum += tree_puts(art_buf,linenum+topline,1)-1;
299 }
300 else if (hide_this_line && do_hiding) {
301 /* do not print line? */
302 linenum--; /* compensate for linenum++ */
303 if (!in_header)
304 hide_this_line = FALSE;
305 }
306 else if (in_header) {
307 artline++;
308 linenum += tree_puts(art_buf,linenum+topline,0)-1;
309 }
310 else { /* just a normal line */
311#ifdef METAMAIL
312 if (mime_article && !tried_display_mime) {
313 if (display_mime() == 0)
314 return DA_NORM;
315 else
316 tried_display_mime = TRUE;
317 }
318#endif
319 if (highlight==artline) { /* this line to be highlit? */
320 if (marking == STANDOUT) {
321#ifdef NOFIREWORKS
322 if (erase_screen)
323 no_sofire();
324#endif
325 standout();
326 }
327 else {
328#ifdef NOFIREWORKS
329 if (erase_screen)
330 no_ulfire();
331#endif
332 underline();
333 }
334 if (*bufptr == '\n')
335 putchar(' ');
336 }
337#ifdef INNERSEARCH
338 outputok = !hide_everything;
339 /* get it into register, hopefully */
340#endif
341#ifdef CLEAREOL
342#ifdef INNERSEARCH
343 if (outputok)
344#endif
345 maybe_eol();
346#endif /* CLEAREOL */
347#ifdef CUSTOMLINES
348 if (pagestop && bufptr == art_buf &&
349 execute(&page_compex,art_buf) )
350 linenum = 32700;
351#endif
352 for (outpos = 0; outpos < COLS; ) {
353 /* while line has room */
354 if (*(unsigned char *)bufptr >= ' ') { /* normal char? */
355#ifdef ULSMARTS
356 if (*bufptr == '_') {
357 if (bufptr[1] == '\b') {
358 if (!under_lining && highlight!=artline
359#ifdef INNERSEARCH
360 && outputok
361#endif
362 ) {
363 under_lining++;
364 if (UG) {
365 if (bufptr != buf &&
366 bufptr[-1] == ' ') {
367 outpos--;
368 backspace();
369 }
370 }
371 underline();
372 }
373 bufptr += 2;
374 }
375 }
376 else {
377 if (under_lining) {
378 under_lining = 0;
379 un_underline();
380 if (UG) {
381 if (*bufptr == ' ')
382 goto skip_put;
383 outpos++;
384 }
385 }
386 }
387#endif
388#ifdef INNERSEARCH
389 if (outputok)
390#endif
391 {
392#ifdef ROTATION
393 if (rotate && !in_header
394 && isalpha(*bufptr)) {
395 if ((*bufptr & 31) <= 13)
396 putchar(*bufptr+13);
397 else
398 putchar(*bufptr-13);
399 }
400 else
401#endif
402 putchar(*bufptr);
403 }
404 if (*UC && ((highlight==artline && marking == 1)
405#ifdef ULSMARTS
406 || under_lining
407#endif
408 )) {
409 backspace();
410 underchar();
411 }
412 skip_put:
413 bufptr++;
414 outpos++;
415 }
416 else if (*bufptr == '\n' || !*bufptr) {
417 /* newline? */
418#ifdef ULSMARTS
419 if (under_lining) {
420 under_lining = 0;
421 un_underline();
422 }
423#endif
424#ifdef DEBUG
425 if (debug & DEB_INNERSRCH && outpos < COLS - 6) {
426 standout();
427 printf("%4d",artline);
428 un_standout();
429 }
430#endif
431#ifdef INNERSEARCH
432 if (outputok)
433#endif
434 putchar('\n') FLUSH;
435 restart = 0;
436 outpos = 1000; /* signal normal \n */
437 }
438 else if (*bufptr == '\t') { /* tab? */
439 int incpos = 8 - outpos % 8;
440#ifdef INNERSEARCH
441 if (outputok)
442#endif
443 if (GT)
444 putchar(*bufptr);
445 else
446 while (incpos--) putchar(' ');
447 bufptr++;
448 outpos += 8 - outpos % 8;
449 }
450 else if (*bufptr == '\f') { /* form feed? */
451#ifdef INNERSEARCH
452 if (outputok)
453#endif
454 fputs("^L",stdout);
455 if (bufptr == blinebeg && highlight != artline)
456 linenum = 32700;
457 /* how is that for a magic number? */
458 bufptr++;
459 outpos += 2;
460 }
461 else { /* other control char */
462#ifdef INNERSEARCH
463 if (outputok)
464#endif
465 {
466 if (dont_filter_control)
467 putchar(*bufptr);
468 else {
469 putchar('^');
470 if (highlight == artline && *UC && marking == 1) {
471 backspace();
472 underchar();
473 putchar(*bufptr+64);
474 backspace();
475 underchar();
476 }
477 else
478 putchar(*bufptr+64);
479 }
480 }
481 bufptr++;
482 outpos += 2;
483 }
484
485 } /* end of column loop */
486
487 if (outpos < 1000) {/* did line overflow? */
488 restart = bufptr;
489 /* restart here next time */
490 if (!AM || XN) {/* no automatic margins on tty? */
491#ifdef INNERSEARCH /* then move it down ourselves */
492 if (outputok)
493#endif
494 putchar('\n') FLUSH;
495 }
496 if (*bufptr == '\n') /* skip the newline */
497 restart = 0;
498 }
499
500 /* handle normal end of output line formalities */
501
502 if (highlight == artline) {
503 /* were we highlighting line? */
504 if (marking == STANDOUT)
505 un_standout();
506 else
507 un_underline();
508 highlight = -1; /* no more we are */
509 }
510 artline++; /* count the line just printed */
511 if (artline - LINES + 1 > topline)
512 /* did we just scroll top line off? */
513 topline = artline - LINES + 1;
514 /* then recompute top line # */
515 }
516
517 /* determine actual position in file */
518
519 if (restart) /* stranded somewhere in the buffer? */
520 artpos += restart - blinebeg;
521 /* just calculate position */
522 else if (in_header)
523 artpos = index(headbuf+artpos, '\n') - headbuf + 1;
524 else /* no, ftell will do */
525 artpos = ftell(artfp);
526 vwtary(artline,artpos); /* remember pos in file */
527 } /* end of line loop */
528
529#ifdef INNERSEARCH
530 innersearch = 0;
531 if (hide_everything) {
532 hide_everything = FALSE;
533 *buf = Ctl('l');
534 goto fake_command;
535 }
536#endif
537 if (linenum >= 32700)/* did last line have formfeed? */
538 vwtary(artline-1,-vrdary(artline-1));
539 /* remember by negating pos in file */
540
541 special = FALSE; /* end of page, so reset page length */
542 firstpage = FALSE; /* and say it is not 1st time thru */
543
544 /* extra loop bombout */
545
546 if (artpos == artsize) {/* did we just now reach EOF? */
547 mode = oldmode;
548 return DA_NORM; /* avoid --MORE--(100%) */
549 }
550
551/* not done with this article, so pretend we are a pager */
552
553reask_pager:
554 unflush_output(); /* disable any ^O in effect */
555 standout(); /* enter standout mode */
556 printf("--MORE--(%ld%%)",(long)(artpos*100/artsize));
557 un_standout(); /* leave standout mode */
558#ifdef CLEAREOL
559 maybe_eol();
560#endif
561 fflush(stdout);
562/* reinp_pager: /* unused, commented for lint */
563 eat_typeahead();
564#ifdef DEBUG
565 if (debug & DEB_CHECKPOINTING) {
566 printf("(%d %d %d)",checkcount,linenum,artline);
567 fflush(stdout);
568 }
569#endif
570 if (checkcount >= docheckwhen &&
571 linenum == LINES &&
572 (artline > 40 || checkcount >= docheckwhen+10) ) {
573 /* while he is reading a whole page */
574 /* in an article he is interested in */
575 checkcount = 0;
576 checkpoint_rc(); /* update .newsrc */
577 }
578 cache_until_key();
579 mode = 'p';
580 getcmd(buf);
581 if (errno) {
582 if (LINES < 100 && !int_count)
583 *buf = '\f';/* on CONT fake up refresh */
584 else {
585 *buf = 'q'; /* on INTR or paper just quit */
586 }
587 }
588 carriage_return();
589#ifndef CLEAREOL
590 erase_eol(); /* and erase the prompt */
591#else
592 if (erase_screen && can_home_clear)
593 clear_rest();
594 else
595 erase_eol(); /* and erase the prompt */
596#endif /* CLEAREOL */
597 carriage_return(); /* Resets kernel's tab column counter to 0 */
598 fflush(stdout);
599
600 fake_command: /* used by innersearch */
601 output_chase_phrase = TRUE;
602
603 /* parse and process pager command */
604
605 switch (page_switch()) {
606 case PS_ASK: /* reprompt "--MORE--..." */
607 goto reask_pager;
608 case PS_RAISE: /* reparse on article level */
609 mode = oldmode;
610 return DA_RAISE;
611 case PS_TOEND: /* fast pager loop exit */
612 mode = oldmode;
613 return DA_TOEND;
614 case PS_NORM: /* display more article */
615 break;
616 }
617 } /* end of page loop */
618}
619
620/* process pager commands */
621
622int
623page_switch()
624{
625 register char *s;
626
627 switch (*buf) {
628 case 'd':
629 case Ctl('d'): /* half page */
630 special = TRUE;
631 slines = LINES / 2 + 1;
632 if (marking && *blinebeg != '\f'
633#ifdef CUSTOMLINES
634 && (!pagestop || blinebeg != art_buf ||
635 !execute(&page_compex,blinebeg))
636#endif
637 ) {
638 up_line();
639 highlight = --artline;
640 restart = blinebeg;
641 artpos = alinebeg;
642 }
643 return PS_NORM;
644 case '!': /* shell escape */
645 escapade();
646 return PS_ASK;
647#ifdef INNERSEARCH
648 case Ctl('i'):
649 gline = 3;
650 sprintf(cmd_buf,"^[^%c]",*blinebeg);
651 compile(&gcompex,cmd_buf,TRUE,TRUE);
652 goto caseG;
653 case Ctl('g'):
654 gline = 3;
655 compile(&gcompex,"^Subject:",TRUE,TRUE);
656 goto caseG;
657 case 'g': /* in-article search */
658 if (!finish_command(FALSE))/* get rest of command */
659 return PS_ASK;
660 s = buf+1;
661 if (isspace(*s))
662 s++;
663 if ((s = compile(&gcompex,s,TRUE,TRUE)) != Nullch) {
664 /* compile regular expression */
665 printf("\n%s\n",s) FLUSH;
666 return PS_ASK;
667 }
668 carriage_return();
669 erase_eol(); /* erase the prompt */
670 carriage_return(); /* Resets kernel's tab column counter to 0 */
671 /* FALL THROUGH */
672 caseG:
673 case 'G': {
674 /* ART_LINE lines_to_skip = 0; */
675 ART_POS start_where;
676
677 if (gline < 0 || gline > LINES-2)
678 gline = LINES-2;
679#ifdef DEBUG
680 if (debug & DEB_INNERSRCH)
681 printf("Start here? %d >=? %d\n",topline + gline + 1,artline)
682 FLUSH;
683#endif
684 if (*buf == Ctl('i') || topline+gline+1 >= artline)
685 start_where = artpos;
686 /* in case we had a line wrap */
687 else {
688 start_where = vrdary(topline+gline+1);
689 if (start_where < 0)
690 start_where = -start_where;
691 }
692 if (start_where < htype[PAST_HEADER].ht_minpos)
693 start_where = htype[PAST_HEADER].ht_minpos;
694 fseek(artfp,(long)start_where,0);
695 innersearch = 0; /* assume not found */
696 while (fgets(buf, sizeof buf, artfp) != Nullch) {
697 /* lines_to_skip++; NOT USED NOW */
698#ifdef DEBUG
699 if (debug & DEB_INNERSRCH)
700 printf("Test %s",buf) FLUSH;
701#endif
702 if (execute(&gcompex,buf) != Nullch) {
703 innersearch = ftell(artfp);
704 break;
705 }
706 }
707 if (!innersearch) {
708 fseek(artfp,artpos,0);
709 fputs("(Not found)",stdout) FLUSH;
710 return PS_ASK;
711 }
712#ifdef DEBUG
713 if (debug & DEB_INNERSRCH)
714 printf("On page? %ld <=? %ld\n",(long)innersearch,(long)artpos)
715 FLUSH;
716#endif
717 if (innersearch <= artpos) { /* already on page? */
718 if (innersearch < artpos) {
719 artline = topline+1;
720 while (vrdary(artline) < innersearch)
721 artline++;
722 }
723 highlight = artline - 1;
724#ifdef DEBUG
725 if (debug & DEB_INNERSRCH)
726 printf("@ %d\n",highlight) FLUSH;
727#endif
728 topline = highlight - gline;
729 if (topline < -1)
730 topline = -1;
731 *buf = '\f'; /* fake up a refresh */
732 innersearch = 0;
733 return page_switch();
734 }
735 else { /* who knows how many lines it is? */
736 do_fseek = TRUE;
737 hide_everything = TRUE;
738 }
739 return PS_NORM;
740 }
741#else
742 case 'g': case 'G': case Ctl('g'):
743 notincl("g");
744 return PS_ASK;
745#endif
746 case '\n': /* one line */
747 special = TRUE;
748 slines = 2;
749 return PS_NORM;
750#ifdef ROTATION
751 case 'X':
752 rotate = !rotate;
753 /* FALL THROUGH */
754#endif
755 case 'l':
756 case '\f': /* refresh screen */
757#ifdef DEBUG
758 if (debug & DEB_INNERSRCH) {
759 printf("Topline = %d",topline) FLUSH;
760 gets(buf);
761 }
762#endif
763 clear();
764 carriage_return(); /* Resets kernel's tab column counter to 0 */
765 do_fseek = TRUE;
766 artline = topline;
767 if (artline < 0)
768 artline = 0;
769 firstpage = (topline < 0);
770 return PS_NORM;
771 case 'b':
772 case '\b':
773 case Ctl('b'): { /* back up a page */
774 ART_LINE target;
775
776#ifndef CLEAREOL
777 clear();
778#else
779 if (can_home_clear) /* if we can home do it */
780 home_cursor();
781 else
782 clear();
783
784#endif /* CLEAREOL */
785 carriage_return(); /* Resets kernel's tab column counter to 0 */
786 do_fseek = TRUE; /* reposition article file */
787 target = topline - (LINES - 2);
788 artline = topline;
789 if (artline >= 0) do {
790 artline--;
791 } while(artline >= 0 && artline > target && vrdary(artline-1) >= 0);
792 topline = artline;
793 /* remember top line of screen */
794 /* (line # within article file) */
795 if (artline < 0)
796 artline = 0;
797 firstpage = (topline < 0);
798 return PS_NORM;
799 }
800 case 'h': { /* help */
801 int cmd;
802
803 if ((cmd = help_page()) > 0)
804 pushchar(cmd);
805 return PS_ASK;
806 }
807 case 't': /* output thread data */
808 page_line = 1;
809 entire_tree(curr_artp);
810 return PS_ASK;
811 case '_':
812 if (!finish_dblchar())
813 return PS_ASK;
814 switch (buf[1] & 0177) {
815 default:
816 goto leave_pager;
817 }
818 break;
819 case '\177':
820 case '\0': /* treat del,break as 'n' */
821 *buf = 'n';
822 /* FALL THROUGH */
823 case 'k': case 'K':
824 case 'T': case 'J':
825 case 'n': case 'N': case Ctl('n'):
826 case 's': case 'S':
827 case 'e':
828 case 'u':
829 case 'w': case 'W':
830 case '|':
831 mark_as_read(); /* mark article as read */
832 /* FALL THROUGH */
833 case 'U': case ',':
834 case '<': case '>':
835 case '[': case ']':
836 case '{': case '}':
837 case '(': case ')':
838 case '+': case ':':
839 case '#':
840 case '$':
841 case '&':
842 case '-':
843 case '.':
844 case '/':
845 case '1': case '2': case '3': case '4': case '5':
846 case '6': case '7': case '8': case '9':
847 case '=':
848 case '?':
849 case 'c': case 'C':
850#ifdef DEBUG
851 case 'D':
852#endif
853 case 'E':
854 case 'f': case 'F': case Ctl('f'):
855 case 'j':
856 case Ctl('k'):
857 case 'm': case 'M':
858 case 'p': case 'P': case Ctl('p'):
859 case 'Q':
860 case 'r': case 'R': case Ctl('r'):
861 case 'v':
862 case 'Y':
863#ifndef ROTATION
864 case 'x': case 'X':
865#endif
866 case Ctl('x'):
867 case 'z': case 'Z':
868 case '^':
869leave_pager:
870#ifdef ROTATION
871 rotate = FALSE;
872#endif
873 reread = FALSE;
874 do_hiding = TRUE;
875 if (index("nNpP\016\020",*buf) == Nullch &&
876 index("wWsSe:!&|/?123456789.",*buf) != Nullch) {
877 setdfltcmd();
878 standout(); /* enter standout mode */
879 printf(prompt,mailcall,dfltcmd);
880 /* print prompt, whatever it is */
881 un_standout(); /* leave standout mode */
882 putchar(' ');
883 fflush(stdout);
884 }
885 return PS_RAISE; /* and pretend we were at end */
886#ifdef ROTATION
887 case 'x':
888 rotate = TRUE;
889 /* FALL THROUGH */
890#endif
891 case 'y':
892 case Ctl('v'):
893 /* Leaving it undocumented in case */
894 /* I want to steal the key--LAW */
895 case ' ': /* continue current article */
896 if (erase_screen) { /* -e? */
897#ifndef CLEAREOL
898 clear(); /* clear screen */
899#else
900 if (can_home_clear) /* if we can home do it */
901 home_cursor();
902 else
903 clear(); /* else clear screen */
904
905#endif /* CLEAREOL */
906 carriage_return(); /* Resets kernel's tab column counter to 0 */
907 fflush(stdout);
908
909 if (*blinebeg != '\f'
910#ifdef CUSTOMLINES
911 && (!pagestop || blinebeg != art_buf ||
912 !execute(&page_compex,blinebeg))
913#endif
914 ) {
915 restart = blinebeg;
916 artline--; /* restart this line */
917 artpos = alinebeg;
918 if (marking) /* and mark repeated line */
919 highlight = artline;
920 }
921 topline = artline;
922 /* and remember top line of screen */
923 /* (line # within article file) */
924 }
925 else if (marking && *blinebeg != '\f'
926#ifdef CUSTOMLINES
927 && (!pagestop || blinebeg != art_buf ||
928 !execute(&page_compex,blinebeg))
929#endif
930 ) {
931 /* are we marking repeats? */
932 up_line(); /* go up one line */
933 highlight = --artline;/* and get ready to highlight */
934 restart = blinebeg; /* the old line */
935 artpos = alinebeg;
936 }
937 return PS_NORM;
938 case 'q': /* quit this article? */
939 do_hiding = TRUE;
940 return PS_TOEND;
941 default:
942 fputs(hforhelp,stdout) FLUSH;
943 settle_down();
944 return PS_ASK;
945 }
946}
947
948#ifdef INNERSEARCH
949bool
950innermore()
951{
952 if (artpos < innersearch) { /* not even on page yet? */
953#ifdef DEBUG
954 if (debug & DEB_INNERSRCH)
955 printf("Not on page %ld < %ld\n",(long)artpos,(long)innersearch)
956 FLUSH;
957#endif
958 return TRUE;
959 }
960 if (artpos == innersearch) { /* just got onto page? */
961 isrchline = artline; /* remember first line after */
962 highlight = artline - 1;
963#ifdef DEBUG
964 if (debug & DEB_INNERSRCH)
965 printf("There it is %ld = %ld, %d @ %d\n",(long)artpos,
966 (long)innersearch,hide_everything,highlight) FLUSH;
967#endif
968 if (hide_everything) { /* forced refresh? */
969 topline = highlight - gline;
970 if (topline < -1)
971 topline = -1;
972 return FALSE; /* let refresh do it all */
973 }
974 }
975#ifdef DEBUG
976 if (debug & DEB_INNERSRCH)
977 printf("Not far enough? %d <? %d + %d\n",artline,isrchline,gline)
978 FLUSH;
979#endif
980 if (artline < isrchline + gline) {
981 return TRUE;
982 }
983 return FALSE;
984}
985#endif
986
987#ifdef METAMAIL
988int
989nontext(content_type)
990char *content_type;
991{
992 char *t;
993
994 if (content_type[0] == '\n')
995 return 0;
996 while (content_type && isspace(*content_type))
997 content_type++;
998 t = index(content_type, ';');
999 if (!t)
1000 t = index(content_type, '\n');
1001 if (t)
1002 *t-- = '\0';
1003 while (t && *t && t > content_type && isspace(*t))
1004 *t-- = '\0';
1005 if (notplain(content_type))
1006 return 1;
1007 return 0;
1008}
1009
1010int
1011notplain(s)
1012char *s;
1013{
1014 char *t;
1015 if (!s)
1016 return 1;
1017 while (*s && isspace(*s))
1018 s++;
1019 for (t=s; *t; ++t) {
1020 if (isupper(*t))
1021 *t = tolower(*t);
1022 }
1023 while (t > s && isspace(*--t)) ;
1024 if (((t-s) == 3) && !strncmp(s, "text", 4))
1025 return 0;
1026 if (strncmp(s, "text/plain", 10))
1027 return 1;
1028 t = index(s, ';');
1029 while (t) {
1030 t++;
1031 while (*t && isspace(*t)) t++;
1032 if (!strncmp(t, "charset", 7)) {
1033 s = index(t, '=');
1034 if (s) {
1035 s++;
1036 while (*s && isspace(*s)) s++;
1037 if (!strncmp(s, "us-ascii", 8))
1038 return 0;
1039 }
1040 return(1);
1041 }
1042 t = index(t, ';');
1043 }
1044 return 0; /* no charset, was text/plain */
1045}
1046#endif