Change the backing variables for config from objects to pointers.
continue;
if (prefix && *prefix && (strncmp(prefix, nntp_data->group, strlen(prefix)) != 0))
continue;
- if (!((regexec(Mask.regex, nntp_data->group, 0, NULL, 0) == 0) ^ Mask.not))
+ if (Mask && !((regexec(Mask->regex, nntp_data->group, 0, NULL, 0) == 0) ^ Mask->not))
continue;
add_folder(menu, state, nntp_data->group, NULL, NULL, NULL, nntp_data);
}
{
continue;
}
- if (!((regexec(Mask.regex, de->d_name, 0, NULL, 0) == 0) ^ Mask.not))
+ if (Mask && !((regexec(Mask->regex, de->d_name, 0, NULL, 0) == 0) ^ Mask->not))
continue;
mutt_file_concat_path(buffer, d, de->d_name, sizeof(buffer));
mutt_str_strfcpy(path, LastDir, sizeof(path));
mutt_pretty_mailbox(path, sizeof(path));
snprintf(title, titlelen, _("Directory [%s], File mask: %s"), path,
- NONULL(Mask.pattern));
+ NONULL(Mask ? Mask->pattern : NULL));
}
}
case OP_ENTER_MASK:
- mutt_str_strfcpy(buf, NONULL(Mask.pattern), sizeof(buf));
+ mutt_str_strfcpy(buf, NONULL(Mask ? Mask->pattern : NULL), sizeof(buf));
if (mutt_get_field(_("File Mask: "), buf, sizeof(buf), 0) == 0)
{
regex_t *rx = mutt_mem_malloc(sizeof(regex_t));
}
else
{
- mutt_str_replace(&Mask.pattern, buf);
- regfree(Mask.regex);
- FREE(&Mask.regex);
- Mask.regex = rx;
- Mask.not = not;
+ if (Mask)
+ {
+ regfree(Mask->regex);
+ FREE(&Mask->regex);
+ }
+ else
+ {
+ Mask = mutt_mem_calloc(1, sizeof(struct Regex *));
+ }
+ mutt_str_replace(&Mask->pattern, buf); //QWQ
+ Mask->regex = rx;
+ Mask->not = not;
destroy_state(&state);
#ifdef USE_IMAP
WHERE char *AttributionLocale;
WHERE char *AttachCharset;
WHERE char *AttachFormat;
-WHERE struct Regex AttachKeyword;
+WHERE struct Regex *AttachKeyword;
WHERE char *ComposeFormat;
WHERE char *ConfigCharset;
WHERE char *ContentType;
WHERE struct ListHead UserHeader INITVAL(STAILQ_HEAD_INITIALIZER(UserHeader));
/* -- formerly in pgp.h -- */
-WHERE struct Regex PgpGoodSign;
-WHERE struct Regex PgpDecryptionOkay;
+WHERE struct Regex *PgpGoodSign;
+WHERE struct Regex *PgpDecryptionOkay;
WHERE char *PgpSignAs;
WHERE short PgpTimeout;
WHERE char *PgpEntryFormat;
WHERE char *NmQueryWindowCurrentSearch;
#endif
-WHERE struct Regex Mask;
-WHERE struct Regex QuoteRegexp;
-WHERE struct Regex ReplyRegexp;
-WHERE struct Regex Smileys;
-WHERE struct Regex GecosMask;
+/* These variables are backing for config items */
+WHERE struct Regex *GecosMask;
+WHERE struct Regex *Mask;
+WHERE struct Regex *QuoteRegexp;
+WHERE struct Regex *ReplyRegexp;
+WHERE struct Regex *Smileys;
#ifdef MAIN_C
const char *const BodyTypes[] = {
/* apply filemask filter. This should really be done at menu setup rather
* than at scan, since it's so expensive to scan. But that's big changes
* to browser.c */
- if (!((regexec(Mask.regex, relpath, 0, NULL, 0) == 0) ^ Mask.not))
+ if (Mask && !((regexec(Mask->regex, relpath, 0, NULL, 0) == 0) ^ Mask->not))
{
FREE(&mx.mbox);
return;
int e, flags = 0;
const char *p = NULL;
regex_t *rx = NULL;
- struct Regex *ptr = (struct Regex *) MuttVars[idx].data;
+ struct Regex *ptr = *(struct Regex **) MuttVars[idx].data;
- if (!ptr->pattern || (mutt_str_strcmp(ptr->pattern, tmp->data) != 0))
+ if (ptr)
{
- bool not = false;
-
- /* $mask is case-sensitive */
- if ((mutt_str_strcmp(MuttVars[idx].option, "mask") != 0) && mutt_mb_is_lower(tmp->data))
- flags |= REG_ICASE;
+ /* Same pattern as we already have */
+ if (mutt_str_strcmp(ptr->pattern, tmp->data) != 0)
+ return 0;
+ }
+ else
+ {
+ ptr = mutt_mem_calloc(1, sizeof(struct Regex *));
+ }
- p = tmp->data;
- if (mutt_str_strcmp(MuttVars[idx].option, "mask") == 0)
- {
- if (*p == '!')
- {
- not = true;
- p++;
- }
- }
+ bool not = false;
- rx = mutt_mem_malloc(sizeof(regex_t));
- e = REGCOMP(rx, p, flags);
- if (e != 0)
- {
- regerror(e, rx, err->data, err->dsize);
- FREE(&rx);
- return 0;
- }
+ /* Should we use smart case matching? */
+ if (((MuttVars[idx].flags & DT_REGEX_MATCH_CASE) == 0) && mutt_mb_is_lower(tmp->data))
+ flags |= REG_ICASE;
- /* get here only if everything went smoothly */
- if (ptr->pattern)
+ p = tmp->data;
+ /* Is a prefix of '!' allowed? */
+ if ((MuttVars[idx].flags & DT_REGEX_ALLOW_NOT) != 0)
+ {
+ if (*p == '!')
{
- FREE(&ptr->pattern);
- regfree((regex_t *) ptr->regex);
- FREE(&ptr->regex);
+ not = true;
+ p++;
}
+ }
- ptr->pattern = mutt_str_strdup(tmp->data);
- ptr->regex = rx;
- ptr->not = not;
+ rx = mutt_mem_malloc(sizeof(regex_t));
+ e = REGCOMP(rx, p, flags);
+ if (e != 0)
+ {
+ regerror(e, rx, err->data, err->dsize);
+ FREE(&rx);
+ return 0;
+ }
- return 1;
+ /* get here only if everything went smoothly */
+ if (ptr->pattern)
+ {
+ FREE(&ptr->pattern);
+ regfree((regex_t *) ptr->regex);
+ FREE(&ptr->regex);
}
- return 0;
+
+ ptr->pattern = mutt_str_strdup(tmp->data);
+ ptr->regex = rx;
+ ptr->not = not;
+
+ return 1;
}
void set_quadoption(int opt, int flag)
struct Envelope *e = Context->hdrs[i]->env;
if (e && e->subject)
{
- e->real_subj = (regexec(ReplyRegexp.regex, e->subject, 1, pmatch, 0)) ?
- e->subject :
- e->subject + pmatch[0].rm_eo;
+ e->real_subj =
+ (ReplyRegexp &&
+ (regexec(ReplyRegexp->regex, e->subject, 1, pmatch, 0))) ?
+ e->subject :
+ e->subject + pmatch[0].rm_eo;
}
}
}
static void free_opt(struct Option *p)
{
- struct Regex *pp = NULL;
+ struct Regex **pp = NULL;
switch (DTYPE(p->type))
{
mutt_addr_free((struct Address **) p->data);
break;
case DT_REGEX:
- pp = (struct Regex *) p->data;
- FREE(&pp->pattern);
- if (pp->regex)
+ pp = (struct Regex **) p->data;
+ FREE(&(*pp)->pattern);
+ if ((*pp)->regex)
{
- regfree(pp->regex);
- FREE(&pp->regex);
+ regfree((*pp)->regex);
+ FREE(&(*pp)->regex);
}
break;
case DT_PATH:
break;
case DT_REGEX:
{
- struct Regex *pp = (struct Regex *) p->data;
- int flags = 0;
-
- FREE(&pp->pattern);
- if (pp->regex)
+ struct Regex **pp = (struct Regex **) p->data;
+ if (*pp)
+ {
+ FREE(&(*pp)->pattern);
+ if ((*pp)->regex)
+ {
+ regfree((*pp)->regex);
+ FREE(&(*pp)->regex);
+ }
+ }
+ else
{
- regfree(pp->regex);
- FREE(&pp->regex);
+ *pp = mutt_mem_calloc(1, sizeof(struct Regex));
}
if (p->init)
{
- int retval;
+ int flags = 0;
char *s = (char *) p->init;
- pp->regex = mutt_mem_calloc(1, sizeof(regex_t));
- pp->pattern = mutt_str_strdup((char *) p->init);
+ (*pp)->regex = mutt_mem_calloc(1, sizeof(regex_t));
+ (*pp)->pattern = mutt_str_strdup((char *) p->init);
if ((mutt_str_strcmp(p->option, "mask") != 0) &&
(mutt_mb_is_lower((const char *) p->init)))
{
if ((mutt_str_strcmp(p->option, "mask") == 0) && *s == '!')
{
s++;
- pp->not = true;
+ (*pp)->not = true;
}
- retval = REGCOMP(pp->regex, s, flags);
- if (retval != 0)
+ int rc = REGCOMP((*pp)->regex, s, flags);
+ if (rc != 0)
{
char msgbuf[STRING];
- regerror(retval, pp->regex, msgbuf, sizeof(msgbuf));
+ regerror(rc, (*pp)->regex, msgbuf, sizeof(msgbuf));
fprintf(stderr, _("restore_default(%s): error in regex: %s\n"),
- p->option, pp->pattern);
+ p->option, (*pp)->pattern);
fprintf(stderr, "%s\n", msgbuf);
mutt_sleep(0);
- FREE(&pp->pattern);
- FREE(&pp->regex);
+ FREE(&(*pp)->pattern);
+ FREE(&(*pp)->regex);
}
}
}
if (query || *s->dptr != '=')
{
/* user requested the value of this variable */
- struct Regex *ptr = (struct Regex *) MuttVars[idx].data;
- pretty_var(err->data, err->dsize, MuttVars[idx].option, NONULL(ptr->pattern));
+ struct Regex *ptr = *(struct Regex **) MuttVars[idx].data;
+ const char *value = ptr ? ptr->pattern : NULL;
+ pretty_var(err->data, err->dsize, MuttVars[idx].option, NONULL(value));
break;
}
struct Envelope *e = Context->hdrs[i]->env;
if (e && e->subject)
{
- e->real_subj = (regexec(ReplyRegexp.regex, e->subject, 1, pmatch, 0)) ?
+ e->real_subj = (ReplyRegexp &&
+ (regexec(ReplyRegexp->regex, e->subject, 1, pmatch, 0))) ?
e->subject :
e->subject + pmatch[0].rm_eo;
}
return r;
}
-/* FILO designed to contain the list of config files that have been sourced and
+/* LIFO designed to contain the list of config files that have been sourced and
* avoid cyclic sourcing */
static struct ListHead MuttrcStack = STAILQ_HEAD_INITIALIZER(MuttrcStack);
#define DT_SORT_AUX 0x80
#define DT_SORT_SIDEBAR 0x100
+/* ... DT_REGEX */
+#define DT_REGEX_MATCH_CASE 0x010 /**< Case-sensitive matching */
+#define DT_REGEX_ALLOW_NOT 0x020 /**< Regex can begin with '!' */
+
/**
* struct Option - Definition of a user-variable
*/
memset(dest, 0, destlen);
- if (GecosMask.regex)
+ if (GecosMask)
{
- if (regexec(GecosMask.regex, pw->pw_gecos, 1, pat_match, 0) == 0)
+ if (regexec(GecosMask->regex, pw->pw_gecos, 1, pat_match, 0) == 0)
mutt_str_strfcpy(dest, pw->pw_gecos + pat_match[0].rm_so,
MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
}
{
int rc = -1;
- if (PgpGoodSign.pattern)
+ if (PgpGoodSign)
{
char *line = NULL;
int lineno = 0;
while ((line = mutt_file_read_line(line, &linelen, fpin, &lineno, 0)) != NULL)
{
- if (regexec(PgpGoodSign.regex, line, 0, NULL, 0) == 0)
+ if (regexec(PgpGoodSign->regex, line, 0, NULL, 0) == 0)
{
mutt_debug(2, "\"%s\" matches regex.\n", line);
rc = 0;
{
int rc = -1;
- if (PgpDecryptionOkay.pattern)
+ if (PgpDecryptionOkay)
{
char *line = NULL;
int lineno = 0;
while ((line = mutt_file_read_line(line, &linelen, fpin, &lineno, 0)) != NULL)
{
- if (regexec(PgpDecryptionOkay.regex, line, 0, NULL, 0) == 0)
+ if (regexec(PgpDecryptionOkay->regex, line, 0, NULL, 0) == 0)
{
mutt_debug(2, "\"%s\" matches regex.\n", line);
rc = 0;
}
else if (check_sig(buf, line_info, n - 1) == 0)
line_info[n].type = MT_COLOR_SIGNATURE;
- else if (regexec(QuoteRegexp.regex, buf, 1, pmatch, 0) == 0)
+ else if (QuoteRegexp && regexec(QuoteRegexp->regex, buf, 1, pmatch, 0) == 0)
{
- if ((regexec(Smileys.regex, buf, 1, smatch, 0) == 0))
+ if (Smileys && (regexec(Smileys->regex, buf, 1, smatch, 0) == 0))
{
if (smatch[0].rm_so > 0)
{
c = buf[smatch[0].rm_so];
buf[smatch[0].rm_so] = 0;
- if (regexec(QuoteRegexp.regex, buf, 1, pmatch, 0) == 0)
+ if (QuoteRegexp && regexec(QuoteRegexp->regex, buf, 1, pmatch, 0) == 0)
{
if (q_classify && line_info[n].quote == NULL)
line_info[n].quote = classify_quote(quote_list, buf + pmatch[0].rm_so,
(*last)--;
goto out;
}
- if (regexec(QuoteRegexp.regex, (char *) fmt, 1, pmatch, 0) != 0)
+ if (QuoteRegexp && regexec(QuoteRegexp->regex, (char *) fmt, 1, pmatch, 0) != 0)
goto out;
(*line_info)[n].quote =
classify_quote(quote_list, (char *) fmt + pmatch[0].rm_so,
rfc2047_decode(&e->subject);
- if (regexec(ReplyRegexp.regex, e->subject, 1, pmatch, 0) == 0)
+ if (ReplyRegexp && (regexec(ReplyRegexp->regex, e->subject, 1, pmatch, 0) == 0))
e->real_subj = e->subject + pmatch[0].rm_eo;
else
e->real_subj = e->subject;
static int search_attach_keyword(char *filename)
{
/* Search for the regex in AttachKeyword within a file */
- if (!AttachKeyword.regex)
+ if (!AttachKeyword || !QuoteRegexp)
return 0;
FILE *attf = mutt_file_fopen(filename, "r");
while (!feof(attf))
{
fgets(inputline, LONG_STRING, attf);
- if (regexec(QuoteRegexp.regex, inputline, 0, NULL, 0) != 0 &&
- regexec(AttachKeyword.regex, inputline, 0, NULL, 0) == 0)
+ if (regexec(QuoteRegexp->regex, inputline, 0, NULL, 0) != 0 &&
+ regexec(AttachKeyword->regex, inputline, 0, NULL, 0) == 0)
{
found = 1;
break;