Hello,
find attached some patches I rebased for mutt-1.7.0. In case someone
besides me is still using them.

Cheers,
        Thomas
>From 27610b5617b89af69a7e343864daa280862432a4 Mon Sep 17 00:00:00 2001
From: Thomas Glanzmann <[email protected]>
Date: Sun, 21 Aug 2016 10:02:27 +0200
Subject: [PATCH 1/5] Attach multiple files by tagging

This allows you to attach multiple files by pressing 'a' in the compose menu,
pressing <tab> or '?' to browse a directory and  select the file by tagging and
press 'q'.
---
 browser.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/browser.c b/browser.c
index 15eccc5..4650709 100644
--- a/browser.c
+++ b/browser.c
@@ -881,6 +881,8 @@ void _mutt_select_file (char *f, size_t flen, int flags, 
char ***files, int *num
 
          if (menu->tagged)
          {
+           /* XXX: make mutt_compose_menu recoginze that there are tagged 
files */
+           f[0] = 1;
            *numfiles = menu->tagged;
            tfiles = safe_calloc (*numfiles, sizeof (char *));
            for (i = 0, j = 0; i < state.entrylen; i++)
-- 
2.1.4

>From d4287bc15173ea58a4e85b9bbafe6b7fe6797b85 Mon Sep 17 00:00:00 2001
From: Thomas Glanzmann <[email protected]>
Date: Sun, 21 Aug 2016 10:05:07 +0200
Subject: [PATCH 2/5] Make it possible to colorize the status bar

Examples:
color status    blue      white

color status    brightred white (New|Del|Post|Inc|Flag):[0-9]+

color status    brightcyan white ^..(s)                                 1
color status    brightred  white ^..(S)                                 1

color status    brightred white ^.(\\\*)                                1
color status    brightred white \\\((all|end|no\ mailbox)\\\)           1
color status    brightred white \\\(([0-9]+%)\\\)                       1

color status    brightred white \\\[([A-Za-z0-9\ ]+)\\\]                1

color status    brightred white \\\(([^)]+/[^)]+)\\\)                   1
color status    blue      white \\\((threads/date-received)\\\)         1
---
 color.c       |  41 ++++++++++++++++-----
 curs_main.c   | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 mutt_curses.h |   2 ++
 pager.c       |   4 +--
 protos.h      |   1 +
 5 files changed, 150 insertions(+), 11 deletions(-)

diff --git a/color.c b/color.c
index c33d41e..369278e 100644
--- a/color.c
+++ b/color.c
@@ -34,6 +34,7 @@ int ColorQuoteUsed;
 int ColorDefs[MT_COLOR_MAX];
 COLOR_LINE *ColorHdrList = NULL;
 COLOR_LINE *ColorBodyList = NULL;
+COLOR_LINE *ColorStatusList = NULL;
 COLOR_LINE *ColorIndexList = NULL;
 
 /* local to this file */
@@ -506,7 +507,7 @@ static int _mutt_parse_uncolor (BUFFER *buf, BUFFER *s, 
unsigned long data,
 static int 
 add_pattern (COLOR_LINE **top, const char *s, int sensitive,
             int fg, int bg, int attr, BUFFER *err,
-            int is_index)
+            int is_index, int match)
 {
 
   /* is_index used to store compiled pattern
@@ -577,6 +578,7 @@ add_pattern (COLOR_LINE **top, const char *s, int sensitive,
     }
     tmp->next = *top;
     tmp->pattern = safe_strdup (s);
+    tmp->match = match;
 #ifdef HAVE_COLOR
     if(fg != -1 && bg != -1)
     {
@@ -719,7 +721,7 @@ _mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err,
                   parser_callback_t callback, short dry_run)
 {
   int object = 0, attr = 0, fg = 0, bg = 0, q_level = 0;
-  int r = 0;
+  int r = 0, match = 0;
 
   if(parse_object(buf, s, &object, &q_level, err) == -1)
     return -1;
@@ -727,8 +729,6 @@ _mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err,
   if(callback(buf, s, &fg, &bg, &attr, err) == -1)
     return -1;
 
-  /* extract a regular expression if needed */
-  
   if (object == MT_COLOR_HEADER || object == MT_COLOR_BODY || object == 
MT_COLOR_INDEX)
   {
     if (!MoreArgs (s))
@@ -740,7 +740,7 @@ _mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err,
     mutt_extract_token (buf, s, 0);
   }
    
-  if (MoreArgs (s))
+  if (MoreArgs (s) && object != MT_COLOR_STATUS)
   {
     strfcpy (err->data, _("too many arguments"), err->dsize);
     return (-1);
@@ -765,12 +765,37 @@ _mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err,
 #endif
   
   if (object == MT_COLOR_HEADER)
-    r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err,0);
+    r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err, 0, match);
   else if (object == MT_COLOR_BODY)
