[comp.sources.amiga] v91i049: VN res1.1-2 - vn news reader, Part03/06

amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (03/14/91)

Submitted-by: eyal@echo.canberra.edu.au (Eyal Lebedinsky)
Posting-number: Volume 91, Issue 049
Archive-name: news/vn-res-1.1-2/part03

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 6)."
# Contents:  SERVER.DOC amiga.c help.c termcap.c vn.c
# Wrapped by tadguy@ab20 on Wed Mar 13 19:10:10 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'SERVER.DOC' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'SERVER.DOC'\"
else
echo shar: Extracting \"'SERVER.DOC'\" \(18433 characters\)
sed "s/^X//" >'SERVER.DOC' <<'END_OF_FILE'
Xvns_envir()
X
X	called to allow server layer to set environment.  Will be called
X	before anything else.  See the vn_env() routine if the server
X	interface intends to use any environment variables.
X
X	There are some procedure pointers in vn which may optionally
X	be set by the server interface.  By default, all of these are
X	NULL:
X
X	(*Massage)(hdr)
X	ARTHEADER *hdr;
X
X		Mail path massaging function.  Allows server interface to
X		interact with the user prior to editing the reply file
X		on mail replies.  See vns_aopen().
X
X	(*Postfunc)(hdr,fn)
X	(*Mailfunc)(hdr,fn)
X	ARTHEADER *hdr;
X	char *fn;
X
X		If set, these functions will be called for mail / post
X		instead of spawning a command.  They are intended for
X		the instance in which these operations can be handled
X		within the executable rather than forking another process.
X		If forking another process has to be done, you might as
X		well set up postcmd / mailcmd, and let vn do it.  fn is
X		the name of a file containing the user's article or mail
X		reply.
X
X	FILE *(*Saveopen)(fn,msg,mode)
X	char *fn;
X	char *msg,
X	char **mode;
X
X		If set, this function allows the server interface to
X		implement its own semantics for the savefile string
X		typed by the user.  It should return an open file
X		pointer, NULL for failure.  msg is a message buffer
X		which will be displayed to the user, replacing the
X		normal "can't open ..." or "appended|created ..."
X		messages.  It MUST be filled in.  mode is a returned
X		pointer to the mode the file was opened with, and
X		will only really be used to pass on to vns_asave(),
X		so it may not really matter.  If untouched, it will
X		be "a".  Note that if this function is defined, the
X		user still can specify a pipe by typing "|<stuff>", but
X		all other interpretation of the savefile string such as
X		expansion of tildes becomes the responsibility of this
X		routine.  This is really intended as the hook to hang
X		something like the concept of "mail-folders" from.
X
X	(*Digsaver)(x,fp,count,name,mode)
X	char *x;
X	FILE *fp;
X	int count;
X	char *name;
X	char *mode;
X
X		If defined, this will be use to save digest extraction
X		articles.  For digest extractions, this will be called
X		instead of vns_asave, and will have to be defined to
X		perform any special massaging similar to vns_asave if
X		the features are expected to work for digest extractions.
X		If not defined, vn will simply shovel digest extractions
X		out to fp with no massaging.  x is the name of a temporary
X		file containing the extracted "article", the other arguments
X		are as for vns_asave.
X
X	char (*Marker)(group,art,oldmark,userkey)
X	NODE *group;
X	int art;
X	char oldmark;
X	char userkey;
X
X		This allows the server interface access to user mark
X		operations.  If defined, it will be called whenever the
X		user marks an article.  It returns the new mark to be
X		placed on the article, which should be a printable
X		character.  The space character is to be used to mean
X		that the article is unmarked.  This is the intended hook
X		to allow the server interface to implement any special
X		actions based on the user marks, such as retention of
X		marked articles when vns_write() is called.  The user
X		will still print/save/read all marked articles by
X		specifying "*", whatever the actual mark returned by
X		this routine, "marked" meaning marked with something
X		other than <space>.  Userkey is the character entered
X		by the user which resulted in the mark action ('x', '^x',
X		'X' or '*').  Remember that 'X' means "unmark".
X
X	(*Hookfunc)(key,reader,go,msg)
X	char key;
X	int reader;
X	int go;
X	char *msg;
X
X		This allows the vns_ layer to hook arbitrary commands
X		into the vn interaction.  If defined, this will be called
X		with every user command key.  reader will be TRUE if called
X		from reading interaction, FALSE if called from page.
X
X		Since this will be called with EVERY user command key, if
X		defined, it is very important that it return <0 for all
X		unrecognized keys, or vn won't be able to do anything.
X
X		Attempts to define most control keys as commands will be
X		ineffective from the reader - they simply will not
X		reach Hookfunc.  They are OK from the page display.
X		You may not use <escape> or numeric characters as commands.
X
X		If go is FALSE, msg argument should not be used, and no
X		real action should be taken.  In this case, the routine
X		should return >= 0 if the key is an additional command,
X		< 0 otherwise.  This is the call vn may make to see if
X		the vns_ layer has a use for a key, without wanting to
X		really invoke that action.
X
X		If go is TRUE, the action is actually to be taken, if
X		applicable.  Return < 0 for undefined key.  If it returns 0,
X		this indicates that the procedure did nothing to the screen,
X		and msg MUST be filled in with a message to display.  This
X		is the way to implement a simple toggle.  If interaction
X		with the user is desired, this routine should call
X		term_set(ERASE), which clears the screen, and return
X		> 0 after performing the interaction.  It should leave
X		the cursor in the desired screen location for continuation
X		when called while reading an article.
X
X		This hook can be used to implement user interaction for
X		any purpose which is server specific.  The one currently
X		being contemplated is control of the way in which articles
X		are saved in files (mailbox format feature).
X
X		Another which suggests itself is allowing the edit of
X		which header lines to display.  In this case, it is OK
X		to take "h" key which only handles this function in a
X		rudimentary fashion.  If this is done, be sure to take
X		the key BOTH on the page display and in the reader - vn
X		will never rewind an article past the point returned by
X		vns_aopen if this is done.
X
X	char *
X	(*Hookhelp)(reader,first,key)
X	int reader, first;
X	char *key;
X
X		This allows help messages for the commands set by Hookfunc,
X		to be shown.  reader is TRUE if from reading an article,
X		FALSE if from page.  first is set TRUE to start list.
X		returns help message, and places corresponding key character
X		in key.  vn will keep calling with first = FALSE until
X		a NULL return indicates the end of the list.
X
X		Note that command keys defined by vns_ layer may be
X		translated via a user .vnkeys file just like the other
X		commands.  These routines work strictly in terms of the
X		translated keys - vn will handle translating back to
X		the users keys for the help display.
X
X		If you define a key already used by vn, it works, but
X		is obviously not a good practice.  Only the "quit" key from
X		the page display can't be superceded.
X
X	All of the procedures will be called with the user's terminal in
X	raw mode and will be expected to leave it that way on return.
X	If these routines need to control ioctl settings or send control
X	sequences to the terminal, they should do so through the tty_set /
X	term_set calls used by the rest of vn.  These routines basically
X	hide ioctl / termcap from everybody.
X
Xvns_news (argc,argv,lfirst,unsub)
Xint argc;
Xchar **argv;
Xint *lfirst;
Xint *unsub;
X
X	called to let server layer process options and enter known newsgroups
X	in vn structure.  arguments are vn's command line.   It calls four
X	specific support routines:
X
X	hashenter(group,highnum,lownum)
X	char *group;
X	int highnum, lownum;
X
X		Enter information about a newsgroup. Group is newsgroup
X		name, highnum the highest article number, lownum the lowest.
X
X	NODE *
X	hashfind(group)
X	char *group;
X
X		Return information on entered group.  See node.h header
X		file for structure and legal usage of its items by server
X		interface routines.  May be called by other vns_ rouines
X		as well.
X
X	fw_group(group,new,sub,read,look)
X	char *group;
X	int new, sub, read, look;
X
X		prepare to enter display information for a new newsgroup.
X		new is non-zero if this is to be considered a "new" newsgroup
X		since the user's last session.  sub is non-zero if user is
X		to be considered "subscribed" to it.  read is the initial
X		"articles read" number for the newsgroup.  look is non-zero
X		if server interface intends to look for articles in this
X		newsgroup.  This parameter is open to interpretation, but
X		should indicate that user's options mean group is to be looked
X		at.  This should NOT reflect the fact that no articles will
X		be found because "read" is up to date.  The parameter is only
X		used for statistical collection, anyway.
X
X	fw_art(anum,subj,lines,author)
X	int anum;
X	char *subj, *lines, *author;
X
X		enter information for an article in the newsgroup last set
X		with fw_group().  anum's should be entered in ascending
X		sequence.
X
X	fw_chg(new,sub,read,look)
X	int new, sub, read, look;
X
X		change the parameters for the current group.  To allow the
X		server interface to modify its setting for the group based
X		on what it discovered while scanning the articles.
X
X	fw_group() should be called once and only once for each group
X	hashenter()'ed.  The order of fw_group() calls determines the
X	order of vn's display to the user.  fw_group() calls may be made
X	after all the hashenter() calls have been made, or they may be
X	interleaved.  If no fw_art() calls are made following a particular
X	fw_group() call, no display page will be generated for that group.
X	If vns_news does not stick to the rules regarding calls to fw_group,
X	vn will exit with a fatal error message.
X
X	Rationale for this is for the server layer to have no knowledge
X	of device dependencies (the calls to fw_art will split up display
X	pages), or any of the vn structures beyond the newsgroup information.
X	And the newsgroup NODE structure has clearly documented pieces
X	which are legal for the server to read or use, and others which are
X	out-of-bounds.  It isolates things fairly well.
X
X	Note that vns_news hides all knowledge of the user's .newsrc file or
X	similar concept, and all knowledge of where articles live and how
X	they are administered.  Error handling is brutally simple.  If the
X	server doesn't obey the rules, vn will exit with a fatal error message
X	if it detects the fact.
X
X	lfirst and unsub are returned to the caller based on the command
X	line:
X
X		lfirst - non-zero if vn is supposed to go directly to
X			the newsgroup summary list on startup (-% option).
X
X		unsub - set non-zero if unsubscribed newsgroups are to
X			be updated on "write alls" (-U option).
X
X	We COULD have vn look for these, and nail them down, but most command
X	line options are things which make sense only to the server interface.
X	Different environments may have different options which make sense.
X	Might as well give the server interface control of the command line
X	exclusively, and advise to consistently use -% and -U if possible.
X
X	See below for some other support routines which might be useful for
X	vns_news().
X
X	In summary, what vns_news should do:
X
X		Call hashenter() for all the legitimate newsgroups.
X		After this, hashfind() may be called at any time to retrieve
X		the information about a group.
X
X		Call fw_group() once and only once for each group, in the
X		order newsgroups should be displayed to the user.  The order
X		need bear no relation to the order of hashenter calls.
X
X		After each fw_group call, shovel in article information with
X		fw_art calls.  Optionally call fw_chg() if anything ought to
X		be changed from the original fw_group call.
X
X		If there are fatal errors call printex() with an explanation.
X
X		To produce non-fatal diagnostics / informational messages,
X		call fgprintf().  If you absolutely want to produce the message,
X		backgrounded or not, you CAN simply output to stderr / stdout,
X		but think before doing it.  It's obnoxious to have a
X		backgrounded program stop on output before it's ready to
X		interact with you.
X
X		ISN'T THAT EASY?
X
XFILE *vns_aopen(art,hdr)
Xint art;
XARTHEADER *hdr;
X
X	Returns an open file pointer to article text for vn's use, or
X	NULL for failure.  Fills in the ARTHEADER argument, containing
X	information conceptually thought of as extracted from the "header"
X	lines.  File pointer should be positioned at the start of the
X	bonafide article text, if headers are contained in the file.  See
X	head.h for the items to be filled in.
X
X	If (*Massage)(), (*Postfunc)() or (*Mailfunc)() are defined, they
X	will be called with this same ARTHEADER instance when they are
X	called.  vns_aopen may set up any arguments in the priv item
X	for the convenience of these routines.
X
X	CAUTION:
X		hdr contains string pointers.  vns_aopen must be sure to
X		point to legitimate storage, not its stack.  And it SHOULD
X		NOT simply malloc() the strings every time without freeing
X		the old ones somehow - this will lose storage every time the
X		user reads a new article.  You MAY NOT assume that the same
X		instance of an ARTHEADER structure is passed to each
X		vns_aopen() call, either.  See str_tpool, and associated
X		routines, below.
X
Xvns_close(fp)
XFILE *fp;
X
X	Called to close article opened with vns_open().  In many instances
X	will simply be an fclose().  vn will NEVER have multiple articles
X	open, so vns_aopen / vns_aclose may maintain static information if
X	they like.
X
Xvns_gset(grp)
Xchar *grp;
X
X	Called as the user moves from page to page of the display.  vns_aopen
X	and vns_aclose calls will refer to this newsgroup.  May do chdir()'s
X	if it likes.
X
Xvns_exit(stat)
Xint stat;
X
X	Called before exit to allow the server layer to clean up.  Called
X	on normal exit & from within printex() (ie. DON'T call printex in
X	unconditionally in this routine)
X
Xvns_write(news,count)
XNODE **news;
Xint count;
X
X	Called to do whatever is the conceptual equivalent of updating the
X	user's .newsrc file.  news is an array of newsgroup nodes in the
X	order that fw_group was called, count is the length of the array.
X	Vn may have modified the rdnum items & the FLG_SUB flag based on
X	user interaction.  User exit, "write" commands, and "subscription"
X	commands will result in this call.  vn will set a flag bit, FLG_ECHG,
X	in the flag item of all newsgroups whose data it changed since last
X	call.  This bit may be used by vns_write to do selective updates, and
X	will be cleared for all groups following return from vns_write().
X
Xvns_asave(art,fp,count,name,mode)
Xint art;
XFILE *fp;
Xint count;
Xchar *name,*mode;
X
X	Called to shovel an article out to an open file pointer.  Intended
X	to allow the server interface to implement any kind of massaging
X	of the article text that is called for.  count starts with 0, and
X	counts the articles being written on this opening of the file.
X	name is the file name, and mode is the mode it was opened with.
X	This information is being passed in to allow implementation of
X	selective copy of header lines, etc. based on the state of the
X	file.  Note that it WILL exist since it's already been opened.  On
X	count 0, this routine may be interested in whether it's empty or not.
X	This routine WILL get called between vns_aopen and vns_aclose.
X
Xchar *Vns_version;
X
X	The server layer must define this string.  It should be a
X	short string which describes the server type / version (something
X	like "NNTP-1.0").  Will be printed as part of the vn version message.
X
XSome support routines:
X
X	regex(), regcmp(), strtok() and strpbrk() are standard SYSV
X	routines not normally available for BSD.  vn uses them, so
X	they are implemented in vn for those systems.  Thus, they are
X	available for use in the server interface.  Be careful with
X	strtok(), which retains context from call to call, if you are
X	not familiar with its use.  To free storage handed you by
X	regcmp(), use regfree() instead of free().
X
X	char *vn_env(var, def)
X	char *var, *def;
X
X	Use this in place of getenv() to be consistent with the rest of
X	vn.  This routine checks first for the variable prefixed with "VN"
X	if it doesn't already begin with "VN".  If neither the prefixed
X	or unprefixed name exists, it returns the def argument.  This allows
X	consistent override of EDITOR with VNEDITOR, etc.
X
X	printex(....)
X
X	printf style argument list.  Generates a fatal error and exits.
X	No newline necessary in the message, and printex() adds the error
X	number to its output automatically.  printex() may be called from
X	anywhere in the server interface to generate a fatal error, except
X	from vns_exit().
X
X	fgprintf(....)
X
X	nonfatal diagnostic / informational message.  printf style argument
X	list.  No extra formatting printed.  Will only print if program is
X	running in the foreground.  fgprintf() should be called only from
X	vns_envir() and vns_news(), as all the other routines come after
X	user interaction has begun.
X
X	char *
X	str_store(s)
X	char *s;
X
X	Returns a pointer to a permanent copy of a string.  DO NOT FREE THAT
X	POINTER!!  This routine is intended to save malloc() overhead, and
X	returns pointers into larger buffer allocated with a single request.
X
X	char *
X	str_tstore(ptr,s)
X	char *ptr;
X	char *s;
X
X	char *
X	str_tpool(n)
X	int n;
X
X	char **
X	str_taptr(ptr)
X	char *ptr;
X
X	str_tfree(ptr)
X	char *ptr;
X
X	Temporary string storage.  str_tpool is called with the maximum
X	number of strings to be allocated, and it returns a pointer to use
X	with the other calls (ptr argument).  str_tstore returns allocated
X	copies of strings.  str_taptr returns an address which may be treated
X	as a string array containing the str_tstore allocated strings
X	beginning with the NEXT str_tstore() call.  May be called several
X	times to get several array pointers.  str_tfree() frees all the strings
X	allocated on the given ptr returned from str_tpool, as well as the
X	pool pointer itself.  The returned addresses are no longer valid, nor
X	is the pool pointer.  Multiple pool pointers may be maintained.
X	Pool pointer contents should not be touched by the caller.  These
X	routines are intended for the convenience of vns_aopen().
X
XHEADER FILES:
X
Xserver.h includes the header files used by vn which are intended to be known
Xto server interface routines.  The server interface routines may include
Xsystem headers, this one, and their own headers.  Among their own headers
Xshould be a config_*.h containing parameters which are likely to be changed
Xfrom installation to installation, such as file paths.  server.h contains
Xnode.h and head.h, defining the NODE and ARTHEADER structures.
X
XA useful constant defined in server.h is RECLEN.  This should be used only
Xas an array dimension for a stack character buffer, intended to be large
Xenough to hold an arbitrary string.  If you use this constant, you are
Xmaking "large enough" the same value used in vn.  Use it for fgets()
Xbuffers, or sprintf buffers prior to making allocated copies of the string,
Xand you'll be working about the way vn does in a lot of places.
END_OF_FILE
if test 18433 -ne `wc -c <'SERVER.DOC'`; then
    echo shar: \"'SERVER.DOC'\" unpacked with wrong size!
