]> git.llucax.com Git - software/mutt-debian.git/blobdiff - pager.c
debian/patches/upstream/611412-bts-regexp.patch: fixes a regexp for BTS in the mutt...
[software/mutt-debian.git] / pager.c
diff --git a/pager.c b/pager.c
index 8f8a92b5a4effee0b05f692e9b4b3827c5a7acba..e19174cd02c558e7ed8b804b681e02537353f2ae 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -110,6 +110,7 @@ struct line_t
   struct syntax_t *syntax;
   struct syntax_t *search;
   struct q_class_t *quote;
+  unsigned int is_cont_hdr; /* this line is a continuation of the previous header line */
 };
 
 #define ANSI_OFF       (1<<0)
@@ -712,27 +713,51 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last,
 
   if (n == 0 || ISHEADER (lineInfo[n-1].type))
   {
-    if (buf[0] == '\n') {
+    if (buf[0] == '\n') /* end of header */
+    {
       lineInfo[n].type = MT_COLOR_NORMAL;
       getyx(stdscr, brailleLine, brailleCol);
-    } else if (n > 0 && (buf[0] == ' ' || buf[0] == '\t'))
-    {
-      lineInfo[n].type = lineInfo[n-1].type; /* wrapped line */
-      (lineInfo[n].syntax)[0].color = (lineInfo[n-1].syntax)[0].color;
     }
     else
     {
-      lineInfo[n].type = MT_COLOR_HDEFAULT;
-      color_line = ColorHdrList;
-      while (color_line)
+      /* if this is a continuation of the previous line, use the previous
+       * line's color as default. */
+      if (n > 0 && (buf[0] == ' ' || buf[0] == '\t'))
+      {
+       lineInfo[n].type = lineInfo[n-1].type; /* wrapped line */
+       (lineInfo[n].syntax)[0].color = (lineInfo[n-1].syntax)[0].color;
+       lineInfo[n].is_cont_hdr = 1;
+      }
+      else
+      {
+       lineInfo[n].type = MT_COLOR_HDEFAULT;
+      }
+
+      for (color_line = ColorHdrList; color_line; color_line = color_line->next)
       {
        if (REGEXEC (color_line->rx, buf) == 0)
        {
          lineInfo[n].type = MT_COLOR_HEADER;
          lineInfo[n].syntax[0].color = color_line->pair;
+         if (lineInfo[n].is_cont_hdr)
+         {
+           /* adjust the previous continuation lines to reflect the color of this continuation line */
+           int j;
+           for (j = n - 1; j >= 0 && lineInfo[j].is_cont_hdr; --j)
+           {
+             lineInfo[j].type = lineInfo[n].type;
+             lineInfo[j].syntax[0].color = lineInfo[n].syntax[0].color;
+           }
+           /* now adjust the first line of this header field */
+           if (j >= 0)
+           {
+             lineInfo[j].type = lineInfo[n].type;
+             lineInfo[j].syntax[0].color = lineInfo[n].syntax[0].color;
+           }
+           *force_redraw = 1; /* the previous lines have already been drawn on the screen */
+         }
          break;
        }
-       color_line = color_line->next;
       }
     }
   }
@@ -812,8 +837,14 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last,
   if (lineInfo[n].type == MT_COLOR_NORMAL || 
       lineInfo[n].type == MT_COLOR_QUOTED)
   {
-    i = 0;
+    size_t nl;
+
+    /* don't consider line endings part of the buffer
+     * for regex matching */
+    if ((nl = mutt_strlen (buf)) > 0 && buf[nl-1] == '\n')
+      buf[nl-1] = 0;
 
+    i = 0;
     offset = 0;
     lineInfo[n].chunks = 0;
     do
@@ -863,6 +894,8 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last,
       else
        offset = (lineInfo[n].syntax)[i].last;
     } while (found || null_rx);
+    if (nl > 0)
+      buf[nl] = '\n';
   }
 }
 
@@ -988,18 +1021,18 @@ trim_incomplete_mbyte(unsigned char *buf, size_t len)
 }
 
 static int
-fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char *buf, 
-            unsigned char *fmt, size_t blen, int *buf_ready)
+fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char **buf,
+            unsigned char **fmt, size_t *blen, int *buf_ready)
 {
-  unsigned char *p;
+  unsigned char *p, *q;
   static int b_read;
-  
+  int l;
+
   if (*buf_ready == 0)
   {
-    buf[blen - 1] = 0;
     if (offset != *last_pos)
       fseeko (f, offset, 0);
-    if (fgets ((char *) buf, blen - 1, f) == NULL)
+    if ((*buf = (unsigned char *) mutt_read_line ((char *) *buf, blen, f, &l, M_EOL)) == NULL)
     {
       fmt[0] = 0;
       return (-1);
@@ -1008,26 +1041,29 @@ fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char *buf,
     b_read = (int) (*last_pos - offset);
     *buf_ready = 1;
 
+    safe_realloc (fmt, *blen);
+
     /* incomplete mbyte characters trigger a segfault in regex processing for
      * certain versions of glibc. Trim them if necessary. */
-    if (b_read == blen - 2)
-      b_read -= trim_incomplete_mbyte(buf, b_read);
+    if (b_read == *blen - 2)
+      b_read -= trim_incomplete_mbyte(*buf, b_read);
     
     /* copy "buf" to "fmt", but without bold and underline controls */
-    p = buf;
+    p = *buf;
+    q = *fmt;
     while (*p)
     {
-      if (*p == '\010' && (p > buf))
+      if (*p == '\010' && (p > *buf))
       {
        if (*(p+1) == '_')      /* underline */
          p += 2;
-       else if (*(p+1))        /* bold or overstrike */
+       else if (*(p+1) && q > *fmt)    /* bold or overstrike */
        {
-         *(fmt-1) = *(p+1);
+         *(q-1) = *(p+1);
          p += 2;
        }
        else                    /* ^H */
-         *fmt++ = *p++;
+         *q++ = *p++;
       }
       else if (*p == '\033' && *(p+1) == '[' && is_ansi (p + 2))
       {
@@ -1041,9 +1077,9 @@ fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char *buf,
          ;
       }
       else
-       *fmt++ = *p++;
+       *q++ = *p++;
     }
-    *fmt = 0;
+    *q = 0;
   }
   return b_read;
 }
@@ -1058,9 +1094,11 @@ static int format_line (struct line_t **lineInfo, int n, unsigned char *buf,
   int ch, vch, k, last_special = -1, special = 0, t;
   wchar_t wc;
   mbstate_t mbstate;
-
   int wrap_cols = mutt_term_width ((flags & M_PAGER_NOWRAP) ? 0 : Wrap);
-  
+
+  if (check_attachment_marker ((char *)buf) == 0)
+    wrap_cols = COLS;
+
   /* FIXME: this should come from lineInfo */
   memset(&mbstate, 0, sizeof(mbstate));
 
@@ -1228,7 +1266,8 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
              int *last, int *max, int flags, struct q_class_t **QuoteList,
              int *q_level, int *force_redraw, regex_t *SearchRE)
 {
-  unsigned char buf[LONG_STRING], fmt[LONG_STRING];
+  unsigned char *buf = NULL, *fmt = NULL;
+  size_t buflen = 0;
   unsigned char *buf_ptr = buf;
   int ch, vch, col, cnt, b_read;
   int buf_ready = 0, change_last = 0;
@@ -1236,6 +1275,7 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
   int offset;
   int def_color;
   int m;
+  int rc = -1;
   ansi_attr a = {0,0,0,-1};
   regmatch_t pmatch[1];
 
@@ -1264,11 +1304,11 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
     if ((*lineInfo)[n].type == -1)
     {
       /* determine the line class */
-      if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0)
+      if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, &buf, &fmt, &buflen, &buf_ready) < 0)
       {
        if (change_last)
          (*last)--;
-       return (-1);
+       goto out;
       }
 
       resolve_types ((char *) fmt, (char *) buf, *lineInfo, n, *last,
@@ -1293,11 +1333,11 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
   if ((flags & M_SHOWCOLOR) && !(*lineInfo)[n].continuation &&
       (*lineInfo)[n].type == MT_COLOR_QUOTED && (*lineInfo)[n].quote == NULL)
   {
-    if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0)
+    if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, &buf, &fmt, &buflen, &buf_ready) < 0)
     {
       if (change_last)
        (*last)--;
-      return (-1);
+      goto out;
     }
     regexec ((regex_t *) QuoteRegexp.rx, (char *) fmt, 1, pmatch, 0);
     (*lineInfo)[n].quote = classify_quote (QuoteList,
@@ -1308,11 +1348,11 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
 
   if ((flags & M_SEARCH) && !(*lineInfo)[n].continuation && (*lineInfo)[n].search_cnt == -1) 
   {
-    if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0)
+    if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, &buf, &fmt, &buflen, &buf_ready) < 0)
     {
       if (change_last)
        (*last)--;
-      return (-1);
+      goto out;
     }
 
     offset = 0;
