amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (02/27/91)
Submitted-by: eyal@echo.canberra.edu.au (Eyal Lebedinsky) Posting-number: Volume 91, Issue 024 Archive-name: news/vn-res1.1/part04 #!/bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 4 (of 6)." # Contents: reader.c session.c # Wrapped by tadguy@ab20 on Tue Feb 26 19:28:45 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'reader.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'reader.c'\" else echo shar: Extracting \"'reader.c'\" \(18716 characters\) sed "s/^X//" >'reader.c' <<'END_OF_FILE' X/* X** vn news reader. X** X** reader.c - article reading interface - "more" like. X** X** see copyright disclaimer / history in vn.c source file X*/ X X#include <stdio.h> X#include <sys/types.h> X#include <ctype.h> X#include <time.h> X#include "tty.h" X#include "config.h" X#include "tune.h" X#include "head.h" X#include "reader.h" X#include "brk.h" X#include "node.h" X#include "page.h" X#include "vn.h" X X#ifdef amiga X#define system(a) Execute(a, 0, 0) Xextern char pr_buf[]; Xextern ttputc (); X#endif X X#define PERTAB 8 /* tab expansion factor */ X#define BACKTRACK 24 X Xextern char *Printer,*Editor,*Mailer,*Poster,*Orgdir,*Savefile,*Savedir,*Ccfile; Xextern int L_allow; Xextern int C_allow; Xextern int Rot; Xextern int Headflag; Xextern int Digest; Xextern int More; Xextern char *No_msg; Xextern char *Roton_msg; Xextern char *Rotoff_msg; Xextern char *Hdon_msg; Xextern char *Hdoff_msg; Xextern char *Def_smode; X Xextern PAGE Page; X Xextern int (*Massage)(); Xextern int (*Postfunc)(); Xextern int (*Mailfunc)(); Xextern int (*Savemode)(); Xextern int (*Hookfunc)(); X Xextern char Cxrtoi[], Cxitor[]; X Xstatic FILE *Fpread; Xstatic char *Fname; Xstatic char *Lookahead; Xstatic int Rlines; Xstatic int Hlines; Xstatic long Rew_pos; X Xstatic void save2_article (), followup (), printr (), searcher (), mail (); Xstatic saver (), edcopy (), rot_line (), do_out (), rerrmsg (); Xstatic char getpgch (), *rprompt (); X X X/* X readfile presents article: X fn = name of article. X sn - name of next article, NULL if last. X pages - pages to advance on return, if applicable X returns 0 for "continue", <0 for "quit" X X calls sig_set(BRK_READ / BRK_RFIN) around reading article. X*/ Xreadfile (fn,sn,pages) Xchar *fn; Xchar *sn; Xint *pages; X{ X ARTHEADER hdr; X FILE *fopen(); X int lines,percent; X int i; X int top, bottom; X int step; X char c, buf[RECLEN]; X char lasave[RECLEN]; X char pstr[24], dgname[48]; X char getpgch(), *index(), *dige_extract(), *tgetstr(); X char *any; X FILE *vns_aopen(); X long ftell(); X X Fname = fn; X *pages = 0; X step = FALSE; /* Boolean; to indicate user input a <RET> (PG_STEP) */ X X term_set(ERASE); X sig_set(BRK_READ,&Fpread); X X any = "any key to continue .... "; X X if (Digest) X { X lines = atoi(Fname); X if ((Fname = dige_extract(dgname,lines,&hdr,&Rew_pos)) == NULL) X { X rerrmsg("couldn't extract article %d from digest",lines); X#ifdef amiga X sprintf(pr_buf,any); X tputs(pr_buf,1,ttputc); X#else X printf(any); X#endif X getnoctl(); X sig_set(BRK_RFIN); X return (0); X } X if ((Fpread = fopen(Fname,"r")) == NULL) X { X rerrmsg("couldn't open %s",Fname); X#ifdef amiga X sprintf(pr_buf,any); X tputs(pr_buf,1,ttputc); X#else X printf(any); X#endif X getnoctl(); X sig_set(BRK_RFIN); X return (0); X } X fseek(Fpread,Rew_pos,0); X } X else X { X if ((Fpread = vns_aopen(atoi(Fname),&hdr)) == NULL) X { X rerrmsg("couldn't open article %s",Fname); X#ifdef amiga X sprintf(pr_buf,any); X tputs(pr_buf,1,ttputc); X#else X printf(any); X#endif X getnoctl(); X sig_set(BRK_RFIN); X return (0); X } X Rew_pos = ftell(Fpread); X } X X Hlines = hdr.hlines; X#ifdef amiga X sprintf (pr_buf,ANFORM,Fname,Cxrtoi[PG_HELP]); X tputs(pr_buf,1,ttputc); X#else X printf (ANFORM,Fname,Cxrtoi[PG_HELP]); X#endif X X lines = 0; X X if (Headflag) X { X rewind(Fpread); X Rlines = 0; X } X else X { X /* use do_out to guard against control sequences */ X Rlines = Hlines; X for (i=0; i < hdr.show_num; ++i) X lines += do_out((hdr.show)[i],L_allow-lines); X lines += do_out("",L_allow-lines); X } X X /* will return out of outer while loop */ X Lookahead = NULL; X while (1) X { X /* X ** lines counts folded lines from do_out. X ** globals Hlines and Rlines refer to records. X ** If Lookahead is null after this loop, we've X ** hit EOF. X */ X if (Lookahead != NULL && More && !step) X { X char *looktmp; X X /* X ** Save Lookahead because `do_out' nukes it. X ** Perhaps we could just use `printf' here X ** but for now we'll play it safe. - GKE 12/26/87 X */ X looktmp = Lookahead; X term_set(ERASE); X /* X ** The following presents the last line of the X ** previous page in reversed video, as the first line X ** of the current page, `rn'-stylee. Since `rn' X ** uses an option to enable/disable this, remove the X ** two `term_set's if not to your liking. X */ X term_set(ONREVERSE); X do_out(lasave,1); X term_set(OFFREVERSE); X Lookahead = looktmp; X } X lines += do_out(Lookahead,L_allow-lines); X while (1) X { X if (Lookahead == NULL) X { X if (fgets(buf,RECLEN-1,Fpread) == NULL) X break; X Lookahead = buf; X if (Rot != 0 && Rlines >= Hlines) X rot_line(buf); X ++Rlines; X } X if (lines >= L_allow) X break; X if (More) X strcpy(lasave,Lookahead); X lines += do_out(Lookahead,L_allow-lines); X } X X if (Lookahead != NULL) X { X /* X ** calculation is truncated rather than rounded, X ** so we shouldn't get "100%". Subtract 2 for X ** 1 line lookahead and empty line at beginning X ** of article. X */ X if (Headflag) X { X top = (Rlines-2); X bottom = hdr.lines + Hlines; X } X else X { X top = (Rlines-Hlines-2); X bottom = hdr.lines; X } X /* X ** protect against division by zero - X ** shouldn't actually come up zero at this X ** point if vns_aopen is sane. 999 will let user X ** know the percentage is obviously wrong. X */ X if (bottom != 0) X percent = (top*100L)/bottom; X else X percent = 999; X sprintf (pstr,PAGE_MID,percent); X } X else X { X if (sn == NULL) X strcpy (pstr,PAGE_END); X else X strcpy (pstr,PAGE_NEXT); X } X c = getpgch(pstr,&hdr); X X /* X handle user input: X CAUTION!! return cases must close Fpread. X */ X step = FALSE; X switch (c) X { X case PG_NEXT: X if (Digest) X { X fclose (Fpread); X unlink (Fname); X } X else X vns_aclose (Fpread); X sig_set(BRK_RFIN); X return (0); X case PG_FLIP: X *pages = 1; /* fall through */ X case PG_QUIT: X if (Digest) X { X fclose (Fpread); X unlink (Fname); X } X else X vns_aclose (Fpread); X sig_set(BRK_RFIN); X return (-1); X case PG_REWIND: X if (Headflag) X { X Rlines = 0; X rewind (Fpread); X } X else X { X fseek (Fpread,Rew_pos,0); X Rlines = Hlines; X } X Lookahead = NULL; X lines = 2 - RECBIAS; X break; X case PG_SEARCH: X searcher(buf); X lines = 2 - RECBIAS; X lines += do_out(buf,L_allow-lines); X break; X case PG_WIND: X fseek (Fpread,0L,2); X lines = 2 - RECBIAS; X Lookahead = NULL; X break; X case PG_STEP: X if (Lookahead == NULL) X { X if (Digest) X { X fclose (Fpread); X unlink (Fname); X } X else X vns_aclose (Fpread); X sig_set(BRK_RFIN); X return (0); X } X lines = L_allow - 1; X step = TRUE; /* Temporarily disable paging */ X break; X default: X if (Lookahead == NULL) X { X if (Digest) X { X fclose (Fpread); X unlink (Fname); X } X else X vns_aclose (Fpread); X sig_set(BRK_RFIN); X return (0); X } X lines = 2 - RECBIAS; X break; X } X } X} X X/* X getpgch prints prompt and gets command from user X handles "mail", "save" and "followup" internally X as well as flag resets. X*/ Xstatic char Xgetpgch(prompt,hdr) Xchar *prompt; XARTHEADER *hdr; X{ X char c; X int ic; X int i; X char mbuf[RECLEN]; X X term_set (ONREVERSE); X#ifdef amiga X sprintf(pr_buf,"%s\015",prompt); X tputs(pr_buf,1,ttputc); X#else X printf("%s\015",prompt); X#endif X term_set (OFFREVERSE); X while ((ic=getnoctl()) != EOF) X { X c = Cxitor[ic]; X if (Hookfunc != NULL && (i = (*Hookfunc)(c,1,1,mbuf)) >= 0) X { X if (i == 0) X { X term_set (ZAP,0,PPR_MAX); X#ifdef amiga X sprintf(pr_buf,"%s\n",mbuf); X tputs(pr_buf,1,ttputc); X#else X printf("%s\n",mbuf); X#endif X } X term_set (ONREVERSE); X#ifdef amiga X sprintf(pr_buf,"%s\015",prompt); X tputs(pr_buf,1,ttputc); X#else X printf("%s\015",prompt); X#endif X term_set (OFFREVERSE); X continue; X } X switch (c) X { X case SETROT: X term_set (ZAP,0,PPR_MAX); X if (Rot == 0) X { X Rot = 13; X#ifdef amiga X sprintf (pr_buf,"%s\n",Roton_msg); X tputs(pr_buf,1,ttputc); X#else X printf ("%s\n",Roton_msg); X#endif X } X else X { X Rot = 0; X#ifdef amiga X sprintf (pr_buf,"%s\n",Rotoff_msg); X tputs(pr_buf,1,ttputc); X#else X printf ("%s\n",Rotoff_msg); X#endif X } X if (Lookahead != NULL && Rlines > Hlines) X rot_line(Lookahead); X break; X case HEADTOG: X term_set (ZAP,0,PPR_MAX); X if (Headflag) X { X Headflag = FALSE; X#ifdef amiga X sprintf (pr_buf,"%s\n",Hdoff_msg); X tputs(pr_buf,1,ttputc); X#else X printf ("%s\n",Hdoff_msg); X#endif X } X else X { X Headflag = TRUE; X#ifdef amiga X sprintf (pr_buf,"%s\n",Hdon_msg); X tputs(pr_buf,1,ttputc); X#else X printf ("%s\n",Hdon_msg); X#endif X } X break; X case PG_HELP: X term_set (ZAP,0,PPR_MAX); X help_rd (); X break; X case PG_REPLY: X mail (hdr); X break; X case PG_FOLLOW: X followup (hdr); X break; X case SAVE: X saver (); X break; X case PRINT: X printr (); X break; X default: X term_set (ZAP,0,PPR_MAX); X return (c); X } X X term_set (ONREVERSE); X#ifdef amiga X sprintf(pr_buf,"%s\015",prompt); X tputs(pr_buf,1,ttputc); X#else X printf("%s\015",prompt); X#endif X term_set (OFFREVERSE); X } X term_set (ZAP,0,PPR_MAX); X return (c); X} X X/* X save article. Like its "session" counterpart, this loses storage X if the user specifies a new file, but it should not be significant X*/ Xstatic Xsaver () X{ X char buf[RECLEN],msg[RECLEN],*str_store(); X X user_str (buf,"save file ? ",0,Savefile); X if (buf[0] != '\0' && buf[0] != '|') X Savefile = str_store(buf); X if (save_art(Fname,buf,msg) != 0) X rerrmsg(msg); X else { X#ifdef amiga X sprintf(pr_buf,"%s\n",msg); X tputs(pr_buf,1,ttputc); X#else X printf("%s\n",msg); X#endif X } X} X X/* X invoke editor on new temp file, mail using reply line, X possibly first allowing user to overide the reply (not INLETTER) X*/ Xstatic Xvoid Xmail (hdr) XARTHEADER *hdr; X{ X char *new, fn[L_tmpnam], cmd [RECLEN+60]; X char *rprompt (); X int i; X FILE *fp, *fopen(); X X if (Massage != NULL) X (*Massage)(hdr); X X if (hdr->mail_err != NULL) X { X rerrmsg(hdr->mail_err); X return; X } X X tmpnam (fn); X if ((fp = fopen(fn,"w")) == NULL) X { X rerrmsg("can't open temp file, %s",fn); X return; X } X X for (i = 0; i < hdr->mail_num; ++i) X fprintf(fp,"%s\n",(hdr->mail)[i]); X fprintf(fp,"\n"); X X fprintf(fp,"%s:\n",hdr->from); X edcopy (fp); X fclose (fp); X X tty_set (SAVEMODE); X X sprintf (cmd,"%s %s", Editor, fn); X chdir (Orgdir); X system (cmd); X vns_gset (Page.h.name); X X new = rprompt ("still want to mail it ? ",cmd); X if (new != NULL && (*new == 'y' || *new == 'Y')) X { X if (Mailfunc == NULL) X { X sprintf (cmd, hdr->mailcmd, fn); X system (cmd); X#ifdef amiga X sprintf (pr_buf,"given to mailer\n"); X tputs(pr_buf,1,ttputc); X#else X printf ("given to mailer\n"); X#endif X } X else X (*Mailfunc)(hdr,fn); X } X else { X#ifdef amiga X sprintf (pr_buf,"not mailed\n"); X tputs(pr_buf,1,ttputc); X#else X printf ("not mailed\n"); X#endif X } X X unlink (fn); X X tty_set (RESTORE); X term_set (RESTART); X} X X/* X post a followup article, invoking editor for user after creating X new temp file. remove after posting. X*/ Xstatic Xvoid Xfollowup (hdr) XARTHEADER *hdr; X{ X char fn[L_tmpnam], *new, cmd [RECLEN], *rprompt(); X int i; X FILE *f, *fopen(); X char *rindex(); X X if (hdr->post_err != NULL) X { X rerrmsg(hdr->post_err); X return; X } X X tmpnam (fn); X if ((f = fopen(fn,"w")) == NULL) X { X rerrmsg("can't open temp file, %s",fn); X return; X } X X for (i=0; i < hdr->post_num; ++i) X fprintf(f,"%s\n",(hdr->post)[i]); X fprintf(f,"\n"); X X fprintf(f,"From article %s, by %s:\n", hdr->artid, hdr->from); X X edcopy (f); X fclose (f); X tty_set (SAVEMODE); X sprintf (cmd,"%s %s", Editor, fn); X chdir (Orgdir); X system (cmd); X vns_gset (Page.h.name); X X new = rprompt("still want to post it ? ",cmd); X if (new != NULL && (*new == 'y' || *new == 'Y')) X { X if (Postfunc == NULL) X { X sprintf (cmd, hdr->postcmd, fn); X system (cmd); X#ifdef amiga X sprintf (pr_buf,"given to posting program\n"); X tputs(pr_buf,1,ttputc); X#else X printf ("given to posting program\n"); X#endif X } X else X (*Postfunc)(hdr,fn); X save2_article (fn); X } X else { X#ifdef amiga X sprintf (pr_buf,"not posted\n"); X tputs(pr_buf,1,ttputc); X#else X printf ("not posted\n"); X#endif X } X unlink (fn); X tty_set (RESTORE); X term_set (RESTART); X} X X/* X get user buffer, return whitespace delimited token X buffer is allowed to overwrite prompt string. This routine X should only be used when the terminal is in cooked mode. X In raw, use user_str(). X*/ Xstatic char * Xrprompt(s,buf) Xchar *s,*buf; X{ X char *strtok(); X X#ifdef amiga X sprintf(pr_buf,"%s",s); X tputs(pr_buf,1,ttputc); X#else X printf("%s",s); X#endif X fgets (buf,RECLEN-1,stdin); X return (strtok(buf," \t\n")); X} X X/* X edcopy copies article to file which user is editting for X a reply or followup, so it may be referenced. It places X ED_MARK in the left hand margin. X*/ Xstatic Xedcopy(fp) XFILE *fp; X{ X long current; X char buf[RECLEN]; X X /* save position, and seek to top of article */ X current = ftell(Fpread); X fseek (Fpread,Rew_pos,0); X X /* if line already begins with ED_MARK, forget about the space */ X while (fgets(buf,RECLEN-1,Fpread) != NULL) X { X if (buf[0] == ED_MARK) X fprintf(fp,"%c%s",ED_MARK,buf); X else X fprintf(fp,"%c %s",ED_MARK,buf); X } X X /* restore position */ X fseek(Fpread,current,0); X} X Xstatic Xrot_line (s) Xunsigned char *s; X{ X for ( ; *s != '\0'; ++s) X { X if (isupper(*s)) X { X *s += Rot; X if (!isupper(*s)) X *s -= 26; X continue; X } X if (islower(*s)) X { X *s += Rot; X if (!islower(*s)) X *s -= 26; X } X } X} X X/* X** output record. folds record to terminal width on word boundaries, X** returning number of lines output. If limit is reached, remainder X** of buffer waiting to be output is returned. Processes several X** special characters: X** form-feed - return "lim" lines so we stop on that line X** tabs - counts "expanded" width X** backspace - assumes they work, -1 width unless in first col. X** bell - pass through with zero width X** newline - end of record. X** del - turns into '_' X** other control - turned into '?' X** (prevents "letter bombs" containing inappropriate control X** sequences for the terminal). X** X** Sets Lookahead pointer to remainder of line or NULL. X*/ Xstatic Xdo_out(s,lim) Xchar *s; Xint lim; X{ X int len,i; X char cs,*word,*start; X X Lookahead = NULL; X if (s == NULL) X return(0); X len = 0; X start = word = s; X X /* X ** NOTE: "normal" return is buried inside switch, at newline X ** ending record X */ X for (i=0; i < lim; ++i) X { X for ( ; len < C_allow; ++s) X { X switch (*s) X { X case '\n': X *s = '\0'; /* fall through */ X case '\0': X#ifdef amiga X sprintf(pr_buf,"%s\n",start); X tputs(pr_buf,1,ttputc); X#else X printf("%s\n",start); X#endif X return(i+1); X case '\t': X len = ((len/PERTAB)+1)*PERTAB; X word = s; X break; X case '\b': X if (len > 0) X --len; X break; X case '\014': X *s = ' '; X i = lim-1; /* fall through */ X case ' ': X word = s+1; X ++len; X break; X case '\177': X *s = '_'; X ++len; X break; X default: X if (iscntrl(*s)) X *s = '?'; X ++len; /* fall through */ X case '\07': X break; X } X } X cs = *s; X *s = '\0'; X if ((len = strlen(word)) < BACKTRACK) X { X *s = cs; X s = word; X cs = *s; X *s = '\0'; X } X else X len = 0; X#ifdef amiga X sprintf(pr_buf,"%s\n",start); X tputs(pr_buf,1,ttputc); X#else X printf("%s\n",start); X#endif X start = s; X *s = cs; X } X Lookahead = start; X return(lim); X} X Xstatic Xvoid Xsave2_article(tempfname) Xchar *tempfname; X{ X FILE *in, *out; X int c; X time_t timenow, time(); X char *today, *ctime(); X X if ((in = fopen(tempfname, "r")) == NULL) X return; X if ((out = fopen(Ccfile, "a")) == NULL) X { X fclose(in); X return; X } X timenow = time((time_t)0); X today = ctime(&timenow); X fprintf(out,"From vn %s",today); X while ((c=getc(in)) != EOF) X putc(c, out); X putc('\n', out); X fclose(in); X fclose(out); X#ifdef amiga X sprintf (pr_buf,"a copy has been saved in %s\n", Ccfile); X tputs(pr_buf,1,ttputc); X#else X printf ("a copy has been saved in %s\n", Ccfile); X#endif X} X X/* X send article to printer X*/ Xstatic Xvoid Xprintr () X{ X char cmd[RECLEN]; X char fn[L_tmpnam]; X long savepos; X FILE *f; X X tmpnam (fn); X if ((f = fopen(fn,"w")) == NULL) X { X rerrmsg("can't open temp file, %s",fn); X return; X } X X savepos = ftell(Fpread); X rewind(Fpread); X while (fgets(cmd,RECLEN-1,Fpread) != NULL) X fputs(cmd,f); X fclose(f); X fseek(Fpread,savepos,0); X X tty_set (SAVEMODE); X#ifdef amiga X sprintf(pr_buf,"Sent to printer\n"); X tputs(pr_buf,1,ttputc); X#else X printf("Sent to printer\n"); X#endif X#ifdef amiga X sprintf (cmd,"%s >null: %s",Printer,fn); X#else X sprintf (cmd,"%s %s 2>/dev/null",Printer,fn); X#endif X system (cmd); X tty_set (RESTORE); X unlink (fn); X} X X/* X search article for specified search pattern, returning the line on which X it is found in buf, a null buffer otherwise. The input file will X be positioned either after the line on which the pattern is X found, or unaaltered if match fails. X*/ Xstatic Xvoid Xsearcher (buf) Xchar *buf; X{ X static char searchstr[RECLEN] = ""; X char lasave[RECLEN]; X char *reg, *regcmp(), *regex(); X long current; X int orlines; X X /* save position, then request search pattern */ X current = ftell(Fpread); X orlines = Rlines; X X sprintf (lasave,SEARCHFORM,searchstr); X user_str (searchstr,lasave,0,searchstr); X X /* Now compile the search string */ X if(( reg = regcmp(searchstr, (char *)0)) == NULL) { X rerrmsg("Invalid search string \"%s\"", searchstr); X *buf = '\0'; X return; X } X X /* try lookahead buffer first */ X if (Lookahead != NULL && regex(reg,Lookahead) != NULL) X { X strcpy(buf,Lookahead); X regfree(reg); X return; X } X X /* Lookahead can point into buf */ X if (Lookahead != NULL) X strcpy(lasave,Lookahead); X X /* now start reading lines, rotating if necessary and do search */ X while (fgets(buf,RECLEN-1,Fpread) != NULL) X { X if (Rot != 0 && Rlines >= Hlines) X rot_line(buf); X ++Rlines; X if( regex(reg, buf) != NULL ){ /* Got it */ X#ifdef MINIX X/* inverse video mucks up this line somehow */ X rerrmsg("\tSkipping ...\n\n"); X#else X rerrmsg("\n\tSkipping ....\n\n"); X#endif X regfree(reg); X return; X } X } X X /* no dice, so restore position */ X regfree(reg); X rerrmsg("Cannot find string \"%s\" in remainder of article", searchstr); X fseek(Fpread,current,0); X Rlines = orlines; X if (Lookahead != NULL) X strcpy(buf,lasave); X else X *buf = '\0'; X} X X/* X** print a reverse video error message while reading an article. X*/ Xstatic Xrerrmsg(s,a,b,c,d,e) Xchar *s; Xlong a,b,c,d,e; X{ X term_set (ONREVERSE); X#ifdef amiga X sprintf(pr_buf,"\n "); X tputs(pr_buf,1,ttputc); X sprintf(pr_buf,s,a,b,c,d,e); X tputs(pr_buf,1,ttputc); X sprintf(pr_buf," \07\n"); X tputs(pr_buf,1,ttputc); X#else X printf("\n "); X printf(s,a,b,c,d,e); X printf(" \07\n"); X#endif X term_set (OFFREVERSE); X} END_OF_FILE if test 18716 -ne `wc -c <'reader.c'`; then echo shar: \"'reader.c'\" unpacked with wrong size! fi # end of 'reader.c' fi if test -f 'session.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'session.c'\" else echo shar: Extracting \"'session.c'\" \(24544 characters\) sed "s/^X//" >'session.c' <<'END_OF_FILE' X/* X** vn news reader. X** X** session.c - top session loop X** X** see copyright disclaimer / history in vn.c source file X*/ X#include <stdio.h> X#include <setjmp.h> X#include <ctype.h> X#include "config.h" X#include "tty.h" X#include "brk.h" X#include "head.h" X#include "tune.h" X#include "node.h" X#include "page.h" X#include "vn.h" X X#ifdef amiga X#define system(a) Execute(a, 0, 0) X#undef getchar X#define getchar ttgetc Xextern char pr_buf[]; Xextern ttputc (); X#endif X Xextern NODE **Newsorder; Xextern char Erasekey, Killkey; Xextern int Rot; Xextern char *Ps1,*Printer; Xextern char *Orgdir,*Savefile; Xextern int Ncount, Cur_page, Lrec, L_allow, C_allow; Xextern int Headflag; Xextern PAGE Page; Xextern int Digest; Xextern char *No_msg; Xextern char *Hdon_msg; Xextern char *Hdoff_msg; Xextern char *Roton_msg; Xextern char *Rotoff_msg; Xextern char Cxitop[], Cxptoi[]; Xextern char *Aformat; Xextern char *Contstr; Xextern char *Kl,*Kr,*Ku,*Kd; Xextern int Nounsub, Listfirst; Xextern char *List_sep; Xextern char *Version, *Vns_version; X Xextern char (*Marker)(); Xextern int (*Hookfunc)(); X Xextern char *strtok (); X Xstatic int C_info; Xstatic int Dskip, Drec; X Xstatic char *Unsub_msg = "Unsubscribed"; Xstatic char *Egroup_msg = "Entire newsgroup"; X Xstatic int Crec; Xstatic int Highrec; X Xstatic show (), wr_show (), spec_group (), tot_list (), do_update (), X new_read (), new_sub (), markstr (), forward (), genlist (), X printstr (), savestr (); X X#ifdef MSDOS X#undef getchar X#define getchar getraw X#endif X X X X/* X main session handler processing input commands X X NOTE: this is where a setjmp call is made to set the break reentry X location. Keep the possible user states in mind. X*/ Xsession () X{ X char alist [RECLEN], c; X int newg, i, j, count; X jmp_buf brkbuf; X X newg = new_groups(); X tty_set (RAWMODE); X find_page (0); X Digest = 0; X X /* reentry point for break from within session interaction */ X setjmp (brkbuf); X sig_set (BRK_SESS,brkbuf); X Headflag = FALSE; X Rot = 0; X X /* done this way so that user gets "really quit?" break treatment */ X if (newg > 0) X { X#ifdef amiga X sprintf (pr_buf,"\n%s",Contstr); X tputs(pr_buf,1,ttputc); X#else X printf ("\n%s",Contstr); X#endif X getnoctl(); X newg = 0; X } X X /* list preview option - clear after first time for long jumps */ X if (Listfirst) X { X /* tot_list settings will be overwritten in this case */ X tot_list(); X Listfirst = 0; X } X X /* if breaking from a digest, recover original page */ X if (Digest) X { X find_page(Cur_page); X Digest = 0; X } X show (); X Crec = RECBIAS; X Highrec = Page.h.artnum + RECBIAS; X term_set (MOVE,0,Crec); X X /* X handle commands until QUIT, update global/local status X and display for each. X */ X for (count = getkey(&c); c != QUIT; count = getkey(&c)) X { X if (Hookfunc != NULL) X { X if ((i = (*Hookfunc)(c,0,1,alist)) >= 0) X { X if (i == 0) X prinfo(alist); X else X { X term_set(ERASE); X show(); X } X term_set (MOVE,0,Crec); X continue; X } X } X X if ( srch_help(c,&i) != 0 || (Digest != 0 && i == 0)) X { X preinfo (UDKFORM,Cxptoi[HELP]); X term_set (MOVE, 0, Crec); X continue; X } X X switch (c) X { X case HEADTOG: X if (Headflag) X { X Headflag = FALSE; X prinfo (Hdoff_msg); X } X else X { X Headflag = TRUE; X prinfo (Hdon_msg); X } X term_set (MOVE,0,Crec); X break; X case SETROT: X if (Rot == 0) X { X Rot = 13; X prinfo (Roton_msg); X } X else X { X Rot = 0; X prinfo (Rotoff_msg); X } X term_set (MOVE,0,Crec); X break; X case SSTAT: X count_msg (); X term_set (MOVE,0,Crec); X break; X case GRPLIST: X tot_list (); X show(); X term_set (MOVE,0,Crec); X break; X case REDRAW: X show(); X term_set (MOVE,0,Crec); X break; X case UNSUBSCRIBE: X new_sub(Page.h.group,0); X do_update(Unsub_msg); X term_set (MOVE,0,Crec); X break; X X case UPDATE: X new_read(Page.h.group,Page.b[Crec-RECBIAS].art_id); X wr_show (); X do_update("Updated to cursor"); X term_set (MOVE,0,Crec); X break; X case UPALL: X new_read(Page.h.group,(Page.h.group)->highnum); X wr_show(); X do_update(Egroup_msg); X term_set (MOVE,0,Crec); X break; X case ORGGRP: X new_read(Page.h.group,(Page.h.group)->orgrd); X wr_show(); X do_update(Egroup_msg); X term_set (MOVE,0,Crec); X break; X case UPSEEN: X up_seen(); X wr_show(); X do_update("All pages displayed to this point updated"); X term_set (MOVE,0,Crec); X break; X case ORGSTAT: X for (i = 0; i < Ncount; ++i) X new_read(Newsorder[i],(Newsorder[i])->orgrd); X wr_show(); X do_update("Original data recovered"); X term_set (MOVE,0,Crec); X break; X case TOPMOVE: X Crec = RECBIAS; X term_set (MOVE, 0, Crec); X break; X case BOTMOVE: X case ALTBOTTOM: X Crec = Highrec - 1; X term_set (MOVE, 0, Crec); X break; X case MIDMOVE: X Crec = (RECBIAS + Highrec - 1) / 2; X if (Crec < RECBIAS) X Crec = RECBIAS; X if (Crec >= Highrec) X Crec = Highrec - 1; X term_set (MOVE, 0, Crec); X break; X case UP: X if (Crec != RECBIAS) X { X Crec -= count; X if (Crec < RECBIAS) X Crec = RECBIAS; X term_set (MOVE, 0, Crec); X } X else X putchar ('\07'); X break; X case DOWN: X if (Crec < (Highrec - 1)) X { X Crec += count; X if (Crec >= Highrec) X Crec = Highrec - 1; X term_set (MOVE, 0, Crec); X } X else X putchar ('\07'); X break; X case MARKSTRING: X (Page.h.group)->flags |= FLG_ACC; X userlist (alist); X markstr (alist,c); X term_set (MOVE, 0, Crec); X write_page (); X break; X case MARK: X case ART_MARK: X genlist (alist,Crec-RECBIAS,count); X markstr (alist,c); X term_set (MOVE, 0, Crec); X write_page (); X break; X case UNMARK: X for (i=0; i < Page.h.artnum; ++i) X { X if (Page.b[i].art_mark != ' ') X { X if (Marker == NULL) X Page.b[i].art_mark = ' '; X else X Page.b[i].art_mark = X (*Marker)(Page.h.group, X Page.b[i].art_id, X Page.b[i].art_mark, c); X term_set (MOVE, 0, i+RECBIAS); X putchar (' '); X } X } X term_set (MOVE, 0, Crec); X write_page (); X break; X case BACK: X count *= -1; /* fall through */ X case FORWARD: X if (forward (count) >= 0) X show(); X else X preinfo ("No more pages"); X term_set (MOVE,0,Crec); X break; X case GRPBACK: X j = (Page.h.group)->order; X for (i = j-1; count > 0 && i >= 0; --i) X { X if ((Newsorder[i])->pages > 0) X { X j = i; X --count; X } X } X if (j == (Page.h.group)->order) X preinfo ("No more newsgroups"); X else X { X forward ((Newsorder[j])->pnum - Cur_page); X show(); X } X term_set (MOVE,0,Crec); X break; X case GRPFORWARD: X j = (Page.h.group)->order; X for (i= j+1; count > 0 && i < Ncount; ++i) X { X if ((Newsorder[i])->pages > 0) X { X j = i; X --count; X } X } X if (j == (Page.h.group)->order) X preinfo ("No more newsgroups"); X else X { X forward ((Newsorder[j])->pnum - Cur_page); X show(); X } X term_set (MOVE,0,Crec); X break; X case DIGEST: X if (Digest) X { X Digest = 0; X find_page (Cur_page); X show(); X Crec = Drec + RECBIAS + 1; X Highrec = Page.h.artnum + RECBIAS; X if (Crec >= Highrec) X Crec = Highrec - 1; X term_set (MOVE,0,Crec); X break; X } X (Page.h.group)->flags |= FLG_ACC; X Dskip = count - 1; X Drec = Crec - RECBIAS; X if (dige_page(Drec,Dskip) >= 0) X { X show(); X Crec = RECBIAS; X Highrec = Page.h.artnum + RECBIAS; X term_set (MOVE,0,Crec); X break; X } X Digest = 0; X preinfo ("Can't unpack the article"); X term_set (MOVE,0,Crec); X break; X case NEWGROUP: X if ((i = spec_group()) < 0) X { X term_set (MOVE,0,Crec); X break; X } X Digest = 0; X show(); X Crec = RECBIAS; X Highrec = Page.h.artnum + RECBIAS; X term_set (MOVE,0,Crec); X break; X X case SAVE: X (Page.h.group)->flags |= FLG_ACC; X genlist (alist,Crec-RECBIAS,count); X savestr (alist); X term_set (MOVE,0,Crec); X break; X case SAVEALL: X (Page.h.group)->flags |= FLG_ACC; X genlist (alist,0,L_allow); X savestr (alist); X term_set (MOVE,0,Crec); X break; X case SAVESTRING: X case ALTSAVE: X (Page.h.group)->flags |= FLG_ACC; X userlist (alist); X savestr (alist); X term_set (MOVE,0,Crec); X break; X case READ: X case ALTREAD: X (Page.h.group)->flags |= FLG_ACC; X genlist (alist,Crec-RECBIAS,count); X readstr (alist,count); X break; X case READALL: X (Page.h.group)->flags |= FLG_ACC; X genlist (alist,0,L_allow); X readstr (alist,0); X break; X case READSTRING: X (Page.h.group)->flags |= FLG_ACC; X userlist (alist); X readstr (alist,0); X break; X case PRINT: X (Page.h.group)->flags |= FLG_ACC; X genlist (alist,Crec-RECBIAS,count); X printstr (alist); X term_set (MOVE,0,Crec); X break; X case PRINTALL: X (Page.h.group)->flags |= FLG_ACC; X genlist (alist,0,L_allow); X printstr (alist); X term_set (MOVE, 0, Crec); X break; X case PRINTSTRING: X (Page.h.group)->flags |= FLG_ACC; X userlist (alist); X printstr (alist); X term_set (MOVE, 0, Crec); X break; X X case HELP: X help (); X show (); X term_set (MOVE, 0, Crec); X break; X case UNESC: X user_str (alist,Ps1,1,""); X term_set (ERASE); X#ifdef amiga X ttflush (); X#else X fflush (stdout); X#endif X tty_set (SAVEMODE); X if (chdir(Orgdir) < 0) { X#ifdef amiga X sprintf (pr_buf,"change to original directory, %s, failed",Orgdir); X tputs(pr_buf,1,ttputc); X#else X printf ("change to original directory, %s, failed",Orgdir); X#endif X } else X { X system (alist); X tty_set (RESTORE); X term_set (RESTART); X } X#ifdef amiga X sprintf (pr_buf,Contstr); X tputs(pr_buf,1,ttputc); X#else X printf (Contstr); X#endif X getnoctl (); X vns_gset(Page.h.name); X show (); X term_set (MOVE, 0, Crec); X break; X case PRTVERSION: X prinfo("%s %s", Version, Vns_version); X term_set (MOVE, 0, Crec); X break; X default: X preinfo("Unhandled key: %c", c); X break; X } X } X X Digest = 0; X for (i=0; i < Ncount; ++i) X { X if ((Newsorder[i])->rdnum < (Newsorder[i])->pgrd) X break; X } X if (i < Ncount) X { X user_str (alist,"Some displayed pages not updated - update ? ", X 1, QUIT_ANSWER); X if (alist[0] == 'y') X up_seen(); X } X sig_set (BRK_OUT); X} X X/* X** update status of Newsgroups to all seen pages X*/ Xup_seen() X{ X int i; X X for (i = 0; i < Ncount; ++i) X { X if (Nounsub && ((Newsorder[i])->flags & FLG_SUB) == 0) X { X new_read(Newsorder[i],(Newsorder[i])->highnum); X continue; X } X if ((Newsorder[i])->rdnum < (Newsorder[i])->pgrd) X new_read(Newsorder[i],(Newsorder[i])->pgrd); X } X} X X/* X count_msg displays count information X*/ Xcount_msg () X{ X int i, gpnum, gscan, gpage; X unsigned long mask; X gpnum = 1; X for (gscan = gpage = i = 0; i<Ncount; ++i) X { X if (((Newsorder[i])->flags & FLG_PAGE) != 0) X { X if (((Newsorder[i])->pnum + (Newsorder[i])->pages - 1) < Cur_page) X ++gpnum; X ++gpage; X for (mask=1; mask != 0L; mask <<= 1) X if (((Newsorder[i])->pgshwn & mask) != 0L) X ++gscan; X } X } X prinfo (CFORMAT,Cur_page+1,Lrec+1,gscan,gpnum,gpage); X} X X/* X forward utility handles paging X*/ Xstatic Xforward (count) Xint count; X{ X if (!Digest) X { X if ((count < 0 && Cur_page <= 0) || (count > 0 && Cur_page >= Lrec)) X return (-1); X Cur_page += count; X if (Cur_page < 0) X Cur_page = 0; X if (Cur_page > Lrec) X Cur_page = Lrec; X find_page (Cur_page); X Crec = RECBIAS; X Highrec = Page.h.artnum + RECBIAS; X return (0); X } X /* X ** in digests, paging past the end of the digest returns to X ** page extracted from. X */ X if (Dskip > 0 && (Dskip + count*L_allow) < 0) X Dskip = 0; X else X Dskip += count * L_allow; X find_page (Cur_page); X if (Dskip >= 0) X { X if (dige_page(Drec,Dskip) >= 0) X { X Crec = RECBIAS; X Highrec = Page.h.artnum + RECBIAS; X return (0); X } X } X Digest = 0; X Crec = Drec + RECBIAS + 1; X Highrec = Page.h.artnum + RECBIAS; X if (Crec >= Highrec) X Crec = Highrec - 1; X return (0); X} X X/* X generate list of articles on current page, X count articles, starting with first. X*/ Xstatic Xgenlist (list,first,count) Xchar *list; Xint first,count; X{ X int i; X for (i=first; i < Page.h.artnum && count > 0; ++i) X { X sprintf (list,"%d ",Page.b[i].art_id); X list += strlen(list); X --count; X } X} X X/* X send list of articles to printer X*/ Xstatic Xprintstr (s) Xchar *s; X{ X char cmd [RECLEN]; X char fn[L_tmpnam]; X char dsave[RECLEN]; /* save list for unlinking */ X X prinfo ("preparing print command ...."); X X if (Digest) X { X dig_list (s); X strcpy(dsave,s); X } X X if (*s != '\0') X { X tmpnam(fn); X if (art_xfer(fn,s,"w",NULL) != 0) X { X preinfo("Couldn't open temporary file"); X return; X } X#ifdef amiga X sprintf (cmd,"%s >null: %s",Printer,fn); X if (system (cmd) != 0) X prinfo ("Sent to printer"); X#else X sprintf (cmd,"%s %s 2>/dev/null",Printer,fn); X if (system (cmd) == 0) X prinfo ("Sent to printer"); X#endif X else X preinfo ("Print failed"); X unlink(fn); X } X else X preinfo (No_msg); X X if (Digest) X dig_ulist (dsave); X} X X/* X read a list of articles. X*/ Xreadstr (s,count) Xchar *s; Xint count; X{ X char *strtok(); X char *fn[MAXARTLIST+1]; X int pc, num, i; X X /* we pre-process tokens to release strtok() for further use */ X fn[0] = strtok(s,List_sep); X for (num=0; fn[num] != NULL; fn[(++num)] = strtok(NULL,List_sep)) X if (num >= MAXARTLIST) X break; X fn[num] = NULL; X X if (fn[0] != NULL) X { X term_set (ERASE); X for (i=0; i < num && readfile(fn[i], fn[i+1] ,&pc) >= 0; ++i) X { X#ifndef MINIX X/* I don't believe this code is correct at all!!! */ X if (Digest) X unlink (fn[i]); X#endif /*!MINIX*/ X } X X#ifndef MINIX X/* I don't believe this code is correct at all!!! */ X if (Digest && fn[i] != NULL) X unlink (fn[i]); X#endif /*!MINIX*/ X if (pc != 0) X forward (pc); X else X { X Crec += count; X if (Crec >= Highrec) X Crec = Highrec - 1; X } X show (); X term_set (MOVE, 0, Crec); X } X else X { X preinfo ("%s",No_msg); X term_set (MOVE, 0, Crec); X } X} X X/* X concatenate articles to save file with appropriate infoline messages. X prompt for save file, giving default. If save file begins with "|" X handle as a filter to pipe to. NOTE - every user specification of X a new Savefile "loses" some storage, but it shouldn't be a very great X amount. X*/ Xstatic Xsavestr (s) Xchar *s; X{ X char *ptr, newfile [MAX_C+1], msg[RECLEN]; X char *str_store(); X char dsave[RECLEN]; X X if (Digest) X { X dig_list (s); X strcpy(dsave,s); X } X X if (*s != '\0') X { X user_str (newfile,"save file ? ",1,Savefile); X ptr = newfile; X if (*ptr == '|') X { X term_set (ERASE); X#ifdef amiga X ttflush (); X#else X fflush (stdout); X#endif X save_art(s,ptr,msg); X#ifdef amiga X sprintf (pr_buf,"%s\n%s",msg,Contstr); X tputs(pr_buf,1,ttputc); X#else X printf ("%s\n%s",msg,Contstr); X#endif X getnoctl (); X show (); X } X else X { X prinfo("saving ...."); X if (*ptr == '\0') X ptr = Savefile; X else X Savefile = str_store(ptr); X if (save_art(s,Savefile,msg) != 0) X preinfo(msg); X else X prinfo(msg); X } X } X else X preinfo (No_msg); X X if (Digest) X dig_ulist (dsave); X} X X/* X basic page display routine. erase screen and format current page X*/ Xstatic Xshow () X{ X int i; X unsigned long mask; X char helpstr[40]; X X term_set (ERASE); X C_info = 0; X i = Cur_page - (Page.h.group)->pnum + 1; X if (Digest) { X#ifdef amiga X sprintf (pr_buf,DHFORMAT,Page.h.name); X tputs(pr_buf,1,ttputc); X#else X printf (DHFORMAT,Page.h.name); X#endif X } else { X#ifdef amiga X sprintf (pr_buf,HFORMAT,Page.h.name,i,(Page.h.group)->pages); X tputs(pr_buf,1,ttputc); X#else X printf (HFORMAT,Page.h.name,i,(Page.h.group)->pages); X#endif X } X X mask = 1L << (i-1); X (Page.h.group)->pgshwn |= mask; X mask = 1; X for (--i; i > 0 && (mask & (Page.h.group)->pgshwn) != 0 ; --i) X mask <<= 1; X if (i <= 0) X (Page.h.group)->pgrd = Page.b[(Page.h.artnum)-1].art_id; X X for (i=0; i < Page.h.artnum; ++i) X { X if (Digest) X { X#ifdef amiga X sprintf(pr_buf,Aformat,Page.b[i].art_mark,ART_UNWRITTEN,Page.b[i].art_id); X tputs(pr_buf,1,ttputc); X sprintf(pr_buf,"%s",Page.b[i].art_t); X tputs(pr_buf,1,ttputc); X#else X printf(Aformat,Page.b[i].art_mark,ART_UNWRITTEN,Page.b[i].art_id); X printf("%s",Page.b[i].art_t); X#endif X continue; X } X X if ((Page.h.group)->rdnum >= Page.b[i].art_id) { X#ifdef amiga X sprintf(pr_buf,Aformat,Page.b[i].art_mark,ART_WRITTEN,Page.b[i].art_id); X tputs(pr_buf,1,ttputc); X#else X printf(Aformat,Page.b[i].art_mark,ART_WRITTEN,Page.b[i].art_id); X#endif X } else { X#ifdef amiga X sprintf(pr_buf,Aformat,Page.b[i].art_mark,ART_UNWRITTEN,Page.b[i].art_id); X tputs(pr_buf,1,ttputc); X#else X printf(Aformat,Page.b[i].art_mark,ART_UNWRITTEN,Page.b[i].art_id); X#endif X } X#ifdef amiga X sprintf(pr_buf,"%s",Page.b[i].art_t); X tputs(pr_buf,1,ttputc); X#else X printf("%s",Page.b[i].art_t); X#endif X } X X sprintf(helpstr,HELPFORM,Cxptoi[HELP]); X if (!Digest && ((Page.h.group)->flags & FLG_SUB) == 0) X prinfo ("%s, %s",Unsub_msg,helpstr); X else X prinfo (helpstr); X} X X/* X update written status marks on screen X*/ Xstatic Xwr_show () X{ X int i,row; X char c; X X row = RECBIAS; X for (i=0; i < Page.h.artnum; ++i) X { X term_set (MOVE,WRCOL,row); X if ((Page.h.group)->rdnum >= Page.b[i].art_id) X c = ART_WRITTEN; X else X c = ART_UNWRITTEN; X#ifdef amiga X sprintf(pr_buf,"%c",c); X tputs(pr_buf,1,ttputc); X#else X printf("%c",c); X#endif X ++row; X } X} X X/* X obtain user input of group name, becomes current page if valid. X returns -1 or page number. calling routine does the show, if needed X*/ Xstatic Xspec_group () X{ X char nbuf [MAX_C + 1]; X NODE *p, *hashfind(); X X user_str(nbuf,"Newsgroup ? ",1,""); X X if (*nbuf == '\0' || (p = hashfind(nbuf)) == NULL) X { X preinfo ("Not a newsgroup"); X return (-1); X } X if ((p->flags & FLG_PAGE) == 0) X { X if ((p->flags & FLG_SUB) == 0) X { X new_sub(p,FLG_SUB); X do_update("Not subscribed: resubscribed for next reading session"); X } X else X prinfo ("No news for that group"); X return (-1); X } X if ((p->flags & FLG_SUB) == 0) X { X new_sub(p,FLG_SUB); X do_update("Resubscribed"); X } X find_page (p->pnum); X return (p->pnum); X} X X/* X obtain user input with prompt p. Optionally on info line. X handle erase and kill characters, suppresses leading X white space. Use defstr as the editable default user input. X If on info line, cursor is not moved anywhere whe done, otherwise X a <CR><LF> is done after input. Should be in raw mode to use X this routine. Used from outside this source file so that we X only have to do erase / kill key stuff one place. X*/ Xuser_str (s,p,iline,defstr) Xchar *s; Xchar *p; Xint iline; Xchar *defstr; X{ X int i,idx,len; X char c; X X if (iline) X { X prinfo ("%s%s",p,defstr); X idx = C_info; X } X else X { X#ifdef amiga X sprintf (pr_buf,"%s%s",p,defstr); X tputs(pr_buf,1,ttputc); X#else X printf ("%s%s",p,defstr); X#endif X idx = strlen(p); X } X X len = strlen(defstr); X for (i=0; i < len; i++) X s[i] = defstr[i]; X X for (i=len; idx < C_allow; ++i) X { X s[i] = getchar(); X c = s[i] & CHMASK; X if (c == '\015' || c == '\012') X break; X if (c == Erasekey) X { X if (i > 0) X { X term_set (RUBSEQ); X i -= 2; X --idx; X } X else X i = -1; X continue; X } X if (c == Killkey) X { X if (iline) X { X prinfo ("%s",p); X idx = C_info; X } X else X { X#ifdef amiga X sprintf (pr_buf,"\r%s",p); X tputs(pr_buf,1,ttputc); X#else X printf ("\r%s",p); X#endif X term_set(ZAP,strlen(p),idx); X#ifdef amiga X ttflush (); X#else X fflush(stdout); X#endif X idx = strlen(p); X } X i = -1; X continue; X } X /* no leading spaces */ X if (c == ' ' && i == 0) X { X i = -1; X putchar('\07'); X continue; X } X /* no controls */ X if (iscntrl(c)) X { X --i; X putchar('\07'); X continue; X } X ++idx; X putchar (s[i]); X#ifdef MINIX X fflush(stdout); X#endif X } X X if (iline) X C_info = idx; X else { X#ifdef amiga X sprintf(pr_buf,"\r\n"); X tputs(pr_buf,1,ttputc); X#else X printf("\r\n"); X#endif X } X X s[i] = '\0'; X} X/* X print something on the information line, X clearing any characters not overprinted. X preinfo includes reverse video and a bell for error messages. X*/ Xpreinfo (s,a,b,c,d,e,f) Xchar *s; X{ X int l; X char buf[RECLEN]; X X term_set (MOVE,0,INFOLINE); X putchar ('\07'); X term_set (ONREVERSE); X sprintf (buf,s,a,b,c,d,e,f); X#ifdef amiga X sprintf (pr_buf," %s",buf); X tputs(pr_buf,1,ttputc); X#else X printf (" %s ",buf); X#endif X term_set (OFFREVERSE); X l = strlen(buf) + 2; X if (l < C_info) X term_set (ZAP,l,C_info); X C_info = l; X#ifdef amiga X ttflush (); X#else X fflush(stdout); X#endif X} X Xprinfo (s,a,b,c,d,e,f) Xchar *s; Xlong a,b,c,d,e,f; X{ X int l; X char buf[RECLEN]; X term_set (MOVE,0,INFOLINE); X sprintf (buf,s,a,b,c,d,e,f); X#ifdef amiga X sprintf (pr_buf,"%s",buf); X tputs(pr_buf,1,ttputc); X#else X printf ("%s ",buf); X#endif X l = strlen(buf); X if (l < C_info) X term_set (ZAP,l,C_info); X C_info = l; X#ifdef amiga X ttflush (); X#else X fflush(stdout); X#endif X} X Xstatic Xtot_list () X{ X int i,max,len; X char c; X char ff[MAX_C+1]; X X term_set (ERASE); X X for (max=i=0; i < Ncount; ++i) X { X if ((Newsorder[i])->pages == 0) X continue; X if ((len = strlen((Newsorder[i])->nd_name)) > max) X max = len; X } X X sprintf (ff,"%%4d %%%ds: %%3d new %%3d updated\n",max); X X for (len=i=0; i < Ncount; ++i) X { X if ((Newsorder[i])->pages == 0) X continue; X#ifdef amiga X sprintf (pr_buf,ff, i, (Newsorder[i])->nd_name, X (Newsorder[i])->highnum - (Newsorder[i])->orgrd, X (Newsorder[i])->rdnum - (Newsorder[i])->orgrd); X tputs(pr_buf,1,ttputc); X#else X printf (ff, i, (Newsorder[i])->nd_name, X (Newsorder[i])->highnum - (Newsorder[i])->orgrd, X (Newsorder[i])->rdnum - (Newsorder[i])->orgrd); X#endif X ++len; X if (len == L_allow && i < (Ncount-1)) X { X#ifdef amiga X sprintf(pr_buf,"\nr - return, n - new group, other to continue ... "); X tputs(pr_buf,1,ttputc); X#else X printf("\nr - return, n - new group, other to continue ... "); X#endif X if ((c = getnoctl()) == 'r' || c == 'n') X break; X printf ("\n\n"); X len = 0; X } X } X if (i >= Ncount) X { X#ifdef amiga X sprintf(pr_buf,"n - new group, other to return ... "); X tputs(pr_buf,1,ttputc); X#else X printf("n - new group, other to return ... "); X#endif X c = getnoctl(); X } X X /* c will remain 'n' while user chooses bad newsgroups */ X while (c == 'n') X { X#ifdef amiga X sprintf(pr_buf,"\n"); X tputs(pr_buf,1,ttputc); X#else X printf("\n"); X#endif X user_str(ff,"Newsgroup number ? ",0,""); X i = atoi(ff); X if (i < 0 || i >= Ncount || (Newsorder[i])->pages == 0) X { X#ifdef amiga X sprintf(pr_buf,"\nBad newsgroup number\n"); X tputs(pr_buf,1,ttputc); X sprintf(pr_buf,"n - new group, other to return ... "); X tputs(pr_buf,1,ttputc); X#else X printf("\nBad newsgroup number\n"); X printf("n - new group, other to return ... "); X#endif X c = getnoctl(); X continue; X } X find_page((Newsorder[i])->pnum); X Crec = RECBIAS; X Highrec = Page.h.artnum + RECBIAS; X c = '\0'; X } X} X X/* X** call vns_write if anything has changed, then wipe FLG_ECHG bits X** also produce message(s) X*/ Xstatic Xdo_update(msg) Xchar *msg; X{ X int i; X X for (i=0; i < Ncount; ++i) X if(((Newsorder[i])->flags & FLG_ECHG) != 0) X break; X if (i < Ncount) X { X prinfo("Writing news status"); X vns_write(Newsorder,Ncount); X for (i=0; i < Ncount; ++i) X (Newsorder[i])->flags &= ~FLG_ECHG; X } X prinfo(msg); X} X X/* X** set a new rdnum value. If a change, set FLG_ECHG X*/ Xstatic Xnew_read(n,rd) XNODE *n; Xint rd; X{ X if (n->rdnum != rd) X { X n->rdnum = rd; X n->flags |= FLG_ECHG; X } X} X X/* X** set a new subscription bit. bit argument is either 0 or FLG_SUB. X*/ Xstatic Xnew_sub(n,bit) XNODE *n; Xunsigned bit; X{ X /* X ** since bit is 0 or FLG_SUB, we could get tricky with ^ X ** but this is clearer X */ X if (bit != 0 && (n->flags & FLG_SUB) == 0) X n->flags |= FLG_SUB|FLG_ECHG; X else X { X if (bit == 0 && (n->flags & FLG_SUB) != 0) X { X n->flags &= ~FLG_SUB; X n->flags |= FLG_ECHG; X } X } X} X X/* X** utility to mark articles. depends on fact that article numbers are X** in ascending order on page. X*/ Xstatic Xmarkstr (list,ckey) Xchar *list; Xchar ckey; X{ X char *tok; X int art, count; X BODY *b; X X count = 1; X b = Page.b; X for (tok = strtok(list,List_sep); tok != NULL; X tok = strtok(NULL,List_sep)) X { X art = atoi(tok); X while (count < Page.h.artnum && b->art_id < art) X { X ++count; X ++b; X } X if (b->art_id == art) X { X /* X ** Can't call Marker inside digests X */ X if (Marker == NULL || Digest) X { X if (b->art_mark != ART_MARK) X b->art_mark = ART_MARK; X else X b->art_mark = ' '; X } X else X { X b->art_mark = X (*Marker)(Page.h.group, art, X b->art_mark, ckey); X } X term_set (MOVE, 0, count-1+RECBIAS); X#ifdef amiga X sprintf (pr_buf,"%c\010",b->art_mark); X tputs(pr_buf,1,ttputc); X#else X printf ("%c\010",b->art_mark); X#endif X } X } X} END_OF_FILE if test 24544 -ne `wc -c <'session.c'`; then echo shar: \"'session.c'\" unpacked with wrong size! fi # end of 'session.c' fi echo shar: End of archive 4 \(of 6\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>. Mail comments to the moderator at <amiga-request@uunet.uu.net>. Post requests for sources, and general discussion to comp.sys.amiga.misc.