fi
# end of 'SERVER.DOC'
fi
if test -f 'amiga.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'amiga.c'\"
else
echo shar: Extracting \"'amiga.c'\" \(14130 characters\)
sed "s/^X//" >'amiga.c' <<'END_OF_FILE'
X#ifdef	amiga
X
X#include <stdio.h>
X#include <string.h>
X#include <pwd.h>
X
X#ifdef vn
X#include "vn.h"
X#endif
X
X#include	<exec/types.h>
X#include	<exec/io.h>
X#include	<intuition/intuition.h>
X#include	<devices/console.h>
X
Xchar * GetConfig(char *field, char *def);
X
X#define INTUITION_REV	0L
X#define	NEW 		1006L
X#define	CRWIDTH		8
X#define	CRHEIGHT	8
X
X#define CTRL	0x0100		/* Control flag, or'ed in		*/
X#define META	0x0200		/* Meta flag, or'ed in			*/
X#define CTLX	0x0400		/* ^X flag, or'ed in			*/
X#define SPEC	0x0800		/* special key (function keys)		*/
X#define MOUS	0x1000		/* alternative input device (mouse)	*/
X#define	SHFT	0x2000		/* shifted (for function keys)		*/
X#define	ALTD	0x4000		/* ALT key...				*/
X#define	NSTRING	128		/* # of bytes, string buffers		*/
X
Xstruct IntuitionBase *IntuitionBase;
Xstruct Window *win;
Xstruct IOStdReq con;		/* ptr to console device driver handle */
X
X/*	Intuition Function type declarations	*/
X
Xstruct IntuitionBase *OpenLibrary();
Xstruct Window *OpenWindow();
Xstruct IntuiMessage *GetMsg();
X
Xtypedef struct {
X	short rw_code;		/* normal keycode to generate */
X	short rw_scode;		/* shifted  "  */
X	short rw_ccode;		/* control  "  */
X} RKEY;
X
X/* raw keycode scan code to emacs keycode translation table */
X
XRKEY keytrans[0x60] = {
X
X/*	CODE	NORM	SHIFT	CTRL */
X/*	0x00,*/	'`',	'~',	0,
X/*	0x01,*/	'1',	'!',	0,
X/*	0x02,*/	'2',	'@',	0,
X/*	0x03,*/	'3',	'#',	0,
X/*	0x04,*/	'4',	'$',	0,
X/*	0x05,*/	'5',	'%',	0,
X/*	0x06,*/	'6',	'^',	0,
X/*	0x07,*/	'7',	'&',	0,
X/*	0x08,*/	'8',	'*',	0,	
X/*	0x09,*/	'9',	'(',	0,
X/*	0x0a,*/	'0',	')',	0,
X/*	0x0b,*/	'-',	'_',	0,
X/*	0x0c,*/	'=',	'+',	0,
X/*	0x0d,*/	'\\',	'|',	0,
X/*	0x0e,*/	0,	0,	0,
X/*	0x0f,*/	SPEC|'C',	'0',	CTRL|SPEC|'C',
X/*	0x10,*/	'q',	'Q',	CTRL|'Q',
X/*	0x11,*/	'w',	'W',	CTRL|'W',
X/*	0x12,*/	'e',	'E',	CTRL|'E',
X/*	0x13,*/	'r',	'R',	CTRL|'R',
X/*	0x14,*/	't',	'T',	CTRL|'T',
X/*	0x15,*/	'y',	'Y',	CTRL|'Y',
X/*	0x16,*/	'u',	'U',	CTRL|'U',
X/*	0x17,*/	'i',	'I',	CTRL|'I',
X/*	0x18,*/	'o',	'O',	CTRL|'O',
X/*	0x19,*/	'p',	'P',	CTRL|'P',
X/*	0x1a,*/	'[',	'{',	0,
X/*	0x1b,*/	']',	'}',	0,
X/*	0x1c,*/	0,	0,	0,
X/*	0x1d,*/	SPEC|'>','1',	CTRL|SPEC|'>',
X/*	0x1e,*/	SPEC|'N','2',	CTRL|SPEC|'N',
X/*	0x1f,*/	SPEC|'V','3',	CTRL|SPEC|'V',
X/*	0x20,*/	'a',	'A',	CTRL|'A',
X/*	0x21,*/	's',	'S',	CTRL|'S',
X/*	0x22,*/	'd',	'D',	CTRL|'D',
X/*	0x23,*/	'f',	'F',	CTRL|'F',
X/*	0x24,*/	'g',	'G',	CTRL|'G',
X/*	0x25,*/	'h',	'H',	CTRL|'H',
X/*	0x26,*/	'j',	'J',	CTRL|'J',
X/*	0x27,*/	'k',	'K',	CTRL|'K',
X/*	0x28,*/	'l',	'L',	CTRL|'L',
X/*	0x29,*/	';',	':',	0,
X/*	0x2a,*/	39,	34,	0,
X/*	0x2b,*/	0,	0,	0,
X/*	0x2c,*/	0,	0,	0,
X/*	0x2d,*/	SPEC|'B','4',	CTRL|SPEC|'B',
X/*	0x2e,*/	0,	'5',		0,
X/*	0x2f,*/	SPEC|'F','6',	CTRL|SPEC|'F',
X	/* this key is probably mapped on forign AIMIGA keyboards */
X/*	0x30,*/	0,	0,	0,
X/*	0x31,*/	'z',	'Z',	CTRL|'Z',
X/*	0x32,*/	'x',	'X',	CTRL|'X',
X/*	0x33,*/	'c',	'C',	CTRL|'C',
X/*	0x34,*/	'v',	'V',	CTRL|'V',
X/*	0x35,*/	'b',	'B',	CTRL|'B',
X/*	0x36,*/	'n',	'N',	CTRL|'N',
X/*	0x37,*/	'm',	'M',	CTRL|'M',
X/*	0x38,*/	',',	'<',	0,
X/*	0x39,*/	'.',	'>',	0,
X/*	0x3a,*/	'/',	'?',	0,
X/*	0x3b,*/	0,	0,	0,
X/*	0x3c,*/	SPEC|'D','.',	CTRL|SPEC|'D',
X/*	0x3d,*/	SPEC|'<','7',	CTRL|SPEC|'<',
X/*	0x3e,*/	SPEC|'P','8',	CTRL|SPEC|'P',
X/*	0x3f,*/	SPEC|'Z','9',	CTRL|SPEC|'Z',
X/*	0x40,*/	' ',	SHFT|' ',	0,
X/*	0x41,*/	CTRL|'H',	SHFT|'D',	0,
X/*	0x42,*/	CTRL|'I',	SHFT|'I',	0,
X/*	0x43,*/	CTRL|'M', CTRL|'M', CTRL|'M',
X/*	0x44,*/	CTRL|'M', CTRL|'M', CTRL|'M',
X/*	0x45,*/	CTRL|'[',	0,	0,
X/*	0x46,*/	SPEC|'D',	0,	0,
X/*	0x47,*/	0,	0,	0,
X/*	0x48,*/	0,	0,	0,
X/*	0x49,*/	0,	0,	0,
X/*	0x4a,*/	'-',	0,	0,
X/*	0x4b,*/	0,	0,	0,
X/*	0x4c,*/	SPEC|'P',	SHFT|SPEC|'P',	CTRL|SPEC|'P',
X/*	0x4d,*/	SPEC|'N',	SHFT|SPEC|'N',	CTRL|SPEC|'N',
X/*	0x4e,*/	SPEC|'F',	SHFT|SPEC|'F',	CTRL|SPEC|'F',
X/*	0x4f,*/	SPEC|'B',	SHFT|SPEC|'B',	CTRL|SPEC|'B',
X/*	0x50,*/	SPEC|'1',	SHFT|SPEC|'1',	CTRL|SPEC|'1',
X/*	0x51,*/	SPEC|'2',	SHFT|SPEC|'2',	CTRL|SPEC|'2',
X/*	0x52,*/	SPEC|'3',	SHFT|SPEC|'3',	CTRL|SPEC|'3',
X/*	0x53,*/	SPEC|'4',	SHFT|SPEC|'4',	CTRL|SPEC|'4',
X/*	0x54,*/	SPEC|'5',	SHFT|SPEC|'5',	CTRL|SPEC|'5',
X/*	0x55,*/	SPEC|'6',	SHFT|SPEC|'6',	CTRL|SPEC|'6',
X/*	0x56,*/	SPEC|'7',	SHFT|SPEC|'7',	CTRL|SPEC|'7',
X/*	0x57,*/	SPEC|'8',	SHFT|SPEC|'8',	CTRL|SPEC|'8',
X/*	0x58,*/	SPEC|'9',	SHFT|SPEC|'9',	CTRL|SPEC|'9',
X/*	0x59,*/	SPEC|'0',	SHFT|SPEC|'0',	CTRL|SPEC|'0',
X/*	0x5a,*/	'(',	0,	0,
X/*	0x5b,*/	')',	0,	0,
X/*	0x5c,*/	'/',	0,	0,
X/*	0x5d,*/	'*',	0,	0,
X/*	0x5e,*/	0,	0,	0,
X/*	0x5f,*/	SPEC|'?',	0,	0,
X};
X
X/* some keyboard keys current states */
X
Xint r_shiftflag;	/* right shift key */
Xint l_shiftflag;	/* left shift key */
Xint r_altflag;		/* right alt key */
Xint l_altflag;		/* left alt key */
Xint r_amiflag;		/* right amiga key */
Xint l_amiflag;		/* left amiga key */
Xint ctrlflag;		/* control key */
Xint lockflag;		/* shift lock key */
X
X/*	output buffers and pointers	*/
X
X#define OBUFSIZE	1024L
X
Xchar out_buf[OBUFSIZE+1];	/* output character buffer */
Xint out_ptr = 0;		/* index to next char to put in buffer */
X
X/*	input buffers and pointers	*/
X
X#define	IBUFSIZE	64	/* this must be a power of 2 */
X
Xunsigned char in_buf[IBUFSIZE];	/* input character buffer */
Xint in_next = 0;		/* pos to retrieve next input character */
Xint in_last = 0;		/* pos to place most recent input character */
X
Xin_init()	/* initialize the input buffer */
X
X{
X	in_next = in_last = 0;
X}
X
Xin_check()	/* is the input buffer non-empty? */
X
X{
X	if (in_next == in_last)
X		return(FALSE);
X	else
X		return(TRUE);
X}
X
Xin_put(event)
X
Xint event;	/* event to enter into the input buffer */
X
X{
X	in_buf[in_last++] = event;
X	in_last &= (IBUFSIZE - 1);
X}
X
Xint in_get()	/* get an event from the input buffer */
X
X{
X	register int event;	/* event to return */
X
X	event = in_buf[in_next++];
X	in_next &= (IBUFSIZE - 1);
X	return(event);
X}
X
X/*
X * This function is called once to set up the terminal device streams.
X */
Xttopen()
X{
X	struct NewWindow new_win;
X	int i;
X	char *pal;
X	extern char *getenv ();
X
X	/* open the intuition library */
X	IntuitionBase = (struct IntuitionBase *)
X		OpenLibrary("intuition.library", INTUITION_REV);
X	if (IntuitionBase == NULL) {
X		printf("%%Can not open Intuition\n");
X		exit(-1);
X	}
X
X	/* read the UULIB:Config file or env:palamiga */
X	if ((pal = GetConfig("PALAMIGA", NULL)) == NULL)
X		pal = getenv ("PALAMIGA");
X	if (pal == NULL)
X		pal = "N";
X	/* initialize the new windows attributes */
X	new_win.LeftEdge = 0;
X	new_win.TopEdge = 0;
X	new_win.Width = 640;
X	if (*pal == 'Y')
X		new_win.Height = 256;
X	else
X		new_win.Height = 200;
X	new_win.DetailPen = 0;
X	new_win.BlockPen = 1;
X	new_win.Title = (unsigned char *)"vn res1.1 Amiga 17/11/90";
X	new_win.Flags = WINDOWCLOSE | SMART_REFRESH | ACTIVATE |
X		WINDOWDRAG | WINDOWDEPTH | /*WINDOWSIZING |*/ SIZEBRIGHT |
X		RMBTRAP | NOCAREREFRESH;
X	new_win.IDCMPFlags = CLOSEWINDOW | /*NEWSIZE |*/ MOUSEBUTTONS |
X		RAWKEY;
X	new_win.Type = WBENCHSCREEN;
X	new_win.FirstGadget = NULL;
X	new_win.CheckMark = NULL;
X	new_win.Screen = NULL;
X	new_win.BitMap = NULL;
X	new_win.MinWidth = 100;
X	new_win.MinHeight = 25;
X	new_win.MaxWidth = 640;
X	if (*pal == 'Y')
X		new_win.MaxHeight = 256;
X	else
X		new_win.MaxHeight = 200;
X
X	/* open the window! */
X	win = (struct Window *)OpenWindow(&new_win);
X	if (win == NULL) {
X		printf("%%Can not open a window\n");
X		exit(-2);
X	}
X
X	/* and open up the console for output */
X	con.io_Data = (APTR)win;
X	OpenDevice("console.device", 0, &con, 0);
X
X	/* and init all the keyboard flags */
X	r_shiftflag = FALSE;
X	l_shiftflag = FALSE;
X	r_altflag = FALSE;
X	l_altflag = FALSE;
X	r_amiflag = FALSE;
X	l_amiflag = FALSE;
X	ctrlflag = FALSE;
X	lockflag = FALSE;
X
X	/* initialize our private event queue */
X	in_init();
X
X}
X
X/*
X * This function gets called just before we go back home to the command
X * interpreter. 
X */
Xttclose()
X
X{
X	/* make sure there is no pending output */
X	ttflush();
X
X	/* and now close up shop */
X	CloseDevice(&con);
X	CloseWindow(win);
X	OpenWorkBench();
X}
X
X/*
X * Write a character to the display. 
X */
X
Xttputc(c)
X
Xchar c;
X
X{
X	/* add the character to the output buffer */
X        out_buf[out_ptr++] = c;
X
X        /* send the buffer out if we are at the limit */
X        if (out_ptr >= OBUFSIZE)
X                ttflush();
X}
X
X/*
X * Flush terminal buffer. Does real work where the terminal output is buffered
X * up. A no-operation on systems where byte at a time terminal I/O is done.
X */
X
Xttflush()
X
X{
X	/* if there are any characters waiting to display... */
X        if (out_ptr) {
X        	out_buf[out_ptr] = 0;	/* terminate the buffer string */
X        	sendcon(out_buf);	/* send them out */
X	        out_ptr = 0;		/* and reset the buffer */
X	}
X}
X
X/*
X * Read a character from the terminal.
X */
X
Xttgetc()
X
X{
X	/* make sure there is no pending output */
Xnxtchr:	ttflush();
X
X	/* if it is already buffered up, get it */
X	if (in_check())
X		return(in_get());
X
X	/* process an INTUITION event (possibly loading the input buffer) */
X	doevent();
X	goto nxtchr;
X}
X
X
Xdoevent()
X
X{
X	register int eventX, eventY;	/* local copies of the event info */
X	struct IntuiMessage *event;	/* current event to repond to */
X	ULONG class;	/* class of event */
X	USHORT code;	/* data code */
X	SHORT x,y;	/* mouse x/y position at time of event */
X	char buf[128];	/*temp buff*/
X
X	/* wait for an event to occur */
X	Wait(1 << win->UserPort->mp_SigBit);
X
X	/* get the event and parse it up */
X	while (event = GetMsg(win->UserPort)) {
X		class = event->Class;
X		code = event->Code;
X		eventX = event->MouseX;
X		eventY = event->MouseY;
X		ReplyMsg(event);
X
X		/* a normal keystroke? */
X		if (class == RAWKEY) {
X			dokey(code);
X			continue;
X		}
X
X		/* User clicked on the close gadget! */
X		if (class == CLOSEWINDOW) {
X#ifdef vn
X			stuffibuf('q', 0, 0);	/* force quit for vn = 'q' */
X#else
X			stuffibuf(255, 0, 0);	/* fake a char to force quit to work */
X#endif
X		}
X
X		/* resolve the mouse address (border adjusted) */
X		if (class == NEWSIZE) {
X			x = (win->Width - 5) / CRWIDTH;
X			y = (win->Height - 10) / CRHEIGHT;
X		} else {
X			x = (eventX - 5) / CRWIDTH;
X			y = (eventY - 10) / CRHEIGHT;
X		}
X		if (x > 77)
X			x = 77;
X		if (y > 23)
X			y = 23;
X
X		/* are we resizing the window? */
X		if (class == NEWSIZE) {
X			stuffibuf(MOUS | '1', x, y);
X			continue;
X		}
X
X		/* and lastly, a mouse button press */
X		switch (code) {
X			case 104:	stuffibuf(MOUS | mod('a'), x, y);
X					break;
X			case 232:	stuffibuf(MOUS | mod('b'), x, y);
X					break;
X			case 105:	stuffibuf(MOUS | mod('e'), x, y);
X					break;
X			case 233:	stuffibuf(MOUS | mod('f'), x, y);
X					break;
X		}
X	}
X	return;
X}
X
Xint mod(c)	/* modify a character by the current shift and control flags */
X
Xint c;		/* original character */
X
X{
X	/* first apply the shift and control modifiers */
X	if (l_shiftflag || r_shiftflag || lockflag)
X		c -= 32;
X	if (ctrlflag)
X		c |= CTRL;
X	return(c);
X}
X
Xsendcon(buf)	/* send a string to the console */
X
Xchar *buf;	/* buffer to write out */
X
X{
X	/* initialize the IO request */
X	con.io_Data = (APTR)buf;
X	con.io_Length = strlen(buf);
X	con.io_Command = CMD_WRITE;
X
X	/* and perform the I/O */
X	SendIO(&con);
X}
X
X
X/* process an incomming keyboard code */
X
Xdokey(code)
X
Xint code;	/* raw keycode to convert */
X
X{
X	register int ekey;	/* translate key */
X	register int dir;	/* key direction (up/down) */
X	char buf[NSTRING];
X
X	/* decode the direction of the key */
X	dir = TRUE;
X	if (code > 127) {
X		code = code & 127;
X		dir = FALSE;
X	}
X
X	/* process various shift keys */
X	if (code >= 0x60) {
X		switch (code) {
X
X			case 0x60:	l_shiftflag = dir;	break;
X			case 0x61:	r_shiftflag = dir;	break;
X			case 0x62:	lockflag    = dir;	break;
X			case 0x63:	ctrlflag    = dir;	break;
X			case 0x64:	l_altflag   = dir;	break;
X			case 0x65:	r_altflag   = dir;	break;
X			case 0x66:	l_amiflag   = dir;	break;
X			case 0x67:	r_amiflag   = dir;	break;
X
X		}
X		return;
X	}
X
X#ifdef  vn
X	/* for vn catch cursor keys */
X	switch (code) {
X	case 0x4c:
X		code = 0x27;
X		break;
X	case 0x4d:
X		code = 0x26;
X		break;
X	case 0x4e:
X		code = 0x44;
X		break;
X	case 0x4f:
X		code = 0x41;
X		break;
X	default:
X		break;
X	}
X#endif
X	/* up keystrokes are ignored for the rest of these */
X	if (dir == FALSE)
X		return;
X
X	/* first apply the shift and control modifiers */
X	if (ctrlflag)
X		ekey = keytrans[code].rw_ccode;
X	else if (l_shiftflag || r_shiftflag || lockflag)
X		ekey = keytrans[code].rw_scode;
X	else
X		ekey = keytrans[code].rw_code;
X
X	/* now apply the ALTD modifier */
X	if (r_altflag || l_altflag)
X		ekey |= ALTD;
X
X	/* apply the META prefix */
X	if (r_amiflag || l_amiflag) {
X		if ('a' <= ekey && ekey <= 'z')
X			ekey -= 32;
X		ekey |= META;
X	}
X
X	/* and place it in the input buffer */
X	stuffibuf(ekey, 0, 0);
X}
X
Xstuffibuf(key, x, y)	/* stuff a key in the input buffer */
X
Xint key;	/* extended keystroke to remember */
Xint x, y;	/* mouse position to record */
X
X{
X	register int upper;	/* upper extended bits of key */
X
X	/* split the extended keystroke */
X	upper = key >> 8;
X	key = key & 255;
X
X	/* if it is JUST control... encode it in! */
X	if (upper == (CTRL >> 8)) {
X		in_put(key - 64);
X		return;
X	}
X
X	/* if it is normal, just place it inqueue */
X	if (upper == 0) {
X		in_put(key);
X		return;
X	}
X
X	/* queue up an extended escape sequence */
X	in_put(0);		/* escape indicator */
X	in_put(upper);		/* event type */
X	if (upper & (MOUS >> 8)) {
X		in_put(x);	/* x position */
X		in_put(y);	/* y position */
X	}
X
X	in_put(key);		/* event code */
X	return;
X}
X
X#define system(a)	Execute(a, 0, 0)
X
Xstruct passwd *
Xgetpwuid (uid)
Xint	uid;
X{
X	static struct passwd passwd;
X
X	if ((passwd.pw_dir = GetConfig("VNUSERDIR", NULL)) == NULL)
X		passwd.pw_dir = "s:";
X	if ((passwd.pw_name = GetConfig("UserName", NULL)) == NULL)
X		passwd.pw_name = getenv ("UserName");
X	if (passwd.pw_name == (char *)NULL)
X		passwd.pw_name = "User";
X
X	return (&passwd);
X}
X
Xstruct passwd *
Xgetpwnam (name)
Xchar	*name;
X{
X	static struct passwd passwd;
X	static char	pw_name[20];
X
X	if ((passwd.pw_dir = GetConfig("VNUSERDIR", NULL)) == NULL)
X		passwd.pw_dir = "s:";
X	passwd.pw_name = pw_name;
X	strncpy (pw_name, name, sizeof (pw_name));
X
X	return (&passwd);
X}
X
Xint
Xgetuid ()
X{
X	return (0);
X}
X
Xint
Xlink (from, to)
Xchar	*from, *to;
X{
X	char	command[128];
X	int	rv;
X
X	strcpy (command, "copy ");
X	strcat (command, from);
X	strcat (command, " TO ");
X	strcat (command, to);
X	strcat (command, " QUIET");
X
X	rv = system (command);
X	if (rv < 0)
X		return (0);
X	else
X		return (-1);
X}
X
X#endif
END_OF_FILE
if test 14130 -ne `wc -c <'amiga.c'`; then
    echo shar: \"'amiga.c'\" unpacked with wrong size!
