Article 2696 of comp.sources.unix:
Path: nntpd.lkg.dec.com!crl.dec.com!crl.dec.com!bloom-beacon.mit.edu!news.kei.com!news.mathworks.com!newsfeed.internetmci.com!in1.uu.net!news1.digital.com!vixie!vixie!not-for-mail
From: davison@borland.com (Wayne Davison)
Newsgroups: comp.sources.unix
Subject: v29i038: trn-3.6 - threaded newsreader based on RN, V3.6, Part01/14
Date: 29 Oct 1995 01:32:41 -0800
Organization: Vixie Enterprises
Lines: 3209
Sender: vixie@vix.com
Approved: vixie@gw.home.vix.com
Message-ID: <1.814959141.29825@gw.home.vix.com>
NNTP-Posting-Host: gw.home.vix.com

Submitted-By: davison@borland.com (Wayne Davison)
Posting-Number: Volume 29, Issue 38
Archive-Name: trn-3.6/part01

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1995-10-29 01:27 PST by <vixie@gw.home.vix.com>.
# Source directory was `/tmp_mnt/fs/a3/CSU/New'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This is part 1 of a multipart archive.                                   
# Do not concatenate these parts, unpack them in order with `/bin/sh'.     
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  echo 'WARNING: not restoring timestamps.  Consider getting and'
  echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if test -r _sharseq.tmp; then
  echo 'Must unpack archives in sequence!'
  echo Please unpack part `cat _sharseq.tmp` next
  exit 1
fi
# ============= trn-3.6/EXTERN.h ==============
if test ! -d 'trn-3.6'; then
  echo 'x - creating directory trn-3.6'
  mkdir 'trn-3.6'
