home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume23 / trn / part04 / art.c next >
Encoding:
C/C++ Source or Header  |  1991-08-22  |  25.6 KB  |  1,052 lines

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