@@ -1341,20 +1381,22 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
   if (!(flags & M_SHOW) && (*lineInfo)[n+1].offset > 0)
   {
     /* we've already scanned this line, so just exit */
-    return (0);
+    rc = 0;
+    goto out;
   }
   if ((flags & M_SHOWCOLOR) && *force_redraw && (*lineInfo)[n+1].offset > 0)
   {
     /* no need to try to display this line... */
-    return (1); /* fake display */
+    rc = 1;
+    goto out; /* fake display */
   }
 
-  if ((b_read = fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, 
-                             sizeof (buf), &buf_ready)) < 0)
+  if ((b_read = fill_buffer (f, last_pos, (*lineInfo)[n].offset, &buf, &fmt, 
+                            &buflen, &buf_ready)) < 0)
   {
     if (change_last)
       (*last)--;
-    return (-1);
+    goto out;
   }
 
   /* now chose a good place to break the line */
@@ -1366,7 +1408,8 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
   {
     if (cnt < b_read)
     {
-      if (ch != -1 && buf[cnt] != ' ' && buf[cnt] != '\t' && buf[cnt] != '\n' && buf[cnt] != '\r')
+      if (ch != -1 && buf[0] != ' ' && buf[0] != '\t' &&
+         buf[cnt] != ' ' && buf[cnt] != '\t' && buf[cnt] != '\n' && buf[cnt] != '\r')
       {
        buf_ptr = buf + ch;
        /* skip trailing blanks */
@@ -1398,7 +1441,10 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
 
   /* if we don't need to display the line we are done */
   if (!(flags & M_SHOW))
-    return 0;
+  {
+    rc = 0;
+    goto out;
+  }
 
   /* display the line */
   format_line (lineInfo, n, buf, flags, &a, cnt, &ch, &vch, &col, &special);
@@ -1459,7 +1505,12 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n,
   if (!(flags & M_SHOW))
     flags = 0;
 
-  return (flags);
+  rc = flags;
+
+out:
+  FREE(&buf);
+  FREE(&fmt);
+  return rc;
 }
 
 static int
@@ -1499,7 +1550,7 @@ static struct mapping_t PagerHelpExtra[] = {
 int 
 mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
 {
-  static char searchbuf[STRING];
+  static char searchbuf[STRING] = "";
   char buffer[LONG_STRING];
   char helpstr[SHORT_STRING*2];
   char tmphelp[SHORT_STRING*2];
@@ -1508,7 +1559,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
   struct q_class_t *QuoteList = NULL;
   int i, j, ch = 0, rc = -1, hideQuoted = 0, q_level = 0, force_redraw = 0;
   int lines = 0, curline = 0, topline = 0, oldtopline = 0, err, first = 1;
-  int r = -1, wrapped = 0;
+  int r = -1, wrapped = 0, searchctx = 0;
   int redraw = REDRAW_FULL;
   FILE *fp = NULL;
   LOFF_T last_pos = 0, last_offset = 0;
@@ -1542,7 +1593,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
   if (stat (fname, &sb) != 0)
   {
     mutt_perror (fname);
-    fclose (fp);
+    safe_fclose (&fp);
     return (-1);
   }
   unlink (fname);
@@ -1744,21 +1795,21 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
       SETCOLOR (MT_COLOR_STATUS);
       BKGDSET (MT_COLOR_STATUS);
       CLEARLINE (statusoffset);
-      if (IsHeader (extra))
+
+      if (IsHeader (extra) || IsMsgAttach (extra))
       {
        size_t l1 = COLS * MB_LEN_MAX;
        size_t l2 = sizeof (buffer);
-       hfi.hdr = extra->hdr;
+       hfi.hdr = (IsHeader (extra)) ? extra->hdr : extra->bdy->hdr;
        mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, NONULL (PagerFmt), &hfi, M_FORMAT_MAKEPRINT);
+       mutt_paddstr (COLS, buffer);
       }
-      else if (IsMsgAttach (extra))
+      else
       {
-       size_t l1 = COLS * MB_LEN_MAX;
-       size_t l2 = sizeof (buffer);
-       hfi.hdr = extra->bdy->hdr;
-       mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, NONULL (PagerFmt), &hfi, M_FORMAT_MAKEPRINT);
+       char bn[STRING];
+       snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str);
+       mutt_paddstr (COLS, bn);
       }
-      mutt_paddstr (COLS, IsHeader (extra) || IsMsgAttach (extra) ?  buffer : banner);
       BKGDSET (MT_COLOR_NORMAL);
       SETCOLOR (MT_COLOR_NORMAL);
     }
