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

📄 pager.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 1996-2002 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_regex.h"#include "keymap.h"#include "mutt_menu.h"#include "mapping.h"#include "sort.h"#include "pager.h"#include "attach.h"#include "mbyte.h"#include "mx.h"#ifdef USE_IMAP#include "imap_private.h"#endif#include "mutt_crypt.h"#include <sys/stat.h>#include <ctype.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <errno.h>#define ISHEADER(x) ((x) == MT_COLOR_HEADER || (x) == MT_COLOR_HDEFAULT)#define IsAttach(x) (x && (x)->bdy)#define IsRecvAttach(x) (x && (x)->bdy && (x)->fp)#define IsSendAttach(x) (x && (x)->bdy && !(x)->fp)#define IsMsgAttach(x) (x && (x)->fp && (x)->bdy && (x)->bdy->hdr)#define IsHeader(x) (x && (x)->hdr && !(x)->bdy)static const char *Not_available_in_this_menu = N_("Not available in this menu.");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.");/* hack to return to position when returning from index to same message */static int TopLine = 0;static HEADER *OldHdr = NULL;#define CHECK_MODE(x)	if (!(x)) \			{ \			  	mutt_flushinp (); \				mutt_error _(Not_available_in_this_menu); \				break; \			}#define CHECK_READONLY	if (Context->readonly) \			{ \				mutt_flushinp (); \				mutt_error _(Mailbox_is_read_only);	\				break; \			}#define CHECK_ATTACH if(option(OPTATTACHMSG)) \		     {\			mutt_flushinp (); \			mutt_error _(Function_not_permitted_in_attach_message_mode); \			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; \		}#endifstruct q_class_t{  int length;  int index;  int color;  char *prefix;  struct q_class_t *next, *prev;  struct q_class_t *down, *up;};struct syntax_t{  int color;  int first;  int last;};struct line_t{  LOFF_T offset;  short type;  short continuation;  short chunks;  short search_cnt;  struct syntax_t *syntax;  struct syntax_t *search;  struct q_class_t *quote;};#define ANSI_OFF       (1<<0)#define ANSI_BLINK     (1<<1)#define ANSI_BOLD      (1<<2)#define ANSI_UNDERLINE (1<<3)#define ANSI_REVERSE   (1<<4)#define ANSI_COLOR     (1<<5)typedef struct _ansi_attr {  int attr;  int fg;  int bg;  int pair;} ansi_attr;static short InHelp = 0;#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)static struct resize {  int line;  int SearchCompiled;  int SearchBack;} *Resize = NULL;#endif#define NumSigLines 4static int check_sig (const char *s, struct line_t *info, int n){  int count = 0;  while (n > 0 && count <= NumSigLines)  {    if (info[n].type != MT_COLOR_SIGNATURE)      break;    count++;    n--;  }  if (count == 0)    return (-1);  if (count > NumSigLines)  {    /* check for a blank line */    while (*s)    {      if (!ISSPACE (*s))	return 0;      s++;    }    return (-1);  }  return (0);}static voidresolve_color (struct line_t *lineInfo, int n, int cnt, int flags, int special,    ansi_attr *a){  int def_color;		/* color without syntax hilight */  int color;			/* final color */  static int last_color;	/* last color set */  int search = 0, i, m;  if (!cnt)    last_color = -1;		/* force attrset() */  if (lineInfo[n].continuation)  {    if (!cnt && option (OPTMARKERS))    {      SETCOLOR (MT_COLOR_MARKERS);      addch ('+');      last_color = ColorDefs[MT_COLOR_MARKERS];    }    m = (lineInfo[n].syntax)[0].first;    cnt += (lineInfo[n].syntax)[0].last;  }  else    m = n;  if (!(flags & M_SHOWCOLOR))    def_color = ColorDefs[MT_COLOR_NORMAL];  else if (lineInfo[m].type == MT_COLOR_HEADER)    def_color = (lineInfo[m].syntax)[0].color;  else    def_color = ColorDefs[lineInfo[m].type];  if ((flags & M_SHOWCOLOR) && lineInfo[m].type == MT_COLOR_QUOTED)  {    struct q_class_t *class = lineInfo[m].quote;    if (class)    {      def_color = class->color;      while (class && class->length > cnt)      {	def_color = class->color;	class = class->up;      }    }  }  color = def_color;  if (flags & M_SHOWCOLOR)  {    for (i = 0; i < lineInfo[m].chunks; i++)    {      /* we assume the chunks are sorted */      if (cnt > (lineInfo[m].syntax)[i].last)	continue;      if (cnt < (lineInfo[m].syntax)[i].first)	break;      if (cnt != (lineInfo[m].syntax)[i].last)      {	color = (lineInfo[m].syntax)[i].color;	break;      }      /* don't break here, as cnt might be        * in the next chunk as well */    }  }  if (flags & M_SEARCH)  {    for (i = 0; i < lineInfo[m].search_cnt; i++)    {      if (cnt > (lineInfo[m].search)[i].last)	continue;      if (cnt < (lineInfo[m].search)[i].first)	break;      if (cnt != (lineInfo[m].search)[i].last)      {	color = ColorDefs[MT_COLOR_SEARCH];	search = 1;	break;      }    }  }  /* handle "special" bold & underlined characters */  if (special || a->attr)  {#ifdef HAVE_COLOR    if ((a->attr & ANSI_COLOR))    {      if (a->pair == -1)	a->pair = mutt_alloc_color (a->fg, a->bg);      color = a->pair;      if (a->attr & ANSI_BOLD)	  color |= A_BOLD;    }    else#endif      if ((special & A_BOLD) || (a->attr & ANSI_BOLD))    {      if (ColorDefs[MT_COLOR_BOLD] && !search)	color = ColorDefs[MT_COLOR_BOLD];      else	color ^= A_BOLD;    }    if ((special & A_UNDERLINE) || (a->attr & ANSI_UNDERLINE))    {      if (ColorDefs[MT_COLOR_UNDERLINE] && !search)	color = ColorDefs[MT_COLOR_UNDERLINE];      else	color ^= A_UNDERLINE;    }    else if (a->attr & ANSI_REVERSE)     {      color ^= A_REVERSE;    }    else if (a->attr & ANSI_BLINK)     {      color ^= A_BLINK;    }    else if (a->attr & ANSI_OFF)    {      a->attr = 0;    }  }  if (color != last_color)  {    attrset (color);    last_color = color;  }}static voidappend_line (struct line_t *lineInfo, int n, int cnt){  int m;  lineInfo[n+1].type = lineInfo[n].type;  (lineInfo[n+1].syntax)[0].color = (lineInfo[n].syntax)[0].color;  lineInfo[n+1].continuation = 1;  /* find the real start of the line */  for (m = n; m >= 0; m--)    if (lineInfo[m].continuation == 0) break;  (lineInfo[n+1].syntax)[0].first = m;  (lineInfo[n+1].syntax)[0].last = (lineInfo[n].continuation) ?     cnt + (lineInfo[n].syntax)[0].last : cnt;}static voidnew_class_color (struct q_class_t *class, int *q_level){  class->index = (*q_level)++;  class->color = ColorQuote[class->index % ColorQuoteUsed];}static voidshift_class_colors (struct q_class_t *QuoteList, struct q_class_t *new_class,		      int index, int *q_level){  struct q_class_t * q_list;  q_list = QuoteList;  new_class->index = -1;  while (q_list)  {    if (q_list->index >= index)    {      q_list->index++;      q_list->color = ColorQuote[q_list->index % ColorQuoteUsed];    }    if (q_list->down)      q_list = q_list->down;    else if (q_list->next)      q_list = q_list->next;    else    {      while (!q_list->next)      {	q_list = q_list->up;	if (q_list == NULL)	  break;      }      if (q_list)	q_list = q_list->next;    }  }  new_class->index = index;  new_class->color = ColorQuote[index % ColorQuoteUsed];  (*q_level)++;}static voidcleanup_quote (struct q_class_t **QuoteList){  struct q_class_t *ptr;  while (*QuoteList)  {    if ((*QuoteList)->down)      cleanup_quote (&((*QuoteList)->down));    ptr = (*QuoteList)->next;    if ((*QuoteList)->prefix)      FREE (&(*QuoteList)->prefix);    FREE (QuoteList);		/* __FREE_CHECKED__ */    *QuoteList = ptr;  }  return;}static struct q_class_t *classify_quote (struct q_class_t **QuoteList, const char *qptr,		int length, int *force_redraw, int *q_level){  struct q_class_t *q_list = *QuoteList;  struct q_class_t *class = NULL, *tmp = NULL, *ptr, *save;  char *tail_qptr;  int offset, tail_lng;  int index = -1;  if (ColorQuoteUsed <= 1)  {    /* not much point in classifying quotes... */    if (*QuoteList == NULL)    {      class = (struct q_class_t *) safe_calloc (1, sizeof (struct q_class_t));      class->color = ColorQuote[0];      *QuoteList = class;    }    return (*QuoteList);  }  /* Did I mention how much I like emulating Lisp in C? */  /* classify quoting prefix */  while (q_list)  {    if (length <= q_list->length)    {      /* case 1: check the top level nodes */      if (mutt_strncmp (qptr, q_list->prefix, length) == 0)      {	if (length == q_list->length)	  return q_list;	/* same prefix: return the current class */	/* found shorter prefix */	if (tmp == NULL)	{	  /* add a node above q_list */	  tmp = (struct q_class_t *) safe_calloc (1, sizeof (struct q_class_t));	  tmp->prefix = (char *) safe_calloc (1, length + 1);	  strncpy (tmp->prefix, qptr, length);	  tmp->length = length;	  /* replace q_list by tmp in the top level list */	  if (q_list->next)	  {	    tmp->next = q_list->next;	    q_list->next->prev = tmp;	  }	  if (q_list->prev)	  {	    tmp->prev = q_list->prev;	    q_list->prev->next = tmp;	  }	  /* make q_list a child of tmp */	  tmp->down = q_list;	  q_list->up = tmp;	  /* q_list has no siblings for now */	  q_list->next = NULL;	  q_list->prev = NULL;	  /* update the root if necessary */	  if (q_list == *QuoteList)	    *QuoteList = tmp;	  index = q_list->index;	  /* tmp should be the return class too */	  class = tmp;	  /* next class to test; if tmp is a shorter prefix for another	   * node, that node can only be in the top level list, so don't	   * go down after this point	   */	  q_list = tmp->next;	}	else	{	  /* found another branch for which tmp is a shorter prefix */	  /* save the next sibling for later */	  save = q_list->next;	  /* unlink q_list from the top level list */	  if (q_list->next)	    q_list->next->prev = q_list->prev;	  if (q_list->prev)	    q_list->prev->next = q_list->next;	  /* at this point, we have a tmp->down; link q_list to it */	  ptr = tmp->down;	  /* sibling order is important here, q_list should be linked last */	  while (ptr->next)	    ptr = ptr->next;	  ptr->next = q_list;	  q_list->next = NULL;	  q_list->prev = ptr;	  q_list->up = tmp;	  index = q_list->index;	  /* next class to test; as above, we shouldn't go down */	  q_list = save;	}	/* we found a shorter prefix, so certain quotes have changed classes */	*force_redraw = 1;	continue;      }      else      {	/* shorter, but not a substring of the current class: try next */	q_list = q_list->next;	continue;      }    }    else    {      /* case 2: try subclassing the current top level node */            /* tmp != NULL means we already found a shorter prefix at case 1 */      if (tmp == NULL && mutt_strncmp (qptr, q_list->prefix, q_list->length) == 0)      {	/* ok, it's a subclass somewhere on this branch */	ptr = q_list;	offset = q_list->length;	q_list = q_list->down;	tail_lng = length - offset;	tail_qptr = (char *) qptr + offset;	while (q_list)	{	  if (length <= q_list->length)	  {	    if (mutt_strncmp (tail_qptr, (q_list->prefix) + offset, tail_lng) == 0)	    {	      /* same prefix: return the current class */	      if (length == q_list->length)		return q_list;	      /* found shorter common prefix */

⌨️ 快捷键说明

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