5 * by JH <jheinonen@users.sourceforge.net>
7 * Copyright (C) Jaakko Heinonen
30 #define UL (unsigned long)
49 static struct option abook_vars[] = {
50 { "autosave", OT_BOOL, BOOL_AUTOSAVE, TRUE },
52 { "show_all_emails", OT_BOOL, BOOL_SHOW_ALL_EMAILS, TRUE },
53 { "index_format", OT_STR, STR_INDEX_FORMAT, UL " {name:22} {email:40} {phone:12|workphone|mobile}" },
54 { "mutt_command", OT_STR, STR_MUTT_COMMAND, UL "mutt" },
55 { "mutt_return_all_emails", OT_BOOL, BOOL_MUTT_RETURN_ALL_EMAILS,
58 { "print_command", OT_STR, STR_PRINT_COMMAND, UL "lpr" },
60 { "www_command", OT_STR, STR_WWW_COMMAND, UL "lynx" },
62 { "address_style", OT_STR, STR_ADDRESS_STYLE, UL "eu" },
64 { "use_ascii_only", OT_BOOL, BOOL_USE_ASCII_ONLY, FALSE },
66 { "add_email_prevent_duplicates", OT_BOOL, BOOL_ADD_EMAIL_PREVENT_DUPLICATES, FALSE },
67 { "preserve_fields", OT_STR, STR_PRESERVE_FIELDS, UL "standard" },
68 { "sort_field", OT_STR, STR_SORT_FIELD, UL "nick" },
69 { "show_cursor", OT_BOOL, BOOL_SHOW_CURSOR, FALSE },
70 { "use_mouse", OT_BOOL, BOOL_USE_MOUSE, FALSE },
71 { "scroll_speed", OT_INT, INT_SCROLL_SPEED, UL 2 },
72 { "use_colors", OT_BOOL, BOOL_USE_COLORS, FALSE },
73 { "color_header_fg", OT_STR, STR_COLOR_HEADER_FG, UL "blue" },
74 { "color_header_fg", OT_STR, STR_COLOR_HEADER_FG, UL "blue" },
75 { "color_header_bg", OT_STR, STR_COLOR_HEADER_BG, UL "red" },
76 { "color_footer_fg", OT_STR, STR_COLOR_FOOTER_FG, UL "red" },
77 { "color_footer_bg", OT_STR, STR_COLOR_FOOTER_BG, UL "default" },
78 { "color_list_even_fg", OT_STR, STR_COLOR_LIST_EVEN_FG, UL "yellow" },
79 { "color_list_even_bg", OT_STR, STR_COLOR_LIST_EVEN_BG, UL "default" },
80 { "color_list_odd_fg", OT_STR, STR_COLOR_LIST_ODD_FG, UL "default" },
81 { "color_list_odd_bg", OT_STR, STR_COLOR_LIST_ODD_BG, UL "default" },
82 { "color_list_header_fg", OT_STR, STR_COLOR_LIST_HEADER_FG, UL "white" },
83 { "color_list_header_bg", OT_STR, STR_COLOR_LIST_HEADER_BG, UL "blue" },
84 { "color_list_highlight_fg", OT_STR, STR_COLOR_LIST_HIGHLIGHT_FG, UL "black" },
85 { "color_list_highlight_bg", OT_STR, STR_COLOR_LIST_HIGHLIGHT_BG, UL "green" },
86 { "color_tab_border_fg", OT_STR, STR_COLOR_TAB_BORDER_FG, UL "cyan" },
87 { "color_tab_border_bg", OT_STR, STR_COLOR_TAB_BORDER_BG, UL "default" },
88 { "color_tab_label_fg", OT_STR, STR_COLOR_TAB_LABEL_FG, UL "magenta" },
89 { "color_tab_label_bg", OT_STR, STR_COLOR_TAB_LABEL_BG, UL "default" },
90 { "color_field_name_fg", OT_STR, STR_COLOR_FIELD_NAME_FG, UL "yellow" },
91 { "color_field_name_bg", OT_STR, STR_COLOR_FIELD_NAME_BG, UL "default" },
92 { "color_field_value_fg", OT_STR, STR_COLOR_FIELD_VALUE_FG, UL "green" },
93 { "color_field_value_bg", OT_STR, STR_COLOR_FIELD_VALUE_BG, UL "default" },
97 static unsigned char bool_opts[BOOL_MAX];
98 static int int_opts[INT_MAXIMUM];
99 static char *str_opts[STR_MAX];
102 set_int(enum int_opts opt, int value)
104 assert(opt >= 0 && opt < INT_MAXIMUM);
106 int_opts[opt] = value;
110 set_bool(enum bool_opts opt, bool value)
112 assert(opt >= 0 && opt < BOOL_MAX);
114 bool_opts[opt] = value;
118 set_str(enum str_opts opt, char *value)
120 assert(opt >= 0 && opt < STR_MAX);
125 str_opts[opt] = xstrdup(value);
129 opt_get_int(enum int_opts opt)
131 assert(opt >= 0 && opt < INT_MAXIMUM);
133 return int_opts[opt];
137 opt_get_bool(enum bool_opts opt)
139 assert(opt >= 0 && opt < BOOL_MAX);
141 return bool_opts[opt];
145 opt_get_str(enum str_opts opt)
147 assert(opt >= 0 && opt < STR_MAX);
149 return str_opts[opt];
153 restore_default(struct option *p)
157 set_bool(p -> data, (bool)p -> init);
160 set_int(p -> data, (int)p -> init);
164 set_str(p -> data, (char *) p -> init);
176 for(i = 0; abook_vars[i].option; i++)
177 restore_default(&abook_vars[i]);
186 * only strings need to be freed
188 for(i = 0; i < STR_MAX; i++) {
203 opt_line_remove_comments(char *p)
205 bool in_quote = FALSE;
214 in_quote = !in_quote;
231 * - b->data points to the found token, or NULL is end of parsing
232 * - b->ptr points to the begining of next token
234 * If the TOKEN_ALLOC option is used, the original string is not mangled
235 * and memory is allocated for the token.
238 get_token(buffer *b, int options)
246 if(*b->ptr && strchr("\"'", *b->ptr))
258 ((options & TOKEN_EQUAL) && (c == '=')) ||
259 ((options & TOKEN_COMMA) && (c == ',')))
263 } else if(c == quote) {
273 return _("quote mismatch");
275 if(options & (TOKEN_EQUAL | TOKEN_COMMA))
276 SKIPWS(b->ptr); /* whitespaces can precede the sign */
278 if((options & TOKEN_EQUAL) && (*b->ptr != '='))
279 return _("no assignment character found");
281 if((options & TOKEN_COMMA) && *b->ptr && (*b->ptr != ','))
282 return _("error in comma separated list");
284 if(b->ptr == b->data) {
286 return NULL; /* no error, just end of parsing */
289 if(options & TOKEN_ALLOC) /* freeing is the caller's responsibility */
290 b->data = xstrndup(b->data, end - b->data);
294 b->ptr++; /* advance to next token */
301 opt_set_set_option(char *p, struct option *opt)
310 if(*p == '\"' && p[len - 1] == '\"') {
312 return _("invalid value");
317 switch(opt -> type) {
319 set_str(opt -> data, p);
322 set_int(opt -> data, safe_atoi(p));
325 if(!strcasecmp(p, "true") || !strcasecmp(p, "on"))
326 set_bool(opt -> data, TRUE);
327 else if(!strcasecmp(p, "false") ||
328 !strcasecmp(p, "off"))
329 set_bool(opt -> data, FALSE);
331 return _("invalid value");
341 opt_set_option(char *var, char *p)
348 for(i = 0; abook_vars[i].option; i++)
349 if(!strcmp(abook_vars[i].option, var))
350 return opt_set_set_option(p, &abook_vars[i]);
352 return _("unknown option");
361 str = opt_get_str(STR_PRESERVE_FIELDS);
362 if(strcasecmp(str, "all") && strcasecmp(str, "none") &&
363 strcasecmp(str, "standard")) {
364 fprintf(stderr, _("valid values for the 'preserve_fields' "
365 "option are 'all', 'standard' "
366 "(default), and 'none'\n"));
367 restore_default(&abook_vars[STR_PRESERVE_FIELDS]);
370 str = opt_get_str(STR_ADDRESS_STYLE);
371 if(strcasecmp(str, "eu") && strcasecmp(str, "uk") &&
372 strcasecmp(str, "us")) {
373 fprintf(stderr, _("valid values for the 'address_style' "
374 "option are 'eu' (default), 'uk', "
376 restore_default(&abook_vars[STR_ADDRESS_STYLE]);
384 * syntax: set <option> = <value>
387 opt_parse_set(buffer *b)
391 if((err = get_token(b, TOKEN_EQUAL)))
394 if((var = b->data) == NULL)
395 return _("invalid value assignment");
397 return opt_set_option(var, b->ptr);
401 opt_parse_customfield(buffer *b)
403 return _("customfield: obsolete command - please use the "
404 "'field' and 'view' commands instead");
407 #include "views.h" /* needed for add_field_to_view */
410 * syntax: view <tab name> = <field1> [ , <field2>, ... ]
413 opt_parse_view(buffer *b)
417 if((err = get_token(b, TOKEN_EQUAL)))
420 if((view = b->data) == NULL)
421 return _("no view name provided");
424 if((err = get_token(b, TOKEN_COMMA)))
430 if((err = add_field_to_view(view, b->data)))
437 #include "database.h" /* needed for declare_new_field */
440 * syntax: field <identifier> = <human readable name> [ , <type> ]
443 opt_parse_field(buffer *b)
445 char *err, *field, *name;
447 if((err = get_token(b, TOKEN_EQUAL)))
450 if((field = b->data) == NULL)
451 return _("no field identifier provided");
453 if((err = get_token(b, TOKEN_COMMA)))
456 if((name = b->data) == NULL)
457 return _("no field name provided");
459 if((err = declare_new_field(field,
462 0 /* reject "standard" fields */)))
471 const char * (*func) (buffer *line);
473 { "set", opt_parse_set },
474 { "customfield", opt_parse_customfield }, /* obsolete */
475 { "view", opt_parse_view },
476 { "field", opt_parse_field },
481 opt_parse_line(char *line, int n, char *fn)
484 const char *err = NULL;
492 if((err = get_token(&b, 0))) {
493 fprintf(stderr, "%s\n", err);
504 b.data = b.ptr = b.ptr;
506 for(i = 0; opt_parsers[i].token; i++)
507 if(!strcmp(opt_parsers[i].token, token)) {
508 if(!(err = opt_parsers[i].func(&b)))
513 fprintf(stderr, _("%s: parse error at line %d: "), fn, n);
515 fprintf(stderr, "%s\n", err);
517 fprintf(stderr, _("unknown token %s\n"), token);
523 load_opts(char *filename)
530 if((in = fopen(filename, "r")) == NULL)
533 for(n = 1;!feof(in); n++) {
540 opt_line_remove_comments(line);
542 err += opt_parse_line(line, n, filename) ? 1:0;
551 /* post-initialization */
552 err += check_options();
553 if(!strcasecmp(opt_get_str(STR_PRESERVE_FIELDS), "standard"))
554 init_standard_fields();