-    r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0);
+    r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0, 
match);
+  else if (object == MT_COLOR_STATUS && MoreArgs(s))
+  {
+    /* 'color status fg bg' can have upto 2 arguments:
+     * 0 arguments: sets the default status color (handled below by else part)
+     * 1 argument : colorize pattern on match
+     * 2 arguments: colorize nth submatch of pattern
+     */
+    mutt_extract_token (buf, s, 0);
+
+    if (MoreArgs(s)) {
+      BUFFER temporary;
+      memset(&temporary, 0, sizeof(BUFFER));
+      mutt_extract_token(&temporary, s, 0);
+      match = atoi(temporary.data);
+      FREE(&temporary.data);
+    }
+
+    if (MoreArgs(s))
+    {
+      strfcpy (err->data, _("too many arguments"), err->dsize);
+      return (-1);
+    }
+
+    r = add_pattern (&ColorStatusList, buf->data, 1, fg, bg, attr, err, 0, 
match);
+  }
   else if (object == MT_COLOR_INDEX)
   {
-    r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, attr, err, 1);
+    r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, attr, err, 1, 
match);
     set_option (OPTFORCEREDRAWINDEX);
   }
   else if (object == MT_COLOR_QUOTED)
diff --git a/curs_main.c b/curs_main.c
index 8e0f52a..0613268 100644
--- a/curs_main.c
+++ b/curs_main.c
@@ -482,6 +482,117 @@ static void resort_index (MUTTMENU *menu)
   menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
 }
 
