borman@stolaf.UUCP (06/28/83)
I've had many requests for the mods to build a pager into readnews, so here it is. (Note that in pager.c there are ifdefs for MOD_NTTY. These are for our local ttydriver, which has an ioctl for resetting ^O. This allows people to ^O an article, and wonder of wonders, it gets reset just in time to print the next header... very handy. If you have such an ioctl on your system, just change the ioctl's as needed and define MOD_NTTY.(there are many other places that this can be put in, if you'd like a list of all the places, drop me a line)) These are the diffs to implement the built-in pager into readnews. The files modified are digest.c, readr.c and rfuncs.c. You also have to change PAGE, the default pager listed in defs.h, to "My Own". (If you don't like that, pick something unique and change all the appropriate references to it) Besides implementing the pager, this also makes the 'w' and 's' different, in that 's' puts on the header when saving the article, and 'w' doesn't. The main thrust of writing this pager has been to keep anything from scrolling off the screen before you get a chance to read it. It does an awfully good job at it. It knows if a new newsgroup is following, and allows for the longer header. It looks at line lengths for long lines that would cause the line count to be incorrect. The biggest kludge about this is how it is implemented with the 'D' option for decrypting things. Things to note: The pager gives you the options of using +'s and -'s to look at various pages of the article, BUT... you can only skip around on pages that you have already seen. (e.g, you can's skip the first 5 pages by giving the command +++++, but if you've read the first 5 pages, you can use ---- to skip back 4 pages, and then +++ to skip forward 3 pages, etc.) This could probably be changed, but it would involve looking at the whole article before presenting it, which it doesn't do right now. You can probably disable the ':' "feature" if you implement this pager. It should be fairly easy to install, just make the following changes and add pager.o to the ROBJECTS line in the makefile. If you have any questions, comments or improvements, I'd be glad to see them. -Dave Borman, St. Olaf College {ihnp4, harpo}!stolaf!borman *** ../vanilla/src/digest.c Wed May 25 12:58:25 1983 --- digest.c Fri Jun 3 16:38:37 1983 *************** *** 324,329 FILE *pfp, *popen(); if (art && arts[art].a_blen > 23-arts[art+1].a_hlen && *PAGER) { if (!index(PAGER, FMETA)) { if ((pfp = popen(PAGER, "w"))==NULL) (void) dprinta(art, ifp, ofp); --- 327,338 ----- FILE *pfp, *popen(); if (art && arts[art].a_blen > 23-arts[art+1].a_hlen && *PAGER) { + #ifdef MOD_PAGE + if (strncmp(PAGER, "My Own") == 0) { + fseek(ifp, arts[art].a_bod, 0); + pprint(ifp, ofp, NULL, arts[art+1].a_hdr, art); + } else + #endif MOD_PAGE if (!index(PAGER, FMETA)) { if ((pfp = popen(PAGER, "w"))==NULL) (void) dprinta(art, ifp, ofp); --- readr.c Mon Jun 27 19:30:22 1983 *************** *** 204,209 if (!bptr[-1] && rfq) return; readmode = NEXT; showtail(fp); clear(bit); saveart; --- 210,219 ----- if (!bptr[-1] && rfq) return; readmode = NEXT; + #ifdef MOD_PAGE + if (showtail(fp)) + return; + #else showtail(fp); #endif MOD_PAGE clear(bit); *************** *** 205,210 return; readmode = NEXT; showtail(fp); clear(bit); saveart; nextbit(); --- 215,221 ----- return; #else showtail(fp); + #endif MOD_PAGE clear(bit); saveart; nextbit(); *************** *** 273,278 case 'w': { char *grn = groupdir; tfilename = filename; if (*bptr == '-') { bptr++; --- 293,301 ----- case 'w': { char *grn = groupdir; + #ifdef MOD_PAGE + i = bptr[-1] == 's'; + #endif MOD_PAGE tfilename = filename; if (*bptr == '-') { bptr++; *************** *** 306,311 else strcat(bptr, "Articles"); } fwait(fsubr(save, tfilename, bptr)); } break; --- 329,337 ----- else strcat(bptr, "Articles"); } + #ifdef MOD_PAGE + rsave(tfilename, bptr, i); + #else fwait(fsubr(save, tfilename, bptr)); #endif MOD_PAGE } *************** *** 307,312 strcat(bptr, "Articles"); } fwait(fsubr(save, tfilename, bptr)); } break; --- 333,339 ----- rsave(tfilename, bptr, i); #else fwait(fsubr(save, tfilename, bptr)); + #endif MOD_PAGE } break; *************** *** 895,900 char temp[100]; char *pp = bptr; FILE *pfp, *popen(); fprintf(stderr, "Caesar decoding:\n"); strcpy(temp, CAESAR); --- 956,966 ----- char temp[100]; char *pp = bptr; FILE *pfp, *popen(); + #ifdef MOD_PAGE + FILE *pifp, *fdopen(); + register int ttt; + int p[2]; + #endif MOD_PAGE fprintf(stderr, "Caesar decoding:\n"); strcpy(temp, CAESAR); *************** *** 902,907 strcat(temp, " "); strcat(temp, bptr); } if (NLINES(h, fp) > LNCNT && *PAGER) { strcat(temp, " | "); strcat(temp, PAGER); --- 968,1008 ----- strcat(temp, " "); strcat(temp, bptr); } + #ifdef MOD_PAGE + if (NLINES(h, fp) > (((rflag && bit < 1) || (bit > ngsize))? 12 : 17) + && *PAGER) { + if (strcmp(PAGER, "My Own") == 0) { + pipe(p); + ttt = dup(1); + dup2(p[1], 1); + close(p[1]); + pifp = fdopen(p[0], "r"); + pfp = popen(temp, "w"); + dup2(ttt, 1); + close(ttt); + /* fsubr only takes function with 2 args, */ + /* so and we need 3... */ + while ((ttt = fork()) == -1) + sleep(1); + if (ttt == 0) { + tprint(fp, pfp, FALSE); + exit(0); + } + pclose(pfp); + pprint(pifp, ofp, &h, 0L, 0); + fclose(pifp); + fwait(ttt); + } else { + strcat(temp, " | "); + strcat(temp, PAGER); + pfp = popen(temp, "w"); + tprint(fp, pfp, FALSE); + } + } else { + pfp = popen(temp, "w"); + tprint(fp, pfp, FALSE); + } + #else MOD_PAGE if (NLINES(h, fp) > LNCNT && *PAGER) { strcat(temp, " | "); strcat(temp, PAGER); *************** *** 908,913 } pfp = popen(temp, "w"); tprint(fp, pfp, FALSE); itsbeenseen(h.ident); fclose(fp); fp = NULL; --- 1009,1015 ----- } pfp = popen(temp, "w"); tprint(fp, pfp, FALSE); + #endif MOD_PAGE itsbeenseen(h.ident); fclose(fp); fp = NULL; *************** *** 923,928 FILE *fd; { if (fd == NULL) return; if (dgest) { --- 1025,1033 ----- FILE *fd; { if (fd == NULL) + #ifdef MOD_PAGE + return(0); + #else return; #endif MOD_PAGE *************** *** 924,929 { if (fd == NULL) return; if (dgest) { digest(fd, ofp, &h); --- 1029,1035 ----- return(0); #else return; + #endif MOD_PAGE if (dgest) { digest(fd, ofp, &h); *************** *** 930,935 } else if (!lflag && !pflag && !eflag) { #ifdef PAGE /* Filter the tail of long messages through PAGER. */ if (NLINES(h, fd) > LNCNT && *PAGER) { if (!index(PAGER, FMETA)) { FILE *pfp, *popen(); --- 1036,1042 ----- } else if (!lflag && !pflag && !eflag) { #ifdef PAGE /* Filter the tail of long messages through PAGER. */ + #ifndef MOD_PAGE if (NLINES(h, fd) > LNCNT && *PAGER) { #else MOD_PAGE if (NLINES(h, fd) > *************** *** 931,936 #ifdef PAGE /* Filter the tail of long messages through PAGER. */ if (NLINES(h, fd) > LNCNT && *PAGER) { if (!index(PAGER, FMETA)) { FILE *pfp, *popen(); int cnt; --- 1038,1049 ----- /* Filter the tail of long messages through PAGER. */ #ifndef MOD_PAGE if (NLINES(h, fd) > LNCNT && *PAGER) { + #else MOD_PAGE + if (NLINES(h, fd) > + (((rflag && bit < 1) || (bit > ngsize))? LNCNT - 5 : LNCNT) + && *PAGER) { + if ( strcmp(PAGER, "My Own") != 0 ) { + #endif MOD_PAGE if (!index(PAGER, FMETA)) { FILE *pfp, *popen(); int cnt; *************** *** 951,958 else pout(ofp); holdup = TRUE; } else #endif --- 1064,1077 ----- else pout(ofp); holdup = TRUE; + #ifdef MOD_PAGE + } else + /* PAGER == "My Own" */ + if (pprint(fd, ofp, &h, 0L, 0)) { + fclose(fd); + return(1); + } + #endif MOD_PAGE } else #endif *************** *** 959,964 tprint(fd, ofp, FALSE), itsbeenseen(h.ident); } fclose(fd); } /* --- 1078,1086 ----- tprint(fd, ofp, FALSE), itsbeenseen(h.ident); } fclose(fd); + #ifdef MOD_PAGE + return(0); + #endif MOD_PAGE } /* *** ../vanilla/src/rfuncs2.c Wed May 25 12:58:00 1983 --- rfuncs2.c Sun Jun 5 18:20:48 1983 *************** *** 64,69 } /* * Save the news item in the user's file. * Fri Mar 12 20:04:43 EST 1982: (ittvax!swatt) --- 64,70 ----- } + #ifndef MOD_PAGE /* * Save the news item in the user's file. * Fri Mar 12 20:04:43 EST 1982: (ittvax!swatt) *************** *** 138,143 if (!isprogram) printf("%s: %s\n", to, isnew ? "New file" : "Appended"); } /* --- 139,145 ----- if (!isprogram) printf("%s: %s\n", to, isnew ? "New file" : "Appended"); } + #endif MOD_PAGE /* ****** THE REST OF THIS ARTICLE IS THE FILE PAGER.C ******* #ifdef MOD_PAGE /* * This pager was originally written by Alan Hastings while system manager * at St. Olaf College, for version 2.3 of Bnews. It has been enhanced and * updated to run under successive versions of Bnews (currently 2.10) by * Dave Borman at St. Olaf. * */ #include "rparams.h" #define TABSIZE 8 #define COL 80 pprint(ifp, ofp, h, end, art) register FILE *ifp, *ofp; struct hbuf *h; long end; int art; { char ppbuf[BUFLEN], resbuf[BUFLEN]; char *respons; long pgoffs[BUFLEN]; long begin; int curpg = 0, lastpg = 0; register int i = 0; int isnew; begin = pgoffs[0] = ftell(ifp); pgoffs[1] = 0L; while (fgets(ppbuf, sizeof(ppbuf), ifp)) { if (end && (ftell(ifp) > end)) break; if (sigtrap) { qfflush(ofp); break; } i += num_lines(ppbuf); if (i > 23) { i = 1; if (++curpg > lastpg) lastpg = curpg; if (pgoffs[lastpg]==0L) { pgoffs[lastpg] = ftell(ifp); pgoffs[lastpg+1] = 0L; } getmore: #ifdef MOD_NTTY fflush(ofp); ioctl(fileno(ofp), TIOXRESO, 0); #endif MOD_NTTY fprintf(ofp, "Page %d -- Press return for more-- [ynq] ", curpg); fflush(ofp); fgets(resbuf, sizeof(resbuf), stdin); respons = resbuf; nstrip(respons); while(*respons == ' ' || *respons == '\t') respons++; switch (*respons) { default: fprintf(ofp, "? for pager commands\n"); goto getmore; case 'y': case 'Y': case '\0': case '\n': break; case 'n': sigtrap = FALSE; fprintf(ofp, "\n"); return(0); case 'h': if (art) dhprint(art, ifp, ofp); else hprint(h, ofp, !cflag); goto getmore; case 'q': return(1); case '+': case '-': { int n = 1, nn; char *r = respons; while (*++r==respons[0]) n++; nn = atoi(r); if (respons[0]=='-') curpg -= (nn==0) ? n+1 : n+nn; else curpg += (nn==0) ? n-1 : n+nn-2; curpg = (curpg < 0) ? 0 : (curpg > lastpg) ? lastpg : curpg; fseek(ifp, pgoffs[curpg], 0); fgets(ppbuf, sizeof(ppbuf), ifp); break; } case '!': fwait(fsubr(ushell, &respons[1], (char *)NULL)); fprintf(ofp, "!\n"); goto getmore; case 'p': fseek(ifp, pgoffs[--curpg], 0); fgets(ppbuf, sizeof(ppbuf), ifp); break; case 'l': curpg = lastpg; fseek(ifp, pgoffs[curpg], 0); fgets(ppbuf, sizeof(ppbuf), ifp); break; case '#': fprintf(ofp, "%d more lines\n", (end ? plinecnt(ifp, end) : linecnt(ifp))+1); goto getmore; case 's': case 'w': { char *rp = &respons[1]; if (*rp != '\0' && *rp != ' ' && *rp != ' ') { fprintf(ofp, "Bad file name.\n"); break; } while (*rp==' ' || *rp=='\t') rp++; if(*rp != '|' && *rp != '/') { char hetyped[BUFLEN]; char *boxptr; strcpy(hetyped,rp); if(boxptr = getenv("NEWSBOX")) if (index(boxptr, '%')) sprintf(rp,boxptr,groupdir); else strcpy(rp, boxptr); else if (hetyped[0]=='~' && hetyped[1]=='/') { strcpy(hetyped, rp+2); strcpy(rp, userhome); } else strcpy(rp, "."); strcat(rp,"/"); if(hetyped[0] != '\0') strcat(rp, hetyped); #ifdef MOD_SAVE else { char *ART = getenv("ARTICLES"); strcpy(rp,ART?ART:"articles"); } #else else strcat(rp, "Articles"); #endif MOD_SAVE } isnew = access( rp, 2 ); if (art) dsaveart(art, ifp, ofp, rp); else if( psave(ifp, rp, *respons=='s' ? 1:0) == 1 ) printf("%s: %s\n", rp, isnew ? "New file": "Appended"); goto getmore; } case '?': fprintf(ofp, "(p)rint again, (n)ext article, (q)uit, (l)ast page, -n, +n, (y)et another page\n"); fprintf(ofp, "(#) of lines left, (s)ave, (w)rite, (h)eader\n"); goto getmore; } } fprintf(ofp, "%s", ppbuf); } fflush(ofp); if (sigtrap) printf(ofp, "\n\n"); else /* if new newsgroup header follows, allow five extra lines */ if (i > (((rflag && bit < 1) || (bit>ngsize)) ? LNCNT - 5 : LNCNT)) { while (i++ < 23) putc('\n', ofp); #ifdef MOD_NTTY ioctl(fileno(ofp), TIOXRESO, 0); #endif MOD_NTTY fprintf(ofp, "-- Press return --"); fflush(ofp); fgets(resbuf, sizeof(resbuf), stdin); } else fprintf(ofp, "\n"); fflush(ofp); sigtrap = FALSE; return(0); } plinecnt(fp, end) FILE *fp; long end; { long curpos; long count; register int nlines = 0; register int c; if (!end) return(linecnt(fp)); if (fp == NULL) return(0); curpos = ftell(fp); count = end - curpos; while (((c = getc(fp)) != EOF) && (--count >= 0)) if (c == '\n') nlines++; fseek(fp, curpos, 0); return(nlines); } num_lines(line) char *line; { register int count = 0; register char *p; for( p = line; *p != NULL; p++ ) switch( *p ){ case '\t': count += TABSIZE - count%TABSIZE;break; default: count++; } return( (count + COL - 1)/COL ); /* COL-1: linelength minus newline */ } psave(ifp, fnm, flg) char *fnm; { long savpos = ftell(ifp); FILE *ofp; int isprogram = 0; struct hbuf savh; if (ifp == NULL) return ( NULL ); if (*fnm == '|'){ if ((ofp = popen (&fnm[1], "w")) == NULL) { printf ("Cannot execute %s\n", &fnm[1]); return (NULL); } isprogram++; } else if ((ofp = fopen(fnm, "a")) == NULL) { printf("Cannot append to %s\n", fnm); return (NULL); } fseek(ifp, 0, 0); /* back to beginning */ if (hread(&savh, ifp, TRUE) == NULL) { /* grab header */ printf("Article is garbled.\n"); return (NULL); } #ifdef V7MAIL savh.subtime = cgtdate(savh.subdate); fprintf(ofp, "From %s %s", #ifdef INTERNET savh.from, #else savh.path, #endif INTERNET ctime(&savh.subtime)); #endif V7MAIL if (flg) hprint(&savh, ofp, 1); #ifdef V7MAIL putc('\n', ofp); /* force blank line before article */ tprint(ifp, ofp, TRUE); putc('\n', ofp); /* force blank line at end (ugh) */ #else tprint(ifp, ofp, FALSE); #endif V7MAIL if (isprogram) pclose(ofp); else fclose(ofp); fseek(ifp, savpos, 0); return(!isprogram); } rsave(ifnm, fnm, flg) char *ifnm, *fnm; { FILE *ifp = fopen(ifnm, "r"); int isnew; if( ifp == NULL ){ printf("Can't get Article.\n"); return; } isnew = access( fnm, 2 ); if( psave(ifp, fnm, flg) == 1 ) printf("%s: %s\n", fnm, isnew ? "New file" : "Appended"); fclose(ifp); } #endif MOD_PAGE