Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37569042
en ru br
ALT Linux repos
S:20230517-alt1

Group :: Networking/Mail
RPM: neomutt

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: neomutt-color-group.patch
Download


From: Alexey Gladkov <gladkov.alexey@gmail.com>
Date: Mon, 22 Jul 2019 20:03:52 +0000 (+0200)
Subject: Add color groups for header and body
X-Git-Url: http://git.altlinux.org/people/glebfm/packages/neomutt.git?p=neomutt.git;a=commitdiff_plain;h=f91e40fd6940d847c557083c33a01440e399fc3d
Add color groups for header and body
Co-authored-by: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
Signed-off-by: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
---
diff --git a/gui/color.c b/gui/color.c
index c21570f..6bdf196 100644
--- a/gui/color.c
+++ b/gui/color.c
@@ -153,6 +153,13 @@ const struct Mapping ComposeFields[] = {
 };
 // clang-format off
 
+static const struct Mapping ColorGroupFields[] =
+{
+  { "start", MT_COLOR_GROUP_START },
+  { "end", MT_COLOR_GROUP_END },
+  { NULL, 0 },
+};
+
 /**
  * defs_free - Free the simple colour definitions
  * @param c Colours
@@ -364,6 +371,8 @@ void mutt_colors_free(struct Colors **ptr)
   defs_free(c);
   quotes_free(c);
   notify_free(&c->notify);
+  mutt_free_color_group_stack(&c->group_header_stack);
+  mutt_free_color_group_stack(&c->group_body_stack);
   FREE(ptr);
 }
 
@@ -388,6 +397,8 @@ struct Colors *mutt_colors_new(void)
   STAILQ_INIT(&c->index_subject_list);
   STAILQ_INIT(&c->index_tag_list);
   STAILQ_INIT(&c->status_list);
+  c->group_header_stack = NULL;
+  c->group_body_stack = NULL;
 
 #ifdef HAVE_COLOR
   start_color();
@@ -953,7 +964,7 @@ enum CommandResult mutt_parse_unmono(struct Buffer *buf, struct Buffer *s,
  */
 static enum CommandResult add_pattern(struct Colors *c, struct ColorLineList *top, const char *s,
                                       bool sensitive, uint32_t fg, uint32_t bg, int attr,
-                                      struct Buffer *err, bool is_index, int match)
+                                      struct Buffer *err, bool is_index, int match, struct ColorGroupStack *cgs)
 {
   struct ColorLine *tmp = NULL;
 
@@ -1043,6 +1054,8 @@ static enum CommandResult add_pattern(struct Colors *c, struct ColorLineList *to
     }
   }
 
+  if (cgs)
+      tmp->group = cgs->group;
   return MUTT_CMD_SUCCESS;
 }
 