fi
if test -f 'trn-3.6/EXTERN.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/EXTERN.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/EXTERN.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/EXTERN.h' &&
X/* $Id: EXTERN.h,v 3.0 1991/09/09 20:18:23 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#undef EXT
X#define EXT extern
X
X#undef INIT
X#define INIT(x)
X
X#undef DOINIT
SHAR_EOF
  $shar_touch -am 0711223593 'trn-3.6/EXTERN.h' &&
  chmod 0644 'trn-3.6/EXTERN.h' ||
  echo 'restore of trn-3.6/EXTERN.h failed'
  shar_count="`wc -c < 'trn-3.6/EXTERN.h'`"
  test 725 -eq "$shar_count" ||
    echo "trn-3.6/EXTERN.h: original size 725, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/INTERN.h ==============
if test -f 'trn-3.6/INTERN.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/INTERN.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/INTERN.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/INTERN.h' &&
X/* $Id: INTERN.h,v 3.0 1991/09/09 20:18:23 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#undef EXT
X#define EXT
X
X#undef INIT
X#ifdef xenix
X#define INIT(x) =x
X#else
X#define INIT(x) = x
X#endif
X
X#define DOINIT
SHAR_EOF
  $shar_touch -am 0711223593 'trn-3.6/INTERN.h' &&
  chmod 0644 'trn-3.6/INTERN.h' ||
  echo 'restore of trn-3.6/INTERN.h failed'
  shar_count="`wc -c < 'trn-3.6/INTERN.h'`"
  test 768 -eq "$shar_count" ||
    echo "trn-3.6/INTERN.h: original size 768, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/addng.c ==============
if test -f 'trn-3.6/addng.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/addng.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/addng.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/addng.c' &&
X/* $Id: addng.c,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "trn.h"
X#include "ngdata.h"
X#include "last.h"
X#include "util.h"
X#include "intrp.h"
X#include "only.h"
X#include "rcstuff.h"
X#include "nntp.h"
X#include "final.h"
X#include "INTERN.h"
X#include "addng.h"
X
Xvoid
Xaddng_init()
X{
X    ;
X}
X
X#ifdef FINDNEWNG
X/* generate a list of new newsgroups from active file */
X
Xbool
Xnewlist(munged,checkinlist)
Xbool_int munged;			/* are we scanning the whole file? */
Xbool_int checkinlist;
X{
X    char *tmpname;
X    register char *s, *status;
X    register NG_NUM ngnum;
X
X    tmpname = filexp(RNEWNAME);
X    tmpfp = fopen(tmpname,"w+");
X    if (tmpfp == Nullfp) {
X	printf(cantcreate,tmpname) FLUSH;
X	return FALSE;
X    }
X    UNLINK(tmpname);			/* be nice to the world */
X
X    for (;;) {
X#ifdef USE_NNTP
X	if (!actfp) {
X	    if (NNTP_LIST_END(ser_line))
X		break;
X	    strcpy(buf, ser_line);
X	    nntp_gets(ser_line, sizeof ser_line);
X	}
X	else
X#endif
X	if (fgets(buf,LBUFLEN,actfp) == Nullch)
X	    break;
X	/* Check if they want to break out of the new newsgroups search */
X	if (int_count) {
X	    int_count = 0;
X	    fclose(tmpfp);
X	    return FALSE;
X	}
X	if (s = index(buf,' ')) {
X	    status=s;
X	    while (isdigit(*status) || isspace(*status)) status++;
X	    *s++ = '\0';
X	    if (strnEQ(buf,"to.",3) || *status == 'x' || *status == '=')
X	        /* since = groups are refiling to another group, just
X		   ignore their existence */
X		continue;
X#ifdef ACTIVE_TIMES
X	    if (inlist(buf) && ((ngnum = find_ng(buf)) == nextrcline
X				|| toread[ngnum] == TR_UNSUB)
X#else
X	    if (checkinlist ?
X		(inlist(buf) && ((ngnum = find_ng(buf)) == nextrcline
X				 || toread[ngnum] == TR_UNSUB))
X	      : (find_ng(buf) == nextrcline
X		 && birthof(buf,(ART_NUM)atol(s)) > lasttime)
X#endif
X	    ) {
X					/* if not in .newsrc and younger */
X					/* than the last time we checked */
X		fprintf(tmpfp,"%s\n",buf);
X					/* then remember said newsgroup */
X	    }
X#ifdef FASTNEW
X	    else {			/* not really a new group */
X		if (!munged) {		/* did we assume not munged? */
X		    fclose(tmpfp);	/* then go back, knowing that */
X		    return TRUE;	/* active file was indeed munged */
X		}
X	    }
X#endif
X	}
X#ifdef DEBUG
X	else
X	    printf("Bad active record: %s\n",buf) FLUSH;
X#endif
X    }
X
X    /* we have successfully generated the list */
X
X    fseek(tmpfp,0L,0);			/* rewind back to the beginning */
X    while (fgets(buf,LBUFLEN,tmpfp) != Nullch) {
X	buf[strlen(buf)-1] = '\0';
X	get_ng(buf,GNG_RELOC);		/* add newsgroup, maybe */
X    }
X    fclose(tmpfp);			/* be nice to ourselves */
X    return FALSE;			/* do not call us again */
X}
X
X#ifdef ACTIVE_TIMES
X#ifdef USE_NNTP
X
Xbool
Xfind_new_groups()
X{
X    char *tmpname;
X    register char *s;
X    time_t server_time;
X    NG_NUM oldnext = nextrcline;	/* remember # lines in newsrc */
X
X    tmpname = filexp(RNEWNAME);
X    tmpfp = fopen(tmpname,"w+");
X    if (tmpfp == Nullfp) {
X	printf(cantcreate,tmpname) FLUSH;
X	return FALSE;
X    }
X    UNLINK(tmpname);			/* be nice to the world */
X
X    server_time = nntp_time();
X    if (!nntp_newgroups(lastnewtime)) {
X	fclose(tmpfp);
X	printf("Can't get new groups from server:\n%s\n", ser_line);
X	return FALSE;
X    }
X
X    while (1) {
X	nntp_gets(ser_line, sizeof ser_line);
X#ifdef DEBUG
X	if (debug & DEB_NNTP)
X	    printf("<%s\n", ser_line) FLUSH;
X#endif
X	if (NNTP_LIST_END(ser_line))
X	    break;
X	if ((s = index(ser_line, ' ')) != Nullch)
X	    *s++ = '\0';
X	else if (findact(buf, ser_line, strlen(ser_line), 0L) >= 0)
X	    s = buf + strlen(ser_line) + 1;
X	if (s) {
X	    while (isdigit(*s) || isspace(*s)) s++;
X	    if (*s == 'x' || *s == '=')
X		continue;
X	}
X	fprintf(tmpfp,"%s\n",ser_line);
X    }
X
X    /* we have successfully generated the list */
X
X    if (ftell(tmpfp)) {
X	fputs("\nFinding new newsgroups:\n",stdout) FLUSH;
X
X	fseek(tmpfp,0L,0);		/* rewind back to the beginning */
X	while (fgets(buf,LBUFLEN,tmpfp) != Nullch) {
X	    buf[strlen(buf)-1] = '\0';
X	    get_ng(buf,0);		/* add newsgroup, maybe */
X	}
X	lastnewtime = server_time;	/* remember when we found new groups */
X    }					/* (ends up back in .rnlast) */
X    fclose(tmpfp);			/* be nice to ourselves */
X
X    return oldnext != nextrcline;
X}
X#else /* !USE_NNTP */
X
Xbool
Xfind_new_groups()
X{
X    register char *s;
X    time_t lastone;
X    NG_NUM oldnext = nextrcline;	/* remember # lines in newsrc */
X
X    fstat(fileno(actfp),&filestat);	/* find active file size */
X    lastactsiz = filestat.st_size;	/* just to save it in .rnlast */
X
X    stat(ACTIVE_TIMES,&filestat);	/* did active.times file grow? */
X    if (filestat.st_size == lastnewsize)
X	return FALSE;
X    lastnewsize = filestat.st_size;
X
X    fputs("\nChecking for new newsgroups...\n",stdout) FLUSH;
X
X    s = filexp(ACTIVE_TIMES);
X    tmpfp = fopen(s,"r");
X    if (tmpfp == Nullfp) {
X	printf(cantopen,s) FLUSH;
X	return FALSE;
X    }
X    lastone = time(Null(time_t*)) - 24L * 60 * 60 - 1;
X    while (fgets(buf,LBUFLEN,tmpfp) != Nullch) {
X	if ((s = index(buf, ' ')) != Nullch)
X	    if ((lastone = atol(s+1)) >= lastnewtime) {
X		char tmpbuf[LBUFLEN];
X		*s = '\0';
X		if (findact(tmpbuf, buf, s - buf, 0L) >= 0) {
X		    s = tmpbuf + (s-buf) + 1;
X		    while (isdigit(*s) || isspace(*s)) s++;
X		    if (*s != 'x' && *s != '=') {
X			get_ng(buf,0);	/* add newsgroup, maybe */
X		    }
X		}
X	    }
X    }
X    fclose(tmpfp);
X    lastnewtime = lastone+1;		/* remember time of last new group */
X					/* (ends up back in .rnlast) */
X    return oldnext != nextrcline;
X}
X#endif /* !USE_NNTP */
X#else /* not ACTIVE_TIMES */
X
Xbool
Xfind_new_groups()
X{
X    long oldactsiz = lastactsiz;
X    NG_NUM oldnext = nextrcline;	/* remember # lines in newsrc */
X
X#ifdef USE_NNTP
X    if (!actfp) {
X	return 0;
X    }
X#endif
X
X    fstat(fileno(actfp),&filestat);	/* did active file grow? */
X
X    if (filestat.st_size == lastactsiz)
X	return FALSE;
X    lastactsiz = filestat.st_size;	/* remember new size */
X
X#ifdef VERBOSE
X    IF(verbose)
X	fputs("\nChecking active file for new newsgroups...\n",stdout) FLUSH;
X    ELSE
X#endif
X#ifdef TERSE
X	fputs("\nNew newsgroups:\n",stdout) FLUSH;
X#endif
X
X#ifdef FASTNEW				/* bad soft ptrs -> edited active */
X    if (!writesoft && oldactsiz) {	/* maybe just do tail of file? */
X	fseek(actfp,oldactsiz-NL_SIZE,0);
X	fgets(buf,LBUFLEN,actfp);
X	if (*buf == '\n' && !newlist(FALSE,FALSE))
X	    goto bugout;
X    }
X#endif
X    fseek(actfp,0L,0);		/* rewind active file */
X    newlist(TRUE,FALSE);		/* sure hope they use hashing... */
Xbugout:
X    return oldnext != nextrcline;
X}
X
X/* return creation time of newsgroup */
X
Xtime_t
Xbirthof(ngnam,ngsize)
Xchar *ngnam;
XART_NUM ngsize;
X{
X#ifdef USE_NNTP		/* ngsize not used */
X    long tot;
X
X    if (!nntp_group(ngnam,-1))
X	return 0;	/* not a real group */
X    (void) sscanf(ser_line,"%*d%ld",&tot);
X    if (tot > 0)
X	return time(Null(time_t*));
X    return 0;
X
X#else /* !USE_NNTP */
X    char tst[512];
X
X    sprintf(tst, ngsize ? "%s/%s/1" : "%s/%s" ,spool,getngdir(ngnam));
X    if (stat(tst,&filestat) < 0)
X	return (ngsize ? 0L : time(Null(time_t*)));
X    /* not there, assume something good */
X    return filestat.st_mtime;
X
X#endif /* !USE_NNTP */
X}
X#endif /* ACTIVE_TIMES */
X
Xbool
Xscanactive()
X{
X    NG_NUM oldnext = nextrcline;	/* remember # lines in newsrc */
X
X    if (actfp) {
X	fseek(actfp,0L,0);
X	newlist(TRUE,TRUE);
X    }
X#ifdef USE_NNTP
X    else {
X	if (maxngtodo != 1) {
X	    strcpy(buf, "*");
X	}
X	else {
X	    sprintf(buf,"*%s*", ngtodo[0]);
X	}
X	if (nntp_list("active", buf, strlen(buf)) == 1) {
X	    newlist(TRUE,TRUE);
X	}
X    }
X#endif
X    if (nextrcline != oldnext) {	/* did we add any new groups? */
X	return TRUE;
X    }
X    return FALSE;
X}
X
X#endif /* FINDNEWNG */
X
SHAR_EOF
  $shar_touch -am 1004153894 'trn-3.6/addng.c' &&
  chmod 0644 'trn-3.6/addng.c' ||
  echo 'restore of trn-3.6/addng.c failed'
  shar_count="`wc -c < 'trn-3.6/addng.c'`"
  test 8196 -eq "$shar_count" ||
    echo "trn-3.6/addng.c: original size 8196, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/addng.h ==============
if test -f 'trn-3.6/addng.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/addng.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/addng.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/addng.h' &&
X/* $Id: addng.h,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
Xvoid	addng_init _((void));
X#ifdef FINDNEWNG
Xbool	newlist _((bool_int,bool_int));
X# ifdef ACTIVE_TIMES
Xbool	find_new_groups _((void));
X# else
Xtime_t	birthof _((char*,ART_NUM));
X# endif
Xbool	scanactive _((void));
X#endif
SHAR_EOF
  $shar_touch -am 0711223593 'trn-3.6/addng.h' &&
  chmod 0644 'trn-3.6/addng.h' ||
  echo 'restore of trn-3.6/addng.h failed'
  shar_count="`wc -c < 'trn-3.6/addng.h'`"
  test 868 -eq "$shar_count" ||
    echo "trn-3.6/addng.h: original size 868, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/art.c ==============
if test -f 'trn-3.6/art.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/art.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/art.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/art.c' &&
X/* $Id: art.c,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "trn.h"
X#include "ngstuff.h"
X#include "ngdata.h"
X#include "cache.h"
X#include "bits.h"
X#include "head.h"
X#include "help.h"
X#include "search.h"
X#include "artio.h"
X#include "ng.h"
X#include "final.h"
X#include "artstate.h"
X#include "rcstuff.h"
X#include "term.h"
X#include "sw.h"
X#include "util.h"
X#include "util2.h"
X#include "nntp.h"
X#include "backpage.h"
X#include "intrp.h"
X#include "rthread.h"
X#include "rt-select.h"
X#include "rt-util.h"
X#include "rt-wumpus.h"
X#include "charsubst.h"
X#include "INTERN.h"
X#include "art.h"
X
X/* page_switch() return values */
X
X#define PS_NORM 0
X#define PS_ASK 1
X#define PS_RAISE 2
X#define PS_TOEND 3
X
Xbool special = FALSE;		/* is next page special length? */
Xint slines = 0;			/* how long to make page when special */
Xchar *restart = Nullch;		/* if nonzero, the place where last */
X				/* line left off on line split */
Xchar *blinebeg;			/* where in buffer current line began */
XART_POS alinebeg;		/* where in file current line began */
X
X#ifdef INNERSEARCH
XART_LINE isrchline = 0;		/* last line to display */
XCOMPEX gcompex;			/* in article search pattern */
X#endif
X
Xbool firstpage;			/* is this the 1st page of article? */
X
Xchar art_buf[LBUFLEN];		/* place for article lines */
X
Xvoid
Xart_init()
X{
X#ifdef INNERSEARCH
X    init_compex(&gcompex)
X#endif
X    ;
X}
X
X#ifdef MIMESHOW
X#define VERY_LONG_STRING        200
Xint
Xdisplay_mime()
X{
X    int code = 1;
X
X    if (!getenv("NOMIME")) {
X	char oldmode = mode;
X
X	fputs("Process MIME article? [yn]",stdout);
X	fflush(stdout);
X	eat_typeahead();
X#ifdef PENDING
X	cache_until_key();
X#endif
X	mode = 'p';
X	getcmd(buf);
X	setdef(buf,"y");
X	mode = oldmode;
X#ifdef VERIFY
X	printcmd();
X#endif
X	carriage_return();
X	erase_eol();	/* erase the prompt */
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X	if (*buf == 'y') {
X	    putchar('\n');
X	    fflush(stdout);
X#ifdef USE_NNTP
X	    nntp_finishbody(FB_OUTPUT);
X#endif
X	    termlib_reset();
X	    resetty();
X	    interp(cmd_buf,(sizeof cmd_buf),getval("MIMESHOW",MIMESHOW));
X	    code = doshell(SH,cmd_buf);
X	    noecho();
X	    crmode();
X	    termlib_init();
X	}
X    }
X    return code;
X}
X#endif
X
X
Xint
Xdo_article()
X{
X    register char *s;
X    bool hide_this_line = FALSE;	/* hidden header line? */
X    ART_LINE linenum;	/* line # on page, 1 origin */
X#ifdef ULSMARTS
X    bool under_lining = FALSE;		/* are we underlining a word? */
X#endif
X    register char *bufptr = art_buf;	/* pointer to input buffer */
X    register int outpos;		/* column position of output */
X    static char prompt_buf[64];		/* place to hold prompt */
X    bool notesfiles = FALSE;		/* might there be notesfiles junk? */
X    char oldmode = mode;
X    char *ctime();
X#ifdef MIMESHOW
X    bool tried_display_mime = FALSE;
X#endif
X#ifdef INNERSEARCH
X    register int outputok = TRUE;
X#endif
X
X#if defined(MIMESHOW) || defined(MIMESTORE)
X    mime_article = FALSE;
X#endif
X
X#ifndef USE_NNTP
X    if (fstat(fileno(artfp),&filestat)) /* get article file stats */
X	return DA_CLEAN;
X    if (!S_ISREG(filestat.st_mode))
X	return DA_NORM;
X    artsize = filestat.st_size;		/* from that get article size */
X#endif
X#ifdef CHARSUBST
X    sprintf(prompt_buf,
X	"%%sEnd of article %ld (of %ld) %%s-- what next? [%%s]",
X	(long)art,(long)lastart);	/* format prompt string */
X#else
X    sprintf(prompt_buf,
X	"%%sEnd of article %ld (of %ld) -- what next? [%%s]",
X	(long)art,(long)lastart);	/* format prompt string */
X#endif
X    prompt = prompt_buf;
X    int_count = 0;		/* interrupt count is 0 */
X    if ((firstpage = (topline < 0)) != 0) {
X	parseheader(art);
X	seekart(htype[PAST_HEADER].ht_minpos);
X    }
X    for (;;) {			/* for each page */
X	if (ThreadedGroup && max_tree_lines)
X	    init_tree();	/* init tree display */
X	assert(art == openart);
X	if (do_fseek) {
X	    parseheader(art);		/* make sure header is ours */
X	    artpos = vrdary(artline);
X	    if (artpos < 0)
X		artpos = -artpos;	/* labs(), anyone? */
X	    if (firstpage)
X		artpos = (ART_POS)0;
X	    if (artpos < htype[PAST_HEADER].ht_minpos) {
X		in_header = SOME_LINE;
X		seekart(htype[PAST_HEADER].ht_minpos);
X	    } else
X		seekart(artpos);
X	    do_fseek = FALSE;
X	    restart = Nullch;
X	}
X	linenum = 1;
X	if (firstpage) {
X	    if (firstline) {
X		interp(art_buf, (sizeof art_buf), firstline);
X		linenum += tree_puts(art_buf,linenum+topline,0);
X	    } else 
X            {
X		ART_NUM i;
X		int selected, unseen;
X
X		selected = (curr_artp->flags & AF_SEL);
X		unseen = !was_read(art);
X		sprintf(art_buf,"%s%s #%ld",ngname,moderated,(long)art);
X		if (selected_only) {
X		    i = selected_count - (unseen && selected);
X		    sprintf(art_buf+strlen(art_buf)," (%ld + %ld more)",
X			    (long)i,(long)toread[ng] - selected_count
X					- (!selected && unseen));
X		}
X		else if ((i = (ART_NUM)(toread[ng] - unseen)) != 0
X		       || (!ThreadedGroup && dmcount))
X		    sprintf(art_buf+strlen(art_buf)," (%ld more)",(long)i);
X		if (!ThreadedGroup && dmcount)
X		    sprintf(art_buf+strlen(art_buf)-1," + %ld Marked to return)",
X			    (long)dmcount);
X		linenum += tree_puts(art_buf,linenum+topline,0);
X	    }
X	    start_header(art);
X	    forcelast = FALSE;		/* we will have our day in court */
X	    restart = Nullch;
X	    artline = 0;		/* start counting lines */
X	    artpos = 0;
X	    vwtary(artline,artpos);	/* remember pos in file */
X	}
X	for (;				/* linenum already set */
X	  in_header || (
X#ifdef INNERSEARCH
X	  innersearch ? innermore() :
X#endif
X	  linenum<(firstpage?initlines:(special?slines:LINES)) );
X	  linenum++) {		/* for each line on page */
X	    if (int_count) {	/* exit via interrupt? */
X		putchar('\n') FLUSH;	/* get to left margin */
X		int_count = 0;	/* reset interrupt count */
X		mode = oldmode;
X		special = FALSE;
X#ifdef USE_NNTP
X		nntp_finishbody(FB_OUTPUT);
X#endif
X		return DA_NORM;	/* skip out of loops */
X	    }
X	    if (restart) {		/* did not finish last line? */
X		bufptr = restart;	/* then start again here */
X		restart = Nullch;	/* and reset the flag */
X	    }
X	    else if (in_header && headbuf[artpos] != '\0') {
X		bufptr = index(headbuf+artpos,'\n') + 1;
X		bcopy(headbuf+artpos,art_buf,bufptr-headbuf-artpos);
X		art_buf[bufptr-headbuf-artpos] = '\0';
X		bufptr = art_buf;
X	    } else {
X		if (readart(art_buf,LBUFLEN) == Nullch) {
X		    break;
X		}
X		bufptr = art_buf;	/* so start at beginning */
X		art_buf[LBUFLEN-1] = '\0';
X					/* make sure string ends */
X	    }
X	    blinebeg = bufptr;	/* remember where we began */
X	    alinebeg = artpos;	/* both in buffer and file */
X	    if (in_header && bufptr == art_buf) {
X		hide_this_line =
X		    parseline(art_buf,do_hiding,hide_this_line);
X		if (!in_header) {
X		    linenum += finish_tree(linenum+topline);
X		    end_header();
X		}
X	    } else if (notesfiles && do_hiding &&
X	      bufptr == art_buf && *art_buf == '#' &&
X	      isupper(art_buf[1]) && art_buf[2] == ':' ) {
X		readart(art_buf,sizeof(art_buf));
X		if (index(art_buf,'!') != Nullch)
X		    readart(art_buf,sizeof(art_buf));
X		htype[PAST_HEADER].ht_minpos = tellart();
X					/* exclude notesfiles droppings */
X		hide_this_line = TRUE;	/* and do not print either */
X		notesfiles = FALSE;
X	    }
X#ifdef CUSTOMLINES
X	    if (hideline && bufptr == art_buf &&
X		  execute(&hide_compex,art_buf) )
X		hide_this_line = TRUE;
X#endif
X	    if (in_header && htype[in_header].ht_flags & HT_MAGIC) {
X		if (in_header == NGS_LINE) {
X		    if ((s = index(art_buf,'\n')) != Nullch)
X			*s = '\0';
X		    hide_this_line = (index(art_buf,',') == Nullch)
X			&& strEQ(art_buf+12, ngname);
X		    if (s != Nullch)
X			*s = '\n';
X		}
X		else if (in_header == EXPIR_LINE) {
X		    if (!(htype[EXPIR_LINE].ht_flags & HT_HIDE))
X			hide_this_line = ((int)strlen(art_buf) < 10);
X		}
X		else if (in_header == FROM_LINE) {
X		    if (do_hiding && (s = extract_name(art_buf+6)) != Nullch)
X			strcpy(art_buf+6,s);
X		}
X#ifdef HAS_STRFTIME
X		else if (in_header == DATE_LINE) {
X		    if (do_hiding && curr_artp->date != -1)
X			strftime(art_buf+6, sizeof(art_buf)-6,
X				 getval("LOCALTIMEFMT", LOCALTIMEFMT),
X				 localtime(&curr_artp->date));
X		}
X#endif
X#if defined(MIMESHOW) || defined(MIMESTORE)
X		else if (!isspace(*art_buf)) {
X		    int nontext _((char *));
X		    int nonprint _((char *));
X		    if (in_header == CONTENT_LINE)
X			mime_article = mime_article || nontext(art_buf+14);
X		    else if (in_header == CONTXFER_LINE)
X			mime_article = mime_article || nonprint(art_buf+27);
X		}
X#endif
X	    }
X	    if (in_header == SUBJ_LINE &&
X		htype[SUBJ_LINE].ht_flags & HT_MAGIC) {
X			    /* is this the subject? */
X		int length;
X
X		length = strlen(art_buf)-1;
X		artline++;
X		art_buf[length] = '\0';		/* wipe out newline */
X#ifdef NOFIREWORKS
X		no_ulfire();
X#endif
X		notesfiles =
X		    (instr(&art_buf[length-10]," - (nf", TRUE) != Nullch);
X		/* tree_puts(, ,1) underlines subject */
X		linenum += tree_puts(art_buf,linenum+topline,1)-1;
X	    }
X	    else if (hide_this_line && do_hiding) {
X					/* do not print line? */
X		linenum--;		/* compensate for linenum++ */
X		if (!in_header)
X		    hide_this_line = FALSE;
X	    }
X	    else if (in_header) {
X		artline++;
X		linenum += tree_puts(art_buf,linenum+topline,0)-1;
X	    }
X	    else {			/* just a normal line */
X#ifdef MIMESHOW
X		if (mime_article && do_hiding && !tried_display_mime) {
X		    if (display_mime() == 0)
X			return DA_NORM;
X		    tried_display_mime = TRUE;
X		}
X#endif
X#ifdef CLEAREOL
X#ifdef INNERSEARCH
X		if (outputok)
X#endif
X		if (can_home_clear) erase_eol();	
X#endif /* CLEAREOL */
X		if (highlight==artline) {	/* this line to be highlit? */
X		    if (marking == STANDOUT) {
X#ifdef NOFIREWORKS
X			if (erase_screen)
X			    no_sofire();
X#endif
X			standout();
X		    }
X		    else {
X#ifdef NOFIREWORKS
X			if (erase_screen)
X			    no_ulfire();
X#endif
X			underline();
X		    }
X		    if (*bufptr == '\n')
X			putchar(' ');
X		}
X#ifdef INNERSEARCH
X		outputok = !hide_everything;
X					/* get it into register, hopefully */
X#endif
X#ifdef CUSTOMLINES
X		if (pagestop && bufptr == art_buf && 
X		  execute(&page_compex,art_buf) )
X		    linenum = 32700;
X#endif
X		for (outpos = 0; outpos < COLS; ) {
X				    /* while line has room */
X		    if (*(unsigned char*)bufptr >= ' ') { /* normal char? */
X#ifdef ULSMARTS
X			if (*bufptr == '_') {
X			    if (bufptr[1] == '\b') {
X#ifdef INNERSEARCH
X				if (outputok)
X#endif
X				if (!under_lining && highlight != artline) {
X				    under_lining++;
X				    if (UG) {
X					if (bufptr != buf && bufptr[-1]==' ') {
X					    outpos--;
X					    backspace();
X					}
X				    }
X				    underline();
X				}
X				bufptr += 2;
X			    }
X			}
X			else {
X			    if (under_lining) {
X				under_lining = 0;
X				un_underline();
X				if (UG) {
X				    outpos++;
X				    if (*bufptr == ' ')
X					goto skip_put;
X				}
X			    }
X			}
X#endif
X#ifdef ROTATION
X			if (rotate && !in_header && isalpha(*bufptr)) {
X# ifdef INNERSEARCH
X			    if (outputok)
X# endif
X				if ((*bufptr & 31) <= 13)
X				    putchar(*bufptr+13);
X				else
X				    putchar(*bufptr-13);
X			    outpos++;
X			}
X			else
X#endif
X			{
X#ifdef CHARSUBST
X			    register int i;
X# ifdef INNERSEARCH
X			    i = putsubstchar(*bufptr, COLS - outpos, outputok);
X# else
X			    i = putsubstchar(*bufptr, COLS - outpos, TRUE);
X# endif
X			    if (i < 0) {
X				outpos += -i - 1;
X				break;
X			    }
X			    outpos += i;
X#else
X# ifdef INNERSEARCH
X			    if (outputok)
X# endif
X				putchar(*bufptr);
X			    outpos++;
X#endif /* CHARSUBST */
X			}
X			if (*UC && ((highlight==artline && marking == STANDOUT)
X#ifdef ULSMARTS
X			    || under_lining
X#endif
X			    )) {
X			    backspace();
X			    underchar();
X			}
X		    skip_put:
X			bufptr++;
X		    }
X		    else if (*bufptr == '\n' || !*bufptr) {
X						    /* newline? */
X#ifdef ULSMARTS
X			if (under_lining) {
X			    under_lining = 0;
X			    un_underline();
X			}
X#endif
X#ifdef DEBUG
X			if (debug & DEB_INNERSRCH && outpos < COLS - 6) {
X			    standout();
X			    printf("%4d",artline); 
X			    un_standout();
X			}
X#endif
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			    putchar('\n') FLUSH;
X			restart = 0;
X			outpos = 1000;	/* signal normal \n */
X		    }
X		    else if (*bufptr == '\t') {	/* tab? */
X			int incpos =  8 - outpos % 8;
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			    if (GT)
X				putchar(*bufptr);
X			    else
X				while (incpos--) putchar(' ');
X			bufptr++;
X			outpos += 8 - outpos % 8;
X		    }
X		    else if (*bufptr == '\f') {	/* form feed? */
X			if (outpos+2 > COLS)
X			    break;
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			    fputs("^L",stdout);
X			if (bufptr == blinebeg && highlight != artline)
X			    linenum = 32700;
X			    /* how is that for a magic number? */
X			bufptr++;
X			outpos += 2;
X		    }
X		    else {		/* other control char */
X			if (dont_filter_control) {
X#ifdef INNERSEARCH
X			    if (outputok)
X#endif
X				putchar(*bufptr);
X			    outpos++;
X			}
X			else if (*bufptr != '\r' || bufptr[1] != '\n') {
X			    if (outpos+2 > COLS)
X				break;
X#ifdef INNERSEARCH
X			    if (outputok)
X#endif
X			    {
X				putchar('^');
X				if (highlight == artline && *UC
X				 && marking == STANDOUT) {
X				    backspace();
X				    underchar();
X				    putchar(*bufptr+64);
X				    backspace();
X				    underchar();
X				}
X				else
X				    putchar(*bufptr+64);
X			    }
X			    outpos += 2;
X			}
X			bufptr++;
X		    }
X		    
X		} /* end of column loop */
X
X		if (outpos < 1000) {  /* did line overflow? */
X		    restart = bufptr; /* restart here next time */
X		    if (!AM || XN || outpos < COLS) {
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			    putchar('\n') FLUSH;
X		    }
X		    if (*bufptr == '\n')    /* skip the newline */
X			restart = 0;
X		}
X
X		/* handle normal end of output line formalities */
X
X		if (highlight == artline) {
X					/* were we highlighting line? */
X		    if (marking == STANDOUT)
X			un_standout();
X		    else
X			un_underline();
X		    highlight = -1;	/* no more we are */
X		    /* in case terminal highlighted rest of line earlier */
X		    /* when we did an eol with highlight turned on: */
X		    if (can_home_clear) erase_eol();
X		}
X		artline++;	/* count the line just printed */
X		if (artline - LINES + 1 > topline)
X			    /* did we just scroll top line off? */
X		    topline = artline - LINES + 1;
X			    /* then recompute top line # */
X	    }
X
X	    /* determine actual position in file */
X
X	    if (restart)	/* stranded somewhere in the buffer? */
X		artpos += restart - blinebeg;
X			    /* just calculate position */
X	    else if (in_header)
X		artpos = index(headbuf+artpos, '\n') - headbuf + 1;
X	    else		/* no, ftell will do */
X		artpos = tellart();
X	    vwtary(artline,artpos);	/* remember pos in file */
X	} /* end of line loop */
X
X#ifdef INNERSEARCH
X	innersearch = 0;
X	if (hide_everything) {
X	    *buf = hide_everything;
X	    hide_everything = 0;
X	    goto fake_command;
X	}
X#endif
X	if (linenum >= 32700)/* did last line have formfeed? */
X	    vwtary(artline-1,-vrdary(artline-1));
X			    /* remember by negating pos in file */
X
X	special = FALSE;	/* end of page, so reset page length */
X	firstpage = FALSE;	/* and say it is not 1st time thru */
X	highlight = -1;
X
X	/* extra loop bombout */
X
X#ifdef USE_NNTP
X	artsize = nntp_artsize();
Xrecheck_pager:
X#endif
X	if (artpos == artsize) {/* did we just now reach EOF? */
X	    mode = oldmode;
X	    return DA_NORM;	/* avoid --MORE--(100%) */
X	}
X
X/* not done with this article, so pretend we are a pager */
X
Xreask_pager:		    
X	unflush_output();	/* disable any ^O in effect */
X	standout();		/* enter standout mode */
X#ifdef USE_NNTP
X	if (artsize == -1)
X	    strcpy(buf,"?");
X	else
X#endif
X	    sprintf(buf,"%ld",(long)(artpos*100/artsize));
X#ifdef CHARSUBST
X	printf("%s--MORE--(%s%%)",current_charsubst(),buf);
X#else
X	printf("--MORE--(%s%%)",buf);
X#endif
X	un_standout();	/* leave standout mode */
X#ifdef CLEAREOL
X 	maybe_eol();
X#endif
X	fflush(stdout);
X	eat_typeahead();
X#ifdef DEBUG
X	if (debug & DEB_CHECKPOINTING) {
X	    printf("(%d %d %d)",checkcount,linenum,artline);
X	    fflush(stdout);
X	}
X#endif
X	if (checkcount >= docheckwhen &&
X	  linenum == LINES &&
X	  (artline > 40 || checkcount >= docheckwhen+10) ) {
X			    /* while he is reading a whole page */
X			    /* in an article he is interested in */
X	    checkcount = 0;
X	    checkpoint_rc();	/* update .newsrc */
X	}
X	cache_until_key();
X#ifdef USE_NNTP
X	if (artsize == -1 && (artsize = nntp_artsize()) != -1) {
X	    carriage_return();
X	    goto recheck_pager;
X	}
X#endif
X	mode = 'p';
X	getcmd(buf);
X	if (errno) {
X	    if (LINES < 100 && !int_count)
X		*buf = '\f';/* on CONT fake up refresh */
X	    else {
X		*buf = 'q';	/* on INTR or paper just quit */
X	    }
X	}
X	carriage_return();
X#ifdef CLEAREOL
X	if (erase_screen && can_home_clear)	
X	    clear_rest();
X	else
X#endif
X	    erase_eol();	/* and erase the prompt */
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X	fflush(stdout);
X
X    fake_command:		/* used by innersearch */
X	output_chase_phrase = TRUE;
X
X	/* parse and process pager command */
X
X	switch (page_switch()) {
X	case PS_ASK:	/* reprompt "--MORE--..." */
X	    goto reask_pager;
X	case PS_RAISE:	/* reparse on article level */
X	    mode = oldmode;
X	    return DA_RAISE;
X	case PS_TOEND:	/* fast pager loop exit */
X	    mode = oldmode;
X	    return DA_TOEND;
X	case PS_NORM:	/* display more article */
X	    break;
X	}
X    } /* end of page loop */
X}
X
X/* process pager commands */
X
Xint
Xpage_switch()
X{
X    register char *s;
X    
X    switch (*buf) {
X    case '!':			/* shell escape */
X	escapade();
X	return PS_ASK;
X#ifdef INNERSEARCH
X    case Ctl('i'): {
X	ART_LINE i = artline;
X	ART_POS pos;
X	gline = 3;
X	s = blinebeg;
X	while (*s == '\n' && i >= topline) {
X	    pos = vrdary(--i);
X	    if (pos < 0)
X		pos = -pos;
X	    if (pos < htype[PAST_HEADER].ht_minpos)
X		break;
X	    seekart((long)pos);
X	    if (readart(s = buf+1, sizeof buf - 1) == Nullch) {
X		s = blinebeg;
X		break;
X	    }
X	}
X	sprintf(cmd_buf,"^[^%c\n]",*s);
X	compile(&gcompex,cmd_buf,TRUE,TRUE);
X	goto caseG;
X    }
X    case Ctl('g'):
X	gline = 3;
X	compile(&gcompex,"^Subject:",TRUE,TRUE);
X	goto caseG;
X    case 'g':		/* in-article search */
X	if (!finish_command(FALSE))/* get rest of command */
X	    return PS_ASK;
X	s = buf+1;
X	if (isspace(*s))
X	    s++;
X	if ((s = compile(&gcompex,s,TRUE,TRUE)) != Nullch) {
X			    /* compile regular expression */
X	    printf("\n%s\n",s) FLUSH;
X	    return PS_ASK;
X	}
X	carriage_return();
X	erase_eol();	/* erase the prompt */
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X	/* FALL THROUGH */
X    caseG:
X    case 'G': {
X	ART_POS start_where;
X
X	if (gline < 0 || gline > LINES-2)
X	    gline = LINES-2;
X#ifdef DEBUG
X	if (debug & DEB_INNERSRCH)
X	    printf("Start here? %d  >=? %d\n",topline + gline + 1,artline)
X	      FLUSH;
X#endif
X	if (*buf == Ctl('i') || topline+gline+1 >= artline)
X	    start_where = artpos;
X			/* in case we had a line wrap */
X	else {
X	    start_where = vrdary(topline+gline+1);
X	    if (start_where < 0)
X		start_where = -start_where;
X	}
X	if (start_where < htype[PAST_HEADER].ht_minpos)
X	    start_where = htype[PAST_HEADER].ht_minpos;
X	seekart((long)start_where);
X	innerlight = 0;
X	innersearch = 0; /* assume not found */
X	while (readart(buf, sizeof buf) != Nullch) {
X#ifdef DEBUG
X	    if (debug & DEB_INNERSRCH)
X		printf("Test %s",buf) FLUSH;
X#endif
X	    if (execute(&gcompex,buf) != Nullch) {
X		innersearch = tellart();
X		break;
X	    }
X	}
X	if (!innersearch) {
X	    seekart(artpos);
X	    fputs("(Not found)",stdout) FLUSH;
X	    return PS_ASK;
X	}
X#ifdef DEBUG
X	if (debug & DEB_INNERSRCH)
X	    printf("On page? %ld <=? %ld\n",(long)innersearch,(long)artpos)
X	      FLUSH;
X#endif
X	if (innersearch <= artpos) {	/* already on page? */
X	    if (innersearch < artpos) {
X		artline = topline+1;
X		while (vrdary(artline) < innersearch)
X		    artline++;
X	    }
X	    highlight = artline - 1;
X#ifdef DEBUG
X	    if (debug & DEB_INNERSRCH)
X		printf("@ %d\n",highlight) FLUSH;
X#endif
X	    topline = highlight - gline;
X	    if (topline < -1)
X		topline = -1;
X	    *buf = '\f';		/* fake up a refresh */
X	    innersearch = 0;
X	    return page_switch();
X	}
X	else {				/* who knows how many lines it is? */
X	    do_fseek = TRUE;
X	    hide_everything = Ctl('l');
X	}
X	return PS_NORM;
X    }
X#else
X    case 'g': case 'G': case Ctl('g'):
X	notincl("g");
X	return PS_ASK;
X#endif
X    case '\n':		/* one line down */
X	special = TRUE;
X	slines = 2;
X	return PS_NORM;
X#ifdef ROTATION
X    case 'X':
X	rotate = !rotate;
X	/* FALL THROUGH */
X#endif
X    case 'l':
X    case '\f':		/* refresh screen */
X    refresh_screen:
X#ifdef DEBUG
X	if (debug & DEB_INNERSRCH) {
X	    printf("Topline = %d",topline) FLUSH;
X	    fgets(buf, sizeof buf, stdin);
X	}
X#endif
X	clear();
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X	do_fseek = TRUE;
X	artline = topline;
X	if (artline < 0)
X	    artline = 0;
X	firstpage = (topline < 0);
X	return PS_NORM;
X#ifdef INNERSEARCH
X    case Ctl('e'):
X#ifdef USE_NNTP
X	nntp_finishbody(FB_OUTPUT);
X	artsize = nntp_artsize();
X#endif
X	innerlight = artline - 1;
X	innersearch = artsize;
X	gline = 0;
X	hide_everything = 'b';
X	return PS_NORM;
X#endif
X    case 'B':		/* one line up */
X	if (topline < 0)
X	    break;
X	if (*IL && *HO) {
X	    ART_POS pos;
X	    home_cursor();
X	    insert_line();
X	    carriage_return();	/* Resets kernel's tab column counter to 0 */
X	    pos = vrdary(topline-1);
X	    if (pos < 0)
X		pos = -pos;
X	    if (pos >= htype[PAST_HEADER].ht_minpos) {
X		seekart((long)pos);
X		if (readart(s = buf, sizeof buf) != Nullch) {
X		    fputs(buf, stdout) FLUSH;
X		    topline--;
X		    artpos = vrdary(--artline);
X		    if (artpos < 0)
X			artpos = -artpos;
X		    seekart(artpos);
X		    goto_line(1, LINES-1);
X		    erase_eol();
X		    carriage_return();
X		    return PS_ASK;
X		}
X	    }
X	}
X	/* FALL THROUGH */
X    case 'b':
X    case '\b':
X    case Ctl('b'): {	/* back up a page */
X	ART_LINE target;
X
X#ifdef CLEAREOL
X	if (can_home_clear)	/* if we can let home do it */
X	    home_cursor();
X	else
X#endif
X	    clear();
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X
X	do_fseek = TRUE;	/* reposition article file */
X	if (*buf == 'B')
X	    target = topline - 1;
X	else {
X	    target = topline - (LINES - 2);
X	    if (marking && (marking_areas & BACKPAGE_MARKING))
X		highlight = topline;
X	}
X	artline = topline;
X	if (artline >= 0) do {
X	    artline--;
X	} while(artline >= 0 && artline > target && vrdary(artline-1) >= 0);
X	topline = artline;
X			/* remember top line of screen */
X			/*  (line # within article file) */
X	if (artline < 0)
X	    artline = 0;
X	firstpage = (topline < 0);
X	return PS_NORM;
X    }
X    case 'h': {		/* help */
X	int cmd;
X
X	if ((cmd = help_page()) > 0)
X	    pushchar(cmd);
X	return PS_ASK;
X    }
X    case 't':		/* output thread data */
X	page_line = 1;
X	entire_tree(curr_artp);
X	return PS_ASK;
X    case '_':
X	if (!finish_dblchar())
X	    return PS_ASK;
X	switch (buf[1] & 0177) {
X#ifdef CHARSUBST
X	case 'C':
X	    if (!*(++charsubst))
X		charsubst = charsets;
X	    goto refresh_screen;
X#endif
X	default:
X	    goto leave_pager;
X	}
X	break;
X    case '\177':
X    case '\0':		/* treat del,break as 'n' */
X	*buf = 'n';
X	/* FALL THROUGH */
X    case 'k':	case 'K':	case 'J':
X    case 'n':	case 'N':	case Ctl('n'):
X    case 's':	case 'S':
X    case 'e':
X    case 'u':
X    case 'w':	case 'W':
X    case '|':
X	mark_as_read();		/* mark article as read */
X	/* FALL THROUGH */
X    case 'U':	case ',':
X    case '<':	case '>':
X    case '[':	case ']':
X    case '{':	case '}':
X    case '(':   case ')':
X    case ':':
X    case '+':
X    case '#':
X    case '$':
X    case '&':
X    case '-':
X    case '.':
X    case '/':
X    case '1': case '2': case '3': case '4': case '5':
X    case '6': case '7': case '8': case '9':
X    case '=':
X    case '?':
X    case 'A':	case 'T':
X    case 'c':	case 'C':	
X#ifdef DEBUG
X    case 'D':
X#endif
X    case 'E':
X    case 'f':	case 'F':	case Ctl('f'):
X    case 'j':
X				case Ctl('k'):
X    case 'm':	case 'M':	
X    case 'p':	case 'P':	case Ctl('p'):	
X		case 'Q':
X    case 'r':	case 'R':	case Ctl('r'):
X    case 'v':
X		case 'Y':
X#ifndef ROTATION
X    case 'x':	case 'X':
X#endif
X    case Ctl('x'):
X    case 'z':	case 'Z':
X    case '^':   case Ctl('^'):
Xleave_pager:
X#ifdef ROTATION
X	rotate = FALSE;
X#endif
X	reread = FALSE;
X	do_hiding = TRUE;
X#ifdef USE_NNTP
X	nntp_finishbody(FB_OUTPUT);
X#endif
X	if (index("nNpP\016\020",*buf) == Nullch &&
X	  index("wWsSe:!&|/?123456789.",*buf) != Nullch) {
X	    setdfltcmd();
X	    standout();		/* enter standout mode */
X	    interp(cmd_buf, sizeof cmd_buf, mailcall);
X#ifdef CHARSUBST
X	    printf(prompt,cmd_buf,current_charsubst(),dfltcmd);
X#else
X	    printf(prompt,cmd_buf,dfltcmd);
X#endif
X			    /* print prompt, whatever it is */
X	    un_standout();	/* leave standout mode */
X	    putchar(' ');
X	    fflush(stdout);
X	}
X	return PS_RAISE;	/* and pretend we were at end */
X#ifdef ROTATION
X    case 'x':
X	rotate = TRUE;
X	/* FALL THROUGH */
X#endif
X    case 'd':		/* half page */
X    case Ctl('d'):
X	special = TRUE;
X	slines = LINES / 2 + 1;
X	/* no divide-by-zero, thank you */
X	if (LINES > 2 && (LINES & 1) && artline % (LINES-2) >= LINES/2 - 1)
X	    slines++;
X	goto go_forward;
X    case 'y':
X    case Ctl('v'):			/* Leaving it undocumented in case */
X					/* I want to steal the key--LAW */
X    case ' ':	/* continue current article */
X	if (erase_screen) {	/* -e? */
X#ifdef CLEAREOL
X	    if (can_home_clear)	/* if we can let home do it */
X		home_cursor();
X	    else
X#endif
X		clear();	/* clear screen */
X	    carriage_return();	/* Resets kernel's tab column counter to 0 */
X	    fflush(stdout);
X	}
X	else {
X	    special = TRUE;
X	    slines = LINES;
X	}
X    go_forward:
X	if (*blinebeg != '\f'
X#ifdef CUSTOMLINES
X	  && (!pagestop || blinebeg != art_buf ||
X	      !execute(&page_compex,blinebeg))
X#endif
X	  ) {
X	    if (!special
X	     || (marking && (*buf!='d' || (marking_areas&HALFPAGE_MARKING)))) {
X		restart = blinebeg;
X		artline--;	 /* restart this line */
X		artpos = alinebeg;
X		if (special)
X		    up_line();
X		if (marking)
X		    highlight = artline;
X	    }
X	    else
X		slines--;
X	}
X	return PS_NORM;
X    case 'q':	/* quit this article? */
X	do_hiding = TRUE;
X#ifdef USE_NNTP
X	nntp_finishbody(FB_OUTPUT);
X#endif
X	return PS_TOEND;
X    default:
X	fputs(hforhelp,stdout) FLUSH;
X	settle_down();
X	return PS_ASK;
X    }
X    return PS_ASK;
X}
X
X#ifdef INNERSEARCH
Xbool
Xinnermore()
X{
X    if (artpos < innersearch) {		/* not even on page yet? */
X#ifdef DEBUG
X	if (debug & DEB_INNERSRCH)
X	    printf("Not on page %ld < %ld\n",(long)artpos,(long)innersearch)
X	      FLUSH;
X#endif
X	return TRUE;
X    }
X    if (artpos == innersearch) {	/* just got onto page? */
X	isrchline = artline;		/* remember first line after */
X	if (innerlight)
X	    highlight = innerlight;
X	else
X	    highlight = artline - 1;
X#ifdef DEBUG
X	if (debug & DEB_INNERSRCH)
X	    printf("There it is %ld = %ld, %d @ %d\n",(long)artpos,
X		(long)innersearch,hide_everything,highlight) FLUSH;
X#endif
X	if (hide_everything) {		/* forced refresh? */
X	    topline = artline - gline - 1;
X	    if (topline < -1)
X		topline = -1;
X	    return FALSE;		/* let refresh do it all */
X	}
X    }
X#ifdef DEBUG
X    if (debug & DEB_INNERSRCH)
X	printf("Not far enough? %d <? %d + %d\n",artline,isrchline,gline)
X	  FLUSH;
X#endif
X    if (artline < isrchline + gline) {
X	return TRUE;
X    }
X    return FALSE;
X}
X#endif
X
X#if defined(MIMESHOW) || defined(MIMESTORE)
Xint
Xnontext(s)
Xchar *s;
X{
X    char *t;
X
X    if (*s == '\n')
X	return 0;
X    while (isspace(*s))
X	s++;
X    t = index(s, ';');
X    if (!t)
X	t = index(s, '\n');
X    if (t)
X	*t-- = '\0';
X    while (t >= s && isspace(*t))
X	t--;
X    *++t = '\0';
X    if (notplain(s))
X	return 1;
X    return 0;
X}
X
X/* return true if this isn't "text" or "text/plain" */
X
Xint
Xnotplain(s)
Xchar *s;
X{
X    char *t;
X    if (!s)
X	return 1;
X    while (isspace(*s))
X	s++;
X    t = s + strlen(s) - 1;
X    while (t >= s && isspace(*t))
X	t--;
X    *++t = '\0';
X    if (t - s == 4 && !strncasecmp(s, "text", 4))
X	return 0;
X    if (strncasecmp(s, "text/plain", 10))
X	return 1;
X    t = index(s, ';');
X    while (t) {
X	t++;
X	while (isspace(*t))
X	    t++;
X	if (!strncasecmp(t, "charset", 7)) {
X	    s = index(t, '=');
X	    if (s) {
X		s++;
X		while (isspace(*s))
X		    s++;
X		if (!strncasecmp(s, "us-ascii", 8))
X		    return 0;
X	    }
X	    return 1;
X	}
X	t = index(t, ';');
X    }
X    return 0;	/* no charset, was text/plain */
X}
X
X/* return true if this isn't "7bit", "8bit", or "binary" */
X
Xint
Xnonprint(s)
Xchar *s;
X{
X    while (isspace(*s))
X	s++;
X    if (strncasecmp(s, "7bit", 4) == 0)
X	s += 4;
X    else if (strncasecmp(s, "8bit", 4) == 0)
X	s += 4;
X    else if (strncasecmp(s, "binary", 6) == 0)
X	s += 6;
X    else
X	return 1;
X    return !(*s == '\0' || isspace(*s) || *s == ';' || *s == '(');	/*)*/ 
X}
X#endif
SHAR_EOF
  $shar_touch -am 1118220194 'trn-3.6/art.c' &&
  chmod 0644 'trn-3.6/art.c' ||
  echo 'restore of trn-3.6/art.c failed'
  shar_count="`wc -c < 'trn-3.6/art.c'`"
  test 28992 -eq "$shar_count" ||
    echo "trn-3.6/art.c: original size 28992, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/art.h ==============
if test -f 'trn-3.6/art.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/art.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/art.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/art.h' &&
X/* $Id: art.h,v 3.0 1991/09/09 20:18:23 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X/* do_article() return values */
X
X#define DA_NORM 0
X#define DA_RAISE 1
X#define DA_CLEAN 2
X#define DA_TOEND 3
X
XEXT ART_LINE highlight INIT(-1);/* next line to be highlighted */
XEXT ART_POS artsize;		/* size in bytes of article */
X
X#ifdef INNERSEARCH
XEXT ART_POS innersearch INIT(0); /* artpos of end of line we want to visit */
XEXT ART_LINE innerlight INIT(0); /* highlight position for innersearch or 0 */
XEXT char hide_everything INIT(0);/* if set, do not write page now, */
X#endif				 /* ...but execute char when done with page */
X
Xvoid	art_init _((void));
Xint	do_article _((void));
Xint	page_switch _((void));
Xbool	innermore _((void));
SHAR_EOF
  $shar_touch -am 1007195794 'trn-3.6/art.h' &&
  chmod 0644 'trn-3.6/art.h' ||
  echo 'restore of trn-3.6/art.h failed'
  shar_count="`wc -c < 'trn-3.6/art.h'`"
  test 1286 -eq "$shar_count" ||
    echo "trn-3.6/art.h: original size 1286, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/artio.c ==============
if test -f 'trn-3.6/artio.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/artio.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/artio.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/artio.c' &&
X/* $Id: artio.c,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "cache.h"
X#include "rthread.h"
X#include "head.h"
X#include "nntp.h"
X#include "art.h"
X#include "bits.h"
X#include "final.h"
X#include "ngdata.h"
X#include "INTERN.h"
X#include "artio.h"
X
Xvoid
Xartio_init()
X{
X    ;
X}
X
X/* open an article, unless it's already open */
X
XFILE *
Xartopen(artnum)
XART_NUM artnum;
X{
X#ifndef USE_NNTP
X    char artname[MAXFILENAME];		/* filename of current article */
X#endif
X    ARTICLE *ap = find_article(artnum);
X
X    if (!ap || !artnum || (ap->flags & (AF_MISSING|AF_FAKE)) == AF_MISSING) {
X	errno = ENOENT;
X	return Nullfp;
X    }
X    if (openart == artnum) {		/* this article is already open? */
X	seekart(0L);			/* just get to the beginning */
X	return artfp;			/* and say we succeeded */
X    }
X    if (artfp != Nullfp) {		/* it was somebody else? */
X	fclose(artfp);			/* put them out of their misery */
X	openart = 0;			/* and remember them no more */
X    }
Xretry_open:
X#ifdef USE_NNTP
X    artfp = nntp_body(artnum);
X#else
X    sprintf(artname,"%ld",(long)artnum);
X    artfp = fopen(artname,"r");
X#endif
X    if (!artfp) {
X#ifdef ETIMEDOUT
X	if (errno == ETIMEDOUT)
X	    goto retry_open;
X#endif
X	if (errno == EINTR)
X	    goto retry_open;
X	uncache_article(ap,FALSE);
X    } else {
X#ifdef LINKART
X	char tmpbuf[256];
X	char *s;
X
X	if (!fstat(fileno(artfp),&filestat)
X	 && filestat.st_size < sizeof tmpbuf) {
X	    fgets(tmpbuf,sizeof tmpbuf,artfp);
X	    if (*tmpbuf == '/') {	/* is a "link" to another article */
X		fclose(artfp);
X		if (s=index(tmpbuf,'\n'))
X		    *s = '\0';
X		if (!(artfp = fopen(tmpbuf,"r"))) {
X		    uncache_article(ap,FALSE);
X		} else {
X		    if (*linkartname)
X			free(linkartname);
X		    linkartname = savestr(tmpbuf);
X		}
X	    } else
X		seekart(0L);		/* get back to the beginning */
X	}
X#endif
X	openart = artnum;		/* remember what we did here */
X    }
X    return artfp;			/* and return either fp or NULL */
X}
SHAR_EOF
  $shar_touch -am 1007195794 'trn-3.6/artio.c' &&
  chmod 0644 'trn-3.6/artio.c' ||
  echo 'restore of trn-3.6/artio.c failed'
  shar_count="`wc -c < 'trn-3.6/artio.c'`"
  test 2535 -eq "$shar_count" ||
    echo "trn-3.6/artio.c: original size 2535, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/artio.h ==============
if test -f 'trn-3.6/artio.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/artio.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/artio.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/artio.h' &&
X/* $Id: artio.h,v 3.0 1991/09/09 20:18:23 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
XEXT ART_POS artpos INIT(0);	/* byte position in article file */
X
XEXT ART_LINE artline INIT(0);	/* current line number in article file */
XEXT FILE *artfp INIT(Nullfp);	/* current article file pointer */
XEXT ART_NUM openart INIT(0);	/* the article number we have open */
X
X#ifdef LINKART
XEXT char *linkartname INIT(nullstr);/* real name of article for Eunice */
X#endif
X
Xvoid artio_init _((void));
XFILE *artopen _((ART_NUM));	/* open an article unless already opened */
X
X#ifdef USE_NNTP
X# define seekart(pos) nntp_seekart(pos)
X# define readart(s,len) nntp_readart(s,len)
X# define tellart() nntp_tellart()
X#else
X# define seekart(pos) fseek(artfp, pos, 0)
X# define readart(s,len) fgets(s,len,artfp)
X# define tellart() ftell(artfp)
X#endif
SHAR_EOF
  $shar_touch -am 1007195794 'trn-3.6/artio.h' &&
  chmod 0644 'trn-3.6/artio.h' ||
  echo 'restore of trn-3.6/artio.h failed'
  shar_count="`wc -c < 'trn-3.6/artio.h'`"
  test 1382 -eq "$shar_count" ||
    echo "trn-3.6/artio.h: original size 1382, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/artsrch.c ==============
if test -f 'trn-3.6/artsrch.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/artsrch.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/artsrch.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/artsrch.c' &&
X/* $Id: artsrch.c,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "search.h"
X#include "term.h"
X#include "util.h"
X#include "intrp.h"
X#include "cache.h"
X#include "bits.h"
X#include "kfile.h"
X#include "head.h"
X#include "final.h"
X#include "nntp.h"
X#include "ng.h"
X#include "ngdata.h"
X#include "ngstuff.h"
X#include "artio.h"
X#include "rthread.h"
X#include "rt-select.h"
X#include "INTERN.h"
X#include "artsrch.h"
X
Xvoid
Xartsrch_init()
X{
X#ifdef ARTSEARCH
X    init_compex(&sub_compex);
X    init_compex(&art_compex);
X#endif
X}
X
X/* search for an article containing some pattern */
X
X#ifdef ARTSEARCH
Xint
Xart_search(patbuf,patbufsiz,get_cmd)
Xchar *patbuf;				/* if patbuf != buf, get_cmd must */
Xint patbufsiz;
Xint get_cmd;				/*   be set to FALSE!!! */
X{
X    char *pattern;			/* unparsed pattern */
X    register char cmdchr = *patbuf;	/* what kind of search? */
X    register char *s;
X    bool backward = cmdchr == '?' || cmdchr == Ctl('p');
X					/* direction of search */
X    COMPEX *compex;			/* which compiled expression */
X    char *cmdlst = Nullch;		/* list of commands to do */
X    int normal_return = SRCH_NOTFOUND;	/* assume no commands */
X    bool saltaway = FALSE;		/* store in KILL file? */
X    char howmuch;		/* search scope: subj/from/Hdr/head/art */
X    char *srchhdr;		/* header to search if Hdr scope */
X    bool topstart = 0;
X    bool doread;			/* search read articles? */
X    bool foldcase = TRUE;		/* fold upper and lower case? */
X    int ignorethru = 0;			/* should we ignore the thru line? */
X    ART_NUM srchfirst;
X
X    int_count = 0;
X    if (cmdchr == '/' || cmdchr == '?') {	/* normal search? */
X	if (get_cmd && buf == patbuf)
X	    if (!finish_command(FALSE))	/* get rest of command */
X		return SRCH_ABORT;
X	compex = &art_compex;
X	if (patbuf[1]) {
X	    howmuch = ARTSCOPE_SUBJECT;
X	    srchhdr = Nullch;
X	    doread = FALSE;
X	}
X	else {
X	    howmuch = art_howmuch;
X	    srchhdr = art_srchhdr;
X	    doread = art_doread;
X	}
X	s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */
X	pattern = buf;
X	if (*pattern) {
X	    if (*lastpat)
X		free(lastpat);
X	    lastpat = savestr(pattern);
X	}
X	if (*s) {			/* modifiers or commands? */
X	    for (s++; *s && index("KabrcfhtBHIN",*s); s++) {
X		switch (*s) {
X		case 'f':		/* scan the From line */
X		    howmuch = ARTSCOPE_FROM;
X		    break;
X		case 'H':		/* scan a specific header */
X		    howmuch = ARTSCOPE_ONEHDR;
X		    srchhdr = s + 1;
X		    if (!(s = index(srchhdr, ':'))) {
X			s = buf + strlen(buf);
X			*s++ = ':';
X			*s = '\0';
X		    }
X		    else
X			s++;
X		    srchhdr = savestr(srchhdr);
X		    goto loop_break;
X		case 'h':		/* scan header */
X		    howmuch = ARTSCOPE_HEAD;
X		    break;
X		case 'b':		/* scan body sans signature */
X		    howmuch = ARTSCOPE_BODY_NOSIG;
X		    break;
X		case 'B':		/* scan body */
X		    howmuch = ARTSCOPE_BODY;
X		    break;
X		case 'a':		/* scan article */
X		    howmuch = ARTSCOPE_ARTICLE;
X		    break;
X		case 't':		/* start from the top */
X		    topstart = TRUE;
X		    break;
X		case 'r':		/* scan read articles */
X		    doread = TRUE;
X		    break;
X		case 'K':		/* put into KILL file */
X		    saltaway = TRUE;
X		    break;
X		case 'c':		/* make search case sensitive */
X		    foldcase = FALSE;
X		    break;
X		case 'I':		/* ignore the killfile thru line */
X		    ignorethru = 1;
X		    break;
X		case 'N':		/* override ignore if -k was used */
X		    ignorethru = -1;
X		    break;
X		}
X	    }
X          loop_break:;
X	}
X	while (isspace(*s) || *s == ':')
X	    s++;
X	if (*s) {
X#ifdef OLD_RN_WAY
X	    if (*s == 'm' || *s == 'M')
X#else
X	    if (*s == 'm')
X#endif
X		doread = TRUE;
X	    if (*s == 'k')		/* grandfather clause */
X		*s = 'j';
X	    cmdlst = savestr(s);
X	    normal_return = SRCH_DONE;
X	}
X	art_howmuch = howmuch;
X	if (art_srchhdr != srchhdr) {
X	    if (art_srchhdr)
X		free(art_srchhdr);
X	    art_srchhdr = srchhdr;
X	}
X	art_doread = doread;
X	if (srchahead)
X	    srchahead = -1;
X    }
X    else {
X	register char *h;
X
X	howmuch = ARTSCOPE_SUBJECT;	/* just search subjects */
X	srchhdr = Nullch;
X	doread = (cmdchr == Ctl('p'));
X	if (cmdchr == Ctl('n'))
X	    normal_return = SRCH_SUBJDONE;
X	compex = &sub_compex;
X	pattern = patbuf+1;
X	strcpy(pattern,": *");
X	h = pattern + strlen(pattern);
X	interp(h,patbufsiz - (h-patbuf),"%\\s");  /* fetch current subject */
X	if (cmdchr == 'k' || cmdchr == 'K' || cmdchr == ','
X	 || cmdchr == '+' || cmdchr == '.') {
X	    if (cmdchr != 'k')
X		saltaway = TRUE;
X	    normal_return = SRCH_DONE;
X	    if (cmdchr == '+') {
X		cmdlst = savestr("+");
X		ignorethru = 1;
X	    }
X	    else if (cmdchr == '.') {
X		cmdlst = savestr(".");
X		ignorethru = 1;
X	    }
X	    else {
X		if (cmdchr == ',')
X		    cmdlst = savestr(",");
X		mark_as_read();		/* this article has this subject */
X	    }
X	    if (!*h) {
X#ifdef VERBOSE
X		IF(verbose)
X		    fputs("\nCannot process a null subject.\n",stdout) FLUSH;
X		ELSE
X#endif
X#ifdef TERSE
X		    fputs("\nNull subject.\n",stdout) FLUSH;
X#endif
X		return SRCH_ABORT;
X	    }
X#ifdef VERBOSE
X	    else if (verbose)
X		if (cmdchr != '+' && cmdchr != '.')
X		    printf("\nMarking subject \"%s\" as read.\n",h) FLUSH;
X		else
X		    printf("\nSelecting subject \"%s\".\n",h) FLUSH;
X#endif
X	}
X	else if (!srchahead)
X	    srchahead = -1;
X
X	{			/* compensate for notesfiles */
X	    register int i;
X	    for (i = 24; *h && i--; h++)
X		if (*h == '\\')
X		    h++;
X	    *h = '\0';
X	}
X#ifdef DEBUG
X	if (debug) {
X	    printf("\npattern = %s\n",pattern) FLUSH;
X	}
X#endif
X    }
X    if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) {
X					/* compile regular expression */
X	printf("\n%s\n",s) FLUSH;
X	return SRCH_ABORT;
X    }
X#ifdef KILLFILES
X    if (saltaway) {
X	char saltbuf[LBUFLEN], *f;
X
X	s = saltbuf;
X	f = pattern;
X	*s++ = '/';
X	while (*f) {
X	    if (*f == '/')
X		*s++ = '\\';
X	    *s++ = *f++;
X	}
X	*s++ = '/';
X	if (doread)
X	    *s++ = 'r';
X	if (ignorethru)
X	    *s++ = (ignorethru == 1 ? 'I' : 'N');
X	if (howmuch != ARTSCOPE_SUBJECT) {
X	    *s++ = scopestr[howmuch];
X	    if (howmuch == ARTSCOPE_ONEHDR) {
X		safecpy(s,srchhdr,LBUFLEN-(s-saltbuf));
X		s = index(s,':');
X		if (!s)
X		    s = saltbuf+LBUFLEN-2;
X	    }
X	}
X	*s++ = ':';
X	if (!cmdlst)
X	    cmdlst = savestr("j");
X	safecpy(s,cmdlst,LBUFLEN-(s-saltbuf));
X	kf_append(saltbuf);
X    }
X#endif
X    if (cmdlst && index(cmdlst,'='))
X	normal_return = SRCH_ERROR;	/* listing subjects is an error? */
X    if (get_cmd) {
X	fputs("\nSearching...\n",stdout) FLUSH;
X					/* give them something to read */
X    }
X    if (mode == 't') {
X	if (!cmdlst)
X	    if (sel_mode == SM_ARTICLE)/* set the selector's default command */
X		cmdlst = savestr("+");
X	    else
X		cmdlst = savestr("++");
X	if (sel_rereading)
X	    doread = TRUE;
X	normal_return = SRCH_DONE;
X    }
X    if (ignorethru == 0 && kill_thru_kludge && cmdlst
X     && (*cmdlst == '+' || *cmdlst == '.'))
X	ignorethru = 1;
X    srchfirst = doread? absfirst
X		      : (mode != 'k' || ignorethru > 0)? firstart : killfirst;
X    if (topstart || art == 0) {
X	art = lastart+1;
X	topstart = FALSE;
X    }
X    if (backward) {
X	if (cmdlst && art <= lastart)
X	    art++;			/* include current article */
X    }
X    else {
X	if (art > lastart)
X	    art = srchfirst-1;
X	else if (cmdlst && art >= absfirst)
X	    art--;			/* include current article */
X    }
X    if (srchahead > 0) {
X	if (!backward)
X	    art = srchahead - 1;
X	srchahead = -1;
X    }
X    assert(!cmdlst || *cmdlst);
X    perform_cnt = 0;
X    for (;;) {
X	/* check if we're out of articles */
X	if (backward? (--art < srchfirst) : (++art > lastart)) {
X	    if (cmdlst)
X		free(cmdlst);
X	    return normal_return;
X	}
X	if (int_count) {
X	    int_count = 0;
X	    if (cmdlst)
X		free(cmdlst);
X	    return SRCH_INTR;
X	}
X	artp = article_ptr(art);
X	if (doread || !(artp->flags & AF_READ)) {
X	    if (wanted(compex,art,howmuch)) {
X				    /* does the shoe fit? */
X		if (cmdlst) {
X		    if (perform(cmdlst,TRUE)) {
X			free(cmdlst);
X			return SRCH_INTR;
X		    }
X		}
X		else
X		    return SRCH_FOUND;
X	    }
X	    else if (!cmdlst && ! (art%50)) {
X		printf("...%ld",(long)art);
X		fflush(stdout);
X	    }
X	}
X    }
X}
X
X/* determine if article fits pattern */
X/* returns TRUE if it exists and fits pattern, FALSE otherwise */
X
Xbool
Xwanted(compex, artnum, scope)
XCOMPEX *compex;
XART_NUM artnum;
Xchar_int scope;
X{
X    ARTICLE *ap = find_article(artnum);
X
X    if (!ap || (ap->flags & AF_MISSING))
X	return FALSE;
X
X    switch (scope) {
X    case ARTSCOPE_SUBJECT:
X	strcpy(buf,"Subject: ");
X	strncpy(buf+9,fetchsubj(artnum,FALSE),256);
X#ifdef DEBUG
X	if (debug & DEB_SEARCH_AHEAD)
X	    printf("%s\n",buf) FLUSH;
X#endif
X	break;
X    case ARTSCOPE_FROM:
X	strcpy(buf, "From: ");
X	strncpy(buf+6,fetchfrom(artnum,FALSE),256);
X	break;
X    case ARTSCOPE_ONEHDR:
X    {
X	int header_num;
X	char *s;
X	assert(art_srchhdr != Nullch);
X	s = index(art_srchhdr,':');
X	header_num = set_line_type(art_srchhdr, s);
X	if (header_num == SOME_LINE)
X	    return FALSE;  /* FIX ME */
X	untrim_cache = TRUE;
X	strcpy(buf, art_srchhdr);
X	sprintf(buf + (s-art_srchhdr), ": %s",
X		prefetchlines(artnum,header_num,FALSE));
X	untrim_cache = FALSE;
X	break;
X    }
X    default:
X	if (scope != ARTSCOPE_BODY && scope != ARTSCOPE_BODY_NOSIG) {
X	    if (!parseheader(artnum))
X		return FALSE;
X	    /* see if it's in the header */
X	    if (execute(compex,headbuf) != Nullch) /* does it match? */
X		return TRUE;			   /* say, "Eureka!" */
X	    if (scope < ARTSCOPE_ARTICLE)
X		return FALSE;
X	}
X	if (!artopen(artnum))		/* ensure we have the body */
X	    return FALSE;
X	seekart(htype[PAST_HEADER].ht_minpos);
X	/* loop through each line of the article */
X	while (readart(buf,LBUFLEN) != Nullch) {
X	    if (scope == ARTSCOPE_BODY_NOSIG && *buf == '-' && buf[1] == '-'
X	     && (buf[2] == '\n' || (buf[2] == ' ' && buf[3] == '\n'))) {
X#ifdef USE_NNTP
X		nntp_finishbody(FB_SILENT);
X#endif
X		break;
X	    }
X	    if (execute(compex,buf) != Nullch) {/* does it match? */
X#ifdef USE_NNTP
X		nntp_finishbody(FB_SILENT);
X#endif
X		return TRUE;			/* say, "Eureka!" */
X	    }
X	}
X	return FALSE;			/* out of article, so no match */
X    }
X    return execute(compex,buf) != Nullch;
X}
X#endif
X
SHAR_EOF
  $shar_touch -am 1107173594 'trn-3.6/artsrch.c' &&
  chmod 0644 'trn-3.6/artsrch.c' ||
  echo 'restore of trn-3.6/artsrch.c failed'
  shar_count="`wc -c < 'trn-3.6/artsrch.c'`"
  test 10580 -eq "$shar_count" ||
    echo "trn-3.6/artsrch.c: original size 10580, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/artsrch.h ==============