+void
+mutt_draw_statusline(int cols, char *inbuf)
+{
+  int i          = 0;
+  int cnt        = 0;
+  int last_color = 0;
+  int color      = 0;
+  int offset     = 0;
+  int found = 0;
+  int null_rx = 0;
+  char buf[2048];
+
+  struct line_t {
+         short chunks;
+         struct syntax_t {
+                 int color;
+                 int first;
+                 int last;
+         } *syntax;
+  } lineInfo = { 0, 0 };
+
+  mutt_format_string(buf, sizeof(buf), cols, cols, 0, ' ', inbuf,
+                    mutt_strlen(inbuf), 0);
+
+  lineInfo.syntax = safe_malloc(sizeof(struct syntax_t));
+  lineInfo.syntax[0].first = -1;
+  lineInfo.syntax[0].last  = -1;
+  lineInfo.syntax[0].color = ColorDefs[MT_COLOR_STATUS];
+  lineInfo.chunks = 1;
+
+    do
+    {
+      found = 0;
+      null_rx = 0;
+      COLOR_LINE *color_line = ColorStatusList;
+
+      if (!buf[offset])
+       break;
+
+      while (color_line)
+      {
+        regmatch_t pmatch[color_line->match + 1];
+
+       if (regexec (&color_line->rx, buf + offset, color_line->match + 1, 
pmatch,
+                    (offset ? REG_NOTBOL : 0)) == 0)
+       {
+         if (pmatch[color_line->match].rm_eo != 
pmatch[color_line->match].rm_so)
+         {
+           if (!found)
+           {
+             if (++(lineInfo.chunks) > 1)
+               safe_realloc (&(lineInfo.syntax),
+                             (lineInfo.chunks) * sizeof (struct syntax_t));
+           }
+           i = lineInfo.chunks - 1;
+           pmatch[color_line->match].rm_so += offset;
+           pmatch[color_line->match].rm_eo += offset;
+           if (!found ||
+               pmatch[color_line->match].rm_so < (lineInfo.syntax)[i].first ||
+               (pmatch[color_line->match].rm_so == (lineInfo.syntax)[i].first 
&&
+                pmatch[color_line->match].rm_eo > (lineInfo.syntax)[i].last))
+           {
+             (lineInfo.syntax)[i].color = color_line->pair;
+             (lineInfo.syntax)[i].first = pmatch[color_line->match].rm_so;
+             (lineInfo.syntax)[i].last = pmatch[color_line->match].rm_eo;
+           }
+           found = 1;
+           null_rx = 0;
+         }
+         else
+           null_rx = 1; /* empty regexp; don't add it, but keep looking */
+       }
+       color_line = color_line->next;
+      }
+
+      if (null_rx)
+       offset++; /* avoid degenerate cases */
+      else
+       offset = (lineInfo.syntax)[i].last;
+    } while (found || null_rx);
+
+    for (cnt = 0; cnt < mutt_strlen(buf); cnt++) {
+           color = lineInfo.syntax[0].color;
+           for (i = 0; i < lineInfo.chunks; i++) {
+                   /* we assume the chunks are sorted */
+                   if (cnt > (lineInfo.syntax)[i].last)
+                           continue;
+                   if (cnt < (lineInfo.syntax)[i].first)
+                           break;
+                   if (cnt != (lineInfo.syntax)[i].last) {
+                           color = (lineInfo.syntax)[i].color;
+                           break;
+                   }
+                   /* don't break here, as cnt might be
+                    * in the next chunk as well */
+           }
+           if (color != last_color) {
+                   attrset (color);
+                   last_color = color;
+           }
+           addch (buf[cnt]); /* XXX more than one char at a time? */
+#if 0
+           waddnstr(stdscr, tgbuf, 10);
+           SETCOLOR (MT_COLOR_NORMAL);
+           waddnstr(stdscr, tgbuf + 10, -1);
+#endif
+    }
+
+    safe_free(&lineInfo.syntax);
+}
+
 static const struct mapping_t IndexHelp[] = {
   { N_("Quit"),  OP_QUIT },
   { N_("Del"),   OP_DELETE },
@@ -647,7 +758,7 @@ int mutt_index_menu (void)
        menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
         mutt_window_move (MuttStatusWindow, 0, 0);
        SETCOLOR (MT_COLOR_STATUS);
-       mutt_paddstr (MuttStatusWindow->cols, buf);
+       mutt_draw_statusline (MuttStatusWindow->cols, buf);
        NORMAL_COLOR;
        menu->redraw &= ~REDRAW_STATUS;
        if (option(OPTTSENABLED) && TSSupported)
diff --git a/mutt_curses.h b/mutt_curses.h
index 6200449..ba8aa52 100644
--- a/mutt_curses.h
+++ b/mutt_curses.h
@@ -137,6 +137,7 @@ enum
 typedef struct color_line
 {
   regex_t rx;
+  int match; /* which substringmap 0 for old behaviour */
   char *pattern;
   pattern_t *color_pattern; /* compiled pattern to speed up index color
                                calculation */
@@ -212,6 +213,7 @@ extern int ColorQuoteUsed;
 extern int ColorDefs[];
 extern COLOR_LINE *ColorHdrList;
 extern COLOR_LINE *ColorBodyList;
+extern COLOR_LINE *ColorStatusList;
 extern COLOR_LINE *ColorIndexList;
 
 void ci_init_color (void);
diff --git a/pager.c b/pager.c
index d7674eb..525f81c 100644
--- a/pager.c
+++ b/pager.c
@@ -1860,13 +1860,13 @@ mutt_pager (const char *banner, const char *fname, int 
flags, pager_t *extra)
        size_t l2 = sizeof (buffer);
        hfi.hdr = (IsHeader (extra)) ? extra->hdr : extra->bdy->hdr;
        mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, 
pager_status_window->cols, NONULL (PagerFmt), &hfi, MUTT_FORMAT_MAKEPRINT);
-       mutt_paddstr (pager_status_window->cols, buffer);
+       mutt_draw_statusline (pager_status_window->cols, buffer);
       }
       else
       {
        char bn[STRING];
        snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str);
