home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-03-13 | 42.6 KB | 1,851 lines |
- Article 997 of comp.sources.unix:
- Path: s.cc.purdue.edu!h.cc.purdue.edu!j.cc.purdue.edu!pur-ee!iuvax!inuxc!ihnp4!ptsfa!ames!amdcad!sun!pitstop!sundc!seismo!uunet!munnari!jz
- From: jz@mulga.oz.au (Justin Zobel)
- Newsgroups: comp.sources.unix
- Subject: v12i006: vmail - screen-based mail handler, Part03/03
- Message-ID: <1856@munnari.oz>
- Date: 13 Oct 87 21:17:15 GMT
- Sender: kre@munnari.oz
- Lines: 1837
- Approved: kre@munnari.oz.au
-
- Submitted by: jz@mulga.oz.au
- Posting-number: Volume 12, Issue 6
- Archive-name: vmail/Part03
-
- This is the third of three parts of vmail, an interactive mail handler
- that sits on top of MH.
- vmail has a number of advantages over raw MH. It is screen-based and
- faster (and more convenient) than the MH show-scan-rmm refile cycle.
- vmail makes it feasible for users to organise and keep track of moderate
- volumes of mail without wasting too much time, and is very simple to use.
- It has been in use at Melbourne University Computer Science Department
- for about six months without any problems, and has become the interface of
- choice for many users.
-
- : ---------------------------------------- cut here
-
- echo x - "load.c" 2>&1
- sed "s/^X//" >"load.c" <<'!The!End!'
- X/* --------------------
- X vmail -- load.c
- X
- X Routines to find folders, find all mail items in folders. Empty
- X folders are ignored.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X#include <ctype.h>
- X
- X
- X/* --------------------
- X Find all folders in mail directory, set up linked list.
- X-------------------- */
- Xvoid
- Xfind_folders()
- X{
- X struct direct *dp;
- X struct stat statbuf;
- X DIR *dirp;
- X int i, n = 0, scmp();
- X char str[LEN], **fds, **ftmp;
- X folder tmp, last = (folder) NULL;
- X
- X stat(mail_dir, &statbuf);
- X /* guess number of folders - 10 is an error bound */
- X ftmp = fds = (char **) malloc(sizeof(char *) * (statbuf.st_nlink+10));
- X dirp = opendir(mail_dir);
- X for(dp=readdir(dirp) ; dp != (struct direct *)NULL ; dp=readdir(dirp)) {
- X if(strcmp(dp->d_name, ".") == 0)
- X continue;
- X if(strcmp(dp->d_name, "..") == 0)
- X continue;
- X sprintf(str, "%s/%s", mail_dir, dp->d_name);
- X stat(str, &statbuf);
- X if(! (statbuf.st_mode & S_IFDIR))
- X continue;
- X if(! (statbuf.st_mode & S_IREAD) || ! (statbuf.st_mode & S_IWRITE)
- X || ! (statbuf.st_mode & S_IEXEC)) {
- X printf("Folder %s unreadable.\n", dp->d_name);
- X continue;
- X }
- X *ftmp = NEWSTR(strlen(dp->d_name)+1);
- X strcpy(*ftmp, dp->d_name);
- X n++, ftmp++;
- X }
- X closedir(dirp);
- X if(n == 0) {
- X printf("No folders.\n");
- X exit(1);
- X }
- X qsort(fds, n, sizeof(char *), scmp);
- X for(i=0, ftmp=fds ; i < n ; ftmp++, i++) {
- X tmp = NEW(mail_folder);
- X tmp->name = *ftmp;
- X tmp->last = tmp->mail = (item) NULL;
- X tmp->pages = tmp->pagenum = 1;
- X tmp->valid = false;
- X tmp->prev = last;
- X tmp->next = (folder) NULL;
- X if(last != (folder) NULL)
- X last->next = tmp;
- X else
- X folders = tmp;
- X last = tmp;
- X }
- X}
- X
- X
- Xint
- Xscmp(p, q)
- X char **p, **q;
- X{
- X return(strcmp(*p, *q));
- X}
- X
- X
- X/* --------------------
- X Find all mail items in given folder, throw away folder record if no
- X mail items. Returns next folder in linked list, adds new folder
- X records to linked list if original record overflows.
- X-------------------- */
- Xfolder
- Xfind_mail(flr, load_time)
- X folder flr;
- X int load_time;
- X{
- X struct direct *dp, *readdir();
- X DIR *dirp, *opendir();
- X int i, n = 0, items[MAXITEMS], *itmp = items, dcmp();
- X char str[LEN];
- X item tmp, last = (item) NULL;
- X folder new_folder();
- X
- X sprintf(str, "%s/%s", mail_dir, flr->name);
- X dirp = opendir(str);
- X if(dirp == (DIR *) NULL) {
- X if(load_time)
- X printf("%s: strange folder.\n", str);
- X } else {
- X for(dp=readdir(dirp) ; dp!=(struct direct *) NULL ; dp=readdir(dirp)) {
- X /* get numbers of all mail items */
- X if(n >= MAXITEMS) {
- X no_control();
- X printf("\nMore than %d items in folder.\n",MAXITEMS-1);
- X exit(1);
- X }
- X /* ignore anything that is not string of digits */
- X if(! digits(dp->d_name))
- X continue;
- X /* assume any file that is string of digits is a mail
- X item and not a directory */
- X *itmp = atoi(dp->d_name);
- X n++, itmp++;
- X }
- X closedir(dirp);
- X }
- X if(n == 0) { /* Empty folder - delete from list */
- X flr->valid = EMPTY;
- X if(load_time)
- X printf("\t%s: empty\n", flr->name);
- X if(flr->prev != (folder) NULL)
- X flr->prev->next = flr->next;
- X else
- X folders = flr->next;
- X if(flr->next != (folder) NULL)
- X flr->next->prev = flr->prev;
- X return(flr->next);
- X } else
- X qsort(items, n, sizeof(int), dcmp);
- X if(load_time) /* show status of folder */
- X if(n == 1)
- X printf("\t%s: %d\n", flr->name, *items);
- X else
- X printf("\t%s: %d-%d (%d items)\n",flr->name,*items,*(items+n-1),n);
- X for(i=0, itmp=items ; i < n ; itmp++, i++) {
- X /* add item to list of items in folder */
- X tmp = NEW(mail_item);
- X get_title(flr, tmp, *itmp);
- X if(i % lines == 0 && last != (item) NULL) {
- X /* add new record for folder */
- X flr->last = last;
- X flr = new_folder(flr);
- X last = (item) NULL;
- X }
- X tmp->next = (item) NULL;
- X tmp->prev = last;
- X if(last != (item) NULL)
- X last->next = tmp;
- X else
- X flr->mail = tmp;
- X last = tmp;
- X }
- X flr->last = last;
- X return(flr->next);
- X}
- X
- X
- Xint
- Xdcmp(a, b)
- X int *a, *b;
- X{
- X return(*a - *b);
- X}
- X
- X
- X/* --------------------
- X Return true if string consists only of digits.
- X-------------------- */
- Xint
- Xdigits(str)
- X char *str;
- X{
- X for( ; *str != '\0' ; str++)
- X if(! isdigit(*str))
- X return(false);
- X return(true);
- X}
- X
- X
- X/* --------------------
- X Make header line from mail item.
- X-------------------- */
- Xvoid
- Xget_title(flr, mail, num)
- X folder flr;
- X item mail;
- X int num;
- X{
- X FILE *fp, *fopen();
- X char date[10], str[LEN], subj[42], from[20], to[16], fill[42];
- X char repl = ' ', *first(), *s, *fgets();
- X int i;
- X
- X subj[0] = from[0] = to[0] = fill[0] = '\0';
- X sprintf(str, "%s/%s/%d", mail_dir, flr->name, num);
- X fp = fopen(str, "r");
- X while((s=fgets(str, LEN, fp)) != (char *) NULL && *str != '\n') {
- X /* while not eof and reading header */
- X str[strlen(str)-1] = '\0';
- X /* should also check date */
- X if(! lstrncmp("date:", str, 5))
- X get_date(str+5, date);
- X else if(! lstrncmp("subject:", str, 8)) {
- X s = first(str+8);
- X strncpy(subj, s, 41);
- X subj[41] = '\0';
- X } else if(! lstrncmp("replied:", str, 8))
- X repl = '-';
- X else if(! lstrncmp("from:", str, 5)) {
- X s = first(str+5);
- X if(! isuser(s)) {
- X strncpy(from, s, 19);
- X from[19] = '\0';
- X }
- X } else if(! lstrncmp("to:", str, 3)) {
- X s = first(str+3);
- X strncpy(to, s, 15);
- X to[15] = '\0';
- X } else if(! lstrncmp("apparently-to:", str, 14)) {
- X s = first(str+14);
- X strncpy(to, s, 15);
- X to[15] = '\0';
- X }
- X }
- X if(s != (char *) NULL) {
- X for(i=0 ; i < 50 && fgets(str, LEN, fp) != (char *) NULL ;) {
- X str[strlen(str)-1] = ' ';
- X strncpy(fill+i, str, 42-i);
- X i += strlen(str);
- X }
- X fill[41] = '\0';
- X }
- X fclose(fp);
- X if(subj[0] == '\0')
- X strcpy(subj, "(none)");
- X flatten(subj);
- X flatten(fill);
- X if(from[0] == '\0')
- X sprintf(str, " %8s %cTo: %-15s %s << %s",date,repl,to,subj,fill);
- X else
- X sprintf(str, " %8s %c%-19s %s << %s",date,repl,from,subj,fill);
- X str[cols-6] = '\0';
- X mail->title = NEWSTR(strlen(str)+1);
- X mail->number = num;
- X strcpy(mail->title, str);
- X}
- X
- X
- X#ifdef USDATE
- X#define DAY1 date[3]
- X#define DAY2 date[4]
- X#define MTH1 date[0]
- X#define MTH2 date[1]
- X#else
- X#define DAY1 date[0]
- X#define DAY2 date[1]
- X#define MTH1 date[3]
- X#define MTH2 date[4]
- X#endif
- X#define YR1 date[6]
- X#define YR2 date[7]
- X
- X/* --------------------
- X Get date from first argument; assumes format is one of
- XDate: Fri, 3 Apr 87 ... (a)
- XDate: Wed, 17 Jun 87 ... (b)
- XDate: 07 Sep 87 ... (c)
- XDate: Tue Sep 29 12:27:01 EST 1987 (d)
- X Dates are put into Imperial form (dd-mm-yy), or US form (mm-dd-yy)
- X if -DUSDATE is set.
- X
- X This routine should be more flexible re: recognizing date formats.
- X-------------------- */
- Xvoid
- Xget_date(str, date)
- X char *str, *date;
- X{
- X int i;
- X bool get_month();
- X char *next_token();
- X
- X date[2] = date[5] = '-';
- X date[8] = '\0';
- X for(; *str == ' ' || *str == '\t' ; str++)
- X ;
- X if(*str == '\0')
- X goto unknown;
- X if(! isdigit(*str)) /* day of month not first field */
- X str = next_token(str); /* skip day of week */
- X if(str == (char *) NULL + 1)
- X goto unknown;
- X
- X if(isdigit(*str)) { /* one of (a), (b) or (c) formats */
- X if(isdigit(*(str+1))) /* two-number date */
- X#ifdef USDATE
- X DAY1 = *str, DAY2 = *(++str);
- X else
- X DAY1 = '0', DAY2 = *str;
- X#else
- X DAY1 = (*str == '0') ? ' ' : *str, DAY2 = *(++str);
- X else
- X DAY1 = ' ', DAY2 = *str;
- X#endif
- X str = next_token(str); /* go to month */
- X if(str == (char *) NULL + 1)
- X goto unknown;
- X if(! get_month(str, date))
- X goto unknown;
- X str = next_token(str); /* go to year */
- X if(str == (char *) NULL + 1)
- X goto unknown;
- X if(! isdigit(*str) || ! isdigit(*(str+1)))
- X goto unknown;
- X YR1 = *str, YR2 = *(str+1);
- X } else { /* format (d) */
- X if(! get_month(str, date))
- X goto unknown;
- X str = next_token(str); /* go to day */
- X if(str == (char *) NULL + 1)
- X goto unknown;
- X if(! isdigit(*str) || ! isdigit(*(str+1)))
- X goto unknown;
- X#ifdef USDATE
- X DAY1 = *str, DAY2 = *(++str);
- X#else
- X DAY1 = (*str == '0') ? ' ' : *str, DAY2 = *(++str);
- X#endif
- X str += strlen(str) - 2; /* go to year */
- X if(! isdigit(*str) || ! isdigit(*(str+1)))
- X goto unknown;
- X YR1 = *str, YR2 = *(str+1);
- X }
- X return; /* date is ok */
- X
- Xunknown: /* erase date */
- X for(i=0 ; i < 8 ; i++)
- X date[i] = ' ';
- X}
- X
- X
- Xstatic char *month[] = {
- X "jan", "feb", "mar", "apr", "may", "jun",
- X "jul", "aug", "sep", "oct", "nov", "dec"
- X};
- X
- X/* --------------------
- X Put the month from the first part of str in date as a number.
- X-------------------- */
- Xbool
- Xget_month(str, date)
- X char *str, *date;
- X{
- X int i;
- X
- X for(i=0 ; i < 12 && lstrncmp(month[i], str, 3) != 0 ; i++)
- X ;
- X if(i == 12) /* string doesn't match month */
- X return(false);
- X else {
- X if(i < 9) /* single digit month */
- X#ifdef USDATE
- X MTH1 = ' ', MTH2 = i + '0' + 1;
- X#else
- X MTH1 = '0', MTH2 = i + '0' + 1;
- X#endif
- X else
- X MTH1 = '1', MTH2 = i + '0' - 9;
- X return(true);
- X }
- X}
- X
- X
- X/* --------------------
- X Replace tabs and newlines in string by spaces.
- X-------------------- */
- Xvoid
- Xflatten(str)
- X char *str;
- X{
- X char prev, *s = str;
- X
- X for(prev='\0' ; (*s = *str) != '\0' ; prev = *str, str++) {
- X if(*str == '\t')
- X *s = ' ';
- X if(prev != ' ' || *s != ' ')
- X s++;
- X }
- X}
- X
- X
- X/* --------------------
- X Return pointer to first non-white character in string.
- X-------------------- */
- Xchar *
- Xfirst(str)
- X char *str;
- X{
- X for(; *str == ' ' || *str == '\t' || *str == '\n' ; str++)
- X ;
- X return(str);
- X}
- X
- X
- X/* --------------------
- X Check given string for occurence of user's name.
- X-------------------- */
- Xint
- Xisuser(str)
- X char *str;
- X{
- X int len = strlen(user);
- X
- X for(; *str != '\0' ; str++)
- X /* assume all chars in all unames alphanumeric */
- X if(*str == *user && strncmp(str, user, len) == 0 &&
- X (*(str+len) < 'a' || *(str+len) > 'z') &&
- X (*(str+len) < 'A' || *(str+len) > 'Z') &&
- X (*(str+len) < '0' || *(str+len) > '9'))
- X return(true);
- X return(false);
- X}
- X
- X
- X/* --------------------
- X Make a new folder record.
- X-------------------- */
- Xfolder
- Xnew_folder(flr)
- X folder flr;
- X{
- X folder f;
- X
- X f = NEW(mail_folder);
- X f->prev = flr;
- X f->next = flr->next;
- X flr->next = f;
- X if(f->next != (folder) NULL)
- X f->next->prev = f;
- X f->pagenum = f->pages = flr->pages + 1;
- X f->name = flr->name;
- X f->valid = true;
- X f->mail = f->last = (item) NULL;
- X flr = f;
- X for(f=f->prev; f != (folder) NULL && f->name == flr->name ; f=f->prev)
- X f->pages = flr->pages;
- X return(flr);
- X}
- X
- X
- X/* --------------------
- X Find next free slot in directory for mail item (that is, find next
- X unused number) -- structures in vmail may not be up to date if user
- X has initiated a "send" process.
- X-------------------- */
- Xint
- Xnext_vacant(flr)
- X folder flr;
- X{
- X struct direct *dp, *readdir();
- X DIR *dirp, *opendir();
- X char str[LEN];
- X int i, n = 0;
- X
- X sprintf(str, "%s/%s", mail_dir, flr->name);
- X dirp = opendir(str);
- X for(dp=readdir(dirp) ; dp != (struct direct *) NULL ; dp=readdir(dirp)) {
- X /* ignore anything that is not string of digits */
- X if(! digits(dp->d_name))
- X continue;
- X if((i = atoi(dp->d_name)) > n)
- X n = i;
- X }
- X closedir(dirp);
- X return(n+1);
- X}
- !The!End!
-
- echo x - "low.c" 2>&1
- sed "s/^X//" >"low.c" <<'!The!End!'
- X/* --------------------
- X vmail -- low.c
- X
- X Low level screen update and data structure update routines, other
- X similar stuff.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X
- X/* --------------------
- X Get string from terminal (visibly).
- X-------------------- */
- Xvoid
- Xget_string(mes, str)
- X char *mes, *str;
- X{
- X char c;
- X int i;
- X
- X move(STATUS, 0);
- X clrtoeol();
- X addstr(mes);
- X refresh();
- X for(i=0 ; (c = getchar()) != '\n' && c != '\r' && c != ESC ; )
- X if(i > 0 && c == '\b') {
- X i--;
- X mvaddch(STATUS, strlen(mes)+i, ' ');
- X move(STATUS, strlen(mes)+i);
- X refresh();
- X } else if(c != '\b') {
- X str[i++] = c;
- X addch(c);
- X refresh();
- X }
- X str[i] = '\0';
- X move(y, 0);
- X}
- X
- X
- X/* --------------------
- X Put string on status line.
- X-------------------- */
- Xvoid
- Xaddstatus(str, stand)
- X char *str;
- X bool stand;
- X{
- X move(STATUS, 0);
- X clrtoeol();
- X if(stand)
- X standout(); /* doesn't do anything? */
- X addstr(str);
- X if(stand)
- X standend();
- X move(y, 0);
- X refresh();
- X}
- X
- X
- X/* --------------------
- X Fudge deleteline because curses wont delete the line immediately
- X after a ^Z, and because it doesnt clear the last line of the screen.
- X-------------------- */
- Xvoid
- Xdeleteline()
- X{
- X mvaddstr(y, 0, "scribble");
- X deleteln();
- X move(FIRST+lines-1, 0);
- X clrtoeol();
- X move(y, 0);
- X}
- X
- X
- Xint
- Xputch(c)
- X char c;
- X{
- X putchar(c); /* turn macro into routine */
- X}
- X
- X
- X/* --------------------
- X Put prompt on screen, wait for getchar().
- X-------------------- */
- Xint
- Xuse_prompt(win)
- X WINDOW *win;
- X{
- X int c = (cols-42)/2;
- X
- X mvwaddstr(win,FIRST+lines-1,c,"-- hit space to continue, q to quit -- ");
- X wrefresh(win);
- X return(getchar());
- X}
- X
- X
- X/* --------------------
- X Put info for mail item on screen at row i.
- X-------------------- */
- Xvoid
- Xshow_title(str, i, mail)
- X char *str;
- X int i;
- X item mail;
- X{
- X sprintf(str, "%4d%s", mail->number, mail->title);
- X mvaddstr(i, 0, str);
- X}
- X
- X
- X/* --------------------
- X Put header for page at top of screen.
- X-------------------- */
- Xvoid
- Xadd_page_header(str)
- X char *str;
- X{
- X sprintf(str, "%s (page %d of %d) ", curflr->name, curflr->pagenum,
- X curflr->pages);
- X mvaddstr(TITLE, 0, str);
- X}
- X
- X
- X/* --------------------
- X Flush typeahead.
- X-------------------- */
- Xchar
- Xflushin()
- X{
- X struct sgttyb sg;
- X
- X if(do_flush) {
- X ioctl(0, TIOCGETP, &sg);
- X ioctl(0, TIOCSETP, &sg);
- X }
- X return(getchar());
- X}
- X
- X
- X/* --------------------
- X Print message, wait for getchar();
- X-------------------- */
- Xvoid
- Xhold_end()
- X{
- X tputs(SO, 1, putch);
- X printf("-- any character to continue --");
- X tputs(SE, 1, putch);
- X fflush(stdout);
- X getchar();
- X}
- X
- X
- X#define ctol(c) (((c) >= 'A' && (c) <= 'Z') ? c-'A'+'a' : c)
- X
- X/* --------------------
- X Case independent strncmp.
- X-------------------- */
- Xlstrncmp(s1, s2, n)
- X char *s1, *s2;
- X int n;
- X{
- X for( ; ctol(*s1) == ctol(*s2) && n > 0 ; s1++, s2++, n--)
- X ;
- X return((n > 0) ? *s1 - *s2 : 0);
- X}
- X
- X
- X/* --------------------
- X String processing - more useful form of index.
- X Skip current non-white then skip white, replacing by null.
- X-------------------- */
- Xchar *
- Xnext_token(t)
- X char *t;
- X{
- X for( ; *t != ' ' && *t != '\t' && *t != '\0' ; t++)
- X ;
- X for( ; *t == ' ' || *t == '\t' ; t++)
- X *t = '\0';
- X return(t);
- X}
- !The!End!
-
- echo x - "main.c" 2>&1
- sed "s/^X//" >"main.c" <<'!The!End!'
- X/* --------------------
- X vmail -- main.c
- X
- X Definitions of global variables, main switch.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X
- Xfolder folders = (folder) NULL, curflr, alternate = (folder) NULL;
- Xitem curmail;
- Xchar *user, *pager = (char *) NULL, *editor = (char *) NULL,
- X *mail_dir = (char *) NULL, *shell = (char *) NULL, *context;
- Xbool top_level = true, do_flush = true, comp_args = true, repl_args = true,
- X forw_args = true;
- Xint lines, cols, y, folder_protect = FPROT;
- Xjmp_buf env;
- X
- X#define HELP 37
- X
- Xchar *help_scr[] = {
- X" . Re-execute last command (if one of acdDefirR)",
- X" (on repeat, r does not prompt for folder)",
- X" /<exp> Search forwards for title with <exp> (/ to repeat)",
- X" ?<exp> Search backwards for title with <exp> (? to repeat)",
- X" <space> Show current mail item",
- X" [n]<return> Go forward one (or n) active page(s) of mail items",
- X" [n]<backspace> Go back one (or n) active page(s) of mail items",
- X" ^L Refresh",
- X" ! Invoke shell",
- X" | Pipe current mail item into command",
- X" ^ Go to first active page",
- X" $ Go to last active page",
- X" a Answer current mail item (call to \"repl\")",
- X" c Compose new mail item (call to \"comp\")",
- X" C Go to folder chooser",
- X" [n]d Delete current (or next inclusive n) mail item(s)",
- X" D Delete current mail item, show next",
- X" e Edit current mail item",
- X" f Forward current mail item (call to \"forw\")",
- X" F List all folders",
- X" g,G Go to named (or alternate) folder",
- X" h Show this page",
- X" [n]H Go to top of page (or nth from top line)",
- X" i Incorporate new mail (call to \"inc\")",
- X" [n]j Move cursor down one (or n) line(s)",
- X" [n]k Move cursor up one (or n) line(s)",
- X" [n]L Go to bottom of page (or nth from bottom line)",
- X" M Go to middle of page",
- X" [n]n Go forward one (or n) folders, make new folder active",
- X" [n]p Go back one (or n) folders, make new folder active",
- X" P Print name of alternate folder",
- X" q Exit from vmail",
- X" r,R Refile item in named (or previous) folder",
- X" s Save current item in named file",
- X" u Undo most recent deletion (1 mail item only)",
- X" v Make current folder inactive",
- X" z Pack current folder"
- X};
- X
- X
- X#define USAGE printf( \
- X"Usage: vmail [-inc] [-flush] [-comp] [-forw] [-ans] [+curfolder] folders ...\n"), \
- X exit(1)
- X
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X char c, last = '\0', get_number(), flushin();
- X int count = 1, /* accumulate count to give to command */
- X pcount = 1;
- X bool flag = false; /* used to check whether to reset count */
- X
- X argc--, argv++;
- X
- X process_args(argc, argv);
- X#ifndef VERSION
- X#define VERSION "(local version)"
- X#endif
- X printf("vmail %s -- reading mail headers\n", VERSION);
- X init(argc, argv);
- X setjmp(env); /* return point from interrupt */
- X c = flushin();
- X for(;;) {
- X while(c == '.')
- X if(last == '\0') {
- X beep();
- X c = flushin();
- X } else {
- X count = pcount;
- X c = last;
- X }
- X switch(c) {
- X case '|': /* pipe mail to command */
- X do_pipe();
- X break;
- X case '!': /* call shell */
- X call_shell();
- X break;
- X case '/': /* search forwards */
- X search(true);
- X break;
- X case '?': /* search backwards */
- X search(false);
- X break;
- X case '^': /* first active page */
- X goto_first_page();
- X break;
- X case '$': /* last active page */
- X goto_last_page();
- X break;
- X case '\n': /* next folder */
- X case '\r': /* next folder */
- X next_page(count, true);
- X break;
- X case ' ': /* show current item */
- X show_mail();
- X break;
- X case DEL: /* previous folder */
- X case '\b': /* previous folder */
- X prev_page(count, true);
- X break;
- X case 'a': /* answer - call to repl */
- X repl();
- X break;
- X case 'c': /* compose - fork of comp */
- X comp();
- X break;
- X case 'C': /* go to folder chooser */
- X choose();
- X break;
- X case 'd': /* delete item */
- X delete_item(count);
- X break;
- X case 'D': /* delete item, show next */
- X change_item(false);
- X show_mail();
- X break;
- X case 'e': /* edit current mail item */
- X edit();
- X break;
- X case 'f': /* forward - call to forw */
- X forw();
- X break;
- X case 'F': /* list all folders */
- X list_folders();
- X break;
- X case 'g': /* go to named folder */
- X goto_folder(true);
- X break;
- X case 'G': /* go to last-named folder */
- X goto_folder(false);
- X break;
- X case 'h': /* help */
- X help();
- X break;
- X case 'H': /* go to top of page */
- X cursor_first(count);
- X break;
- X case 'i': /* inc */
- X inc();
- X break;
- X case 'j': /* cursor down */
- X cursor_down(count);
- X break;
- X case 'k': /* cursor up */
- X cursor_up(count);
- X break;
- X case CTRL_L: /* redraw */
- X display_page();
- X break;
- X case 'L': /* go to bottom of page */
- X cursor_last(count);
- X break;
- X case 'M': /* go to middle of page */
- X cursor_middle();
- X break;
- X case 'n': /* next folder - load if not there */
- X goto_next_folder(count);
- X break;
- X case 'p': /* prev folder - load if not there */
- X goto_prev_folder(count);
- X break;
- X case 'P': /* print name of last-named folder */
- X show_folder();
- X break;
- X case 'q': /* quit */
- X to_normal();
- X fix_mh();
- X exit(0);
- X break;
- X case 'r': /* move item to named folder */
- X move_item(true);
- X break;
- X case 'R': /* move item to previous folder */
- X move_item(false);
- X break;
- X case 's': /* save item in named file */
- X save_item();
- X break;
- X case 'u': /* undo */
- X undo();
- X break;
- X case 'v': /* make folder inactive */
- X inactive();
- X break;
- X case 'z': /* pack current folder */
- X pack_folder();
- X break;
- X case '0': /* start of count */
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X c = get_number(c, &count);
- X flag = true;
- X break;
- X default:
- X addstatus("command unknown -- `h' for help", true);
- X break;
- X }
- X switch(c) {
- X /* repeatable commands */
- X case 'r': /* refile item in named folder */
- X last = 'R';
- X pcount = 1;
- X break;
- X case 'a': /* reply - call to repl */
- X case 'c': /* compose - fork of comp */
- X case 'd': /* delete item */
- X case 'D': /* delete item, show next */
- X case 'e': /* edit current mail item */
- X case 'f': /* forward - call to forw */
- X case 'i': /* inc */
- X case 'R': /* refile to previous folder */
- X case 'w': /* write to file */
- X last = c;
- X pcount = count;
- X break;
- X default:
- X break;
- X }
- X if(!flag) {
- X c = flushin();
- X count = 1;
- X } else {
- X flag = false;
- X }
- X }
- X}
- X
- X
- X/* --------------------
- X Read a number from terminal.
- X-------------------- */
- Xchar
- Xget_number(c, count)
- X char c;
- X int *count;
- X{
- X *count = c - '0';
- X while((c = getchar()) >= '0' && c <= '9')
- X *count = *count * 10 + c - '0';
- X return(c);
- X}
- X
- X
- XWINDOW *helpwin = (WINDOW *) NULL;
- X
- X/* --------------------
- X Display help messages on help screen.
- X-------------------- */
- Xhelp()
- X{
- X WINDOW *newwin();
- X int i, j;
- X
- X if(helpwin == (WINDOW *) NULL)
- X helpwin = newwin(0, 0, 0, 0);
- X wclear(helpwin);
- X for(j=i=0 ; i <= HELP ; i++, j++) {
- X if((i+2) % lines == 0) {
- X if(use_prompt(helpwin) == 'q')
- X break;
- X j=0;
- X wclear(helpwin);
- X }
- X if(i >= HELP) {
- X use_prompt(helpwin);
- X break;
- X }
- X mvwaddstr(helpwin, j+1, 0, help_scr[i]);
- X }
- X display_page();
- X}
- X
- X
- X/* --------------------
- X Process arguments, command-line or given in profile.
- X-------------------- */
- Xvoid
- Xprocess_args(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X for( ; argc > 0 ; argc--, argv++)
- X if(!strcmp(argv[0], "-inc")) { /* incorporate mail before starting */
- X if(!vfork()) {
- X execlp(INC, INC, 0);
- X printf("Warning: can't execute %s\n", INC);
- X exit(0);
- X }
- X wait(0);
- X printf("\n");
- X } else if(!strcmp(argv[0], "-flush")) /* don't flush typeahead */
- X do_flush = false;
- X else if(!strcmp(argv[0], "-forw")) /* no args to forw */
- X forw_args = false;
- X else if(!strcmp(argv[0], "-comp")) /* no args to comp */
- X comp_args = false;
- X else if(!strcmp(argv[0], "-ans")) /* no args to repl */
- X repl_args = false;
- X else if(*argv[0] == '-') {
- X printf("%s: illegal option\n", argv[0]);
- X USAGE;
- X }
- X}
- !The!End!
-
- echo x - "move.c" 2>&1
- sed "s/^X//" >"move.c" <<'!The!End!'
- X/* --------------------
- X vmail -- move.c
- X
- X Routines to delete or move a mail item from current folder.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X#include <errno.h>
- X
- Xstatic char prevfile[LEN] = "";
- X
- Xextern int errno;
- X
- X/* --------------------
- X Move current item to folder prevfile (get_name = false) or as read from
- X terminal (get_name = true).
- X-------------------- */
- Xvoid
- Xmove_item(get_name)
- X bool get_name;
- X{
- X char *s, str[LEN], str2[LEN];
- X folder f, new_folder(), create_folder();
- X item m;
- X bool redraw, /* true if screen to be refreshed */
- X change_item();
- X int fdi, fdo, i = FIRST-1, num, N;
- X
- X /* get name if required */
- X if(get_name || *prevfile == '\0') {
- X get_string("folder? ", str);
- X if(*str == '\0') {
- X addstatus("no name given for folder", true);
- X return;
- X }
- X strcpy(prevfile, str);
- X } else
- X strcpy(str, prevfile);
- X /* find first page of named folder */
- X sprintf(str2, "refiling to %s ...", str);
- X addstatus(str2, false);
- X GOTO_NAME(f, str);
- X if(f == (folder) NULL) { /* create folder */
- X f = create_folder(str);
- X if(f == (folder) NULL)
- X return;
- X } else {
- X if(f->name == curflr->name) {
- X addstatus("can't move item to current folder", true);
- X return;
- X }
- X if(f->valid) { /* goto last mail item in folder */
- X LAST_OF_NAME(f);
- X for(i=FIRST, m=f->mail ; m->next != (item) NULL ; i++, m=m->next)
- X ;
- X }
- X }
- X /* remember current location of mail */
- X m = curmail;
- X num = curmail->number;
- X s = curflr->name;
- X /* delete item from current folder, update current folder & screen */
- X redraw = change_item(true);
- X if(f->valid) /* update structures of mail items */
- X if(i > lines) {
- X /* create new folder record */
- X f = new_folder(f);
- X f->mail = f->last = m;
- X m->prev = m->next = (item) NULL;
- X N = f->prev->last->number;
- X } else {
- X /* insert at end of list of mail items */
- X m->prev = f->last; m->next = (item) NULL;
- X f->last->next = m;
- X f->last = m;
- X N = m->prev->number;
- X }
- X else
- X N = next_vacant(f);
- X/* to avoid race between "send" or other process in background and vmail
- X foreground, compute next free slot, dont just use given value
- X*/
- X sprintf(str2, "%s/%s/%d", mail_dir, f->name, N);
- X /* loop until unused file name found */
- X for(errno=0 ; (fdo = open(str2, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0
- X && errno == EEXIST ; errno=0) {
- X N = N + 1;
- X sprintf(str2, "%s/%s/%d", mail_dir, f->name, N);
- X }
- X if(f->valid)
- X m->number = N;
- X sprintf(str, "%s/%s/%d", mail_dir, s, num);
- X fdi = open(str, O_RDONLY);
- X while((i = read(fdi, str2, LEN)) > 0) /* copy original to new */
- X write(fdo, str2, i);
- X close(fdi);
- X close(fdo);
- X unlink(str); /* remove original */
- X if(redraw)
- X display_page();
- X else {
- X add_page_header(str);
- X move(y, 0);
- X refresh();
- X }
- X addstatus("refiled", true);
- X if(curflr == (folder) NULL) {
- X to_normal();
- X exit(1);
- X }
- X}
- X
- X
- X/* --------------------
- X Delete count items.
- X-------------------- */
- Xvoid
- Xdelete_item(count)
- X int count;
- X{
- X bool redraw = false, change_item();
- X item m;
- X char str[LEN];
- X
- X for( ; count > 0 ; count--) {
- X m = curmail->next;
- X redraw = change_item(false);
- X if(redraw || m != curmail) /* on new page, or last item deleted */
- X break;
- X }
- X if(redraw)
- X display_page();
- X else {
- X add_page_header(str);
- X move(y, 0);
- X refresh();
- X }
- X}
- X
- X
- X/* --------------------
- X Structure for deleted item.
- X-------------------- */
- Xstruct {
- X folder flr;
- X int number;
- X} deleted = {(folder) NULL, 0};
- X
- X
- X/* --------------------
- X Either delete (do_move = false) or prepare to move (do_move = true) item.
- X Delete item from current folder, update screen, find new current folder
- X if current folder has become empty.
- X-------------------- */
- Xbool
- Xchange_item(do_move)
- X bool do_move;
- X{
- X item tmp, m = curmail;
- X folder F, p, f = curflr, pval, nval;
- X char s1[LEN], s2[LEN];
- X bool redraw, doexit = false;
- X
- X if(curmail->next == (item) NULL && curmail->prev == (item) NULL) {
- X /* have last item in page */
- X redraw = true;
- X pval = curflr->prev; PREV_VALID(pval);
- X nval = curflr->next; NEXT_VALID(nval);
- X if(pval == (folder) NULL && nval == (folder) NULL) {
- X /* no more active pages */
- X if(! do_move)
- X addstatus("Deleting last active mail item -- bye", true);
- X doexit = true;
- X } else {
- X /* update pages, pagenum */
- X for(p=curflr->prev ; p != (folder) NULL && p->name == curflr->name
- X ; p=p->prev)
- X p->pages -= 1;
- X for(p=curflr->next ; p != (folder) NULL && p->name == curflr->name
- X ; p=p->next)
- X p->pages -= 1, p->pagenum -= 1;
- X /* find next active page, drop current page from list */
- X if(curflr->prev != (folder) NULL)
- X curflr->prev->next = curflr->next;
- X else
- X folders = curflr->next;
- X if(curflr->next != (folder) NULL)
- X curflr->next->prev = curflr->prev;
- X curflr = (nval == (folder) NULL) ? pval : nval;
- X curmail = curflr->mail;
- X }
- X } else {
- X redraw = false;
- X deleteline();
- X /* move first item from next to current */
- X if(curflr->next != (folder) NULL && curflr->name == curflr->next->name)
- X show_title(s1, FIRST+lines-1, curflr->next->mail);
- X for(p=curflr->next ; p != (folder) NULL && p->name == curflr->name ;
- X p=p->next) {
- X tmp = p->mail;
- X p->mail = tmp->next;
- X if(p->mail == (item) NULL) { /* remove folder from list */
- X p->prev->next = p->next;
- X if(p->next != (folder) NULL)
- X p->next->prev = p->prev;
- X /* update page counts */
- X for(F=p->prev ; F != (folder) NULL && F->name == p->name
- X ; F=F->prev)
- X F->pages -= 1;
- X } else
- X p->mail->prev = (item) NULL;
- X p->prev->last->next = tmp;
- X tmp->prev = p->prev->last;
- X tmp->next = (item) NULL;
- X p->prev->last = tmp;
- X }
- X /* delete item from linked list of items */
- X if(m->prev == (item) NULL)
- X curflr->mail = m->next;
- X else
- X m->prev->next = m->next;
- X if(m->next == (item) NULL) {
- X curflr->last = m->prev;
- X curmail = m->prev;
- X y--;
- X } else {
- X m->next->prev = m->prev;
- X curmail = m->next;
- X }
- X move(y, 0);
- X }
- X if(! do_move) {
- X deleted.flr = f;
- X deleted.number = m->number;
- X sprintf(s1, "%s/%s/%d", mail_dir, f->name, m->number);
- X sprintf(s2, "%s/%s/#%d", mail_dir, f->name, m->number);
- X rename(s1, s2);
- X if(doexit) {
- X to_normal();
- X exit(0);
- X }
- X }
- X return(redraw);
- X}
- X
- X
- X/* --------------------
- X Create folder of given name if user agrees, creating directory and
- X entry in linked list of folders.
- X-------------------- */
- Xfolder
- Xcreate_folder(str)
- X char *str;
- X{
- X struct stat statbuf;
- X char str2[LEN], c;
- X folder fnew, p, f;
- X
- X squash(str);
- X sprintf(str2, "%s does not exist (or is empty) - create? ", str);
- X mvaddstr(STATUS, 0, str2); refresh();
- X c = getchar();
- X move(STATUS, 0); clrtoeol(); move(y, 0); refresh();
- X if(c != 'y')
- X return((folder) NULL);
- X for(p=(folder) NULL, f=folders ; f != (folder) NULL &&
- X strcmp(str, f->name) > 0 ; p=f, f=f->next)
- X ;
- X /* create physical folder */
- X sprintf(str2, "%s/%s", mail_dir, str);
- X if(stat(str2, &statbuf)) { /* doesn't exist */
- X if(mkdir(str2, folder_protect)) {
- X addstatus("Cannot make folder", true);
- X return((folder) NULL);
- X }
- X } else
- X if(!(statbuf.st_mode & S_IREAD) || !(statbuf.st_mode & S_IWRITE)
- X || !(statbuf.st_mode & S_IEXEC)) {
- X addstatus("Cannot write in folder", true);
- X return((folder) NULL);
- X }
- X /* make a new folder record, insert it */
- X fnew = NEW(mail_folder);
- X fnew->name = NEWSTR(strlen(str)+1);
- X strcpy(fnew->name, str);
- X fnew->mail = fnew->last = (item) NULL;
- X fnew->next = fnew->prev = (folder) NULL;
- X fnew->pages = fnew->pagenum = 1;
- X fnew->valid = false;
- X if(p == (folder) NULL) {
- X fnew->next = folders;
- X folders->prev = fnew;
- X folders = fnew;
- X } else {
- X p->next = fnew;
- X if(f != (folder) NULL)
- X f->prev = fnew;
- X fnew->prev = p;
- X fnew->next = f;
- X }
- X return(fnew);
- X}
- X
- X
- X/* --------------------
- X Crude undo. Sophisticated undo rather too painful to code.
- X-------------------- */
- Xvoid
- Xundo()
- X{
- X folder f = deleted.flr, p;
- X char s1[LEN], s2[LEN];
- X
- X if(f == (folder) NULL) {
- X addstatus("nothing to undo", true);
- X return;
- X } else {
- X addstatus("undoing ...", true);
- X deleted.flr = (folder) NULL;
- X }
- X sprintf(s1, "%s/%s/#%d", mail_dir, f->name, deleted.number);
- X sprintf(s2, "%s/%s/%d", mail_dir, f->name, deleted.number);
- X rename(s1, s2);
- X /* find first page of folder */
- X p = f; FRST_OF_NAME(p);
- X /* find last page of folder */
- X LAST_OF_NAME(f);
- X curflr = p;
- X p->next = f->next;
- X/* should free old folder/mail records */
- X/* p->valid = false; */
- X p->mail = p->last = (item) NULL;
- X p->pagenum = p->pages = 1;
- X if(p->next != (folder) NULL)
- X p->next->prev = p;
- X find_mail(curflr, false);
- X curmail = curflr->mail;
- X y = FIRST;
- X display_page();
- X}
- X
- X
- X/* --------------------
- X Pack current folder. Unsets "deleted" if last removed record was
- X on current folder.
- X-------------------- */
- Xvoid
- Xpack_folder()
- X{
- X folder f = curflr;
- X item m;
- X char path[LEN], s1[LEN], s2[LEN];
- X bool found;
- X int newnum = 1;
- X
- X addstatus("Packing folder ...", false);
- X FRST_OF_NAME(f);
- X /* unset undo if packing that folder */
- X if(deleted.flr != (folder) NULL && deleted.flr->name == curflr->name)
- X deleted.flr = (folder) NULL;
- X sprintf(path, "%s/%s/", mail_dir, curflr->name);
- X for( ; f != (folder) NULL && f->name == curflr->name ; f=f->next)
- X for(m=f->mail ; m != (item) NULL ; m=m->next) {
- X for(found=false ; !found && newnum < m->number ; ) {
- X sprintf(s1, "%s%d", path, newnum);
- X if(! access(s1, R_OK))
- X newnum++;
- X else
- X found = true;
- X }
- X if(found) {
- X sprintf(s2, "%s%d", path, m->number);
- X rename(s2, s1);
- X m->number = newnum;
- X }
- X }
- X display_page();
- X}
- !The!End!
-
- echo x - "page.c" 2>&1
- sed "s/^X//" >"page.c" <<'!The!End!'
- X/* --------------------
- X vmail -- page.c
- X
- X Routines for paging between folders.
- X
- X Copyright (C) J. Zobel, University of Melbourne, October 1987.
- X-------------------- */
- X
- X#include "defs.h"
- X
- X/* --------------------
- X Clear screen, show current page of mail items.
- X-------------------- */
- Xvoid
- Xdisplay_page()
- X{
- X int i;
- X item mail;
- X char str[LEN];
- X
- X clear();
- X add_page_header(str);
- X for(i=FIRST, mail=curflr->mail ; mail != (item) NULL ; i++, mail=mail->next)
- X show_title(str, i, mail);
- X move(y, 0);
- X refresh();
- X}
- X
- X
- X/* --------------------
- X Find previous valid page of mail items (times count).
- X-------------------- */
- Xvoid
- Xprev_page(count, display)
- X int count;
- X bool display;
- X{
- X bool show = false;
- X folder f, p = curflr;
- X
- X for( ; count > 0 ; count--) {
- X f = curflr->prev; PREV_VALID(f);
- X if(f == (folder) NULL)
- X break;
- X else {
- X show = true;
- X y = FIRST;
- X curflr = f;
- X curmail = curflr->mail;
- X }
- X }
- X if(p != curflr)
- X alternate = p;
- X if(display) {
- X if(show)
- X display_page();
- X if(f == (folder) NULL)
- X addstatus("first active page", true);
- X }
- X}
- X
- X
- X/* --------------------
- X Find next valid page of mail items (times count).
- X-------------------- */
- Xvoid
- Xnext_page(count, display)
- X int count;
- X bool display;
- X{
- X bool show = false;
- X folder f, p = curflr;
- X
- X for( ; count > 0 ; count--) {
- X f = curflr->next; NEXT_VALID(f);
- X if(f == (folder) NULL)
- X break;
- X else {
- X show = true;
- X y = FIRST;
- X curflr = f;
- X curmail = curflr->mail;
- X }
- X }
- X if(p != curflr)
- X alternate = p;
- X if(display) {
- X if(show)
- X display_page();
- X if(f == (folder) NULL)
- X addstatus("last active page", true);
- X }
- X}
- X
- X
- X/* --------------------
- X Move cursor up count lines.
- X-------------------- */
- Xvoid
- Xcursor_up(count)
- X int count;
- X{
- X bool redraw = false;
- X
- X addstatus("", false); /* clear status line */
- X for( ; count > 0 ; count--)
- X if(curmail->prev == (item) NULL) {
- X if(curflr->prev == (folder) NULL ||
- X curflr->name != curflr->prev->name) {
- X addstatus("first page of folder", true);
- X break;
- X } else {
- X redraw = true;
- X prev_page(1, false);
- X /* find last mail item on page */
- X for( ; curmail->next != (item) NULL ; y++)
- X curmail=curmail->next;
- X }
- X } else {
- X y--;
- X curmail = curmail->prev;
- X }
- X if(redraw)
- X display_page();
- X else {
- X move(y, 0);
- X refresh();
- X }
- X}
- X
- X
- X/* --------------------
- X Move cursor down count lines.
- X-------------------- */
- Xvoid
- Xcursor_down(count)
- X int count;
- X{
- X bool redraw = false;
- X
- X addstatus("", false); /* clear status line */
- X for( ; count > 0 ; count--)
- X if(curmail->next == (item) NULL) {
- X if(curflr->next == (folder) NULL ||
- X curflr->name != curflr->next->name) {
- X addstatus("last page of folder", true);
- X break;
- X } else {
- X redraw = true;
- X next_page(1, false);
- X }
- X } else {
- X y++;
- X curmail = curmail->next;
- X }
- X if(redraw)
- X display_page();
- X else {
- X move(y, 0);
- X refresh();
- X }
- X}
- X
- X
- X/* --------------------
- X Go to next folder, make active if not so already.
- X-------------------- */
- Xvoid
- Xgoto_next_folder(count)
- X int count;
- X{
- X bool changed = false;
- X folder f, p = curflr;
- X
- X for( ; count > 0 ; count--) {
- X /* skip other pages of current folder */
- X for(f=p ; p->next->name == f->name ; p=p->next)
- X ;
- X if(p->next == (folder) NULL) {
- X addstatus("last folder", true);
- X break;
- X } else {
- X changed = true;
- X p = p->next;
- X }
- X }
- X if(changed) {
- X do {
- X if(!p->valid) {
- X p->valid = true;
- X addstatus("reading mail headers ...", true);
- X find_mail(p, false);
- X }
- X if(p->valid == EMPTY)
- X p = p->next;
- X } while(p != (folder) NULL && p->valid != true);
- X if(p == (folder) NULL)
- X addstatus("can't go forward that many folders", true);
- X else {
- X alternate = curflr;
- X curflr = p;
- X curmail = p->mail;
- X y = FIRST;
- X display_page();
- X }
- X }
- X}
- X
- X
- X/* --------------------
- X Goto previous folder, make active if not so already.
- X-------------------- */
- Xvoid
- Xgoto_prev_folder(count)
- X int count;
- X{
- X bool changed = false;
- X folder f, p = curflr;
- X
- X for( ; count > 0 ; count--) {
- X /* skip other pages of current folder */
- X for(f=p ; p->prev->name == f->name ; p=p->prev)
- X ;
- X if(curflr->prev == (folder) NULL) {
- X addstatus("first folder", true);
- X break;
- X } else {
- X changed = true;
- X p = p->prev;
- X }
- X }
- X if(changed) {
- X do {
- X if(!p->valid) {
- X p->valid = true;
- X addstatus("reading mail headers ...", true);
- X find_mail(p, false);
- X }
- X if(p->valid == EMPTY)
- X p = p->prev;
- X } while(p != (folder) NULL && p->valid != true);
- X if(p == (folder) NULL)
- X addstatus("can't go back that many folders", true);
- X else {
- X /* skip other pages of current folder */
- X for(f=p ; p->prev->name == f->name ; p=p->prev)
- X ;
- X alternate = curflr;
- X curflr = p;
- X curmail = p->mail;
- X y = FIRST;
- X display_page();
- X }
- X }
- X}
- X
- X
- X/* --------------------
- X Make new folder current as specified - read from terminal (get_name =
- X true) or use value in alternate (get_name = false).
- X-------------------- */
- Xvoid
- Xgoto_folder(get_name)
- X bool get_name;
- X{
- X char buf[LEN], *str = buf;
- X folder f;
- X int i;
- X
- X if(get_name || alternate == (folder) NULL) {
- X /* no alternate folder */
- X get_string("folder? ", str);
- X for(i=0 ; *str == ' ' ; i++, str++)
- X ;
- X for(; i < LEN && buf[i] != ' ' && buf[i] != '\0' ; i++)
- X ;
- X if(i < LEN)
- X buf[i] = '\0';
- X GOTO_NAME(f, str);
- X if(f == (folder) NULL) {
- X addstatus("no such folder", true);
- X return;
- X }
- X if(!f->valid) {
- X f->valid = true;
- X addstatus("reading mail headers ...", true);
- X find_mail(f, false);
- X if(f->valid == EMPTY) {
- X sprintf(str, "%s -- folder empty", f->name);
- X addstatus(str, true);
- X return;
- X }
- X }
- X } else
- X f = alternate;
- X if(f == curflr)
- X addstatus("already in that folder", true);
- X else {
- X alternate = curflr;
- X curflr = f;
- X curmail = f->mail;
- X y = FIRST;
- X display_page();
- X }
- X}
- X
- X
- X/* --------------------
- X Go to first line of page, as offset by count.
- X-------------------- */
- Xvoid
- Xcursor_first(count)
- X int count;
- X{
- X item m = curflr->mail;
- X
- X addstatus("", false); /* clear status line */
- X for(y=FIRST ; m != (item) NULL && count > 1 ; count--, y++, m=m->next)
- X ;
- X if(m == (item) NULL)
- X beep();
- X else {
- X curmail = m;
- X move(y, 0);
- X refresh();
- X }
- X}
- X
- X
- X/* --------------------
- X Go to middle line of page.
- X-------------------- */
- Xvoid
- Xcursor_middle()
- X{
- X item m, p;
- X bool tog = false;
- X
- X addstatus("", false); /* clear status line */
- X /* find middle of page - p traverses page at half speed */
- X for(y=FIRST, m=p=curflr->mail ; m != (item) NULL ; m=m->next, tog= !tog)
- X if(tog) {
- X y++;
- X p = p->next;
- X }
- X curmail = p;
- X move(y, 0);
- X refresh();
- X}
- X
- X
- X/* --------------------
- X Go to last line of page, as offset by count.
- X-------------------- */
- Xvoid
- Xcursor_last(count)
- X int count;
- X{
- X item m = curflr->mail;
- X
- X addstatus("", false); /* clear status line */
- X /* find last item, including y-value */
- X for(y=FIRST ; m->next != (item) NULL ; y++, m=m->next)
- X ;
- X for(; m != (item) NULL && count > 1 ; count--, y--, m=m->prev)
- X ;
- X if(m == (item) NULL)
- X beep();
- X else {
- X curmail = m;
- X move(y, 0);
- X refresh();
- X }
- X}
- X
- X
- X/* --------------------
- X Go to first page. ***should use count as offset***
- X-------------------- */
- Xvoid
- Xgoto_first_page()
- X{
- X folder f;
- X
- X f = folders; NEXT_VALID(f);
- X if(f == (folder) NULL) {
- X /* no valid folders - bleah?! */
- X addstatus("no valid folders, exiting", true);
- X to_normal();
- X exit(1);
- X } else if(f != curflr) {
- X alternate = curflr;
- X curflr = f;
- X curmail = f->mail;
- X y = FIRST;
- X display_page();
- X }
- X}
- X
- X
- X/* --------------------
- X Go to last page. ***should use count as offset***
- X-------------------- */
- Xvoid
- Xgoto_last_page()
- X{
- X folder f, p;
- X
- X for(f=folders ; f != (folder) NULL ; f=f->next)
- X if(f->valid)
- X p = f;
- X if(p == (folder) NULL) {
- X /* no valid folders - bleah?! */
- X addstatus("no valid folders, exiting", true);
- X to_normal();
- X exit(1);
- X } else if(p != curflr) {
- X alternate = curflr;
- X curflr = p;
- X curmail = p->mail;
- X y = FIRST;
- X display_page();
- X }
- X}
- !The!End!
- exit
-
-
-