home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / trn_12.zip / src / art.c < prev    next >
C/C++ Source or Header  |  1993-12-04  |  28KB  |  1,068 lines

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