if test -f 'trn-3.6/artsrch.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/artsrch.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/artsrch.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/artsrch.h' &&
X/* $Id: artsrch.h,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#ifndef NBRA
X#include "search.h"
X#endif
X
X#ifdef ARTSEARCH
X
X#define SRCH_ABORT 0
X#define SRCH_INTR 1
X#define SRCH_FOUND 2
X#define SRCH_NOTFOUND 3
X#define SRCH_DONE 4
X#define SRCH_SUBJDONE 5
X#define SRCH_ERROR 6
X#endif
X
XEXT char *lastpat INIT(nullstr);	/* last search pattern */
X#ifdef ARTSEARCH
XEXT COMPEX sub_compex;		/* last compiled subject search */
XEXT COMPEX art_compex;		/* last compiled normal search */
X#   ifdef CONDSUB
XEXT COMPEX *bra_compex INIT(&(art_compex));
X					/* current compex with brackets */
X#   endif
X
X#define ARTSCOPE_SUBJECT	0
X#define ARTSCOPE_FROM		1
X#define ARTSCOPE_ONEHDR		2
X#define ARTSCOPE_HEAD		3
X#define ARTSCOPE_BODY_NOSIG	4
X#define ARTSCOPE_BODY		5
X#define ARTSCOPE_ARTICLE	6
X
XEXT char scopestr[] INIT("sfHha");
XEXT char art_howmuch;		/* search scope */
XEXT char *art_srchhdr;		/* specific header to search or NULL */
XEXT bool art_doread;		/* search read articles? */
X#endif
X
Xvoid	artsrch_init _((void));
X#ifdef ARTSEARCH
Xint	art_search _((char*, int, int));
Xbool	wanted _((COMPEX*, ART_NUM, char_int));
X			/* return TRUE if current article matches pattern */
X#endif
SHAR_EOF
  $shar_touch -am 1107173594 'trn-3.6/artsrch.h' &&
  chmod 0644 'trn-3.6/artsrch.h' ||
  echo 'restore of trn-3.6/artsrch.h failed'
  shar_count="`wc -c < 'trn-3.6/artsrch.h'`"
  test 1753 -eq "$shar_count" ||
    echo "trn-3.6/artsrch.h: original size 1753, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/artstate.h ==============
