home *** CD-ROM | disk | FTP | other *** search
- /* @(#)curses.c (c) copyright 3/18/87 (Dan Heller) */
-
- /* curses.c -- routine to deal with the curses interface */
- #ifdef CURSES
-
- #include "mush.h"
- #include "bindings.h"
-
- curses_init(argc, argv)
- register char **argv;
- {
- char buf[80];
- extern char *UP, ttytype[];
-
- if (argv && *++argv && !strcmp(*argv, "-?"))
- return help(0, "curses", cmd_help);
- #ifdef SUNTOOL
- if (istool) {
- print("Sorry, can't change to curses mode from tool.\n");
- return -1;
- } else
- #endif /* SUNTOOL */
- if (!is_shell) {
- /*
- * Can't start curses, but we can prepare to.
- * Also allow -C switch to be shut off.
- */
- if (argv && *argv && !lcase_strncmp(*argv, "off", -1))
- turnoff(glob_flags, PRE_CURSES);
- else
- turnon(glob_flags, PRE_CURSES);
- return 0;
- } else if (argc && (iscurses || ison(glob_flags, PRE_CURSES))) {
- print("You are already using curses mode.\n");
- return -1;
- } else if (ison(glob_flags, IS_GETTING)) {
- print("Finish your letter first.\n");
- return -1;
- }
-
- #ifndef attrset /* terminfo version of curses */
- /* you can not start curses in no echo mode.. must be in normal mode */
- echom();
- nocrmode();
- #endif /* attrset */
- (void) initscr();
- #ifdef SIGCONT
- /* initscr will play with signals -- make sure they're set right. */
- (void) signal(SIGTSTP, stop_start);
- (void) signal(SIGCONT, stop_start);
- #endif /* SIGCONT */
- #if !defined(SYSV) && !defined(USG)
- if (!UP || !*UP)
- #else /* ~SYSV && ~USG */
- if (!stdscr)
- #endif /* ~SYSV && ~USG */
- {
- print("Terminal type %s can not use the curses interface.\n", ttytype);
- return -1;
- }
- iscurses = TRUE;
- noechom(); /* reset tty state -- */
- crmode(); /* do not use "echo_on/off()" */
- scrollok(stdscr, TRUE);
- /* if the user hasn't set his screen explicitly, set it for him */
- set_screen_size();
- if (crt > LINES - 1 || !do_set(set_options, "crt")) {
- crt = LINES;
- (void)cmd_line(sprintf(buf, "\\set screen = %d crt = %d", screen, crt),
- msg_list);
- } else
- (void)cmd_line(sprintf(buf, "\\set screen = %d", screen), msg_list);
- if (argc) {
- (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1), msg_list);
- (void) curses_help_msg(TRUE);
- }
- if (!do_set(set_options, "no_reverse"))
- turnon(glob_flags, REV_VIDEO);
- turnoff(glob_flags, CONT_PRNT);
- return 0; /* doesn't affect messages */
- }
-
- struct cmd_map *active_cmd; /* See bindings.h for description */
-
- /*
- * get input in cbreak mode and execute the appropriate command.
- * when the command is done (usually), the user is prompted to
- * hit any key to continue. At this point, the user may enter a
- * new command so no screen refreshing needs to be done. This
- * new command is returned to caller and may be passed back.
- *
- * The flag CNTD_CMD (continued command) is set if
- * this routine is called with the passed parameter (c) != 0. If
- * so, then the character passed is the character input by the
- * user at the last "hit return" prompt indicating that he wants
- * to execute a new command and not draw the screen.
- *
- * CNTD_CMD is also set if the command that the user invokes
- * causes any sort of output that requires a screen refresh. The
- * variable redo is set to 1 if the header page not only requires
- * redrawing, but updating ... (new call to do_hdrs)
- *
- * calls that say: print("%s", compose_hdr(current_msg)) are constructed
- * that way because if the header has a `%' in it, then print will try to
- * expand it.
- */
- curses_command(c)
- register int c;
- {
- char buf[BUFSIZ], file[128], list[128];
- int n, curlin;
- static int redo = 0; /* set if headers should be redrawn */
-
- if (c != 0)
- turnon(glob_flags, CNTD_CMD);
- else
- turnoff(glob_flags, CNTD_CMD);
- clear_msg_list(msg_list); /* play it safe */
- if (isoff(glob_flags, CNTD_CMD)) {
- (void) check_new_mail();
- curlin = max(1, current_msg - n_array[0] + 1);
- scrn_line(curlin, buf);
- if (ison(glob_flags, REV_VIDEO) && msg_cnt)
- STANDOUT(curlin, 0, buf);
- mail_status(0);
- move(curlin, 0), refresh();
- /* reprint to remove reverse video from current line (don't refresh) */
- if (ison(glob_flags, REV_VIDEO))
- mvaddstr(curlin, 0, buf);
- c = getcmd(); /* get input AFTER line redrawn without reverse video */
- }
- buf[0] = list[0] = file[0] = '\0';
-
- if (c == C_WRITE_LIST || c == C_SAVE_LIST || c == C_COPY_LIST
- || c == C_DELETE_LIST || c == C_UNDEL_LIST) {
- if (msg_cnt < 1) {
- mac_flush();
- print("Not enough messages.");
- c = C_NULL;
- } else if (c == C_DELETE_LIST && ison(glob_flags, READ_ONLY)) {
- mac_flush();
- print("Folder is read-only.");
- c = C_NULL;
- } else if (!curses_msg_list(sprintf(buf, "%s msg list: ",
- (c == C_WRITE_LIST)? "write" : (c == C_SAVE_LIST)? "save" :
- (c == C_COPY_LIST)? "copy" :
- (c == C_DELETE_LIST)? "delete" : "undelete"), list, msg_list))
- c = C_NULL;
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- }
-
- /* first do non-mail command type stuff */
- switch (c) {
- case C_ERROR :
- bell();
- mac_flush();
-
- when C_NULL :
- if (isoff(glob_flags, CNTD_CMD))
- bell();
-
- /* goto a specific message number */
- when C_GOTO_MSG :
- if (curses_msg_list(strcpy(buf, "goto msg: "), list, msg_list)) {
- /*
- * Reset the current message in case a
- * backquoted command (like `from`) changed it
- */
- n = current_msg;
- do if (++n >= msg_cnt)
- n = 0;
- while (n != current_msg && !msg_bit(msg_list, n));
- if (n == current_msg && !msg_bit(msg_list, n)) {
- mac_flush(); /* bail out if in macro processing */
- print("Message not found.");
- }
- else if ((current_msg = n) < n_array[0]
- || n > n_array[screen-1])
- redo = 1;
- } else {
- mac_flush();
- bell();
- }
- if (ison(glob_flags, CNTD_CMD) && msg_cnt)
- print("%-.*s", COLS-2, compose_hdr(current_msg));
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
-
- /* screen optimization stuff */
- when C_REVERSE :
- if (ison(glob_flags, REV_VIDEO))
- turnoff(glob_flags, REV_VIDEO);
- else
- turnon(glob_flags, REV_VIDEO);
-
- when C_REDRAW : redo = 1;
-
- /*
- * screen movement
- */
- when C_NEXT_MSG :
- if (current_msg + 2 > msg_cnt ||
- isoff(glob_flags, CNTD_CMD) && curlin == LINES-2) {
- mac_flush(); /* Bail out if in macro processing */
- bell(); /* reached the end */
- } else {
- if (ison(glob_flags, CNTD_CMD)) {
- if (++current_msg > n_array[screen-1])
- redo = 1;
- print("%-.*s", COLS-2, compose_hdr(current_msg));
- putchar('\n');
- } else {
- if (++current_msg > n_array[screen-1])
- n_array[screen++] = current_msg;
- move(++curlin, 0);
- printw("%-.*s", COLS-2, compose_hdr(current_msg));
- clrtoeol();
- }
- }
-
- when C_PREV_MSG :
- if (isoff(glob_flags, CNTD_CMD) && curlin == 1 || current_msg == 0)
- {
- mac_flush(); /* Bail out if in macro processing */
- bell(); /* at the beginning */
- } else {
- if (--current_msg < n_array[0])
- redo = 1;
- if (ison(glob_flags, CNTD_CMD)) {
- print("%-.*s", COLS-2, compose_hdr(current_msg));
- putchar('\n');
- }
- }
-
- when C_FIRST_MSG : case C_LAST_MSG :
- if (!msg_cnt) {
- mac_flush();
- bell();
- break;
- }
- n = current_msg;
- move(LINES-1, 0), refresh();
- if (c == C_FIRST_MSG && (current_msg = 0) < n_array[0] ||
- c == C_LAST_MSG && (current_msg = msg_cnt-1)> n_array[screen-1])
- if (isoff(glob_flags, CNTD_CMD))
- (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1),
- msg_list);
- else
- redo = 1;
- if (ison(glob_flags, CNTD_CMD) && n != current_msg)
- print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
-
- /* top and bottom of headers screen */
- when C_TOP_PAGE : case C_BOTTOM_PAGE :
- if (msg_cnt && isoff(glob_flags, CNTD_CMD))
- if (c == C_TOP_PAGE)
- current_msg = n_array[0];
- else
- current_msg = min(n_array[screen-1], msg_cnt-1);
- else {
- mac_flush();
- bell();
- }
-
- when C_NEXT_SCREEN : /* next page */
- move(LINES-1, 0), refresh();
- if (msg_cnt-1 > n_array[screen-1]) {
- clear();
- set_screen_size();
- (void) cmd_line(strcpy(buf, "\\headers +"), msg_list);
- if (current_msg < n_array[0])
- current_msg = n_array[0];
- (void) curses_help_msg(TRUE);
- return redo = 0;
- } else {
- mac_flush();
- bell();
- }
-
- when C_PREV_SCREEN : /* previous page */
- move(LINES-1, 0), refresh();
- if (n_array[0] > 0) {
- clear();
- set_screen_size();
- (void) cmd_line(strcpy(buf, "\\headers -"), msg_list);
- if (current_msg > n_array[screen-1])
- current_msg = n_array[screen-1];
- (void) curses_help_msg(TRUE);
- return redo = 0;
- } else {
- mac_flush();
- bell();
- }
-
- /* read from/save to record file (.mushrc) */
- when C_SOURCE : case C_SAVEOPTS : {
- int argc;
- char *argv[3];
- print("%s filename [default]: ",
- (c == C_SOURCE)? "source" : "save options to");
- argc = Getstr(file, LINES-40, 0);
- clr_bot_line();
- if (argc < 0)
- break;
- if (argc > 0)
- argv[1] = file, argc = 2;
- else
- argc = 1;
- argv[argc] = NULL;
- turnon(glob_flags, PRE_CURSES);
- if (c == C_SOURCE) {
- (void) source(argc, argv);
- mac_flush(); /* can't change things in mid-macro */
- redo = isoff(glob_flags, CNTD_CMD);
- } else
- (void) save_opts(argc, argv);
- turnoff(glob_flags, PRE_CURSES);
- }
-
- /*
- * search commands
- */
- when C_NEXT_SEARCH : case C_PREV_SEARCH : case C_CONT_SEARCH :
- if (c != C_CONT_SEARCH)
- c = search(0 + (c == C_PREV_SEARCH));
- else
- c = search(-1);
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- if (c == 0)
- break;
- if (ison(glob_flags, CNTD_CMD))
- print("%-.*s",COLS-2, compose_hdr(current_msg)), putchar('\n');
- if (n_array[0] > current_msg || n_array[screen-1] < current_msg) {
- redo = 1;
- if (isoff(glob_flags, CNTD_CMD))
- (void) cmd_line(sprintf(buf, "\\headers %d",
- current_msg+1), msg_list);
- }
-
- /*
- * actions on messages
- */
- /* delete/undelete */
- when C_DELETE_MSG : case C_DELETE_LIST :
- case C_UNDEL_MSG : case C_UNDEL_LIST :
- if (!msg_cnt) {
- print("No messages.");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- break;
- }
- if (ison(glob_flags, READ_ONLY)) {
- mac_flush();
- print("Folder is read-only.");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- break;
- }
- Debug("current message = %d", current_msg + 1);
- if (!*list)
- set_msg_bit(msg_list, current_msg);
- turnon(glob_flags, DO_UPDATE);
- for (n = 0; n < msg_cnt; n++)
- if (msg_bit(msg_list, n)) {
- if (c == C_DELETE_MSG || c == C_DELETE_LIST)
- turnon(msg[n].m_flags, DELETE);
- else
- turnoff(msg[n].m_flags, DELETE);
- if (isoff(glob_flags, CNTD_CMD) && (msg_cnt < screen ||
- n >= n_array[0] && n <= n_array[screen-1])) {
- move(max(1, n - n_array[0] + 1), 0);
- printw("%-.*s", COLS-1, compose_hdr(n));
- } else
- redo = 1;
- }
- if (ison(glob_flags, CNTD_CMD) || *list) {
- /* print(), THEN putchar() -- overwrite line */
- if (ison(glob_flags, CNTD_CMD)) {
- print("%sdeleted %s",
- (c == C_DELETE_MSG || c == C_DELETE_LIST)? "":"un", list);
- putchar('\n');
- }
- if (c == C_DELETE_MSG || c == C_DELETE_LIST) {
- if (ison(msg[current_msg].m_flags, DELETE) ||
- ison(msg[current_msg].m_flags, SAVED))
- (void) next_msg();
- if (isoff(msg[current_msg].m_flags, DELETE) &&
- do_set(set_options, "autoprint"))
- return C_DISPLAY_MSG;
- }
- if (ison(glob_flags, CNTD_CMD))
- puts(compose_hdr(current_msg));
- else if (current_msg < n_array[0]
- || current_msg > n_array[screen-1])
- redo = 1;
- }
-
- /*
- * write/save messages. If a list is necessary, the user already
- * entered it above since he must have used a capital letter. If so,
- * list will contain good data (already been validated above).
- * if a list is given, set iscurses to 0 so that print statements
- * will scroll and the user sees the multiple output. else, one
- * line can go on the bottom line just fine.
- */
- when C_WRITE_MSG : case C_SAVE_MSG : case C_COPY_MSG :
- case C_WRITE_LIST : case C_SAVE_LIST : case C_COPY_LIST : {
- register char *p =
- (c == C_WRITE_MSG || c == C_WRITE_LIST)? "write" :
- (c == C_SAVE_MSG || c == C_SAVE_LIST)? "save" : "copy";
- if (!msg_cnt) {
- print("No messages.");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- break;
- }
- print(sprintf(buf, "filename to %s%s: ", p,
- (c != C_WRITE_MSG && c != C_WRITE_LIST)? " [mbox]" : ""));
- if (Getstr(file, COLS-1-strlen(buf), 0) >= 0) {
- char *argv[3];
- clr_bot_line();
- argv[0] = strcpy(buf, p);
- p = file; skipspaces(0);
- argv[1] = (*p) ? p : NULL;
- argv[2] = NULL;
- if (!*list)
- set_msg_bit(msg_list, current_msg);
- move(LINES-1, 0), refresh();
- if (*list)
- iscurses = FALSE;
- /* Turn on piping to make save_msg look at msg_list */
- turnon(glob_flags, IS_PIPE);
- if (save_msg(1 + (*file != '\0'), argv, msg_list) < 0)
- *list = 0;
- turnoff(glob_flags, IS_PIPE);
- if (ison(glob_flags, CNTD_CMD))
- redo = 1, putchar('\n'), puts(compose_hdr(current_msg));
- if (*list)
- iscurses = redo = TRUE, turnon(glob_flags, CNTD_CMD);
- else if (isoff(glob_flags, CNTD_CMD) && msg_cnt) {
- move(curlin, 0);
- printw("%-.*s", COLS-1, compose_hdr(current_msg));
- }
- } else {
- print("No messages saved.");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- }
- }
-
- /* preserve message */
- when C_PRESERVE :
- if (!msg_cnt) {
- print("No messages.");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- break;
- }
- if (ison(msg[current_msg].m_flags, PRESERVE))
- turnoff(msg[current_msg].m_flags, PRESERVE);
- else
- turnon(msg[current_msg].m_flags, PRESERVE);
- turnon(glob_flags, DO_UPDATE);
- if (ison(glob_flags, CNTD_CMD)) {
- wprint("%-.*s\n", COLS-1, compose_hdr(current_msg));
- redo = 1;
- } else {
- move(curlin, 0);
- printw("%-.*s", COLS-1, compose_hdr(current_msg));
- }
-
- /* order messages (sort) and redisplay the headers */
- when C_SORT : case C_REV_SORT :
- (void) strcpy(file, "sort");
- if (c == C_REV_SORT) {
- print("Reverse "), turnon(glob_flags, CONT_PRNT);
- (void) strcat(file, " -");
- }
- print(
- "Order messages by [author, date, length, Status, subject]: "
- );
- if ((c = m_getchar()) == 'a' || c == 'd' || c == 'l' ||
- c == 'S' || c == 's' || c == 'R') {
- print("reordering messages...");
- (void) cmd_line(sprintf(buf, "%s %c", file, c), msg_list);
- print_more("done.");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n'), puts(compose_hdr(current_msg));
- redo = 1;
- } else
- clr_bot_line();
-
- when C_QUIT_HARD :
- (void) mush_quit(0, DUBL_NULL);
- redo = 1; /* new mail must have come in */
-
- /* quit or update -- vrfy_update (returns 1 if updated) */
- when C_QUIT : case C_UPDATE : {
- clr_bot_line();
- redo = (c == C_UPDATE);
- if (!vrfy_update(&redo))
- if (c == C_UPDATE)
- break;
- if (isoff(glob_flags, CNTD_CMD))
- (void) cmd_line(sprintf(buf, "\\headers %d", current_msg+1),
- msg_list);
- }
-
- when C_EXIT : case C_EXIT_HARD :
- clr_bot_line();
- iscurses = FALSE;
- if (c != C_EXIT && c != C_EXIT_HARD)
- putchar('\n');
- cleanup(0);
-
- /* change to a new folder */
- when C_FOLDER :
- for (;;) {
- SIGRET (*oldint)(), (*oldquit)();
- on_intr();
- print("New folder (?=list): ");
- c = Getstr(file, COLS-22, 0);
- off_intr();
- if (c > 0) {
- if (!strcmp(file, "?")) {
- clr_bot_line();
- iscurses = 0;
- puts("folders in your folder directory:");
- (void) cmd_line(strcpy(buf, "\\folders"), msg_list);
- puts("Precede folder names with a +. `%' to specify system mailbox.");
- turnon(glob_flags, CNTD_CMD), iscurses = 1;
- continue;
- }
- clearok(stdscr, FALSE);
- /* if vrfy_update doesn't verify, but folder command fails,
- * then we need to reset the updatability of current folder
- */
- c = (ison(glob_flags, DO_UPDATE))? TRUE : FALSE;
- if (strcmp(file, "-?")) {
- redo = 1; /* so vrfy_update() won't quit */
- (void) vrfy_update(&redo);
- }
- move(LINES-1, 0), refresh();
- if (cmd_line(sprintf(buf, "folder ! -N %s", file),
- msg_list) == -1) {
- if (c) /* remember state of updatability of folder */
- turnon(glob_flags, DO_UPDATE);
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- } else
- redo = 1, turnoff(glob_flags, CNTD_CMD);
- break;
- } else {
- print("\"%s\" unchanged.", mailfile);
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- break;
- }
- }
-
- /* shell escape */
- when C_SHELL_ESC :
- print("Shell command: ");
- if (Getstr(file, COLS-24, 0) < 0)
- clr_bot_line();
- else {
- putchar('\n');
- iscurses = FALSE;
- (void) cmd_line(sprintf(buf, "sh %s", file), msg_list);
- iscurses = TRUE;
- turnon(glob_flags, CNTD_CMD);
- }
-
- /* do a line-mode like command */
- when C_CURSES_ESC :
- print(":");
- if (Getstr(buf, COLS-2, 0) < 0)
- break;
- putchar('\n');
- iscurses = FALSE;
- if (!*buf) {
- /* return -1 because iscurses = 0 is not enough! */
- redo = 0;
- endwin(); /* this turns echoing back on! */
- echo_off();
- return -1;
- }
- /* The "source" and "curses" commands need some indication
- * that we are in curses mode, so use the PRE_CURSES flag.
- */
- turnon(glob_flags, PRE_CURSES);
- (void) cmd_line(buf, msg_list);
- /* they may have affected message status or had text output */
- turnon(glob_flags, CNTD_CMD), redo = 1;
- turnoff(glob_flags, PRE_CURSES);
- iscurses = TRUE;
- if (msg_cnt)
- puts(compose_hdr(current_msg));
-
- /* send message to printer, redo to display 'p' status */
- when C_PRINT_MSG : redo = (lpr(0, DUBL_NULL, msg_list) == 0);
-
- /* cd */
- when C_CHDIR :
- print("chdir to [~]: ");
- if (Getstr(file, COLS-12, 0) < 0)
- break;
- clr_bot_line();
- (void) cmd_line(sprintf(buf, "cd %s", file), msg_list);
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
-
- /* variable settings */
- when C_VAR_SET : case C_IGNORE : case C_ALIAS : case C_OWN_HDR :
- curs_vars(c); /* CNTD_CMD is reset if there's output! */
-
- when C_VERSION :
- (void) do_version();
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
-
- when C_MAIL_FLAGS :
- print("flags [-?]: ");
- if ((c = Getstr(file, COLS-12, 0)) < 0)
- break;
- putchar('\n');
- if (c == 0)
- (void) strcpy(file, "-?");
- else
- redo = 1; /* In case of -f flag, to display the 'f' status */
- /* Fall thru */
- case C_MAIL : {
- u_long flgs = glob_flags;
- turnon(glob_flags, IGN_BANG);
- clr_bot_line();
- iscurses = FALSE;
- (void) cmd_line(sprintf(buf, "mail %s", file), msg_list);
- glob_flags = flgs;
- iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
- if (msg_cnt)
- print("%-.*s", COLS-2, compose_hdr(current_msg)), putchar('\n');
- }
-
- /* reply to mail */
- when C_REPLY_SENDER : case C_REPLY_ALL : {
- register char *p = (c == C_REPLY_ALL)? "replyall" : "replysender";
- clr_bot_line();
- iscurses = FALSE;
- if (isoff(msg[current_msg].m_flags, REPLIED))
- redo = 1;
- (void) cmd_line(sprintf(buf, "%s %d", p, current_msg+1),
- msg_list);
- if (msg_cnt)
- puts(compose_hdr(current_msg));
- iscurses = TRUE, turnon(glob_flags, CNTD_CMD);
- }
-
- /* type out a message */
- when C_DISPLAY_MSG : case C_TOP_MSG : case C_DISPLAY_NEXT :
- if (!msg_cnt ||
- c != C_DISPLAY_NEXT && ison(msg[current_msg].m_flags, DELETE)) {
- if (!msg_cnt)
- print("No messages.");
- else
- print("Message %d deleted; type 'u' to undelete.",
- current_msg+1);
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- break;
- }
- clr_bot_line();
- iscurses = FALSE;
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- if (c == C_DISPLAY_MSG)
- c = cmd_line(strcpy(buf, "type"), msg_list);
- else if (c == C_TOP_MSG)
- c = cmd_line(strcpy(buf, "top"), msg_list);
- else {
- /* "next" screws up the screen whether it displays or not */
- (void) cmd_line(strcpy(buf, "next"), msg_list);
- c = 0;
- }
- if (c > -1)
- turnon(glob_flags, CNTD_CMD), redo = 1;
- iscurses = TRUE;
- puts(compose_hdr(current_msg));
-
- /* bind a key or string to a curses-mode command */
- when C_BIND : case C_UNBIND : case C_MAP : case C_BIND_MACRO :
- case C_MAP_BANG : {
- char *argv[2];
- argv[0] = (c == C_BIND) ? "bind" :
- (c == C_UNBIND) ? "unbind" :
- (c == C_MAP) ? "map" :
- (c == C_MAP_BANG) ? "map!" : "bind-macro";
- argv[1] = NULL;
- if (bind_it(1, argv) < -1)
- turnon(glob_flags, CNTD_CMD);
- else if (ison(glob_flags, CNTD_CMD)) /* if it was set anyway */
- putchar('\n');
- else
- (void) curses_help_msg(TRUE);
- }
-
- when C_MACRO :
- turnon(glob_flags, IN_MACRO);
- /* Current macro should already be in the mac_stack, so
- * all we have to do here is look for the next character
- */
-
- /* help stuff */
- when C_HELP :
- move(LINES-1, 0), refresh();
- (void) help(0, "curses", cmd_help);
- turnon(glob_flags, CNTD_CMD);
- if (msg_cnt)
- puts(compose_hdr(current_msg));
-
- otherwise :
- mac_flush();
- bell();
- if (ison(glob_flags, CNTD_CMD)) {
- /* use print instead of puts to overwrite hit_return msg */
- print("unknown command"), putchar('\n');
- redo = 1;
- }
- }
-
- if (ison(glob_flags, CNTD_CMD)) {
- int old_cnt = msg_cnt;
- if (!(c = hit_return()) && !redo && msg_cnt == old_cnt)
- redraw();
- clr_bot_line();
- if (old_cnt != msg_cnt)
- redo = 1;
- if (c)
- return c;
- }
- if (redo) {
- set_screen_size(); /* it may have changed */
- n = current_msg;
- clear();
- if (/* msg_cnt < screen || */ n_array[0] < n && n < n_array[screen-1])
- (void) do_hdrs(0, DUBL_NULL, NULL);
- else
- (void) cmd_line(sprintf(buf, "\\headers %d", n+1), msg_list);
- (void) curses_help_msg(TRUE);
- redo = 0;
- }
- return 0;
- }
-
- vrfy_update(redo)
- int *redo;
- {
- char buf[16];
- int c;
-
- /* update current folder */
- if (ison(glob_flags, DO_UPDATE)) {
- if (ison(glob_flags, READ_ONLY)) {
- mac_flush();
- print("Folder is read-only.");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- return 0;
- }
- print("Update folder [y]? ");
- if ((c = getchar()) != 'y' && c != 'Y' && c != '\n' && !isspace(c)) {
- print("Folder unchanged.");
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- return 0;
- }
- } else if (*redo)
- return 1;
- if (cmd_line(strcpy(buf, *redo? "update" : "quit"), msg_list) != -1
- && ison(glob_flags, CNTD_CMD))
- *redo = 1, turnoff(glob_flags, CNTD_CMD);
- turnoff(glob_flags, DO_UPDATE);
- return 1; /* make sure bottom line is clear and no reverse video */
- }
-
- scrn_line(line, buf)
- char *buf;
- {
- #ifndef A_CHARTEXT
- (void) strncpy(buf, stdscr->_y[line], COLS-1);
- buf[COLS-1] = 0; /* strncpy does not null terminate */
- #else
- int n;
-
- for (n = 0; n < COLS; n++)
- if ((buf[n] = (mvinch(line, n) & A_CHARTEXT)) == '\0')
- break;
- buf[n] = '\0';
- #endif /* A_CHARTEXT */
- }
-
- /*
- * Generate the help message from the variable curses_help.
- * If visible is true, the message is displayed,
- * otherwise its size (in lines) is computed and returned.
- */
- curses_help_msg(visible)
- int visible;
- {
- int count, i, len, siz = 0, mxm = 0;
- static int old_siz = 0;
- register struct cmd_map *list;
- extern struct cmd_map map_func_names[];
- char *curs_help = do_set(set_options, "curses_help"), **format;
-
- if (!curs_help) {
- if (old_siz && visible) {
- int bot = min(n_array[screen-1], msg_cnt-1);
- move(max(0, bot - n_array[0]) + 2, 0), clrtobot();
- old_siz = 0;
- }
- return 0;
- } else if (!*curs_help)
- curs_help = DEF_CURSES_HELP;
- /* Split the help string into words */
- if (!(format = mk_argv(curs_help, &count, FALSE)) || count <= 0)
- return 0;
- /* Generate a help message for each word */
- for (i = 0; i < count; i++) {
- char buf[MAX_BIND_LEN*2+MAX_LONG_CMD+5], asc[MAX_BIND_LEN*2];
-
- buf[0] = '\0'; /* default to empty in case of no match */
- for (list = cmd_map; list; list = list->m_next) {
- if (!strcmp(format[i], map_func_names[list->m_cmd].m_str)) {
- len = strlen(sprintf(buf, "(%s) %s ",
- ctrl_strcpy(asc, list->m_str, FALSE),
- map_func_names[list->m_cmd].m_str));
- if (len > mxm)
- mxm = len;
- break;
- }
- }
- strdup(format[i], buf); /* replace word with its "definition" */
- }
- /* Columnate the output nicely */
- if (mxm > 0) {
- len = (COLS - 1) / mxm;
- if (len == 0) {
- if (visible)
- print("Curses help message too long!");
- return 0;
- }
- siz = count / len;
- if (count % len)
- siz++;
- if (siz > LINES / 3) {
- if (visible)
- print("Curses help message too long!");
- return 0;
- }
- if (visible) {
- int next = LINES - 1 - siz;
- if (old_siz > siz) {
- int bot = min(n_array[screen-1], msg_cnt-1);
- move(max(0, bot - n_array[0]) + 2, 0), clrtobot();
- }
- old_siz = siz;
- for (i = 0; i < count; i++) {
- if (!(i % len))
- move(next, 0), clrtoeol(), ++next;
- if (format[i][0])
- printw("%-*.*s", mxm, mxm, format[i]);
- }
- refresh();
- }
- }
- free_vec(format);
- return siz;
- }
-
- set_screen_size()
- {
- int hlp_siz = LINES - 2 - curses_help_msg(FALSE);
-
- if (!do_set(set_options, "screen"))
- #ifdef USG
- switch (_tty.sg_ospeed & CBAUD)
- #else /* USG */
- switch (_tty.sg_ospeed)
- #endif /* USG */
- {
- case B300 : screen = min(hlp_siz, 7);
- when B1200 : screen = min(hlp_siz, 14);
- when B2400 : screen = min(hlp_siz, 22);
- otherwise : screen = hlp_siz;
- }
- else
- screen = min(screen, hlp_siz);
- }
-
- /*
- * prompt for a carriage return, but return whatever user types unless
- * it's a character which he might regret (like 'q' or 'x'). Ignore
- * interrupts (kind of) because we have nowhere to longjmp to. When we
- * return, we'll setjmp again (top of loop.c)
- */
- hit_return()
- {
- int c;
-
- turnon(glob_flags, IGN_SIGS);
- iscurses = FALSE;
- (void) check_new_mail();
- iscurses = TRUE;
- mail_status(1), addstr("...continue... "), refresh();
- c = getcmd();
- turnoff(glob_flags, IGN_SIGS);
-
- /* don't let the user type something he might regret */
- if (c == C_QUIT || c == C_EXIT)
- return C_NULL;
- return c;
- }
-
- curses_msg_list(str, list, m_list)
- register char *str, *list;
- char m_list[];
- {
- register char *p = NULL;
- int c, sv_cur_msg = current_msg;
-
- print(str);
- c = Getstr(list, COLS-13, 0);
- move(LINES-1, 0), refresh();
- if (c <= 0 || !(p = do_range(list, m_list)) ||
- (p == list && *p && *p != '$' && *p != '^')) {
- if (p)
- print("Invalid message list: %s", p);
- current_msg = sv_cur_msg;
- return 0;
- }
- current_msg = sv_cur_msg;
- return 1;
- }
-
- curs_vars(which)
- int which; /* really, a char */
- {
- char c, buf[128], buf2[128], *string;
- struct options **list;
-
- switch(which) {
- case C_OWN_HDR : string = "my_hdr", list = &own_hdrs;
- when C_ALIAS : string = "alias", list = &aliases;
- when C_IGNORE : string = "ignore", list = &ignore_hdr;
- when C_VAR_SET : string = "set", list = &set_options;
- otherwise : clr_bot_line(); return;
- }
-
- print("%s [? Set Unset All]: ", string);
- c = m_getchar();
- clr_bot_line();
- switch (Lower(c)) {
- /* if help, print help -- if "all", show all settings. */
- case '?' : case 'a' :
- if (c == '?') {
- if (!strcmp(string, "set")) {
- print("which variable? [all <var>]: ");
- if ((c = Getstr(buf+1, COLS-40, 0)) < 0)
- return;
- clr_bot_line();
- buf[0] = '?';
- if (c > 0) {
- char *argv[3];
- argv[0] = string;
- argv[1] = buf;
- argv[2] = NULL;
- Lower(buf[1]);
- if (!strcmp(buf+1, "a"))
- (void) strcpy(buf+1, "all");
- if (!strcmp(buf+1, "all"))
- turnon(glob_flags, CNTD_CMD);
- (void) set(2, argv, (char *) 0);
- break;
- }
- }
- /* help returns next command (hit_return) */
- (void) help(0, string, cmd_help);
- turnon(glob_flags, CNTD_CMD);
- return;
- }
- turnon(glob_flags, CNTD_CMD);
- (void) do_set(*list, NULL);
-
- /* if set, prompt for string and let user type */
- when 's' :
- print("set: ");
- c = Getstr(buf, COLS-18, 0);
- clr_bot_line();
- if (c > 0)
- (void) cmd_line(sprintf(buf2, "%s %s", string, buf), msg_list);
-
- /* if unset, just as easy as set! */
- when 'u' :
- print("unset: ", string);
- if (Getstr(buf, COLS-18, 0) > 0 && !un_set(list, buf))
- print("%s isn't set", buf);
- }
- if (ison(glob_flags, CNTD_CMD))
- putchar('\n');
- else
- (void) curses_help_msg(TRUE);
- }
- #endif /* CURSES */
-