📄 menu.c
字号:
/* * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.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_curses.h"#include "mutt_menu.h"#include "mbyte.h"#ifdef USE_IMAP#include "imap.h"#endif#include <string.h>#include <stdlib.h>extern int Charset_is_utf8; /* FIXME: bad modularisation */extern size_t UngetCount;static void print_enriched_string (int attr, unsigned char *s, int do_color){ wchar_t wc; size_t k; size_t n = mutt_strlen ((char *)s); mbstate_t mbstate; memset (&mbstate, 0, sizeof (mbstate)); while (*s) { if (*s < M_TREE_MAX) { if (do_color) SETCOLOR (MT_COLOR_TREE); while (*s && *s < M_TREE_MAX) { switch (*s) { case M_TREE_LLCORNER: if (option (OPTASCIICHARS)) addch ('`'); else if (Charset_is_utf8) addstr ("\342\224\224"); /* WACS_LLCORNER */ else addch (ACS_LLCORNER); break; case M_TREE_ULCORNER: if (option (OPTASCIICHARS)) addch (','); else if (Charset_is_utf8) addstr ("\342\224\214"); /* WACS_ULCORNER */ else addch (ACS_ULCORNER); break; case M_TREE_LTEE: if (option (OPTASCIICHARS)) addch ('|'); else if (Charset_is_utf8) addstr ("\342\224\234"); /* WACS_LTEE */ else addch (ACS_LTEE); break; case M_TREE_HLINE: if (option (OPTASCIICHARS)) addch ('-'); else if (Charset_is_utf8) addstr ("\342\224\200"); /* WACS_HLINE */ else addch (ACS_HLINE); break; case M_TREE_VLINE: if (option (OPTASCIICHARS)) addch ('|'); else if (Charset_is_utf8) addstr ("\342\224\202"); /* WACS_VLINE */ else addch (ACS_VLINE); break; case M_TREE_TTEE: if (option (OPTASCIICHARS)) addch ('-'); else if (Charset_is_utf8) addstr ("\342\224\254"); /* WACS_TTEE */ else addch (ACS_TTEE); break; case M_TREE_BTEE: if (option (OPTASCIICHARS)) addch ('-'); else if (Charset_is_utf8) addstr ("\342\224\264"); /* WACS_BTEE */ else addch (ACS_BTEE); break; case M_TREE_SPACE: addch (' '); break; case M_TREE_RARROW: addch ('>'); break; case M_TREE_STAR: addch ('*'); /* fake thread indicator */ break; case M_TREE_HIDDEN: addch ('&'); break; case M_TREE_EQUALS: addch ('='); break; case M_TREE_MISSING: addch ('?'); break; } s++, n--; } if (do_color) attrset(attr); } else if ((k = mbrtowc (&wc, (char *)s, n, &mbstate)) > 0) { addnstr ((char *)s, k); s += k, n-= k; } else break; }}static void menu_make_entry (char *s, int l, MUTTMENU *menu, int i) { if (menu->dialog) { strncpy (s, menu->dialog[i], l); menu->current = -1; /* hide menubar */ } else menu->make_entry (s, l, menu, i);}void menu_pad_string (char *s, size_t n){ int shift = option (OPTARROWCURSOR) ? 3 : 0; int cols = COLS - shift; mutt_format_string (s, n, cols, cols, 0, ' ', s, strlen (s), 1); s[n - 1] = 0;}void menu_redraw_full (MUTTMENU *menu){ SETCOLOR (MT_COLOR_NORMAL); /* clear() doesn't optimize screen redraws */ move (0, 0); clrtobot (); if (option (OPTHELP)) { SETCOLOR (MT_COLOR_STATUS); move (option (OPTSTATUSONTOP) ? LINES-2 : 0, 0); mutt_paddstr (COLS, menu->help); SETCOLOR (MT_COLOR_NORMAL); menu->offset = 1; menu->pagelen = LINES - 3; } else { menu->offset = option (OPTSTATUSONTOP) ? 1 : 0; menu->pagelen = LINES - 2; } mutt_show_error (); menu->redraw = REDRAW_INDEX | REDRAW_STATUS;}void menu_redraw_status (MUTTMENU *menu){ char buf[STRING]; snprintf (buf, sizeof (buf), M_MODEFMT, menu->title); SETCOLOR (MT_COLOR_STATUS); move (option (OPTSTATUSONTOP) ? 0 : LINES - 2, 0); mutt_paddstr (COLS, buf); SETCOLOR (MT_COLOR_NORMAL); menu->redraw &= ~REDRAW_STATUS;}void menu_redraw_index (MUTTMENU *menu){ char buf[STRING]; int i; for (i = menu->top; i < menu->top + menu->pagelen; i++) { if (i < menu->max) { menu_make_entry (buf, sizeof (buf), menu, i); menu_pad_string (buf, sizeof (buf)); if (option (OPTARROWCURSOR)) { attrset (menu->color (i)); CLEARLINE (i - menu->top + menu->offset); if (i == menu->current) { attrset (menu->color (i)); ADDCOLOR (MT_COLOR_INDICATOR); addstr ("->"); attrset (menu->color (i)); addch (' '); } else { attrset (menu->color (i)); addstr (" "); } print_enriched_string (menu->color(i), (unsigned char *) buf, 1); SETCOLOR (MT_COLOR_NORMAL); } else { attrset (menu->color (i)); if (i == menu->current) { ADDCOLOR (MT_COLOR_INDICATOR); BKGDSET (MT_COLOR_INDICATOR); } CLEARLINE (i - menu->top + menu->offset); print_enriched_string (menu->color(i), (unsigned char *) buf, i != menu->current); SETCOLOR (MT_COLOR_NORMAL); BKGDSET (MT_COLOR_NORMAL); } } else CLEARLINE (i - menu->top + menu->offset); } menu->redraw = 0;}void menu_redraw_motion (MUTTMENU *menu){ char buf[STRING]; if (menu->dialog) { menu->redraw &= ~REDRAW_MOTION; return; } move (menu->oldcurrent + menu->offset - menu->top, 0); SETCOLOR (MT_COLOR_NORMAL); BKGDSET (MT_COLOR_NORMAL); if (option (OPTARROWCURSOR)) { /* clear the pointer */ attrset (menu->color (menu->oldcurrent)); addstr (" "); if (menu->redraw & REDRAW_MOTION_RESYNCH) { clrtoeol (); menu_make_entry (buf, sizeof (buf), menu, menu->oldcurrent); menu_pad_string (buf, sizeof (buf)); move (menu->oldcurrent + menu->offset - menu->top, 3); print_enriched_string (menu->color(menu->oldcurrent), (unsigned char *) buf, 1); SETCOLOR (MT_COLOR_NORMAL); } /* now draw it in the new location */ move (menu->current + menu->offset - menu->top, 0); attrset (menu->color (menu->current)); ADDCOLOR (MT_COLOR_INDICATOR); addstr ("->"); SETCOLOR (MT_COLOR_NORMAL); } else { /* erase the current indicator */ attrset (menu->color (menu->oldcurrent)); clrtoeol (); menu_make_entry (buf, sizeof (buf), menu, menu->oldcurrent); menu_pad_string (buf, sizeof (buf)); print_enriched_string (menu->color(menu->oldcurrent), (unsigned char *) buf, 1); /* now draw the new one to reflect the change */ menu_make_entry (buf, sizeof (buf), menu, menu->current); menu_pad_string (buf, sizeof (buf)); attrset (menu->color (menu->current)); ADDCOLOR (MT_COLOR_INDICATOR); BKGDSET (MT_COLOR_INDICATOR); CLEARLINE (menu->current - menu->top + menu->offset); print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 0); SETCOLOR (MT_COLOR_NORMAL); BKGDSET (MT_COLOR_NORMAL); } menu->redraw &= REDRAW_STATUS;}void menu_redraw_current (MUTTMENU *menu){ char buf[STRING]; move (menu->current + menu->offset - menu->top, 0); menu_make_entry (buf, sizeof (buf), menu, menu->current); menu_pad_string (buf, sizeof (buf)); if (option (OPTARROWCURSOR)) { int attr = menu->color (menu->current); attrset (attr); clrtoeol (); attrset (menu->color (menu->current)); ADDCOLOR (MT_COLOR_INDICATOR); addstr ("->"); attrset (attr); addch (' '); menu_pad_string (buf, sizeof (buf)); print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 1); SETCOLOR (MT_COLOR_NORMAL); } else { attrset (menu->color (menu->current)); ADDCOLOR (MT_COLOR_INDICATOR); BKGDSET (MT_COLOR_INDICATOR); clrtoeol (); print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 0); SETCOLOR (MT_COLOR_NORMAL); BKGDSET (MT_COLOR_NORMAL); } menu->redraw &= REDRAW_STATUS;}void menu_redraw_prompt (MUTTMENU *menu){ if (menu->dialog) { if (option (OPTMSGERR)) { mutt_sleep (1); unset_option (OPTMSGERR); } if (*Errorbuf) mutt_clear_error (); SETCOLOR (MT_COLOR_NORMAL); mvaddstr (LINES - 1, 0, menu->prompt); clrtoeol (); }}void menu_check_recenter (MUTTMENU *menu){ int c = MIN (MenuContext, menu->pagelen / 2); int old_top = menu->top; if (!option (OPTMENUMOVEOFF) && menu->max <= menu->pagelen) /* less entries than lines */ { if (menu->top != 0) { menu->top = 0; set_option (OPTNEEDREDRAW); } } else { if (option (OPTMENUSCROLL) || (menu->pagelen <= 0) || (c < MenuContext)) { if (menu->current < menu->top + c) menu->top = menu->current - c; else if (menu->current >= menu->top + menu->pagelen - c) menu->top = menu->current - menu->pagelen + c + 1; } else { if (menu->current < menu->top + c) menu->top -= (menu->pagelen - c) * ((menu->top + menu->pagelen - 1 - menu->current) / (menu->pagelen - c)) - c; else if ((menu->current >= menu->top + menu->pagelen - c)) menu->top += (menu->pagelen - c) * ((menu->current - menu->top) / (menu->pagelen - c)) - c; } } if (!option (OPTMENUMOVEOFF)) /* make entries stick to bottom */ menu->top = MIN (menu->top, menu->max - menu->pagelen); menu->top = MAX (menu->top, 0); if (menu->top != old_top) menu->redraw |= REDRAW_INDEX;}void menu_jump (MUTTMENU *menu){ int n; char buf[SHORT_STRING]; if (menu->max) { mutt_ungetch (LastKey, 0); buf[0] = 0; if (mutt_get_field (_("Jump to: "), buf, sizeof (buf), 0) == 0 && buf[0]) { n = atoi (buf) - 1; if (n >= 0 && n < menu->max) { menu->current = n; menu->redraw = REDRAW_MOTION; } else mutt_error _("Invalid index number."); } } else mutt_error _("No entries.");}void menu_next_line (MUTTMENU *menu){ if (menu->max) { int c = MIN (MenuContext, menu->pagelen / 2); if (menu->top + 1 < menu->max - c && (option(OPTMENUMOVEOFF) || (menu->max > menu->pagelen && menu->top < menu->max - menu->pagelen))) { menu->top++; if (menu->current < menu->top + c && menu->current < menu->max - 1) menu->current++; menu->redraw = REDRAW_INDEX; } else mutt_error _("You cannot scroll down farther."); } else mutt_error _("No entries.");}void menu_prev_line (MUTTMENU *menu){ if (menu->top > 0) { int c = MIN (MenuContext, menu->pagelen / 2); menu->top--; if (menu->current >= menu->top + menu->pagelen - c && menu->current > 1) menu->current--; menu->redraw = REDRAW_INDEX; } else mutt_error _("You cannot scroll up farther.");}/* * pageup: jumplen == -pagelen * pagedown: jumplen == pagelen * halfup: jumplen == -pagelen/2 * halfdown: jumplen == pagelen/2 */#define DIRECTION ((neg * 2) + 1)void menu_length_jump (MUTTMENU *menu, int jumplen){ int tmp, neg = (jumplen >= 0) ? 0 : -1; int c = MIN (MenuContext, menu->pagelen / 2); if (menu->max) { /* possible to scroll? */ if (DIRECTION * menu->top < (tmp = (neg ? 0 : (menu->max /*-1*/) - (menu->pagelen /*-1*/)))) { menu->top += jumplen; /* jumped too long? */ if ((neg || !option (OPTMENUMOVEOFF)) && DIRECTION * menu->top > tmp) menu->top = tmp; /* need to move the cursor? */ if ((DIRECTION * (tmp = (menu->current - (menu->top + (neg ? (menu->pagelen - 1) - c : c)) ))) < 0) menu->current -= tmp; menu->redraw = REDRAW_INDEX; } else if (menu->current != (neg ? 0 : menu->max - 1) && !menu->dialog) { menu->current += jumplen; menu->redraw = REDRAW_MOTION; } else mutt_error (neg ? _("You are on the first page.") : _("You are on the last page.")); menu->current = MIN (menu->current, menu->max - 1); menu->current = MAX (menu->current, 0); } else mutt_error _("No entries.");}#undef DIRECTIONvoid menu_next_page (MUTTMENU *menu){ menu_length_jump (menu, MAX (menu->pagelen /* - MenuOverlap */, 0));}void menu_prev_page (MUTTMENU *menu){ menu_length_jump (menu, 0 - MAX (menu->pagelen /* - MenuOverlap */, 0));}void menu_half_down (MUTTMENU *menu){ menu_length_jump (menu, menu->pagelen / 2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -