2000 /* * vdig - Display a digest the way vnews displays news. * * DESCRIPTION: * vdig is a program that reads an internet digest format message * (like the Dead-Flames), and displays it like vnews. For each * message, vdig first displays the subject of the message, * the name of the sender, the number of lines in the message, * and a list of any other newsgroups to which the message cross-posted. * vdig then prints a "more?" prompt in the lower left hand corner * of the screen. If you want to see the message, type the space bar, * and vdig will display the first page. If you want to skip the * message, type the n key, and vdig will go on to the next message. * After vdig displays the first page of a message, you can page * through the message by typing the space bar. After vdig displays * the last page of a message, when you type the space bar, vdig * goes on to the next message. * * vdig has a number of other features like scrolling through a message * a line or page at a time, saving an individual message in a file, * replying to the sender of an individual message with email, etc. * Type the question mark key for a list of what each key does. * * USAGE: * vdig can read the digest from a named file, or from the standard * input if no filename is given: * % vdig file * % vdig < file * You can also use vdig within the Berkeley mailer (/usr/ucb/Mail) * and just pipe the digest message directly to vdig, without having * to save it in a file: % Mail Mail version SMI 4.0 Mon Aug 10 16:41:36 EDT 1992 Type ? for help. "/usr/spool/mail/juo": 1 message 1 new >N 1 Dead-Flames-Request@fuggles.acc.virginia.edu Thu Sep 10 00:05 711/26064 Dead-Flames Digest #240 & | vdig Pipe to: "vdig" * * That also works with the System V mailer mailx. * * INSTALLATION: * vdig uses the curses library. On most unix machines, you * can compile it like this: * % cc -o vdig vdig.c -lcurses * On some, curses uses the termcap library, so you have to say * this, instead: * % cc -o vdig vdig.c -lcurses -ltermcap. * I'm not sure how to do this on a PC. * HISTORY: * I picked this program up from a friend a while ago and haven't * had to do much of anything to it. I've been using it for about * a year without any major problems (on rare occasions things get * hung when I run vdig from vmail and suspend them, but I've never * bothered tracking that down to see if it is a vmail bug or a vdig * bug; in either case it doesn't happen often). If you find any * problems (or make any improvements) you can send mail to * juo@cs.rutgers.edu. * * Version 0.1, 9/11/91 * Final "initial" version. * Version 1.1, 9/10/92 * Add these comments, no code changes. * */ #include #include #include #include #include #include extern int errno; extern char *Malloc(); extern char *Realloc(); #define GROWTH (128) #define MAXLINLEN (1024) /* these shouldn't be hardwired */ int scrwidth = 79; /* set this to 1 less than your screen width to minimize worries about getting screen boundary just exactly perfect. */ int scrheight = 24; struct mess { char *subject; char *from; char *crosspost; int lines; int len; char *headers; char *text; char **bos; char **eos; int screenlines; int headlines; char **screen; }; struct grow { int curlen; int maxlen; char *text; }; struct mess *readmess (); char *expandfilename (); struct mess **messlist = NULL; int nummess; void catch (); void catch2 (); int caught = 0; int tty_fd; static jmp_buf pipe_env; char title [128]; char status1 [1024]; char status2 [1024]; FILE *debug_fp = NULL; main (argc, argv) int argc; char *argv []; { FILE *fp; struct mess *m; char *p; char c; int notdone; int insamemsg; char prompt [80]; char tmps [1024]; int lastpage; int k; int curmess; int print_flag; int prevmess; int count; int optind; optind = 1; if (optind < argc) { p = argv [optind]; if (*p == '-') { ++p; if (*p == 'd') { ++p; debug_fp = fopen (p, "w"); if (debug_fp == NULL) { perror (argv [0]); exit (1); } ++optind; } } } if (optind < argc) { fp = fopen (argv [optind], "r"); if (fp == NULL) { perror (argv [optind]); exit (1); } readallmess (fp); } else { readallmess (stdin); fp = freopen ("/dev/tty", "r", stdin); if (fp == NULL) { perror (argv [0]); exit (1); } } screenon (0); signal (SIGINT, catch); if ( (nummess > 0) && (messlist [0]) && (messlist [0]->subject) ) strcpy (title, messlist [0]->subject); else strcpy (title, ""); notdone = 1; curmess = 0; prevmess = 0; caught = 0; status2 [0] = '\0'; while (notdone) { m = messlist [curmess]; if (m == NULL) break; setstatus1 (title, curmess, nummess - 1); insamemsg = 1; m->bos = m->screen; m->eos = m->screen; /* -1 only header, 1 skip header, 0 figure it */ print_flag = -1; printmoremess (m, print_flag); strcpy (prompt, "more? "); lastpage = 0; while (insamemsg) { caught = 0; c = getcmdchar (prompt, &count); switch (c) { case ' ' : if (lastpage) { if ( (curmess + 1) < nummess) { ++curmess; insamemsg = 0; } break; } if (print_flag == -1) print_flag = 1; lastpage = printmoremess (m, print_flag); print_flag = 0; if (lastpage) strcpy (prompt, "more? "); else sprintf (prompt, "more(%d%%)? ", percent (m) ); break; case 'A' : if ( (count >= 0) && count < nummess) { prevmess = curmess; curmess = count; insamemsg = 0; } break; case 's' : case 'w' : savemess (m, c); break; case 'd' : debug_printmess (m); lastpage = redrawscreen (m, print_flag); break; case 'r' : case 'R' : case 'f' : case 'F' : mailmess (m, c, title); lastpage = redrawscreen (m, print_flag); break; case '|' : pipemess (m); lastpage = redrawscreen (m, print_flag); break; case '?' : printhelp (); break; /* fall through */ case '\014' : lastpage = redrawscreen (m, print_flag); #if 0 main_redraw : m->eos = m->bos; move (0, 0); clear (); refresh (); lastpage = printmoremess (m, print_flag); #endif break; case '\005' : /* ^E */ case '\016' : /* ^N */ case '\004' : /* ^D */ case '\006' : /* ^F */ if (count == 0) count = 1; if (c == '\004') count = count * ( (scrheight - 4) / 2); else if (c == '\006') count = count * (scrheight - 4); scrolldown (m, count); print_flag = 0; lastpage = printmoremess (m, print_flag); if (lastpage) strcpy (prompt, "more? "); else sprintf (prompt, "more(%d%%)? ", percent (m) ); break; case '\031' : /* ^Y */ case '\020' : /* ^P */ case '\025' : /* ^U */ case '\002' : /* ^B */ if (count == 0) count = 1; if (c == '\025') count = count * ( (scrheight - 4) / 2); else if (c == '\002') count = count * (scrheight - 4); scrollup (m, count); print_flag = 0; lastpage = printmoremess (m, print_flag); if (lastpage) strcpy (prompt, "more? "); else sprintf (prompt, "more(%d%%)? ", percent (m) ); break; case 'n' : case '+' : if (count == 0) count = 1; if ( (curmess + count) < nummess) { prevmess = curmess; cur 2000 mess = curmess + count; insamemsg = 0; } break; case 'b' : if (count == 0) count = 1; if ( (curmess - count) >= 0) { prevmess = curmess; curmess = curmess - count; insamemsg = 0; } break; case '-' : if (prevmess != curmess) { int swapmess; swapmess = prevmess; prevmess = curmess; curmess = swapmess; insamemsg = 0; } break; case 'q' : case 'x' : insamemsg = 0; notdone = 0; break; } } } #if 0 refresh (); echo (); nocbreak (); move (scrheight - 1, 0); addch ('\n'); refresh (); endwin (); #endif screenoff (); /* putchar ('\n'); */ if (debug_fp) fclose (debug_fp); } redrawscreen (m, print_flag) struct mess *m; int print_flag; { int lastpage; m->eos = m->bos; move (0, 0); clear (); refresh (); lastpage = printmoremess (m, print_flag); return (lastpage); } char * getsecondcmd (prompt) char *prompt; { static char cmline [128]; int col; int basecol; char c; move (scrheight - 2, 0); clrtoeol (); addstr (prompt); basecol = strlen (prompt); col = 0; refresh (); caught = 0; c = getch (); while ( (c != '\r') && (c != '\n') ) { if (caught) return (NULL); if ( (c == '\010') || (c == '\377') ) { if (col >0) { addch ('\010'); --col; } } else if (c < ' ') { } else { addch (c); cmline [col] = c; ++col; } refresh (); c = getch (); } cmline [col] = '\0'; return (cmline); } mailmess (m, savetype, title) struct mess *m; char savetype; char *title; { FILE *fp; char filename [256]; char tmps [1024]; int lastnl; char *p; struct stat buf; struct stat buf2; int k; int append; sprintf (filename, "/tmp/vd%05d", getpid () ); fp = fopen (filename, "w"); if (fp == NULL) { char tmps [1204]; sprintf (tmps, "Cannot open %s", filename); seconderror (tmps); return (1); } fprintf (fp, "To: %s\n", m->from); fprintf (fp, "Subject: Re: %s\n", m->subject); fprintf (fp, "-----\n"); fprintf (fp, "\n"); if ( (savetype == 'R') || (savetype == 'F') ) { if (*title) fprintf (fp, "In %s, ", title); if (savetype == 'R') fprintf (fp, "you write:\n"); else fprintf (fp, "%s writes:\n", m->from); lastnl = 1; p = m->text; while (*p) { if (lastnl) { fputc ('>', fp); fputc (' ', fp); lastnl = 0; } fputc (*p, fp); if (*p == '\n') lastnl = 1; ++p; } } fclose (fp); sprintf (tmps, "vi %s", filename); screenoff (); system (tmps); dispose (filename); screenon (1); unlink (filename); return (0); } dispose (filename) char *filename; { char tmps [1024]; while (1) { fprintf (stderr, "What now, [s]end, [d]elete, [e]dit, [q]uit? "); fgets (tmps, 1023, stdin); if (tmps [0] == 'e') { sprintf (tmps, "vi %s", filename); system (tmps); } else if (tmps [0] == 'd') { break; } else if (tmps [0] == 'q') { break; } else if (tmps [0] == 's') { if (dosend (filename) == 0) break; } } return (0); } dosend (filename) char *filename; { FILE *fp; FILE *fpmail; char *p; char *q; char tmps [MAXLINLEN + 1]; char to [MAXLINLEN + 1]; char cc [MAXLINLEN + 1]; int haveto; int havecc; int k; int rc; int gotdash; void (*old_sigpipe)(); void broken_pipe (); fp = fopen (filename, "r"); if (fp == NULL) { perror (filename); return (-1); } haveto = 0; havecc = 0; while (p = fgets (tmps, MAXLINLEN, fp) ) { if (strncmp (tmps, "To: ", 4) == 0) { #define BINMAIL 1 #ifdef BINMAIL if (haveto) { fprintf (stderr, "Can not handle multiple To: addresses\n"); fclose (fp); return (-1); } if (parseaddr (tmps + 4, to, "To:") != 0) { fclose (fp); return (-1); } #endif haveto = 1; } #ifdef BINMAIL else if (strncmp (tmps, "Bcc: ", 5) == 0) { if (havecc) { fprintf (stderr, "Can not handle multiple Cc/Bcc: addresses\n"); fclose (fp); return (-1); } if (parseaddr (tmps + 5, cc, "Bcc:") != 0) { fclose (fp); return (-1); } havecc = 1; } else if (strncmp (tmps, "Cc: ", 4) == 0) { if (havecc) { fprintf (stderr, "Can not handle multiple Cc/Bcc: addresses\n"); fclose (fp); return (-1); } if (parseaddr (tmps + 4, cc, "Cc:") != 0) { fclose (fp); return (-1); } havecc = 1; } #endif else if (strcmp (tmps, "-----\n") == 0) break; } if (p == NULL) { fprintf (stderr, "Missing ----- line, can not send.\n"); return (1); } if (haveto == 0) { fprintf (stderr, "Missing To: address, can not send.\n"); return (1); } #ifdef BINMAIL if (havecc) sprintf (tmps, "/bin/mail %s %s", to, cc); else sprintf (tmps, "/bin/mail %s", to); #endif fprintf (stderr, "would: %s\n", tmps); fpmail = popen (tmps, "w"); if (fpmail == NULL) { perror (tmps); fclose (fp); return (-1); } fseek (fp, 0, 0); old_sigpipe = signal (SIGPIPE, broken_pipe); if (setjmp (pipe_env) == 0) { gotdash = 0; while (p = fgets (tmps, MAXLINLEN, fp) ) { if (!gotdash && (strcmp (tmps, "-----\n") == 0) ) { gotdash = 1; continue; } #ifdef BINMAIL if (!gotdash && (strncmp (tmps, "Bcc: ", 5) == 0) ) continue; #endif fputs (tmps, fpmail); } rc = 0; sprintf (status2, "Reply sent to %s", to); } else { rc = 1; } signal (SIGPIPE, old_sigpipe); pclose (fpmail); fclose (fp); return (rc); } parseaddr (src, addr, addrname) char *src; char *addr; char *addrname; { int k; char *p; char *q; char close; k = 0; p = src; q = addr; while ( (*p != '\n') && (*p != '\0') ) { if (*p == '<') break; ++p; } if (*p == '<') { ++p; while ( (*p != '>') && (*p != '\0') && (k < MAXLINLEN) ) { *q++ = *p++; ++k; } if (*p != '>') { fprintf (stderr, "Missing > in %s address\n", addrname); return (-1); } *q++ = '\0'; return (0); } p = src; while (*p == ' ') ++p; if ( (*p == '"') || (*p == '(') ) { if (*p == '"') close = '"'; else close = ')'; while ( (*p != close) && (*p != '\0') ) ++p; if (*p != close) { fprintf (stderr, "Missing closing %s in %s address\n", close, addrname); return (-1); } while (*p == ' ') ++p; } while ( (*p != '\n') && (*p != '\0') && (*p != '"') && (*p != '(') && (k < MAXLINLEN) ) { *q++ = *p++; ++k; } *q = '\0'; return (0); } savemess (m, savetype) struct mess *m; char savetype; { FILE *fp; char *filename; char *p; struct stat buf; int k; int append; filename = getsecondcmd ("file: "); if ( (filename == NULL) || (*filename == '\0') ) { move (scrheight - 2, 0); clrtoeol (); return (1); } filename = expandfilename (filename); k = stat (filename, &buf); if (k == 0) append = 1; else append = 0; if (append) fp = fopen (filename, "a"); else fp = fopen (filename, "w"); if (fp == NULL) { char tmps [1204]; sprintf (tmps, "Cannot open %s", filename); seconderror (tmps); return (1); } 2000 if (savetype == 's') { p = m->headers; while (*p) { fputc (*p, fp); ++p; } fputc ('\n', fp); } p = m->text; while (*p) { fputc (*p, fp); ++p; } fclose (fp); if (append) addstr (" appended"); else addstr (" created"); return (0); } pipemess (m) struct mess *m; { FILE *fp; char *filename; char *p; int k; void broken_pipe (); void (*old_sigpipe)(); filename = getsecondcmd ("|"); if ( (filename == NULL) || (*filename == '\0') ) { move (scrheight - 2, 0); clrtoeol (); return (1); } screenoff (); fp = popen (filename, "w"); if (fp == NULL) { char tmps [1204]; sprintf (tmps, "Cannot popen %s\n", filename); fputs (tmps, stderr); screenon (1); return (1); } old_sigpipe = signal (SIGPIPE, broken_pipe); if (setjmp (pipe_env) == 0) { p = m->headers; while (*p) { fputc (*p, fp); ++p; } fputc ('\n', fp); p = m->text; while (*p) { fputc (*p, fp); ++p; } } signal (SIGPIPE, old_sigpipe); pclose (fp); screenon (1); return (0); } void broken_pipe (sig) int sig; { longjmp (pipe_env, 1); } char * expandfilename (s) char *s; { extern char *getenv (); static char filename [1024]; char *home; if ( (s [0] != '~') || (s [1] != '/') ) return (s); home = getenv ("HOME"); if (home == NULL) return (s); strcpy (filename, home); strcat (filename, s + 1); return (filename); } printmoremess (m, print_flag) struct mess *m; int print_flag; { char tmps [128]; int lines; int width; int last_was_nl; char *p; char *q; int k; int start_y; int more_count; char **line; int done; start_y = 0; more_count = scrheight - 2; line = m->eos; if (print_flag != 1) m->bos = line; if (print_flag == -1) { move (0, 0); clrtobot (); for (k = 0; k < m->headlines; ++k) { addstr (*line); addch ('\n'); ++line; } done = (*line == NULL); if (line != m->screen) --line; m->eos = line; return (done); } else if (print_flag == 1) { start_y = m->headlines - 1; more_count = (scrheight - 2) - (m->headlines - 1); } else { start_y = 0; more_count = scrheight - 2; } move (start_y, 0); clrtobot (); for (k = 0; k < more_count; ++k) { if (*line == NULL) break; if (**line) addstr (*line); addch ('\n'); ++line; } done = (*line == NULL); if (line != m->screen) --line; m->eos = line; return (done); } readallmess (fp) FILE *fp; { struct mess *m; int maxmess; maxmess = 50; nummess = 0; messlist = (struct mess **) Malloc (maxmess * sizeof (struct mess *) ); while (m = readmess (fp) ) { if ( (nummess + 1) >= maxmess) { maxmess += 50; messlist = (struct mess **) Realloc (maxmess * sizeof (struct mess *) ); } messlist [nummess] = m; ++nummess; formatmess (m); } } formatmess (m) struct mess *m; { /* ++curlines; */ #define GROWSCREEN() {\ if (curlines >= (maxlines - 1) )\ {\ maxlines += 20;\ screen = (char **) Realloc (screen, maxlines * sizeof (char *) );\ }\ } char **screen; int maxlines; int curlines; int headlines; char *p; char *q; char *s; char tmps [MAXLINLEN + 16]; int n; maxlines = 20; curlines = 0; screen = (char **) Malloc (maxlines * sizeof (char *) ); if (m->subject) { sprintf (tmps, "Subject: %s", m->subject); n = strlen (tmps); p = tmps; while (n >= scrwidth) { s = Malloc (scrwidth + 1); strncpy (s, p, scrwidth); /* s [scrwidth - 1] = '\0'; */ s [scrwidth] = '\0'; screen [curlines] = s; ++curlines; GROWSCREEN (); n = n - (scrwidth); p = p + (scrwidth); } s = Malloc (n + 1); strcpy (s, p); screen [curlines] = s; ++curlines; GROWSCREEN (); } else { s = screen [curlines]; s = Malloc (17); strcpy (s, "Subject: [none]"); screen [curlines] = s; ++curlines; GROWSCREEN (); } if (m->from) { sprintf (tmps, "From: %s", m->from); n = strlen (tmps); p = tmps; while (n >= scrwidth) { s = Malloc (scrwidth + 1); strncpy (s, p, scrwidth); s [scrwidth] = '\0'; screen [curlines] = s; ++curlines; GROWSCREEN (); n = n - scrwidth; p = p + scrwidth; } s = Malloc (n + 1); strcpy (s, p); screen [curlines] = s; ++curlines; GROWSCREEN (); } else { screen [curlines] = Malloc (17); strcpy (screen [curlines], "From: [unknown]"); ++curlines; GROWSCREEN (); } if (m->crosspost) { sprintf (tmps, "Crossposted-To: %s", m->crosspost); n = strlen (tmps); p = tmps; while (n >= scrwidth) { s = Malloc (scrwidth + 1); strncpy (s, p, scrwidth); s [scrwidth] = '\0'; screen [curlines] = s; ++curlines; GROWSCREEN (); n = n - scrwidth; p = p + scrwidth; } s = Malloc (n + 1); strcpy (s, p); screen [curlines] = s; ++curlines; GROWSCREEN (); } sprintf (tmps, "(%d lines)", m->lines); s = Malloc (strlen (tmps) + 1); strcpy (s, tmps); screen [curlines] = s; ++curlines; GROWSCREEN (); s = Malloc (2); s [0] = '\0'; screen [curlines] = s; ++curlines; GROWSCREEN (); headlines = curlines; if (m->text) { p = m->text; while (*p) { n = linlen (p); while (n >= scrwidth) { s = Malloc (scrwidth + 1); strncpy (s, p, scrwidth); s [scrwidth] = '\0'; screen [curlines] = s; ++curlines; GROWSCREEN (); n = n - scrwidth; p = p + scrwidth; } s = Malloc (n + 2); if (n > 0) { strncpy (s, p, n); } s [n] = '\0'; screen [curlines] = s; ++curlines; GROWSCREEN (); p = p + n; if (*p) ++p; } } screen [curlines] = NULL; m->screen = screen; m->screenlines = curlines; m->headlines = headlines; #undef GROWSCREEN } linlen (p) char *p; { int n; n = 0; while ( (*p != '\n') && (*p != '\r') && (*p != '\0') ) { ++p; ++n; } return (n); } getcmdchar (prompt, count) char *prompt; int *count; { char c; int n; n = 0; if (status2 [0] != '\0') { move (scrheight - 2, 0); clrtoeol (); addstr (status2); status2 [0] = '\0'; } move (scrheight - 1, 0); clrtoeol (); if (status1 [0] != '\0') { move (scrheight - 1, 10); addstr (status1); move (scrheight - 1, 0); } addstr (prompt); refresh (); c = getch (); while ( ('0' <= c) && (c <= '9') ) { n = 10 * n + c - '0'; c = getch (); } if (count) *count = n; return (c); } printmesshead (m) struct mess *m; { char tmps [256]; move (0, 0); clear (); addstr ("Subject: "); if (m->subject) addstr (m->subject); addch ('\n'); addstr ("From: "); if (m->from) addstr (m->from); addch ('\n'); sprintf (tmps, "(%d lines)", m->lines); addstr (tmps); addch ('\n'); } struct mess * readmess (fp) FILE *fp; { struct mess *m; char tmps [1024]; int curlen; int maxlen; char *grow; char *p; int n; int line_count; int got_header; do { if (fgets (tmps, 1023, fp) == NULL) { return (NULL); } } while (blank (tmps) ); m = (struct mess *) Mal 2000 loc (sizeof (struct mess) ); m->from = NULL; m->subject = NULL; m->crosspost = NULL; m->text = NULL; m->headers = NULL; m->lines = 0; m->screen = NULL; m->screenlines = 0; m->len = 0; grow = (char *) Malloc (GROWTH); maxlen = GROWTH; curlen = 0; *grow = '\0'; line_count = 0; got_header = 0; while (!blank (tmps) ) { n = strlen (tmps); while ( (curlen + n) >= maxlen) { grow = (char *) Realloc (grow, maxlen + GROWTH); maxlen += GROWTH; } strcpy (grow + curlen, tmps); curlen += n; ++line_count; if (debug_fp) { fprintf (debug_fp, "read 1: \"%s\"\n", tmps); } if (strncmp (tmps, "From: ", 6) == 0) { n = strlen (tmps + 6); m->from = (char *) Malloc (n); strncpy (m->from, tmps + 6, n - 1); m->from [n - 1] = '\0'; got_header = 1; } else if (strncmp (tmps, "Subject: ", 9) == 0) { n = strlen (tmps + 9); m->subject = (char *) Malloc (n); strncpy (m->subject, tmps + 9, n - 1); m->subject [n - 1] = '\0'; got_header = 1; } else if (strncmp (tmps, "Crossposted-To: ", 16) == 0) { n = strlen (tmps + 16); m->crosspost = (char *) Malloc (n); strncpy (m->crosspost, tmps + 16, n - 1); m->crosspost [n - 1] = '\0'; got_header = 1; } if (fgets (tmps, 1023, fp) == NULL) { m->text = grow; m->lines = line_count; m->len = curlen; return (m); } } m->headers = grow; grow = (char *) Malloc (GROWTH); maxlen = GROWTH; curlen = 0; *grow = '\0'; line_count = 0; while (fgets (tmps, 1023, fp) != NULL) { if (debug_fp) { fprintf (debug_fp, "read 2: \"%s\"\n", tmps); } /* if ( (tmps [0] == '-') && (tmps [1] != ' ') ) */ if (strncmp (tmps, "------------------------------", 20) == 0) break; n = strlen (tmps); while ( (curlen + n) >= maxlen) { grow = (char *) Realloc (grow, maxlen + GROWTH); maxlen += GROWTH; } strcpy (grow + curlen, tmps); curlen += n; ++line_count; } m->text = grow; m->lines = line_count; m->len = curlen; if (debug_fp) { fprintf (debug_fp, "read 3: m->lines = %d, m->len = %d\n", m->lines, m->len); } return (m); } blank (p) char *p; { while ( (*p == ' ') || (*p == '\t') || (*p == '\n') ) ++p; return (*p == '\0'); } debug_printmess (m) struct mess *m; { int k; char *s; char **line; move (2, 0); clrtobot (); if (m->subject) printw ("subject = \"%s\"\n", m->subject); else printw ("subject = NULL\n"); if (m->from) printw ("from = \"%s\"\n", m->from); else printw ("from = NULL\n"); printw ("bos = %d = 0x%x\n", m->bos, m->bos); printw ("eos = %d = 0x%x\n", m->eos, m->bos); refresh (); if (m->screen) { line = m->screen; k = 0; while ( (*line) && (k < 9) ) { /* printw ("X%sX\n", *line); */ printw ("X 0x%x 0x%x %sX\n", line, *line); refresh (); ++line; ++k; } /* printw ("text = \"%s\"\n", m->text); */ } else printw ("screen = NULL\n"); refresh (); getcmdchar ("continue", NULL); } scrolldown (m, count) struct mess *m; int count; { int j; int k; char **line; line = m->eos = m->bos; for (j = 0; (j < count) && (*line != NULL); ++j) ++line; m->eos = line; } scrollup (m, count) struct mess *m; int count; { int j; int k; char **line; line = m->eos = m->bos; for (j = 0; (j < count) && (line > m->screen); ++j) --line; m->eos = line; } percent (m) struct mess *m; { int percent; percent = (100 * (m->eos - m->screen) ) / m->screenlines; if (percent >= 100) percent = 99; return (percent); } seconderror (s) char *s; { move (scrheight - 2, 0); clrtoeol (); addstr (s); } void catch (sig) int sig; { caught = sig; } void catch2 (sig) int sig; { char tmps [1204]; sprintf (tmps, "\ncaught sig %d\n", sig); err2 (tmps); } screenon (needreturn) int needreturn; { char c; int x; int y; fflush (stdin); fflush (stdout); fflush (stderr); if (needreturn) { fputs ("[Hit return to continue]\n", stderr); c = getchar (); while ( (c != '\n') && (c != '\r') ) { fputs ("hit return...\n", stderr); c = getchar (); } } initscr (); #if 0 /* this doesn't really work quite right anyways, so just * assume 24x80 for now... */ #ifdef SYSV getmaxyx (stdscr, y, x); #else #ifdef BSD { struct winsize ws; if (ioctl (fileno (stdin), TIOCGWINSZ, &ws) == 0) { y = ws.ws_row; x = ws.ws_col; } else { y = 0; x = 0; } } #endif #endif if (y > 0) scrheight = y; if (x > 0) scrwidth = x - 1; #endif cbreak (); noecho (); refresh (); } screenoff () { refresh (); echo (); nocbreak (); move (scrheight - 1, 0); addch ('\n'); refresh (); endwin (); fflush (stdin); fflush (stdout); fflush (stderr); } err2 (s) char *s; { write (2, s, strlen (s) ); } char * Malloc (n) int n; { void *p; p = (void *) malloc (n); if (p == NULL) { fprintf (stderr, "\nMalloc (%d), out of memory\n", n); } return (p); } char * Realloc (p, n) void *p; int n; { void *q; q = (void *) realloc (p, n); if (q == NULL) { fprintf (stderr, "\nRealloc (%d), out of memory\n", n); } return (q); } setstatus1 (title, curmess, nummess) char *title; int curmess; int nummess; { int j; int k; int pad_blanks; char *p; char *q; char tmps [128]; sprintf (tmps, "%d/%d", curmess, nummess); j = strlen (title) + 4; k = strlen (tmps); if (j + 20 < scrwidth) { pad_blanks = ( ( (scrwidth - 20) - j) / 2) + 2; q = status1; for (j = 0; j < pad_blanks; ++j) *q++ = ' '; p = title; while (*p) *q++ = *p++; pad_blanks = pad_blanks + (9 - k); for (j = 0; j < pad_blanks; ++j) *q++ = ' '; strcpy (q, tmps); } else if (k + 10 < scrwidth) { pad_blanks = (scrwidth - 10 - strlen (tmps) ); q = status1; for (j = 0; j < pad_blanks; ++j) *q++ = ' '; strcpy (q, tmps); } else { status1 [0] = '\0'; } } /* Vnews commands: ( may be preceded by a non-negative count) V 2.2 1/17/89 CR Next page or article D Decrypt a rot 13 joke n Go to next article A Go to article numbered count e Mark current article as unread < Go to article with given ID + or = Go forwards count articles p Go to parent article - Go to previous article ug Unsubscribe to this group ^B Go backwards count pages ^L Redraw screen ^N Go forward count lines v Print netnews version ^P Go backwards count lines q Quit ^D Go forward half a page x Quit without updating .newsrc ^U Go backwards half a page c Cancel the current article h Display article header H Display all article headers ! Escape to shell ? Display this message r Reply to article using editor K Mark rest of newsgroup read R Reply--put current article in reply b Go back 1 article in same group ESC-r Reply directly using mailer m Move on to next item in a digest f Post a followup article s Save article in file N Go to newsgroup (next is default) w Save without header l List unread articles in group L List all articles in group [Press CR to see article, h to see header... (any command will work)] */ /* ' ' A 887 s w r R f F | ^L ^E ^D ^Y ^U n b q x Vdig commands: ( may be preceded by a non-negative count) CR Next page or article D n Go to next article A Go to article numbered count e < [ + or = Go forwards count articles ] p [ - Go to previous article ] ug ^B Go backwards count pages ^L Redraw screen ^N Go forward count lines [ v Print netnews version ] ^P Go backwards count lines q Quit ^D Go forward half a page x ^U Go backwards half a page c h H ! Escape to shell ? Display this message r Reply to article using editor K R Reply--put current article in reply b Go back 1 article in same group [ ESC-r Reply directly using mailer ] m f Post a followup article s Save article in file N w Save without header l L [Press CR to see article, h to see header... (any command will work)] */ printhelp () { char *s = "\n\ \n\ vdig commands: ( may be preceded by a non-negative count) V 1.1 9/10/92\n\ CR Next page or article A Go to article numbered count\n\ n Go to next article b Go back count articles\n\ + Go forwards count articles - Go to previous article\n\ ^B Go backwards count pages ^F Go forwards count pages\n\ ^D Go forward half a page ^U Go backwards half a page\n\ ^N Go forward count lines ^P Go backwards count lines\n\ r Reply to article using editor R Reply--put current article in reply\n\ f Post a followup article ? Display this message\n\ s Save article in file w Save without header\n\ ^L Redraw screen q Quit\n\ \n\ [Press CR to see article, h to see header... (any command will work)]\n\ "; move (0, 0); clear (); refresh (); addstr (s); refresh (); } . 0