@@ -1965,12 +2016,17 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
        {
          wrapped = 0;
 
+         if (SearchContext > 0 && SearchContext < LINES - 2 - option (OPTHELP) ? 1 : 0)
+           searchctx = SearchContext;
+         else
+           searchctx = 0;
+
 search_next:
          if ((!SearchBack && ch==OP_SEARCH_NEXT) ||
              (SearchBack &&ch==OP_SEARCH_OPPOSITE))
          {
            /* searching forward */
-           for (i = wrapped ? 0 : topline + 1; i < lastLine; i++)
+           for (i = wrapped ? 0 : topline + searchctx + 1; i < lastLine; i++)
            {
              if ((!hideQuoted || lineInfo[i].type != MT_COLOR_QUOTED) && 
                    !lineInfo[i].continuation && lineInfo[i].search_cnt > 0)
@@ -1991,7 +2047,7 @@ search_next:
          else
          {
            /* searching backward */
-           for (i = wrapped ? lastLine : topline - 1; i >= 0; i--)
+           for (i = wrapped ? lastLine : topline + searchctx - 1; i >= 0; i--)
            {
              if ((!hideQuoted || (has_types && 
                    lineInfo[i].type != MT_COLOR_QUOTED)) && 
@@ -2012,7 +2068,12 @@ search_next:
          }
 
          if (lineInfo[topline].search_cnt > 0)
+         {
            SearchFlag = M_SEARCH;
+           /* give some context for search results */
+           if (topline - searchctx > 0)
+             topline -= searchctx;
+         }
 
          break;
        }
@@ -2021,9 +2082,10 @@ search_next:
       case OP_SEARCH:
       case OP_SEARCH_REVERSE:
         strfcpy (buffer, searchbuf, sizeof (buffer));
-       if (mutt_get_field ((SearchBack ? _("Reverse search: ") :
-                         _("Search: ")), buffer, sizeof (buffer),
-                         M_CLEAR) != 0)
+       if (mutt_get_field ((ch == OP_SEARCH || ch == OP_SEARCH_NEXT) ?
+                           _("Search for: ") : _("Reverse search for: "),
+                           buffer, sizeof (buffer),
+                           M_CLEAR) != 0)
          break;
 
        if (!strcmp (buffer, searchbuf))
@@ -2067,7 +2129,6 @@ search_next:
        {
          regerror (err, &SearchRE, buffer, sizeof (buffer));
          mutt_error ("%s", buffer);
-         regfree (&SearchRE);
          for (i = 0; i < maxLine ; i++)
          {
            /* cleanup */
@@ -2120,7 +2181,17 @@ search_next:
            mutt_error _("Not found.");
          }
          else
+         {
            SearchFlag = M_SEARCH;
+           /* give some context for search results */
+           if (SearchContext > 0 && SearchContext < LINES - 2 - option (OPTHELP) ? 1 : 0)
+             searchctx = SearchContext;
+           else
+             searchctx = 0;
+           if (topline - searchctx > 0)
+             topline -= searchctx;
+         }
+
        }
        redraw = REDRAW_BODY;
        break;
@@ -2281,6 +2352,20 @@ search_next:
        }
        break;
 
+      case OP_MAIN_SET_FLAG:
+      case OP_MAIN_CLEAR_FLAG:
+       CHECK_MODE(IsHeader (extra));
+       CHECK_READONLY;
+
+       if (mutt_change_flag (extra->hdr, (ch == OP_MAIN_SET_FLAG)) == 0)
+         redraw |= REDRAW_STATUS | REDRAW_INDEX;
+       if (extra->hdr->deleted && option (OPTRESOLVE))
+       {
+         ch = -1;
+         rc = OP_MAIN_NEXT_UNDELETED;
+       }
+       break;
+
       case OP_DELETE_THREAD:
       case OP_DELETE_SUBTHREAD:
        CHECK_MODE(IsHeader (extra));
@@ -2677,7 +2762,7 @@ search_next:
     }
   }
 
-  fclose (fp);
+  safe_fclose (&fp);
   if (IsHeader (extra))
   {
     Context->msgnotreadyet = -1;