@@ -1240,32 +1253,36 @@ static enum CommandResult parse_color(struct Colors *c, struct Buffer *buf, stru
 #endif
 
   if (object == MT_COLOR_ATTACH_HEADERS)
-    rc = add_pattern(c, &c->attach_list, buf->data, true, fg, bg, attr, err, false, match);
+    rc = add_pattern(c, &c->attach_list, buf->data, true, fg, bg, attr, err, false, match, NULL);
   else if (object == MT_COLOR_BODY)
-    rc = add_pattern(c, &c->body_list, buf->data, true, fg, bg, attr, err, false, match);
+    rc = add_pattern(c, &c->body_list, buf->data, true, fg, bg, attr,
+                     err, false, match, c->group_body_stack);
   else if (object == MT_COLOR_HEADER)
-    rc = add_pattern(c, &c->hdr_list, buf->data, false, fg, bg, attr, err, false, match);
+  {
+    rc = add_pattern(c, &c->hdr_list, buf->data, false, fg, bg, attr,
+                     err, false, match, c->group_header_stack);
+  }
   else if (object == MT_COLOR_INDEX)
   {
-    rc = add_pattern(c, &c->index_list, buf->data, true, fg, bg, attr, err, true, match);
+    rc = add_pattern(c, &c->index_list, buf->data, true, fg, bg, attr, err, true, match, NULL);
   }
   else if (object == MT_COLOR_INDEX_AUTHOR)
   {
     rc = add_pattern(c, &c->index_author_list, buf->data, true, fg, bg, attr,
-                     err, true, match);
+                     err, true, match, NULL);
   }
   else if (object == MT_COLOR_INDEX_FLAGS)
   {
-    rc = add_pattern(c, &c->index_flags_list, buf->data, true, fg, bg, attr, err, true, match);
+    rc = add_pattern(c, &c->index_flags_list, buf->data, true, fg, bg, attr, err, true, match, NULL);
   }
   else if (object == MT_COLOR_INDEX_SUBJECT)
   {
     rc = add_pattern(c, &c->index_subject_list, buf->data, true, fg, bg, attr,
-                     err, true, match);
+                     err, true, match, NULL);
   }
   else if (object == MT_COLOR_INDEX_TAG)
   {
-    rc = add_pattern(c, &c->index_tag_list, buf->data, true, fg, bg, attr, err, true, match);
+    rc = add_pattern(c, &c->index_tag_list, buf->data, true, fg, bg, attr, err, true, match, NULL);
   }
   else if (object == MT_COLOR_QUOTED)
   {
@@ -1322,7 +1339,7 @@ static enum CommandResult parse_color(struct Colors *c, struct Buffer *buf, stru
       return MUTT_CMD_WARNING;
     }
 
-    rc = add_pattern(c, &c->status_list, buf->data, true, fg, bg, attr, err, false, match);
+    rc = add_pattern(c, &c->status_list, buf->data, true, fg, bg, attr, err, false, match, NULL);
   }
   else // Remaining simple colours
   {
@@ -1373,3 +1390,128 @@ enum CommandResult mutt_parse_mono(struct Buffer *buf, struct Buffer *s,
 
   return parse_color(Colors, buf, s, err, parse_attr_spec, dry_run, false);
 }
+
+#ifdef HAVE_COLOR
+/* usage: color-group { header | body } { start | end } <regexp>
+ */
+enum CommandResult mutt_parse_color_group(struct Buffer *buf, struct Buffer *s,
+                                          intptr_t data, struct Buffer *err)
+{
+        int target = 0;
+        int object = 0;
+        int r = 0;
+        regex_t *rx;
+        struct ColorGroup *grp;
+        struct ColorGroupStack **stack, *newStack;
+
+        if(!MoreArgs(s))
+        {
+                mutt_str_copy(err->data, _("(0) Missing arguments."), err->dsize);
+                return MUTT_CMD_ERROR;
+        }
+
+        mutt_extract_token(buf, s, 0);
+
+        if ((target = mutt_map_get_value(buf->data, Fields)) == -1)
+        {
+                snprintf(err->data, err->dsize, _("%s: no such object"), buf->data);
+                return MUTT_CMD_ERROR;
+        }
+
+        if (target == MT_COLOR_HEADER)
+        {
+                stack = &Colors->group_header_stack;
+        }
+        else if (target == MT_COLOR_BODY)
+        {
+                stack = &Colors->group_body_stack;
+        }
+        else
+        {
+                mutt_str_copy(err->data, _("Target must be 'header' or 'body'."), err->dsize);
+                return MUTT_CMD_ERROR;
+        }
+
+        mutt_extract_token(buf, s, 0);
+
+        if ((object = mutt_map_get_value(buf->data, ColorGroupFields)) == -1)
+        {
+                snprintf(err->data, err->dsize, _("%s: no such object"), buf->data);
+                return MUTT_CMD_ERROR;
+        }
+
+        if (!MoreArgs(s))
+        {
+                mutt_str_copy(err->data, _("(1) Missing arguments."), err->dsize);
+                return MUTT_CMD_ERROR;
+        }
+
+        mutt_extract_token(buf, s, 0);
+
+        if (MoreArgs(s))
+        {
+                mutt_str_copy(err->data, _("too many arguments"), err->dsize);
+                return MUTT_CMD_ERROR;
+        }
+
+        if (OptNoCurses || !has_colors())
+                return MUTT_CMD_SUCCESS;
+
+        rx = mutt_mem_calloc(1, sizeof(regex_t));
+
+        int flags = mutt_mb_is_lower(buf->data) ? REG_ICASE : 0;
+        if ((r = REG_COMP(rx, buf->data, flags)) != 0)
+        {
+                regerror(r, rx, err->data, err->dsize);
+                FREE(rx);
+                return MUTT_CMD_ERROR;
+        }
+
+        if (object == MT_COLOR_GROUP_END)
+        {
+                if (!*stack)
+                {
+                        mutt_str_copy(err->data, "Unexpected group ending.", err->dsize);
+                        regfree(rx);
+                        FREE(rx);
+                        return MUTT_CMD_ERROR;
+                }
+
+                (*stack)->group->pattern_end = mutt_str_dup(buf->data);
+                (*stack)->group->rx_end = rx;
+
+                newStack = (*stack)->next;
+                FREE(stack);
+                *stack = newStack;
+
+                return MUTT_CMD_SUCCESS;
+        }
+
+        grp = mutt_mem_calloc(1, sizeof(struct ColorGroup));
+        grp->pattern_start = mutt_str_dup(buf->data);
+        grp->rx_start = rx;
+
+        newStack = mutt_mem_calloc(1, sizeof(struct ColorGroupStack));
+        newStack->group = grp;
+        newStack->next = *stack;
+
+        *stack = newStack;
+
+        return MUTT_CMD_SUCCESS;
+}
+#endif
+
+void mutt_free_color_group_stack(struct ColorGroupStack **top)
+{
+        struct ColorGroupStack *t, *e;
+        if (!top)
+                return;
+        t = *top;
+        while (t)
+        {
+                e = t->next;
+                FREE(&t);
+                t = e;
+        }
+        *top = NULL;
+}
diff --git a/gui/color.h b/gui/color.h
index 8f02b32..0bb19b9 100644
--- a/gui/color.h
+++ b/gui/color.h
@@ -29,6 +29,29 @@
 #include "mutt/lib.h"
 #include "mutt_commands.h"
 
+enum ColorGroupPart
+{
+  MT_COLOR_GROUP_START,
+  MT_COLOR_GROUP_END,
+};
+
+struct ColorGroup
+{
+  char *pattern_start;
+  char *pattern_end;
+  regex_t *rx_start;
+  regex_t *rx_end;
+  struct ColorGroup *next;
+};
+
+struct ColorGroupStack
+{
+  struct ColorGroup *group;
+  struct ColorGroupStack *next;
+};
+
+void mutt_free_color_group_stack(struct ColorGroupStack **top);
+
 /**
  * struct ColorLine - A regular expression and a color to highlight a line
  */
@@ -38,6 +61,7 @@ struct ColorLine
   int match;                         ///< Substring to match, 0 for old behaviour
   char *pattern;                     ///< Pattern to match
   struct PatternList *color_pattern; ///< Compiled pattern to speed up index color calculation
+  struct ColorGroup *group;
   uint32_t fg;                       ///< Foreground colour
   uint32_t bg;                       ///< Background colour
   int pair;                          ///< Colour pair index
@@ -140,6 +164,9 @@ struct Colors
   struct ColorLineList index_tag_list;     ///< List of colours applied to tags in the index
   struct ColorLineList status_list;        ///< List of colours applied to the status bar
 
+  struct ColorGroupStack *group_header_stack;
+  struct ColorGroupStack *group_body_stack;
+
   int *quotes;                             ///< Array of colours for quoted email text
   int quotes_used;                         ///< Number of colours for quoted email text
 
@@ -182,6 +209,7 @@ void           mutt_colors_free(struct Colors **ptr);
 enum CommandResult mutt_parse_color  (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
 enum CommandResult mutt_parse_mono   (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
 enum CommandResult mutt_parse_uncolor(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
+enum CommandResult mutt_parse_color_group(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
 enum CommandResult mutt_parse_unmono (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err);
 
 #endif /* MUTT_COLOR_H */
diff --git a/init.c b/init.c
index 458b07a..8ec1c51 100644
--- a/init.c
+++ b/init.c
@@ -964,6 +964,7 @@ int mutt_init(struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
 done:
   mutt_buffer_dealloc(&err);
   mutt_buffer_dealloc(&buf);
+
   return rc;
 }
 
diff --git a/mutt_commands.c b/mutt_commands.c
index 94f9855..7f23063 100644
--- a/mutt_commands.c
+++ b/mutt_commands.c
@@ -59,6 +59,7 @@ static const struct Command mutt_commands[] = {
   { "charset-hook",        mutt_parse_hook,        MUTT_CHARSET_HOOK },
 #ifdef HAVE_COLOR
   { "color",               mutt_parse_color,       0 },
+  { "color-group",         mutt_parse_color_group, 0 },
 #endif
   { "crypt-hook",          mutt_parse_hook,        MUTT_CRYPT_HOOK },
   { "echo",                parse_echo,             0 },
diff --git a/pager.c b/pager.c
index a180873..258c88b 100644
--- a/pager.c
+++ b/pager.c
@@ -197,6 +197,8 @@ struct PagerRedrawData
   struct Line *line_info;
   FILE *fp;
   struct stat sb;
+  struct ColorGroupStack *group_header_stack;
+  struct ColorGroupStack *group_body_stack;
 };
 
 /* hack to return to position when returning from index to same message */
@@ -1006,10 +1008,12 @@ int mutt_is_quote_line(char *line, regmatch_t *pmatch)
  */
 static void resolve_types(char *buf, char *raw, struct Line *line_info, int n,
                           int last, struct QClass **quote_list, int *q_level,
-                          bool *force_redraw, bool q_classify)
+                          bool *force_redraw, bool q_classify,
+                          struct PagerRedrawData *rd)
 {
   struct ColorLine *color_line = NULL;
   struct ColorLineList *head = NULL;
+  struct ColorGroupStack **color_stack;
   regmatch_t pmatch[1];
   bool found;
   bool null_rx;
@@ -1129,9 +1133,15 @@ static void resolve_types(char *buf, char *raw, struct Line *line_info, int n,
     offset = 0;
     line_info[n].chunks = 0;
     if (line_info[n].type == MT_COLOR_HDRDEFAULT)
+    {
       head = &Colors->hdr_list;
+      color_stack = &rd->group_header_stack;
+    }
     else
+    {
       head = &Colors->body_list;
+      color_stack = &rd->group_body_stack;
+    }
     STAILQ_FOREACH(color_line, head, entries)
     {
       color_line->stop_matching = false;
@@ -1145,6 +1155,34 @@ static void resolve_types(char *buf, char *raw, struct Line *line_info, int n,
       null_rx = false;
       STAILQ_FOREACH(color_line, head, entries)
       {
+        if (color_line->group)
+        {
+          short is_start_group = (!*color_stack || (*color_stack)->group != color_line->group);
+
+          regex_t *rx = is_start_group
+                        ? color_line->group->rx_start
+                        : color_line->group->rx_end;
+          if (rx && regexec (rx, buf + offset, 1, pmatch, (offset ? REG_NOTBOL : 0)) == 0)
+          {
+            struct ColorGroupStack *newStack;
+
+            if (is_start_group)
+            {
+              newStack = mutt_mem_calloc(1, sizeof(struct ColorGroupStack));
+              newStack->group = color_line->group;
+              newStack->next  = *color_stack;
+            }
+            else
+            {
+              newStack = (*color_stack)->next;
+              FREE(color_stack);
+            }
+
+            *color_stack = newStack;
+          }
+          else if (is_start_group)
+            continue;
+        }
         if (!color_line->stop_matching &&
             (regexec(&color_line->regex, buf + offset, 1, pmatch,
                      ((offset != 0) ? REG_NOTBOL : 0)) == 0))
@@ -1676,7 +1714,7 @@ static int format_line(struct Line **line_info, int n, unsigned char *buf,
  * @retval 0  normal exit, line was not displayed
  * @retval >0 normal exit, line was displayed
  */
-static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
+static int display_line(struct PagerRedrawData *rd, LOFF_T *last_pos, struct Line **line_info,
                         int n, int *last, int *max, PagerFlags flags,
                         struct QClass **quote_list, int *q_level, bool *force_redraw,
                         regex_t *search_re, struct MuttWindow *win_pager)
@@ -1720,7 +1758,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
   if (flags & MUTT_PAGER_LOGS)
   {
     /* determine the line class */
-    if (fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
+    if (fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
     {
       if (change_last)
         (*last)--;
@@ -1744,7 +1782,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
     if (curr_line->type == -1)
     {
       /* determine the line class */
-      if (fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
+      if (fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
       {
         if (change_last)
           (*last)--;
@@ -1752,7 +1790,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
       }
 
       resolve_types((char *) fmt, (char *) buf, *line_info, n, *last,
-                    quote_list, q_level, force_redraw, flags & MUTT_SHOWCOLOR);
+                    quote_list, q_level, force_redraw, flags & MUTT_SHOWCOLOR, rd);
 
       /* avoid race condition for continuation lines when scrolling up */
       for (m = n + 1; m < *last && (*line_info)[m].offset && (*line_info)[m].continuation; m++)
@@ -1775,7 +1813,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
   if ((flags & MUTT_SHOWCOLOR) && !curr_line->continuation &&
       (curr_line->type == MT_COLOR_QUOTED) && !curr_line->quote)
   {
-    if (fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
+    if (fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
     {
       if (change_last)
         (*last)--;
@@ -1796,7 +1834,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
 
   if ((flags & MUTT_SEARCH) && !curr_line->continuation && (curr_line->search_cnt == -1))
   {
-    if (fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
+    if (fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready) < 0)
     {
       if (change_last)
         (*last)--;
@@ -1842,7 +1880,7 @@ static int display_line(FILE *fp, LOFF_T *last_pos, struct Line **line_info,
     goto out; /* fake display */
   }
 
-  b_read = fill_buffer(fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready);
+  b_read = fill_buffer(rd->fp, last_pos, curr_line->offset, &buf, &fmt, &buflen, &buf_ready);
   if (b_read < 0)
   {
     if (change_last)
@@ -2090,7 +2128,7 @@ static void pager_custom_redraw(struct Menu *pager_menu)
     }
     int i = -1;
     int j = -1;
-    while (display_line(rd->fp, &rd->last_pos, &rd->line_info, ++i, &rd->last_line,
+    while (display_line(rd, &rd->last_pos, &rd->line_info, ++i, &rd->last_line,
                         &rd->max_line, rd->has_types | rd->search_flag | (rd->flags & MUTT_PAGER_NOWRAP),
                         &rd->quote_list, &rd->q_level, &rd->force_redraw,
                         &rd->search_re, rd->extra->win_pager) == 0)
@@ -2117,7 +2155,7 @@ static void pager_custom_redraw(struct Menu *pager_menu)
       while ((rd->lines < rd->extra->win_pager->state.rows) &&
              (rd->line_info[rd->curline].offset <= rd->sb.st_size - 1))
       {
-        if (display_line(rd->fp, &rd->last_pos, &rd->line_info, rd->curline,
+        if (display_line(rd, &rd->last_pos, &rd->line_info, rd->curline,
                          &rd->last_line, &rd->max_line,
                          (rd->flags & MUTT_DISPLAYFLAGS) | rd->hide_quoted |
                              rd->search_flag | (rd->flags & MUTT_PAGER_NOWRAP),
@@ -2760,7 +2798,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
           rd.search_compiled = true;
           /* update the search pointers */
           int line_num = 0;
-          while (display_line(rd.fp, &rd.last_pos, &rd.line_info, line_num,
+          while (display_line(&rd, &rd.last_pos, &rd.line_info, line_num,
                               &rd.last_line, &rd.max_line,
                               MUTT_SEARCH | (flags & MUTT_PAGER_NSKIP) | (flags & MUTT_PAGER_NOWRAP),
                               &rd.quote_list, &rd.q_level, &rd.force_redraw,
@@ -2878,7 +2916,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
         {
           while (((new_topline < rd.last_line) ||
                   (0 == (dretval = display_line(
-                             rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
+                             &rd, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
                              &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
                              &rd.quote_list, &rd.q_level, &rd.force_redraw,
                              &rd.search_re, rd.extra->win_pager)))) &&
@@ -2892,7 +2930,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
 
         while ((((new_topline + C_SkipQuotedOffset) < rd.last_line) ||
                 (0 == (dretval = display_line(
-                           rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
+                           &rd, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
                            &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
                            &rd.quote_list, &rd.q_level, &rd.force_redraw,
                            &rd.search_re, rd.extra->win_pager)))) &&
@@ -2909,7 +2947,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
 
         while ((((new_topline + C_SkipQuotedOffset) < rd.last_line) ||
                 (0 == (dretval = display_line(
-                           rd.fp, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
+                           &rd, &rd.last_pos, &rd.line_info, new_topline, &rd.last_line,
                            &rd.max_line, MUTT_TYPES | (flags & MUTT_PAGER_NOWRAP),
                            &rd.quote_list, &rd.q_level, &rd.force_redraw,
                            &rd.search_re, rd.extra->win_pager)))) &&
@@ -2931,7 +2969,7 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
         {
           int line_num = rd.curline;
           /* make sure the types are defined to the end of file */
-          while (display_line(rd.fp, &rd.last_pos, &rd.line_info, line_num, &rd.last_line,
+          while (display_line(&rd, &rd.last_pos, &rd.line_info, line_num, &rd.last_line,
                               &rd.max_line, rd.has_types | (flags & MUTT_PAGER_NOWRAP),
                               &rd.quote_list, &rd.q_level, &rd.force_redraw,
                               &rd.search_re, rd.extra->win_pager) == 0)
@@ -3617,5 +3655,8 @@ int mutt_pager(const char *banner, const char *fname, PagerFlags flags, struct P
   window_set_visible(rd.extra->win_pager->parent, false);
   mutt_window_reflow(dialog_find(rd.extra->win_pager));
 
+  mutt_free_color_group_stack(&rd.group_header_stack);
+  mutt_free_color_group_stack(&rd.group_body_stack);
+
   return (rc != -1) ? rc : 0;
 }
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin