/* $Id: art.c,v 3.0 1992/02/01 03:09:32 davison Trn $
/* This software is Copyright 1991 by Stan Barber.
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
* use this software as long as: there is no monetary profit gained
* specifically from the use or reproduction of this software, it is not
* sold, rented, traded or otherwise marketed, and this copyright notice is
* included prominently in any copy made.
* The author make no claims as to the fitness or correctness of this software
* for any use whatsoever, and it is provided as is. Any use of this software
* is at the user's own risk.
/* 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 */
#define VERY_LONG_STRING 200
if (!getenv("NOMETAMAIL")) {
interp(cmd_buf
,(sizeof cmd_buf
),getval("MIMESHOW",MIMESHOW
));
code
= doshell(SH
,cmd_buf
);
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? */
bool tried_display_mime
= FALSE
;
if (fstat(fileno(artfp
),&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 */
if ((firstpage
= (topline
< 0)) != 0) {
fseek(artfp
,htype
[PAST_HEADER
].ht_minpos
,0);
for (;;) { /* for each page */
if (ThreadedGroup
&& max_tree_lines
)
init_tree(); /* init tree display */
parseheader(art
); /* make sure header is ours */
artpos
= vrdary(artline
);
artpos
= -artpos
; /* labs(), anyone? */
if (artpos
< htype
[PAST_HEADER
].ht_minpos
) {
fseek(artfp
,htype
[PAST_HEADER
].ht_minpos
,0);
interp(art_buf
, (sizeof art_buf
), firstline
);
linenum
+= tree_puts(art_buf
,linenum
+topline
,0);
artopen(art
); /* rewind article in case interp */
/* forced a header parse */
selected
= (curr_artp
->flags
& AF_SEL
);
sprintf(art_buf
,"%s%s #%ld",ngname
,moderated
,(long)art
);
i
= selected_count
- (unseen
&& selected
);
sprintf(art_buf
+strlen(art_buf
)," (%ld + %ld more)",
(long)i
,(long)toread
[ng
] - selected_count
- (!selected
&& unseen
));
else if ((i
= (ART_NUM
)(toread
[ng
] - unseen
)) != 0
|| (!ThreadedGroup
&& dmcount
))
sprintf(art_buf
+strlen(art_buf
)," (%ld more)",(long)i
);
if (!ThreadedGroup
&& dmcount
)
sprintf(art_buf
+strlen(art_buf
)-1," + %ld Marked to return)",
linenum
+= tree_puts(art_buf
,linenum
+topline
,0);
forcelast
= FALSE
; /* we will have our day in court */
artline
= 0; /* start counting lines */
vwtary(artline
,artpos
); /* remember pos in file */
for (; /* linenum already set */
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 if (in_header
&& headbuf
[artpos
] != '\0') {
bufptr
= index(headbuf
+artpos
,'\n') + 1;
bcopy(headbuf
+artpos
,art_buf
,bufptr
-headbuf
-artpos
);
art_buf
[bufptr
-headbuf
-artpos
] = '\0';
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
);
linenum
+= finish_tree(linenum
+topline
);
} 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
) {
if ((s
= index(art_buf
,'\n')) != Nullch
)
hide_this_line
= (index(art_buf
,',') == Nullch
)
&& strEQ(art_buf
+12, ngname
);
else if (in_header
== EXPIR_LINE
) {
if (!(htype
[EXPIR_LINE
].ht_flags
& HT_HIDE
))
hide_this_line
= (strlen(art_buf
) < 10);
else if (in_header
== FROM_LINE
) {
if (do_hiding
&& (s
= extract_name(art_buf
+6)) != Nullch
)
else if (in_header
== DATE_LINE
) {
if (do_hiding
&& curr_artp
->date
!= -1)
strftime(art_buf
+6, sizeof(art_buf
)-6,
getval("LOCALTIMEFMT", LOCALTIMEFMT
),
localtime(&curr_artp
->date
));
else if (in_header
== CONTENT_LINE
) {
mime_article
= nontext(art_buf
+14);
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", TRUE
) != Nullch
);
/* tree_puts(, ,1) underlines subject */
linenum
+= tree_puts(art_buf
,linenum
+topline
,1)-1;
else if (hide_this_line
&& do_hiding
) {
linenum
--; /* compensate for linenum++ */
linenum
+= tree_puts(art_buf
,linenum
+topline
,0)-1;
else { /* just a normal line */
if (mime_article
&& !tried_display_mime
) {
tried_display_mime
= TRUE
;
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 (*(unsigned char *)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? */
int incpos
= 8 - outpos
% 8;
while (incpos
--) putchar(' ');
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
|| XN
) {/* no automatic margins on tty? */
#ifdef INNERSEARCH /* then move it down ourselves */
if (*bufptr
== '\n') /* skip the newline */
/* 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 */
artpos
= index(headbuf
+artpos
, '\n') - headbuf
+ 1;
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 */
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
)
erase_eol(); /* and erase the prompt */
carriage_return(); /* Resets kernel's tab column counter to 0 */
fake_command
: /* used by innersearch */
output_chase_phrase
= TRUE
;
/* 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 */
carriage_return(); /* Resets kernel's tab column counter to 0 */
/* 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
;
carriage_return(); /* Resets kernel's tab column counter to 0 */
firstpage
= (topline
< 0);
case Ctl('b'): { /* back up a page */
if (can_home_clear
) /* if we can home do it */
carriage_return(); /* Resets kernel's tab column counter to 0 */
do_fseek
= TRUE
; /* reposition article file */
target
= topline
- (LINES
- 2);
} while(artline
>= 0 && artline
> target
&& vrdary(artline
-1) >= 0);
/* remember top line of screen */
/* (line # within article file) */
firstpage
= (topline
< 0);
if ((cmd
= help_page()) > 0)
case 't': /* output thread data */
case '\0': /* treat del,break as 'n' */
case 'n': case 'N': case Ctl('n'):
mark_as_read(); /* mark article as read */
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
case 'f': case 'F': case Ctl('f'):
case 'p': case 'P': case Ctl('p'):
case 'r': case 'R': case Ctl('r'):
if (index("nNpP\016\020",*buf
) == Nullch
&&
index("wWsSe:!&|/?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 */
/* 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 */
clear(); /* else clear screen */
carriage_return(); /* Resets kernel's tab column counter to 0 */
&& (!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
) {
if (content_type
[0] == '\n')
while (content_type
&& isspace(*content_type
))
t
= index(content_type
, ';');
t
= index(content_type
, '\n');
while (t
&& *t
&& t
> content_type
&& isspace(*t
))
if (notplain(content_type
))
while (*s
&& isspace(*s
))
while (t
> s
&& isspace(*--t
)) ;
if (((t
-s
) == 3) && !strncmp(s
, "text", 4))
if (strncmp(s
, "text/plain", 10))
while (*t
&& isspace(*t
)) t
++;
if (!strncmp(t
, "charset", 7)) {
while (*s
&& isspace(*s
)) s
++;
if (!strncmp(s
, "us-ascii", 8))
return 0; /* no charset, was text/plain */