if test -f 'trn-3.6/artstate.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/artstate.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/artstate.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/artstate.h' &&
X/* $Id: artstate.h,v 3.0 1991/09/09 20:18:23 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
XEXT bool reread INIT(FALSE);		/* consider current art temporarily */
X					/* unread? */
X
XEXT bool do_fseek INIT(FALSE);	/* should we back up in article file? */
X
XEXT bool oldsubject INIT(FALSE);	/* not 1st art in subject thread */
XEXT ART_LINE topline INIT(-1);		/* top line of current screen */
XEXT bool do_hiding INIT(TRUE);		/* hide header lines with -h? */
X#ifdef ROTATION
XEXT bool rotate INIT(FALSE);		/* has rotation been requested? */
X#endif
XEXT char *prompt;			/* pointer to current prompt */
X
XEXT char *firstline INIT(Nullch);			/* special first line? */
X#ifdef CUSTOMLINES
XEXT char *hideline INIT(Nullch);		/* custom line hiding? */
XEXT char *pagestop INIT(Nullch);		/* custom page terminator? */
XEXT COMPEX hide_compex;
XEXT COMPEX page_compex;
X#endif
SHAR_EOF
  $shar_touch -am 0711223593 'trn-3.6/artstate.h' &&
  chmod 0644 'trn-3.6/artstate.h' ||
  echo 'restore of trn-3.6/artstate.h failed'
  shar_count="`wc -c < 'trn-3.6/artstate.h'`"
  test 1415 -eq "$shar_count" ||
    echo "trn-3.6/artstate.h: original size 1415, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/autosub.c ==============