fi
# end of 'amiga.c'
fi
if test -f 'help.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'help.c'\"
else
echo shar: Extracting \"'help.c'\" \(9154 characters\)
sed "s/^X//" >'help.c' <<'END_OF_FILE'
X/*
X** vn news reader.
X**
X** help.c - print help
X**
X** see copyright disclaimer / history in vn.c source file
X*/
X#include <stdio.h>
X#include <setjmp.h>
X#include "config.h"
X#include "tty.h"
X#include "tune.h"
X#include "node.h"
X#include "page.h"
X#include "reader.h"
X#include "vn.h"
X
Xextern int L_allow;
Xextern int C_allow;
Xextern int Digest;
Xextern char *Contstr;
Xextern char Cxptoi[], Cxrtoi[];
X
Xextern int (*Hookfunc)();
Xextern char *(*Hookhelp)();
X
Xstatic h_print ();
X
X/*
X	Help message table.  Character for command, plus its help
X	message.  Table order is order of presentation to user.
X*/
Xstatic struct HELPTAB
X{
X	char cmd, *msg;
X	int dig;
X	char *amsg;
X} 
XHelptab [] =
X{
X	{ QUIT, "quit", 1, NULL},
X	{ UP, "(or up arrow) move up [number of lines]", 1, NULL},
X	{ DOWN, "(or down arrow) move down [number of lines]", 1, NULL},
X#ifdef PAGEARROW
X	{ BACK, "(or left arrow) previous page [number of pages]", 1, NULL},
X	{ FORWARD, "(or right arrow) next page [number of pages]", 1, NULL},
X#else
X	{ BACK, "previous page [number of pages]", 1, NULL},
X	{ FORWARD, "next page [number of pages]", 1, NULL},
X#endif
X	{ GRPBACK, "previous newsgroup [number of newsgroups]", 0, NULL },
X	{ GRPFORWARD, "next newsgroup [number of newsgroups]", 0, NULL },
X	{ TOPMOVE, "move to top of page", 1, NULL},
X	{ BOTMOVE, "move to bottom of page", 1, NULL},
X	{ ALTBOTTOM, "move to bottom of page (alternate L)", 1, NULL},
X	{ MIDMOVE, "move to middle of page", 1, NULL},
X	{ DIGEST, "unpack digest", 1, "exit digest"},
X	{ READ, "read article [number of articles]", 1, NULL},
X	{ ALTREAD, "read article (alternate 'r')", 1, NULL},
X	{ READALL, "read all articles on page", 1, NULL},
X	{ READSTRING, "specify articles to read", 1, NULL},
X	{ SAVE, "save or pipe article [number of articles]", 1, NULL},
X	{ SAVEALL, "save or pipe all articles on page", 1, NULL},
X	{ SAVESTRING, "specify articles to save", 1, NULL},
X	{ ALTSAVE, "specify articles to save (alternate ctl-s)", 1, NULL},
X	{ PRINT, "print article [number of articles]", 1, NULL},
X	{ PRINTALL, "print all article on page", 1, NULL},
X	{ PRINTSTRING, "specify articles to print", 1, NULL},
X	{ UPDATE, "update .newsrc status to cursor", 0, NULL},
X	{ UPALL, "update .newsrc status for whole newsgroup", 0, NULL},
X	{ UPSEEN, "update .newsrc status for all pages displayed", 0, NULL},
X	{ ORGGRP, "recover original .newsrc status for newsgroup", 0, NULL},
X	{ ORGSTAT, "recover all original .newsrc status", 0, NULL},
X	{ SSTAT, "display count of groups and pages - shown and total", 0, NULL},
X	{ GRPLIST, "list newsgroups with new article, updated counts", 0, NULL},
X	{ NEWGROUP, "specify newsgroup to display and/or resubscribe to", 1, NULL},
X	{ UNSUBSCRIBE, "unsubscribe from group", 0, NULL},
X	{ MARK, "mark/unmark article [number of articles]", 1, NULL},
X	{ ART_MARK, "mark/unmark article [number of articles]", 1, NULL},
X	{ UNMARK, "erase marks on articles", 1, NULL},
X	{ MARKSTRING, "specify articles to mark/unmark", 1, NULL},
X	{ HEADTOG, "toggle flag for display of headers when reading", 1, NULL},
X	{ SETROT, "toggle rotation for reading", 1, NULL},
X	{ REDRAW, "redraw screen", 1, NULL},
X#ifdef amiga
X	{ UNESC, "escape to AMIGADOS to execute a command", 1, NULL},
X#else
X	{ UNESC, "escape to UNIX to execute a command", 1, NULL},
X#endif
X	{ PRTVERSION, "show vn version", 1, NULL},
X	{ HELP, "show this help menu", 1, NULL}
X};
X
X#define HTSIZE (sizeof(Helptab)/sizeof(struct HELPTAB))
X
X
X#ifdef amiga
Xextern char pr_buf[];
Xextern ttputc ();
X#endif
X
X#define HHLINES 5	/* lines (CRs + 1) contained in HELP_HEAD */
X/*
X	help from main screen
X*/
Xhelp ()
X{
X	int i,lcount,lim;
X	char *hs;
X	char c;
X
X	term_set (ERASE);
X	lim = L_allow + RECBIAS - 2;
X#ifdef amiga
X	sprintf(pr_buf,"%s\n","[...] = effect of optional number preceding command\n");
X	tputs(pr_buf,1,ttputc);
X	sprintf(pr_buf,"%s\n","pipes are specified by filenames beginning with |\n");
X	tputs(pr_buf,1,ttputc);
X	sprintf(pr_buf,"%s\n","articles specified as a list of numbers, title search string, or\n");
X	tputs(pr_buf,1,ttputc);
X	sprintf(pr_buf,"%s\n","	* to specify marked articles.  ! may be used to negate any\n");
X	tputs(pr_buf,1,ttputc);
X#else
X	printf("%s\n","[...] = effect of optional number preceding command\n");
X	printf("%s\n","pipes are specified by filenames beginning with |\n");
X	printf("%s\n","articles specified as a list of numbers, title search string, or\n");
X	printf("%s\n","	* to specify marked articles.  ! may be used to negate any\n");
X#endif
X	lcount = HHLINES;
X	for (i=0; i < HTSIZE; ++i)
X	{
X		if (Digest && !(Helptab[i].dig))
X			continue;
X		if (Hookfunc != NULL && (*Hookfunc)(Helptab[i].cmd,0,0) >= 0)
X			continue;
X		++lcount;
X		if (Digest && Helptab[i].amsg != NULL)
X			h_print (Cxptoi[Helptab[i].cmd],Helptab[i].amsg);
X		else
X			h_print (Cxptoi[Helptab[i].cmd],Helptab[i].msg);
X		if (lcount >= lim)
X		{
X#ifdef amiga
X			sprintf (pr_buf,"\n%s",Contstr);
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("\n%s",Contstr);
X#endif
X			getnoctl ();
X			term_set (MOVE,0,lim+1);
X			term_set (ZAP,0,strlen(Contstr));
X			term_set (MOVE,0,lim-1);
X			putchar ('\n');
X			lcount = 0;
X		}
X	}
X	if (Hookhelp != NULL)
X	{
X		for (hs=(*Hookhelp)(0,1,&c);
X				hs != NULL; hs = (*Hookhelp)(0,0,&c))
X		{
X			++lcount;
X			h_print (Cxptoi[c],hs);
X			if (lcount >= lim)
X			{
X#ifdef amiga
X				sprintf (pr_buf,"\n%s",Contstr);
X				tputs(pr_buf,1,ttputc);
X#else
X				printf ("\n%s",Contstr);
X#endif
X				getnoctl ();
X				term_set (MOVE,0,lim+1);
X				term_set (ZAP,0,strlen(Contstr));
X				term_set (MOVE,0,lim-1);
X				putchar ('\n');
X				lcount = 0;
X			}
X		}
X	}
X	if (lcount > 0)
X	{
X#ifdef amiga
X		sprintf (pr_buf,"\n%s",Contstr);
X		tputs(pr_buf,1,ttputc);
X#else
X		printf ("\n%s",Contstr);
X#endif
X		getnoctl ();
X	}
X}
X
X/*
X	help from reader
X*/
Xhelp_rd()
X{
X	char *hs;
X	char c;
X
X#ifdef amiga
X	sprintf(pr_buf,"\n");	/* "confused" tab expansion on first line */
X	tputs(pr_buf,1,ttputc);
X#else
X	printf("\n");	/* "confused" tab expansion on first line */
X#endif
X
X	hr_print (Cxrtoi[PG_NEXT],HPG_NEXT);
X	hr_print (Cxrtoi[PG_QUIT],HPG_QUIT);
X	hr_print (Cxrtoi[PG_FLIP],HPG_FLIP);
X	hr_print (Cxrtoi[PG_REWIND],HPG_REWIND);
X	hr_print (Cxrtoi[PG_WIND],HPG_WIND);
X	hr_print (Cxrtoi[PG_SEARCH],HPG_SEARCH);
X	hr_print (Cxrtoi[PG_STEP],HPG_STEP);
X	hr_print (Cxrtoi[PG_REPLY],HPG_REPLY);
X	hr_print (Cxrtoi[PG_FOLLOW],HPG_FOLLOW);
X	hr_print (Cxrtoi[SAVE],HPG_SAVE);
X	hr_print (Cxrtoi[PRINT],HPG_PRINT);
X	hr_print (Cxrtoi[SETROT],HPG_ROT);
X	hr_print (Cxrtoi[HEADTOG],HPG_HEAD);
X	hr_print (Cxrtoi[PG_HELP],HPG_HELP);
X	if (Hookhelp != NULL)
X	{
X		for (hs=(*Hookhelp)(1,1,&c);
X				hs != NULL; hs = (*Hookhelp)(1,0,&c))
X			h_print (Cxrtoi[c],hs);
X	}
X#ifdef amiga
X	sprintf (pr_buf,"%s\n",HPG_DEF);
X	tputs(pr_buf,1,ttputc);
X#else
X	printf ("%s\n",HPG_DEF);
X#endif
X}
X
Xhr_print(c,msg)
Xchar c;
Xchar *msg;
X{
X	if (Hookfunc == NULL || (*Hookfunc)(c,1,0) < 0)
X		h_print(c,msg);
X}
X
Xsrch_help(c,dig)
Xchar c;
Xint *dig;
X{
X	int i;
X
X	for (i=0; i < HTSIZE; ++i)
X		if (Helptab[i].cmd == c)
X			break;
X	if (i < HTSIZE)
X	{
X		*dig = Helptab[i].dig;
X		return (0);
X	}
X	return(-1);
X}
X
X/*
X	h_print prints a character and a legend for a help menu.
X*/
Xstatic
Xh_print(c,s)
Xchar c,*s;
X{
X	if (strlen(s) > (C_allow - 14))
X		s [C_allow - 14] = '\0';
X	if (c > ' ' && c != '\177') {
X#ifdef amiga
X		sprintf (pr_buf,"	 %c - %s\n",c,s);
X		tputs(pr_buf,1,ttputc);
X#else
X		printf ("	 %c - %s\n",c,s);
X#endif
X	} else
X	{
X		switch (c)
X		{
X		case '\177':
X#ifdef amiga
X			sprintf (pr_buf,"  <delete> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("  <delete> - %s\n",s);  
X#endif
X			break;
X		case '\040':
X#ifdef amiga
X			sprintf (pr_buf,"   <space> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("   <space> - %s\n",s);  
X#endif
X			break;
X		case '\033':
X#ifdef amiga
X			sprintf (pr_buf,"  <escape> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("  <escape> - %s\n",s);  
X#endif
X			break;
X		case '\n':
X#ifdef amiga
X			sprintf (pr_buf,"  <return> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("  <return> - %s\n",s);  
X#endif
X			break;
X		case '\t':
X#ifdef amiga
X			sprintf (pr_buf,"     <tab> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("     <tab> - %s\n",s);  
X#endif
X			break;
X		case '\b':
X#ifdef amiga
X			sprintf (pr_buf," <back sp> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf (" <back sp> - %s\n",s);  
X#endif
X			break;
X		case '\f':
X#ifdef amiga
X			sprintf (pr_buf,"<formfeed> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("<formfeed> - %s\n",s);  
X#endif
X			break;
X		case '\07':
X#ifdef amiga
X			sprintf (pr_buf,"    <bell> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("    <bell> - %s\n",s);  
X#endif
X			break;
X		case '\0':
X#ifdef amiga
X			sprintf (pr_buf,"    <null> - %s\n",s);  
X			tputs(pr_buf,1,ttputc);
X#else
X			printf ("    <null> - %s\n",s);  
X#endif
X			break;
X		default:
X			if (c < '\033')
X			{
X				c += 'a' - 1;
X#ifdef amiga
X				sprintf(pr_buf," control-%c - %s\n",c,s);
X				tputs(pr_buf,1,ttputc);
X#else
X				printf(" control-%c - %s\n",c,s);
X#endif
X			}
X			else {
X#ifdef amiga
X				printf(pr_buf,"       %c0%o - %s\n",'\\',(int) c,s);
X				tputs(pr_buf,1,ttputc);
X#else
X				printf("       %c0%o - %s\n",'\\',(int) c,s);
X#endif
X			}
X			break;
X		}
X	}
X}
END_OF_FILE
if test 9154 -ne `wc -c <'help.c'`; then
    echo shar: \"'help.c'\" unpacked with wrong size!
fi
# end of 'help.c'
fi
if test -f 'termcap.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'termcap.c'\"
else
echo shar: Extracting \"'termcap.c'\" \(7492 characters\)
sed "s/^X//" >'termcap.c' <<'END_OF_FILE'
X/*
X *	termcap.c	V1.1	20/7/87		agc	Joypace Ltd
X *
X *	Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
X *	This file may be freely distributed provided that this notice
X *	remains attached.
X *
X *	A public domain implementation of the termcap(3) routines.
X *
X *
X *
X *	 Klamer Schutte	      V1.2    Nov. 1988
X *
X *   - Can match multiple terminal names		 [tgetent]
X *   - Removal of **area assignments			 [tgetstr]
X *
X *	 Terrence W. Holm     V1.3    May, Sep, Oct.  1988
X *
X *   - Correct when TERM != name and TERMCAP is defined	 [tgetent]
X *   - Correct the comparison for the terminal name 	 [tgetent]
X *   - Correct the value of ^x escapes              	 [tgetstr]
X *   - Added %r to reverse row/column			 [tgoto]
X *   - Fixed end of definition test			 [tgetnum/flag/str]
X *
X *	 Terrence W. Holm     V1.4    Jan. 1989
X *
X *   - Incorporated Klamer's V1.2 fixes into V1.3
X *   - Added %d, (old %d is now %2)			 [tgoto]
X *   - Allow '#' comments in definition file		 [tgetent]
X */
X
X#include <lib.h>
X#include <termcap.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <ctype.h>
X#include <string.h>
X
Xchar *capab = (char *)NULL;		/* the capability itself */
X
X#if 0
X/*  The following are not yet used.  */
Xextern short ospeed;		/* output speed */
Xextern char PC;			/* padding character */
Xextern char *BC;		/* back cursor movement */
Xextern char *UP;		/* up cursor movement */
X#endif
X
X/*
X *	tgetent - get the termcap entry for terminal name, and put it
X *	in bp (which must be an array of 1024 chars). Returns 1 if
X *	termcap entry found, 0 if not found, and -1 if file not found.
X */
X
Xint tgetent(bp, name)
Xchar *bp;
Xchar *name;
X{
X  FILE *fp;
X  char *file;
X  char *term;
X  short len = strlen(name);
X#ifndef amiga
X  extern char *getenv ();
X#endif
X  capab = bp;
X
X  /* If TERMCAP begins with a '/' then use TERMCAP as the path	 */
X  /* Name of the termcap definitions file. If TERMCAP is a	 */
X  /* Definition and TERM equals "name" then use TERMCAP as the	 */
X  /* Definition. Otherwise use "/etc/termcap" as the path name.	 */
X
X  if ((file = getenv("TERMCAP")) == (char *)NULL)
X#ifdef amiga
X	file = "s:termcap";
X#else
X	file = "/etc/termcap";
X#endif
X  else if (*file != DIRSEP) {
X	if ((term = getenv("TERM")) != (char *)NULL && strcmp(term, name) == 0) {
X		*bp = '\0';
X		strncat(bp, file, 1023);
X		return(1);
X	} else
X#ifdef amiga
X		file = "s:termcap";
X#else
X		file = "/etc/termcap";
X#endif
X  }
X
X  if ((fp = fopen(file, "r")) == (FILE *) NULL) {
X	capab = (char *)NULL;		/* no valid termcap  */
X	return(-1);
X  }
X  for (;;) {
X	/* Read in each definition */
X	int def_len = 0;
X	char *cp = bp;
X
X	do {
X		if (fgets(&bp[def_len], (unsigned int)(1024 - def_len), fp) == (char *)NULL) {
X			fclose(fp);
X			capab = (char *)NULL;	/* no valid termcap */
X			return(0);
X		}
X		def_len = strlen(bp) - 2;
X	} while (bp[def_len] == '\\');
X
X	while (isspace(*cp)) cp++;
X
X	/* Comment lines start with a '#'  */
X	if (*cp == '#') continue;
X
X	/* See if any of the terminal names in this definition */
X	/* Match "name".						 */
X
X	do {
X		if (strncmp(name, cp, len) == 0 &&
X		    (cp[len] == '|' || cp[len] == ':')) {
X			fclose(fp);
X			return(1);
X		}
X		while ((*cp) && (*cp != '|') && (*cp != ':')) cp++;
X	} while (*cp++ == '|');
X  }
X}
X
X
X/*
X *	tgetnum - get the numeric terminal capability corresponding
X *	to id. Returns the value, -1 if invalid.
X */
X
Xint tgetnum(id)
Xchar *id;
X{
X  register char *cp = capab;
X
X  if (cp == (char *)NULL || id == (char *)NULL) return(-1);
X
X  for (;;) {
X	while (*cp++ != ':')
X		if (cp[-1] == '\0') return(-1);
X
X	while (isspace(*cp)) cp++;
X
X	if (strncmp(cp, id, 2) == 0 && cp[2] == '#') return(atoi(cp + 3));
X  }
X}
X
X
X/*
X *	tgetflag - get the boolean flag corresponding to id. Returns -1
X *	if invalid, 0 if the flag is not in termcap entry, or 1 if it is
X *	present.
X */
X
Xint tgetflag(id)
Xchar *id;
X{
X  register char *cp = capab;
X
X  if (cp == (char *)NULL || id == (char *)NULL) return(-1);
X
X  for (;;) {
X	while (*cp++ != ':')
X		if (cp[-1] == '\0') return(0);
X
X	while (isspace(*cp)) cp++;
X
X	if (strncmp(cp, id, 2) == 0) return(1);
X  }
X}
X
X
X/*
X *	tgetstr - get the string capability corresponding to id and place
X *	it in area (advancing area at same time). Expand escape sequences
X *	etc. Returns the string, or NULL if it can't do it.
X */
X
Xchar *tgetstr(id, area)
Xchar *id;
Xchar **area;
X{
X  register char *cp = capab;
X  register char *wsp = *area;	/* workspace pointer  */
X
X  if (cp == (char *)NULL || id == (char *)NULL) return((char *)NULL);
X
X  for (;;) {
X	while (*cp++ != ':')
X		if (cp[-1] == '\0') return((char *)NULL);
X
X	while (isspace(*cp)) cp++;
X
X	if (strncmp(cp, id, 2) == 0 && cp[2] == '=') {
X		for (cp += 3; *cp && *cp != ':'; wsp++, cp++) switch (*cp) {
X			    case '^':
X				*wsp = *++cp - '@';
X				break;
X
X			    case '\\':
X				switch (*++cp) {
X				    case 'E':
X					*wsp = '\033';
X					break;
X				    case 'n':
X					*wsp = '\n';
X					break;
X				    case 'r':
X					*wsp = '\r';
X					break;
X				    case 't':
X					*wsp = '\t';
X					break;
X				    case 'b':
X					*wsp = '\b';
X					break;
X				    case 'f':
X					*wsp = '\f';
X					break;
X				    case '0':
X				    case '1':
X				    case '2':
X				    case '3':
X					{
X						int i;
X						int t = 0;
X						for (i = 0; i < 3 &&
X						     isdigit(*cp); ++i, ++cp)
X							t = t * 8 + *cp - '0';
X						*wsp = t;
X						cp--;
X						break;
X					}
X				    default:
X					*wsp = *cp;
X				}
X				break;
X
X			    default:	*wsp = *cp;
X  			}
X
X		*wsp++ = '\0';
X
X		{
X			char *ret = *area;
X			*area = wsp;
X			return(ret);
X		}
X	}
X  }				/* end for(;;) */
X}
X
X
X
X/*
X *	tgoto - given the cursor motion string cm, make up the string
X *	for the cursor to go to (destcol, destline), and return the string.
X *	Returns "OOPS" if something's gone wrong, or the string otherwise.
X */
X
Xchar *tgoto(cm, destcol, destline)
Xchar *cm;
Xint destcol;
Xint destline;
X{
X  PRIVATE char ret[24];
X  char *rp = ret;
X  int incr = 0;
X  int argno = 0;
X  int numval;
X
X  for (; *cm; cm++) {
X	if (*cm == '%') {
X		switch (*++cm) {
X		    case 'i':	incr = 1;	  			break;
X
X		    case 'r':	argno = 1;	  			break;
X
X		    case '+':
X#ifdef amiga
X			numval = (argno == 0 ? destcol : destline);
X#else
X			numval = (argno == 0 ? destline : destcol);
X#endif
X			*rp++ = numval + incr + *++cm;
X			argno = 1 - argno;
X			break;
X
X		    case '2':
X#ifdef amiga
X			numval = (argno == 0 ? destcol : destline);
X			numval = (numval + incr) % 100;
X#else
X			numval = (argno == 0 ? destline : destcol);
X			numval = (numval + incr) % 100;
X#endif
X			*rp++ = '0' + (numval / 10);
X			*rp++ = '0' + (numval % 10);
X			argno = 1 - argno;
X			break;
X
X		    case 'd':
X#ifdef amiga
X			numval = (argno == 0 ? destcol : destline);
X			numval = (numval + incr) % 1000;
X#else
X			numval = (argno == 0 ? destline : destcol);
X			numval = (numval + incr) % 1000;
X#endif
X			if (numval > 99) *rp++ = '0' + (numval / 100);
X			if (numval > 9) *rp++ = '0' + (numval / 10) % 10;
X			*rp++ = '0' + (numval % 10);
X			argno = 1 - argno;
X			break;
X
X		    case '%':	*rp++ = '%';	  			break;
X
X		    default:	return("OOPS");
X  		}
X
X	} else
X		*rp++ = *cm;
X  }
X
X  *rp = '\0';
X  return(ret);
X}
X
X
X
X/*
X *	tputs - put the string cp out onto the terminal, using the function
X *	outc. This should do padding for the terminal, but I can't find a
X *	terminal that needs padding at the moment...
X */
X
Xint tputs(cp, affcnt, outc)
Xregister char *cp;
Xint affcnt;
X_PROTOTYPE( void (*outc), (int ch));
X{
X  if (cp == (char *)NULL) return(1);
X  /* Do any padding interpretation - left null for MINIX just now */
X  while (*cp) (*outc) (*cp++);
X  return(1);
X}
END_OF_FILE
if test 7492 -ne `wc -c <'termcap.c'`; then
    echo shar: \"'termcap.c'\" unpacked with wrong size!
fi
# end of 'termcap.c'
fi
if test -f 'vn.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vn.c'\"
else
echo shar: Extracting \"'vn.c'\" \(10307 characters\)
sed "s/^X//" >'vn.c' <<'END_OF_FILE'
X/*
Xvn news reader for visual page oriented display of news
Xaimed at scanning large numbers of articles.
X
XOriginal program by Bob McQueer in several versions 1983-1986.  Released
Xinto the public domain in 1986.  While no copyright notice appears, the
Xoriginal author asks that a history of changes crediting the proper people
Xbe maintained.
X
XBob McQueer
X{amdahl, sun, mtxinu, hoptoad, cpsc6a}!rtech!bobm
X
XHistory:
X
X	(bobm@rtech) 5/86 - first "public" version
X
X	(bobm@rtech) 12/86 - version incorporates:
X
X		bug fixes:
X			str_store NULL string bug
X			not picking up first article in newsgroup
X			RESTART terminal reset for exit to editor.
X			skip whitespace in "empty" digest lines while unpacking
X			DISTRIBUTION line in followups.
X			:100%: prompt on last line in reader.
X			interpretation of multiple negations -w -t options.
X
X			Many thanks to several people who noted the first
X			two bugs as well as fixes.
X
X			Thank you to Karl Williamson for helpful information
X			tracking down the "concept terminal" bug (RESTART).
X
X		SYSV ifdef's adapted from those done by Larry Tepper
X		at ATT Denver - sent in by Karl Williamson, drutx!khw.
X		Many people submitted SYSV ifdef's - thank you all.
X
X		print capability from reader from Karl Williamson,
X		drutx!khw
X
X		Changes to use alternate header lines for mail, from changes
X		by Andy Marrinson, andy@icom.UUCP (ihnp4!icom!andy).  Ifdef'ed
X		to allow local configuration (bobm@rtech).
X
X		"author_copy" file for followups, prevention of multiple
X		"re: "'s, insert blank line and original author line
X		before excerpted text from Andy Marrinson, andy@icom.UUCP
X
X		Search string capability in reader, from Lawrie Brown,
X		seismo!munnari!cdsadfa.oz!lpb (Australia).  Somewhat
X		modified by interaction with the :100%: bug.
X
X		Arrow key support, adapted from changes by Lawrie Brown.
X		Modified to simply not allow control keys for arrows (allowing
X		SOME controls is too prone to problems, esp. with .vnkey), and
X		to allow the PAGEARROW ifdef (bobm@rtech)
X
X		prevention of followups to "mod" and "announce", from
X		Lawrie Brown.
X
X		OLDRC ifdef adapted from changes by Lawrie Brown.  ADDRMUNGE
X		added to allow OZ domain addressing changes from Australia
X		to be grafted back in, and provide a hook for anybody else
X		wanting to do something similar.
X
X		Bob McQueer, bobm@rtech:
X
X			a menu selection from the % command to jump to
X			a new newsgroup
X
X			linked list on hash table - no longer a compiled
X			in limit for number of newsgroups
X
X			.vnkey keystroke mapping file.
X
X			options to get the % command list on entry, and to
X			change how unsubscribed groups are handled for updates.
X
X			allow configurable use of vs / ve pair for terminal
X			handling.
X
X	8/87 (bobm@rtech)
X
X		Server interface changes.  Creation of vns_xxx routines
X		formally defining how to attach vn to an abstracted
X		news server, rearranged existing code to use that
X		abstraction.  Sourcefile list altered a good bit by
X		the rearrangement.  Some of this was splitting some
X		routines out from vn.c into smaller modules.  Reader
X		code was altered a good bit to work through the
X		ARTHEADER abstraction, rather than searching for
X		header lines.  Temp file writing code was the other
X		area heavily affected.  The std.c server interface
X		essentially incorporates the old newsrc.c code, plus
X		the old outgroup() and gethead() routines.
X
X		vns_changes also included:
X
X			Modification of mailer interface for MAILCHOOSE,
X			getting rid of ADDRMUNGE (superseded by vns
X			interface definition)
X
X			Moved readstr() into the session loop code,
X			allowing a lot of static declarations to be
X			placed therein.  Also made it possible to
X			use strtok() underneath readstr().
X
X			Made "save" write directly into file, rather
X			than forking a cat (gee, that sounds perverse).
X
X			Also fixes it so that "|" save convention works
X			from reader.
X
X			Digest unpacking has to know about header lines,
X			unfortunately, so it has local definitions for
X			some header lines.
X
X		Incorporates:
X
X			The much-discussed "continued header line" bug
X			fix, of course.  Includes the multiple header
X			line nfgets() by Andrew Worsley, andrew@munnari.oz,
X			with a couple cosmetic changes.
X
X			Top / Middle / Bottom keys from Karl Williamson
X			print capability from reader from Karl Williamson,
X			drutx!khw
X
X			Edit old save file changes from George Pavel,
X			gp@lll-lcc.arpa.  Used it to allow edit of
X			the some other old strings, too.
X
X			Fix for the bad number input bug on the choose
X			new group from list feature, as reported by
X			Dave Tallman, tallman@hc.arpa.  His fix with
X			a few minor changes.
X
X			A couple save file tweaks - allow a "%s" in VNSAVE
X			to specify individual directories by newsgroup.
X			Allow a "w:" prefix on filename to write instead
X			of appending, allow %d for article number in name.
X
X			The VNEDITOR variable.
X
X			Statistics collection ability.
X
X			Update of .newsrc "read" number to reflect removed
X			articles, preventing rescanning of group on next
X			session.
X
X			take out SIGHUP catching to avoid problems with
X			message being output.
X
X			key to print version being used.
X
X	Bug fixes following 12/87 posting.  Made this version 1/88 / res1.1
X	to distinguish.
X
X		Digest extraction in reader.c, fix from steve@mahendo.  Thanks
X		to steve@mahendo & greg@mahendo for tracking down digest
X		extraction bugs.  I obviously didn't beat on the feature enough
X		after rearranging things to abstract the server interface.
X		The digest extraction display is a little less informative,
X		the price paid to allow mail & followup.
X
X		SYS V ifdefs - svart.c, independently arrived at by several
X		people - thank you.  At the behest of a couple people I made
X		it spawn a "mkdir" instead of punting by calling mknod.
X
X		Fix bug which would cause vn to crash if article has
X		no "From" / "Reply-to" / "Path" line. - std.c
X
X		Fix bug preventing assignment of .newsrc to filesystem other
X		than that containing user's HOME.
X
X		Fix excessive allocation in hash.c
X
X		Handle duplicate active list records more gracefully.
X
X		term_set(RESTART) call added to recovery from being
X		backgrounded in sig_set.c, in case something you ran while
X		backgrounded messed up your terminal state.  I lost the name
X		of the person reporting the problem & fix - my apologies.
X
X		display optimization in reader.c which repaints instead of
X		scrolling if indicated by user's MORE variable.  This came
X		from Greg Earle, earle@mahendo.  Modified slightly for
X		cosmetic reasons & to fix a small folded-line bug.
X
X	2/88 (bobm)
X
X		Put mode on open() call in temp_open, as per bug fix from
X		Don Craig.  This has been working this way a long time on
X		a lot of systems (the file is unlinked after creation, so
X		the actual mode doesn't really matter, and as long as your
X		open call doesn't check the unused bits a random argument
X		works), but it was wrong, anyway.
X
X	4/88 (bobm)
X
X		Change server interface a bit to allow more control over
X		saving features, and provide a more generalized interface
X		for the vns_ routines to hang interactive hooks from.
X		Allow vns_ layer knowledge of marks.  These changes
X		should allow future implementation of selective lists,
X		use of the interface for a mailer, extra functionality
X		add-on at the vns level, etc.
X
X		incorporate changes to allow 8 bit intl. character set
X		in user strings - came from Marius Olafsson, marius@rhi.
X		Also made 0x7f a #define'ed mask in case you should want
X		to try allowing 8 bit command chars.
X
X		Jay Maynard, splut!jay pointed out that the percentage
X		calculation in reader overflowed for a 327+ line article
X		on a 16 bit machine, and sent fix.
X
X		std.c - fix "all.all" bug (any newsgroup names with
X		multiple "all"'s in them incorrectly converted into RE's
X		which would match practically nothing).  Up vns_Version
X		stamp to 1.2.
X
X
X		11/90 Michael Taylor
X		Amiga Port
XKnown bugs:
X
X	If your terminal init string contains a newline, I suspect you will
X	get an initial "stopped on tty output" if you fire up backgrounded.
X	Cooked mode until session is started probably saves us in a lot of
X	cases where the init string contains no newlines.  Can be fixed, but
X	it's esoteric enough that I don't want to add another file to the
X	"patched" list.
X
X	non-erasure of stuff on prompt line when the new
X	string includes an escape sequence (like PS1 maybe)
X	because it doesn't realize that the escape sequence
X	won't overprint the existing stuff
X
X	control-w and update on exit may not update pages which have been
X	scanned in funny orders by jumping into the middle of groups
X
X	inaccurate numbers on '%' command results - reflect ranges, not
X	actual numbers of articles.
X
X	no arrow keys recognized which don't begin with <escape>
X
X	doesn't know about the version 2.11 'm' in active list, or
X	use the 'y' / 'n' either.
X
X	crash due to embedding $\(\) type substring specifiers in regular
X	expressions.  Obscure and hard to fix in a proper and portable way.
X
X	Spool numbers are kept in int, not long - it would take quite
X	a bit of scrubbing through the code to root out this 32-bit'ism.
X	I wish I had typedef'ed the things.
X*/
X#include <stdio.h>
X#include "node.h"
X#include "tty.h"
X#include "brk.h"
X
Xextern int Lrec;
X
Xextern NODE **Newsorder;
Xextern int Ncount;
X
Xextern int Listfirst, Nounsub;
X
X#ifdef amiga
Xchar pr_buf[1024];
X#endif
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X	/*
X		initialize environment variables,
X		scan .newsrc file, using any command line options present.
X	 */
X	term_set (START);
X	envir_set ();
X	sig_set (BRK_IN);
X
X	stat_start();
X
X	hashinit();
X	temp_open();
X
X	vns_news (argc,argv,&Listfirst,&Nounsub);
X
X	fw_done ();
X
X	make_newsorder();
X
X	tty_set (BACKSTOP);
X
X	if (Lrec >= 0)
X		session ();
X	else
X	{
X		new_groups ();
X		fprintf (stderr,"\nNo News\n");
X	}
X
X#ifndef	MINIX
X	tty_set (COOKED);
X#else
X	tty_set (XCOOKED);
X#endif
X
X#ifdef MSDOS
X	{
X		extern char *Orgdir;
X
X		if (chdir(Orgdir) < 0)
X			fprintf (stderr,
X				"change to original directory, %s, failed",
X				Orgdir);
X	}
X#endif
X#ifdef amiga
X	{
X		extern char *Orgdir;
X
X		if (chdir(Orgdir) < 0)
X			fprintf (stderr,
X				"change to original directory, %s, failed",
X				Orgdir);
X	}
X#endif
X
X	/* exiting, don't worry about FLG_ECHG resetting */
X	vns_write(Newsorder,Ncount);
X
X	term_set (STOP);
X	vns_exit(0);
X#ifdef amiga
X	kill_tmp ();
X#endif
X	stat_end( Lrec >= 0 ? 1 : 0 );
X}
END_OF_FILE
if test 10307 -ne `wc -c <'vn.c'`; then
    echo shar: \"'vn.c'\" unpacked with wrong size!
fi
# end of 'vn.c'
fi
echo shar: End of archive 3 \(of 6\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.