diff options
Diffstat (limited to 'curs_lib.c')
-rw-r--r-- | curs_lib.c | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/curs_lib.c b/curs_lib.c new file mode 100644 index 00000000..c2177fc2 --- /dev/null +++ b/curs_lib.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "mutt.h" +#include "mutt_menu.h" +#include "mutt_curses.h" +#include "pager.h" + +#include <termios.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.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 + * buffering routines. + */ +static short UngetCount = 0; + +#define UngetBufLen 128 +static int UngetBuf[UngetBufLen]; + +void mutt_refresh (void) +{ + /* don't refresh in the middle of macros unless necessary */ + if (!UngetCount || option (OPTFORCEREFRESH)) + refresh (); +} + +int mutt_getch (void) +{ + int ch; + + if (UngetCount) + return (UngetBuf[--UngetCount]); + + Signals &= ~S_INTERRUPT; + +#ifdef KEY_RESIZE + /* ncurses 4.2 sends this when the screen is resized */ + ch = KEY_RESIZE; + while (ch == KEY_RESIZE) +#endif /* KEY_RESIZE */ + ch = getch (); + + if (Signals & S_INTERRUPT) + mutt_query_exit (); + + if ((ch & 0x80) && option (OPTMETAKEY)) + { + /* send ALT-x as ESC-x */ + ch &= ~0x80; + mutt_ungetch (ch); + return ('\033'); + } + + return (ch == ctrl ('G') ? ERR : ch); +} + +int mutt_get_field (/* const */ char *field, char *buf, size_t buflen, int complete) +{ + int ret; + int len = strlen (field); /* in case field==buffer */ + + do + { + CLEARLINE (LINES-1); + addstr (field); + mutt_refresh (); + ret = mutt_enter_string ((unsigned char *) buf, buflen, LINES-1, len, complete); + } + while (ret == 1); + CLEARLINE (LINES-1); + return (ret); +} + +int mutt_get_password (char *msg, char *buf, size_t buflen) +{ + int rc; + + CLEARLINE (LINES-1); + addstr (msg); + rc = mutt_enter_string ((unsigned char *) buf, buflen, LINES - 1, strlen (msg), M_PASS); + CLEARLINE (LINES-1); + return (rc); +} + +void mutt_clear_error (void) +{ + Errorbuf[0] = 0; + CLEARLINE (LINES-1); +} + +void mutt_edit_file (const char *editor, const char *data) +{ + char cmd[LONG_STRING]; + + endwin (); + mutt_expand_fmt (cmd, sizeof (cmd), editor, data); + mutt_system (cmd); + keypad (stdscr, TRUE); + clearok (stdscr, TRUE); +} + +int mutt_yesorno (const char *msg, int def) +{ + int ch; + + CLEARLINE(LINES-1); + printw("%s: [%c] ", msg, def ? 'y' : 'n'); + FOREVER + { + mutt_refresh (); + ch = mutt_getch (); + if (ch == ERR) return(-1); + if (CI_is_return (ch)) + break; + else if (ch == 'y') + { + def = 1; + break; + } + else if (ch == 'n') + { + def = 0; + break; + } + else + { + BEEP(); + } + } + addstr (def ? "Yes" : "No"); + mutt_refresh (); + return (def); +} + +/* this function is called when the user presses the abort key */ +void mutt_query_exit (void) +{ + mutt_flushinp (); + curs_set (1); + if (Timeout) + timeout (-1); /* restore blocking operation */ + if (mutt_yesorno ("Exit Mutt?", 1) == 1) + { + endwin (); + exit (0); + } + mutt_curs_set (-1); + Signals &= ~S_INTERRUPT; +} + +void mutt_curses_error (const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + vsnprintf (Errorbuf, sizeof (Errorbuf), fmt, ap); + va_end (ap); + + Errorbuf[ (COLS < sizeof (Errorbuf) ? COLS : sizeof (Errorbuf)) - 2 ] = 0; + + BEEP (); + SETCOLOR (MT_COLOR_ERROR); + mvaddstr (LINES-1, 0, Errorbuf); + clrtoeol (); + SETCOLOR (MT_COLOR_NORMAL); + mutt_refresh (); + + set_option (OPTMSGERR); +} + +void mutt_message (const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + vsnprintf (Errorbuf, sizeof (Errorbuf), fmt, ap); + va_end (ap); + + Errorbuf[ (COLS < sizeof (Errorbuf) ? COLS : sizeof (Errorbuf)) - 2 ] = 0; + + SETCOLOR (MT_COLOR_MESSAGE); + mvaddstr (LINES - 1, 0, Errorbuf); + clrtoeol (); + SETCOLOR (MT_COLOR_NORMAL); + mutt_refresh (); + + unset_option (OPTMSGERR); +} + +void mutt_show_error (void) +{ + SETCOLOR (option (OPTMSGERR) ? MT_COLOR_ERROR : MT_COLOR_MESSAGE); + CLEARLINE (LINES-1); + addstr (Errorbuf); + SETCOLOR (MT_COLOR_NORMAL); +} + +void mutt_endwin (const char *msg) +{ + move (LINES - 1, COLS - 1); + attrset (A_NORMAL); + mutt_refresh (); + endwin (); + fputc ('\n', stdout); + if (msg) + puts (msg); +} + +void mutt_perror (const char *s) +{ + char *p = strerror (errno); + + mutt_error ("%s: %s (errno = %d)", s, p ? p : "unknown error", errno); +} + +int mutt_any_key_to_continue (const char *s) +{ + struct termios t; + struct termios old; + int f, ch; + + f = open ("/dev/tty", O_RDONLY); + tcgetattr (f, &t); + memcpy ((void *)&old, (void *)&t, sizeof(struct termios)); /* save original state */ + t.c_lflag &= ~(ICANON | ECHO); + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + tcsetattr (f, TCSADRAIN, &t); + fflush (stdout); + if (s) + fputs (s, stdout); + else + fputs ("Press any key to continue...", stdout); + fflush (stdout); + ch = fgetc (stdin); + fflush (stdin); + tcsetattr (f, TCSADRAIN, &old); + close (f); + fputs ("\r\n", stdout); + return (ch); +} + +int mutt_do_pager (const char *banner, + const char *tempfile, + int do_color, + pager_t *info) +{ + int rc; + + if (strcmp (Pager, "builtin") == 0) + rc = mutt_pager (banner, tempfile, do_color, info); + else + { + char cmd[STRING]; + + endwin (); + snprintf (cmd, sizeof (cmd), "%s %s", Pager, tempfile); + mutt_system (cmd); + mutt_unlink (tempfile); + rc = 0; + } + + return rc; +} + +int mutt_enter_fname (const char *prompt, char *buf, size_t blen, int *redraw, int buffy) +{ + int i; + + mvaddstr (LINES-1, 0, (char *) prompt); + addstr (" ('?' for list): "); + if (buf[0]) + addstr (buf); + clrtoeol (); + mutt_refresh (); + + if ((i = mutt_getch ()) == ERR) + { + CLEARLINE (LINES-1); + return (-1); + } + else if (i == '?') + { + mutt_refresh (); + buf[0] = 0; + mutt_select_file (buf, blen, 0); + *redraw = REDRAW_FULL; + } + else + { + char *pc = safe_malloc (strlen (prompt) + 3); + + sprintf (pc, "%s: ", prompt); + mutt_ungetch (i); + if (mutt_get_field (pc, buf, blen, (buffy ? M_EFILE : M_FILE) | M_CLEAR) + != 0) + buf[0] = 0; + MAYBE_REDRAW (*redraw); + free (pc); + } + + return 0; +} + +/* FOO - this could be made more efficient by allocating/deallocating memory + * instead of using a fixed array + */ +void mutt_ungetch (int ch) +{ + if (UngetCount < UngetBufLen) /* make sure not to overflow */ + UngetBuf[UngetCount++] = ch; +} + +void mutt_flushinp (void) +{ + UngetCount = 0; + flushinp (); +} + +#if (defined(USE_SLANG_CURSES) || defined(HAVE_CURS_SET)) +/* The argument can take 3 values: + * -1: restore the value of the last call + * 0: make the cursor invisible + * 1: make the cursor visible + */ +void mutt_curs_set (int cursor) +{ + static int SavedCursor = 1; + + if (cursor < 0) + cursor = SavedCursor; + else + SavedCursor = cursor; + + curs_set (cursor); +} +#endif |