--------
RCS file: RCS/config.h,v
retrieving revision 6.0
diff -c -r6.0 config.h
*** /tmp/,RCSt1029201	Sat May 28 13:07:53 1988
--- config.h	Mon Apr 11 17:35:21 1988
***************
*** 41,46
  #define NOJOB_FG 1
  
  /*
  ** arrow key treatment.  If PAGEARROW is defined, right and left arrow
  ** keys will be synonyms for <return> (next-page) and <backspace> (previous).
  ** Otherwise, the right arrow will function as down, and the left as up.

--- 41,57 -----
  #define NOJOB_FG 1
  
  /*
+ ** bit mask for interpreting command characters.  Set it to 0xff, and
+ ** we should be able to handle 8 bit characters for control keys -
+ ** leaving it 0x7f protects against possible parity bits in ascii
+ ** characters.  A lot of the general paranoia about character handling
+ ** in raw mode comes from one of the earliest versions which was
+ ** run on an amdahl using an IBM series 1 front end - it had a very
+ ** brain damaged implementation of ioctl().
+ */
+ #define CHMASK 0x7f
+ 
+ /*
  ** arrow key treatment.  If PAGEARROW is defined, right and left arrow
  ** keys will be synonyms for <return> (next-page) and <backspace> (previous).
  ** Otherwise, the right arrow will function as down, and the left as up.
===================================================================
RCS file: RCS/envir_set.c,v
retrieving revision 6.0
diff -c -r6.0 envir_set.c
*** /tmp/,RCSt1029201	Sat May 28 13:07:55 1988
--- envir_set.c	Mon Apr 11 17:40:10 1988
***************
*** 111,117
  	char in,out,*ptr;
  	char *index(), xln_str();
  
! 	for (i=0; i < 128; ++i)
  		Cxitop[i] = Cxitor[i] = Cxptoi[i] = Cxrtoi[i] = i;
  
  	if ((fp = fopen(fname,"r")) != NULL)

--- 111,117 -----
  	char in,out,*ptr;
  	char *index(), xln_str();
  
! 	for (i=0; i < CHMASK+1; ++i)
  		Cxitop[i] = Cxitor[i] = Cxptoi[i] = Cxrtoi[i] = i;
  
  	if ((fp = fopen(fname,"r")) != NULL)
***************
*** 152,157
  char *s;
  {
  	if (*s < '0' || *s > '9')
! 		return(*s & 0x7f);
! 	return((char)(atoi(s) & 0x7f));
  }

--- 152,157 -----
  char *s;
  {
  	if (*s < '0' || *s > '9')
! 		return(*s & CHMASK);
! 	return((char)(atoi(s) & CHMASK));
  }
===================================================================
RCS file: RCS/getch.c,v
retrieving revision 6.0
diff -c -r6.0 getch.c
*** /tmp/,RCSt1029201	Sat May 28 13:07:56 1988
--- getch.c	Mon Apr 11 17:40:18 1988
***************
*** 7,12
  */
  #include <stdio.h>
  #include <setjmp.h>
  #include "config.h"
  #include "vn.h"
  

--- 7,13 -----
  */
  #include <stdio.h>
  #include <setjmp.h>
+ #include <ctype.h>
  #include "config.h"
  #include "vn.h"
  
***************
*** 27,33
  	static char	ckseq[32];
  
  	/* Check for leading count */
! 	for (i = 0; (*c = getchar() & 0x7f) >= '0' && *c <= '9'; i = i * 10 + *c - '0')
  		;
  
  	/* @#$!!! flakey front ends that won't map newlines in raw mode */

--- 28,34 -----
  	static char	ckseq[32];
  
  	/* Check for leading count */
!  	for (i = 0; isdigit(*c = getchar() & CHMASK); i = i * 10 + *c - '0')
  		;
  
  	/* @#$!!! flakey front ends that won't map newlines in raw mode */
***************
*** 54,60
  			if( strcmp(ckseq, Kl) == 0 ) { *c = UP; break; }
  			if( strcmp(ckseq, Kr) == 0 ) { *c = DOWN; break; }
  #endif
! 			*c = (getchar() & 0x7f);
  			ckseq[++j] = *c; ckseq[j+1] = '\0';
  		}
  	}

--- 55,61 -----
  			if( strcmp(ckseq, Kl) == 0 ) { *c = UP; break; }
  			if( strcmp(ckseq, Kr) == 0 ) { *c = DOWN; break; }
  #endif
! 			*c = (getchar() & CHMASK);
  			ckseq[++j] = *c; ckseq[j+1] = '\0';
  		}
  	}
