/*
 * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
 * 
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */ 

#include "sort.h"
#include "buffy.h"

enum
{
  DT_BOOL, /* boolean option */
  DT_NUM,  /* a number */
  DT_STR,  /* a string */
  DT_PATH, /* a pathname */
  DT_QUAD, /* quad-option (yes/no/ask-yes/ask-no) */
  DT_SORT, /* sorting methods */
  DT_RX,   /* regular expressions */
  DT_MAGIC /* mailbox type */
};

/* flags to parse_set() */
#define M_SET_INV	1	/* default is to invert all vars */
#define M_SET_UNSET	2	/* default is to unset all vars */

/* forced redraw types */
#define R_NONE			0
#define R_INDEX			(1<<0)
#define R_PAGER			(1<<1)
#define R_BOTH			(R_INDEX | R_PAGER)

struct option_t
{
  char *option;
  short type;
  short redraw;
  void *data;
  size_t size; /* DT_STR and DT_PATH */
};

#define S_DECL(x) x,sizeof(x)

struct option_t MuttVars[] = {
  { "abort_nosubject",	DT_QUAD, R_NONE, (void *) OPT_SUBJECT,	0 },
  { "abort_unmodified",	DT_QUAD, R_NONE, (void *) OPT_ABORT,	0 },
  { "alias_file",	DT_PATH, R_NONE, S_DECL(AliasFile) },
  { "allow_8bit",	DT_BOOL, R_NONE, (void *) OPTALLOW8BIT,	0 },
  { "alternates",	DT_RX,	 R_BOTH, &Alternates },
  { "arrow_cursor",	DT_BOOL, R_BOTH, (void *) OPTARROWCURSOR, 0 },
  { "ascii_chars",	DT_BOOL, R_BOTH, (void *) OPTASCIICHARS, 0 },
  { "askbcc",		DT_BOOL, R_NONE, (void *) OPTASKBCC,	0 },
  { "askcc",		DT_BOOL, R_NONE, (void *) OPTASKCC,	0 },
  { "attach_split",	DT_BOOL, R_NONE, (void *) OPTATTACHSPLIT,0 },
  { "attach_sep",	DT_STR,	 R_NONE, S_DECL(AttachSep) },
  { "attribution",	DT_STR,	 R_NONE, S_DECL(Attribution) },
  { "autoedit",		DT_BOOL, R_NONE, (void *) OPTAUTOEDIT,	0 },
  { "auto_tag",		DT_BOOL, R_NONE, (void *) OPTAUTOTAG,	0 },
  { "beep",		DT_BOOL, R_NONE, (void *) OPTBEEP,	0 },
  { "charset",		DT_STR,	 R_NONE, S_DECL(Charset) },
  { "check_new",	DT_BOOL, R_NONE, (void *) OPTCHECKNEW,	0 },
  { "confirmappend",	DT_BOOL, R_NONE, (void *) OPTCONFIRMAPPEND, 0 },
  { "confirmcreate",	DT_BOOL, R_NONE, (void *) OPTCONFIRMCREATE, 0 },
  { "copy",		DT_QUAD, R_NONE, (void *) OPT_COPY,	0 },
  { "date_format",	DT_STR,	 R_BOTH, S_DECL(DateFmt) },
  { "decode_format",	DT_STR,	 R_NONE, S_DECL(DecodeFmt) },
  { "delete",		DT_QUAD, R_NONE, (void *) OPT_DELETE,	0 },
  { "dsn_notify",	DT_STR,	 R_NONE, S_DECL (DsnNotify) },
  { "dsn_return",	DT_STR,	 R_NONE, S_DECL (DsnReturn) },
  { "edit_hdrs",	DT_BOOL, R_NONE, (void *) OPTEDITHDRS,	0 },
  { "editor",		DT_PATH, R_NONE, S_DECL(Editor) },
  { "escape",		DT_STR,	 R_NONE, S_DECL(EscChar) },
  { "fast_reply",	DT_BOOL, R_NONE, (void *) OPTFASTREPLY,	0 },
  { "fcc_attach",	DT_BOOL, R_NONE, (void *) OPTFCCATTACH,	0 },
  { "folder",		DT_PATH, R_NONE, S_DECL(Maildir) },
  { "force_name",	DT_BOOL, R_NONE, (void *) OPTFORCENAME,	0 },
  { "forw_decode",	DT_BOOL, R_NONE, (void *) OPTFORWDECODE },
  { "forw_format",	DT_STR,	 R_NONE, S_DECL(ForwFmt) },
  { "forw_quote",	DT_BOOL, R_NONE, (void *) OPTFORWQUOTE },
  { "hdr_format",	DT_STR,	 R_BOTH, S_DECL(HdrFmt) },
  { "hdrs",		DT_BOOL, R_NONE, (void *) OPTHDRS,	0 },
  { "header",		DT_BOOL, R_NONE, (void *) OPTHEADER,	0 },
  { "help",		DT_BOOL, R_BOTH, (void *) OPTHELP,	0 },
  { "history",		DT_NUM,	 R_NONE, &HistSize },
  { "hostname",		DT_STR,	 R_NONE, S_DECL(Fqdn) },
  { "in_reply_to",	DT_STR,	 R_NONE, S_DECL(InReplyTo) },
  { "include",		DT_QUAD, R_NONE, (void *) OPT_INCLUDE,	0 },
  { "indent_str",	DT_STR,	 R_NONE, S_DECL(Prefix) },
  { "ignore_list_reply_to", DT_BOOL, R_NONE, (void *) OPTIGNORELISTREPLYTO, 0 },
  { "ispell",		DT_PATH, R_NONE, S_DECL(Ispell) },
  { "locale",		DT_STR,  R_BOTH, S_DECL(Locale) },
  { "mail_check",	DT_NUM,  R_NONE, &BuffyTimeout },
  { "mailcap_path",	DT_STR,	 R_NONE, S_DECL(MailcapPath) },
  { "mark_old",		DT_BOOL, R_BOTH, (void *) OPTMARKOLD,	0 },
  { "markers",		DT_BOOL, R_PAGER, (void *) OPTMARKERS,	0 },
  { "mask",		DT_RX,	 R_NONE, &Mask },
  { "mbox",		DT_PATH, R_BOTH, S_DECL(Inbox) },
  { "mbox_type",	DT_MAGIC,R_NONE, &DefaultMagic },
  { "metoo",		DT_BOOL, R_NONE, (void *) OPTMETOO,	0 },
  { "menu_scroll",	DT_BOOL, R_NONE, (void *) OPTMENUSCROLL },
  { "mime_fwd",		DT_BOOL, R_NONE, (void *) OPTMIMEFWD,	0 },
  { "move",		DT_QUAD, R_NONE, (void *) OPT_MOVE,	0 },
  { "msg_format",	DT_STR,	 R_NONE, S_DECL(MsgFmt) },
  { "pager",		DT_PATH, R_NONE, S_DECL(Pager) },
  { "pager_context",	DT_NUM,	 R_NONE, &PagerContext },
  { "pager_format",	DT_STR,	 R_PAGER, S_DECL(PagerFmt) },
  { "pager_index_lines",DT_NUM,	 R_PAGER, &PagerIndexLines },
  { "pager_stop",	DT_BOOL, R_NONE, (void *) OPTPAGERSTOP,	0 },

#ifdef _PGPPATH
  { "pgp",		DT_PATH, R_NONE, S_DECL(Pgp) },
  { "pgp_autosign",	DT_BOOL, R_NONE, (void *) OPTPGPAUTOSIGN, 0 },
  { "pgp_autoencrypt",	DT_BOOL, R_NONE, (void *) OPTPGPAUTOENCRYPT, 0 },
  { "pgp_encryptself",	DT_BOOL, R_NONE, (void *) OPTPGPENCRYPTSELF, 0 },
  { "pgp_long_ids",	DT_BOOL, R_NONE, (void *) OPTPGPLONGIDS, 0 },
  { "pgp_replyencrypt",	DT_BOOL, R_NONE, (void *) OPTPGPREPLYENCRYPT, 0 },
  { "pgp_replysign",	DT_BOOL, R_NONE, (void *) OPTPGPREPLYSIGN, 0 },
  { "pgp_sign_as",	DT_STR,	 R_NONE, S_DECL(PgpSignAs) },
  { "pgp_strict_enc",	DT_BOOL, R_NONE, (void *) OPTPGPSTRICTENC, 0 },
  { "pgp_pubring",	DT_PATH, R_NONE, S_DECL(PgpPubring) },
  { "pgp_secring",	DT_PATH, R_NONE, S_DECL(PgpSecring) },
  { "pgp_timeout",	DT_NUM,	 R_NONE, &PgpTimeout },
  { "pgp_version",	DT_STR,  R_NONE, S_DECL(PgpVersion) },
  { "verify_sig",	DT_QUAD, R_NONE, (void *) OPT_VERIFYSIG,	0 },
#endif /* _PGPPATH */

