home *** CD-ROM | disk | FTP | other *** search
- From: argv@zipcode.com (Dan Heller)
- Newsgroups: comp.sources.misc
- Subject: v18i063: mush - Mail User's Shell, Part06/22
- Message-ID: <1991Apr21.024958.11318@sparky.IMD.Sterling.COM>
- Date: 21 Apr 91 02:49:58 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: 30d30a46 16880541 f8e371cd c77b71a9
-
- Submitted-by: Dan Heller <argv@zipcode.com>
- Posting-number: Volume 18, Issue 63
- Archive-name: mush/part06
- Supersedes: mush: Volume 12, Issue 28-47
-
- #!/bin/sh
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file curs_io.c continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 6; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping curs_io.c'
- else
- echo 'x - continuing file curs_io.c'
- sed 's/^X//' << 'SHAR_EOF' >> 'curs_io.c' &&
- X struct cmd_map *list;
- X
- X literal_next = FALSE;
- X if (iscntrl(c) || c == del_line || c == del_char || c == del_word
- X || c == lit_next || lit_bs)
- X if (!in_macro() || !lit_bs)
- X backspace(String, &count);
- X else
- X --count;
- X else if (in_macro() && c == MAC_LONG_CMD)
- X --count;
- X /* check to see if user is escaping a map or map! */
- X else
- X for (list = curr_map; list; list = list->m_next)
- X if (list->m_str[0] == c) {
- X if (!in_macro())
- X backspace(String, &count);
- X else
- X --count;
- X break;
- X }
- X /* A literal-next advances the macro offset */
- X String[count++] = c;
- X if (iscntrl(c) || c == del_char) {
- X if (iscntrl(c)) {
- X /*
- X * Decrement wrapcolumn because two chars added.
- X * It will be restored from save_wc before return.
- X */
- X if (wrapcolumn > 1)
- X wrapcolumn--;
- X Addch('^');
- X }
- X Addch(_unctrl[c][1]);
- X } else
- X Addch(c);
- X } else if (complete && (c == complete || c == complist)) {
- X (void) completion(String, &count, (c == complist), (c == complete));
- X } else if (c == del_line) {
- X if (count) {
- X do
- X backspace(String, &count);
- X while (count);
- X }
- X } else if (c == reprint_line)
- X String[count] = 0, wprint("\n%s", String);
- X else if (c == del_word) /* word erase */
- X while (count) {
- X backspace(String, &count);
- X if (!count ||
- X isspace(String[count-1]) && !isspace(String[count]) ||
- X !isalnum(String[count-1]) && isalnum(String[count]))
- X break;
- X }
- X else if (c == del_char || c == CTRL('H') || c == 127 /* CTRL('?') */) {
- X if (count)
- X backspace(String, &count);
- X /* if iscurses, then backspacing too far cancels a function */
- X else if (!count && iscurses && isoff(glob_flags, LINE_MACRO)) {
- X mac_flush();
- X String[0] = '\0';
- X wrapcolumn = save_wc;
- X return -1;
- X }
- X } else if (count == length)
- X bell();
- X else if (c == '\t')
- X do {
- X /* Yuck -- tabs break map! */
- X Addch(' ');
- X String[count] = ' ';
- X } while (++count % 8 && count < length);
- X else if (in_macro() && c == MAC_LONG_CMD) {
- X char cbuf[MAX_LONG_CMD + 1];
- X
- X if ((c = read_long_cmd(cbuf)) == 0) {
- X c = MAC_LONG_CMD;
- X goto check_expand; /* How could I avoid this? */
- X } else if (c > 0) {
- X int ok;
- X
- X String[count] = '\0';
- X if ((ok = reserved_cmd(cbuf, TRUE)) > 0) {
- X /* Reprint the line */
- X if (iscurses)
- X print(":%s", String);
- X else
- X wprint("\r%s", String);
- X continue; /* Get next char without changing count */
- X } else if (ok < 0) {
- X String[offset] = '\0';
- X wrapcolumn = save_wc;
- X return ok;
- X } else
- X goto push_back;
- X } else {
- X /*
- X * Ooops. We read a bunch of stuff we should not
- X * have read, because this isn't really a long command.
- X * Use a trick to push the whole thing back, ala ungetc.
- X * Wouldn't it be nifty if stdio worked this way? :-)
- X */
- push_back:
- X if (c > 0) {
- X cbuf[c++] = MAC_LONG_END;
- X cbuf[c] = '\0';
- X }
- X c = MAC_LONG_CMD;
- X Ungetstr(cbuf);
- X goto check_expand; /* How could I avoid this goto? */
- X }
- X } else {
- check_expand:
- X if (!curr_map || !check_map(c, curr_map)) {
- X /* else if (match != MATCH) */
- X if (c != '\t' && iscntrl(c)) {
- X Addch('^');
- X Addch(_unctrl[c][1]);
- X /* Decrement wrapcolumn as above */
- X if (wrapcolumn > 1)
- X wrapcolumn--;
- X } else
- X Addch(c);
- X String[count++] = c;
- X }
- X }
- X /* Null-terminate for macro lookup purposes.
- X * This will be overwritten by the next character.
- X */
- X String[count] = '\0';
- X if (line_wrap(String, &count))
- X break;
- X }
- X (void) fflush(stdout); /* for sys-v folks */
- X
- X if (c == eofc || c == EOF || ison(glob_flags, WAS_INTR)) {
- X if (feof(stdin))
- X clearerr(stdin);
- X wrapcolumn = save_wc;
- X return -1;
- X }
- X if (count && String[count-1] == '\\') {
- X int count2;
- X if (isoff(glob_flags, ECHO_FLAG))
- X putchar('\n');
- X wrapcolumn = save_wc;
- X /*
- X * NOTE: If the offset passed here is ever made greater than 0,
- X * the value of wrapcolumn must again be changed/restored ...
- X */
- X if ((count2 = Getstr(&String[count-1], length - count + 1, 0)) == -1)
- X return -1;
- X return count + count2;
- X }
- X if (!iscurses && isoff(glob_flags, ECHO_FLAG))
- X putchar('\n');
- X /* Should be null-terminated already, but just in case */
- X String[count] = '\0';
- X wrapcolumn = save_wc;
- X return count;
- }
- X
- static
- backspace(str, n)
- register char *str;
- int *n;
- {
- X (*n)--;
- X Addch('\b'); Addch(' '); Addch('\b');
- X if (iscntrl(str[*n])) {
- X Addch('\b'); Addch(' '); Addch('\b');
- X /* Re-increment wrapcolumn -- see Getstr */
- X if (wrapcolumn)
- X wrapcolumn++;
- X }
- }
- X
- #undef Addch
- X
- /*
- X * Check to see if what the user is typing is supposed to be expanded
- X * into a longer string. The first char is 'c' and the map list to use
- X * is in map_list. Continue looping (reading chars from stdin or a
- X * currently active mapping) until a match happens or we've determined
- X * that there is no match.
- X */
- check_map(c, map_list)
- char c;
- struct cmd_map *map_list;
- {
- X char mbuf[MAX_MACRO_LEN], *p = mbuf;
- X struct cmd_map *list;
- X int m, n, match;
- X
- X *p++ = c;
- X
- X while (isoff(glob_flags, WAS_INTR)) {
- X m = 0;
- X *p = 0; /* make sure it's null terminated */
- X /*
- X * loop thru the list of maps and check to see if the typed
- X * char matches the mapping. If it matches completely, substitute
- X * the stuff in x_str and return. If a partial match occurs, then
- X * read the next char until a timeout or no match.
- X */
- X for (list = map_list; list; list = list->m_next) {
- X if ((match = prefix(mbuf, list->m_str)) == MATCH) {
- X /* Must turn on flags BEFORE pushing */
- X line_macro(list->x_str);
- X return 1;
- X } else if (match != NO_MATCH)
- X m++; /* something matched partially */
- X }
- X if (!m)
- X break;
- X /* see if there's anything on the queue to read... */
- X if (mac_pending()
- #if !defined(SELECT) && !defined(M_UNIX)
- #ifdef FIONREAD
- X || !ioctl(0, FIONREAD, &n) && n > 0
- #else
- #ifdef M_XENIX
- X || rdchk(0) > 0
- #endif /* M_XENIX */
- #endif /* FIONREAD */
- #endif /* SELECT */
- X )
- X *p++ = m_getchar();
- X else {
- X /* The user has typed the first part of a map or macro. Give him
- X * a chance to finish it.
- X */
- #if defined(BSD) || defined(M_UNIX) || defined(SELECT)
- X /* If the system has select(), use it. It's much faster and
- X * more aesthetic since there is no mandatory timeout.
- X */
- X struct timeval timer;
- #ifdef FD_SET
- X fd_set rmask, wmask, xmask;
- X FD_SET(0, &rmask); /* Test stdin for read */
- X FD_ZERO(&wmask); /* Don't care about write */
- X FD_ZERO(&xmask); /* Don't care about exception */
- #else
- X int rmask = 1, wmask = 0, xmask = 0;
- #endif /* FD_SET */
- X timer.tv_sec = 1;
- X timer.tv_usec = 0;
- X n = select(1, &rmask, &wmask, &xmask, &timer);
- #else /* !SELECT */
- #ifdef FIONREAD
- X /* system doesn't have select(), so use FIONREAD to see if
- X * there are any chars on the queue to read.
- X */
- X (void) sleep(1);
- X (void) ioctl(0, FIONREAD, &n);
- #else
- #ifdef M_XENIX
- X (void) sleep(1);
- X n = rdchk(0);
- #else
- X
- X /* system has neither select() nor FIONREAD, so just set n
- X * and force the user to either complete the map or fail it
- X * without a timeout. Chars won't echo till he does one or
- X * the other.
- X */
- X n = 1;
- #endif /* M_XENIX */
- #endif /* FIONREAD */
- #endif /* SELECT */
- X if (n > 0)
- X /* don't read all 'n' chars -- there may be a match early */
- X *p++ = m_getchar(); /* To flush macros and reset flags */
- X else /* still nothing to read? User doesn't want to use map */
- X break;
- X }
- X }
- X /* no match or a timeout. This isn't a map, just return. */
- X *p = 0;
- X if (mbuf[1])
- X (void) mac_push(mbuf + 1);
- X return 0;
- }
- X
- /*
- X * Check for line wrap. This should happen only in composition mode and
- X * only when the variable wrapcolumn has a value greater than zero. Line
- X * wrap is implemented using Ungetstr [that is, mac_push()].
- X *
- X * Returns 1 if the line was wrapped, 0 if not.
- X */
- line_wrap(string, count)
- char *string; /* The string to be wrapped */
- int *count; /* Offset of string terminator */
- {
- X char *tail = NULL;
- X int n = *count;
- X
- X if (wrapcolumn < 1 || *count <= wrapcolumn
- X || isoff(glob_flags, IS_GETTING) /* Wrap only in msg body */
- X || ison(glob_flags, QUOTE_MACRO) /* Don't wrap quoted macros */
- X || ison(glob_flags, ECHO_FLAG)) /* Can't wrap in echo mode */
- X return 0;
- X
- X /* Back up past the wrapcolumn point */
- X for (; n > wrapcolumn; --n)
- X ;
- X /* Look for a space */
- X while (n && !isspace(string[n]))
- X --n;
- X /* If no break found, return no wrap */
- X if (!n)
- X return 0;
- X tail = &string[n+1];
- X /* Skip the break char and any whitespace */
- X while (n && isspace(string[n]))
- X --n;
- X ++n; /* move back into the whitespace */
- X /* Erase the stuff that will wrap */
- X while (*count > n)
- X backspace(string,count);
- X string[*count] = '\0';
- X /* Push the tail, if any */
- X if (*tail)
- X Ungetstr(tail);
- X return 1;
- }
- X
- /*
- X * Error bell used by completion()
- X */
- errbell(ret)
- int ret;
- {
- X if (ret < 0 || !chk_option("quiet", "complete,completion"))
- X bell();
- X return ret;
- }
- X
- /*
- X * Perform word completion on the input string
- X */
- completion(string, count, showlist, ignore)
- char *string; /* The string to be completed */
- int *count; /* Offset of string terminator */
- int showlist; /* Display list, complete if also ignore */
- int ignore; /* Ignore the fignore matches, do complete */
- {
- X char buf[MAXPATHLEN], *b = buf, **exp;
- X int n = *count, f, len, prefix, trim, overstrike, expandall;
- X
- X if (!*string || !*count)
- X return errbell(-1);
- X
- X /* Look for a delimiter */
- X while (n > 0 && !index(DELIM, string[--n]))
- X ;
- X if (n > 0 || index(DELIM, string[n]))
- X n++;
- X b = buf + (len = Strcpy(buf, &string[n]));
- X Debug("\nexpanding (%s) ... ", buf);
- X if (!any(buf, FMETA)) {
- X expandall = 0;
- X overstrike = (*buf == '+' || *buf == '~' || *buf == '%');
- X trim = (overstrike && len > 1);
- X if (!overstrike || len > 1 || (*buf == '+' && showlist))
- X *b++ = '*', *b = 0;
- X /* Previous behavior for '+' completions (trailing '/'):
- X if (len > 1 || *buf != '~' || *buf != '%')
- X *b++ = '*', *b = 0;
- X */
- X f = filexp(buf, &exp);
- X if (*--b == '*')
- X *b = 0; /* We need the original buf below */
- X } else {
- X overstrike = 1;
- X trim = (*buf == '+' || *buf == '~');
- X /*
- X * Check first to see if the base pattern matches.
- X * If not, append a '*' and try again.
- X * Don't expand all matches in the latter case.
- X */
- X if ((f = filexp(buf, &exp)) < 1) {
- X *b++ = '*', *b = 0;
- X f = filexp(buf, &exp);
- X *--b = 0; /* We need the original buf below */
- X expandall = 0;
- X } else
- X expandall = !showlist;
- X }
- X if (ignore)
- X f = fignore(f, &exp);
- X if (f < 0) {
- X Debug("globbing error!\n%s", string);
- X free_vec(exp);
- X return errbell(-1);
- X } else if (f > 0) {
- X Debug("result is: "), print_argv(exp);
- X if (!expandall && f > 1)
- X prefix = lcprefix(exp, overstrike ? 0 : len);
- X else
- X prefix = 0;
- X if (showlist && (f > 1 || !ignore)) {
- X int pfx = prefix;
- X if (!expandall)
- X while (pfx && exp[0][pfx - 1] != '/')
- X --pfx;
- X putchar('\n');
- X if (columnate(f, exp, pfx) < 0)
- X (void) errbell(-1);
- X /* Reprint the line */
- X if (iscurses) {
- X wprint(":%s", string);
- X turnon(glob_flags, CNTD_CMD);
- X } else {
- X if (isoff(glob_flags, IS_GETTING))
- X mail_status(1);
- X wprint("%s", string);
- X }
- X if (!ignore)
- X overstrike = 0;
- X }
- X if (ignore || !showlist) {
- X if (expandall || strlen(exp[0]) > len) {
- X if (!showlist)
- X Debug("%s", string);
- X if (overstrike && (prefix || expandall || f == 1)) {
- X char *tmpv[3];
- X tmpv[0] = buf;
- X if (trim)
- X tmpv[1] = trim_filename(exp[0]);
- X else
- X tmpv[1] = exp[0];
- X tmpv[2] = NULL;
- X /* Back up as far as is necessary */
- X len = lcprefix(tmpv, 0);
- X /* If nothing will be erased, we may need to beep */
- X if (n + len == *count) {
- X if (!expandall && !tmpv[1][len])
- X (void) errbell(0);
- X }
- X /* Erase the stuff that will complete */
- X while (*count > n + len)
- X backspace(string,count);
- X string[*count] = '\0';
- X }
- X if (expandall || f == 1) {
- X /* Unget the names IN REVERSE ORDER! */
- X while (f--) {
- X if (trim)
- X b = trim_filename(exp[f]);
- X else
- X b = exp[f];
- X if (f) {
- X Ungetstr(b);
- X Ungetstr(" ");
- X } else
- X Ungetstr(b + len);
- X }
- X } else {
- X if (prefix > len) {
- X exp[0][prefix] = 0;
- X if (!showlist)
- X Debug("\ncompletion is (%s)\n%s", exp[0], string);
- X if (trim)
- X Ungetstr(trim_filename(exp[0]) + len);
- X else
- X Ungetstr(&exp[0][len]);
- X } else if (!showlist)
- X Debug("\nno longer prefix\n%s", string);
- X /* Special case because "+" always tries to expand "+*"
- X * to get listings and avoid getpath()'s trailing '/'.
- X * No error bell is needed in those cases.
- X */
- X if (strcmp(buf, "+") != 0)
- X (void) errbell(0);
- X }
- X } else {
- X Debug("no longer prefix\n%s", string);
- X (void) errbell(0);
- X }
- X }
- X } else {
- X Debug("no match\n%s", string);
- X (void) errbell(0);
- X }
- X free_vec(exp);
- X return 1;
- }
- X
- fignore(argc, argvp)
- int argc;
- char ***argvp;
- {
- X char *fign = do_set(set_options, "fignore");
- X char **flist, buf[MAXPATHLEN], *b = buf;
- X int fcnt, i;
- X
- X if (argc < 2 || !fign || !*fign)
- X return argc;
- X if (!argvp || !*argvp && !**argvp)
- X return -1;
- X
- X if ((flist = mk_argv(fign, &fcnt, FALSE)) && fcnt > 0) {
- X *b++ = '*';
- X for (i = 0; i < fcnt; i++) {
- X if (flist[i][0] == '.' && !any(flist[i], FMETA)) {
- X (void) strcpy(b, flist[i]);
- X (void) strdup(flist[i], buf);
- X }
- X }
- X Debug("ignoring "), print_argv(flist);
- X fcnt = gdiffv(argc, argvp, fcnt, flist);
- X free_vec(flist);
- X if (fcnt == 0)
- X fcnt = argc;
- X else {
- X free_elems(&((*argvp)[fcnt]));
- X (*argvp)[fcnt] = NULL;
- X }
- X }
- X return fcnt;
- }
- SHAR_EOF
- echo 'File curs_io.c is complete' &&
- chmod 0644 curs_io.c ||
- echo 'restore of curs_io.c failed'
- Wc_c="`wc -c < 'curs_io.c'`"
- test 18325 -eq "$Wc_c" ||
- echo 'curs_io.c: original size 18325, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= curses.c ==============
- if test -f 'curses.c' -a X"$1" != X"-c"; then
- echo 'x - skipping curses.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting curses.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'curses.c' &&
- /* @(#)curses.c (c) copyright 3/18/87 (Dan Heller) */
- X
- /* curses.c -- routine to deal with the curses interface */
- #ifdef CURSES
- X
- #include "mush.h"
- #include "bindings.h"
- X
- curses_init(argc, argv)
- register char **argv;
- {
- X char buf[80];
- X extern char *UP;
- #ifndef M_UNIX
- X extern char ttytype[];
- #endif /* M_UNIX */
- X
- X if (argv && *++argv && !strcmp(*argv, "-?"))
- X return help(0, "curses", cmd_help);
- #ifdef SUNTOOL
- X if (istool) {
- X print("Sorry, can't change to curses mode from tool.\n");
- X return -1;
- X } else
- #endif /* SUNTOOL */
- X if (!is_shell) {
- X /*
- X * Can't start curses, but we can prepare to.
- X * Also allow -C switch to be shut off.
- X */
- X if (argv && *argv && !lcase_strncmp(*argv, "off", -1))
- X turnoff(glob_flags, PRE_CURSES);
- X else
- X turnon(glob_flags, PRE_CURSES);
- X return 0;
- X } else if (argc && (iscurses || ison(glob_flags, PRE_CURSES))) {
- X print("You are already using curses mode.\n");
- X return -1;
- X } else if (ison(glob_flags, IS_GETTING)) {
- X print("Finish your letter first.\n");
- X return -1;
- X }
- X
- #ifndef attrset /* terminfo version of curses */
- X /* you can not start curses in no echo mode.. must be in normal mode */
- X echom();
- X nocrmode();
- #endif /* attrset */
- X (void) initscr();
- #ifdef SIGCONT
- X /* initscr will play with signals -- make sure they're set right. */
- X (void) signal(SIGTSTP, stop_start);
- X (void) signal(SIGCONT, stop_start);
- #endif /* SIGCONT */
- #if !defined(SYSV) && !defined(USG)
- X if (!UP || !*UP)
- #else /* ~SYSV && ~USG */
- X if (!stdscr)
- #endif /* ~SYSV && ~USG */
- X {
- X print("Terminal type %s can not use the curses interface.\n", ttytype);
- X return -1;
- X }
- X iscurses = TRUE;
- X noechom(); /* reset tty state -- */
- X crmode(); /* do not use "echo_on/off()" */
- X scrollok(stdscr, TRUE);
- X /* if the user hasn't set his screen explicitly, set it for him */
- X set_screen_size();
- X if (crt > LINES - 1 || !do_set(set_options, "crt")) {
- X crt = LINES;
- X (void)cmd_line(sprintf(buf, "\\set screen = %d crt = %d", screen, crt),
- X msg_list);
- X } else
- X (void)cmd_line(sprintf(buf, "\\set screen = %d", screen), msg_list);
- X if (argc) {
- X (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1), msg_list);
- X (void) curses_help_msg(TRUE);
- X }
- X if (!do_set(set_options, "no_reverse"))
- X turnon(glob_flags, REV_VIDEO);
- X turnoff(glob_flags, CONT_PRNT);
- X return 0; /* doesn't affect messages */
- }
- X
- struct cmd_map *active_cmd; /* See bindings.h for description */
- X
- /*
- X * get input in cbreak mode and execute the appropriate command.
- X * when the command is done (usually), the user is prompted to
- X * hit any key to continue. At this point, the user may enter a
- X * new command so no screen refreshing needs to be done. This
- X * new command is returned to caller and may be passed back.
- X *
- X * The flag CNTD_CMD (continued command) is set if
- X * this routine is called with the passed parameter (c) != 0. If
- X * so, then the character passed is the character input by the
- X * user at the last "hit return" prompt indicating that he wants
- X * to execute a new command and not draw the screen.
- X *
- X * CNTD_CMD is also set if the command that the user invokes
- X * causes any sort of output that requires a screen refresh. The
- X * variable redo is set to 1 if the header page not only requires
- X * redrawing, but updating ... (new call to do_hdrs)
- X *
- X * calls that say: print("%s", compose_hdr(current_msg)) are constructed
- X * that way because if the header has a `%' in it, then print will try to
- X * expand it.
- X */
- curses_command(c)
- register int c;
- {
- X char buf[BUFSIZ], file[128], list[128];
- X int n, curlin;
- X static int redo = 0; /* set if headers should be redrawn */
- X
- X if (c != 0)
- X turnon(glob_flags, CNTD_CMD);
- X else
- X turnoff(glob_flags, CNTD_CMD);
- X clear_msg_list(msg_list); /* play it safe */
- X if (isoff(glob_flags, CNTD_CMD)) {
- X (void) check_new_mail();
- X curlin = max(1, current_msg - n_array[0] + 1);
- X if (ison(glob_flags, REV_VIDEO) && msg_cnt) {
- X scrn_line(curlin, buf);
- X STANDOUT(curlin, 0, buf);
- X }
- X mail_status(0);
- X move(curlin, 0), refresh();
- X /* reprint to remove reverse video from current line (don't refresh) */
- X if (ison(glob_flags, REV_VIDEO) && msg_cnt)
- X mvaddstr(curlin, 0, buf);
- X c = getcmd(); /* get input AFTER line redrawn without reverse video */
- X }
- X buf[0] = list[0] = file[0] = '\0';
- X
- X if (c == C_WRITE_LIST || c == C_SAVE_LIST || c == C_COPY_LIST
- X || c == C_DELETE_LIST || c == C_UNDEL_LIST) {
- X if (msg_cnt < 1) {
- X mac_flush();
- X print("Not enough messages.");
- X c = C_NULL;
- X } else if (c == C_DELETE_LIST && ison(glob_flags, READ_ONLY)) {
- X mac_flush();
- X print("Folder is read-only.");
- X c = C_NULL;
- X } else if (!curses_msg_list(sprintf(buf, "%s msg list: ",
- X (c == C_WRITE_LIST)? "write" : (c == C_SAVE_LIST)? "save" :
- X (c == C_COPY_LIST)? "copy" :
- X (c == C_DELETE_LIST)? "delete" : "undelete"), list, msg_list))
- X c = C_NULL;
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X }
- X
- X /* first do non-mail command type stuff */
- X switch (c) {
- X case C_ERROR :
- X bell();
- X mac_flush();
- X
- X when C_NULL :
- X if (isoff(glob_flags, CNTD_CMD))
- X bell();
- X
- X /* goto a specific message number */
- X when C_GOTO_MSG :
- X if (curses_msg_list(strcpy(buf, "goto msg: "), list, msg_list)) {
- X /*
- X * Reset the current message in case a
- X * backquoted command (like `from`) changed it
- X */
- X n = current_msg;
- X do if (++n >= msg_cnt)
- X n = 0;
- X while (n != current_msg && !msg_bit(msg_list, n));
- X if (n == current_msg && !msg_bit(msg_list, n)) {
- X mac_flush(); /* bail out if in macro processing */
- X print("Message not found.");
- X }
- X else if ((current_msg = n) < n_array[0]
- X || n > n_array[screen-1])
- X redo = 1;
- X } else {
- X mac_flush();
- X bell();
- X }
- X if (ison(glob_flags, CNTD_CMD) && msg_cnt)
- X print("%-.*s", COLS-2, compose_hdr(current_msg));
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X
- X /* screen optimization stuff */
- X when C_REVERSE :
- X if (ison(glob_flags, REV_VIDEO))
- X turnoff(glob_flags, REV_VIDEO);
- X else
- X turnon(glob_flags, REV_VIDEO);
- X
- X when C_REDRAW : redo = 1;
- X
- X /*
- X * screen movement
- X */
- X when C_NEXT_MSG :
- X if (current_msg + 2 > msg_cnt ||
- X isoff(glob_flags, CNTD_CMD) && curlin == LINES-2) {
- X mac_flush(); /* Bail out if in macro processing */
- X bell(); /* reached the end */
- X } else {
- X if (ison(glob_flags, CNTD_CMD)) {
- X if (++current_msg > n_array[screen-1])
- X redo = 1;
- X print("%-.*s", COLS-2, compose_hdr(current_msg));
- X putchar('\n');
- X } else {
- X if (++current_msg > n_array[screen-1])
- X n_array[screen++] = current_msg;
- X move(++curlin, 0);
- X printw("%-.*s", COLS-2, compose_hdr(current_msg));
- X clrtoeol();
- X }
- X }
- X
- X when C_PREV_MSG :
- X if (isoff(glob_flags, CNTD_CMD) && curlin == 1 ||
- X current_msg == 0 || msg_cnt == 0) {
- X mac_flush(); /* Bail out if in macro processing */
- X bell(); /* at the beginning */
- X } else {
- X if (--current_msg < n_array[0])
- X redo = 1;
- X if (ison(glob_flags, CNTD_CMD)) {
- X print("%-.*s", COLS-2, compose_hdr(current_msg));
- X putchar('\n');
- X }
- X }
- X
- X when C_FIRST_MSG : case C_LAST_MSG :
- X if (!msg_cnt) {
- X mac_flush();
- X bell();
- X break;
- X }
- X n = current_msg;
- X move(LINES-1, 0), refresh();
- X if (c == C_FIRST_MSG && (current_msg = 0) < n_array[0] ||
- X c == C_LAST_MSG && (current_msg = msg_cnt-1)> n_array[screen-1])
- X if (isoff(glob_flags, CNTD_CMD))
- X (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1),
- X msg_list);
- X else
- X redo = 1;
- X if (ison(glob_flags, CNTD_CMD) && n != current_msg)
- X print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
- X
- X /* top and bottom of headers screen */
- X when C_TOP_PAGE : case C_BOTTOM_PAGE :
- X if (msg_cnt && isoff(glob_flags, CNTD_CMD))
- X if (c == C_TOP_PAGE)
- X current_msg = n_array[0];
- X else
- X current_msg = min(n_array[screen-1], msg_cnt-1);
- X else {
- X mac_flush();
- X bell();
- X }
- X
- X when C_NEXT_SCREEN : /* next page */
- X move(LINES-1, 0), refresh();
- X if (msg_cnt-1 > n_array[screen-1]) {
- X clear();
- X set_screen_size();
- X (void) cmd_line(strcpy(buf, "\\headers +"), msg_list);
- X if (current_msg < n_array[0])
- X current_msg = n_array[0];
- X (void) curses_help_msg(TRUE);
- X return redo = 0;
- X } else {
- X mac_flush();
- X bell();
- X }
- X
- X when C_PREV_SCREEN : /* previous page */
- X move(LINES-1, 0), refresh();
- X if (n_array[0] > 0) {
- X clear();
- X set_screen_size();
- X (void) cmd_line(strcpy(buf, "\\headers -"), msg_list);
- X if (current_msg > n_array[screen-1])
- X current_msg = n_array[screen-1];
- X (void) curses_help_msg(TRUE);
- X return redo = 0;
- X } else {
- X mac_flush();
- X bell();
- X }
- X
- X /* read from/save to record file (.mushrc) */
- X when C_SOURCE : case C_SAVEOPTS : {
- X int argc;
- X char *argv[3];
- X print("%s filename [default]: ",
- X (c == C_SOURCE)? "source" : "save options to");
- X argc = Getstr(file, COLS-40, 0);
- X clr_bot_line();
- X if (argc < 0)
- X break;
- X if (argc > 0)
- X argv[1] = file, argc = 2;
- X else
- X argc = 1;
- X argv[argc] = NULL;
- X turnon(glob_flags, PRE_CURSES);
- X if (c == C_SOURCE) {
- X (void) source(argc, argv);
- X mac_flush(); /* can't change things in mid-macro */
- X redo = isoff(glob_flags, CNTD_CMD);
- X } else
- X (void) save_opts(argc, argv);
- X turnoff(glob_flags, PRE_CURSES);
- X }
- X
- X /*
- X * search commands
- X */
- X when C_NEXT_SEARCH : case C_PREV_SEARCH : case C_CONT_SEARCH :
- X if (c != C_CONT_SEARCH)
- X c = search(0 + (c == C_PREV_SEARCH));
- X else
- X c = search(-1);
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X if (c == 0)
- X break;
- X if (ison(glob_flags, CNTD_CMD))
- X print("%-.*s",COLS-2, compose_hdr(current_msg)), putchar('\n');
- X if (n_array[0] > current_msg || n_array[screen-1] < current_msg) {
- X redo = 1;
- X if (isoff(glob_flags, CNTD_CMD))
- X (void) cmd_line(sprintf(buf, "\\headers %d",
- X current_msg+1), msg_list);
- X }
- X
- X /*
- X * actions on messages
- X */
- X /* delete/undelete */
- X when C_DELETE_MSG : case C_DELETE_LIST :
- X case C_UNDEL_MSG : case C_UNDEL_LIST :
- X if (!msg_cnt) {
- X print("No messages.");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X break;
- X }
- X if (ison(glob_flags, READ_ONLY)) {
- X mac_flush();
- X print("Folder is read-only.");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X break;
- X }
- X Debug("current message = %d", current_msg + 1);
- X if (!*list)
- X set_msg_bit(msg_list, current_msg);
- X turnon(glob_flags, DO_UPDATE);
- X for (n = 0; n < msg_cnt; n++)
- X if (msg_bit(msg_list, n)) {
- X if (c == C_DELETE_MSG || c == C_DELETE_LIST)
- X turnon(msg[n].m_flags, DELETE|DO_UPDATE);
- X else
- X turnoff(msg[n].m_flags, DELETE);
- X if (isoff(glob_flags, CNTD_CMD) && (msg_cnt < screen ||
- X n >= n_array[0] && n <= n_array[screen-1])) {
- X move(max(1, n - n_array[0] + 1), 0);
- X printw("%-.*s", COLS-1, compose_hdr(n));
- X } else
- X redo = 1;
- X }
- X if (ison(glob_flags, CNTD_CMD) || *list) {
- X /* print(), THEN putchar() -- overwrite line */
- X if (ison(glob_flags, CNTD_CMD)) {
- X print("%sdeleted %s",
- X (c == C_DELETE_MSG || c == C_DELETE_LIST)? "":"un", list);
- X putchar('\n');
- X }
- X if (c == C_DELETE_MSG || c == C_DELETE_LIST) {
- X if (ison(msg[current_msg].m_flags, DELETE) ||
- X ison(msg[current_msg].m_flags, SAVED))
- X (void) next_msg();
- X if (isoff(msg[current_msg].m_flags, DELETE) &&
- X do_set(set_options, "autoprint"))
- X return C_DISPLAY_MSG;
- X }
- X if (ison(glob_flags, CNTD_CMD))
- X puts(compose_hdr(current_msg));
- X else if (current_msg < n_array[0]
- X || current_msg > n_array[screen-1])
- X redo = 1;
- X }
- X
- X /*
- X * write/save messages. If a list is necessary, the user already
- X * entered it above since he must have used a capital letter. If so,
- X * list will contain good data (already been validated above).
- X * if a list is given, set iscurses to 0 so that print statements
- X * will scroll and the user sees the multiple output. else, one
- X * line can go on the bottom line just fine.
- X */
- X when C_WRITE_MSG : case C_SAVE_MSG : case C_COPY_MSG :
- X case C_WRITE_LIST : case C_SAVE_LIST : case C_COPY_LIST : {
- X register char *p =
- X (c == C_WRITE_MSG || c == C_WRITE_LIST)? "write" :
- X (c == C_SAVE_MSG || c == C_SAVE_LIST)? "save" : "copy";
- X if (!msg_cnt) {
- X print("No messages.");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X break;
- X }
- X if (c != C_WRITE_MSG && c != C_WRITE_LIST) {
- X char *f = do_set(set_options, "mbox");
- X if (f)
- X (void) sprintf(file, "[%s]", f);
- X else
- X (void) sprintf(file, "[%s]", DEF_MBOX);
- X } /* else file is already init'd to "" */
- X print(sprintf(buf, "filename to %s%s: ", p, file));
- X if (Getstr(file, COLS-1-strlen(buf), 0) >= 0) {
- X char *argv[3];
- X clr_bot_line();
- X argv[0] = strcpy(buf, p);
- X p = file; skipspaces(0);
- X argv[1] = (*p) ? p : NULL;
- X argv[2] = NULL;
- X if (!*list)
- X set_msg_bit(msg_list, current_msg);
- X move(LINES-1, 0), refresh();
- X if (*list)
- X iscurses = FALSE;
- X /* Turn on piping to make save_msg look at msg_list */
- X turnon(glob_flags, IS_PIPE);
- X if (save_msg(1 + (*file != '\0'), argv, msg_list) < 0)
- X *list = 0;
- X turnoff(glob_flags, IS_PIPE);
- X if (ison(glob_flags, CNTD_CMD))
- X redo = 1, putchar('\n'), puts(compose_hdr(current_msg));
- X if (*list)
- X iscurses = redo = TRUE, turnon(glob_flags, CNTD_CMD);
- X else if (isoff(glob_flags, CNTD_CMD) && msg_cnt) {
- X move(curlin, 0);
- X printw("%-.*s", COLS-1, compose_hdr(current_msg));
- X }
- X } else {
- X print("No messages saved.");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X }
- X }
- X
- X /* preserve message or place mark on message */
- X when C_PRESERVE : case C_MARK_MSG :
- X if (!msg_cnt) {
- X print("No messages.");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X break;
- X }
- X if (ison(msg[current_msg].m_flags,
- X c == C_MARK_MSG ? M_PRIORITY(0) : PRESERVE))
- X turnoff(msg[current_msg].m_flags,
- X c == C_MARK_MSG ? M_PRIORITY(0) : PRESERVE);
- X else
- X turnon(msg[current_msg].m_flags,
- X c == C_MARK_MSG ? M_PRIORITY(0) : PRESERVE);
- X if (c != C_MARK_MSG)
- X turnon(glob_flags, DO_UPDATE);
- X if (ison(glob_flags, CNTD_CMD)) {
- X wprint("%-.*s\n", COLS-1, compose_hdr(current_msg));
- X redo = 1;
- X } else {
- X move(curlin, 0);
- X printw("%-.*s", COLS-1, compose_hdr(current_msg));
- X }
- X
- X /* order messages (sort) and redisplay the headers */
- X when C_SORT : case C_REV_SORT :
- X (void) strcpy(file, "sort");
- X if (c == C_REV_SORT) {
- X print("Reverse "), turnon(glob_flags, CONT_PRNT);
- X (void) strcat(file, " -");
- X }
- X print(
- X "Order messages by [author, date, length, Status, subject, priority]: "
- X );
- X if ((c = m_getchar()) == 'a' || c == 'd' || c == 'l' ||
- X c == 'S' || c == 's' || c == 'R' || c == 'p') {
- X print("reordering messages...");
- X (void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list);
- X print_more("done.");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n'), puts(compose_hdr(current_msg));
- X redo = 1;
- X } else
- X clr_bot_line();
- X
- X when C_QUIT_HARD :
- X (void) mush_quit(0, DUBL_NULL);
- X redo = 1; /* new mail must have come in */
- X
- X /* quit or update -- vrfy_update (returns 1 if updated) */
- X when C_QUIT : case C_UPDATE : {
- X clr_bot_line();
- X redo = (c == C_UPDATE);
- X if (!vrfy_update(&redo))
- X if (c == C_UPDATE)
- X break;
- X if (isoff(glob_flags, CNTD_CMD))
- X (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1),
- X msg_list);
- X }
- X
- X when C_EXIT : case C_EXIT_HARD :
- X clr_bot_line();
- X iscurses = FALSE;
- X if (c != C_EXIT && c != C_EXIT_HARD)
- X putchar('\n');
- X cleanup(0);
- X
- X /* change to a new folder */
- X when C_FOLDER :
- X for (;;) {
- X SIGRET (*oldint)(), (*oldquit)();
- X on_intr();
- X print("New folder (?=list): ");
- X c = Getstr(file, COLS-22, 0);
- X off_intr();
- X if (c > 0) {
- X if (!strcmp(file, "?")) {
- X clr_bot_line();
- X iscurses = 0;
- X puts("folders in your folder directory:");
- X (void) cmd_line(strcpy(buf, "\\folders"), msg_list);
- X puts("Precede folder names with a +. `%' to specify system mailbox.");
- X turnon(glob_flags, CNTD_CMD), iscurses = 1;
- X continue;
- X }
- X clearok(stdscr, FALSE);
- X /* if vrfy_update doesn't verify, but folder command fails,
- X * then we need to reset the updatability of current folder
- X */
- X c = (ison(glob_flags, DO_UPDATE))? TRUE : FALSE;
- X if (strcmp(file, "-?")) {
- X redo = 1; /* so vrfy_update() won't quit */
- X (void) vrfy_update(&redo);
- X }
- X move(LINES-1, 0), refresh();
- X if (cmd_line(sprintf(buf, "folder ! -N %s", file),
- X msg_list) == -1) {
- X if (c) /* remember state of updatability of folder */
- X turnon(glob_flags, DO_UPDATE);
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X } else
- X redo = 1, turnoff(glob_flags, CNTD_CMD);
- X break;
- X } else {
- X print("\"%s\" unchanged.", mailfile);
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X break;
- X }
- X }
- X
- X /* shell escape */
- X when C_SHELL_ESC :
- X print("Shell command: ");
- X if (Getstr(file, COLS-24, 0) < 0)
- X clr_bot_line();
- X else {
- X putchar('\n');
- X iscurses = FALSE;
- X (void) cmd_line(sprintf(buf, "sh %s", file), msg_list);
- X iscurses = TRUE;
- X turnon(glob_flags, CNTD_CMD);
- X }
- X
- X /* do a line-mode like command */
- X when C_CURSES_ESC :
- X print(":");
- X if (Getstr(buf, COLS-2, 0) < 0)
- X break;
- X putchar('\n');
- X iscurses = FALSE;
- X if (!*buf) {
- X /* return -1 because iscurses = 0 is not enough! */
- X redo = 0;
- X endwin(); /* this turns echoing back on! */
- X echo_off();
- X return -1;
- X }
- X /* The "source" and "curses" commands need some indication
- X * that we are in curses mode, so use the PRE_CURSES flag.
- X */
- X turnon(glob_flags, PRE_CURSES);
- X (void) cmd_line(buf, msg_list);
- X /* they may have affected message status or had text output */
- X turnon(glob_flags, CNTD_CMD), redo = 1;
- X turnoff(glob_flags, PRE_CURSES);
- X iscurses = TRUE;
- X if (msg_cnt)
- X puts(compose_hdr(current_msg));
- X
- X /* send message to printer, redo to display 'p' status */
- X when C_PRINT_MSG : redo = (lpr(0, DUBL_NULL, msg_list) == 0);
- X
- X /* cd */
- X when C_CHDIR :
- X print("chdir to [~]: ");
- X if (Getstr(file, COLS-12, 0) < 0)
- X break;
- X clr_bot_line();
- X (void) cmd_line(sprintf(buf, "cd %s", file), msg_list);
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X
- X /* variable settings */
- X when C_VAR_SET : case C_IGNORE : case C_ALIAS : case C_OWN_HDR :
- X curs_vars(c); /* CNTD_CMD is reset if there's output! */
- X
- X when C_VERSION :
- X (void) do_version();
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X
- X when C_MAIL_FLAGS :
- X print("flags [-?]: ");
- X if ((c = Getstr(file, COLS-12, 0)) < 0)
- X break;
- X putchar('\n');
- X if (c == 0)
- X (void) strcpy(file, "-?");
- X else
- X redo = 1; /* In case of -f flag, to display the 'f' status */
- X /* Fall thru */
- X case C_MAIL : {
- X u_long flgs = glob_flags;
- X turnon(glob_flags, IGN_BANG);
- X clr_bot_line();
- X iscurses = FALSE;
- X (void) cmd_line(sprintf(buf, "mail %s", file), msg_list);
- X glob_flags = flgs;
- X iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
- X if (msg_cnt)
- X print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
- X }
- X
- X /* reply to mail */
- X when C_REPLY_SENDER : case C_REPLY_ALL : {
- X register char *p = (c == C_REPLY_ALL)? "replyall" : "replysender";
- X clr_bot_line();
- X iscurses = FALSE;
- X if (isoff(msg[current_msg].m_flags, REPLIED))
- X redo = 1;
- X (void) cmd_line(sprintf(buf, "%s %d", p, current_msg+1),
- X msg_list);
- X if (msg_cnt)
- X puts(compose_hdr(current_msg));
- X iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
- X }
- X
- X /* type out a message */
- X when C_DISPLAY_MSG : case C_TOP_MSG : case C_DISPLAY_NEXT :
- X if (!msg_cnt ||
- X c != C_DISPLAY_NEXT && ison(msg[current_msg].m_flags, DELETE)) {
- X if (!msg_cnt)
- X print("No messages.");
- X else
- X print("Message %d deleted; type 'u' to undelete.",
- X current_msg+1);
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X break;
- X }
- X clr_bot_line();
- X iscurses = FALSE;
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X if (c == C_DISPLAY_MSG)
- X c = cmd_line(strcpy(buf, "type"), msg_list);
- X else if (c == C_TOP_MSG)
- X c = cmd_line(strcpy(buf, "top"), msg_list);
- X else {
- X /* "next" screws up the screen whether it displays or not */
- X (void) cmd_line(strcpy(buf, "next"), msg_list);
- X c = 0;
- X }
- X if (c > -1)
- X turnon(glob_flags, CNTD_CMD), redo = 1;
- X iscurses = TRUE;
- X puts(compose_hdr(current_msg));
- X
- X /* bind a key or string to a curses-mode command */
- X when C_BIND : case C_UNBIND : case C_MAP : case C_BIND_MACRO :
- X case C_MAP_BANG : {
- X char *argv[2];
- X argv[0] = (c == C_BIND) ? "bind" :
- X (c == C_UNBIND) ? "unbind" :
- X (c == C_MAP) ? "map" :
- X (c == C_MAP_BANG) ? "map!" : "bind-macro";
- X argv[1] = NULL;
- X if (bind_it(1, argv) < -1)
- X turnon(glob_flags, CNTD_CMD);
- X else if (ison(glob_flags, CNTD_CMD)) /* if it was set anyway */
- X putchar('\n');
- X else
- X (void) curses_help_msg(TRUE);
- X }
- X
- X when C_MACRO :
- X turnon(glob_flags, IN_MACRO);
- X /* Current macro should already be in the mac_stack, so
- X * all we have to do here is look for the next character
- X */
- X
- X /* help stuff */
- X when C_HELP :
- X move(LINES-1, 0), refresh();
- X (void) help(0, "curses", cmd_help);
- X turnon(glob_flags, CNTD_CMD);
- X if (msg_cnt)
- X puts(compose_hdr(current_msg));
- X
- X otherwise :
- X mac_flush();
- X bell();
- X if (ison(glob_flags, CNTD_CMD)) {
- X /* use print instead of puts to overwrite hit_return msg */
- X print("unknown command"), putchar('\n');
- X redo = 1;
- X }
- X }
- X
- X if (ison(glob_flags, CNTD_CMD)) {
- X int old_cnt = msg_cnt;
- X if (!(c = hit_return()) && !redo && msg_cnt == old_cnt)
- X redraw();
- X clr_bot_line();
- X if (old_cnt != msg_cnt)
- X redo = 1;
- X if (c)
- X return c;
- X }
- X if (redo) {
- X set_screen_size(); /* it may have changed */
- X n = current_msg;
- X clear();
- X if (/* msg_cnt < screen || */ n_array[0] < n && n < n_array[screen-1])
- X (void) do_hdrs(0, DUBL_NULL, NULL);
- X else
- X (void) cmd_line(sprintf(buf, "\\headers %d", n+1), msg_list);
- X (void) curses_help_msg(TRUE);
- X redo = 0;
- X }
- X return 0;
- }
- X
- vrfy_update(redo)
- int *redo;
- {
- X char buf[16];
- X int c;
- X
- X /* update current folder */
- X if (ison(glob_flags, DO_UPDATE)) {
- X if (ison(glob_flags, READ_ONLY)) {
- X mac_flush();
- X print("Folder is read-only.");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X return 0;
- X }
- X print("Update folder [y]? ");
- X if ((c = getchar()) != 'y' && c != 'Y' && c != '\n' && !isspace(c)) {
- X print("Folder unchanged.");
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X return 0;
- X }
- X } else if (*redo)
- X return 1;
- X if (cmd_line(strcpy(buf, *redo? "update" : "quit"), msg_list) != -1
- X && ison(glob_flags, CNTD_CMD))
- X *redo = 1, turnoff(glob_flags, CNTD_CMD);
- X turnoff(glob_flags, DO_UPDATE);
- X return 1; /* make sure bottom line is clear and no reverse video */
- }
- X
- scrn_line(line, buf)
- char *buf;
- {
- #ifndef A_CHARTEXT
- X (void) strncpy(buf, stdscr->_y[line], COLS-1);
- X buf[COLS-1] = 0; /* strncpy does not null terminate */
- #else
- X int n;
- X
- X for (n = 0; n < COLS; n++)
- X if ((buf[n] = (mvinch(line, n) & A_CHARTEXT)) == '\0')
- X break;
- X buf[n] = '\0';
- #endif /* A_CHARTEXT */
- }
- X
- /*
- X * Generate the help message from the variable curses_help.
- X * If visible is true, the message is displayed,
- X * otherwise its size (in lines) is computed and returned.
- X */
- curses_help_msg(visible)
- int visible;
- {
- X int count, i, len, siz = 0, mxm = 0;
- X static int old_siz = 0;
- X register struct cmd_map *list;
- X extern struct cmd_map map_func_names[];
- X char *curs_help = do_set(set_options, "curses_help"), **format;
- X
- X if (!curs_help) {
- X if (old_siz && visible) {
- X int bot = min(n_array[screen-1], msg_cnt-1);
- X move(max(0, bot - n_array[0]) + 2, 0), clrtobot();
- X old_siz = 0;
- X }
- X return 0;
- X } else if (!*curs_help)
- X curs_help = DEF_CURSES_HELP;
- X /* Split the help string into words */
- X if (!(format = mk_argv(curs_help, &count, FALSE)) || count <= 0)
- X return 0;
- X /* Generate a help message for each word */
- X for (i = 0; i < count; i++) {
- X char buf[MAX_BIND_LEN*2+MAX_LONG_CMD+5], asc[MAX_BIND_LEN*2];
- X
- X buf[0] = '\0'; /* default to empty in case of no match */
- X for (list = cmd_map; list; list = list->m_next) {
- X if (!strcmp(format[i], map_func_names[list->m_cmd].m_str)) {
- X len = strlen(sprintf(buf, "(%s) %s ",
- X ctrl_strcpy(asc, list->m_str, FALSE),
- X map_func_names[list->m_cmd].m_str));
- X if (len > mxm)
- X mxm = len;
- X break;
- X }
- X }
- X strdup(format[i], buf); /* replace word with its "definition" */
- X }
- X /* Columnate the output nicely */
- X if (mxm > 0) {
- X len = (COLS - 1) / mxm;
- X if (len == 0) {
- X if (visible)
- X print("Curses help message too long!");
- X return 0;
- X }
- X siz = count / len;
- X if (count % len)
- X siz++;
- X if (siz > LINES / 3) {
- X if (visible)
- X print("Curses help message too long!");
- X return 0;
- X }
- X if (visible) {
- X int next = LINES - 1 - siz;
- X if (old_siz > siz) {
- X int bot = min(n_array[screen-1], msg_cnt-1);
- X move(max(0, bot - n_array[0]) + 2, 0), clrtobot();
- X }
- X old_siz = siz;
- X for (i = 0; i < count; i++) {
- X if (!(i % len))
- X move(next, 0), clrtoeol(), ++next;
- X if (format[i][0])
- X printw("%-*.*s", mxm, mxm, format[i]);
- X }
- X refresh();
- X }
- X }
- X free_vec(format);
- X return siz;
- }
- X
- set_screen_size()
- {
- X int hlp_siz = LINES - 2 - curses_help_msg(FALSE);
- X
- X if (!do_set(set_options, "screen"))
- #ifdef USG
- X switch (_tty.sg_ospeed & CBAUD)
- #else /* USG */
- X switch (_tty.sg_ospeed)
- #endif /* USG */
- X {
- X case B300 : screen = min(hlp_siz, 7);
- X when B1200 : screen = min(hlp_siz, 14);
- X when B2400 : screen = min(hlp_siz, 22);
- X otherwise : screen = hlp_siz;
- X }
- X else
- X screen = min(screen, hlp_siz);
- }
- X
- /*
- X * prompt for a carriage return, but return whatever user types unless
- X * it's a character which he might regret (like 'q' or 'x'). Ignore
- X * interrupts (kind of) because we have nowhere to longjmp to. When we
- X * return, we'll setjmp again (top of loop.c)
- X */
- hit_return()
- {
- X int c;
- X
- X turnon(glob_flags, IGN_SIGS);
- X iscurses = FALSE;
- X (void) check_new_mail();
- X iscurses = TRUE;
- X mail_status(1), addstr("...continue... "), refresh();
- X c = getcmd();
- X turnoff(glob_flags, IGN_SIGS);
- X
- X /* don't let the user type something he might regret */
- X if (c == C_QUIT || c == C_EXIT)
- X return C_NULL;
- X return c;
- }
- X
- curses_msg_list(str, list, m_list)
- register char *str, *list;
- char m_list[];
- {
- X register char *p = NULL;
- X int c, sv_cur_msg = current_msg;
- X
- X print(str);
- X c = Getstr(list, COLS-13, 0);
- X move(LINES-1, 0), refresh();
- X if (c <= 0 || !(p = do_range(list, m_list)) ||
- X (p == list && *p && *p != '$' && *p != '^')) {
- X if (p)
- X print("Invalid message list: %s", p);
- X current_msg = sv_cur_msg;
- X return 0;
- X }
- X current_msg = sv_cur_msg;
- X return 1;
- }
- X
- curs_vars(which)
- int which; /* really, a char */
- {
- X char c, buf[128], buf2[128], *string;
- X struct options **list;
- X
- X switch(which) {
- X case C_OWN_HDR : string = "my_hdr", list = &own_hdrs;
- X when C_ALIAS : string = "alias", list = &aliases;
- X when C_IGNORE : string = "ignore", list = &ignore_hdr;
- X when C_VAR_SET : string = "set", list = &set_options;
- X otherwise : clr_bot_line(); return;
- X }
- X
- X print("%s [? Set Unset All]: ", string);
- X c = m_getchar();
- X clr_bot_line();
- X switch (Lower(c)) {
- X /* if help, print help -- if "all", show all settings. */
- X case '?' : case 'a' :
- X if (c == '?') {
- X if (!strcmp(string, "set")) {
- X print("which variable? [all <var>]: ");
- X if ((c = Getstr(buf+1, COLS-40, 0)) < 0)
- X return;
- X clr_bot_line();
- X buf[0] = '?';
- X if (c > 0) {
- X char *argv[3];
- X argv[0] = string;
- X argv[1] = buf;
- X argv[2] = NULL;
- X Lower(buf[1]);
- X if (!strcmp(buf+1, "a"))
- X (void) strcpy(buf+1, "all");
- X if (!strcmp(buf+1, "all"))
- X turnon(glob_flags, CNTD_CMD);
- X (void) set(2, argv, (char *) 0);
- X break;
- X }
- X }
- X /* help returns next command (hit_return) */
- X (void) help(0, string, cmd_help);
- X turnon(glob_flags, CNTD_CMD);
- X return;
- X }
- X turnon(glob_flags, CNTD_CMD);
- X (void) do_set(*list, NULL);
- X
- X /* if set, prompt for string and let user type */
- X when 's' :
- X print("set: ");
- X c = Getstr(buf, COLS-18, 0);
- X clr_bot_line();
- X if (c > 0)
- X (void) cmd_line(sprintf(buf2, "%s %s", string, buf), msg_list);
- X
- X /* if unset, just as easy as set! */
- X when 'u' :
- X print("unset: ", string);
- X if (Getstr(buf, COLS-18, 0) > 0 && !un_set(list, buf))
- X print("%s isn't set", buf);
- X }
- X if (ison(glob_flags, CNTD_CMD))
- X putchar('\n');
- X else
- X (void) curses_help_msg(TRUE);
- }
- #endif /* CURSES */
- SHAR_EOF
- chmod 0644 curses.c ||
- echo 'restore of curses.c failed'
- Wc_c="`wc -c < 'curses.c'`"
- test 28914 -eq "$Wc_c" ||
- echo 'curses.c: original size 28914, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= dates.c ==============
- if test -f 'dates.c' -a X"$1" != X"-c"; then
- echo 'x - skipping dates.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting dates.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'dates.c' &&
- /* @(#)dates.c 3.0 (c) copyright 3/01/90 (Dan Heller, Bart Schaefer) */
- X
- #include "mush.h"
- X
- /*
- X * %ld%3c%s gmt_in_secs weekday orig_timezone
- X * The standard "date format" stored in the msg data structure.
- X */
- char *day_names[] = {
- X "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
- char *month_names[] = { /* imported in pick.c */
- X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- X
- static int mtbl[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
- X
- /* Time Zone Stuff */
- struct zoneoff {
- X char *zname;
- X int hr_off;
- X int mn_off;
- } time_zones[] = {
- X /* Universal Time */
- X { "UT", 0, 0 }, { "GMT", 0, 0 },
- X /* European Time */
- X { "BST", 1, 0 }, /* Brit. Summer */
- X { "EET", 2, 0 }, { "EEST", 3, 0 }, /* Eastern */
- X { "EET DST", 3, 0 },
- X { "MET", 1, 0 }, { "MEST", 2, 0 }, /* Middle */
- X { "MET DST", 2, 0 },
- X { "WET", 0, 0 }, { "WEST", 1, 0 }, /* Western */
- X { "WET DST", 1, 0 },
- X /* North American Time */
- X { "NST", -3,-30 }, /* Newfoundland */
- X { "AST", -4, 0 }, { "ADT", -3, 0 }, /* Atlantic */
- X { "EST", -5, 0 }, { "EDT", -4, 0 }, /* Eastern */
- X { "CST", -6, 0 }, { "CDT", -5, 0 }, /* Central */
- X { "MST", -7, 0 }, { "MDT", -6, 0 }, /* Mountain */
- X { "PST", -8, 0 }, { "PDT", -7, 0 }, /* Pacific */
- X { "YST", -9, 0 }, { "YDT", -8, 0 }, /* Yukon */
- X { "HST", -10, 0 }, { "HDT", -9, 0 }, /* Hawaii */
- X /* Japan and Australia Time */
- X {"JST", 9, 0 }, /* Japan */
- X {"AEST", 10, 0 }, {"AESST", 11, 0 }, /* Eastern */
- X {"ACST", 9, 30 }, {"ACSST", 10, 30 }, /* Central */
- X {"AWST", 8, 0 }, /* Western */
- X /* Military Time */
- X { "A", 1, 0 }, { "N", -1, 0 },
- X { "B", 2, 0 }, { "O", -2, 0 },
- X { "C", 3, 0 }, { "P", -3, 0 },
- X { "D", 4, 0 }, { "Q", -4, 0 },
- X { "E", 5, 0 }, { "R", -5, 0 },
- X { "F", 6, 0 }, { "S", -6, 0 },
- X { "G", 7, 0 }, { "T", -7, 0 },
- X { "H", 8, 0 }, { "U", -8, 0 },
- X { "I", 9, 0 }, { "V", -9, 0 },
- X { "K", 10, 0 }, { "W", -10, 0 },
- X { "L", 11, 0 }, { "X", -11, 0 },
- X { "M", 12, 0 }, { "Y", -12, 0 },
- X { "Z", 0, 0 },
- X /* Also legal is +/- followed by hhmm offset from UT */
- X { 0, 0, 0 }
- };
- X
- long
- getzoff(zone)
- char *zone;
- {
- X struct zoneoff *z;
- X int hours, mins;
- X char sign[2];
- X
- X if (!zone || !*zone)
- X return 0;
- X if (sscanf(zone, "%1[-+]%2d%2d", sign, &hours, &mins) == 3)
- X return (hours * 3600 + mins * 60) * (*sign == '-' ? -1 : 1);
- X for (z = time_zones; z->zname; z++)
- X if (lcase_strncmp(zone, z->zname, -1) == 0)
- X return z->hr_off * 3600 + z->mn_off * 60;
- X return 0;
- }
- X
- /*
- X * Kind of the reverse of localtime() and gmtime() -- converts a struct tm
- X * to time in seconds since 1970. Valid until 2038.
- X * If the "zone" argument is present, it modifies the return value.
- X * The zone should be a string, either +/-hhmm or symbolic (above).
- X * The "how" argument should be -1 to convert FROM gmt, 1 to convert TO gmt,
- X * and (as a "side-effect") 0 if the Zone parameter is to be ignored.
- X *
- X * Thanks to ktl@wag240.caltech.edu (Kian-Tat Lim) for similar algorithm
- X * written in perl from which this was derived.
- X */
- long
- time2gmt(tym, zone, how)
- struct tm *tym;
- char *zone;
- int how;
- {
- X long year, julian;
- X
- X if (tym->tm_year < 100)
- X year = tym->tm_year + 1900;
- X if (year < 69)
- X year += 100;
- X
- X julian = 365 * (year - 1970) + (int)((year - 1970 + 1) / 4) +
- X mtbl[tym->tm_mon] + tym->tm_mday - 1;
- X /* tym->tm_yday might not be valid */
- X if (tym->tm_mon > 1 && year%4 == 0 && (year%100 != 0 || year%400 == 0))
- X julian++;
- X julian *= 86400; /* convert to seconds */
- X julian += (tym->tm_hour * 60 + tym->tm_min) * 60 + tym->tm_sec;
- X return julian - getzoff(zone) * how;
- }
- X
- struct tm *
- time_n_zone(zone)
- char *zone;
- {
- X struct tm *T;
- X char *tz;
- #if defined(SYSV) || defined(TIMEZONE)
- X long x;
- X
- X (void) time(&x);
- X T = localtime(&x);
- #ifndef TIMEZONE
- X {
- X extern char *tzname[];
- X tz = tzname[T->tm_isdst];
- X }
- #endif /* TIMEZONE */
- #else /* SYSV || TIMEZONE */
- X extern char *timezone();
- X struct timeval mytime;
- X struct timezone myzone;
- X
- X (void) gettimeofday(&mytime, &myzone);
- X T = localtime(&mytime.tv_sec);
- X tz = timezone(myzone.tz_minuteswest, (T->tm_isdst && myzone.tz_dsttime));
- #endif /* !SYSV */
- X
- #ifdef TIMEZONE
- #ifdef DAYLITETZ
- X if (T->tm_isdst)
- X tz = DAYLITETZ;
- X else
- #endif /* DAYLITETZ */
- X tz = TIMEZONE;
- #endif /* TIMEZONE */
- SHAR_EOF
- true || echo 'restore of dates.c failed'
- fi
- echo 'End of part 6'
- echo 'File dates.c is continued in part 7'
- echo 7 > _shar_seq_.tmp
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-