⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 curs_main.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 "attach.h"#include "mailbox.h"#include "mapping.h"#include "sort.h"#include "buffy.h"#include "mx.h"#ifdef USE_POP#include "pop.h"#endif#ifdef USE_IMAP#include "imap_private.h"#endif#include "mutt_crypt.h"#include <ctype.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#include <string.h>#include <sys/stat.h>#include <errno.h>static const char *No_mailbox_is_open = N_("No mailbox is open.");static const char *There_are_no_messages = N_("There are no messages.");static const char *Mailbox_is_read_only = N_("Mailbox is read-only.");static const char *Function_not_permitted_in_attach_message_mode = N_("Function not permitted in attach-message mode.");static const char *No_visible = N_("No visible messages.");#define CHECK_IN_MAILBOX if (!Context) \	{ \		mutt_flushinp (); \		mutt_error _(No_mailbox_is_open); \		break; \	}#define CHECK_MSGCOUNT if (!Context) \	{ \	  	mutt_flushinp (); \		mutt_error _(No_mailbox_is_open); \		break; \	} \	else if (!Context->msgcount) \	{ \	  	mutt_flushinp (); \		mutt_error _(There_are_no_messages); \		break; \	}#define CHECK_VISIBLE if (Context && menu->current >= Context->vcount) \  	{\	  	mutt_flushinp (); \	  	mutt_error _(No_visible); \	  	break; \	}    #define CHECK_READONLY if (Context->readonly) \			{ \			  	mutt_flushinp (); \				mutt_error _(Mailbox_is_read_only); \				break; \			}#ifdef USE_IMAP /* the error message returned here could be better. */#define CHECK_IMAP_ACL(aclbit) if (Context->magic == M_IMAP) \		if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \		&& !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,aclbit)){ \			mutt_flushinp(); \			mutt_error ("Operation not permitted by the IMAP ACL for this mailbox"); \			break; \		}#else#define CHECK_IMAP_ACL(aclbit) /**/#endif#define CHECK_ATTACH if(option(OPTATTACHMSG)) \		     {\			mutt_flushinp (); \			mutt_error _(Function_not_permitted_in_attach_message_mode); \			break; \		     }#define CURHDR Context->hdrs[Context->v2r[menu->current]]#define OLDHDR Context->hdrs[Context->v2r[menu->oldcurrent]]#define UNREAD(h) mutt_thread_contains_unread (Context, h)extern size_t UngetCount;void index_make_entry (char *s, size_t l, MUTTMENU *menu, int num){  format_flag flag = M_FORMAT_MAKEPRINT | M_FORMAT_ARROWCURSOR | M_FORMAT_INDEX;  int edgemsgno, reverse = Sort & SORT_REVERSE;  HEADER *h = Context->hdrs[Context->v2r[num]];  THREAD *tmp;  if ((Sort & SORT_MASK) == SORT_THREADS && h->tree)  {    flag |= M_FORMAT_TREE; /* display the thread tree */    if (h->display_subject)      flag |= M_FORMAT_FORCESUBJ;    else    {      if (reverse)      {	if (menu->top + menu->pagelen > menu->max)	  edgemsgno = Context->v2r[menu->max - 1];	else	  edgemsgno = Context->v2r[menu->top + menu->pagelen - 1];      }      else	edgemsgno = Context->v2r[menu->top];      for (tmp = h->thread->parent; tmp; tmp = tmp->parent)      {	if (!tmp->message)	  continue;	/* if no ancestor is visible on current screen, provisionally force	 * subject... */	if (reverse ? tmp->message->msgno > edgemsgno : tmp->message->msgno < edgemsgno)	{	  flag |= M_FORMAT_FORCESUBJ;	  break;	}	else if (tmp->message->virtual >= 0)	  break;      }      if (flag & M_FORMAT_FORCESUBJ)      {	for (tmp = h->thread->prev; tmp; tmp = tmp->prev)	{	  if (!tmp->message)	    continue;	  /* ...but if a previous sibling is available, don't force it */	  if (reverse ? tmp->message->msgno > edgemsgno : tmp->message->msgno < edgemsgno)	    break;	  else if (tmp->message->virtual >= 0)	  {	    flag &= ~M_FORMAT_FORCESUBJ;	    break;	  }	}      }    }  }  _mutt_make_string (s, l, NONULL (HdrFmt), Context, h, flag);}int index_color (int index_no){  HEADER *h = Context->hdrs[Context->v2r[index_no]];  if (h && h->pair)    return h->pair;  mutt_set_header_color (Context, h);  return h->pair;}static int ci_next_undeleted (int msgno){  int i;  for (i=msgno+1; i < Context->vcount; i++)    if (! Context->hdrs[Context->v2r[i]]->deleted)      return (i);  return (-1);}static int ci_previous_undeleted (int msgno){  int i;  for (i=msgno-1; i>=0; i--)    if (! Context->hdrs[Context->v2r[i]]->deleted)      return (i);  return (-1);}/* Return the index of the first new message, or failing that, the first * unread message. */static int ci_first_message (void){  int old = -1, i;  if (Context && Context->msgcount)  {    for (i=0; i < Context->vcount; i++)    {      if (! Context->hdrs[Context->v2r[i]]->read &&	  ! Context->hdrs[Context->v2r[i]]->deleted)      {	if (! Context->hdrs[Context->v2r[i]]->old)	  return (i);	else if (old == -1)	  old = i;      }    }    if (old != -1)      return (old);    /* If Sort is reverse and not threaded, the latest message is first.     * If Sort is threaded, the latest message is first iff exactly one     * of Sort and SortAux are reverse.     */    if (((Sort & SORT_REVERSE) && (Sort & SORT_MASK) != SORT_THREADS) ||	((Sort & SORT_MASK) == SORT_THREADS &&	 ((Sort ^ SortAux) & SORT_REVERSE)))      return 0;    else      return (Context->vcount ? Context->vcount - 1 : 0);  }  return 0;}/* This should be in mx.c, but it only gets used here. */static int mx_toggle_write (CONTEXT *ctx){  if (!ctx)    return -1;  if (ctx->readonly)  {    mutt_error _("Cannot toggle write on a readonly mailbox!");    return -1;  }  if (ctx->dontwrite)  {    ctx->dontwrite = 0;    mutt_message _("Changes to folder will be written on folder exit.");  }  else  {    ctx->dontwrite = 1;    mutt_message _("Changes to folder will not be written.");  }  return 0;}static void update_index (MUTTMENU *menu, CONTEXT *ctx, int check,			  int oldcount, int index_hint){  /* store pointers to the newly added messages */  HEADER  **save_new = NULL;  int j;    /* take note of the current message */  if (oldcount)  {    if (menu->current < Context->vcount)      menu->oldcurrent = index_hint;    else      oldcount = 0; /* invalid message number! */  }    /* We are in a limited view. Check if the new message(s) satisfy   * the limit criteria. If they do, set their virtual msgno so that   * they will be visible in the limited view */  if (Context->pattern)  {#define THIS_BODY Context->hdrs[j]->content    for (j = (check == M_REOPENED) ? 0 : oldcount; j < Context->msgcount; j++)    {      if (mutt_pattern_exec (Context->limit_pattern,			     M_MATCH_FULL_ADDRESS, 			     Context, Context->hdrs[j]))      {	Context->hdrs[j]->virtual = Context->vcount;	Context->v2r[Context->vcount] = j;	Context->hdrs[j]->limited = 1;	Context->vcount++;	Context->vsize += THIS_BODY->length + THIS_BODY->offset - THIS_BODY->hdr_offset;      }    }#undef THIS_BODY  }      /* save the list of new messages */  if (oldcount && check != M_REOPENED      && ((Sort & SORT_MASK) == SORT_THREADS))  {    save_new = (HEADER **) safe_malloc (sizeof (HEADER *) * (Context->msgcount - oldcount));    for (j = oldcount; j < Context->msgcount; j++)      save_new[j-oldcount] = Context->hdrs[j];  }    /* if the mailbox was reopened, need to rethread from scratch */  mutt_sort_headers (Context, (check == M_REOPENED));  /* uncollapse threads with new mail */  if ((Sort & SORT_MASK) == SORT_THREADS)  {    if (check == M_REOPENED)    {      THREAD *h, *j;            Context->collapsed = 0;            for (h = Context->tree; h; h = h->next)      {	for (j = h; !j->message; j = j->child)	  ;	mutt_uncollapse_thread (Context, j->message);      }      mutt_set_virtual (Context);    }    else if (oldcount)    {      for (j = 0; j < Context->msgcount - oldcount; j++)      {	int k;		for (k = 0; k < Context->msgcount; k++)	{	  HEADER *h = Context->hdrs[k];	  if (h == save_new[j] && (!Context->pattern || h->limited))	    mutt_uncollapse_thread (Context, h);	}      }      FREE (&save_new);      mutt_set_virtual (Context);    }  }    menu->current = -1;  if (oldcount)  {    /* restore the current message to the message it was pointing to */    for (j = 0; j < Context->vcount; j++)    {      if (Context->hdrs[Context->v2r[j]]->index == menu->oldcurrent)      {	menu->current = j;	break;      }    }  }    if (menu->current < 0)    menu->current = ci_first_message ();  }static void resort_index (MUTTMENU *menu){  int i;  HEADER *current = CURHDR;  menu->current = -1;  mutt_sort_headers (Context, 0);  /* Restore the current message */  for (i = 0; i < Context->vcount; i++)  {    if (Context->hdrs[Context->v2r[i]] == current)    {      menu->current = i;      break;    }  }    if ((Sort & SORT_MASK) == SORT_THREADS && menu->current < 0)    menu->current = mutt_parent_message (Context, current);    if (menu->current < 0)    menu->current = ci_first_message ();    menu->redraw = REDRAW_INDEX | REDRAW_STATUS;}struct mapping_t IndexHelp[] = {  { N_("Quit"),  OP_QUIT },  { N_("Del"),   OP_DELETE },  { N_("Undel"), OP_UNDELETE },  { N_("Save"),  OP_SAVE },  { N_("Mail"),  OP_MAIL },  { N_("Reply"), OP_REPLY },  { N_("Group"), OP_GROUP_REPLY },  { N_("Help"),  OP_HELP },  { NULL }};/* This function handles the message index window as well as commands returned * from the pager (MENU_PAGER). */int mutt_index_menu (void){  char buf[LONG_STRING], helpstr[SHORT_STRING];  int op = OP_NULL;  int done = 0;                /* controls when to exit the "event" loop */  int i = 0, j;  int tag = 0;                 /* has the tag-prefix command been pressed? */  int newcount = -1;  int oldcount = -1;  int rc = -1;  MUTTMENU *menu;  char *cp;                    /* temporary variable. */  int index_hint;   /* used to restore cursor position */  int do_buffy_notify = 1;  int close = 0; /* did we OP_QUIT or OP_EXIT out of this menu? */  int attach_msg = option(OPTATTACHMSG);    menu = mutt_new_menu ();  menu->menu = MENU_MAIN;  menu->offset = 1;  menu->pagelen = LINES - 3;  menu->make_entry = index_make_entry;  menu->color = index_color;  menu->current = ci_first_message ();  menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, IndexHelp);    if (!attach_msg)     mutt_buffy_check(1); /* force the buffy check after we enter the folder */  FOREVER  {    tag = 0; /* clear the tag-prefix */    menu->max = Context ? Context->vcount : 0;    oldcount = Context ? Context->msgcount : 0;    /* check if we need to resort the index because just about     * any 'op' below could do mutt_enter_command(), either here or     * from any new menu launched, and change $sort/$sort_aux     */    if (option (OPTNEEDRESORT) && Context && Context->msgcount)      resort_index (menu);        if (option (OPTREDRAWTREE) && Context && Context->msgcount && (Sort & SORT_MASK) == SORT_THREADS)    {      mutt_draw_tree (Context);      menu->redraw |= REDRAW_STATUS;      unset_option (OPTREDRAWTREE);    }    if (Context && !attach_msg)    {      int check;      /* check for new mail in the mailbox.  If nonzero, then something has       * changed about the file (either we got new mail or the file was       * modified underneath us.)       */#ifdef USE_IMAP      imap_allow_reopen (Context);#endif          index_hint = (Context->vcount && menu->current >= 0 && menu->current < Context->vcount) ? CURHDR->index : 0;      if ((check = mx_check_mailbox (Context, &index_hint, 0)) < 0)      {	if (!Context->path)	{	  /* fatal error occurred */	  FREE (&Context);	  menu->redraw = REDRAW_FULL;	}	set_option (OPTSEARCHINVALID);      }      else if (check == M_NEW_MAIL || check == M_REOPENED || check == M_FLAGS)      {	update_index (menu, Context, check, oldcount, index_hint);		/* notify the user of new mail */	if (check == M_REOPENED)	  mutt_error _("Mailbox was externally modified.  Flags may be wrong.");	else if (check == M_NEW_MAIL)	{	  mutt_message _("New mail in this mailbox.");	  if (option (OPTBEEPNEW))	    beep ();	} else if (check == M_FLAGS)	  mutt_message _("Mailbox was externally modified.");	/* avoid the message being overwritten by buffy */	do_buffy_notify = 0;		menu->redraw = REDRAW_FULL;	menu->max = Context->vcount;		set_option (OPTSEARCHINVALID);      }    }#ifdef USE_IMAP    imap_keepalive ();    imap_disallow_reopen (Context);#endif    if (!attach_msg)    {     /* check for new mail in the incoming folders */     oldcount = newcount;     if ((newcount = mutt_buffy_check (0)) != oldcount)       menu->redraw |= REDRAW_STATUS;     if (do_buffy_notify)     {       if (mutt_buffy_notify () && option (OPTBEEPNEW)) 	beep ();     }     else       do_buffy_notify = 1;    }    if (op != -1)      mutt_curs_set (0);    if (menu->redraw & REDRAW_FULL)    {      menu_redraw_full (menu);      mutt_show_error ();    }    if (menu->menu == MENU_MAIN)    {      if (Context && Context->hdrs && !(menu->current >= Context->vcount))      {	menu_check_recenter (menu);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -