argv@zipcode.com (Dan Heller) (04/21/91)
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.