📄 enter.c
字号:
/* * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org> * Copyright (C) 2000 Edmund Grimley Evans <edmundo@rano.org> * * 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 "keymap.h"#include "history.h"#include <string.h>/* redraw flags for mutt_enter_string() */enum{ M_REDRAW_INIT = 1, /* go to end of line and redraw */ M_REDRAW_LINE /* redraw entire line */};static int my_wcwidth (wchar_t wc){ int n = wcwidth (wc); if (IsWPrint (wc) && n > 0) return n; if (!(wc & ~0x7f)) return 2; if (!(wc & ~0xffff)) return 6; return 10;}/* combining mark / non-spacing character */#define COMB_CHAR(wc) (IsWPrint (wc) && !wcwidth (wc))static int my_wcswidth (const wchar_t *s, size_t n){ int w = 0; while (n--) w += my_wcwidth (*s++); return w;}static int my_addwch (wchar_t wc){ int n = wcwidth (wc); if (IsWPrint (wc) && n > 0) return mutt_addwch (wc); if (!(wc & ~0x7f)) return printw ("^%c", ((int)wc + 0x40) & 0x7f); if (!(wc & ~0xffff)) return printw ("\\u%04x", (int)wc); return printw ("\\u%08x", (int)wc);}static size_t width_ceiling (const wchar_t *s, size_t n, int w1){ const wchar_t *s0 = s; int w = 0; for (; n; s++, n--) if ((w += my_wcwidth (*s)) > w1) break; return s - s0; }static void my_wcstombs (char *dest, size_t dlen, const wchar_t *src, size_t slen){ mbstate_t st; size_t k; /* First convert directly into the destination buffer */ memset (&st, 0, sizeof (st)); for (; slen && dlen >= MB_LEN_MAX; dest += k, dlen -= k, src++, slen--) if ((k = wcrtomb (dest, *src, &st)) == (size_t)(-1)) break; /* If this works, we can stop now */ if (dlen >= MB_LEN_MAX) { wcrtomb (dest, 0, &st); return; } /* Otherwise convert any remaining data into a local buffer */ { char buf[3 * MB_LEN_MAX]; char *p = buf; for (; slen && p - buf < dlen; p += k, src++, slen--) if ((k = wcrtomb (p, *src, &st)) == (size_t)(-1)) break; p += wcrtomb (p, 0, &st); /* If it fits into the destination buffer, we can stop now */ if (p - buf <= dlen) { memcpy (dest, buf, p - buf); return; } /* Otherwise we truncate the string in an ugly fashion */ memcpy (dest, buf, dlen); dest[dlen - 1] = '\0'; /* assume original dlen > 0 */ }}size_t my_mbstowcs (wchar_t **pwbuf, size_t *pwbuflen, size_t i, char *buf){ wchar_t wc; mbstate_t st; size_t k; wchar_t *wbuf; size_t wbuflen; wbuf = *pwbuf, wbuflen = *pwbuflen; memset (&st, 0, sizeof (st)); for (; (k = mbrtowc (&wc, buf, MB_LEN_MAX, &st)) && k != (size_t)(-1) && k != (size_t)(-2); buf += k) { if (i >= wbuflen) { wbuflen = i + 20; safe_realloc (&wbuf, wbuflen * sizeof (*wbuf)); } wbuf[i++] = wc; } *pwbuf = wbuf, *pwbuflen = wbuflen; return i;}/* * Replace part of the wchar_t buffer, from FROM to CURPOS, by BUF. */static void replace_part (ENTER_STATE *state, size_t from, char *buf){ /* Save the suffix */ size_t savelen = state->lastchar - state->curpos; wchar_t *savebuf = safe_calloc (savelen, sizeof (wchar_t)); memcpy (savebuf, state->wbuf + state->curpos, savelen * sizeof (wchar_t)); /* Convert to wide characters */ state->curpos = my_mbstowcs (&state->wbuf, &state->wbuflen, from, buf); /* Make space for suffix */ if (state->curpos + savelen > state->wbuflen) { state->wbuflen = state->curpos + savelen; safe_realloc (&state->wbuf, state->wbuflen * sizeof (wchar_t)); } /* Restore suffix */ memcpy (state->wbuf + state->curpos, savebuf, savelen * sizeof (wchar_t)); state->lastchar = state->curpos + savelen; FREE (&savebuf);}/* * Returns: * 1 need to redraw the screen and call me again * 0 if input was given * -1 if abort. */int mutt_enter_string(char *buf, size_t buflen, int y, int x, int flags){ int rv; ENTER_STATE *es = mutt_new_enter_state (); rv = _mutt_enter_string (buf, buflen, y, x, flags, 0, NULL, NULL, es); mutt_free_enter_state (&es); return rv;}int _mutt_enter_string (char *buf, size_t buflen, int y, int x, int flags, int multiple, char ***files, int *numfiles, ENTER_STATE *state){ int width = COLS - x - 1; int redraw; int pass = (flags & M_PASS); int first = 1; int ch, w, r; size_t i; wchar_t *tempbuf = 0; size_t templen = 0; history_class_t hclass; wchar_t wc; mbstate_t mbstate; int rv = 0; memset (&mbstate, 0, sizeof (mbstate)); if (state->wbuf) { /* Coming back after return 1 */ redraw = M_REDRAW_LINE; } else { /* Initialise wbuf from buf */ state->wbuflen = 0; state->lastchar = my_mbstowcs (&state->wbuf, &state->wbuflen, 0, buf); redraw = M_REDRAW_INIT; } if (flags & (M_FILE | M_EFILE)) hclass = HC_FILE; else if (flags & M_CMD) hclass = HC_CMD; else if (flags & M_ALIAS) hclass = HC_ALIAS; else if (flags & M_COMMAND) hclass = HC_COMMAND; else if (flags & M_PATTERN) hclass = HC_PATTERN; else hclass = HC_OTHER; for (;;) { if (redraw && !pass) { if (redraw == M_REDRAW_INIT) { /* Go to end of line */ state->curpos = state->lastchar; state->begin = width_ceiling (state->wbuf, state->lastchar, my_wcswidth (state->wbuf, state->lastchar) - width + 1); } if (state->curpos < state->begin || my_wcswidth (state->wbuf + state->begin, state->curpos - state->begin) >= width) state->begin = width_ceiling (state->wbuf, state->lastchar, my_wcswidth (state->wbuf, state->curpos) - width / 2); move (y, x); w = 0; for (i = state->begin; i < state->lastchar; i++) { w += my_wcwidth (state->wbuf[i]); if (w > width) break; my_addwch (state->wbuf[i]); } clrtoeol (); move (y, x + my_wcswidth (state->wbuf + state->begin, state->curpos - state->begin)); } mutt_refresh (); if ((ch = km_dokey (MENU_EDITOR)) == -1) { rv = -1; goto bye; } if (ch != OP_NULL) { first = 0; if (ch != OP_EDITOR_COMPLETE && ch != OP_EDITOR_COMPLETE_QUERY) state->tabs = 0; redraw = M_REDRAW_LINE; switch (ch) { case OP_EDITOR_HISTORY_UP: state->curpos = state->lastchar; replace_part (state, 0, mutt_history_prev (hclass)); redraw = M_REDRAW_INIT; break; case OP_EDITOR_HISTORY_DOWN: state->curpos = state->lastchar; replace_part (state, 0, mutt_history_next (hclass)); redraw = M_REDRAW_INIT; break; case OP_EDITOR_BACKSPACE: if (state->curpos == 0) BEEP (); else { i = state->curpos; while (i && COMB_CHAR (state->wbuf[i - 1])) --i; if (i) --i; memmove (state->wbuf + i, state->wbuf + state->curpos, (state->lastchar - state->curpos) * sizeof (wchar_t)); state->lastchar -= state->curpos - i; state->curpos = i; } break; case OP_EDITOR_BOL: state->curpos = 0; break; case OP_EDITOR_EOL: redraw= M_REDRAW_INIT; break; case OP_EDITOR_KILL_LINE: state->curpos = state->lastchar = 0; break; case OP_EDITOR_KILL_EOL: state->lastchar = state->curpos; break; case OP_EDITOR_BACKWARD_CHAR: if (state->curpos == 0) BEEP (); else { while (state->curpos && COMB_CHAR (state->wbuf[state->curpos - 1])) state->curpos--; if (state->curpos) state->curpos--; } break; case OP_EDITOR_FORWARD_CHAR: if (state->curpos == state->lastchar) BEEP (); else { ++state->curpos; while (state->curpos < state->lastchar && COMB_CHAR (state->wbuf[state->curpos])) ++state->curpos; } break; case OP_EDITOR_BACKWARD_WORD: if (state->curpos == 0) BEEP (); else { while (state->curpos && iswspace (state->wbuf[state->curpos - 1])) --state->curpos; while (state->curpos && !iswspace (state->wbuf[state->curpos - 1])) --state->curpos; } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -