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