X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-ui%2Fcurs_lib.c;h=e8fb02e386ab728c5d357da55503a3d9fa471205;hp=c50c18d2883d57c67dabc5d839af138da123625b;hb=16be8d10413bbcf822577afd4019d65aba7459e0;hpb=c9b049f668148dab6ae90f32de6a4981f673bfa1 diff --git a/lib-ui/curs_lib.c b/lib-ui/curs_lib.c index c50c18d..e8fb02e 100644 --- a/lib-ui/curs_lib.c +++ b/lib-ui/curs_lib.c @@ -11,27 +11,22 @@ * please see the file GPL in the top level source directory. */ -#include +#include -#include -#ifdef HAVE_SYS_IOCTL_H -# include -#elif defined(HAVE_IOCTL_H) -# include -#endif #include +#include #include #include #include -#include "curses.h" #include "menu.h" #include "enter.h" #include "mutt.h" #include "pager.h" #include "charset.h" +#include "madtty.h" /* not possible to unget more than one char under some curses libs, and it * is impossible to unget function keys in SLang, so roll our own input @@ -41,33 +36,6 @@ ssize_t UngetCount = 0; static ssize_t UngetBufLen = 0; static event_t *KeyEvent; -void mutt_refresh (void) -{ - /* don't refresh when we are waiting for a child. */ - if (option (OPTKEEPQUIET)) - return; - - /* don't refresh in the middle of macros unless necessary */ - if (UngetCount && !option (OPTFORCEREFRESH)) - return; - - /* else */ - refresh (); -} - -/* Make sure that the next refresh does a full refresh. This could be - optmized by not doing it at all if DISPLAY is set as this might - indicate that a GUI based pinentry was used. Having an option to - customize this is of course the Mutt way. */ -void mutt_need_hard_redraw (void) -{ - if (!getenv ("DISPLAY")) { - keypad (stdscr, TRUE); - clearok (stdscr, TRUE); - set_option (OPTNEEDREDRAW); - } -} - event_t mutt_getch (void) { int ch; @@ -79,7 +47,7 @@ event_t mutt_getch (void) SigInt = 0; mutt_allow_interrupt (1); - ch = getch (); + ch = getch(); mutt_allow_interrupt (0); if (SigInt) @@ -88,20 +56,27 @@ event_t mutt_getch (void) if (ch == ERR) return err; - if ((ch & 0x80) && option (OPTMETAKEY)) { - /* send ALT-x as ESC-x */ - ch &= ~0x80; - mutt_ungetch (ch, 0); - ret.ch = '\033'; - ret.op = 0; - return ret; - } - ret.ch = ch; ret.op = 0; return (ch == ctrl ('G') ? err : ret); } +#ifndef waddnwstr +int waddwch(WINDOW *win, wchar_t wc) +{ + char buf[MB_LEN_MAX * 2]; + mbstate_t mbstate; + ssize_t n1, n2; + + p_clear(&mbstate, 1); + if ((n1 = wcrtomb(buf, wc, &mbstate)) == -1 + || (n2 = wcrtomb(buf + n1, 0, &mbstate)) == -1) + return -1; /* ERR */ + return waddstr(win, buf); +} +#endif + + int _mutt_get_field ( const char *field, char *buf, ssize_t buflen, int complete, int multiple, char ***files, int *numfiles) { @@ -111,14 +86,14 @@ int _mutt_get_field ( const char *field, char *buf, ssize_t buflen, ENTER_STATE *es = mutt_new_enter_state (); do { - CLEARLINE (LINES - 1); - addstr (field); + CLEARLINE(stdscr, LINES - 1); + waddstr (stdscr, field); mutt_refresh (); getyx (stdscr, y, x); ret = _mutt_enter_string(buf, buflen, y, x, complete, multiple, files, numfiles, es); } while (ret == 1); - CLEARLINE (LINES - 1); + CLEARLINE(stdscr, LINES - 1); mutt_free_enter_state (&es); return (ret); @@ -139,19 +114,86 @@ void mutt_clear_error (void) { Errorbuf[0] = 0; if (!option (OPTNOCURSES)) - CLEARLINE (LINES - 1); + CLEARLINE(stdscr, LINES - 1); +} + +static struct timeval const slice = { 0, 1000 * 1000 / 100 }; +static struct timeval timeval_add(struct timeval a, struct timeval b) +{ + int usec = a.tv_usec + b.tv_usec; + a.tv_sec += b.tv_sec; + while (usec > 1000 * 1000) { + a.tv_sec += 1; + usec -= 1000 * 1000; + } + a.tv_usec = usec; + return a; +} + +static int is_expired(struct timeval now, struct timeval expiry) +{ + return now.tv_sec > expiry.tv_sec + || (now.tv_sec == expiry.tv_sec && now.tv_usec > expiry.tv_usec); } void mutt_edit_file(const char *data) { - char cmd[LONG_STRING]; - - mutt_endwin (NULL); - m_quotefile_fmt(cmd, sizeof (cmd), mod_core.editor, data); - if (mutt_system (cmd) == -1) - mutt_error (_("Error running \"%s\"!"), cmd); - keypad (stdscr, TRUE); - clearok (stdscr, TRUE); + char cmd[STRING]; + const char *args[] = { "/bin/sh", "-c", cmd, NULL }; + int dirty = 0, ch, res, mh, mw, pty, pid; + struct timeval next; + madtty_t *rt; + + m_quotefile_fmt(cmd, sizeof(cmd), mod_core.editor, data); + getmaxyx(main_w, mh, mw); + SigChild = 0; + + rt = madtty_create(mh - 2, mw); + pid = madtty_forkpty(rt, args[0], args, &pty); + if (pid < 0) { + madtty_destroy(rt); + mutt_error(_("unable to start editor")); + return; + } + + SETCOLOR(main_w, MT_COLOR_SIDEBAR); + mvwhline(main_w, 0, 0, ACS_HLINE, mw); + + nodelay(stdscr, true); + gettimeofday(&next, NULL); + while (!SigChild) { + struct timeval tv = { 0, 1000 * 1000 / 100 }; + fd_set rfds; + + FD_ZERO(&rfds); + FD_SET(0, &rfds); + FD_SET(pty, &rfds); + + if (select(pty + 1, &rfds, NULL, NULL, &tv) < 0) + break; + + if (FD_ISSET(pty, &rfds)) { + madtty_process(rt); + dirty = 1; + } + + while ((ch = getch()) != ERR) { + madtty_keypress(rt, ch); /* pass the keypress for handling */ + dirty = 1; + } + + gettimeofday(&tv, NULL); + if (dirty && is_expired(tv, next)) { + madtty_draw(rt, main_w, 1, 0); + wrefresh(main_w); + dirty = 0; + next = timeval_add(tv, slice); + } + } + while (waitpid(pid, &res, 0) < 0 && errno == EINTR); + nodelay(stdscr, false); + close(pty); + madtty_destroy(rt); } int mutt_yesorno (const char *msg, int def) @@ -175,7 +217,7 @@ int mutt_yesorno (const char *msg, int def) reno_ok = (expr = nl_langinfo (NOEXPR)) && expr[0] == '^' && !regcomp (&reno, expr, REG_NOSUB | REG_EXTENDED); - CLEARLINE (LINES - 1); + CLEARLINE(stdscr, LINES - 1); /* * In order to prevent the default answer to the question to wrapped @@ -183,11 +225,11 @@ int mutt_yesorno (const char *msg, int def) * ensure there is enough room for the answer and truncate the question * to fit. */ - answer_string = p_new(char, COLS + 1); - snprintf (answer_string, COLS + 1, " ([%s]/%s): ", def == M_YES ? yes : no, + answer_string = p_new(char, getmaxx(stdscr) + 1); + snprintf (answer_string, getmaxx(stdscr) + 1, " ([%s]/%s): ", def == M_YES ? yes : no, def == M_YES ? no : yes); answer_string_len = m_strlen(answer_string); - printw ("%.*s%s", COLS - answer_string_len, msg, answer_string); + wprintw (stdscr, "%.*s%s", getmaxx(stdscr) - answer_string_len, msg, answer_string); p_delete(&answer_string); for (;;) { @@ -222,9 +264,10 @@ int mutt_yesorno (const char *msg, int def) regfree (&reno); if (def != -1) { - addstr ((char *) (def == M_YES ? yes : no)); + waddstr (stdscr, (char *) (def == M_YES ? yes : no)); mutt_refresh (); } + CLEARLINE(stdscr, LINES - 1); return (def); } @@ -234,10 +277,10 @@ void mutt_query_exit (void) mutt_flushinp (); curs_set (1); if (Timeout) - timeout (-1); /* restore blocking operation */ + wtimeout (stdscr, -1); /* restore blocking operation */ if (mutt_yesorno (_("Exit Madmutt?"), M_YES) == M_YES) { mutt_endwin (NULL); - exit (1); + mutt_exit(1); } mutt_clear_error (); mutt_curs_set (-1); @@ -254,15 +297,15 @@ void mutt_curses_error (const char *fmt, ...) va_end (ap); mutt_format_string (TmpErrorbuf, sizeof (TmpErrorbuf), - 0, COLS - 2, 0, 0, Errorbuf, sizeof (Errorbuf), 0); + 0, getmaxy(stdscr) - 2, 0, 0, Errorbuf, sizeof (Errorbuf), 0); snprintf (Errorbuf, sizeof (Errorbuf), "%s", TmpErrorbuf); /* overkill */ if (!option (OPTKEEPQUIET)) { BEEP (); - SETCOLOR (MT_COLOR_ERROR); - mvaddstr (LINES - 1, 0, Errorbuf); - clrtoeol (); - SETCOLOR (MT_COLOR_NORMAL); + SETCOLOR(stdscr, MT_COLOR_ERROR); + mvwaddstr (stdscr, LINES - 1, 0, Errorbuf); + wclrtoeol (stdscr); + SETCOLOR(stdscr, MT_COLOR_NORMAL); mutt_refresh (); } @@ -307,14 +350,14 @@ void mutt_curses_message (const char *fmt, ...) va_end (ap); mutt_format_string (TmpErrorbuf, sizeof (TmpErrorbuf), - 0, COLS - 2, 0, 0, Errorbuf, sizeof (Errorbuf), 0); + 0, getmaxx(stdscr) - 2, 0, 0, Errorbuf, sizeof (Errorbuf), 0); snprintf (Errorbuf, sizeof (Errorbuf), "%s", TmpErrorbuf); /* overkill */ if (!option (OPTKEEPQUIET)) { - SETCOLOR (MT_COLOR_MESSAGE); - mvaddstr (LINES - 1, 0, Errorbuf); - clrtoeol (); - SETCOLOR (MT_COLOR_NORMAL); + SETCOLOR(stdscr, MT_COLOR_MESSAGE); + mvwaddstr (stdscr, LINES - 1, 0, Errorbuf); + wclrtoeol (stdscr); + SETCOLOR(stdscr, MT_COLOR_NORMAL); mutt_refresh (); } @@ -326,32 +369,26 @@ void mutt_show_error (void) if (option (OPTKEEPQUIET)) return; - SETCOLOR (option (OPTMSGERR) ? MT_COLOR_ERROR : MT_COLOR_MESSAGE); - CLEARLINE (LINES - 1); - addstr (Errorbuf); - SETCOLOR (MT_COLOR_NORMAL); + SETCOLOR(stdscr, option (OPTMSGERR) ? MT_COLOR_ERROR : MT_COLOR_MESSAGE); + CLEARLINE(stdscr, LINES - 1); + waddstr (stdscr, Errorbuf); + SETCOLOR(stdscr, MT_COLOR_NORMAL); } -void mutt_endwin (const char *msg) +void curses_initialize(void) { - if (!option (OPTNOCURSES)) { - CLEARLINE (LINES - 1); - - attrset (A_NORMAL); - mutt_refresh (); - endwin (); - } - - if (msg && *msg) { - puts (msg); - fflush (stdout); - } -} - -void _mutt_perror (const char *s, const char* filename, int line) -{ - char *p = strerror (errno); - mutt_error ("%s: %s (errno = %d) from %s:%i", s, p ? p : _("unknown error"), errno, filename, line); + initscr(); + if (start_color() == ERR || !has_colors() || COLORS < 8) + mutt_exit(-1); + madtty_init_colors(); + ci_start_color(); + noecho(); + raw(); + keypad(stdscr, true); + typeahead(-1); + meta(stdscr, true); + curs_set(0); + ESCDELAY = 50; } int mutt_any_key_to_continue (const char *s) @@ -388,16 +425,16 @@ int _mutt_enter_fname (const char *prompt, char *buf, ssize_t blen, { event_t ch; - mvaddstr (LINES - 1, 0, (char *) prompt); - addstr (_(" ('?' for list): ")); + mvwaddstr(stdscr, LINES - 1, 0, (char *) prompt); + waddstr(stdscr, _(" ('?' for list): ")); if (buf[0]) - addstr (buf); - clrtoeol (); + waddstr (stdscr, buf); + wclrtoeol (stdscr); mutt_refresh (); ch = mutt_getch (); if (ch.ch == -1) { - CLEARLINE (LINES - 1); + CLEARLINE(stdscr, LINES - 1); return (-1); } else if (ch.ch == '?') { @@ -469,8 +506,8 @@ int mutt_multi_choice (const char *prompt, const char *letters) int choice; char *p; - mvaddstr (LINES - 1, 0, prompt); - clrtoeol (); + mvwaddstr (stdscr, LINES - 1, 0, prompt); + wclrtoeol (stdscr); for (;;) { mutt_refresh (); ch = mutt_getch (); @@ -492,29 +529,11 @@ int mutt_multi_choice (const char *prompt, const char *letters) } BEEP (); } - CLEARLINE (LINES - 1); + CLEARLINE(stdscr, LINES - 1); mutt_refresh (); return choice; } -/* - * addwch would be provided by an up-to-date curses library - */ - -int mutt_addwch (wchar_t wc) -{ - char buf[MB_LEN_MAX * 2]; - mbstate_t mbstate; - ssize_t n1, n2; - - p_clear(&mbstate, 1); - if ((n1 = wcrtomb(buf, wc, &mbstate)) == -1 || - (n2 = wcrtomb(buf + n1, 0, &mbstate)) == -1) - return -1; /* ERR */ - else - return addstr (buf); -} - ssize_t mutt_pretty_size(char *s, ssize_t len, ssize_t n) { if (n == 0) @@ -640,10 +659,10 @@ void mutt_format_s_tree (char *dest, ssize_t destlen, /* * mutt_paddstr (n, s) is almost equivalent to - * mutt_format_string (bigbuf, big, n, n, 0, ' ', s, big, 0), addstr (bigbuf) + * mutt_format_string (bigbuf, big, n, n, 0, ' ', s, big, 0), waddstr (main_w, bigbuf) */ -void mutt_paddstr (int n, const char *s) +void mutt_paddstr(WINDOW *win, int n, const char *s) { wchar_t wc; int w; @@ -663,44 +682,10 @@ void mutt_paddstr (int n, const char *s) if (w >= 0) { if (w > n) break; - addnstr ((char *) s, k); + waddnstr(win, (char *) s, k); n -= w; } } while (n-- > 0) - addch (' '); -} - -/* this routine should be called after receiving SIGWINCH */ -void mutt_resize_screen (void) -{ - char *cp; - int fd; - struct winsize w; - - int rows, cols; - - rows = -1; - cols = -1; - if ((fd = open ("/dev/tty", O_RDONLY)) != -1) { - if (ioctl (fd, TIOCGWINSZ, &w) != -1) { - rows = w.ws_row; - cols = w.ws_col; - } - close (fd); - } - if (rows <= 0) { - if ((cp = getenv ("LINES")) != NULL) { - rows = atoi (cp); - } - else - rows = 24; - } - if (cols <= 0) { - if ((cp = getenv ("COLUMNS")) != NULL) - cols = atoi (cp); - else - cols = 80; - } - resizeterm (rows, cols); + waddch(win, ' '); }