+ /* get some $madmutt_ values dynamically */
+ if (m_strcmp("madmutt_pwd", option->option) == 0) {
+ val = p_new(char, _POSIX_PATH_MAX);
+ val = getcwd (val, _POSIX_PATH_MAX-1);
+ clean = 1;
+ } else if (m_strcmp("madmutt_folder_path", option->option) == 0 &&
+ CurrentFolder && *CurrentFolder) {
+ val = CurrentFolder;
+ } else if (m_strcmp("madmutt_folder_name", option->option) == 0 &&
+ CurrentFolder && *CurrentFolder) {
+
+ ssize_t Maildirlength = m_strlen(Maildir);
+
+ /*
+ * if name starts with $folder, just strip it to keep hierarchy
+ * $folder=imap://host, path=imap://host/inbox/b -> inbox/b
+ */
+ if (Maildirlength > 0 && m_strncmp(CurrentFolder, Maildir,
+ Maildirlength) == 0 &&
+ m_strlen(CurrentFolder) > Maildirlength) {
+ val = CurrentFolder + Maildirlength;
+ if (Maildir[Maildirlength]!='/')
+ val += 1;
+ /* if not $folder, just use everything after last / */
+ } else if ((t = strrchr (CurrentFolder, '/')) != NULL)
+ val = t+1;
+ /* default: use as-is */
+ else
+ val = (char *) CurrentFolder;
+
+ } else
+ val = (char *) option->init;
+
+ snprintf (dst, dstlen, "%s=\"%s\"", option->option, NONULL (val));
+ if (clean)
+ p_delete(&val);
+}
+
+static int path_from_string (struct option_t* dst, const char* val,
+ char* errbuf __attribute__ ((unused)), ssize_t errlen __attribute__ ((unused))) {
+ char path[_POSIX_PATH_MAX];
+
+ if (!dst)
+ return (0);
+
+ if (!val || !*val) {
+ p_delete((char**) dst->data);
+ return (1);
+ }
+
+ path[0] = '\0';
+ m_strcpy(path, sizeof(path), val);
+ mutt_expand_path (path, sizeof(path));
+ m_strreplace((char **) dst->data, path);
+ return (1);
+}
+
+static int str_from_string (struct option_t* dst, const char* val,
+ char* errbuf, ssize_t errlen) {
+ if (!dst)
+ return (0);
+
+ if (!check_special (dst->option, (unsigned long) val, errbuf, errlen))
+ return (0);
+
+ m_strreplace((char**) dst->data, val);
+ return (1);
+}
+
+static int user_from_string (struct option_t* dst, const char* val,
+ char* errbuf __attribute__ ((unused)), ssize_t errlen __attribute__ ((unused))) {
+ /* if dst == NULL, we may get here in case the user did unset it,
+ * see parse_set() where item is free()'d before coming here; so
+ * just silently ignore it */
+ if (!dst)
+ return (1);
+ if (m_strlen((char*) dst->data) == 0)
+ dst->data = (unsigned long) m_strdup(val);
+ else {
+ char* s = (char*) dst->data;
+ m_strreplace(&s, val);
+ }
+ if (m_strlen(dst->init) == 0)
+ dst->init = m_strdup((char*) dst->data);
+ return (1);
+}
+
+static void quad_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ const char *vals[] = { "no", "yes", "ask-no", "ask-yes" };
+ snprintf (dst, dstlen, "%s=%s", option->option,
+ vals[quadoption (option->data)]);
+}
+
+static int quad_from_string (struct option_t* dst, const char* val,
+ char* errbuf __attribute__ ((unused)), ssize_t errlen __attribute__ ((unused))) {
+ int flag = -1;
+
+ if (!dst)
+ return (0);
+ if (ascii_strncasecmp (val, "yes", 3) == 0)
+ flag = M_YES;
+ else if (ascii_strncasecmp (val, "no", 2) == 0)
+ flag = M_NO;
+ else if (ascii_strncasecmp (val, "ask-yes", 7) == 0)
+ flag = M_ASKYES;
+ else if (ascii_strncasecmp (val, "ask-no", 6) == 0)
+ flag = M_ASKNO;
+
+ if (flag < 0)
+ return (0);
+
+ set_quadoption (dst->data, flag);
+ return (1);
+}
+
+static void sort_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ const struct mapping_t *map = get_sortmap (option);
+ const char *p = NULL;
+
+ if (!map) {
+ snprintf (dst, sizeof(dst), "%s=unknown", option->option);
+ return;
+ }
+
+ p = mutt_getnamebyvalue(*((short *)option->data) & SORT_MASK, map);
+
+ snprintf (dst, dstlen, "%s=%s%s%s", option->option,
+ (*((short *) option->data) & SORT_REVERSE) ?
+ "reverse-" : "",
+ (*((short *) option->data) & SORT_LAST) ? "last-" :
+ "", NONULL (p));
+}
+
+static int sort_from_string (struct option_t* dst, const char* val,
+ char* errbuf, ssize_t errlen) {
+ const struct mapping_t *map = NULL;
+ if (!(map = get_sortmap (dst))) {
+ if (errbuf)
+ snprintf (errbuf, errlen, _("%s: Unknown type."),
+ dst->option);
+ return (0);
+ }
+ if (parse_sort (dst, val, map, errbuf, errlen) == -1)
+ return (0);
+ return (1);
+}
+
+static void rx_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ rx_t* p = (rx_t*) option->data;
+ snprintf (dst, dstlen, "%s=\"%s\"", option->option,
+ NONULL (p->pattern));
+}
+
+static int rx_from_string (struct option_t* dst, const char* val,
+ char* errbuf, ssize_t errlen) {
+ rx_t* p = NULL;
+ regex_t* rx = NULL;
+ int flags = 0, e = 0, not = 0;
+ char* s = NULL;
+
+ if (!dst)
+ return (0);
+
+ if (option (OPTATTACHMSG) && !m_strcmp(dst->option, "reply_regexp")) {
+ if (errbuf)
+ snprintf (errbuf, errlen,
+ "Operation not permitted when in attach-message mode.");
+ return (0);
+ }
+
+ if (!((rx_t*) dst->data))
+ *((rx_t**) dst->data) = p_new(rx_t, 1);
+
+ p = (rx_t*) dst->data;
+
+ /* something to do? */
+ if (!val || !*val || (p->pattern && m_strcmp(p->pattern, val) == 0))
+ return (1);
+
+ if (m_strcmp(dst->option, "mask") != 0)
+ flags |= mutt_which_case (val);
+
+ s = (char*) val;
+ if (m_strcmp(dst->option, "mask") == 0 && *s == '!') {
+ not = 1;
+ s++;
+ }
+
+ rx = p_new(regex_t, 1);
+
+ if ((e = REGCOMP (rx, s, flags)) != 0) {
+ regerror (e, rx, errbuf, errlen);
+ regfree (rx);
+ p_delete(&rx);
+ return (0);
+ }
+
+ if (p->rx) {
+ regfree (p->rx);
+ p_delete(&p->rx);
+ }
+
+ m_strreplace(&p->pattern, val);
+ p->rx = rx;
+ p->not = not;
+
+ if (m_strcmp(dst->option, "reply_regexp") == 0)
+ mutt_adjust_all_subjects ();
+
+ return (1);
+}
+
+static void magic_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ const char* s = NULL;
+ switch (option->data) {
+ case M_MBOX: s = "mbox"; break;
+ case M_MMDF: s = "MMDF"; break;
+ case M_MH: s = "MH"; break;
+ case M_MAILDIR: s = "Maildir"; break;
+ default: s = "unknown"; break;
+ }
+ snprintf (dst, dstlen, "%s=%s", option->option, s);
+}
+
+static int magic_from_string (struct option_t* dst, const char* val,
+ char* errbuf __attribute__ ((unused)), ssize_t errlen __attribute__ ((unused))) {
+ int flag = -1;
+
+ if (!dst || !val || !*val)
+ return (0);
+ if (ascii_strncasecmp (val, "mbox", 4) == 0)
+ flag = M_MBOX;
+ else if (ascii_strncasecmp (val, "mmdf", 4) == 0)
+ flag = M_MMDF;
+ else if (ascii_strncasecmp (val, "mh", 2) == 0)
+ flag = M_MH;
+ else if (ascii_strncasecmp (val, "maildir", 7) == 0)
+ flag = M_MAILDIR;
+
+ if (flag < 0)
+ return (0);
+
+ *((short*) dst->data) = flag;
+ return (1);
+
+}
+
+static void addr_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ char s[HUGE_STRING];
+ s[0] = '\0';
+ rfc822_write_address (s, sizeof(s), *((address_t**) option->data), 0);
+ snprintf (dst, dstlen, "%s=\"%s\"", option->option, NONULL (s));
+}
+
+static int addr_from_string (struct option_t* dst, const char* val,
+ char* errbuf __attribute__ ((unused)), ssize_t errlen __attribute__ ((unused))) {
+ if (!dst)
+ return (0);
+ address_list_wipe((address_t**) dst->data);
+ if (val && *val)
+ *((address_t**) dst->data) = rfc822_parse_adrlist (NULL, val);
+ return (1);
+}
+
+int mutt_option_value (const char* val, char* dst, ssize_t dstlen) {
+ struct option_t* option = NULL;
+ char* tmp = NULL, *t = NULL;
+ ssize_t l = 0;
+
+ if (!(option = hash_find (ConfigOptions, val))) {
+ *dst = '\0';
+ return (0);
+ }
+ tmp = p_new(char, dstlen+1);
+ FuncTable[DTYPE (option->type)].opt_to_string (tmp, dstlen, option);
+
+ /* as we get things of type $var=value and don't want to bloat the
+ * above "just" for expansion, we do the stripping here */
+ t = strchr (tmp, '=');
+ t++;
+ l = m_strlen(t);
+ if (l >= 2) {
+ if (t[l-1] == '"' && *t == '"') {
+ t[l-1] = '\0';
+ t++;
+ }
+ }
+ memcpy (dst, t, l+1);
+ p_delete(&tmp);
+
+ return (1);
+}
+
+static void toggle_quadoption (int opt)