  { "pipe_split",	DT_BOOL, R_NONE, (void *) OPTPIPESPLIT,	0 },
  { "pipe_decode",	DT_BOOL, R_NONE, (void *) OPTPIPEDECODE,	0 },
  { "pipe_sep",		DT_STR,	 R_NONE, S_DECL(PipeSep) },
#ifdef USE_POP
  { "pop_delete",	DT_BOOL, R_NONE, (void *) OPTPOPDELETE,	0 },
  { "pop_host",		DT_STR,	 R_NONE, S_DECL(PopHost) },
  { "pop_port",		DT_NUM,	 R_NONE, &PopPort },
  { "pop_pass",		DT_STR,	 R_NONE, S_DECL(PopPass) },
  { "pop_user",		DT_STR,	 R_NONE, S_DECL(PopUser) },
#endif /* USE_POP */
  { "post_indent_str",	DT_STR,	 R_NONE, S_DECL(PostIndentString) },
  { "postpone",		DT_QUAD, R_NONE, (void *) OPT_POSTPONE,	0 },
  { "postponed",	DT_PATH, R_NONE, S_DECL(Postponed) },
  { "print",		DT_QUAD, R_NONE, (void *) OPT_PRINT,	0 },
  { "print_cmd",	DT_PATH, R_NONE, S_DECL(PrintCmd) },
  { "prompt_after",	DT_BOOL, R_NONE, (void *) OPTPROMPTAFTER, 0 },
  { "quote_regexp",	DT_RX,	 R_PAGER, &QuoteRegexp },
  { "reply_regexp",	DT_RX,	 R_INDEX, &ReplyRegexp },
  { "read_inc",		DT_NUM,	 R_NONE, &ReadInc },
  { "read_only",	DT_BOOL, R_NONE, (void *) OPTREADONLY,	0 },
  { "realname",		DT_STR,	 R_BOTH, S_DECL(Realname) },
  { "recall",		DT_QUAD, R_NONE, (void *) OPT_RECALL,	0 },
  { "record",		DT_PATH, R_NONE, S_DECL(Outbox) },
  { "references",	DT_NUM,	 R_NONE, &TrimRef },
  { "reply_to",		DT_QUAD, R_NONE, (void *) OPT_REPLYTO,	0 },
  { "resolve",		DT_BOOL, R_NONE, (void *) OPTRESOLVE,	0 },
  { "reverse_alias",	DT_BOOL, R_BOTH, (void *) OPTREVALIAS,	0 },
  { "reverse_name",	DT_BOOL, R_BOTH, (void *) OPTREVNAME,	0 },
  { "save_address",	DT_BOOL, R_NONE, (void *) OPTSAVEADDRESS,	0 },
  { "save_empty",	DT_BOOL, R_NONE, (void *) OPTSAVEEMPTY,	0 },
  { "save_name",	DT_BOOL, R_NONE, (void *) OPTSAVENAME,	0 },
  { "sendmail",		DT_PATH, R_NONE, S_DECL(Sendmail) },
  { "sendmail_bounce",	DT_PATH, R_NONE, S_DECL(SendmailBounce) },
  { "shell",		DT_PATH, R_NONE, S_DECL(Shell) },
  { "sig_dashes",	DT_BOOL, R_NONE, (void *) OPTSIGDASHES,	0 },
  { "signature",	DT_PATH, R_NONE, S_DECL(Signature) },
  { "simple_search",	DT_STR,	 R_NONE, S_DECL(SimpleSearch) },
  { "smart_wrap",	DT_BOOL, R_PAGER,(void *) OPTWRAP,	0 },
  { "sort",		DT_SORT, R_INDEX, &Sort,	0 },
  { "sort_aux",		DT_SORT, R_INDEX, &SortAux, 0 },
  { "sort_browser",	DT_SORT, R_NONE, &BrowserSort, 0 },
  { "sort_re",		DT_BOOL, R_INDEX, (void *) OPTSORTRE,	0 },
  { "spoolfile",	DT_PATH, R_NONE, S_DECL(Spoolfile) },
  { "status_chars",	DT_STR,	 R_BOTH, S_DECL(StChars) },
  { "status_format",	DT_STR,	 R_BOTH, S_DECL(Status) },
  { "status_on_top",	DT_BOOL, R_BOTH, (void *) OPTSTATUSONTOP,	0 },
  { "strict_threads",	DT_BOOL, R_INDEX, (void *) OPTSTRICTTHREADS, 0 },
  { "suspend",		DT_BOOL, R_NONE, (void *) OPTSUSPEND,	0 },
  { "thorough_search",	DT_BOOL, R_NONE, (void *) OPTTHOROUGHSRC, 0 },
  { "tilde",		DT_BOOL, R_PAGER,(void *) OPTTILDE,	0 },
  { "timeout",		DT_NUM,	 R_NONE, &Timeout },
  { "tmpdir",		DT_PATH, R_NONE, S_DECL(Tempdir) },
  { "to_chars",		DT_STR,	 R_BOTH, S_DECL(Tochars) },
  { "use_8bitmime",	DT_BOOL, R_NONE, (void *) OPTUSE8BITMIME,	0 },
  { "use_domain",	DT_BOOL, R_NONE, (void *) OPTUSEDOMAIN,	0 },
  { "use_from",		DT_BOOL, R_NONE, (void *) OPTUSEFROM,	0 },
  { "use_mailcap",	DT_QUAD, R_NONE, (void *) OPT_USEMAILCAP, 0 },
  { "visual",		DT_PATH, R_NONE, S_DECL(Visual) },
  { "wait_key",		DT_BOOL, R_NONE, (void *) OPTWAITKEY,	0 },
  { "write_inc",	DT_NUM,	 R_NONE, &WriteInc },
  { NULL,		0,	 0,	NULL,	0 }
};

