home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / trn / part08 / art.c next >
Encoding:
C/C++ Source or Header  |  1991-12-02  |  24.9 KB  |  1,026 lines

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