/* $Header: art.c,v 4.3.1.4 85/05/23 12:13:31 lwall Exp $
* Revision 4.3.1.4 85/05/23 12:13:31 lwall
* shouldn't display article that's really a subdirectory.
* Revision 4.3.1.3 85/05/13 09:29:55 lwall
* Added CUSTOMLINES option.
* Revision 4.3.1.2 85/05/10 13:46:07 lwall
* Fixed header reparse bug on backpage.
* Revision 4.3.1.1 85/05/10 11:30:56 lwall
* Revision 4.3 85/05/01 11:34:51 lwall
* Baseline for release with 4.3bsd.
/* page_switch() return values */
bool special
= FALSE
; /* is next page special length? */
int slines
= 0; /* how long to make page when special */
ART_LINE highlight
= -1; /* next line to be highlighted */
char *restart
= Nullch
; /* if nonzero, the place where last */
/* line left off on line split */
char *blinebeg
; /* where in buffer current line began */
ART_POS alinebeg
; /* where in file current line began */
ART_POS innersearch
= 0; /* artpos of end of line we found */
ART_LINE isrchline
= 0; /* last line to display */
bool hide_everything
= FALSE
;
/* if set, do not write page now, */
/* but refresh when done with page */
COMPEX gcompex
; /* in article search pattern */
bool firstpage
; /* is this the 1st page of article? */
char art_buf
[LBUFLEN
]; /* place for article lines */
ART_POS artsize
; /* size in bytes of article */
bool hide_this_line
= FALSE
; /* hidden header line? */
ART_LINE linenum
; /* line # on page, 1 origin */
bool under_lining
= FALSE
;
/* are we underlining a word? */
register char *bufptr
= art_buf
;
/* pointer to input buffer */
register int outpos
; /* column position of output */
static char prompt_buf
[64]; /* place to hold prompt */
bool notesfiles
= FALSE
; /* might there be notesfiles junk? */
if (fstat(artfp
->_file
,&filestat
))
/* get article file stats */
if (filestat
.st_mode
& S_IFMT
!= S_IFREG
)
artsize
= filestat
.st_size
;
/* from that get article size */
"%%sEnd of article %ld (of %ld)--what next? [%%s]",
(long)art
,(long)lastart
); /* format prompt string */
int_count
= 0; /* interrupt count is 0 */
firstpage
= (topline
< 0);
for (;;) { /* for each page */
parse_maybe(art
); /* make sure header is ours */
artpos
= vrdary(artline
);
artpos
= -artpos
; /* labs(), anyone? */
if (artpos
< htype
[PAST_HEADER
].ht_minpos
)
interp(art_buf
, (sizeof art_buf
), firstline
);
fputs(art_buf
,stdout
) FLUSH
;
artopen(art
); /* rewind article in case interp */
/* forced a header parse */
printf("Article %ld",(long)art
);
i
= (((ART_NUM
)toread
[ng
]) - 1 + was_read(art
));
printf(" (%ld more",(long)i
);
printf(" + %ld Marked to return)",(long)dmcount
);
printf(" (%ld more)",(long)i
);
if (htype
[NGS_LINE
].ht_flags
& HT_HIDE
)
printf(" in %s", ngname
);
fputs(":\n",stdout
) FLUSH
;
forcelast
= FALSE
; /* we will have our day in court */
artline
= 0; /* start counting lines */
vwtary(artline
,artpos
); /* remember pos in file */
for (linenum
=(firstpage
?2:1);
innersearch
? innermore() :
linenum
<(firstpage
?initlines
:(special
?slines
:LINES
)) );
linenum
++) { /* for each line on page */
if (int_count
) { /* exit via interrupt? */
putchar('\n') FLUSH
; /* get to left margin */
int_count
= 0; /* reset interrupt count */
return DA_NORM
; /* skip out of loops */
if (restart
) { /* did not finish last line? */
bufptr
= restart
; /* then start again here */
restart
= Nullch
; /* and reset the flag */
else { /* not a restart */
if (fgets(art_buf
,LBUFLEN
,artfp
)==Nullch
) {
return DA_NORM
; /* skip out of loops */
bufptr
= art_buf
; /* so start at beginning */
art_buf
[LBUFLEN
-1] = '\0';
/* make sure string ends */
blinebeg
= bufptr
; /* remember where we began */
alinebeg
= artpos
; /* both in buffer and file */
if (in_header
&& bufptr
== art_buf
)
parseline(art_buf
,do_hiding
,hide_this_line
);
else if (notesfiles
&& do_hiding
&&
bufptr
== art_buf
&& *art_buf
== '#' &&
isupper(art_buf
[1]) && art_buf
[2] == ':' ) {
fgets(art_buf
,sizeof(art_buf
),artfp
);
if (index(art_buf
,'!') != Nullch
)
fgets(art_buf
,sizeof(art_buf
),artfp
);
htype
[PAST_HEADER
].ht_minpos
= ftell(artfp
);
/* exclude notesfiles droppings */
hide_this_line
= TRUE
; /* and do not print either */
if (hideline
&& bufptr
== art_buf
&&
execute(&hide_compex
,art_buf
) )
if (in_header
&& htype
[in_header
].ht_flags
& HT_MAGIC
) {
if (in_header
== NGS_LINE
) {
hide_this_line
= (index(art_buf
,',') == Nullch
);
else if (in_header
== EXPIR_LINE
) {
if (!(htype
[EXPIR_LINE
].ht_flags
& HT_HIDE
))
hide_this_line
= (strlen(art_buf
) < 10);
if (in_header
== SUBJ_LINE
&&
htype
[SUBJ_LINE
].ht_flags
& HT_MAGIC
) {
/* is this the subject? */
length
= strlen(art_buf
)-1;
art_buf
[length
] = '\0'; /* wipe out newline */
(instr(&art_buf
[length
-10]," - (nf") != Nullch
);
if (length
+UG
> COLS
) { /* rarely true */
vwtary(artline
,vrdary(artline
-1)+COLS
);
*s
++ = '\0'; /* make into 2 strings */
fputs(art_buf
,stdout
) FLUSH
;
underprint(s
); /* print subject underlined */
putchar('\n') FLUSH
; /* and finish the line */
else if (hide_this_line
&& do_hiding
) {
linenum
--; /* compensate for linenum++ */
else { /* just a normal line */
if (highlight
==artline
) { /* this line to be highlit? */
if (marking
== STANDOUT
) {
outputok
= !hide_everything
;
/* get it into register, hopefully */
if (pagestop
&& bufptr
== art_buf
&&
execute(&page_compex
,art_buf
) )
for (outpos
= 0; outpos
< COLS
; ) {
/* while line has room */
if (*bufptr
>= ' ') { /* normal char? */
if (!under_lining
&& highlight
!=artline
if ((*bufptr
& 31) <= 13)
if (*UC
&& ((highlight
==artline
&& marking
== 1)
else if (*bufptr
== '\n' || !*bufptr
) {
if (debug
& DEB_INNERSRCH
&& outpos
< COLS
- 6) {
outpos
= 1000; /* signal normal \n */
else if (*bufptr
== '\t') { /* tab? */
outpos
+= 8 - outpos
% 8;
else if (*bufptr
== '\f') { /* form feed? */
if (bufptr
== blinebeg
&& highlight
!= artline
)
/* how is that for a magic number? */
else { /* other control char */
if (highlight
== artline
&& *UC
&& marking
== 1) {
} /* end of column loop */
if (outpos
< 1000) {/* did line overflow? */
/* restart here next time */
if (AM
) { /* automatic margins on tty? */
if (!XN
&& *bufptr
== '\n')
/* need we simulate XN? */
else { /* cursor just hangs there */
/* so move it down ourselves */
/* simulate XN if need be */
maybe_eol(); */ /* PWP *//* comment this out for now
/* handle normal end of output line formalities */
if (highlight
== artline
) {
/* were we highlighting line? */
highlight
= -1; /* no more we are */
artline
++; /* count the line just printed */
if (artline
- LINES
+ 1 > topline
)
/* did we just scroll top line off? */
topline
= artline
- LINES
+ 1;
/* then recompute top line # */
/* determine actual position in file */
if (restart
) /* stranded somewhere in the buffer? */
artpos
+= restart
- blinebeg
;
/* just calculate position */
else /* no, ftell will do */
vwtary(artline
,artpos
); /* remember pos in file */
if (linenum
>= 32700)/* did last line have formfeed? */
vwtary(artline
-1,-vrdary(artline
-1));
/* remember by negating pos in file */
special
= FALSE
; /* end of page, so reset page length */
firstpage
= FALSE
; /* and say it is not 1st time thru */
if (artpos
== artsize
) /* did we just now reach EOF? */
return DA_NORM
; /* avoid --MORE--(100%) */
/* not done with this article, so pretend we are a pager */
unflush_output(); /* disable any ^O in effect */
standout(); /* enter standout mode */
printf("--MORE--(%ld%%)",(long)(artpos
*100/artsize
));
un_standout(); /* leave standout mode */
/* reinp_pager: /* unused, commented for lint */
if (debug
& DEB_CHECKPOINTING
) {
printf("(%d %d %d)",checkcount
,linenum
,artline
);
if (checkcount
>= docheckwhen
&&
(artline
> 40 || checkcount
>= docheckwhen
+10) ) {
/* while he is reading a whole page */
/* in an article he is interested in */
checkpoint_rc(); /* update .newsrc */
collect_subjects(); /* loads subject cache until */
if (LINES
< 100 && !int_count
)
*buf
= '\f';/* on CONT fake up refresh */
*buf
= 'q'; /* on INTR or paper just quit */
erase_eol(); /* and erase the prompt */
if (erase_screen
&& can_home_clear
) /* PWP was here */
erase_eol(); /* and erase the prompt */
fake_command
: /* used by innersearch */
/* parse and process pager command */
case PS_ASK
: /* reprompt "--MORE--..." */
case PS_RAISE
: /* reparse on article level */
case PS_TOEND
: /* fast pager loop exit */
case PS_NORM
: /* display more article */
/* process pager commands */
case Ctl('d'): /* half page */
if (marking
&& *blinebeg
!= '\f'
&& (!pagestop
|| blinebeg
!= art_buf
||
!execute(&page_compex
,blinebeg
))
case '!': /* shell escape */
sprintf(cmd_buf
,"^[^%c]",*blinebeg
);
compile(&gcompex
,cmd_buf
,TRUE
,TRUE
);
compile(&gcompex
,"^Subject:",TRUE
,TRUE
);
case 'g': /* in-article search */
if (!finish_command(FALSE
))/* get rest of command */
if ((s
= compile(&gcompex
,s
,TRUE
,TRUE
)) != Nullch
) {
/* compile regular expression */
printf("\n%s\n",s
) FLUSH
;
erase_eol(); /* erase the prompt */
/* ART_LINE lines_to_skip = 0; */
if (gline
< 0 || gline
> LINES
-2)
if (debug
& DEB_INNERSRCH
)
printf("Start here? %d >=? %d\n",topline
+ gline
+ 1,artline
)
if (*buf
== Ctl('i') || topline
+gline
+1 >= artline
)
/* in case we had a line wrap */
start_where
= vrdary(topline
+gline
+1);
start_where
= -start_where
;
if (start_where
< htype
[PAST_HEADER
].ht_minpos
)
start_where
= htype
[PAST_HEADER
].ht_minpos
;
fseek(artfp
,(long)start_where
,0);
innersearch
= 0; /* assume not found */
while (fgets(buf
, sizeof buf
, artfp
) != Nullch
) {
/* lines_to_skip++; NOT USED NOW */
if (debug
& DEB_INNERSRCH
)
printf("Test %s",buf
) FLUSH
;
if (execute(&gcompex
,buf
) != Nullch
) {
innersearch
= ftell(artfp
);
fputs("(Not found)",stdout
) FLUSH
;
if (debug
& DEB_INNERSRCH
)
printf("On page? %ld <=? %ld\n",(long)innersearch
,(long)artpos
)
if (innersearch
<= artpos
) { /* already on page? */
if (innersearch
< artpos
) {
while (vrdary(artline
) < innersearch
)
if (debug
& DEB_INNERSRCH
)
printf("@ %d\n",highlight
) FLUSH
;
topline
= highlight
- gline
;
*buf
= '\f'; /* fake up a refresh */
else { /* who knows how many lines it is? */
case 'g': case 'G': case Ctl('g'):
case '\n': /* one line */
case '\f': /* refresh screen */
if (debug
& DEB_INNERSRCH
) {
printf("Topline = %d",topline
) FLUSH
;
firstpage
= (topline
< 0);
case '\b': /* I like backspace for this -- PWP */
/* Leaving it undocumented in case */
/* I want to steal the key--LAW */
case Ctl('b'): { /* back up a page */
if (can_home_clear
) /* if we can home do it -- PWP */
do_fseek
= TRUE
; /* reposition article file */
target
= topline
- (LINES
- 2);
} while (artline
>= 0 && artline
> target
&&
/* remember top line of screen */
/* (line # within article file) */
firstpage
= (topline
< 0);
if ((cmd
= help_page()) > 0)
case '\0': /* treat del,break as 'n' */
case 'n': case 'N': case Ctl('n'):
mark_as_read(art
); /* mark article as read */
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
case 'p': case 'P': case Ctl('p'):
case 'r': case 'R': case Ctl('r'):
if (index("nNpP",*buf
) == Nullch
&&
index("wWsS!&|/?123456789.",*buf
) != Nullch
) {
standout(); /* enter standout mode */
printf(prompt
,mailcall
,dfltcmd
);
/* print prompt, whatever it is */
un_standout(); /* leave standout mode */
return PS_RAISE
; /* and pretend we were at end */
case Ctl('v'): /* I like emacs -- PWP */
/* Leaving it undocumented in case */
/* I want to steal the key--LAW */
case ' ': /* continue current article */
if (erase_screen
) { /* -e? */
clear(); /* clear screen */
if (can_home_clear
) /* if we can home do it -- PWP */
clear(); /* else clear screen */
&& (!pagestop
|| blinebeg
!= art_buf
||
!execute(&page_compex
,blinebeg
))
artline
--; /* restart this line */
if (marking
) /* and mark repeated line */
/* and remember top line of screen */
/* (line # within article file) */
else if (marking
&& *blinebeg
!= '\f'
&& (!pagestop
|| blinebeg
!= art_buf
||
!execute(&page_compex
,blinebeg
))
/* are we marking repeats? */
up_line(); /* go up one line */
highlight
= --artline
;/* and get ready to highlight */
restart
= blinebeg
; /* the old line */
case 'q': /* quit this article? */
fputs(hforhelp
,stdout
) FLUSH
;
if (artpos
< innersearch
) { /* not even on page yet? */
if (debug
& DEB_INNERSRCH
)
printf("Not on page %ld < %ld\n",(long)artpos
,(long)innersearch
)
if (artpos
== innersearch
) { /* just got onto page? */
isrchline
= artline
; /* remember first line after */
if (debug
& DEB_INNERSRCH
)
printf("There it is %ld = %ld, %d @ %d\n",(long)artpos
,
(long)innersearch
,hide_everything
,highlight
) FLUSH
;
if (hide_everything
) { /* forced refresh? */
topline
= highlight
- gline
;
return FALSE
; /* let refresh do it all */
if (debug
& DEB_INNERSRCH
)
printf("Not far enough? %d <? %d + %d\n",artline
,isrchline
,gline
)
if (artline
< isrchline
+ gline
) {