if test -f 'trn-3.6/autosub.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/autosub.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/autosub.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/autosub.c' &&
X/* $Id: autosub.c,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "search.h"
X#include "ngsrch.h"
X#include "util.h"
X#include "final.h"
X#include "INTERN.h"
X#include "autosub.h"
X
X/* Consider the newsgroup specified, and return:	*/
X/* : if we should autosubscribe to it			*/
X/* ! if we should autounsubscribe to it			*/
X/* \0 if we should ask the user.			*/
Xint
Xauto_subscribe(ng)
Xchar *ng;
X{
X    char *s;
X
X    if((s = getval("AUTOSUBSCRIBE", (char *)NULL))
X	&& matchlist(s, ng)) return ':';
X    if((s = getval("AUTOUNSUBSCRIBE", (char *)NULL))
X	&& matchlist(s, ng)) return '!';
X    return 0;
X}
X
Xbool
Xmatchlist(patlist, s)
Xchar *patlist;
Xchar *s;
X{
X    COMPEX ilcompex;
X    char *p;
X    char *err;
X    bool result;
X    bool tmpresult;
X
X    result = FALSE;
X    init_compex(&ilcompex);
X    while(patlist && *patlist) {
X
X	if(*patlist == '!') {
X		patlist++;
X		tmpresult = FALSE;
X	} else tmpresult = TRUE;
X
X	if(p = index(patlist, ',')) *p = '\0';
X        /* compile regular expression */
X	err = ng_comp(&ilcompex,patlist,TRUE,TRUE);
X	if(p) *p++ = ',';
X
X	if(err != Nullch) {
X	    printf("\n%s\n", err) FLUSH;
X	    finalize(1);
X	}
X	
X	if (execute(&ilcompex,s) != Nullch)
X	    result = tmpresult;
X	patlist = p;
X    }
X    free_compex(&ilcompex);
X    return result;
X}
SHAR_EOF
  $shar_touch -am 0711223593 'trn-3.6/autosub.c' &&
  chmod 0644 'trn-3.6/autosub.c' ||
  echo 'restore of trn-3.6/autosub.c failed'
  shar_count="`wc -c < 'trn-3.6/autosub.c'`"
  test 1888 -eq "$shar_count" ||
    echo "trn-3.6/autosub.c: original size 1888, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/autosub.h ==============