***************
*** 73,79
  getnoctl ()
  {
  	char c;
! 	while ((c = getchar() & 0x7f) < ' ' || c == '\177')
  	{
  		if (c == '\015' || c == '\012')
  			c = '\n';

--- 74,80 -----
  getnoctl ()
  {
  	char c;
!  	while (iscntrl(c = getchar() & CHMASK))
  	{
  		if (c == '\015' || c == '\012')
  			c = '\n';
===================================================================
RCS file: RCS/help.c,v
retrieving revision 6.0
diff -c -r6.0 help.c
*** /tmp/,RCSt1029201	Sat May 28 13:07:59 1988
--- help.c	Tue Apr 12 10:51:21 1988
***************
*** 21,26
  extern char *Contstr;
  extern char Cxptoi[], Cxrtoi[];
  
  /*
  	Help message table.  Character for command, plus its help
  	message.  Table order is order of presentation to user.

--- 21,29 -----
  extern char *Contstr;
  extern char Cxptoi[], Cxrtoi[];
  
+ extern int (*Hookfunc)();
+ extern char *(*Hookhelp)();
+ 
  /*
  	Help message table.  Character for command, plus its help
  	message.  Table order is order of presentation to user.
***************
*** 43,48
  	{ BACK, "previous page [number of pages]", 1, NULL},
  	{ FORWARD, "next page [number of pages]", 1, NULL},
  #endif
  	{ TOPMOVE, "move to top of page", 1, NULL},
  	{ BOTMOVE, "move to bottom of page", 1, NULL},
  	{ ALTBOTTOM, "move to bottom of page (alternate L)", 1, NULL},

--- 46,53 -----
  	{ BACK, "previous page [number of pages]", 1, NULL},
  	{ FORWARD, "next page [number of pages]", 1, NULL},
  #endif
+ 	{ GRPBACK, "previous newsgroup [number of newsgroups]", 0, NULL },
+ 	{ GRPFORWARD, "next newsgroup [number of newsgroups]", 0, NULL },
  	{ TOPMOVE, "move to top of page", 1, NULL},
  	{ BOTMOVE, "move to bottom of page", 1, NULL},
  	{ ALTBOTTOM, "move to bottom of page (alternate L)", 1, NULL},
***************
*** 71,76
  	{ MARK, "mark/unmark article [number of articles]", 1, NULL},
  	{ ART_MARK, "mark/unmark article [number of articles]", 1, NULL},
  	{ UNMARK, "erase marks on articles", 1, NULL},
  	{ HEADTOG, "toggle flag for display of headers when reading", 1, NULL},
  	{ SETROT, "toggle rotation for reading", 1, NULL},
  	{ REDRAW, "redraw screen", 1, NULL},

--- 76,82 -----
  	{ MARK, "mark/unmark article [number of articles]", 1, NULL},
  	{ ART_MARK, "mark/unmark article [number of articles]", 1, NULL},
  	{ UNMARK, "erase marks on articles", 1, NULL},
+ 	{ MARKSTRING, "specify articles to mark/unmark", 1, NULL},
  	{ HEADTOG, "toggle flag for display of headers when reading", 1, NULL},
  	{ SETROT, "toggle rotation for reading", 1, NULL},
  	{ REDRAW, "redraw screen", 1, NULL},
***************
*** 86,92
  */
  help ()
  {
! 	int i,lcount,lim; 
  	term_set (ERASE);
  	lim = L_allow + RECBIAS - 2;
  	printf("%s\n",HELP_HEAD);

--- 92,101 -----
  */
  help ()
  {
! 	int i,lcount,lim;
! 	char *hs;
! 	char c;
! 
  	term_set (ERASE);
  	lim = L_allow + RECBIAS - 2;
  	printf("%s\n",HELP_HEAD);
***************
*** 91,97
  	lim = L_allow + RECBIAS - 2;
  	printf("%s\n",HELP_HEAD);
  	lcount = HHLINES;
! 	for (i=0; i < (sizeof(Helptab))/(sizeof(struct HELPTAB)); ++i)
  	{
  		if (Digest && !(Helptab[i].dig))
  			continue;

--- 100,106 -----
  	lim = L_allow + RECBIAS - 2;
  	printf("%s\n",HELP_HEAD);
  	lcount = HHLINES;
! 	for (i=0; i < HTSIZE; ++i)
  	{
  		if (Digest && !(Helptab[i].dig))
  			continue;
***************
*** 95,100
  	{
  		if (Digest && !(Helptab[i].dig))
  			continue;
  		++lcount;
  		if (Digest && Helptab[i].amsg != NULL)
  			h_print (Cxptoi[Helptab[i].cmd],Helptab[i].amsg);

--- 104,111 -----
  	{
  		if (Digest && !(Helptab[i].dig))
  			continue;
+ 		if (Hookfunc != NULL && (*Hookfunc)(Helptab[i].cmd,0,0) >= 0)
+ 			continue;
  		++lcount;
  		if (Digest && Helptab[i].amsg != NULL)
  			h_print (Cxptoi[Helptab[i].cmd],Helptab[i].amsg);
***************
*** 111,116
  			lcount = 0;
  		}
  	}
  	if (lcount > 0)
  	{
  		printf ("\n%s",Contstr);

--- 122,146 -----
  			lcount = 0;
  		}
  	}
+ 	if (Hookhelp != NULL)
+ 	{
+ 		for (hs=(*Hookhelp)(0,1,&c);
+ 				hs != NULL; hs = (*Hookhelp)(0,0,&c))
+ 		{
+ 			++lcount;
+ 			h_print (Cxptoi[c],hs);
+ 			if (lcount >= lim)
+ 			{
+ 				printf ("\n%s",Contstr);
+ 				getnoctl ();
+ 				term_set (MOVE,0,lim+1);
+ 				term_set (ZAP,0,strlen(Contstr));
+ 				term_set (MOVE,0,lim-1);
+ 				putchar ('\n');
+ 				lcount = 0;
+ 			}
+ 		}
+ 	}
  	if (lcount > 0)
  	{
  		printf ("\n%s",Contstr);
***************
*** 123,142
  */
  help_rd()
  {
! 	h_print (Cxrtoi[PG_NEXT],HPG_NEXT);
! 	h_print (Cxrtoi[PG_QUIT],HPG_QUIT);
! 	h_print (Cxrtoi[PG_FLIP],HPG_FLIP);
! 	h_print (Cxrtoi[PG_REWIND],HPG_REWIND);
! 	h_print (Cxrtoi[PG_WIND],HPG_WIND);
! 	h_print (Cxrtoi[PG_SEARCH],HPG_SEARCH);
! 	h_print (Cxrtoi[PG_STEP],HPG_STEP);
! 	h_print (Cxrtoi[PG_REPLY],HPG_REPLY);
! 	h_print (Cxrtoi[PG_FOLLOW],HPG_FOLLOW);
! 	h_print (Cxrtoi[SAVE],HPG_SAVE);
! 	h_print (Cxrtoi[PRINT],HPG_PRINT);
! 	h_print (Cxrtoi[SETROT],HPG_ROT);
! 	h_print (Cxrtoi[HEADTOG],HPG_HEAD);
! 	h_print (Cxrtoi[PG_HELP],HPG_HELP);
  	printf ("%s\n",HPG_DEF);
  }
  

--- 153,183 -----
  */
  help_rd()
  {
! 	char *hs;
! 	char c;
! 
! 	printf("\n");	/* "confused" tab expansion on first line */
! 
! 	hr_print (Cxrtoi[PG_NEXT],HPG_NEXT);
! 	hr_print (Cxrtoi[PG_QUIT],HPG_QUIT);
! 	hr_print (Cxrtoi[PG_FLIP],HPG_FLIP);
! 	hr_print (Cxrtoi[PG_REWIND],HPG_REWIND);
! 	hr_print (Cxrtoi[PG_WIND],HPG_WIND);
! 	hr_print (Cxrtoi[PG_SEARCH],HPG_SEARCH);
! 	hr_print (Cxrtoi[PG_STEP],HPG_STEP);
! 	hr_print (Cxrtoi[PG_REPLY],HPG_REPLY);
! 	hr_print (Cxrtoi[PG_FOLLOW],HPG_FOLLOW);
! 	hr_print (Cxrtoi[SAVE],HPG_SAVE);
! 	hr_print (Cxrtoi[PRINT],HPG_PRINT);
! 	hr_print (Cxrtoi[SETROT],HPG_ROT);
! 	hr_print (Cxrtoi[HEADTOG],HPG_HEAD);
! 	hr_print (Cxrtoi[PG_HELP],HPG_HELP);
! 	if (Hookhelp != NULL)
! 	{
! 		for (hs=(*Hookhelp)(1,1,&c);
! 				hs != NULL; hs = (*Hookhelp)(1,0,&c))
! 			h_print (Cxrtoi[c],hs);
! 	}
  	printf ("%s\n",HPG_DEF);
  }
  
***************
*** 138,143
  	h_print (Cxrtoi[HEADTOG],HPG_HEAD);
  	h_print (Cxrtoi[PG_HELP],HPG_HELP);
  	printf ("%s\n",HPG_DEF);
  }
  
  srch_help(c,dig)

--- 179,192 -----
  			h_print (Cxrtoi[c],hs);
  	}
  	printf ("%s\n",HPG_DEF);
+ }
+ 
+ hr_print(c,msg)
+ char c;
+ char *msg;
+ {
+ 	if (Hookfunc == NULL || (*Hookfunc)(c,1,0) < 0)
+ 		h_print(c,msg);
  }
  
  srch_help(c,dig)
===================================================================
RCS file: RCS/pagefile.c,v
retrieving revision 6.0
diff -c -r6.0 pagefile.c
*** /tmp/,RCSt1029201	Sat May 28 13:08:01 1988
--- pagefile.c	Mon Apr 11 17:40:55 1988
***************
*** 7,12
  */
  
  #include <stdio.h>
  
  #ifdef SYSV
  #include <sys/types.h>

--- 7,13 -----
  */
  
  #include <stdio.h>
+ #include <ctype.h>
  
  #ifdef SYSV
  #include <sys/types.h>
***************
*** 47,53
  	Lrec = -1;
  	tmpnam (tmpart);
  	Pgsize = sizeof (HEAD) + L_allow * sizeof(BODY);
! 	if ((Tdes = open(tmpart,O_RDWR|O_CREAT)) < 0)
  		printex ("can't open %s",tmpart);
  	unlink (tmpart);
  }

--- 48,54 -----
  	Lrec = -1;
  	tmpnam (tmpart);
  	Pgsize = sizeof (HEAD) + L_allow * sizeof(BODY);
! 	if ((Tdes = open(tmpart,O_RDWR|O_CREAT,0600)) < 0)
  		printex ("can't open %s",tmpart);
  	unlink (tmpart);
  }
***************
*** 217,224
  {
  	while (*s != '\0')
  	{
! 		if (*s < ' ')
! 			*s += 'A' - 1;
  		++s;
  	}
  }

--- 218,225 -----
  {
  	while (*s != '\0')
  	{
! 		if (iscntrl(*s))
! 			*s = '?';
  		++s;
  	}
  }
===================================================================
RCS file: RCS/reader.c,v
retrieving revision 6.0
diff -c -r6.0 reader.c
*** /tmp/,RCSt1029201	Sat May 28 13:08:04 1988
--- reader.c	Tue Apr 12 10:51:27 1988
***************
*** 8,13
  
  #include <stdio.h>
  #include <sys/types.h>
  #include "tty.h"
  #include "config.h"
  #include "tune.h"

--- 8,14 -----
  
  #include <stdio.h>
  #include <sys/types.h>
+ #include <ctype.h>
  #include "tty.h"
  #include "config.h"
  #include "tune.h"
***************
*** 33,38
  extern char *Rotoff_msg;
  extern char *Hdon_msg;
  extern char *Hdoff_msg;
  
  extern PAGE Page;
  

--- 34,40 -----
  extern char *Rotoff_msg;
  extern char *Hdon_msg;
  extern char *Hdoff_msg;
+ extern char *Def_smode;
  
  extern PAGE Page;
  
***************
*** 39,44
  extern int (*Massage)();
  extern int (*Postfunc)();
  extern int (*Mailfunc)();
  
  extern char Cxrtoi[], Cxitor[];
  

--- 41,48 -----
  extern int (*Massage)();
  extern int (*Postfunc)();
  extern int (*Mailfunc)();
+ extern int (*Savemode)();
+ extern int (*Hookfunc)();
  
  extern char Cxrtoi[], Cxitor[];
  
***************
*** 201,207
  			*/
  			if (Headflag)
  			{
! 				top = (Rlines-2)*100;
  				bottom = hdr.lines + Hlines;
  			}
  			else

--- 205,211 -----
  			*/
  			if (Headflag)
  			{
! 				top = (Rlines-2);
  				bottom = hdr.lines + Hlines;
  			}
  			else
***************
*** 206,212
  			}
  			else
  			{
! 				top = (Rlines-Hlines-2)*100;
  				bottom = hdr.lines;
  			}
  			/*

--- 210,216 -----
  			}
  			else
  			{
! 				top = (Rlines-Hlines-2);
  				bottom = hdr.lines;
  			}
  			/*
***************
*** 216,222
  			** know the percentage is obviously wrong.
  			*/
  			if (bottom != 0)
! 				percent = top/bottom;
  			else
  				percent = 999;
  			sprintf (pstr,PAGE_MID,percent);

--- 220,226 -----
  			** know the percentage is obviously wrong.
  			*/
  			if (bottom != 0)
! 				percent = (top*100L)/bottom;
  			else
  				percent = 999;
  			sprintf (pstr,PAGE_MID,percent);
***************
*** 330,335
  {
  	char c;
  	int ic;
  	term_set (ONREVERSE);
  	printf("%s\015",prompt);
  	term_set (OFFREVERSE);

--- 334,342 -----
  {
  	char c;
  	int ic;
+ 	int i;
+ 	char mbuf[RECLEN];
+ 
  	term_set (ONREVERSE);
  	printf("%s\015",prompt);
  	term_set (OFFREVERSE);
***************
*** 335,341
  	term_set (OFFREVERSE);
  	while ((ic=getnoctl()) != EOF)
  	{
! 		switch (c = Cxitor[ic])
  		{
  		case SETROT:
  			term_set (ZAP,0,PPR_MAX);

--- 342,349 -----
  	term_set (OFFREVERSE);
  	while ((ic=getnoctl()) != EOF)
  	{
! 		c = Cxitor[ic];
! 		if (Hookfunc != NULL && (i = (*Hookfunc)(c,1,1,mbuf)) >= 0)
  		{
  			if (i == 0)
  			{
***************
*** 337,342
  	{
  		switch (c = Cxitor[ic])
  		{
  		case SETROT:
  			term_set (ZAP,0,PPR_MAX);
  			if (Rot == 0)

--- 345,362 -----
  		c = Cxitor[ic];
  		if (Hookfunc != NULL && (i = (*Hookfunc)(c,1,1,mbuf)) >= 0)
  		{
+ 			if (i == 0)
+ 			{
+ 				term_set (ZAP,0,PPR_MAX);
+ 				printf("%s\n",mbuf);
+ 			}
+ 			term_set (ONREVERSE);
+ 			printf("%s\015",prompt);
+ 			term_set (OFFREVERSE);
+ 			continue;
+ 		}
+ 		switch (c)
+ 		{
  		case SETROT:
  			term_set (ZAP,0,PPR_MAX);
  			if (Rot == 0)
***************
*** 588,594
  {
  	for ( ; *s != '\0'; ++s)
  	{
! 		if (*s >= 'A' && *s <= 'Z')
  		{
  			*s += Rot;
  			if (*s > 'Z')

--- 608,614 -----
  {
  	for ( ; *s != '\0'; ++s)
  	{
! 		if (isupper(*s))
  		{
  			*s += Rot;
  			if (!isupper(*s))
***************
*** 591,597
  		if (*s >= 'A' && *s <= 'Z')
  		{
  			*s += Rot;
! 			if (*s > 'Z')
  				*s -= 26;
  			continue;
  		}

--- 611,617 -----
  		if (isupper(*s))
  		{
  			*s += Rot;
! 			if (!isupper(*s))
  				*s -= 26;
  			continue;
  		}
***************
*** 595,601
  				*s -= 26;
  			continue;
  		}
! 		if (*s >= 'a' && *s <= 'z')
  		{
  			*s += Rot;
  			if (*s > 'z')

--- 615,621 -----
  				*s -= 26;
  			continue;
  		}
! 		if (islower(*s))
  		{
  			*s += Rot;
  			if (!islower(*s))
***************
*** 598,604
  		if (*s >= 'a' && *s <= 'z')
  		{
  			*s += Rot;
! 			if (*s > 'z')
  				*s -= 26;
  		}
  	}

--- 618,624 -----
  		if (islower(*s))
  		{
  			*s += Rot;
! 			if (!islower(*s))
  				*s -= 26;
  		}
  	}
***************
*** 615,621
  **	bell - pass through with zero width
  **	newline - end of record.
  **	del - turns into '_'
! **	other control - 'A' - 1 added ('01' = ctl-A).  Makes escape = "[".
  **		(prevents "letter bombs" containing inappropriate control
  **			sequences for the terminal).
  **

--- 635,641 -----
  **	bell - pass through with zero width
  **	newline - end of record.
  **	del - turns into '_'
! **	other control - turned into '?'
  **		(prevents "letter bombs" containing inappropriate control
  **			sequences for the terminal).
  **
***************
*** 670,677
  				++len;
  				break;
  			default:
! 				if (*s < ' ')
! 					*s += 'A' - 1;
  				++len;		/* fall through */
  			case '\07':
  				break;

--- 690,697 -----
  				++len;
  				break;
  			default:
!  				if (iscntrl(*s))
! 					*s = '?';
  				++len;		/* fall through */
  			case '\07':
  				break;
===================================================================
RCS file: RCS/server.doc,v
retrieving revision 6.0
diff -c -r6.0 server.doc
*** /tmp/,RCSt1029201	Sat May 28 13:08:08 1988
--- server.doc	Tue Apr 12 11:44:47 1988
***************
*** 15,29
  		interact with the user prior to editing the reply file
  		on mail replies.  See vns_aopen().
  
- 	(*Headedit)()
- 
- 		If set, will be called instead of the default action when
- 		the user chooses the "toggle header flag" command.  This
- 		is intended to allow the server interface to implement a
- 		user selection of which headers to display when reading
- 		an article.  If this is set, note that the reader code will
- 		never rewind an article past the point set by vns_aopen().
- 
  	(*Postfunc)(hdr,fn)
  	(*Mailfunc)(hdr,fn)
  	ARTHEADER *hdr;

--- 15,20 -----
  		interact with the user prior to editing the reply file
  		on mail replies.  See vns_aopen().
  
  	(*Postfunc)(hdr,fn)
  	(*Mailfunc)(hdr,fn)
  	ARTHEADER *hdr;
***************
*** 37,42
  		well set up postcmd / mailcmd, and let vn do it.  fn is
  		the name of a file containing the user's article or mail
  		reply.
  
  	All of the procedures will be called with the user's terminal in
  	raw mode and will be expected to leave it that way on return.

--- 28,167 -----
  		well set up postcmd / mailcmd, and let vn do it.  fn is
  		the name of a file containing the user's article or mail
  		reply.
+ 
+ 	FILE *(*Saveopen)(fn,msg,mode)
+ 	char *fn;
+ 	char *msg,
+ 	char **mode;
+ 
+ 		If set, this function allows the server interface to
+ 		implement its own semantics for the savefile string
+ 		typed by the user.  It should return an open file
+ 		pointer, NULL for failure.  msg is a message buffer
+ 		which will be displayed to the user, replacing the
+ 		normal "can't open ..." or "appended|created ..."
+ 		messages.  It MUST be filled in.  mode is a returned
+ 		pointer to the mode the file was opened with, and
+ 		will only really be used to pass on to vns_asave(),
+ 		so it may not really matter.  If untouched, it will
+ 		be "a".  Note that if this function is defined, the
+ 		user still can specify a pipe by typing "|<stuff>", but
+ 		all other interpretation of the savefile string such as
+ 		expansion of tildes becomes the responsibility of this
+ 		routine.  This is really intended as the hook to hang
+ 		something like the concept of "mail-folders" from.
+ 
+ 	(*Digsaver)(x,fp,count,name,mode)
+ 	char *x;
+ 	FILE *fp;
+ 	int count;
+ 	char *name;
+ 	char *mode;
+ 
+ 		If defined, this will be use to save digest extraction
+ 		articles.  For digest extractions, this will be called
+ 		instead of vns_asave, and will have to be defined to
+ 		perform any special massaging similar to vns_asave if
+ 		the features are expected to work for digest extractions.
+ 		If not defined, vn will simply shovel digest extractions
+ 		out to fp with no massaging.  x is the name of a temporary
+ 		file containing the extracted "article", the other arguments
+ 		are as for vns_asave.
+ 
+ 	char (*Marker)(group,art,oldmark,userkey)
+ 	NODE *group;
+ 	int art;
+ 	char oldmark;
+ 	char userkey;
+ 
+ 		This allows the server interface access to user mark
+ 		operations.  If defined, it will be called whenever the
+ 		user marks an article.  It returns the new mark to be
+ 		placed on the article, which should be a printable
+ 		character.  The space character is to be used to mean
+ 		that the article is unmarked.  This is the intended hook
+ 		to allow the server interface to implement any special
+ 		actions based on the user marks, such as retention of
+ 		marked articles when vns_write() is called.  The user
+ 		will still print/save/read all marked articles by
+ 		specifying "*", whatever the actual mark returned by
+ 		this routine, "marked" meaning marked with something
+ 		other than <space>.  Userkey is the character entered
+ 		by the user which resulted in the mark action ('x', '^x',
+ 		'X' or '*').  Remember that 'X' means "unmark".
+ 
+ 	(*Hookfunc)(key,reader,go,msg)
+ 	char key;
+ 	int reader;
+ 	int go;
+ 	char *msg;
+ 
+ 		This allows the vns_ layer to hook arbitrary commands
+ 		into the vn interaction.  If defined, this will be called
+ 		with every user command key.  reader will be TRUE if called
+ 		from reading interaction, FALSE if called from page.
+ 
+ 		Since this will be called with EVERY user command key, if
+ 		defined, it is very important that it return <0 for all
+ 		unrecognized keys, or vn won't be able to do anything.
+ 
+ 		Attempts to define most control keys as commands will be
+ 		ineffective from the reader - they simply will not
+ 		reach Hookfunc.  They are OK from the page display.
+ 		You may not use <escape> or numeric characters as commands.
+ 
+ 		If go is FALSE, msg argument should not be used, and no
+ 		real action should be taken.  In this case, the routine
+ 		should return >= 0 if the key is an additional command,
+ 		< 0 otherwise.  This is the call vn may make to see if
+ 		the vns_ layer has a use for a key, without wanting to
+ 		really invoke that action.
+ 
+ 		If go is TRUE, the action is actually to be taken, if
+ 		applicable.  Return < 0 for undefined key.  If it returns 0,
+ 		this indicates that the procedure did nothing to the screen,
+ 		and msg MUST be filled in with a message to display.  This
+ 		is the way to implement a simple toggle.  If interaction
+ 		with the user is desired, this routine should call
+ 		term_set(ERASE), which clears the screen, and return
+ 		> 0 after performing the interaction.  It should leave
+ 		the cursor in the desired screen location for continuation
+ 		when called while reading an article.
+ 
+ 		This hook can be used to implement user interaction for
+ 		any purpose which is server specific.  The one currently
+ 		being contemplated is control of the way in which articles
+ 		are saved in files (mailbox format feature).
+ 
+ 		Another which suggests itself is allowing the edit of
+ 		which header lines to display.  In this case, it is OK
+ 		to take "h" key which only handles this function in a
+ 		rudimentary fashion.  If this is done, be sure to take
+ 		the key BOTH on the page display and in the reader - vn
+ 		will never rewind an article past the point returned by
+ 		vns_aopen if this is done.
+ 
+ 	char *
+ 	(*Hookhelp)(reader,first,key)
+ 	int reader, first;
+ 	char *key;
+ 
+ 		This allows help messages for the commands set by Hookfunc,
+ 		to be shown.  reader is TRUE if from reading an article,
+ 		FALSE if from page.  first is set TRUE to start list.
+ 		returns help message, and places corresponding key character
+ 		in key.  vn will keep calling with first = FALSE until
+ 		a NULL return indicates the end of the list.
+ 
+ 		Note that command keys defined by vns_ layer may be
+ 		translated via a user .vnkeys file just like the other
+ 		commands.  These routines work strictly in terms of the
+ 		translated keys - vn will handle translating back to
+ 		the users keys for the help display.
+ 
+ 		If you define a key already used by vn, it works, but
+ 		is obviously not a good practice.  Only the "quit" key from
+ 		the page display can't be superceded.
  
  	All of the procedures will be called with the user's terminal in
  	raw mode and will be expected to leave it that way on return.
===================================================================
RCS file: RCS/session.c,v
retrieving revision 6.0
diff -c -r6.0 session.c
*** /tmp/,RCSt1029201	Sat May 28 13:08:12 1988
--- session.c	Tue Apr 12 14:42:41 1988
***************
*** 7,12
  */
  #include <stdio.h>
  #include <setjmp.h>
  #include "config.h"
  #include "tty.h"
  #include "brk.h"

--- 7,13 -----
  */
  #include <stdio.h>
  #include <setjmp.h>
+ #include <ctype.h>
  #include "config.h"
  #include "tty.h"
  #include "brk.h"
***************
*** 38,44
  extern char *List_sep;
  extern char *Version, *Vns_version;
  
! extern int (*Headedit)();
  
  static int C_info;
  static int Dskip, Drec;

--- 39,46 -----
  extern char *List_sep;
  extern char *Version, *Vns_version;
  
! extern char (*Marker)();
! extern int (*Hookfunc)();
  
  static int C_info;
  static int Dskip, Drec;
***************
*** 58,64
  session ()
  {
  	char alist [RECLEN], c;
! 	int newg, i, count;
  	jmp_buf brkbuf;
  
  	newg = new_groups();

--- 60,66 -----
  session ()
  {
  	char alist [RECLEN], c;
! 	int newg, i, j, count;
  	jmp_buf brkbuf;
  
  	newg = new_groups();
***************
*** 105,110
  	 */
  	for (count = getkey(&c); c != QUIT; count = getkey(&c))
  	{
  		if ( srch_help(c,&i) != 0 || (Digest != 0 && i == 0))
  		{
  			preinfo (UDKFORM,Cxptoi[HELP]);

--- 107,128 -----
  	 */
  	for (count = getkey(&c); c != QUIT; count = getkey(&c))
  	{
+ 		if (Hookfunc != NULL)
+ 		{
+ 			if ((i = (*Hookfunc)(c,0,1,alist)) >= 0)
+ 			{
+ 				if (i == 0)
+ 					prinfo(alist);
+ 				else
+ 				{
+ 					term_set(ERASE);
+ 					show();
+ 				}
+ 				term_set (MOVE,0,Crec);
+ 				continue;
+ 			}
+ 		}
+ 
  		if ( srch_help(c,&i) != 0 || (Digest != 0 && i == 0))
  		{
  			preinfo (UDKFORM,Cxptoi[HELP]);
***************
*** 115,128
  		switch (c)
  		{
  		case HEADTOG:
- 			if (Headedit != NULL)
- 			{
- 				term_set(ERASE);
- 				(*Headedit)();
- 				show();
- 				term_set (MOVE,0,Crec);
- 				break;
- 			}
  			if (Headflag)
  			{
  				Headflag = FALSE;

--- 133,138 -----
  		switch (c)
  		{
  		case HEADTOG:
  			if (Headflag)
  			{
  				Headflag = FALSE;
***************
*** 237,242
  			else
  				putchar ('\07');
  			break;
  		case MARK:
  		case ART_MARK:
  			count += Crec - 1;

--- 247,259 -----
  			else
  				putchar ('\07');
  			break;
+ 		case MARKSTRING:
+ 			(Page.h.group)->flags |= FLG_ACC;
+ 			userlist (alist);
+ 			markstr (alist,c);
+ 			term_set (MOVE, 0, Crec);
+ 			write_page ();
+ 			break;
  		case MARK:
  		case ART_MARK:
  			genlist (alist,Crec-RECBIAS,count);
***************
*** 239,259
  			break;
  		case MARK:
  		case ART_MARK:
! 			count += Crec - 1;
! 			if (count >= Highrec)
! 				count = Highrec - 1;
! 			for (i=Crec; i <= count; ++i)
! 			{
! 				if (Page.b[i-RECBIAS].art_mark != ART_MARK)
! 					Page.b[i-RECBIAS].art_mark = ART_MARK;
! 				else
! 					Page.b[i-RECBIAS].art_mark = ' ';
! 				if (i != Crec)
! 					term_set (MOVE, 0, i);
! 				printf ("%c\010",Page.b[i-RECBIAS].art_mark);
! 			}
! 			if (count != Crec)
! 				term_set (MOVE, 0, Crec);
  			write_page ();
  			break;
  		case UNMARK:

--- 256,264 -----
  			break;
  		case MARK:
  		case ART_MARK:
! 			genlist (alist,Crec-RECBIAS,count);
! 			markstr (alist,c);
! 			term_set (MOVE, 0, Crec);
  			write_page ();
  			break;
  		case UNMARK:
***************
*** 259,265
  		case UNMARK:
  			for (i=0; i < Page.h.artnum; ++i)
  			{
! 				if (Page.b[i].art_mark == ART_MARK)
  				{
  					Page.b[i].art_mark = ' ';
  					term_set (MOVE, 0, i+RECBIAS);

--- 264,270 -----
  		case UNMARK:
  			for (i=0; i < Page.h.artnum; ++i)
  			{
! 				if (Page.b[i].art_mark != ' ')
  				{
  					if (Marker == NULL)
  						Page.b[i].art_mark = ' ';
***************
*** 261,267
  			{
  				if (Page.b[i].art_mark == ART_MARK)
  				{
! 					Page.b[i].art_mark = ' ';
  					term_set (MOVE, 0, i+RECBIAS);
  					putchar (' ');
  				}

--- 266,278 -----
  			{
  				if (Page.b[i].art_mark != ' ')
  				{
! 					if (Marker == NULL)
! 						Page.b[i].art_mark = ' ';
! 					else
! 						Page.b[i].art_mark =
! 						(*Marker)(Page.h.group,
! 							Page.b[i].art_id,
! 							Page.b[i].art_mark, c);
  					term_set (MOVE, 0, i+RECBIAS);
  					putchar (' ');
  				}
***************
*** 278,283
  				preinfo ("No more pages");
  			term_set (MOVE,0,Crec);
  			break;
  		case DIGEST:
  			if (Digest)
  			{

--- 289,332 -----
  				preinfo ("No more pages");
  			term_set (MOVE,0,Crec);
  			break;
+ 		case GRPBACK:
+ 			j = (Page.h.group)->order;
+ 			for (i = j-1; count > 0 && i >= 0; --i)
+ 			{
+ 				if ((Newsorder[i])->pages > 0)
+ 				{
+ 					j = i;
+ 					--count;
+ 				}
+ 			}
+ 			if (j == (Page.h.group)->order)
+ 				preinfo ("No more newsgroups");
+ 			else
+ 			{
+ 				forward ((Newsorder[j])->pnum - Cur_page);
+ 				show();
+ 			}
+ 			term_set (MOVE,0,Crec);
+ 			break;
+ 		case GRPFORWARD:
+ 			j = (Page.h.group)->order;
+ 			for (i= j+1; count > 0 && i < Ncount; ++i)
+ 			{
+ 				if ((Newsorder[i])->pages > 0)
+ 				{
+ 					j = i;
+ 					--count;
+ 				}
+ 			}
+ 			if (j == (Page.h.group)->order)
+ 				preinfo ("No more newsgroups");
+ 			else
+ 			{
+ 				forward ((Newsorder[j])->pnum - Cur_page);
+ 				show();
+ 			}
+ 			term_set (MOVE,0,Crec);
+ 			break;
  		case DIGEST:
  			if (Digest)
  			{
***************
*** 552,558
  	if (*s != '\0')
  	{
  		tmpnam(fn);
! 		if (art_xfer(fn,s,"w") != 0)
  		{
  			preinfo("Couldn't open temporary file");
  			return;

--- 601,607 -----
  	if (*s != '\0')
  	{
  		tmpnam(fn);
! 		if (art_xfer(fn,s,"w",NULL) != 0)
  		{
  			preinfo("Couldn't open temporary file");
  			return;
***************
*** 795,800
  char *defstr;
  {
  	int i,idx,len;
  
  	if (iline)
  	{

--- 844,850 -----
  char *defstr;
  {
  	int i,idx,len;
+ 	char c;
  
  	if (iline)
  	{
***************
*** 811,817
   	for (i=0; i < len; i++)
   		s[i] = defstr[i];
   
! 	for (i=len; idx < C_allow && (s[i] = getchar() & 0x7f) != '\012' && s[i] != '\015'; ++i)
  	{
  		if (s[i] == Erasekey)
  		{

--- 861,867 -----
   	for (i=0; i < len; i++)
   		s[i] = defstr[i];
   
!  	for (i=len; idx < C_allow; ++i)
  	{
  		s[i] = getchar();
  		c = s[i] & CHMASK;
***************
*** 813,819
   
  	for (i=len; idx < C_allow && (s[i] = getchar() & 0x7f) != '\012' && s[i] != '\015'; ++i)
  	{
! 		if (s[i] == Erasekey)
  		{
  			if (i > 0)
  			{

--- 863,873 -----
   
   	for (i=len; idx < C_allow; ++i)
  	{
! 		s[i] = getchar();
! 		c = s[i] & CHMASK;
! 		if (c == '\015' || c == '\012')
! 			break;
! 		if (c == Erasekey)
  		{
  			if (i > 0)
  			{
***************
*** 825,831
  				i = -1;
  			continue;
  		}
! 		if (s[i] == Killkey)
  		{
   			if (iline)
   			{

--- 879,885 -----
  				i = -1;
  			continue;
  		}
! 		if (c == Killkey)
  		{
   			if (iline)
   			{
***************
*** 843,849
  			continue;
  		}
  		/* no leading spaces */
! 		if (s[i] == ' ' && i == 0)
  		{
  			i = -1;
  			putchar('\07');

--- 897,903 -----
  			continue;
  		}
  		/* no leading spaces */
! 		if (c == ' ' && i == 0)
  		{
  			i = -1;
  			putchar('\07');
***************
*** 850,856
  			continue;
  		}
  		/* no controls */
! 		if (s[i] < ' ' || s[i] == '\177')
  		{
  			--i;
  			putchar('\07');

--- 904,910 -----
  			continue;
  		}
  		/* no controls */
!  		if (iscntrl(c))
  		{
  			--i;
  			putchar('\07');
***************
*** 867,873
  
  	s[i] = '\0';
  }
- 
  /*
  	print something on the information line,
  	clearing any characters not overprinted.

--- 921,926 -----
  
  	s[i] = '\0';
  }
  /*
  	print something on the information line,
  	clearing any characters not overprinted.
***************
*** 1027,1032
  		{
  			n->flags &= ~FLG_SUB;
  			n->flags |= FLG_ECHG;
  		}
  	}
  }

--- 1080,1133 -----
  		{
  			n->flags &= ~FLG_SUB;
  			n->flags |= FLG_ECHG;
+ 		}
+ 	}
+ }
+ 
+ /*
+ ** utility to mark articles.  depends on fact that article numbers are
+ ** in ascending order on page.
+ */
+ static
+ markstr (list,ckey)
+ char *list;
+ char ckey;
+ {
+ 	char *tok;
+ 	int art, count;
+ 	BODY *b;
+ 
+ 	count = 1;
+ 	b = Page.b;
+ 	for (tok = strtok(list,List_sep); tok != NULL;
+ 					tok = strtok(NULL,List_sep))
+ 	{
+ 		art = atoi(tok);
+ 		while (count < Page.h.artnum && b->art_id < art)
+ 		{
+ 			++count;
+ 			++b;
+ 		}
+ 		if (b->art_id == art)
+ 		{
+ 			/*
+ 			** Can't call Marker inside digests
+ 			*/
+ 			if (Marker == NULL || Digest)
+ 			{
+ 				if (b->art_mark != ART_MARK)
+ 					b->art_mark = ART_MARK;
+ 				else
+ 					b->art_mark = ' ';
+ 			}
+ 			else
+ 			{
+ 				b->art_mark =
+ 					(*Marker)(Page.h.group, art,
+ 						b->art_mark, ckey);
+ 			}
+ 			term_set (MOVE, 0, count-1+RECBIAS);
+ 			printf ("%c\010",b->art_mark);
  		}
  	}
  }
===================================================================
RCS file: RCS/strings.c,v
retrieving revision 6.0
diff -c -r6.0 strings.c
*** /tmp/,RCSt1029201	Sat May 28 13:08:17 1988
--- strings.c	Mon Apr 11 17:42:04 1988
***************
*** 10,16
  #include "node.h"
  #include "page.h"
  
! char *Version = "1/88";
  
  char *No_msg = "No articles";
  char *Hdon_msg = "Headers being printed";

--- 10,16 -----
  #include "node.h"
  #include "page.h"
  
! char *Version = "4/88";
  
  char *No_msg = "No articles";
  char *Hdon_msg = "Headers being printed";
===================================================================
RCS file: RCS/svart.c,v
retrieving revision 6.0
diff -c -r6.0 svart.c
*** /tmp/,RCSt1029201	Sat May 28 13:08:18 1988
--- svart.c	Mon Apr 11 17:42:21 1988
***************
*** 20,25
  extern char *List_sep;
  extern char *Home;
  extern char *Savedir;
  
  /*
  ** save article in file.  Called from reader and session both.

--- 20,27 -----
  extern char *List_sep;
  extern char *Home;
  extern char *Savedir;
+ extern FILE *(*Saveopen)();
+ extern int (*Digsaver)();
  
  /*
  ** save article in file.  Called from reader and session both.
***************
*** 46,52
  	if (*dest == '|')
  	{
  		tmpnam(fn);
! 		if (art_xfer(fn,art,"w") != 0)
  		{
  			strcpy(msg,"Can't open temporary file");
  			return (-1);

--- 48,54 -----
  	if (*dest == '|')
  	{
  		tmpnam(fn);
! 		if (art_xfer(fn,art,"w",NULL) != 0)
  		{
  			strcpy(msg,"Can't open temporary file");
  			return (-1);
***************
*** 59,64
  		return (rstat);
  	}
  
  	if ((colon = index(dest,':')) != NULL)
  	{
  		mode = dest;

--- 61,69 -----
  		return (rstat);
  	}
  
+ 	if (Saveopen != NULL)
+ 		return (art_xfer(dest,art,"a",msg));
+ 
  	if ((colon = index(dest,':')) != NULL)
  	{
  		mode = dest;
***************
*** 94,100
  
  	rstat = stat(dest,&sbuf);
  
! 	if (art_xfer(dest,art,mode) != 0)
  	{
  		sprintf(msg,"Can't open %s with mode %s",dest,mode);
  		return(-1);

--- 99,105 -----
  
  	rstat = stat(dest,&sbuf);
  
! 	if (art_xfer(dest,art,mode,msg) != 0)
  	{
  		sprintf(msg,"Can't open %s with mode %s",dest,mode);
  		return(-1);
***************
*** 202,207
  **
  ** Called directly to copy a list of articles to a temp. file to
  ** direct to printer.
  */
  art_xfer(fn,list,mode)
  char *fn, *list, *mode;

--- 207,219 -----
  **
  ** Called directly to copy a list of articles to a temp. file to
  ** direct to printer.
+ **
+ ** NOTE:
+ **	The msg argument only matters if Saveopen is not NULL.  If so, it
+ **	is non-NULL if *Saveopen is to be called, and points to the message
+ **	buffer.  Will be called with msg = NULL to fill temp. files rather
+ **	than user named files.  If *Saveopen is called, mode argument is
+ **	actually returned by it, and only matters for vns_asave call.
  */
  art_xfer(fn,list,mode,msg)
  char *fn, *list, *mode, *msg;
***************
*** 203,210
  ** Called directly to copy a list of articles to a temp. file to
  ** direct to printer.
  */
! art_xfer(fn,list,mode)
! char *fn, *list, *mode;
  {
  	char *p;
  	FILE *fout, *fin;

--- 215,222 -----
  **	than user named files.  If *Saveopen is called, mode argument is
  **	actually returned by it, and only matters for vns_asave call.
  */
! art_xfer(fn,list,mode,msg)
! char *fn, *list, *mode, *msg;
  {
  	char *p;
  	FILE *fout, *fin;
***************
*** 212,218
  	char buf[RECLEN];
  	char *strtok();
  
! 	if ((fout = fopen(fn,mode)) == NULL)
  		return (-1);
  
  	count = 0;

--- 224,234 -----
  	char buf[RECLEN];
  	char *strtok();
  
! 	if (Saveopen != NULL && msg != NULL)
! 		fout = (*Saveopen)(fn,msg,&mode);
! 	else
! 		fout = fopen(fn,mode);
! 	if (fout == NULL)
  		return (-1);
  
  	count = 0;
***************
*** 220,225
  	{
  		if (Digest)
  		{
  			fin = fopen(p,"r");
  			if (fin == NULL)
  				continue;

--- 236,247 -----
  	{
  		if (Digest)
  		{
+ 			if (Digsaver != NULL)
+ 			{
+ 				(*Digsaver)(p,fout,count,fn,mode);
+ 				++count;
+ 				continue;
+ 			}
  			fin = fopen(p,"r");
  			if (fin == NULL)
  				continue;
===================================================================
RCS file: RCS/userlist.c,v
retrieving revision 6.0
diff -c -r6.0 userlist.c
*** /tmp/,RCSt1029201	Sat May 28 13:08:20 1988
--- userlist.c	Mon Apr 11 17:42:32 1988
***************
*** 67,73
  		{
  			for (i=0; i < Page.h.artnum; ++i)
  			{
! 				if (Page.b[i].art_mark == ART_MARK)
  				{
  					anum[acount] = Page.b[i].art_id;
  					++acount;

--- 67,73 -----
  		{
  			for (i=0; i < Page.h.artnum; ++i)
  			{
! 				if (Page.b[i].art_mark != ' ')
  				{
  					anum[acount] = Page.b[i].art_id;
  					++acount;
===================================================================
RCS file: RCS/vn.c,v
retrieving revision 6.0
diff -c -r6.0 vn.c
*** /tmp/,RCSt1029201	Sat May 28 13:08:23 1988
--- vn.c	Mon Apr 11 17:42:47 1988
***************
*** 187,192
  		from Greg Earle, earle@mahendo.  Modified slightly for
  		cosmetic reasons & to fix a small folded-line bug.
  
  Known bugs:
  
  	If your terminal init string contains a newline, I suspect you will

--- 187,225 -----
  		from Greg Earle, earle@mahendo.  Modified slightly for
  		cosmetic reasons & to fix a small folded-line bug.
  
+ 	2/88 (bobm)
+ 
+ 		Put mode on open() call in temp_open, as per bug fix from
+ 		Don Craig.  This has been working this way a long time on
+ 		a lot of systems (the file is unlinked after creation, so
+ 		the actual mode doesn't really matter, and as long as your
+ 		open call doesn't check the unused bits a random argument
+ 		works), but it was wrong, anyway.
+ 
+ 	4/88 (bobm)
+ 
+ 		Change server interface a bit to allow more control over
+ 		saving features, and provide a more generalized interface
+ 		for the vns_ routines to hang interactive hooks from.
+ 		Allow vns_ layer knowledge of marks.  These changes
+ 		should allow future implementation of selective lists,
+ 		use of the interface for a mailer, extra functionality
+ 		add-on at the vns level, etc.
+ 
+ 		incorporate changes to allow 8 bit intl. character set
+ 		in user strings - came from Marius Olafsson, marius@rhi.
+ 		Also made 0x7f a #define'ed mask in case you should want
+ 		to try allowing 8 bit command chars.
+ 
+ 		Jay Maynard, splut!jay pointed out that the percentage
+ 		calculation in reader overflowed for a 327+ line article
+ 		on a 16 bit machine, and sent fix.
+ 
+ 		std.c - fix "all.all" bug (any newsgroup names with
+ 		multiple "all"'s in them incorrectly converted into RE's
+ 		which would match practically nothing).  Up vns_Version
+ 		stamp to 1.2.
+ 
  Known bugs:
  
  	If your terminal init string contains a newline, I suspect you will
***************
*** 214,219
  
  	crash due to embedding $\(\) type substring specifiers in regular
  	expressions.  Obscure and hard to fix in a proper and portable way.
  */
  #include <stdio.h>
  #include "node.h"

--- 247,256 -----
  
  	crash due to embedding $\(\) type substring specifiers in regular
  	expressions.  Obscure and hard to fix in a proper and portable way.
+ 
+ 	Spool numbers are kept in int, not long - it would take quite
+ 	a bit of scrubbing through the code to root out this 32-bit'ism.
+ 	I wish I had typedef'ed the things.
  */
  #include <stdio.h>
  #include "node.h"
===================================================================
RCS file: RCS/vn.h,v
retrieving revision 6.0
diff -c -r6.0 vn.h
*** /tmp/,RCSt1029201	Sat May 28 13:08:25 1988
--- vn.h	Mon Apr 11 17:35:48 1988
***************
*** 15,21
  #define ART_UNWRITTEN ' '
  
  
- #define ANFORM ":%s - %c for help:\n"
  #define ANFLINES 1
  #define UDKFORM "undefined key - %c for help"
  #define HELPFORM "%c for help"

--- 15,20 -----
  #define ART_UNWRITTEN ' '
  
  
  #define ANFLINES 1
  #define UDKFORM "undefined key - %c for help"
  #define HELPFORM "%c for help"
***************
*** 31,36
  #define DOWN 'j'
  #define FORWARD '\012'
  #define BACK '\010'
  #define READ 'r'
  #define ALTREAD ' '
  #define READALL 'R'

--- 30,37 -----
  #define DOWN 'j'
  #define FORWARD '\012'
  #define BACK '\010'
+ #define GRPFORWARD '>'
+ #define GRPBACK '<'
  #define READ 'r'
  #define ALTREAD ' '
  #define READALL 'R'
***************
*** 44,49
  #define PRINTSTRING '\020'
  #define MARK 'x'
  #define UNMARK 'X'
  #define REDRAW '\014'
  #define QUIT 'q'
  #define SSTAT '#'

--- 45,51 -----
  #define PRINTSTRING '\020'
  #define MARK 'x'
  #define UNMARK 'X'
+ #define MARKSTRING '\030'
  #define REDRAW '\014'
  #define QUIT 'q'
  #define SSTAT '#'
===================================================================
RCS file: RCS/vnglob.c,v
retrieving revision 6.0
diff -c -r6.0 vnglob.c
*** /tmp/,RCSt1029201	Sat May 28 13:08:28 1988
--- vnglob.c	Tue Apr 12 14:43:01 1988
***************
*** 21,27
  char *Editor, *Ps1, *Printer;
  
  int (*Massage)() = NULL;
- int (*Headedit)() = NULL;
  int (*Postfunc)() = NULL;
  int (*Mailfunc)() = NULL;
  

--- 21,26 -----
  char *Editor, *Ps1, *Printer;
  
  int (*Massage)() = NULL;
  int (*Postfunc)() = NULL;
  int (*Mailfunc)() = NULL;
  char (*Marker)() = NULL;
***************
*** 24,29
  int (*Headedit)() = NULL;
  int (*Postfunc)() = NULL;
  int (*Mailfunc)() = NULL;
  
  char Erasekey, Killkey;		/* user keys from stty */
  char *Orgdir;			/* .newsrc file, and original pwd */

--- 23,33 -----
  int (*Massage)() = NULL;
  int (*Postfunc)() = NULL;
  int (*Mailfunc)() = NULL;
+ char (*Marker)() = NULL;
+ int (*Hookfunc)() = NULL;
+ char *(*Hookhelp)() = NULL;
+ FILE *(*Saveopen)() = NULL;
+ int (*Digsaver)() = NULL;
  
  char Erasekey, Killkey;		/* user keys from stty */
  char *Orgdir;			/* .newsrc file, and original pwd */
***************
*** 41,47
  char *Ku, *Kd, *Kl, *Kr;	/* Cursor movement capabilities */
  
  /* character translation arrays for commands */
! char Cxitop[128], Cxitor[128], Cxrtoi[128], Cxptoi[128];
  
  /*
  	cur_page - current page displayed;

--- 45,51 -----
  char *Ku, *Kd, *Kl, *Kr;	/* Cursor movement capabilities */
  
  /* character translation arrays for commands */
! char Cxitop[CHMASK+1], Cxitor[CHMASK+1], Cxrtoi[CHMASK+1], Cxptoi[CHMASK+1];
  
  /*
  	cur_page - current page displayed;


