Commit | Line | Data |
---|---|---|
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 | ||
50 | bool special = FALSE; /* is next page special length? */ | |
51 | int slines = 0; /* how long to make page when special */ | |
52 | ART_LINE highlight = -1; /* next line to be highlighted */ | |
53 | char *restart = Nullch; /* if nonzero, the place where last */ | |
54 | /* line left off on line split */ | |
55 | char *blinebeg; /* where in buffer current line began */ | |
56 | ART_POS alinebeg; /* where in file current line began */ | |
57 | ||
58 | #ifdef INNERSEARCH | |
59 | ART_POS innersearch = 0; /* artpos of end of line we found */ | |
60 | /* for 'g' command */ | |
61 | ART_LINE isrchline = 0; /* last line to display */ | |
62 | bool hide_everything = FALSE; | |
63 | /* if set, do not write page now, */ | |
64 | /* but refresh when done with page */ | |
65 | COMPEX gcompex; /* in article search pattern */ | |
66 | #endif | |
67 | ||
68 | bool firstpage; /* is this the 1st page of article? */ | |
69 | ||
70 | char art_buf[LBUFLEN]; /* place for article lines */ | |
71 | ||
72 | void | |
73 | art_init() | |
74 | { | |
75 | ; | |
76 | } | |
77 | ||
78 | #ifdef METAMAIL | |
79 | #define VERY_LONG_STRING 200 | |
80 | int | |
81 | display_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 | ||
100 | int | |
101 | do_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 | ||
553 | reask_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 | ||
622 | int | |
623 | page_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 '^': | |
869 | leave_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 | |
949 | bool | |
950 | innermore() | |
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 | |
988 | int | |
989 | nontext(content_type) | |
990 | char *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 | ||
1010 | int | |
1011 | notplain(s) | |
1012 | char *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 |