if test -f 'trn-3.6/autosub.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/autosub.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/autosub.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/autosub.h' &&
X/* $Id: autosub.h,v 3.0 1991/09/09 20:18:23 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
XEXT int auto_subscribe _((char*));
XEXT bool matchlist _((char*, char*));
SHAR_EOF
  $shar_touch -am 0711223593 'trn-3.6/autosub.h' &&
  chmod 0644 'trn-3.6/autosub.h' ||
  echo 'restore of trn-3.6/autosub.h failed'
  shar_count="`wc -c < 'trn-3.6/autosub.h'`"
  test 725 -eq "$shar_count" ||
    echo "trn-3.6/autosub.h: original size 725, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/backpage.c ==============
if test -f 'trn-3.6/backpage.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/backpage.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/backpage.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/backpage.c' &&
X/* $Id: backpage.c,v 3.0 1991/09/09 20:18:23 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "intrp.h"
X#include "final.h"
X#include "INTERN.h"
X#include "backpage.h"
X
XART_LINE maxindx = -1;
X
Xvoid
Xbackpage_init()
X{
X    char *varyname;
X    
X    varyname = filexp(VARYNAME);
X    close(creat(varyname,0600));
X    varyfd = open(varyname,2);
X    UNLINK(varyname);
X    if (varyfd < 0) {
X	printf(cantopen,varyname) FLUSH;
X	sig_catcher(0);
X    }
X    
X}
X
X/* virtual array read */
X
XART_POS
Xvrdary(indx)
XART_LINE indx;
X{
X    int subindx;
X    long offset;
X
X#ifdef DEBUG
X    if (indx > maxindx) {
X	printf("vrdary(%ld) > %ld\n",(long)indx, (long)maxindx) FLUSH;
X	return 0;
X    }
X#endif
X    if (indx < 0)
X	return 0;
X    subindx = indx % VARYSIZE;
X    offset = (indx - subindx) * sizeof(varybuf[0]);
X    if (offset != oldoffset) {
X	if (oldoffset >= 0) {
X#ifndef lint
X	    (void)lseek(varyfd,oldoffset,0);
X	    write(varyfd, (char *)varybuf,sizeof(varybuf));
X#endif /* lint */
X	}
X#ifndef lint
X	(void)lseek(varyfd,offset,0);
X	read(varyfd,(char *)varybuf,sizeof(varybuf));
X#endif /* lint */
X	oldoffset = offset;
X    }
X    return varybuf[subindx];
X}
X
X/* write to virtual array */
X
Xvoid
Xvwtary(indx,newvalue)
XART_LINE indx;
XART_POS newvalue;
X{
X    int subindx;
X    long offset;
X
X#ifdef DEBUG
X    if (indx < 0)
X	printf("vwtary(%ld)\n",(long)indx) FLUSH;
X    if (!indx)
X	maxindx = 0;
X    if (indx > maxindx) {
X	if (indx != maxindx + 1)
X	    printf("indx skipped %d-%d\n",maxindx+1,indx-1) FLUSH;
X	maxindx = indx;
X    }
X#endif
X    subindx = indx % VARYSIZE;
X    offset = (indx - subindx) * sizeof(varybuf[0]);
X    if (offset != oldoffset) {
X	if (oldoffset >= 0) {
X#ifndef lint
X	    (void)lseek(varyfd,oldoffset,0);
X	    write(varyfd,(char *)varybuf,sizeof(varybuf));
X#endif /* lint */
X	}
X#ifndef lint
X	(void)lseek(varyfd,offset,0);
X	read(varyfd,(char *)varybuf,sizeof(varybuf));
X#endif /* lint */
X	oldoffset = offset;
X    }
X    varybuf[subindx] = newvalue;
X}
X
SHAR_EOF
  $shar_touch -am 0711223593 'trn-3.6/backpage.c' &&
  chmod 0644 'trn-3.6/backpage.c' ||
  echo 'restore of trn-3.6/backpage.c failed'
  shar_count="`wc -c < 'trn-3.6/backpage.c'`"
  test 2542 -eq "$shar_count" ||
    echo "trn-3.6/backpage.c: original size 2542, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/backpage.h ==============
