📄 curs_lib.c
字号:
/* * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org> * Copyright (C) 2004 g10 Code GmbH * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mutt_menu.h"#include "mutt_curses.h"#include "pager.h"#include "mbyte.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>#ifdef HAVE_LANGINFO_YESEXPR#include <langinfo.h>#endif/* 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. */size_t UngetCount = 0;static size_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; event_t err = {-1, OP_NULL }, ret; if (!option(OPTUNBUFFEREDINPUT) && UngetCount) return (KeyEvent[--UngetCount]); SigInt = 0; mutt_allow_interrupt (1);#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 (); mutt_allow_interrupt (0); if (SigInt) mutt_query_exit (); 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);}int _mutt_get_field (/* const */ char *field, char *buf, size_t buflen, int complete, int multiple, char ***files, int *numfiles){ int ret; int x, y; ENTER_STATE *es = mutt_new_enter_state(); do { CLEARLINE (LINES-1); addstr (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); mutt_free_enter_state (&es); return (ret);}int mutt_get_field_unbuffered (char *msg, char *buf, size_t buflen, int flags){ int rc; set_option (OPTUNBUFFEREDINPUT); rc = mutt_get_field (msg, buf, buflen, flags); unset_option (OPTUNBUFFEREDINPUT); return (rc);}void mutt_clear_error (void){ Errorbuf[0] = 0; if (!option(OPTNOCURSES)) CLEARLINE (LINES-1);}void mutt_edit_file (const char *editor, const char *data){ char cmd[LONG_STRING]; mutt_endwin (NULL); mutt_expand_file_fmt (cmd, sizeof (cmd), editor, data); if (mutt_system (cmd) == -1) mutt_error (_("Error running \"%s\"!"), cmd); keypad (stdscr, TRUE); clearok (stdscr, TRUE);}int mutt_yesorno (const char *msg, int def){ event_t ch; char *yes = _("yes"); char *no = _("no"); char *answer_string; size_t answer_string_len;#ifdef HAVE_LANGINFO_YESEXPR char *expr; regex_t reyes; regex_t reno; int reyes_ok; int reno_ok; char answer[2]; answer[1] = 0; reyes_ok = (expr = nl_langinfo (YESEXPR)) && expr[0] == '^' && !regcomp (&reyes, expr, REG_NOSUB|REG_EXTENDED); reno_ok = (expr = nl_langinfo (NOEXPR)) && expr[0] == '^' && !regcomp (&reno, expr, REG_NOSUB|REG_EXTENDED);#endif CLEARLINE(LINES-1); /* * In order to prevent the default answer to the question to wrapped * around the screen in the even the question is wider than the screen, * ensure there is enough room for the answer and truncate the question * to fit. */ answer_string = safe_malloc (COLS + 1); snprintf (answer_string, COLS + 1, " ([%s]/%s): ", def == M_YES ? yes : no, def == M_YES ? no : yes); answer_string_len = strlen (answer_string); printw ("%.*s%s", COLS - answer_string_len, msg, answer_string); FREE (&answer_string); FOREVER { mutt_refresh (); ch = mutt_getch (); if (CI_is_return (ch.ch)) break; if (ch.ch == -1) { def = -1; break; }#ifdef HAVE_LANGINFO_YESEXPR answer[0] = ch.ch; if (reyes_ok ? (regexec (& reyes, answer, 0, 0, 0) == 0) :#else if (#endif (tolower (ch.ch) == 'y')) { def = M_YES; break; } else if (#ifdef HAVE_LANGINFO_YESEXPR reno_ok ? (regexec (& reno, answer, 0, 0, 0) == 0) :#endif (tolower (ch.ch) == 'n')) { def = M_NO; break; } else { BEEP(); } }#ifdef HAVE_LANGINFO_YESEXPR if (reyes_ok) regfree (& reyes); if (reno_ok) regfree (& reno);#endif if (def != -1) { addstr ((char *) (def == M_YES ? 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?"), M_YES) == M_YES) { endwin (); exit (1); } mutt_clear_error(); mutt_curs_set (-1); SigInt = 0;}void mutt_curses_error (const char *fmt, ...){ va_list ap; va_start (ap, fmt); vsnprintf (Errorbuf, sizeof (Errorbuf), fmt, ap); va_end (ap); dprint (1, (debugfile, "%s\n", Errorbuf)); mutt_format_string (Errorbuf, sizeof (Errorbuf), 0, COLS-2, 0, 0, Errorbuf, sizeof (Errorbuf), 0); if (!option (OPTKEEPQUIET)) { BEEP (); SETCOLOR (MT_COLOR_ERROR); mvaddstr (LINES-1, 0, Errorbuf); clrtoeol (); SETCOLOR (MT_COLOR_NORMAL); mutt_refresh (); } set_option (OPTMSGERR);}void mutt_curses_message (const char *fmt, ...){ va_list ap; va_start (ap, fmt); vsnprintf (Errorbuf, sizeof (Errorbuf), fmt, ap); va_end (ap); mutt_format_string (Errorbuf, sizeof (Errorbuf), 0, COLS-2, 0, 0, Errorbuf, sizeof (Errorbuf), 0); if (!option (OPTKEEPQUIET)) { SETCOLOR (MT_COLOR_MESSAGE); mvaddstr (LINES - 1, 0, Errorbuf); clrtoeol (); SETCOLOR (MT_COLOR_NORMAL); mutt_refresh (); } unset_option (OPTMSGERR);}#ifdef USE_SOCKETvoid mutt_progress_bar (progress_t* progress, long pos){ char posstr[SHORT_STRING]; if (!pos) { if (!NetInc) mutt_message (progress->msg); else { if (progress->size) mutt_pretty_size (progress->sizestr, sizeof (progress->sizestr), progress->size); progress->pos = 0; } } if (!NetInc) return; if (pos >= progress->pos + (NetInc << 10)) { progress->pos = pos; pos = pos / (NetInc << 10) * (NetInc << 10); mutt_pretty_size (posstr, sizeof (posstr), pos); if (progress->size) mutt_message ("%s %s/%s", progress->msg, posstr, progress->sizestr); else mutt_message ("%s %s", progress->msg, posstr); }}#endifvoid 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);}void mutt_endwin (const char *msg){ 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -