[alt.sources] Todd's hacks to rn

todd@ivucsb.sba.ca.us (Todd Day) (07/10/89)

Those of you who have requested the diffs to my hacks, well, here
they are.

I have included a file called 1READ_FIRST, so please do.

Also, to those of you who have already grabbed the source off anise,
make sure you got rn40todd.Z and not rn.todd.tar.Z.  The later is
patchlevel39 and the former is patchlevel40.  (anise is anise.acc.com
[129.192.64.22])  These diffs are also available on anise (rn40todd.dif.Z).

To those of you who don't know what I am talking about, my hacks to
rn present you with a visual interface to the subjects when you type
';' or '%'.  A user who never types these two characters will never
know about my hacks (i.e., this doesn't interrupt normal rn).  All
my changes are in the documentation and in the help section of rn.

Good Luck!

#! /bin/sh
# To extract, remove mail header lines and type "sh filename"
echo x - 1READ_FIRST
sed -e 's/^X//' > 1READ_FIRST << '!FaR!OuT!'
X
X						July 7, 1989
XHello!
X
X	This is Todd's attempt at making rn act a bit more like vn (and
Xnow nn).  I have incorporated it first into rn:patchlevel39, then I
Xapplied level40 patches to it.  In other words, it should be at level 40.
X
X	Please note that my changes are kinda kludgey, in keeping with
Xthe programming style of lwall :-)
X
X	All of my changes have been documented in the documentation
Xplus the help files.
X
X	You enter my special mode by typing ';' anywhere.  As far
Xas I know, unless you type ';' or '%' at any prompt, you
Xwill not even know that rn has been modified.  In other words, users
Xthat don't want to use my changes don't have to.
X
X	If you find any bugs, please send them to me (plus fixes,
Xif you gottem).
X
X	Please be patient with me about this software.  I am now
Xusing nn (and suggest that you use it, also), but I will try to
Xupdate this software (in keeping with being a nice net.citizen).
X
X	Good luck... hope you like this stuff.  It cut my reading
Xtime down in half.  Most of the time, I would start reading the
Xarticle (since it all was displayed).  Now, with this program,
XI was able to delete stuff I really shouldn't have been reading.
X
X	Oh, I almost forgot.  You MUST have CACHESUBJ set in
Xcommon.h.  This is true for most people.  It is only false for
Xpdp11s.  Also, you must have a sorta smart terminal (I don't make
Xtoo much use of termcap stuff).  By sorta smart terminal, I mean
Xmust have do, cd, and up entry in termcap file.  Just about every
Xterminal I know of has this. [see term.c]
X
X	You can find most of my changes in ng.c.  Just search for
XSubScan(tm).
X
X	Have fun!
X
X
XTodd Day | todd@ivucsb.sba.ca.us | ivucsb!todd@anise.acc.com
X"Santa Barbara - so many babes... so few who will talk to me."
!FaR!OuT!
echo x - rn40.diff
sed -e 's/^X//' > rn40.diff << '!FaR!OuT!'
Xdiff -c rn40/Wishlist rn40.todd/Wishlist
X*** rn40/Wishlist	Fri Nov 21 12:43:04 1986
X--- rn40.todd/Wishlist	Fri Jul  7 13:44:34 1989
X***************
X*** 1,5
X  Generalized article set manipulation
X! 	Interface to subject listing.
X  	Recursive newsgroup visitation.
X  Virtual article abstract type to allow the following:
X  	Personalized header munging via % subs.
X
X--- 1,5 -----
X  Generalized article set manipulation
X! 	Interface to subject listing.  <===AHA!  I got that one!!! (-Todd-)
X  	Recursive newsgroup visitation.
X  Virtual article abstract type to allow the following:
X  	Personalized header munging via % subs.
Xdiff -c rn40/art.c rn40.todd/art.c
X*** rn40/art.c	Mon Feb  2 14:24:24 1987
X--- rn40.todd/art.c	Tue Jun 13 22:16:46 1989
X***************
X*** 784,789
X      case '1': case '2': case '3': case '4': case '5':
X      case '6': case '7': case '8': case '9':
X      case '=':
X      case '?':
X      case 'c':	case 'C':	
X      case 'f':	case 'F':	
X
X--- 784,790 -----
X      case '1': case '2': case '3': case '4': case '5':
X      case '6': case '7': case '8': case '9':
X      case '=':
X+     case ';': case '%':
X      case '?':
X      case 'c':	case 'C':	
X      case 'f':	case 'F':	
Xdiff -c rn40/artsrch.c rn40.todd/artsrch.c
X*** rn40/artsrch.c	Fri Nov 21 12:41:36 1986
X--- rn40.todd/artsrch.c	Tue Jun 13 22:16:48 1989
X***************
X*** 37,43
X  
X  #ifdef ARTSEARCH
X  int
X! art_search(patbuf,patbufsiz,get_cmd)
X  char *patbuf;				/* if patbuf != buf, get_cmd must */
X  int patbufsiz;
X  int get_cmd;				/*   be set to FALSE!!! */
X
X--- 37,43 -----
X  
X  #ifdef ARTSEARCH
X  int
X! art_search(patbuf,patbufsiz,get_cmd,force_doread,print_msg)
X  char *patbuf;				/* if patbuf != buf, get_cmd must */
X  int patbufsiz;
X  int get_cmd;				/*   be set to FALSE!!! */
X***************
X*** 41,46
X  char *patbuf;				/* if patbuf != buf, get_cmd must */
X  int patbufsiz;
X  int get_cmd;				/*   be set to FALSE!!! */
X  {
X      char *pattern;			/* unparsed pattern */
X      register char cmdchr = *patbuf;	/* what kind of search? */
X
X--- 41,48 -----
X  char *patbuf;				/* if patbuf != buf, get_cmd must */
X  int patbufsiz;
X  int get_cmd;				/*   be set to FALSE!!! */
X+ int force_doread;			/* search read arts also */
X+ int print_msg;
X  {
X      char *pattern;			/* unparsed pattern */
X      register char cmdchr = *patbuf;	/* what kind of search? */
X***************
X*** 127,133
X  	    mark_as_read(art);		/* this article has this subject */
X  	    if (!*h) {
X  #ifdef VERBOSE
X! 		IF(verbose)
X  		    fputs("\nCannot delete null subject.\n",stdout) FLUSH;
X  		ELSE
X  #endif
X
X--- 129,135 -----
X  	    mark_as_read(art);		/* this article has this subject */
X  	    if (!*h) {
X  #ifdef VERBOSE
X! 		IF(verbose && print_msg)
X  		    fputs("\nCannot delete null subject.\n",stdout) FLUSH;
X  		ELSE
X  #endif
X***************
X*** 132,138
X  		ELSE
X  #endif
X  #ifdef TERSE
X! 		    fputs("\nNull subject.\n",stdout) FLUSH;
X  #endif
X  		return SRCH_ABORT;
X  	    }
X
X--- 134,141 -----
X  		ELSE
X  #endif
X  #ifdef TERSE
X! 		    if (print_msg)
X! 		        fputs("\nNull subject.\n",stdout) FLUSH;
X  #endif
X  		return SRCH_ABORT;
X  	    }
X***************
X*** 137,143
X  		return SRCH_ABORT;
X  	    }
X  #ifdef VERBOSE
X! 	    else if (verbose)
X  		printf("\nMarking subject \"%s\" as read.\n",h) FLUSH;
X  #endif
X  	}
X
X--- 140,146 -----
X  		return SRCH_ABORT;
X  	    }
X  #ifdef VERBOSE
X! 	    else if (verbose && print_msg)
X  		printf("\nMarking subject \"%s\" as read.\n",h) FLUSH;
X  #endif
X  	}
X***************
X*** 158,164
X      }
X      if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) {
X  					/* compile regular expression */
X! 	printf("\n%s\n",s) FLUSH;
X  	return SRCH_ABORT;
X      }
X  #ifdef KILLFILES
X
X--- 161,168 -----
X      }
X      if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) {
X  					/* compile regular expression */
X! 	if (print_msg)
X! 	    printf("\n%s\n",s) FLUSH;
X  	return SRCH_ABORT;
X      }
X  #ifdef KILLFILES
X***************
X*** 183,189
X  #endif
X      if (cmdlst && index(cmdlst,'='))
X  	normal_return = SRCH_ERROR;	/* listing subjects is an error? */
X!     if (get_cmd) {
X  	fputs("\nSearching...\n",stdout) FLUSH;
X  					/* give them something to read */
X      }
X
X--- 187,193 -----
X  #endif
X      if (cmdlst && index(cmdlst,'='))
X  	normal_return = SRCH_ERROR;	/* listing subjects is an error? */
X!     if (get_cmd && print_msg) {
X  	fputs("\nSearching...\n",stdout) FLUSH;
X  					/* give them something to read */
X      }
X***************
X*** 226,232
X  	    if (wanted(compex,art,howmuch)) {
X  				    /* does the shoe fit? */
X  		if (cmdlst) {
X! 		    if (perform(cmdlst,TRUE)) {
X  			if (cmdlst)
X  			    free(cmdlst);
X  			return SRCH_INTR;
X
X--- 230,236 -----
X  	    if (wanted(compex,art,howmuch)) {
X  				    /* does the shoe fit? */
X  		if (cmdlst) {
X! 		    if (perform(cmdlst,TRUE,print_msg)) {
X  			if (cmdlst)
X  			    free(cmdlst);
X  			return SRCH_INTR;
X***************
X*** 238,244
X  		    return SRCH_FOUND;
X  		}
X  	    }
X! 	    else if (!cmdlst && ! (art%50)) {
X  		printf("...%ld",(long)art);
X  		fflush(stdout);
X  	    }
X
X--- 242,248 -----
X  		    return SRCH_FOUND;
X  		}
X  	    }
X! 	    else if (!cmdlst && !(art%50) && print_msg) {
X  		printf("...%ld",(long)art);
X  		fflush(stdout);
X  	    }
Xdiff -c rn40/bits.c rn40.todd/bits.c
X*** rn40/bits.c	Fri Nov 21 13:48:14 1986
X--- rn40.todd/bits.c	Tue Jun 13 22:16:50 1989
X***************
X*** 189,194
X  	return;
X      }
X  #endif
X      if (!ctl_read(artnum)) {
X  	ctl_set(artnum);
X  	if (toread[ng] > TR_NONE)
X
X--- 189,197 -----
X  	return;
X      }
X  #endif
X+ #ifdef CACHESUBJ
X+     x_clear(artnum);
X+ #endif
X      if (!ctl_read(artnum)) {
X  	ctl_set(artnum);
X  	if (toread[ng] > TR_NONE)
X***************
X*** 496,501
X      ctlsize = (MEM_SIZE)(OFFSET(lastart)/BITSPERBYTE+20);
X  #endif lint
X      ctlarea = safemalloc(ctlsize);	/* allocate control area */
X  
X      /* now modify ctlarea to reflect what has already been read */
X  
X
X--- 499,507 -----
X      ctlsize = (MEM_SIZE)(OFFSET(lastart)/BITSPERBYTE+20);
X  #endif lint
X      ctlarea = safemalloc(ctlsize);	/* allocate control area */
X+ #ifdef CACHESUBJ
X+     xmark = safemalloc(ctlsize);
X+ #endif
X  
X      /* now modify ctlarea to reflect what has already been read */
X  
X***************
X*** 535,540
X      unread = lastart - firstbit + 1;	/* assume this range unread */
X      for (i=OFFSET(firstbit)/BITSPERBYTE; i<ctlsize; i++)
X  	ctlarea[i] = 0;			/* assume unread */
X  #ifdef DEBUGGING
X      if (debug & DEB_CTLAREA_BITMAP) {
X  	printf("\n%s\n",mybuf) FLUSH;
X
X--- 541,551 -----
X      unread = lastart - firstbit + 1;	/* assume this range unread */
X      for (i=OFFSET(firstbit)/BITSPERBYTE; i<ctlsize; i++)
X  	ctlarea[i] = 0;			/* assume unread */
X+ #ifdef CACHESUBJ
X+     for (i=OFFSET(absfirst)/BITSPERBYTE; i<ctlsize; i++)
X+ 	xmark[i] = 0;
X+     xmarked = FALSE;
X+ #endif
X  #ifdef DEBUGGING
X      if (debug & DEB_CTLAREA_BITMAP) {
X  	printf("\n%s\n",mybuf) FLUSH;
X***************
X*** 606,611
X  	if (newsize > ctlsize) {
X  	    newsize += 20;
X  	    ctlarea = saferealloc(ctlarea,newsize);
X  	    ctlsize = newsize;
X  	}
X  	toread[ng] += (ART_UNREAD)(newlast-lastart);
X
X--- 617,625 -----
X  	if (newsize > ctlsize) {
X  	    newsize += 20;
X  	    ctlarea = saferealloc(ctlarea,newsize);
X+ #ifdef CACHESUBJ
X+ 	    xmark = saferealloc(xmark,newsize);
X+ #endif
X  	    ctlsize = newsize;
X  	}
X  	toread[ng] += (ART_UNREAD)(newlast-lastart);
X***************
X*** 609,615
X  	    ctlsize = newsize;
X  	}
X  	toread[ng] += (ART_UNREAD)(newlast-lastart);
X! 	for (i=lastart+1; i<=newlast; i++)
X  	    ctl_clear(i);	/* these articles are unread */
X  #ifdef CACHESUBJ
X  	if (subj_list != Null(char**)) {
X
X--- 623,629 -----
X  	    ctlsize = newsize;
X  	}
X  	toread[ng] += (ART_UNREAD)(newlast-lastart);
X! 	for (i=lastart+1; i<=newlast; i++) {
X  	    ctl_clear(i);	/* these articles are unread */
X  #ifdef CACHESUBJ
X  	    x_clear(i);		/* these article are unmarked */
X***************
X*** 611,616
X  	toread[ng] += (ART_UNREAD)(newlast-lastart);
X  	for (i=lastart+1; i<=newlast; i++)
X  	    ctl_clear(i);	/* these articles are unread */
X  #ifdef CACHESUBJ
X  	if (subj_list != Null(char**)) {
X  #ifndef lint
X
X--- 625,634 -----
X  	toread[ng] += (ART_UNREAD)(newlast-lastart);
X  	for (i=lastart+1; i<=newlast; i++) {
X  	    ctl_clear(i);	/* these articles are unread */
X+ #ifdef CACHESUBJ
X+ 	    x_clear(i);		/* these article are unmarked */
X+ #endif
X+ 	}
X  #ifdef CACHESUBJ
X  	if (subj_list != Null(char**)) {
X  #ifndef lint
Xdiff -c rn40/bits.h rn40.todd/bits.h
X*** rn40/bits.h	Fri Nov 21 13:49:50 1986
X--- rn40.todd/bits.h	Tue Jun 13 22:16:52 1989
X***************
X*** 16,21
X  			/* with the following interpretation: */
X  			/*	0 => unread  */
X  			/*	1 => read    */
X  
X  /* if subscripting is faster than shifting on your machine, define this */
X  #undef USESUBSCRIPT
X
X--- 16,28 -----
X  			/* with the following interpretation: */
X  			/*	0 => unread  */
X  			/*	1 => read    */
X+ EXT MEM_SIZE ctlsize;			/* size of bitmap in bytes */
X+ #ifdef CACHESUBJ
X+ EXT char *xmark INIT(Nullch);	/* same here, but */
X+ 				/* 0 => unmarked */
X+ 				/* 1 => marked */
X+ EXT int xmarked INIT(FALSE);	/* any marks done? */
X+ #endif
X  
X  /* if subscripting is faster than shifting on your machine, define this */
X  #undef USESUBSCRIPT
X***************
X*** 36,41
X  #define ctl_set(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] |= pow2((OFFSET(a)) % BITSPERBYTE))
X  #define ctl_clear(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] &= ~pow2((OFFSET(a)) % BITSPERBYTE))
X  #define ctl_read(a) ((ctlarea[(OFFSET(a)) / BITSPERBYTE] & pow2((OFFSET(a)) % BITSPERBYTE)) != 0)
X  
X  #define was_read(a) ((a)<firstbit || ctl_read(a))
X  #endif lint
X
X--- 43,55 -----
X  #define ctl_set(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] |= pow2((OFFSET(a)) % BITSPERBYTE))
X  #define ctl_clear(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] &= ~pow2((OFFSET(a)) % BITSPERBYTE))
X  #define ctl_read(a) ((ctlarea[(OFFSET(a)) / BITSPERBYTE] & pow2((OFFSET(a)) % BITSPERBYTE)) != 0)
X+ 
X+ #ifdef CACHESUBJ
X+ #define x_set(a) (xmark[(OFFSET(a)) / BITSPERBYTE] |= pow2((OFFSET(a)) % BITSPERBYTE))
X+ #define x_clear(a) (xmark[(OFFSET(a)) / BITSPERBYTE] &= ~pow2((OFFSET(a)) % BITSPERBYTE))
X+ #define x_marked(a) ((xmark[(OFFSET(a)) / BITSPERBYTE] & pow2((OFFSET(a)) % BITSPERBYTE)) != 0)
X+ #endif
X+ 
X  
X  #define was_read(a) ((a)<firstbit || ctl_read(a))
X  #endif lint
Xdiff -c rn40/help.c rn40.todd/help.c
X*** rn40/help.c	Fri Nov 21 13:39:04 1986
X--- rn40.todd/help.c	Thu Dec 22 17:47:12 1988
X***************
X*** 72,78
X  Type h at end of article for a description of these commands:\n\
X  ",STANDOUT)) ||
X      (cmd = print_lines("\
X! 	# $ & / = ? c C f F k K ^K m M number r R ^R s S u v w W Y ^ |\n\
X  \n\
X  (To return to the middle of the article after one of these commands, type ^L.)\n\
X  ",NOMARKING)) )
X
X--- 72,78 -----
X  Type h at end of article for a description of these commands:\n\
X  ",STANDOUT)) ||
X      (cmd = print_lines("\
X! 	# $ & / = ; % ? c C f F k K ^K m M number r R ^R s S u v w W Y ^ |\n\
X  \n\
X  (To return to the middle of the article after one of these commands, type ^L.)\n\
X  ",NOMARKING)) )
X***************
X*** 154,159
X  k	Mark current SUBJECT as read.\n\
X  K	Mark current SUBJECT as read, and save command in KILL file.\n\
X  =	List subjects of unread articles.\n\
X  u	Unsubscribe to this newsgroup.\n\
X  ^K	Edit local KILL file (the one for this newsgroup).\n\
X  q	Quit this newsgroup for now.\n\
X
X--- 154,161 -----
X  k	Mark current SUBJECT as read.\n\
X  K	Mark current SUBJECT as read, and save command in KILL file.\n\
X  =	List subjects of unread articles.\n\
X+ ;	Interactive subject list.\n\
X+ %	Same as ';', but include read articles.\n\
X  u	Unsubscribe to this newsgroup.\n\
X  ^K	Edit local KILL file (the one for this newsgroup).\n\
X  q	Quit this newsgroup for now.\n\
X***************
X*** 164,169
X      return 0;
X  }
X  
X  int
X  help_ng()
X  {
X
X--- 166,172 -----
X      return 0;
X  }
X  
X+ #ifdef CACHESUBJ
X  int
X  help_sub_scan()
X  {
X***************
X*** 165,170
X  }
X  
X  int
X  help_ng()
X  {
X      int cmd;
X
X--- 168,225 -----
X  
X  #ifdef CACHESUBJ
X  int
X+ help_sub_scan()
X+ {
X+     int cmd;
X+ 
X+     page_init();
X+     if ((cmd = print_lines("\
X+ Subject Scan/Display commands:\n\
X+ ",STANDOUT)) ||
X+     (cmd = print_lines("\n\
X+ SP,CR,r	Display article, and follow its thread in the Article\n\
X+ 	Selection Level.  Once in the Article Selection Level,\n\
X+ 	you may use any of its commands.  You may return via\n\
X+ 	';' or '%'.\n\
X+ j	Move down to next subject.\n\
X+ k	Move up to previous subject.\n\
X+ n	Display next page of subjects.\n\
X+ ",NOMARKING)) ||
X+     (cmd = print_lines("\
X+ p	Display previous page of subjects.\n\
X+ N,>	Go to next unread newsgroup.\n\
X+ P,<	Go to previous unread newsgroup.\n\
X+ t	Move to top of current page.\n\
X+ b	Move to bottom of current page.\n\
X+ T	Move to top of all subjects.\n\
X+ B	Move to bottom of all subjects.\n\
X+ d	Mark all articles with same subject as read.  Same\n\
X+ 	as 'k' at the Article Selection Level.\n\
X+ f	Toggle thread following mode.\n\
X+ x	Mark or unmark article.  After return from Article\n\
X+ 	Selection level, the next marked article will be read.\n\
X+ c	Clear all marked articles.\n\
X+ ",NOMARKING)) ||
X+     (cmd = print_lines("\
X+ /pattern\n\
X+ 	Search for next subject and, if found, put at top of\n\
X+ 	page.  Usage same as pattern searches at Article\n\
X+ 	Selection Level, including 'header' and 'all' searches.\n\
X+ ?pattern\n\
X+ 	Same as /pattern above, except search for previous subject.\n\
X+ ^L	Redraw screen.\n\
X+ ;	Show only unread subjects.  May force you to next unread\n\
X+ 	newsgroup if all subjects are read.\n\
X+ %	Show all subjects.\n\
X+ q	Quit this level.\n\
X+ ",NOMARKING)) )
X+ 	return cmd;
X+     get_anything();
X+     return 0;
X+ }
X+ #endif
X+ 
X+ int
X  help_ng()
X  {
X      int cmd;
X***************
X*** 182,187
X  y,SP	Do this newsgroup now.\n\
X  .cmd	Do this newsgroup, executing cmd as first command.\n\
X  =	Equivalent to .=<carriage return>.\n\
X  u	Unsubscribe from this newsgroup.\n\
X  c	Catch up (mark this newsgroup all read).\n\
X  ",NOMARKING) )
X
X--- 237,244 -----
X  y,SP	Do this newsgroup now.\n\
X  .cmd	Do this newsgroup, executing cmd as first command.\n\
X  =	Equivalent to .=<carriage return>.\n\
X+ ;	Interactive subject list.\n\
X+ %	Same as ';', but include read articles.\n\
X  u	Unsubscribe from this newsgroup.\n\
X  c	Catch up (mark this newsgroup all read).\n\
X  ",NOMARKING) )
Xdiff -c rn40/kfile.c rn40.todd/kfile.c
X*** rn40/kfile.c	Fri Nov 21 13:27:12 1986
X--- rn40.todd/kfile.c	Thu Dec 22 17:54:02 1988
X***************
X*** 108,114
X  	}
X  	else if (*buf == '/' && firstart <= lastart) {
X  	    mention(buf);
X! 	    switch (art_search(buf, (sizeof buf), FALSE)) {
X  	    case SRCH_ABORT:
X  		continue;
X  	    case SRCH_INTR:
X
X--- 108,114 -----
X  	}
X  	else if (*buf == '/' && firstart <= lastart) {
X  	    mention(buf);
X! 	    switch (art_search(buf, (sizeof buf), FALSE, FALSE, TRUE)) {
X  	    case SRCH_ABORT:
X  		continue;
X  	    case SRCH_INTR:
X***************
X*** 168,176
X  	    setthru(lastart);
X  	putchar('\n') FLUSH;
X  #ifdef VERBOSE
X! 	IF(verbose)
X! 	    if (entering)
X! 		get_anything();
X  #endif
X  	if (anytokill)			/* if there was anything to kill */
X  	    forcelast = FALSE;		/* allow for having killed it all */
X
X--- 168,175 -----
X  	    setthru(lastart);
X  	putchar('\n') FLUSH;
X  #ifdef VERBOSE
X! 	IF(verbose && !sub_scan_mode && entering)
X! 	    get_anything();
X  #endif
X  	if (anytokill)			/* if there was anything to kill */
X  	    forcelast = FALSE;		/* allow for having killed it all */
XOnly in rn40.todd: myread
Xdiff -c rn40/ng.c rn40.todd/ng.c
X*** rn40/ng.c	Fri Nov 21 13:39:08 1986
X--- rn40.todd/ng.c	Wed Jun 14 10:11:46 1989
X***************
X*** 123,128
X  #endif
X      
X      mode = 'a';
X      recent_art = curr_art = 0;
X      exit_code = NG_NORM;
X      if (eaccess(ngdir,5)) {		/* directory read protected? */
X
X--- 123,129 -----
X  #endif
X      
X      mode = 'a';
X+     cur_art_ptr = percent_prev = percent_art = 0;
X      recent_art = curr_art = 0;
X      exit_code = NG_NORM;
X      if (eaccess(ngdir,5)) {		/* directory read protected? */
X***************
X*** 395,401
X  #ifdef MAILCALL
X  	setmail();
X  #endif
X! 	setdfltcmd();
X  #ifdef CLEAREOL
X  	if (erase_screen && can_home_clear)	/* PWP was here */
X  	    clear_rest();
X
X--- 396,403 -----
X  #ifdef MAILCALL
X  	setmail();
X  #endif
X! 	if (!sub_scan_mode)
X! 	    setdfltcmd();
X  #ifdef CLEAREOL
X  	if (erase_screen && can_home_clear)	/* PWP was here */
X  	    clear_rest();
X***************
X*** 480,485
X      }
X  #endif
X      mode = oldmode;
X      return exit_code;
X  }					/* Whew! */
X  
X
X--- 482,489 -----
X      }
X  #endif
X      mode = oldmode;
X+     if (exit_code != 'n' && exit_code != 'p')	/* just to make sure */
X+ 	sub_scan_mode = 0;
X      return exit_code;
X  }					/* Whew! */
X  
X***************
X*** 536,541
X  	    return AS_NORM;
X  	}
X  	else {
X  	    exit_code = NG_MINUS;
X  	    return AS_CLEAN;
X  	}
X
X--- 540,547 -----
X  	    return AS_NORM;
X  	}
X  	else {
X+ 	    if (sub_scan_mode)
X+ 		goto SubScan;
X  	    exit_code = NG_MINUS;
X  	    return AS_CLEAN;
X  	}
X***************
X*** 541,547
X  	}
X      case 'n':		/* find next unread article? */
X  	if (art > lastart) {
X! 	    if (toread[ng])
X  		art = firstart;
X  	    else
X  		return AS_CLEAN;
X
X--- 547,555 -----
X  	}
X      case 'n':		/* find next unread article? */
X  	if (art > lastart) {
X! 	    if (sub_scan_mode)
X! 		goto SubScan;
X! 	    else if (toread[ng])
X  		art = firstart;
X  	    else
X  		return AS_CLEAN;
X***************
X*** 552,558
X  	    goto normal_search;
X  	}
X  #endif
X! 	else
X  	    art++;
X  #ifdef ARTSEARCH
X  	srchahead = 0;
X
X--- 560,566 -----
X  	    goto normal_search;
X  	}
X  #endif
X! 	else {
X  	    art++;
X  	    if (sub_scan_mode)
X  		goto SubScan;
X***************
X*** 554,559
X  #endif
X  	else
X  	    art++;
X  #ifdef ARTSEARCH
X  	srchahead = 0;
X  #endif
X
X--- 562,570 -----
X  #endif
X  	else {
X  	    art++;
X+ 	    if (sub_scan_mode)
X+ 		goto SubScan;
X+ 	}
X  #ifdef ARTSEARCH
X  	srchahead = 0;
X  #endif
X***************
X*** 615,621
X  	char cmd = *buf;
X  	
X  	reread = TRUE;		/* assume this */
X! 	switch (art_search(buf, (sizeof buf), TRUE)) {
X  	case SRCH_ERROR:
X  	    return AS_ASK;
X  	case SRCH_ABORT:
X
X--- 626,632 -----
X  	char cmd = *buf;
X  	
X  	reread = TRUE;		/* assume this */
X! 	switch (art_search(buf,(sizeof buf),TRUE,sub_scan_mode=='%',TRUE)) {
X  	case SRCH_ERROR:
X  	    return AS_ASK;
X  	case SRCH_ABORT:
X***************
X*** 646,651
X  	    fputs("\n\n\n\nSubject not found.\n",stdout) FLUSH;
X  	    pad(just_a_sec/3);	/* 1/3 second */
X  #endif
X  	    art = firstart;
X  	    reread = FALSE;
X  	    return AS_NORM;
X
X--- 657,664 -----
X  	    fputs("\n\n\n\nSubject not found.\n",stdout) FLUSH;
X  	    pad(just_a_sec/3);	/* 1/3 second */
X  #endif
X+ 	    if (sub_scan_mode)		/* return to SubScan */
X+ 		goto SubScan;
X  	    art = firstart;
X  	    reread = FALSE;
X  	    return AS_NORM;
X***************
X*** 666,671
X      return AS_ASK;
X  #endif
X      case 'u':			/* unsubscribe from this newsgroup? */
X  	rcchar[ng] = NEGCHAR;
X  	return AS_CLEAN;
X      case 'M':
X
X--- 679,685 -----
X      return AS_ASK;
X  #endif
X      case 'u':			/* unsubscribe from this newsgroup? */
X+ 	sub_scan_mode = 0;
X  	rcchar[ng] = NEGCHAR;
X  	return AS_CLEAN;
X      case 'M':
X***************
X*** 735,740
X  	    yankback();
X  #endif
X  	if (*buf == 'u') {
X  	    rcchar[ng] = NEGCHAR;
X  	    return AS_CLEAN;
X  	}
X
X--- 749,755 -----
X  	    yankback();
X  #endif
X  	if (*buf == 'u') {
X+ 	    sub_scan_mode = 0;
X  	    rcchar[ng] = NEGCHAR;
X  	    return AS_CLEAN;
X  	}
X***************
X*** 745,750
X  	exit_code = NG_ASK;
X  	/* FALL THROUGH */
X      case 'q':			/* go back up to newsgroup level? */
X  	return AS_CLEAN;
X      case 'j':
X  	putchar('\n') FLUSH;
X
X--- 760,767 -----
X  	exit_code = NG_ASK;
X  	/* FALL THROUGH */
X      case 'q':			/* go back up to newsgroup level? */
X+ 	if (sub_scan_mode)
X+ 	    goto SubScan;
X  	return AS_CLEAN;
X      case 'j':
X  	putchar('\n') FLUSH;
X***************
X*** 826,831
X  	art = oldart;
X  	return AS_ASK;
X      }
X      case '^':
X  	art = firstart;
X  #ifdef ARTSEARCH
X
X--- 843,1222 -----
X  	art = oldart;
X  	return AS_ASK;
X      }
X+ #ifdef CACHESUBJ
X+ 					/* SubScan			     */
X+ 					/* MODIFICATION BELOW BY TODD DAY    */
X+ 					/* based on concepts by Steve Lemke  */
X+ 					/* and Paul Traina.
X+ 					/* ';' will now bring up full screen */
X+ 					/* interface for easily selecting    */
X+ 					/* articles to read and delete.      */
X+ 					/* '%' does same, but to read        */
X+ 					/* articles, also.		     */
X+     case '%':
X+     case ';':
X+ 	sub_scan_mode = 0;		/* entry from menu */
X+ SubScan:
X+ 	{
X+ 	char tmpbuf[256];		/* max 256 col terminal */
X+ 	static ART_NUM oldfirstart, oldart;
X+ 	int cap, hi_ptr, not_clear, tmp;
X+ 	static ART_NUM arts[256];	/* max 256 line terminal */
X+ 	char buf_cmd, cmd, *subjline = getval("SUBJLINE",Nullch);
X+ 
X+ 	if (!smart_term) {		/* die if term is dumb */
X+ 	    printf("\nSorry, terminal not powerful enough.\n");
X+ 	    return AS_ASK;
X+ 	}
X+ 
X+ 	if (sub_scan_mode)		/* recover cmd */
X+ 	    buf_cmd = sub_scan_mode;
X+ 	else {
X+ 	    buf_cmd = *buf;
X+ 	    oldfirstart = firstart;
X+ 	    oldart = art;
X+ 	}
X+ 					/* search for more threads to read */
X+ 	if (sub_scan_mode && xmarked && *buf != ';' && *buf != '%') {
X+ 	    for (tmp = xmarked; tmp <= lastart; tmp++) {
X+ 		if ( (buf_cmd == '%' || !was_read(tmp)) && x_marked(tmp) ) {
X+ 		    xmarked = art = tmp;
X+ 		    goto Read;
X+ 		}
X+ 		    
X+ 	    }
X+ 	    xmarked = FALSE;
X+ 	}
X+ 	sub_scan_mode = 0;		/* turn off thread return mode */
X+ 	
X+ 	if (!subj_list)
X+ 	    fetchsubj(art,TRUE,FALSE);
X+ 
X+ Swap:	if (buf_cmd == '%') {
X+ 	    oldfirstart = firstart;	/* save first unread article */
X+ 	    firstart = absfirst;	/* set to real first article */
X+ 	}
X+ 	else
X+ 	    firstart = oldfirstart;	/* set to first unread article */
X+ Top:	hi_ptr = 0;
X+ 	cmd = ' ';
X+ 	if (percent_art < firstart)
X+ 	    percent_art = firstart;
X+ 
X+ 	for (i=percent_art; i<=lastart; i++) {
X+ 					/* fill page */
X+ 	    not_clear = TRUE;		/* screen not clear */
X+ 	    cap = 0;
X+ 	    percent_art = i;		/* update last top article */
X+ 	    do {
X+ ClrEOS:		if ( (buf_cmd == '%' || !was_read(i)) &&
X+ 		  (subj_list[OFFSET(i)] != Nullch || fetchsubj(i,FALSE,FALSE))
X+ 		  && *subj_list[OFFSET(i)]) {
X+ 					/* save article number */
X+ 		    arts[cap++] = i;
X+ 					/* print article subject */	
X+ 		    sprintf(tmpbuf,"  %c%5ld ", x_marked(i)?'*':' ',i);
X+ 		    safecpy(tmpbuf + 9, subj_list[OFFSET(i)], COLS - 10);
X+ 		    if (not_clear) {	/* screen need clearing? */
X+ 			clear();
X+ 			not_clear = FALSE;
X+ 		    }
X+ 		    printf("%s\n", tmpbuf) FLUSH;
X+ 		}
X+ 		i++;
X+ 					/* stop if end of screen */
X+ 	    } while (cap < LINES-1 && i <= lastart);
X+ 	    i--;
X+ 
X+ 	    if (hi_ptr == -3)		/* last command was 'd' (del) */
X+ 		hi_ptr = cap - 1;
X+ 	    else if (hi_ptr == -2) {	/* last command was (prev) */
X+ 		if (cap <= 0) {		/* nothing on screen */
X+ 		    clear();
X+ 		    sub_scan_mode = buf_cmd;
X+ 		    exit_code = 'n';	/* goto next news group */
X+ 		    return AS_CLEAN;
X+ 		}
X+ 	    	hi_ptr = cap - 1;
X+ 		if (cmd == 'k' || cmd == 'd')
X+ 		    cur_art_ptr = hi_ptr;
X+ 	    }
X+ 	    else {			/* last command was (next) */
X+ 		hi_ptr = cap - 1;
X+ 		if (cmd == 'j')
X+ 		    cur_art_ptr = 0;
X+ 	    }
X+ 
X+ 	    if (cap <= 0) {		/* oh oh! no articles on screen */
X+ 		if (cmd == 'j' || cmd == 'n') {
X+ 		    cur_art_ptr = hi_ptr = LINES-2;
X+ 		    i = arts[cur_art_ptr];/* bottom of screen */
X+ 		    goto Skip;
X+ 		}
X+ 		else
X+ 		    goto Prev;		/* back up one page if current empty */
X+ 	    }
X+ 
X+ 	    if (cur_art_ptr > hi_ptr)
X+ 		cur_art_ptr = hi_ptr;
X+ 
X+ RedoBt:	    standout();
X+ 	    printf("%s", ngname);
X+ 	    un_standout();
X+ 	    printf(" %s", buf_cmd=='%' ? "all" : "unread");
X+ #ifdef VERBOSE
X+ 	    if (verbose)
X+ 		printf(" articles");
X+ #endif
X+ 	    if (dfltcmd[0] == '^' || srchahead || scanon) {
X+ 		dfltcmd = "^Nnpq";
X+ 		srchahead = -1;
X+ 		printf(", follow threads");
X+ 	    }
X+ 	    else {
X+ 		dfltcmd = "npq";
X+ 		srchahead = 0;
X+ 	    }
X+ Place:					/* place cursor */
X+ 	    home_cursor();
X+ 	    for (tmp = 0; tmp < cur_art_ptr; tmp++)
X+ 		tputs(DO, 1, putchr);
X+ 	    printf(">");
X+ 
X+ Skip:	    fflush(stdout);
X+ 	    eat_typeahead();
X+ 					/* scan keyboard, do cmds */
X+ 	    do {
X+ 		collect_subjects();	/* get more subjs in background */
X+ 		getcmd(tmpbuf);
X+ 		cmd = tmpbuf[0];
X+      		switch(cmd) {
X+ 		    case 'f':
X+ 			if (dfltcmd[0] == '^')
X+ 			    dfltcmd = "npq";
X+ 			else
X+ 			    dfltcmd = "^Nnpq";
X+ 			home_cursor();
X+ 			for (tmp = 0; tmp <= hi_ptr; tmp++)
X+ 			    tputs(DO, 1, putchr);
X+ 			printf("                                                                             \r");
X+ 			goto RedoBt;
X+ 		    case '>':
X+ 			cmd = 'N';
X+ 		    case '<':
X+ 			if (cmd == '<')
X+ 			    cmd = 'P';
X+ 		    case 'N':
X+ 		    case 'P':
X+ 			clear();
X+ 			sub_scan_mode = buf_cmd;
X+ 			exit_code = tolower(cmd);
X+ 			return AS_CLEAN;
X+ 		    case 'c':
X+ 			for (tmp = OFFSET(firstart)/BITSPERBYTE; tmp<ctlsize;
X+ 			  tmp++)
X+ 			    xmark[tmp] = 0;
X+ 			xmarked = FALSE;
X+ 			goto Top;
X+ 		    case 'x':
X+ 			art = arts[cur_art_ptr];
X+ 			if (x_marked(art)) {	/* already marked? */
X+ 			    x_clear(art);
X+ 			    printf("  \r>");
X+ 			}
X+ 			else {			/* not marked yet */
X+ 			    x_set(art);
X+ 			    printf(" *\r>");
X+ 			    xmarked = TRUE;	/* we have marked something */
X+ 			}
X+ 			fflush(stdout);
X+ 			continue;
X+ 		    case '%':
X+ 		    case ';':
X+ 			if (buf_cmd == cmd)
X+ 			    continue;	/* we are in this mode already */
X+ 			buf_cmd = cmd;	/* swap modes */
X+ 			goto Swap;
X+ 		    case 'h': 		/* help */
X+ 			clear();
X+ 			if ((tmp = help_sub_scan()) > 0)
X+ 			    pushchar(tmp);
X+ 		    case '':		/* redraw screen */
X+ 			goto Top;
X+ 		    case '/':		/* do search */
X+ 		    case '?':
X+ 			buf[0] = cmd;
X+ 			buf[1] = FINISHCMD;
X+ 			buf[2] = '\0';
X+ 			art = arts[cur_art_ptr];
X+ 			home_cursor();
X+ 			for (tmp = 0; tmp <= hi_ptr; tmp++)
X+ 			    tputs(DO, 1, putchr);
X+ 			printf("                                                                             \r");
X+ 			if (art_search(buf, (sizeof buf), TRUE, buf_cmd == '%',
X+ 			  FALSE) == SRCH_FOUND) {
X+ 			    i = art - 1;
X+ 					/* best guess at prev page */
X+ 			    for (tmp = 0, percent_prev = art;
X+ 			      percent_prev > firstart && tmp < LINES;
X+ 				percent_prev--) {
X+ 				if (buf_cmd == '%' || !was_read(percent_prev) )
X+ 				    tmp++;
X+ 			    }
X+ 			    cur_art_ptr = 0;
X+ 			    hi_ptr = -1;
X+ 			    break;
X+ 			}
X+ 			else {
X+ 			    printf("\r");
X+ 			    goto RedoBt;
X+ 			}
X+ 		    case 'T':		/* top of subjects */
X+ 			i = firstart - 1;
X+ 			cur_art_ptr = 0;
X+ 			hi_ptr = -1;
X+ 			break;
X+ 		    case 'B':		/* bottom of subjects */
X+ 					/* find end page */
X+ 			for (tmp = 0, percent_art = lastart;
X+ 			  percent_art > firstart && tmp < LINES-2;
X+ 			  percent_art--) {
X+ 			    if (buf_cmd == '%' || !was_read(percent_art) )
X+ 				tmp++;
X+ 			}
X+ 					/* best guess at prev page */
X+ 			for (tmp = 0, percent_prev = percent_art;
X+ 			  percent_prev > firstart && tmp < LINES-1;
X+ 			  percent_prev--) {
X+ 			    if (buf_cmd == '%' || !was_read(percent_prev) )
X+ 				tmp++;
X+ 			}
X+ 			cur_art_ptr = LINES;
X+ 			goto Top;
X+ 		    case 't':		/* top of page */
X+ 			cur_art_ptr = 0;
X+ 			rubout();
X+ 			goto Place;	/* move cursor */
X+ 		    case 'b':		/* bottom of directory */
X+ 			cur_art_ptr = hi_ptr;
X+ 			rubout();
X+ 			goto Place;	/* move cursor */
X+ 		    case 'd':		/* mark arts as read */
X+ 			if (buf_cmd == '%')
X+ 			    continue;	/* disable for % mode */
X+ 			tmpbuf[0] = 'k';/* kill */
X+ 			tmpbuf[1] = '\0';
X+ 			printf("\r");	/* clear to end of screen */
X+ 			tputs(CD, 1, putchr);
X+ 			printf("Marking subject as read...");
X+ 			art = arts[cur_art_ptr];
X+ 			i = art;	/* redraw page at current pos */
X+ 			cap = cur_art_ptr;
X+ 			fflush(stdout);
X+ 			art_search(tmpbuf, sizeof(tmpbuf), FALSE, FALSE, FALSE);
X+ 			hi_ptr = -3;
X+ 			printf("\r");
X+ 			tputs(CD, 1, putchr);
X+ 			goto ClrEOS;
X+ 		    case 'j':		/* go down */
X+ 			if (cur_art_ptr < hi_ptr) {
X+ 			    cur_art_ptr++;
X+ 			    rubout();
X+ 			    tputs(DO, 1, putchr);
X+ 			    printf(">");
X+ 			}
X+ 			else
X+ 			    goto Next;
X+ 			break;
X+ 		    case 'k':		/* go up */
X+ 			if (cur_art_ptr > 0) {
X+ 			    cur_art_ptr--;
X+ 			    rubout();
X+ 			    tputs(UP, 1, putchr);
X+ 			    printf(">");
X+ 			}
X+ 			else
X+ 			    goto Prev;
X+ 			break;
X+ 		    case 'n':
X+ Next:			if (i >= lastart && cap){/* if at end, ignore request */
X+ 			    home_cursor();
X+ 			    for (tmp = 0; tmp <= hi_ptr; tmp++)
X+ 				tputs(DO, 1, putchr);
X+ 			    printf("                                                                             \r");
X+ 			    standout();
X+ 			    printf("\007End of Subjects");
X+ 			    un_standout();
X+ 			    goto Place;
X+ 			}
X+ 					/* save top of page */
X+ 			percent_prev = percent_art;
X+ 			hi_ptr = -1;	/* quit do loop */
X+ 			break;
X+ 		    case 'p':
X+ Prev:			if (percent_art <= firstart && cap) {
X+ 			    home_cursor();
X+ 			    for (tmp = 0; tmp <= hi_ptr; tmp++)
X+ 				tputs(DO, 1, putchr);
X+ 			    printf("                                                                             \r");
X+ 			    standout();
X+ 			    printf("\007Beginning of Subjects");
X+ 			    un_standout();
X+ 			    goto Place;
X+ 			}
X+ 			i = percent_prev - 1;
X+ 			if (i < firstart)
X+ 			    i = firstart - 1;
X+ 					/* best guess at prev page */
X+ 			for (tmp = 0;
X+ 			  percent_prev > firstart && tmp < LINES-1;
X+ 			  percent_prev--) {
X+ 			    if (buf_cmd == '%' || !was_read(percent_prev) )
X+ 				tmp++;
X+ 			}
X+ 			hi_ptr = -2;	/* quit do loop */
X+ 			break;
X+ 		    case 'r':		/* read article */
X+ 		    case '\n':
X+ 		    case '\r':
X+ 		    case ' ':
X+ 			art = arts[cur_art_ptr];
X+ 			if (xmarked) {
X+ 			    x_set(art);
X+ 			    xmarked = FALSE;
X+ 	    		    for (tmp = firstart; tmp <= lastart; tmp++) {
X+ 				if ( (buf_cmd == '%' || !was_read(tmp))
X+ 				  && x_marked(tmp) ) {
X+ 				    xmarked = art = tmp;
X+ 				    break;
X+ 				}
X+ 	    		    }
X+ 			}
X+ Read:			reread = TRUE;
X+ 			if (xmarked)
X+ 			    xmarked++;
X+ 			sub_scan_mode = buf_cmd;/* return from threads */
X+ 			return AS_NORM;	/* print art */
X+ 		    case 'q':		/* quit do and for loop */
X+ 			hi_ptr = -4;
X+ 			break;
X+ 		}
X+ 		fflush(stdout);
X+ 	    } while (hi_ptr >= 0);
X+ 					/* exit huge for-loop on quit */
X+ 	    if (hi_ptr == -4)
X+ 		break;
X+ 	}
X+ 	clear();
X+ 	int_count = sub_scan_mode = 0;
X+ 	art = oldart;
X+ 	firstart = oldfirstart;
X+ 	printf("\nEnd of subject scan.\n") FLUSH;
X+ 	return AS_CLEAN;
X+     }
X+ #endif
X+ 
X+ 
X      case '^':
X  	art = firstart;
X  #ifdef ARTSEARCH
Xdiff -c rn40/ng.h rn40.todd/ng.h
X*** rn40/ng.h	Fri Nov 21 12:37:52 1986
X--- rn40.todd/ng.h	Thu Dec  8 13:37:04 1988
X***************
X*** 8,13
X  
X  EXT ART_NUM art INIT(0);	/* current or prospective article # */
X  
X  EXT int checkcount INIT(0);	/* how many articles have we read */
X  			/*   in the current newsgroup since */
X  			/*   the last checkpoint? */
X
X--- 8,18 -----
X  
X  EXT ART_NUM art INIT(0);	/* current or prospective article # */
X  
X+ EXT ART_NUM percent_art INIT(0); /* last top article displayed by '%' & ';' */
X+ EXT ART_NUM percent_prev INIT(0);/* prev top article displayed by '%' & ';' */
X+ EXT ART_NUM cur_art_ptr INIT(0); /* current (or last) pointed article */
X+ EXT int sub_scan_mode INIT(0);	 /* check for return from threads */
X+ 
X  EXT int checkcount INIT(0);	/* how many articles have we read */
X  			/*   in the current newsgroup since */
X  			/*   the last checkpoint? */
Xdiff -c rn40/ngstuff.c rn40.todd/ngstuff.c
X*** rn40/ngstuff.c	Fri Nov 21 13:22:16 1986
X--- rn40.todd/ngstuff.c	Fri Dec 16 17:52:46 1988
X***************
X*** 192,198
X  	}
X  	check_first(min);
X  	for (art=min; art<=max; art++) {
X! 	    if (perform(cmdlst,TRUE)) {
X  #ifdef VERBOSE
X  		IF(verbose)
X  		    printf("\n(Interrupted at article %ld)\n",(long)art)
X
X--- 192,198 -----
X  	}
X  	check_first(min);
X  	for (art=min; art<=max; art++) {
X! 	    if (perform(cmdlst,TRUE,TRUE)) {
X  #ifdef VERBOSE
X  		IF(verbose)
X  		    printf("\n(Interrupted at article %ld)\n",(long)art)
X***************
X*** 215,221
X  }
X  
X  int
X! perform(cmdlst,toplevel)
X  register char *cmdlst;
X  int toplevel;
X  {
X
X--- 215,221 -----
X  }
X  
X  int
X! perform(cmdlst,toplevel,print_msg)
X  register char *cmdlst;
X  int toplevel;
X  int print_msg;
X***************
X*** 218,223
X  perform(cmdlst,toplevel)
X  register char *cmdlst;
X  int toplevel;
X  {
X      register int ch;
X      
X
X--- 218,224 -----
X  perform(cmdlst,toplevel,print_msg)
X  register char *cmdlst;
X  int toplevel;
X+ int print_msg;
X  {
X      register int ch;
X      
X***************
X*** 221,227
X  {
X      register int ch;
X      
X!     if (toplevel) {
X  	printf("%-6ld",art);
X  	fflush(stdout);
X      }
X
X--- 222,228 -----
X  {
X      register int ch;
X      
X!     if (toplevel && print_msg) {
X  	printf("%-6ld",art);
X  	fflush(stdout);
X      }
X***************
X*** 232,238
X  	    if (!was_read(art)) {
X  		mark_as_read(art);
X  #ifdef VERBOSE
X! 		IF(verbose)
X  		    fputs("\tJunked",stdout);
X  #endif
X  	    }
X
X--- 233,239 -----
X  	    if (!was_read(art)) {
X  		mark_as_read(art);
X  #ifdef VERBOSE
X! 		IF(verbose && print_msg)
X  		    fputs("\tJunked",stdout);
X  #endif
X  	    }
X***************
X*** 241,247
X  	    if (was_read(art)) {
X  		unmark_as_read(art);
X  #ifdef VERBOSE
X! 		IF(verbose)
X  		    fputs("\tMarked unread",stdout);
X  #endif
X  	    }
X
X--- 242,248 -----
X  	    if (was_read(art)) {
X  		unmark_as_read(art);
X  #ifdef VERBOSE
X! 		IF(verbose && print_msg)
X  		    fputs("\tMarked unread",stdout);
X  #endif
X  	    }
X***************
X*** 250,256
X  #ifdef DELAYMARK
X  	    delay_unmark(art);
X  #ifdef VERBOSE
X! 		IF(verbose)
X  		    fputs("\tWill return",stdout);
X  #endif
X  #else
X
X--- 251,257 -----
X  #ifdef DELAYMARK
X  	    delay_unmark(art);
X  #ifdef VERBOSE
X! 		IF(verbose && print_msg)
X  		    fputs("\tWill return",stdout);
X  #endif
X  #else
X***************
X*** 265,271
X  		;
X  	    ELSE
X  #endif
X! 		putchar('\n') FLUSH;		/* ghad! */
X  	}
X  	else if (ch == 'C') {
X  #ifdef ASYNC_PARSE
X
X--- 266,273 -----
X  		;
X  	    ELSE
X  #endif
X! 		if (print_msg)
X! 		    putchar('\n') FLUSH;	/* ghad! */
X  	}
X  	else if (ch == 'C') {
X  #ifdef ASYNC_PARSE
X***************
X*** 282,288
X  	    cmdlst = dointerp(tmpbuf, (sizeof tmpbuf), cmdlst,":");
X  	    if (*cmdlst != ':')
X  		--cmdlst;
X! 	    if (perform(tmpbuf,FALSE))
X  		return -1;
X  #else
X  	    notincl("%");
X
X--- 284,290 -----
X  	    cmdlst = dointerp(tmpbuf, (sizeof tmpbuf), cmdlst,":");
X  	    if (*cmdlst != ':')
X  		--cmdlst;
X! 	    if (perform(tmpbuf,FALSE,TRUE))
X  		return -1;
X  #else
X  	    notincl("%");
X***************
X*** 319,325
X  	fflush(stdout);
X  #endif
X      }
X!     if (toplevel) {
X  #ifdef VERBOSE
X  	IF(verbose)
X  	    putchar('\n') FLUSH;
X
X--- 321,327 -----
X  	fflush(stdout);
X  #endif
X      }
X!     if (toplevel && print_msg) {
X  #ifdef VERBOSE
X  	IF(verbose)
X  	    putchar('\n') FLUSH;
Xdiff -c rn40/rn.1 rn40.todd/rn.1
X*** rn40/rn.1	Fri Nov 21 13:39:24 1986
X--- rn40.todd/rn.1	Tue Jun 13 23:01:02 1989
X***************
X*** 90,97
X  level.
X  .PP
X  .I Rn
X! operates on three levels: the newsgroup selection level, the article
X! selection level, and the paging level.
X  Each level has its own set of commands, and its own help menu.
X  At the paging level (the bottom level),
X  .I rn
X
X--- 90,97 -----
X  level.
X  .PP
X  .I Rn
X! operates on four levels: the newsgroup selection level, the article
X! selection level, the subject scan level, and the paging level.
X  Each level has its own set of commands, and its own help menu.
X  At the paging level (the bottom level),
X  .I rn
X***************
X*** 101,106
X  At the article selection level, you may specify which article you want
X  next, or read them in the default order, which is either in order of
X  arrival on your system, or by subject threads.
X  At the newsgroup selection level (the top level), you may specify which
X  newsgroup you want next, or read them in the default order, which is the
X  order that the newsgroups occur in your
X
X--- 101,111 -----
X  At the article selection level, you may specify which article you want
X  next, or read them in the default order, which is either in order of
X  arrival on your system, or by subject threads.
X+ At the subject scan level, a list of subjects is displayed and you can
X+ use a screen oriented marker to select what subjects you want to read.
X+ You will follow a thread in the article selection level until it ends,
X+ and at that point, you will
X+ automatically be returned to the subject scan level.
X  At the newsgroup selection level (the top level), you may specify which
X  newsgroup you want next, or read them in the default order, which is the
X  order that the newsgroups occur in your
X***************
X*** 185,190
X  The command will be interpreted as if given on the article selection level.
X  .Ip = 8
X  Do this newsgroup now, but list subjects before displaying articles.
X  .Ip n 8
X  Go to the next newsgroup with unread news.
X  .Ip N 8
X
X--- 190,199 -----
X  The command will be interpreted as if given on the article selection level.
X  .Ip = 8
X  Do this newsgroup now, but list subjects before displaying articles.
X+ .Ip ; 8
X+ Do this newsgroup now, but startup subject display/scan mode of unread articles.
X+ .Ip % 8
X+ Same as ;, but include read articles as well.
X  .Ip n 8
X  Go to the next newsgroup with unread news.
X  .Ip N 8
X***************
X*** 632,637
X  from a range or search command.
X  .Ip = 8
X  List subjects of unread articles.
X  .Ip # 8
X  Print last article number.
X  .Sh "Pager Level"
X
X--- 641,650 -----
X  from a range or search command.
X  .Ip = 8
X  List subjects of unread articles.
X+ .Ip ; 8
X+ Start subject display/scan mode on unread articles.
X+ .Ip % 8
X+ Same as ; but include read articles as well.
X  .Ip # 8
X  Print last article number.
X  .Sp
X***************
X*** 634,639
X  List subjects of unread articles.
X  .Ip # 8
X  Print last article number.
X  .Sh "Pager Level"
X  At the pager level (within an article), the prompt looks like this:
X  .Sp
X
X--- 647,719 -----
X  Same as ; but include read articles as well.
X  .Ip # 8
X  Print last article number.
X+ .Sp
X+ .Sh "Subject Display/Scan Mode"
X+ If your site supports the '-S' option and your terminal is sufficiently
X+ smart, you can take advantage of this mode.  You do not have to have the '-S'
X+ option enabled to use this mode, though it greatly speeds things up.
X+ This mode is invoked by either ';' or '%'.  ';' will use only unread
X+ articles, while '%' will use read articles also.
X+ .PP
X+ After entering this mode, the screen will be cleared and a list of
X+ subjects will be displayed.  The prompt '>' will indicate which subject
X+ you are currently acting on.
X+ .PP
X+ The commands in this section differ greatly from that of the other three
X+ sections.  This is because this section is screen oriented (like 'vi')
X+ and the 'j' and 'k' keys are used for cursor movement.  A detailed description
X+ of the keys is given below:
X+ .Sp
X+ .Ip SP,CR,r 8
X+ Display article, and follow its thread in the Article Selection Level.
X+ Once in the Article Selection Level, you may use any of its commands.
X+ You may return via ';' or '%'.
X+ .Ip f 8
X+ Toggle thread follow mode.
X+ .Ip j 8
X+ Move down to next subject.
X+ .Ip k 8
X+ Move up to previous subject.
X+ .Ip n 8
X+ Display next page of subjects.
X+ .Ip p 8
X+ Display previous page of subjects.
X+ .Ip N,> 8
X+ Go to next unread newsgroup.
X+ .Ip P,< 8
X+ Go to previous unread newsgroup.
X+ .Ip t 8
X+ Move to top of current page.
X+ .Ip b 8
X+ Move to bottom of current page.
X+ .Ip T 8
X+ Move to top of all subjects.
X+ .Ip B 8
X+ Move to bottom of all subjects.
X+ .Ip d 8
X+ Mark all articles with same subject as read.  Same as 'k' at the
X+ Article Selection Level.
X+ .Ip x 8
X+ Mark article for reading.  After returning from a thread read, the
X+ next marked article will be read.
X+ .Ip c 8
X+ Clear all marks (see x).
X+ .Ip /pattern 8
X+ Search for next subject and, if found, put at top of page.  Usage same as
X+ pattern searches at Article Selection Level, including 'header' and 'all'
X+ searches.
X+ .Ip ?pattern 8
X+ Same as /pattern above, except search for previous subject.
X+ .Ip ^L 8
X+ Redraw screen.
X+ .Ip ; 8
X+ Show only unread subjects.  May force you to next unread newsgroup if
X+ all subjects are read.
X+ .Ip % 8
X+ Show all subjects.
X+ .Ip q 8
X+ Quit this level.
X+ .Sp
X  .Sh "Pager Level"
X  At the pager level (within an article), the prompt looks like this:
X  .Sp
X***************
X*** 693,699
X  as if typed to the \*(L"What next?\*(R" prompt at the end of the article.
X  See the documentation at the article selection level for these commands.
X  .Sp	
X!     # $ & / = ? c C f F k K ^K m M r R ^R u v Y ^
X  .br
X      number
X  .br
X
X--- 773,779 -----
X  as if typed to the \*(L"What next?\*(R" prompt at the end of the article.
X  See the documentation at the article selection level for these commands.
X  .Sp	
X!     # $ & / = ; % ? c C f F k K ^K m M r R ^R u v Y ^
X  .br
X      number
X  .br
Xdiff -c rn40/rn.c rn40.todd/rn.c
X*** rn40/rn.c	Fri Nov 21 13:39:26 1986
X--- rn40.todd/rn.c	Wed Dec 21 07:17:36 1988
X***************
X*** 85,90
X  					/*   with no unread news? */
X  	bool retry;			/* cycle back to top of list? */
X  	NG_NUM recent_ng = 0;
X  	
X  	current_ng = 0;
X  	do {
X
X--- 85,91 -----
X  					/*   with no unread news? */
X  	bool retry;			/* cycle back to top of list? */
X  	NG_NUM recent_ng = 0;
X+ 	sub_scan_mode = 0;
X  	
X  	current_ng = 0;
X  	do {
X***************
X*** 174,179
X  			continue;
X  		    }
X  		    dfltcmd = "ynq";
X  #ifdef VERBOSE
X  		    IF(verbose)
X  			sprintf(promptbuf,
X
X--- 175,186 -----
X  			continue;
X  		    }
X  		    dfltcmd = "ynq";
X+ 		    if (sub_scan_mode) {
X+ 			buf[0] = sub_scan_mode;
X+ 			buf[1] = '\0';
X+ 			sub_scan_mode = 0;
X+ 			goto SubGrp;
X+ 		    }
X  #ifdef VERBOSE
X  		    IF(verbose)
X  			sprintf(promptbuf,
X***************
X*** 210,216
X  #ifdef VERIFY
X  		printcmd();
X  #endif
X! 		switch (*buf) {
X  		case 'p':		/* find previous unread newsgroup */
X  		    do {
X  			if (ng <= 0)
X
X--- 217,223 -----
X  #ifdef VERIFY
X  		printcmd();
X  #endif
X! SubGrp:		switch (*buf) {
X  		case 'p':		/* find previous unread newsgroup */
X  		    do {
X  			if (ng <= 0)
X***************
X*** 452,458
X  		    crmode();
X  		    goto reask_newsgroup;
X  		}
X! 		case '.': case '=':
X  		case 'y': case 'Y': /* do normal thing */
X  		    if (ng >= nextrcline) {
X  			fputs("\nNot on a newsgroup.",stdout) FLUSH;
X
X--- 459,465 -----
X  		    crmode();
X  		    goto reask_newsgroup;
X  		}
X! 		case '.': case '=': case ';': case '%':
X  		case 'y': case 'Y': /* do normal thing */
X  		    if (ng >= nextrcline) {
X  			fputs("\nNot on a newsgroup.",stdout) FLUSH;
X***************
X*** 460,465
X  		    }
X  		    if (*buf == '=')
X  			s = savestr("=");
X  		    else if (*buf == '.') {	/* start command? */
X  			if (!finish_command(FALSE)) /* get rest of command */
X  			    goto reinp_newsgroup;
X
X--- 467,476 -----
X  		    }
X  		    if (*buf == '=')
X  			s = savestr("=");
X+ 		    else if (*buf == ';')
X+ 			s = savestr(";");
X+ 		    else if (*buf == '%')
X+ 			s = savestr("%");
X  		    else if (*buf == '.') {	/* start command? */
X  			if (!finish_command(FALSE)) /* get rest of command */
X  			    goto reinp_newsgroup;
X***************
X*** 471,476
X  		    if (toread[ng])
X  			retry = TRUE;
X  		    switch (do_newsgroup(s)) {
X  		    case NG_ERROR:
X  		    case NG_NORM:
X  			ng++;
X
X--- 482,495 -----
X  		    if (toread[ng])
X  			retry = TRUE;
X  		    switch (do_newsgroup(s)) {
X+ 		    case 'p':
X+ 			buf[0] = 'p';
X+ 			buf[1] = '\0';
X+ 			goto SubGrp;
X+ 		    case 'n':
X+ 			buf[0] = 'n';
X+ 			buf[1] = '\0';
X+ 			goto SubGrp;
X  		    case NG_ERROR:
X  		    case NG_NORM:
X  			ng++;
Xdiff -c rn40/term.c rn40.todd/term.c
X*** rn40/term.c	Fri Nov 21 13:39:32 1986
X--- rn40.todd/term.c	Tue Jun 13 22:17:02 1989
X***************
X*** 156,161
X  	    BC = Tgetstr("le");
X      } else
X  	BC = "\b";			/* make a backspace handy */
X      UP = Tgetstr("up");			/* move up a line */
X      if (!*UP)				/* no UP string? */
X  	marking = 0;			/* disable any marking */
X
X--- 156,162 -----
X  	    BC = Tgetstr("le");
X      } else
X  	BC = "\b";			/* make a backspace handy */
X+     DO = Tgetstr("do");			/* move down a line */
X      UP = Tgetstr("up");			/* move up a line */
X      if (!*UP)				/* no UP string? */
X  	marking = 0;			/* disable any marking */
X***************
X*** 164,169
X      else
X  	CL = Tgetstr("cl");		/* get clear string */
X      CE = Tgetstr("ce");			/* clear to end of line string */
X  #ifdef CLEAREOL
X      CM = Tgetstr("cm");			/* cursor motion - PWP */
X      HO = Tgetstr("ho");			/* home cursor if no CM - PWP */
X
X--- 165,172 -----
X      else
X  	CL = Tgetstr("cl");		/* get clear string */
X      CE = Tgetstr("ce");			/* clear to end of line string */
X+     CD = Tgetstr("cd");			/* clear to end of display - PWP */
X+     smart_term = *DO && *UP && *CD;	/* necessary for sub disp/scan */
X  #ifdef CLEAREOL
X      CM = Tgetstr("cm");			/* cursor motion - PWP */
X      HO = Tgetstr("ho");			/* home cursor if no CM - PWP */
X***************
X*** 167,173
X  #ifdef CLEAREOL
X      CM = Tgetstr("cm");			/* cursor motion - PWP */
X      HO = Tgetstr("ho");			/* home cursor if no CM - PWP */
X-     CD = Tgetstr("cd");			/* clear to end of display - PWP */
X      if (!*CE || !*CD || (!*CM && !*HO))	/* can we CE, CD, and home? */
X  	can_home_clear = FALSE;		/*  no, so disable use of clear eol */
X  #endif CLEAREOL
X
X--- 170,175 -----
X  #ifdef CLEAREOL
X      CM = Tgetstr("cm");			/* cursor motion - PWP */
X      HO = Tgetstr("ho");			/* home cursor if no CM - PWP */
X      if (!*CE || !*CD || (!*CM && !*HO))	/* can we CE, CD, and home? */
X  	can_home_clear = FALSE;		/*  no, so disable use of clear eol */
X  #endif CLEAREOL
Xdiff -c rn40/term.h rn40.todd/term.h
X*** rn40/term.h	Fri Nov 21 13:23:06 1986
X--- rn40.todd/term.h	Sat Dec 17 09:12:50 1988
X***************
X*** 136,141
X   */
X  
X  #ifdef HAVETERMLIB
X  EXT char *BC INIT(Nullch);		/* backspace character */
X  EXT char *UP INIT(Nullch);		/* move cursor up one line */
X  EXT char *CR INIT(Nullch);		/* get to left margin, somehow */
X
X--- 136,142 -----
X   */
X  
X  #ifdef HAVETERMLIB
X+ EXT int smart_term INIT(FALSE);		/* do we have smart_terminal? */
X  EXT char *BC INIT(Nullch);		/* backspace character */
X  EXT char *DO INIT(Nullch);		/* move cursor down one line */
X  EXT char *UP INIT(Nullch);		/* move cursor up one line */
X***************
X*** 137,142
X  
X  #ifdef HAVETERMLIB
X  EXT char *BC INIT(Nullch);		/* backspace character */
X  EXT char *UP INIT(Nullch);		/* move cursor up one line */
X  EXT char *CR INIT(Nullch);		/* get to left margin, somehow */
X  EXT char *VB INIT(Nullch);		/* visible bell */
X
X--- 138,144 -----
X  #ifdef HAVETERMLIB
X  EXT int smart_term INIT(FALSE);		/* do we have smart_terminal? */
X  EXT char *BC INIT(Nullch);		/* backspace character */
X+ EXT char *DO INIT(Nullch);		/* move cursor down one line */
X  EXT char *UP INIT(Nullch);		/* move cursor up one line */
X  EXT char *CR INIT(Nullch);		/* get to left margin, somehow */
X  EXT char *VB INIT(Nullch);		/* visible bell */
X***************
X*** 141,149
X  EXT char *CR INIT(Nullch);		/* get to left margin, somehow */
X  EXT char *VB INIT(Nullch);		/* visible bell */
X  EXT char *CL INIT(Nullch);		/* home and clear screen */
X- EXT char *CE INIT(Nullch);		/* clear to end of line */
X- #ifdef CLEAREOL
X- EXT char *CM INIT(Nullch);		/* cursor motion -- PWP */
X  EXT char *HO INIT(Nullch);		/* home cursor -- PWP */
X  EXT char *CD INIT(Nullch);		/* clear to end of display -- PWP */
X  #endif CLEAREOL
X
X--- 143,148 -----
X  EXT char *CR INIT(Nullch);		/* get to left margin, somehow */
X  EXT char *VB INIT(Nullch);		/* visible bell */
X  EXT char *CL INIT(Nullch);		/* home and clear screen */
X  EXT char *HO INIT(Nullch);		/* home cursor -- PWP */
X  EXT char *CE INIT(Nullch);		/* clear to end of line */
X  EXT char *CD INIT(Nullch);		/* clear to end of display -- PWP */
X***************
X*** 145,150
X  #ifdef CLEAREOL
X  EXT char *CM INIT(Nullch);		/* cursor motion -- PWP */
X  EXT char *HO INIT(Nullch);		/* home cursor -- PWP */
X  EXT char *CD INIT(Nullch);		/* clear to end of display -- PWP */
X  #endif CLEAREOL
X  EXT char *SO INIT(Nullch);		/* begin standout mode */
X
X--- 144,150 -----
X  EXT char *VB INIT(Nullch);		/* visible bell */
X  EXT char *CL INIT(Nullch);		/* home and clear screen */
X  EXT char *HO INIT(Nullch);		/* home cursor -- PWP */
X+ EXT char *CE INIT(Nullch);		/* clear to end of line */
X  EXT char *CD INIT(Nullch);		/* clear to end of display -- PWP */
X  EXT char *CM INIT(Nullch);		/* cursor motion -- PWP */
X  EXT char *SO INIT(Nullch);		/* begin standout mode */
X***************
X*** 146,152
X  EXT char *CM INIT(Nullch);		/* cursor motion -- PWP */
X  EXT char *HO INIT(Nullch);		/* home cursor -- PWP */
X  EXT char *CD INIT(Nullch);		/* clear to end of display -- PWP */
X! #endif CLEAREOL
X  EXT char *SO INIT(Nullch);		/* begin standout mode */
X  EXT char *SE INIT(Nullch);		/* end standout mode */
X  EXT int SG INIT(0);		/* blanks left by SO and SE */
X
X--- 146,152 -----
X  EXT char *HO INIT(Nullch);		/* home cursor -- PWP */
X  EXT char *CE INIT(Nullch);		/* clear to end of line */
X  EXT char *CD INIT(Nullch);		/* clear to end of display -- PWP */
X! EXT char *CM INIT(Nullch);		/* cursor motion -- PWP */
X  EXT char *SO INIT(Nullch);		/* begin standout mode */
X  EXT char *SE INIT(Nullch);		/* end standout mode */
X  EXT int SG INIT(0);		/* blanks left by SO and SE */
!FaR!OuT!
exit
-- 

Todd Day | todd@ivucsb.sba.ca.us | ivucsb!todd@anise.acc.com
"Santa Barbara - so many babes... so few who will talk to me."