-       mutt_paddstr (pager_status_window->cols, bn);
+       mutt_draw_statusline (pager_status_window->cols, bn);
       }
       NORMAL_COLOR;
       if (option(OPTTSENABLED) && TSSupported)
diff --git a/protos.h b/protos.h
index 19d6400..c543b04 100644
--- a/protos.h
+++ b/protos.h
@@ -182,6 +182,7 @@ void mutt_decode_base64 (STATE *s, long len, int istext, 
iconv_t cd);
 void mutt_default_save (char *, size_t, HEADER *);
 void mutt_display_address (ENVELOPE *);
 void mutt_display_sanitize (char *);
+void mutt_draw_statusline(int n, char *);
 void mutt_edit_content_type (HEADER *, BODY *, FILE *);
 void mutt_edit_file (const char *, const char *);
 void mutt_edit_headers (const char *, const char *, HEADER *, char *, size_t);
-- 
2.1.4

>From 06814960e7a88a661537d2fa1d1b607f3e48f363 Mon Sep 17 00:00:00 2001
From: Thomas Glanzmann <[email protected]>
Date: Sun, 21 Aug 2016 10:07:01 +0200
Subject: [PATCH 3/5] make it possible to change headers after editing the body
 of the message

This patch looks at certain paramters after an E-Mail message is edited and
makes it possible to adapt the from header based on certain conditions or the
from lines.

Example:

send2-hook '! ~C problems@' 'clr_header reply-to:'
send2-hook '~C problems@' 'set_header reply-to: problems'

send2-hook '! ~C @lhsystems.com' 'set_header from: Thomas Glanzmann 
<[email protected]>'
send2-hook '~C @lhsystems.com | ~C @tomorrow-focus.de' 'set_header from: Thomas 
Glanzmann <[email protected]>'
---
 hook.c   | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 init.h   |  4 ++++
 mutt.h   |  6 +++++
 protos.h |  1 +
 4 files changed, 90 insertions(+)

diff --git a/hook.c b/hook.c
index 1b906c3..823164c 100644
--- a/hook.c
+++ b/hook.c
@@ -42,6 +42,82 @@ typedef struct hook
 static HOOK *Hooks = NULL;
 
 static int current_hook_type = 0;
+static ENVELOPE *current_hook_env = NULL;
+
+int mutt_modify_header (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER 
*err)
+{
+  size_t keylen;
+  char *p;
+  ADDRESS **c = NULL;
+
+
+  mutt_extract_token (buf, s, MUTT_TOKEN_SPACE | MUTT_TOKEN_QUOTE);
+  if ((p = strpbrk (buf->data, ": \t")) == NULL || *p != ':')
+  {
+    strfcpy (err->data, _("invalid header field"), err->dsize);
+    return (-1);
+  }
+
+  keylen = p - buf->data + 1;
+
+  if (current_hook_env == NULL) {
+         strfcpy (err->data, _("not called inside a hook"), err->dsize);
+         return (-1);
+  }
+
+  if (ascii_strncasecmp (buf->data, "reply-to:", 9) == 0) {
+       c = &(current_hook_env->reply_to);
+
+  } else if (ascii_strncasecmp (buf->data, "from:", 5) == 0) {
+       c = &(current_hook_env->from);
+
+  } else {
+        strfcpy (err->data, _("can't handle this heaer"), err->dsize);
+       return -1;
+  }
+
+  switch(data) {
+  case MODIFYHEADER_ADD:
+         /* FIXME: check if already there --tg 17:37 05-05-12 */
+         *c = rfc822_parse_adrlist (*c, buf->data + keylen);
+         break;
+
+  case MODIFYHEADER_CLR:
+         rfc822_free_address (c);
+         break;
+
+  case MODIFYHEADER_DEL:
+#if 0
+         {
+                 ADDRESS *t = *c;
+                 while(t) {
+                         if (ascii_strncasecmp (buf->data + keylen, t->mailbox,
+                                         mutt_strlen(buf->data + keylen)) == 
0) {
+                         }
+
+                         rfc822_free_address (c);
+                 }
+         }
+#else
+        strfcpy (err->data, _("not implemented"), err->dsize);
+       return -1;
+#endif
+         break;
+
+  case MODIFYHEADER_SET:
+         rfc822_free_address (c);
+         *c = rfc822_parse_adrlist (*c, buf->data + keylen);
+         break;
+
+  default:
+         strfcpy (err->data, _("can only add, del or set header"), err->dsize);
+         return -1;
+         break;
+  }
+
+  memset (buf, 0, sizeof (BUFFER));
+  return 0;
+}
 
 int mutt_parse_hook (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
 {
@@ -350,6 +426,7 @@ void mutt_message_hook (CONTEXT *ctx, HEADER *hdr, int type)
   HOOK *hook;
 
   current_hook_type = type;
+  current_hook_env  = hdr->env;
 
   mutt_buffer_init (&err);
   err.dsize = STRING;
@@ -368,6 +445,7 @@ void mutt_message_hook (CONTEXT *ctx, HEADER *hdr, int type)
          mutt_error ("%s", err.data);
          mutt_sleep (1);
          current_hook_type = 0;
+          current_hook_env  = NULL;
          FREE (&err.data);
 
          return;
@@ -377,6 +455,7 @@ void mutt_message_hook (CONTEXT *ctx, HEADER *hdr, int type)
   FREE (&err.data);
 
   current_hook_type = 0;
+  current_hook_env  = NULL;
 }
 
 static int
diff --git a/init.h b/init.h
index 3f3f96d..d809281 100644
--- a/init.h
+++ b/init.h
@@ -3877,6 +3877,7 @@ struct command_t
 };
 
 const struct command_t Commands[] = {
+  { "add_header",       mutt_modify_header,     MODIFYHEADER_ADD },
   { "alternates",      parse_alternates,       0 },
   { "unalternates",    parse_unalternates,     0 },
 #ifdef USE_SOCKET
@@ -3889,10 +3890,12 @@ const struct command_t Commands[] = {
   { "alternative_order",       parse_list,     UL &AlternativeOrderList},
   { "bind",            mutt_parse_bind,        0 },
   { "charset-hook",    mutt_parse_hook,        MUTT_CHARSETHOOK },
+  { "clr_header",       mutt_modify_header,     MODIFYHEADER_CLR },
 #ifdef HAVE_COLOR
   { "color",           mutt_parse_color,       0 },
   { "uncolor",         mutt_parse_uncolor,     0 },
 #endif
+  { "del_header",       mutt_modify_header,     MODIFYHEADER_DEL },
   { "exec",            mutt_parse_exec,        0 },
   { "fcc-hook",                mutt_parse_hook,        MUTT_FCCHOOK },
   { "fcc-save-hook",   mutt_parse_hook,        MUTT_FCCHOOK | MUTT_SAVEHOOK },
@@ -3932,6 +3935,7 @@ const struct command_t Commands[] = {
   { "source",          parse_source,           0 },
   { "spam",            parse_spam_list,        MUTT_SPAM },
   { "nospam",          parse_spam_list,        MUTT_NOSPAM },
+  { "set_header",       mutt_modify_header,     MODIFYHEADER_SET },
   { "subscribe",       parse_subscribe,        0 },
   { "toggle",          parse_set,              MUTT_SET_INV },
   { "unalias",         parse_unalias,          0 },
diff --git a/mutt.h b/mutt.h
index 2cf55b1..1575d5d 100644
--- a/mutt.h
+++ b/mutt.h
@@ -313,6 +313,12 @@ enum
 #define MUTT_SPAM          1
 #define MUTT_NOSPAM        2
 
+/* flags for mutt_modify_header */
+#define MODIFYHEADER_ADD (1<<0)
+#define MODIFYHEADER_CLR (1<<1)
+#define MODIFYHEADER_DEL (1<<2)
+#define MODIFYHEADER_SET (1<<3)
+
 /* boolean vars */
 enum
 {
diff --git a/protos.h b/protos.h
index c543b04..91a134b 100644
--- a/protos.h
+++ b/protos.h
@@ -328,6 +328,7 @@ int mutt_match_rx_list (const char *, RX_LIST *);
 int mutt_match_spam_list (const char *, SPAM_LIST *, char *, int);
 int mutt_messages_in_thread (CONTEXT *, HEADER *, int);
 int mutt_multi_choice (char *prompt, char *letters);
+int mutt_modify_header (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER 
*err);
 int mutt_needs_mailcap (BODY *);
 int mutt_num_postponed (int);
 int mutt_parse_bind (BUFFER *, BUFFER *, unsigned long, BUFFER *);
-- 
2.1.4

>From 8ea755c230eb70b705f15778fceabdc7ad5b2aae Mon Sep 17 00:00:00 2001
From: Thomas Glanzmann <[email protected]>
Date: Sun, 21 Aug 2016 10:21:58 +0200
Subject: [PATCH 4/5] Make it possible to collapse all thread expect for a few
 matching some citeria

Example:

set collapse_flagged=no
set collapse_unread=no
folder-hook . 'push <collapse-all>'

collapse everything expect flagged and unread threads.
---
 curs_main.c | 17 +++++++++++++----
 init.h      |  6 ++++++
 mutt.h      |  2 ++
 protos.h    |  1 +
 thread.c    | 16 +++++++++++++++-
 5 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/curs_main.c b/curs_main.c
index 0613268..07c957b 100644
--- a/curs_main.c
+++ b/curs_main.c
@@ -113,6 +113,11 @@ static const char *No_visible = N_("No visible messages.");
 #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)
+#define FLAGGED(h) mutt_thread_contains_flagged (Context, h)
+
+#define CHECK_IF_TO_COLLAPSE(header) \
+  ((option (OPTCOLLAPSEUNREAD)  || !UNREAD (header)) && \
+   (option (OPTCOLLAPSEFLAGGED) || FLAGGED(header) == 0))
 
 /* de facto standard escapes for tsl/fsl */
 static char *tsl = "\033]0;";
@@ -1965,14 +1970,14 @@ int mutt_index_menu (void)
          if (option (OPTUNCOLLAPSEJUMP))
            menu->current = mutt_thread_next_unread (Context, CURHDR);
        }
-       else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
+        else if CHECK_IF_TO_COLLAPSE(CURHDR)
        {
          menu->current = mutt_collapse_thread (Context, CURHDR);
          mutt_set_virtual (Context);
        }
        else
        {
-         mutt_error _("Thread contains unread messages.");
+          mutt_error _("Thread contains unread or flagged messages.");
          break;
        }
 
@@ -1997,8 +2002,10 @@ int mutt_index_menu (void)
 
          if (CURHDR->collapsed)
            final = mutt_uncollapse_thread (Context, CURHDR);
-         else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
+          else if CHECK_IF_TO_COLLAPSE(CURHDR)
+          {
            final = mutt_collapse_thread (Context, CURHDR);
+          }
          else
            final = CURHDR->virtual;
 
@@ -2016,9 +2023,11 @@ int mutt_index_menu (void)
            {
              if (h->collapsed)
                mutt_uncollapse_thread (Context, h);
-             else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (h))
+              else if CHECK_IF_TO_COLLAPSE(h)
+              {
                mutt_collapse_thread (Context, h);
            }
+            }
            top = top->next;
          }
 
diff --git a/init.h b/init.h
index 381e43f..8ebc621 100644
--- a/init.h
+++ b/init.h
@@ -3616,6 +3616,12 @@ struct option_t MuttVars[] = {
   ** tunnel commands per connection.
   */
 #endif
+  { "collapse_flagged",        DT_BOOL, R_NONE, OPTCOLLAPSEFLAGGED, 1 },
+  /*
+  ** .pp
+  ** When \fIunset\fP, Mutt will not collapse a thread if it contains any
+  ** flagged messages.
+  */
   { "uncollapse_jump",         DT_BOOL, R_NONE, OPTUNCOLLAPSEJUMP, 0 },
   /*
   ** .pp
diff --git a/mutt.h b/mutt.h
index 1575d5d..ffa44a1 100644
--- a/mutt.h
+++ b/mutt.h
@@ -163,6 +163,7 @@ typedef enum
 #define MUTT_THREAD_GET_HIDDEN  (1<<2)
 #define MUTT_THREAD_UNREAD      (1<<3)
 #define MUTT_THREAD_NEXT_UNREAD (1<<4)
+#define MUTT_THREAD_FLAGGED       (1<<5)
 
 enum
 {
@@ -338,6 +339,7 @@ enum
   OPTCHECKMBOXSIZE,
   OPTCHECKNEW,
   OPTCOLLAPSEUNREAD,
+  OPTCOLLAPSEFLAGGED,
   OPTCONFIRMAPPEND,
   OPTCONFIRMCREATE,
   OPTDELETEUNTAG,
diff --git a/protos.h b/protos.h
index 91a134b..45667cd 100644
--- a/protos.h
+++ b/protos.h
@@ -62,6 +62,7 @@ int _mutt_aside_thread (HEADER *, short, short);
 #define mutt_uncollapse_thread(x,y) _mutt_traverse_thread 
(x,y,MUTT_THREAD_UNCOLLAPSE)
 #define mutt_get_hidden(x,y)_mutt_traverse_thread (x,y,MUTT_THREAD_GET_HIDDEN) 
 #define mutt_thread_contains_unread(x,y) _mutt_traverse_thread 
(x,y,MUTT_THREAD_UNREAD)
+#define mutt_thread_contains_flagged(x,y) _mutt_traverse_thread 
(x,y,MUTT_THREAD_FLAGGED)
 #define mutt_thread_next_unread(x,y) 
_mutt_traverse_thread(x,y,MUTT_THREAD_NEXT_UNREAD)
 int _mutt_traverse_thread (CONTEXT *ctx, HEADER *hdr, int flag);
 
diff --git a/thread.c b/thread.c
index cf77bdb..d429c0f 100644
--- a/thread.c
+++ b/thread.c
@@ -1129,7 +1129,7 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int 
flag)
   THREAD *thread, *top;
   HEADER *roothdr = NULL;
   int final, reverse = (Sort & SORT_REVERSE), minmsgno;
-  int num_hidden = 0, new = 0, old = 0;
+  int num_hidden = 0, new = 0, old = 0, flagged = 0;
   int min_unread_msgno = INT_MAX, min_unread = cur->virtual;
 #define CHECK_LIMIT (!ctx->pattern || cur->limited)
 
@@ -1162,6 +1162,11 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, 
int flag)
     }
   }
 
+  if (cur->flagged && CHECK_LIMIT)
+  {
+    flagged = 1;
+  }
+
   if (cur->virtual == -1 && CHECK_LIMIT)
     num_hidden++;
 
@@ -1188,6 +1193,8 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int 
flag)
       return (num_hidden);
     else if (flag & MUTT_THREAD_NEXT_UNREAD)
       return (min_unread);
+    else if (flag & MUTT_THREAD_FLAGGED)
+      return (flagged);
   }
   
   FOREVER
@@ -1239,6 +1246,11 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, 
int flag)
        }
       }
 
+      if (cur->flagged && CHECK_LIMIT)
+      {
+        flagged = 1;
+      }
+
       if (cur->virtual == -1 && CHECK_LIMIT)
        num_hidden++;
     }
@@ -1274,6 +1286,8 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int 
flag)
     return (num_hidden+1);
   else if (flag & MUTT_THREAD_NEXT_UNREAD)
     return (min_unread);
+  else if (flag & MUTT_THREAD_FLAGGED)
+    return (flagged);
 
   return (0);
 #undef CHECK_LIMIT
-- 
2.1.4

>From 668502204b7297903c29b3bd023eae0d81a80483 Mon Sep 17 00:00:00 2001
From: Thomas Glanzmann <[email protected]>
Date: Sun, 21 Aug 2016 10:12:49 +0200
Subject: [PATCH 5/5] Introduce attach_umask to specify the umask that is used
 to save attachements

This patch introduces a new parameter attach_umask which allows to specify the
umask that is being used to save attachments. It defaults to 0077. It changes
the file creation mode of safe_open from 0600 to 0644 which is not a problem
because mutt sets the umask to 0700 when starting in main() in main.c The umask
is honored by open.

Example:
set attach_umask=0022
---
 attach.c  | 14 ++++++++++++--
 globals.h |  1 +
 init.h    |  5 +++++
 lib.c     |  4 ++--
 4 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/attach.c b/attach.c
index 84cdf6d..7a098b8 100644
--- a/attach.c
+++ b/attach.c
@@ -691,12 +691,22 @@ bail:
 static FILE *
 mutt_save_attachment_open (char *path, int flags)
 {
+   mode_t omask, nmask;
+   FILE *ret;
+
   if (flags == MUTT_SAVE_APPEND)
     return fopen (path, "a");
   if (flags == MUTT_SAVE_OVERWRITE)
     return fopen (path, "w");          /* __FOPEN_CHECKED__ */
-  
-  return safe_fopen (path, "w");
+
+  if (sscanf(AttachUmask, "%o", &nmask) == 1) {
+    omask = umask(nmask);
+    ret = safe_fopen (path, "w");
+    umask(omask);
+  } else
+    ret = safe_fopen (path, "w");
+
+  return ret;
 }
 
 /* returns 0 on success, -1 on error */
diff --git a/globals.h b/globals.h
index 95a6869..5e35e07 100644
--- a/globals.h
+++ b/globals.h
@@ -35,6 +35,7 @@ WHERE char *AliasFile;
 WHERE char *AliasFmt;
 WHERE char *AssumedCharset;
 WHERE char *AttachSep;
+WHERE char *AttachUmask;
 WHERE char *Attribution;
 WHERE char *AttachCharset;
 WHERE char *AttachFormat;
diff --git a/init.h b/init.h
index babc574..8ebc621 100644
--- a/init.h
+++ b/init.h
@@ -259,6 +259,11 @@ struct option_t MuttVars[] = {
   ** $$attach_sep separator is added after each attachment. When \fIset\fP,
   ** Mutt will operate on the attachments one by one.
   */
+  { "attach_umask",     DT_STR,  R_NONE, UL &AttachUmask, UL "0077" },
+  /*
+  ** .pp
+  ** The umask which is used while saving attachments. Defaults to 0077.
+  */
   { "attribution",     DT_STR,  R_NONE, UL &Attribution, UL "On %d, %n wrote:" 
},
   /*
   ** .pp
diff --git a/lib.c b/lib.c
index 224232b..aa401df 100644
--- a/lib.c
+++ b/lib.c
@@ -642,7 +642,7 @@ int safe_open (const char *path, int flags)
                        safe_dir, sizeof (safe_dir)) == -1)
       return -1;
     
-    if ((fd = open (safe_file, flags, 0600)) < 0)
+    if ((fd = open (safe_file, flags, 0644)) < 0)
     {
       rmdir (safe_dir);
       return fd;
@@ -654,7 +654,7 @@ int safe_open (const char *path, int flags)
       return -1;
   }
 
-  if ((fd = open (path, flags & ~O_EXCL, 0600)) < 0)
+  if ((fd = open (path, flags & ~O_EXCL, 0644)) < 0)
     return fd;
     
   /* make sure the file is not symlink */
-- 
2.1.4

Reply via email to