bug 764: Initialize the right member of union option_value
[elinks.git] / src / config / options.h
blobeaa08f465cccbf873dac89125a98e050f02d45a8
2 #ifndef EL__CONFIG_OPTIONS_H
3 #define EL__CONFIG_OPTIONS_H
5 #include "main/object.h"
6 #include "util/color.h"
7 #include "util/lists.h"
8 #include "util/memory.h"
9 #include "util/string.h"
11 /* TODO: We should provide some generic mechanism for options caching. */
13 /* Fix namespace clash on Cygwin. */
14 #define option option_elinks
17 enum option_flags {
18 /* bitmask */
19 /* The option is hidden - it serves for internal purposes, never is
20 * read, never is written, never is displayed, never is crawled through
21 * etc. */
22 OPT_HIDDEN = 1,
23 /* For OPT_TREE, automatically create missing hiearchy piece just under
24 * this category when adding an option. The 'template' for the added
25 * hiearchy piece (category) is stored as "_template_" category. */
26 OPT_AUTOCREATE = 2,
27 /* The option has been modified in some way and must be saved
28 * to elinks.conf. ELinks uses this flag only while it is
29 * saving the options. When the config.saving_style option
30 * has value 3, saving works like this:
31 * - First, ELinks sets OPT_MUST_SAVE in the options that have
32 * OPT_TOUCHED or OPT_DELETED, and clears it in the rest.
33 * - ELinks then parses the old configuration file and any
34 * files named in "include" commands.
35 * - If the old configuration file contains a "set" or "unset"
36 * command for this option, ELinks rewrites the command and
37 * clears OPT_MUST_SAVE.
38 * - If an included file contains a "set" or "unset" command
39 * for this option, ELinks compares the value of the option
40 * to the value given in the command. ELinks clears
41 * OPT_MUST_SAVE if the values match, or sets it if they
42 * differ.
43 * - After ELinks has rewritten the configuration file and
44 * parsed the included files, it appends the options that
45 * still have the OPT_MUST_SAVE flag.
46 * Other saving styles are variants of this:
47 * - 0: ELinks does not append any options to the
48 * configuration file. So OPT_MUST_SAVE has no effect.
49 * - 1: ELinks initially sets OPT_MUST_SAVE in all options,
50 * regardless of OPT_TOUCHED and OPT_DELETED.
51 * - 2: ELinks initially sets OPT_MUST_SAVE in all options,
52 * and does not read any configuration files. */
53 OPT_MUST_SAVE = 4,
54 /* This is used to mark options modified after the last save. That's
55 * being useful if you want to save only the options whose value
56 * changed. */
57 OPT_TOUCHED = 8,
58 /* If set on the tree argument to add_opt (not necessarily the direct
59 * parent) or on the option itself, it will create the listbox (options
60 * manager) item for the option. */
61 OPT_LISTBOX = 16,
62 /* This is used to mark that the option _and_ the option name is
63 * allocated and should be freed when the option is released. */
64 OPT_ALLOC = 32,
65 /* For OPT_TREE, automatically sort the content of the tree
66 * alphabetically (but all subtrees in front of ordinary options) when
67 * adding new options. Note that this applies only to the one level
68 * below - it will not apply to the sub-trees in this tree. Also, this
69 * can be quite expensive for busy-adding big trees, so think twice
70 * before doing it - in fact, it is supposed to be used only where you
71 * add stuff from more modules, not all at once; typically the
72 * config_options root tree. Especially NOT RECOMMENDED to be used on
73 * the template trees. */
74 OPT_SORT = 64,
75 /* This is used to mark option as deleted */
76 OPT_DELETED = 128,
77 /* Specifies that values of boolean aliases should be inverted. */
78 OPT_ALIAS_NEGATE = 256
81 enum option_type {
82 OPT_BOOL = 0,
83 OPT_INT,
84 OPT_LONG,
85 OPT_STRING,
87 OPT_CODEPAGE,
88 OPT_LANGUAGE,
89 OPT_COLOR,
91 OPT_COMMAND,
93 OPT_ALIAS,
95 OPT_TREE,
98 struct listbox_item; /* bfu/listbox.h */
99 struct option; /* defined later in this file */
100 struct session; /* session/session.h */
102 typedef unsigned char *option_command_fn_T(struct option *,
103 unsigned char ***, int *);
105 union option_value {
106 /* XXX: Keep first to make @options_root initialization possible. */
107 /* The OPT_TREE list_head is allocated. */
108 LIST_OF(struct option) *tree;
110 /* Used by OPT_BOOL, OPT_INT, OPT_CODEPAGE and OPT_LANGUAGE */
111 int number;
113 /* Used by OPT_LONG */
114 long big_number;
116 /* The OPT_COLOR value */
117 color_T color;
119 /* The OPT_COMMAND value */
120 option_command_fn_T *command;
122 /* The OPT_STRING string is allocated and has length MAX_STR_LEN.
123 * The OPT_ALIAS string is NOT allocated, has variable length
124 * (opt->max) and should remain untouched! It contains the full path to
125 * the "real" / aliased option. */
126 unsigned char *string;
130 /* @session is the session via which the user changed the options,
131 * or NULL if not known. Because the options are currently not
132 * session-specific, it is best to ignore this parameter. In a future
133 * version of ELinks, this parameter might mean the session to which
134 * the changed options apply.
136 * @current is the option whose change hook is being called. It is
137 * never NULL.
139 * @changed is the option that was changed, or NULL if multiple
140 * descendants of @current may have been changed. */
141 typedef int (*change_hook_T)(struct session *session, struct option *current,
142 struct option *changed);
144 struct option {
145 OBJECT_HEAD(struct option);
147 unsigned char *name;
148 enum option_flags flags;
149 enum option_type type;
150 long min, max;
151 union option_value value;
152 unsigned char *desc;
153 unsigned char *capt;
155 struct option *root;
157 /* To be called when the option (or sub-option if it's a tree) is
158 * changed. If it returns zero, we will continue descending the options
159 * tree checking for change handlers. */
160 change_hook_T change_hook;
162 struct listbox_item *box_item;
165 /** An initializer for struct option. This is quite rare:
166 * most places should instead initialize struct option_init,
167 * with ::INIT_OPT_INT or a similar macro. */
168 #define INIT_OPTION(name, flags, type, min, max, value, desc, capt) \
169 { NULL_LIST_HEAD, INIT_OBJECT("option"), name, flags, type, min, max, { (LIST_OF(struct option) *) (value) }, desc, capt }
171 extern struct option *config_options;
172 extern struct option *cmdline_options;
175 extern void init_options(void);
176 extern void done_options(void);
179 struct change_hook_info {
180 unsigned char *name;
181 change_hook_T change_hook;
184 extern void register_change_hooks(const struct change_hook_info *change_hooks);
187 extern LIST_OF(struct option) *init_options_tree(void);
188 extern void prepare_mustsave_flags(LIST_OF(struct option) *, int set_all);
189 extern void untouch_options(LIST_OF(struct option) *);
191 extern void smart_config_string(struct string *, int, int,
192 LIST_OF(struct option) *, unsigned char *, int,
193 void (*)(struct string *, struct option *,
194 unsigned char *, int, int, int, int));
196 extern struct option *copy_option(struct option *);
197 extern void delete_option(struct option *);
198 void mark_option_as_deleted(struct option *);
200 /* Some minimal option cache */
202 struct option_resolver {
203 int id;
204 unsigned char *name;
207 /* Update the visibility of the box item of each option
208 * in config_options to honour the value of config.show_template. */
209 void update_options_visibility(void);
211 /* Toggle the value of the given option numeric, respecting option->min
212 * and option->max. */
213 void toggle_option(struct session *ses, struct option *option);
215 /* Call the change-hooks for the given option and recur on its parent. */
216 void call_change_hooks(struct session *ses, struct option *current,
217 struct option *option);
219 /* Do proper bookkeeping after an option has changed - call this every time
220 * you change an option value. */
221 void option_changed(struct session *ses, struct option *option);
223 extern int commit_option_values(struct option_resolver *resolvers,
224 struct option *root,
225 union option_value *values, int size);
226 extern void checkout_option_values(struct option_resolver *resolvers,
227 struct option *root,
228 union option_value *values, int size);
230 /* Shitload of various incredible macro combinations and other unusable garbage
231 * follows. Have fun. */
233 /* Basically, for main hiearchy addressed from root (almost always) you want to
234 * use get_opt_type() and add_opt_type(). For command line options, you want to
235 * use get_opt_type_tree(cmdline_options, "option"). */
237 extern struct option *get_opt_rec(struct option *, const unsigned char *);
238 extern struct option *get_opt_rec_real(struct option *, const unsigned char *);
239 struct option *indirect_option(struct option *);
240 #ifdef CONFIG_DEBUG
241 extern union option_value *get_opt_(unsigned char *, int, enum option_type, struct option *, unsigned char *);
242 #define get_opt(tree, name, type) get_opt_(__FILE__, __LINE__, type, tree, name)
243 #else
244 extern union option_value *get_opt_(struct option *, unsigned char *);
245 #define get_opt(tree, name, type) get_opt_(tree, name)
246 #endif
248 #define get_opt_bool_tree(tree, name) get_opt(tree, name, OPT_BOOL)->number
249 #define get_opt_int_tree(tree, name) get_opt(tree, name, OPT_INT)->number
250 #define get_opt_long_tree(tree, name) get_opt(tree, name, OPT_LONG)->big_number
251 #define get_opt_str_tree(tree, name) get_opt(tree, name, OPT_STRING)->string
252 #define get_opt_codepage_tree(tree, name) get_opt(tree, name, OPT_CODEPAGE)->number
253 #define get_opt_color_tree(tree, name) get_opt(tree, name, OPT_COLOR)->color
254 #define get_opt_tree_tree(tree_, name) get_opt(tree_, name, OPT_TREE)->tree
256 #define get_opt_bool(name) get_opt_bool_tree(config_options, name)
257 #define get_opt_int(name) get_opt_int_tree(config_options, name)
258 #define get_opt_long(name) get_opt_long_tree(config_options, name)
259 #define get_opt_str(name) get_opt_str_tree(config_options, name)
260 #define get_opt_codepage(name) get_opt_codepage_tree(config_options, name)
261 #define get_opt_color(name) get_opt_color_tree(config_options, name)
262 #define get_opt_tree(name) get_opt_tree_tree(config_options, name)
264 #define get_cmd_opt_bool(name) get_opt_bool_tree(cmdline_options, name)
265 #define get_cmd_opt_int(name) get_opt_int_tree(cmdline_options, name)
266 #define get_cmd_opt_long(name) get_opt_long_tree(cmdline_options, name)
267 #define get_cmd_opt_str(name) get_opt_str_tree(cmdline_options, name)
268 #define get_cmd_opt_codepage(name) get_opt_codepage_tree(cmdline_options, name)
269 #define get_cmd_opt_color(name) get_opt_color_tree(cmdline_options, name)
270 #define get_cmd_opt_tree(name) get_opt_tree_tree(cmdline_options, name)
272 extern struct option *add_opt(struct option *, unsigned char *, unsigned char *,
273 unsigned char *, enum option_flags, enum option_type,
274 long, long, longptr_T, unsigned char *);
276 /* Hack which permit to disable option descriptions, to reduce elinks binary size.
277 * It may of some use for people wanting a very small static non-i18n elinks binary,
278 * at time of writing gain is over 25Kbytes. --Zas */
279 #ifndef CONFIG_SMALL
280 #define DESC(x) (x)
281 #else
282 #define DESC(x) ((unsigned char *) "")
283 #endif
286 #define add_opt_bool_tree(tree, path, capt, name, flags, def, desc) \
287 add_opt(tree, path, capt, name, flags, OPT_BOOL, 0, 1, (longptr_T) def, DESC(desc))
289 #define add_opt_int_tree(tree, path, capt, name, flags, min, max, def, desc) \
290 add_opt(tree, path, capt, name, flags, OPT_INT, min, max, (longptr_T) def, DESC(desc))
292 #define add_opt_long_tree(tree, path, capt, name, flags, min, max, def, desc) \
293 add_opt(tree, path, capt, name, flags, OPT_LONG, min, max, (longptr_T) def, DESC(desc))
295 #define add_opt_str_tree(tree, path, capt, name, flags, def, desc) \
296 do { \
297 unsigned char *ptr = mem_alloc(MAX_STR_LEN); \
298 safe_strncpy(ptr, def, MAX_STR_LEN); \
299 add_opt(tree, path, capt, name, flags, OPT_STRING, 0, MAX_STR_LEN, (longptr_T) ptr, DESC(desc)); \
300 } while (0)
302 #define add_opt_codepage_tree(tree, path, capt, name, flags, def, desc) \
303 add_opt(tree, path, capt, name, flags, OPT_CODEPAGE, 0, 0, (longptr_T) get_cp_index(def), DESC(desc))
305 #define add_opt_lang_tree(tree, path, capt, name, flags, desc) \
306 add_opt(tree, path, capt, name, flags, OPT_LANGUAGE, 0, 0, (longptr_T) 0, DESC(desc))
308 #define add_opt_color_tree(tree, path, capt, name, flags, def, desc) \
309 add_opt(tree, path, capt, name, flags, OPT_COLOR, 0, 0, (longptr_T) def, DESC(desc))
311 #define add_opt_command_tree(tree, path, capt, name, flags, cmd, desc) \
312 add_opt(tree, path, capt, name, flags, OPT_COMMAND, 0, 0, (longptr_T) cmd, DESC(desc));
314 #define add_opt_alias_tree(tree, path, capt, name, flags, def, desc) \
315 add_opt(tree, path, capt, name, flags, OPT_ALIAS, 0, strlen(def), (longptr_T) def, DESC(desc))
317 #define add_opt_tree_tree(tree, path, capt, name, flags, desc) \
318 add_opt(tree, path, capt, name, flags, OPT_TREE, 0, 0, (longptr_T) init_options_tree(), DESC(desc));
321 /* Builtin options */
323 /** How to initialize and register struct option. register_options()
324 * moves the values from this to struct option. This initialization
325 * must be deferred to run time because C89 provides no portable way
326 * to initialize the correct member of union option_value at compile
327 * time. */
328 struct option_init {
329 /** The name of the option tree where the option should be
330 * registered. option.root is computed from this. */
331 unsigned char *path;
333 /** The name of the option. This goes to option.name. */
334 unsigned char *name;
336 /** The caption shown in the option manager. This goes to
337 * option.capt. */
338 unsigned char *capt;
340 /** The long description shown when the user edits the option,
341 * or NULL if not available. This goes to option.desc. */
342 unsigned char *desc;
344 /** Flags for the option. These go to option.flags. */
345 enum option_flags flags;
347 /** Type of the option. This goes to option.type. */
348 enum option_type type;
350 /** Minimum and maximum value of the option. These go to
351 * option.min and option.max. For some option types, @c max
352 * is the maximum length or fixed length instead. */
353 long min, max;
355 /** @name Default value of the option
356 * The value of an option can be an integer, a data pointer,
357 * or a function pointer. This structure has a separate
358 * member for each of those types, to avoid compile-time casts
359 * that could lose some bits of the value. Although this
360 * scheme looks a bit bloaty, struct option_init remains
361 * smaller than struct option and so does not require any
362 * extra space in union option_info. @{ */
364 /** The default value of the option, if the #type is ::OPT_BOOL,
365 * ::OPT_INT, or ::OPT_LONG. Zero otherwise. This goes to
366 * option_value.number or option_value.big_number. */
367 long value_long;
369 /** The default value of the option, if the #type is ::OPT_STRING,
370 * ::OPT_CODEPAGE, ::OPT_COLOR, or ::OPT_ALIAS. NULL otherwise.
371 * This goes to option_value.string, or after some parsing to
372 * option_value.color or option_value.number. */
373 void *value_dataptr;
375 /** The constant value of the option, if the #type is ::OPT_COMMAND.
376 * NULL otherwise. This goes to option_value.command. */
377 option_command_fn_T *value_funcptr;
379 /** @} */
382 /** Instructions for registering an option, and storage for the option
383 * itself. */
384 union option_info {
385 /** How to initialize and register #option. This must be the
386 * first member of the union, to let C89 compilers initialize
387 * it. */
388 struct option_init init;
390 /** register_options() constructs the option here, based on
391 * the instructions in #init. By doing so, it of course
392 * overwrites #init. Thus, only @c option can be used
393 * afterwards. */
394 struct option option;
397 extern void register_options(union option_info info[], struct option *tree);
398 extern void unregister_options(union option_info info[], struct option *tree);
400 #define NULL_OPTION_INFO \
401 {{ NULL, NULL, NULL, NULL, 0, \
402 0, 0, 0, 0, NULL, NULL }}
404 #define INIT_OPT_BOOL(path, capt, name, flags, def, desc) \
405 {{ path, name, capt, DESC(desc), flags, \
406 OPT_BOOL, 0, 1, def, NULL, NULL }}
408 #define INIT_OPT_INT(path, capt, name, flags, min, max, def, desc) \
409 {{ path, name, capt, DESC(desc), flags, \
410 OPT_INT, min, max, def, NULL, NULL }}
412 #define INIT_OPT_LONG(path, capt, name, flags, min, max, def, desc) \
413 {{ path, name, capt, DESC(desc), flags, \
414 OPT_LONG, min, max, def, NULL, NULL }}
416 #define INIT_OPT_STRING(path, capt, name, flags, def, desc) \
417 {{ path, name, capt, DESC(desc), flags, \
418 OPT_STRING, 0, MAX_STR_LEN, 0, def, NULL }}
420 #define INIT_OPT_CODEPAGE(path, capt, name, flags, def, desc) \
421 {{ path, name, capt, DESC(desc), flags, \
422 OPT_CODEPAGE, 0, 0, 0, def, NULL }}
424 #define INIT_OPT_COLOR(path, capt, name, flags, def, desc) \
425 {{ path, name, capt, DESC(desc), flags, \
426 OPT_COLOR, 0, 0, 0, def, NULL }}
428 #define INIT_OPT_LANGUAGE(path, capt, name, flags, desc) \
429 {{ path, name, capt, DESC(desc), flags, \
430 OPT_LANGUAGE, 0, 0, 0, NULL, NULL }}
432 #define INIT_OPT_COMMAND(path, capt, name, flags, cmd, desc) \
433 {{ path, name, capt, DESC(desc), flags, \
434 OPT_COMMAND, 0, 0, 0, NULL, cmd }}
436 #define INIT_OPT_CMDALIAS(path, capt, name, flags, def, desc) \
437 {{ path, name, capt, DESC(desc), flags, \
438 OPT_ALIAS, 0, sizeof(def) - 1, 0, def, NULL }}
440 #define INIT_OPT_ALIAS(path, name, flags, def) \
441 {{ path, name, NULL, NULL, flags, \
442 OPT_ALIAS, 0, sizeof(def) - 1, 0, def, NULL }}
444 #define INIT_OPT_TREE(path, capt, name, flags, desc) \
445 {{ path, name, capt, DESC(desc), flags, \
446 OPT_TREE, 0, 0, 0, NULL, NULL }}
449 /* TODO: We need to do *something* with this ;). */
451 enum referer {
452 REFERER_NONE,
453 REFERER_SAME_URL,
454 REFERER_FAKE,
455 REFERER_TRUE,
458 enum verbose_level {
459 VERBOSE_QUIET,
460 VERBOSE_WARNINGS,
461 VERBOSE_ALL,
463 VERBOSE_LEVELS,
466 #endif