const struct mapping_t SortMethods[] = {
  { "date",		SORT_DATE },
  { "date-sent",	SORT_DATE },
  { "date-received",	SORT_RECEIVED },
  { "mailbox-order",	SORT_ORDER },
  { "subject",		SORT_SUBJECT },
  { "alpha",		SORT_SUBJECT }, /* alphabetic sort */
  { "from",		SORT_FROM },
  { "size",		SORT_SIZE },
  { "threads",		SORT_THREADS },
  { NULL,		0 }
};

/* functions used to parse commands in a rc file */

static int parse_list (const char *, void *, char *, size_t);
static int parse_unlist (const char *, void *, char *, size_t);
static int parse_alias (const char *, void *, char *, size_t);
static int parse_unalias (const char *, void *, char *, size_t);
static int parse_ignore (const char *, void *, char *, size_t);
static int parse_unignore (const char *, void *, char *, size_t);
static int parse_source (const char *, void *, char *, size_t);
static int parse_set (const char *, void *, char *, size_t);
static int parse_my_hdr (const char *, void *, char *, size_t);
static int parse_unmy_hdr (const char *, void *, char *, size_t);

struct command_t
{
  char *name;
  int (*func) (const char *, void *, char *, size_t);
  void *data;
};

struct command_t Commands[] = {
  { "alias",		parse_alias,		NULL },
  { "auto_view",	parse_list,		&AutoViewList },
  { "bind",		mutt_parse_bind,	NULL },
#ifdef HAVE_COLOR
  { "color",		mutt_parse_color,	NULL },
#endif
  { "fcc-hook",		mutt_parse_hook,	(void *) M_FCCHOOK },
  { "folder-hook",	mutt_parse_hook,	(void *) M_FOLDERHOOK },
  { "hdr_order",	parse_list,		&HeaderOrderList },
  { "ignore",		parse_ignore,		NULL },
  { "lists",		parse_list,		&MailLists },
  { "macro",		mutt_parse_macro,	NULL },
  { "mailboxes",	mutt_parse_mailboxes,	NULL },
  { "mbox-hook",	mutt_parse_hook,	(void *) M_MBOXHOOK },
  { "mono",		mutt_parse_mono,	NULL },
  { "my_hdr",		parse_my_hdr,		NULL },
  { "push",		mutt_parse_push,	NULL },
  { "save-hook",	mutt_parse_hook,	(void *) M_SAVEHOOK },
  { "send-hook",	mutt_parse_hook,	(void *) M_SENDHOOK },
  { "set",		parse_set,		NULL },
  { "source",		parse_source,		NULL },
  { "toggle",		parse_set,		(void *) M_SET_INV },
  { "unalias",		parse_unalias,		NULL },
  { "unignore",		parse_unignore,		NULL },
  { "unlists",		parse_unlist,		&MailLists },
  { "unmy_hdr",		parse_unmy_hdr,		NULL },
  { "unset",		parse_set,		(void *) M_SET_UNSET },
  { NULL,		NULL,			NULL }
};
