NeoMutt  2021-10-29-220-g2b1eec
Teaching an old dog new tricks
DOXYGEN
regex.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <stddef.h>
32 #include <stdbool.h>
33 #include <stdint.h>
34 #include "mutt/lib.h"
35 #include "config/lib.h"
36 #include "email/lib.h"
37 #include "core/lib.h"
38 #include "gui/lib.h"
39 #include "index/lib.h"
40 #include "pattern/lib.h"
41 #include "color.h"
42 #include "context.h"
43 #include "mutt_globals.h"
44 #include "regex4.h"
45 
46 // clang-format off
47 struct RegexColorList AttachList;
48 struct RegexColorList BodyList;
49 struct RegexColorList HeaderList;
50 struct RegexColorList IndexAuthorList;
51 struct RegexColorList IndexFlagsList;
52 struct RegexColorList IndexList;
53 struct RegexColorList IndexSubjectList;
54 struct RegexColorList IndexTagList;
55 struct RegexColorList StatusList;
56 // clang-format on
57 
63 void regex_color_free(struct RegexColor **ptr, bool free_colors)
64 {
65  if (!ptr || !*ptr)
66  return;
67 
68  struct RegexColor *cl = *ptr;
69 
70  if (free_colors && (cl->fg != COLOR_UNSET) && (cl->bg != COLOR_UNSET))
71  mutt_color_free(cl->fg, cl->bg);
72 
73  regfree(&cl->regex);
75  FREE(&cl->pattern);
76  FREE(ptr);
77 }
78 
83 void regex_color_list_clear(struct RegexColorList *rcl)
84 {
85  struct RegexColor *np = NULL, *tmp = NULL;
86  STAILQ_FOREACH_SAFE(np, rcl, entries, tmp)
87  {
88  STAILQ_REMOVE(rcl, np, RegexColor, entries);
89  regex_color_free(&np, true);
90  }
91 }
92 
97 {
107 }
108 
113 {
123 }
124 
130 struct RegexColorList *regex_colors_get_list(enum ColorId cid)
131 {
132  switch (cid)
133  {
135  return &AttachList;
136  case MT_COLOR_BODY:
137  return &BodyList;
138  case MT_COLOR_HEADER:
139  return &HeaderList;
140  case MT_COLOR_INDEX:
141  return &IndexList;
143  return &IndexAuthorList;
145  return &IndexFlagsList;
147  return &IndexSubjectList;
148  case MT_COLOR_INDEX_TAG:
149  return &IndexTagList;
150  case MT_COLOR_STATUS:
151  return &StatusList;
152  default:
153  return NULL;
154  }
155 }
156 
162 {
163  struct RegexColor *cl = mutt_mem_calloc(1, sizeof(struct RegexColor));
164 
165  cl->fg = COLOR_UNSET;
166  cl->bg = COLOR_UNSET;
167 
168  return cl;
169 }
170 
187 enum CommandResult add_pattern(struct RegexColorList *rcl, const char *s,
188  bool sensitive, uint32_t fg, uint32_t bg, int attr,
189  struct Buffer *err, bool is_index, int match)
190 {
191  struct RegexColor *rcol = NULL;
192 
193  STAILQ_FOREACH(rcol, rcl, entries)
194  {
195  if ((sensitive && mutt_str_equal(s, rcol->pattern)) ||
196  (!sensitive && mutt_istr_equal(s, rcol->pattern)))
197  {
198  break;
199  }
200  }
201 
202  if (rcol)
203  {
204  if ((fg != COLOR_UNSET) && (bg != COLOR_UNSET))
205  {
206  if ((rcol->fg != fg) || (rcol->bg != bg))
207  {
208  mutt_color_free(rcol->fg, rcol->bg);
209  rcol->fg = fg;
210  rcol->bg = bg;
211  attr |= mutt_color_alloc(fg, bg);
212  }
213  else
214  attr |= (rcol->pair & ~A_BOLD);
215  }
216  rcol->pair = attr;
217  }
218  else
219  {
220  rcol = regex_color_new();
221  if (is_index)
222  {
223  struct Buffer *buf = mutt_buffer_pool_get();
224  mutt_buffer_strcpy(buf, s);
225  const char *const c_simple_search =
226  cs_subset_string(NeoMutt->sub, "simple_search");
227  mutt_check_simple(buf, NONULL(c_simple_search));
228  struct Mailbox *m_cur = get_current_mailbox();
229  struct Menu *menu = get_current_menu();
230  rcol->color_pattern =
231  mutt_pattern_comp(m_cur, menu, buf->data, MUTT_PC_FULL_MSG, err);
233  if (!rcol->color_pattern)
234  {
235  regex_color_free(&rcol, true);
236  return MUTT_CMD_ERROR;
237  }
238  }
239  else
240  {
241  uint16_t flags = 0;
242  if (sensitive)
243  flags = mutt_mb_is_lower(s) ? REG_ICASE : 0;
244  else
245  flags = REG_ICASE;
246 
247  const int r = REG_COMP(&rcol->regex, s, flags);
248  if (r != 0)
249  {
250  regerror(r, &rcol->regex, err->data, err->dsize);
251  regex_color_free(&rcol, true);
252  return MUTT_CMD_ERROR;
253  }
254  }
255  rcol->pattern = mutt_str_dup(s);
256  rcol->match = match;
257  if ((fg != COLOR_UNSET) && (bg != COLOR_UNSET))
258  {
259  rcol->fg = fg;
260  rcol->bg = bg;
261  attr |= mutt_color_alloc(fg, bg);
262  }
263  rcol->pair = attr;
264  STAILQ_INSERT_HEAD(rcl, rcol, entries);
265  }
266 
267  if (is_index)
268  {
269  /* force re-caching of index colors */
270  struct EventColor ev_c = { MT_COLOR_INDEX };
272  }
273 
274  return MUTT_CMD_SUCCESS;
275 }
276 
290 bool regex_colors_parse_color_list(enum ColorId cid, const char *pat, uint32_t fg,
291  uint32_t bg, int attrs, int *rc, struct Buffer *err)
292 
293 {
294  switch (cid)
295  {
297  *rc = add_pattern(&AttachList, pat, true, fg, bg, attrs, err, false, 0);
298  break;
299  case MT_COLOR_BODY:
300  *rc = add_pattern(&BodyList, pat, true, fg, bg, attrs, err, false, 0);
301  break;
302  case MT_COLOR_HEADER:
303  *rc = add_pattern(&HeaderList, pat, false, fg, bg, attrs, err, false, 0);
304  break;
305  case MT_COLOR_INDEX:
306  *rc = add_pattern(&IndexList, pat, true, fg, bg, attrs, err, true, 0);
307  break;
309  *rc = add_pattern(&IndexAuthorList, pat, true, fg, bg, attrs, err, true, 0);
310  break;
312  *rc = add_pattern(&IndexFlagsList, pat, true, fg, bg, attrs, err, true, 0);
313  break;
315  *rc = add_pattern(&IndexSubjectList, pat, true, fg, bg, attrs, err, true, 0);
316  break;
317  case MT_COLOR_INDEX_TAG:
318  *rc = add_pattern(&IndexTagList, pat, true, fg, bg, attrs, err, true, 0);
319  break;
320  default:
321  return false;
322  }
323 
324  return true;
325 }
326 
338 int regex_colors_parse_status_list(enum ColorId cid, const char *pat, uint32_t fg,
339  uint32_t bg, int attrs, int match, struct Buffer *err)
340 {
341  if (cid != MT_COLOR_STATUS)
342  return -1;
343 
344  int rc = add_pattern(&StatusList, pat, true, fg, bg, attrs, err, false, match);
345  return rc;
346 }
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
struct Notify * ColorsNotify
Notifications: ColorId, EventColor.
Definition: notify.c:33
struct RegexColorList IndexFlagsList
List of colours applied to the flags in the index.
Definition: regex.c:51
struct RegexColorList IndexAuthorList
List of colours applied to the author in the index.
Definition: regex.c:50
struct RegexColorList IndexSubjectList
List of colours applied to the subject in the index.
Definition: regex.c:53
void regex_colors_clear(void)
Clear the Regex colours.
Definition: regex.c:112
struct RegexColorList StatusList
List of colours applied to the status bar.
Definition: regex.c:55
void regex_colors_init(void)
Initialise the Regex colours.
Definition: regex.c:96
struct RegexColorList IndexList
List of default colours applied to the index.
Definition: regex.c:52
struct RegexColorList IndexTagList
List of colours applied to tags in the index.
Definition: regex.c:54
struct RegexColorList BodyList
List of colours applied to the email body.
Definition: regex.c:48
enum CommandResult add_pattern(struct RegexColorList *rcl, const char *s, bool sensitive, uint32_t fg, uint32_t bg, int attr, struct Buffer *err, bool is_index, int match)
Associate a colour to a pattern.
Definition: regex.c:187
struct RegexColorList * regex_colors_get_list(enum ColorId cid)
Return the RegexColorList for a colour id.
Definition: regex.c:130
struct RegexColor * regex_color_new(void)
Create a new RegexColor.
Definition: regex.c:161
struct RegexColorList HeaderList
List of colours applied to the email headers.
Definition: regex.c:49
bool regex_colors_parse_color_list(enum ColorId cid, const char *pat, uint32_t fg, uint32_t bg, int attrs, int *rc, struct Buffer *err)
Parse a Regex 'color' command.
Definition: regex.c:290
struct RegexColorList AttachList
List of colours applied to the attachment headers.
Definition: regex.c:47
void regex_color_free(struct RegexColor **ptr, bool free_colors)
Free a RegexColor.
Definition: regex.c:63
int regex_colors_parse_status_list(enum ColorId cid, const char *pat, uint32_t fg, uint32_t bg, int attrs, int match, struct Buffer *err)
Parse a Regex 'color status' command.
Definition: regex.c:338
void regex_color_list_clear(struct RegexColorList *rcl)
Clear a list of colours.
Definition: regex.c:83
void mutt_color_free(uint32_t fg, uint32_t bg)
Free a colour.
Definition: color.c:109
int mutt_color_alloc(uint32_t fg, uint32_t bg)
Allocate a colour pair.
Definition: color.c:188
Color and attribute parsing.
#define COLOR_UNSET
Definition: color.h:104
ColorId
List of all colored objects.
Definition: color.h:35
@ MT_COLOR_INDEX_AUTHOR
Index: author field (takes a pattern)
Definition: color.h:77
@ MT_COLOR_HEADER
Message headers (takes a pattern)
Definition: color.h:48
@ MT_COLOR_STATUS
Status bar (takes a pattern)
Definition: color.h:70
@ MT_COLOR_INDEX_SUBJECT
Index: subject field (takes a pattern)
Definition: color.h:79
@ MT_COLOR_BODY
Pager: highlight body of message (takes a pattern)
Definition: color.h:39
@ MT_COLOR_INDEX_TAG
Index: tag field (g, takes a pattern)
Definition: color.h:80
@ MT_COLOR_ATTACH_HEADERS
MIME attachment test (takes a pattern)
Definition: color.h:38
@ MT_COLOR_INDEX
Index: default colour (takes a pattern)
Definition: color.h:76
@ MT_COLOR_INDEX_FLAGS
Index: flags field (takes a pattern)
Definition: color.h:78
CommandResult
Error codes for command_t parse functions.
Definition: command.h:34
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:37
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:35
struct PatternList * mutt_pattern_comp(struct Mailbox *m, struct Menu *menu, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1092
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1038
Convenience wrapper for the config headers.
The "currently-open" mailbox.
Convenience wrapper for the core headers.
Structs that make up an email.
Convenience wrapper for the gui headers.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
GUI manage the main index (list of emails)
struct Menu * get_current_menu(void)
Get the current Menu.
Definition: index.c:500
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition: index.c:474
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:355
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:40
Convenience wrapper for the library headers.
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:727
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:181
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:715
Hundreds of global variables to back the user variables.
@ NT_COLOR_SET
Color has been set.
Definition: notify2.h:41
@ NT_COLOR
Colour has changed, NotifyColor, EventColor.
Definition: notify_type.h:39
Match patterns to emails.
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:61
void mutt_check_simple(struct Buffer *s, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:116
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_INIT(head)
Definition: queue.h:372
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:383
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:54
Regex Colour.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
An Event that happened to a Colour.
Definition: notify2.h:53
enum ColorId cid
Colour ID that has changed.
Definition: notify2.h:54
A mailbox.
Definition: mailbox.h:82
Definition: lib.h:69
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A regular expression and a color to highlight a line.
Definition: regex4.h:36
regex_t regex
Compiled regex.
Definition: regex4.h:38
struct PatternList * color_pattern
Compiled pattern to speed up index color calculation.
Definition: regex4.h:40
int pair
Colour pair index.
Definition: regex4.h:43
char * pattern
Pattern to match.
Definition: regex4.h:37
uint32_t bg
Background colour.
Definition: regex4.h:42
int match
Substring to match, 0 for old behaviour.
Definition: regex4.h:39
uint32_t fg
Foreground colour.
Definition: regex4.h:41