+static int bool_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 = 1;
+ else if (ascii_strncasecmp (val, "no", 2) == 0)
+ flag = 0;
+
+ if (flag < 0)
+ return (0);
+ if (flag)
+ set_option (dst->data);
+ else
+ unset_option (dst->data);
+ return (1);
+}
+
+static void num_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ /* XXX puke */
+ const char* fmt = (m_strcmp(option->option, "umask") == 0) ?
+ "%s=%04o" : "%s=%d";
+ snprintf (dst, dstlen, fmt, option->option,
+ *((short*) option->data));
+}
+
+static int num_from_string (struct option_t* dst, const char* val,
+ char* errbuf, ssize_t errlen) {
+ int num = 0, old = 0;
+ char* t = NULL;
+
+ if (!dst)
+ return (0);
+
+ num = strtol (val, &t, 0);
+
+ if (m_strisempty(val) || *t || (short) num != num) {
+ if (errbuf) {
+ snprintf (errbuf, errlen, _("'%s' is invalid for $%s"),
+ val, dst->option);
+ }
+ return (0);
+ }
+
+ /* just temporarily accept new val so that check_special for
+ * $history already has it when doing history's init() */
+ old = *((short*) dst->data);
+ *((short*) dst->data) = (short) num;
+
+ if (!check_special (dst->option, (unsigned long) num, errbuf, errlen)) {
+ *((short*) dst->data) = old;
+ return (0);
+ }
+
+ return (1);
+}
+
+static void str_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ snprintf (dst, dstlen, "%s=\"%s\"", option->option,
+ NONULL (*((char**) option->data)));
+}
+
+static void user_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ snprintf (dst, dstlen, "%s=\"%s\"", option->option,
+ NONULL (((char*) option->data)));
+}
+
+static void sys_to_string (char* dst, ssize_t dstlen,
+ struct option_t* option) {
+ char *val = NULL, *t = NULL;
+ int clean = 0;
+
+ /* 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 (m_strisempty(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 (m_strisempty(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 || m_strisempty(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);
+
+}