if test -f 'trn-3.6/backpage.h' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/backpage.h (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/backpage.h (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/backpage.h' &&
X/* $Id: backpage.h,v 3.0 1991/09/09 20:18:23 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X/* things for doing the 'back page' command */
X
XEXT int varyfd INIT(0);			/* virtual array file for storing  */
X					/* file offsets */
XEXT ART_POS varybuf[VARYSIZE];		/* current window onto virtual array */
X
XEXT long oldoffset INIT(-1);		/* offset to block currently in window */
X
Xvoid	backpage_init _((void));
XART_POS	vrdary _((ART_LINE));
Xvoid	vwtary _((ART_LINE,ART_POS));
SHAR_EOF
  $shar_touch -am 0711223593 'trn-3.6/backpage.h' &&
  chmod 0644 'trn-3.6/backpage.h' ||
  echo 'restore of trn-3.6/backpage.h failed'
  shar_count="`wc -c < 'trn-3.6/backpage.h'`"
  test 1030 -eq "$shar_count" ||
    echo "trn-3.6/backpage.h: original size 1030, current size $shar_count"
  rm -f _sharnew.tmp
fi
# ============= trn-3.6/bits.c ==============
if test -f 'trn-3.6/bits.c' && test X"$1" != X"-c"; then
  echo 'x - skipping trn-3.6/bits.c (file already exists)'
  rm -f _sharnew.tmp
else
  > _sharnew.tmp
  echo 'x - extracting trn-3.6/bits.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'trn-3.6/bits.c' &&
X/* $Id: bits.c,v 3.0 1992/02/01 03:09:32 davison Trn $
X */
X/* This software is Copyright 1991 by Stan Barber. 
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made. 
X *
X * The authors make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk. 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "cache.h"
X#include "INTERN.h"
X#include "bits.h"
X#include "EXTERN.h"
X#include "rcstuff.h"
X#include "head.h"
X#include "term.h"
X#include "util.h"
X#include "util2.h"
X#include "final.h"
X#include "trn.h"
X#include "ng.h"
X#include "artio.h"
X#include "intrp.h"
X#include "ngdata.h"
X#include "rcln.h"
X#include "ndir.h"
X#include "nntp.h"
X#include "rthread.h"
X#include "rt-select.h"
X#include "rt-util.h"
X
X#ifdef DBM_XREFS
X#    ifdef NULL
X#	undef NULL
X#    endif
X#    include <dbm.h>
X#endif
X
Xstatic long chase_count = 0;
X
Xvoid
Xbits_init()
X{
X    ;
X}
X
Xvoid
Xrc_to_bits()
X{
X    char *mybuf = buf;			/* place to decode rc line */
X    register char *s, *c, *h;
X    register long i;
X    register ART_NUM unread;
X    register ARTICLE *ap;
X
X    /* modify the article flags to reflect what has already been read */
X
X    for (s = rcline[ng] + rcnums[ng]; *s == ' '; s++) ;
X					/* find numbers in rc line */
X    i = strlen(s);
X#ifndef lint
X    if (i >= LBUFLEN-2)			/* bigger than buf? */
X	mybuf = safemalloc((MEM_SIZE)(i+2));
X#endif
X    strcpy(mybuf,s);			/* make scratch copy of line */
X    mybuf[i++] = ',';			/* put extra comma on the end */
X    mybuf[i] = '\0';
X    s = mybuf;				/* initialize the for loop below */
X    if (strnEQ(s,"1-",2)) {		/* can we save some time here? */
X	firstart = atol(s+2)+1;		/* process first range thusly */
X	if (firstart < absfirst)
X	    firstart = absfirst;
X	s=index(s,',') + 1;
X	for (i = absfirst, ap = article_ptr(i); i < firstart; i++, ap++)
X	    ap->flags |= AF_READ;
X    } else {
X	i = firstart = absfirst;
X	ap = article_ptr(i);
X    }
X    unread = lastart - firstart + 1;	/* assume this range unread */
X#ifdef DEBUG
X    if (debug & DEB_CTLAREA_BITMAP) {
X	printf("\n%s\n",mybuf) FLUSH;
X	for (i = absfirst, ap = article_ptr(i); i < firstart; i++, ap++)
X	    if (!(ap->flags & AF_READ))
X		printf("%ld ",(long)i) FLUSH;
X    }
X#endif
X    for ( ; (c = index(s,',')) != Nullch; s = ++c) {	/* for each range */
X	ART_NUM min, max;
X
X	*c = '\0';			/* do not let index see past comma */
X	h = index(s,'-');
X	min = atol(s);
X	if (h)				/* is there a dash? */
X	    max = atol(h+1);
X	else
X	    max = min;
X	if (min < firstart)		/* make sure range is in range */
X	    min = firstart;
X	if (min > lastart)
X	    min = lastart+1;
X	for (; i < min; i++, ap++)
X	    ap->flags &= ~AF_READ;
X	if (max > lastart)
X	    max = lastart;
X	if (min <= max) {		/* non-null range? */
X	    unread -= max - min + 1;/* adjust unread count */
X	    /* mark all arts in range as read */
X	    for (; i <= max; i++, ap++)
X		ap->flags |= AF_READ;
X	}
X#ifdef DEBUG
X	if (debug & DEB_CTLAREA_BITMAP) {
X	    printf("\n%s\n",s) FLUSH;
X	    for (i=absfirst; i <= lastart; i++)
X		if (!was_read(i))
X		    printf("%ld ",(long)i) FLUSH;
X	}
X#endif
X    }
X    for (; i <= lastart; i++, ap++)
X	ap->flags &= ~AF_READ;
X#ifdef DEBUG
X    if (debug & DEB_CTLAREA_BITMAP) {
X	fputs("\n(hit CR)",stdout) FLUSH;
X	fgets(cmd_buf, sizeof cmd_buf, stdin);
X    }
X#endif
X    if (mybuf != buf)
X	free(mybuf);
X    toread[ng] = unread;
X}
X
X/* reconstruct the .newsrc line in a human readable form */
X
Xvoid
Xbits_to_rc()
X{
X    register char *s, *mybuf = buf;
X    register ART_NUM i;
X    ART_NUM count=0;
X    int safelen = LBUFLEN - 32;
X
X    strcpy(buf,rcline[ng]);		/* start with the newsgroup name */
X    s = buf + rcnums[ng] - 1;		/* use s for buffer pointer */
X    *s++ = RCCHAR(rcchar[ng]);		/* put the requisite : or !*/
X    for (i=absfirst; i<=lastart; i++)
X	if (!was_read(i))
X	    break;
X    sprintf(s," 1-%ld,",(long)i-1);
X    s += strlen(s);
X    for (; i<=lastart; i++) {	/* for each article in newsgroup */
X	if (s-mybuf > safelen) {	/* running out of room? */
X	    safelen *= 2;
X	    if (mybuf == buf) {		/* currently static? */
X		*s = '\0';
X		mybuf = safemalloc((MEM_SIZE)safelen + 32);
X		strcpy(mybuf,buf);	/* so we must copy it */
X		s = mybuf + (s-buf);
X					/* fix the pointer, too */
X	    }
X	    else {			/* just grow in place, if possible */
X		char *newbuf;
X
X		newbuf = saferealloc(mybuf,(MEM_SIZE)safelen + 32);
X		s = newbuf + (s-mybuf);
X		mybuf = newbuf;
X	    }
X	}
X	if (!was_read(i))		/* still unread? */
X	    count++;			/* then count it */
X	else {				/* article was read */
X	    ART_NUM oldi;
X
X	    sprintf(s,"%ld",(long)i);	/* put out the min of the range */
X	    s += strlen(s);		/* keeping house */
X	    oldi = i;			/* remember this spot */
X	    do i++; while (i <= lastart && was_read(i));
X					/* find 1st unread article or end */
X	    i--;			/* backup to last read article */
X	    if (i > oldi) {		/* range of more than 1? */
X		sprintf(s,"-%ld,",(long)i);
X					/* then it out as a range */
X		s += strlen(s);		/* and housekeep */
X	    }
X	    else
X		*s++ = ',';		/* otherwise, just a comma will do */
X	}
X    }
X    if (*(s-1) == ',')			/* is there a final ','? */
X	s--;				/* take it back */
X    *s++ = '\0';			/* and terminate string */
X#ifdef DEBUG
X    if (debug & DEB_NEWSRC_LINE && !panic) {
X	printf("%s: %s\n",rcline[ng],rcline[ng]+rcnums[ng]) FLUSH;
X	printf("%s\n",mybuf) FLUSH;
X    }
X#endif
X    free(rcline[ng]);			/* return old rc line */
X    if (mybuf == buf) {
X	rcline[ng] = safemalloc((MEM_SIZE)(s-buf)+1);
X					/* grab a new rc line */
X	strcpy(rcline[ng], buf);	/* and load it */
X    }
X    else {
X	mybuf = saferealloc(mybuf,(MEM_SIZE)(s-mybuf)+1);
X					/* be nice to the heap */
X	rcline[ng] = mybuf;
X    }
X    *(rcline[ng] + rcnums[ng] - 1) = '\0';
X    if (rcchar[ng] == NEGCHAR) {	/* did they unsubscribe? */
X	printf(unsubto,ngname) FLUSH;
X	toread[ng] = TR_UNSUB;		/* make line invisible */
X    }
X    else
X	/*NOSTRICT*/
X	toread[ng] = (ART_UNREAD)count;		/* remember how many unread there are */
X}
X
X#ifdef USE_NNTP
X
X/* Parse the LISTGROUP output and set anything not mentioned as missing. */
X
Xvoid
Xsetmissingbits()				/* NNTP version */
X{
X    register ART_NUM num, priornum;
X    register ARTICLE *ap;
X
X    if (!nntp_listgroup())
X	return;
X    for (priornum = absfirst-1, ap = article_ptr(absfirst);; ap++) {
X	nntp_gets(ser_line, sizeof ser_line);
X	if (NNTP_LIST_END(ser_line))
X	    break;
X	num = atol(ser_line);
X	while (++priornum < num)
X	    uncache_article(ap++,FALSE);
X    }
X}
X
X#else /* !USE_NNTP */
X
X/* Scan the directory to find which articles are present. */
X
Xvoid
Xsetfoundbits()
X{
X    register ART_NUM first = lastart+1;
X    register DIR *dirp;
X    register Direntry_t *dp;
X    long an;
X    char ch;
X
X    if (!(dirp = opendir(".")))
X	return;
X    
X    found_min = absfirst;
X    an = (lastart-found_min)/BITSPERBYTE+20;
X    found_bits = safemalloc((MEM_SIZE)an);
X    bzero(found_bits, an);
X
X    while ((dp = readdir(dirp)) != Null(Direntry_t*)) {
X	if (sscanf(dp->d_name, "%ld%c", &an, &ch) == 1) {
X	    if (an <= lastart && an >= found_min) {
X		if (an < first)
X		    first = an;
X		foundart(an);
X	    }
X	}
X    }
X    closedir(dirp);
X    abs1st[ng] = first;
X    if (first > absfirst)
X	checkexpired(ng,first);
X    absfirst = first;
X}
X
Xvoid
Xsetmissingbits()				/* non-NNTP version */
X{
X    register ARTICLE *ap;
X    register ART_NUM an;
X
X    if (!found_bits)
X	return;
X
X    for (an = absfirst, ap = article_ptr(an); an <= lastart; an++, ap++) {
X	if (artismissing(an))
X	    onemissing(ap);
X    }
X    free(found_bits);
X    found_bits = NULL;
X}
X#endif /* !USE_NNTP */
X
X/* mark an article unread, keeping track of toread[] */
X
Xvoid
Xonemore(ap)
XARTICLE *ap;
X{
X    if (ap->flags & AF_READ) {
X	register ART_NUM artnum = article_num(ap);
X	check_first(artnum);
X	ap->flags &= ~AF_READ;
X	++toread[ng];
X	ap->flags &= ~AF_DEL;
X	if (ap->subj) {
X	    if (selected_only) {
X		if (ap->subj->flags & sel_mask) {
X		    ap->flags |= sel_mask;
X		    selected_count++;
X		}
X	    } else
X		ap->subj->flags |= SF_VISIT;
X	}
X    }
X}
X
X/* mark an article read, keeping track of toread[] */
X
Xvoid
Xoneless(ap)
XARTICLE *ap;
X{
X    if (!(ap->flags & AF_READ)) {
X	ap->flags |= AF_READ;
X	/* Keep selected_count accurate */
X	if (ap->flags & sel_mask) {
X	    selected_count--;
X	    ap->flags &= ~sel_mask;
X	}
X	if (toread[ng] > TR_NONE)
X	    --toread[ng];
X    }
X}
X
Xvoid
Xonemissing(ap)
XARTICLE *ap;
X{
SHAR_EOF
  : || echo 'restore of trn-3.6/bits.c failed'
fi
echo 'End of archive part 1'
echo 'File trn-3.6/bits.c is continued in part 2'
echo 2 > _sharseq.tmp
exit 0


