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
19 /* The option is hidden - it serves for internal purposes, never is
20 * read, never is written, never is displayed, never is crawled through
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. */
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
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. */
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
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. */
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. */
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. */
75 /* This is used to mark option as deleted */
77 /* Specifies that values of boolean aliases should be inverted. */
78 OPT_ALIAS_NEGATE
= 256
98 struct listbox_item
; /* bfu/listbox.h */
99 struct option
; /* defined later in this file */
100 struct session
; /* session/session.h */
103 /* XXX: Keep first to make @options_root initialization possible. */
104 /* The OPT_TREE list_head is allocated. */
105 LIST_OF(struct option
) *tree
;
107 /* Used by OPT_BOOL, OPT_INT, OPT_CODEPAGE and OPT_LANGUAGE */
110 /* Used by OPT_LONG */
113 /* The OPT_COLOR value */
116 /* The OPT_COMMAND value */
117 unsigned char *(*command
)(struct option
*, unsigned char ***, int *);
119 /* The OPT_STRING string is allocated and has length MAX_STR_LEN.
120 * The OPT_ALIAS string is NOT allocated, has variable length
121 * (opt->max) and should remain untouched! It contains the full path to
122 * the "real" / aliased option. */
123 unsigned char *string
;
127 /* @session is the session via which the user changed the options,
128 * or NULL if not known. Because the options are currently not
129 * session-specific, it is best to ignore this parameter. In a future
130 * version of ELinks, this parameter might mean the session to which
131 * the changed options apply.
133 * @current is the option whose change hook is being called. It is
136 * @changed is the option that was changed, or NULL if multiple
137 * descendants of @current may have been changed. */
138 typedef int (*change_hook_T
)(struct session
*session
, struct option
*current
,
139 struct option
*changed
);
142 OBJECT_HEAD(struct option
);
145 enum option_flags flags
;
146 enum option_type type
;
148 union option_value value
;
154 /* To be called when the option (or sub-option if it's a tree) is
155 * changed. If it returns zero, we will continue descending the options
156 * tree checking for change handlers. */
157 change_hook_T change_hook
;
159 struct listbox_item
*box_item
;
162 #define INIT_OPTION(name, flags, type, min, max, value, desc, capt) \
163 { NULL_LIST_HEAD, INIT_OBJECT("option"), name, flags, type, min, max, { (LIST_OF(struct option) *) (value) }, desc, capt }
165 extern struct option
*config_options
;
166 extern struct option
*cmdline_options
;
169 extern void init_options(void);
170 extern void done_options(void);
173 struct change_hook_info
{
175 change_hook_T change_hook
;
178 extern void register_change_hooks(const struct change_hook_info
*change_hooks
);
181 extern LIST_OF(struct option
) *init_options_tree(void);
182 extern void prepare_mustsave_flags(LIST_OF(struct option
) *, int set_all
);
183 extern void untouch_options(LIST_OF(struct option
) *);
185 extern void smart_config_string(struct string
*, int, int,
186 LIST_OF(struct option
) *, unsigned char *, int,
187 void (*)(struct string
*, struct option
*,
188 unsigned char *, int, int, int, int));
190 enum copy_option_flags
{
191 /* Do not create a listbox option for the new option. */
192 CO_NO_LISTBOX_ITEM
= (1 << 0),
194 /* Do not copy children. */
195 CO_SHALLOW
= (1 << 1),
198 extern struct option
*copy_option(struct option
*, int);
200 struct option
*get_option_shadow(struct option
*, struct option
*,
203 extern void delete_option(struct option
*);
204 void mark_option_as_deleted(struct option
*);
206 /* Some minimal option cache */
208 struct option_resolver
{
213 /* Update the visibility of the box item of each option
214 * in config_options to honour the value of config.show_template. */
215 void update_options_visibility(void);
217 /* Toggle the value of the given option numeric, respecting option->min
218 * and option->max. */
219 void toggle_option(struct session
*ses
, struct option
*option
);
221 /* Call the change-hooks for the given option and recur on its parent. */
222 void call_change_hooks(struct session
*ses
, struct option
*current
,
223 struct option
*option
);
225 /* Do proper bookkeeping after an option has changed - call this every time
226 * you change an option value. */
227 void option_changed(struct session
*ses
, struct option
*option
);
229 extern int commit_option_values(struct option_resolver
*resolvers
,
231 union option_value
*values
, int size
);
232 extern void checkout_option_values(struct option_resolver
*resolvers
,
234 union option_value
*values
, int size
);
236 /* Shitload of various incredible macro combinations and other unusable garbage
237 * follows. Have fun. */
239 /* Basically, for main hiearchy addressed from root (almost always) you want to
240 * use get_opt_type() and add_opt_type(). For command line options, you want to
241 * use get_opt_type_tree(cmdline_options, "option", NULL). */
243 extern struct option
*get_opt_rec(struct option
*, const unsigned char *);
244 extern struct option
*get_opt_rec_real(struct option
*, const unsigned char *);
245 struct option
*indirect_option(struct option
*);
247 extern union option_value
*get_opt_(unsigned char *, int, enum option_type
, struct option
*, unsigned char *, struct session
*);
248 #define get_opt(tree, name, ses, type) get_opt_(__FILE__, __LINE__, type, tree, name, ses)
250 extern union option_value
*get_opt_(struct option
*, unsigned char *, struct session
*);
251 #define get_opt(tree, name, ses, type) get_opt_(tree, name, ses)
254 #define get_opt_bool_tree(tree, name, ses) get_opt(tree, name, ses, OPT_BOOL)->number
255 #define get_opt_int_tree(tree, name, ses) get_opt(tree, name, ses, OPT_INT)->number
256 #define get_opt_long_tree(tree, name, ses) get_opt(tree, name, ses, OPT_LONG)->big_number
257 #define get_opt_str_tree(tree, name, ses) get_opt(tree, name, ses, OPT_STRING)->string
258 #define get_opt_codepage_tree(tree, name, ses) get_opt(tree, name, ses, OPT_CODEPAGE)->number
259 #define get_opt_color_tree(tree, name, ses) get_opt(tree, name, ses, OPT_COLOR)->color
260 #define get_opt_tree_tree(tree_, name, ses) get_opt(tree_, name, ses, OPT_TREE)->tree
262 #define get_opt_bool(name, ses) get_opt_bool_tree(config_options, name, ses)
263 #define get_opt_int(name, ses) get_opt_int_tree(config_options, name, ses)
264 #define get_opt_long(name, ses) get_opt_long_tree(config_options, name, ses)
265 #define get_opt_str(name, ses) get_opt_str_tree(config_options, name, ses)
266 #define get_opt_codepage(name, ses) get_opt_codepage_tree(config_options, name, ses)
267 #define get_opt_color(name, ses) get_opt_color_tree(config_options, name, ses)
268 #define get_opt_tree(name, ses) get_opt_tree_tree(config_options, name, ses)
270 #define get_cmd_opt_bool(name) get_opt_bool_tree(cmdline_options, name, NULL)
271 #define get_cmd_opt_int(name) get_opt_int_tree(cmdline_options, name, NULL)
272 #define get_cmd_opt_long(name) get_opt_long_tree(cmdline_options, name, NULL)
273 #define get_cmd_opt_str(name) get_opt_str_tree(cmdline_options, name, NULL)
274 #define get_cmd_opt_codepage(name) get_opt_codepage_tree(cmdline_options, name, NULL)
275 #define get_cmd_opt_color(name) get_opt_color_tree(cmdline_options, name, NULL)
276 #define get_cmd_opt_tree(name) get_opt_tree_tree(cmdline_options, name, NULL)
278 extern struct option
*add_opt(struct option
*, unsigned char *, unsigned char *,
279 unsigned char *, enum option_flags
, enum option_type
,
280 long, long, longptr_T
, unsigned char *);
282 /* Hack which permit to disable option descriptions, to reduce elinks binary size.
283 * It may of some use for people wanting a very small static non-i18n elinks binary,
284 * at time of writing gain is over 25Kbytes. --Zas */
288 #define DESC(x) ((unsigned char *) "")
292 #define add_opt_bool_tree(tree, path, capt, name, flags, def, desc) \
293 add_opt(tree, path, capt, name, flags, OPT_BOOL, 0, 1, (longptr_T) def, DESC(desc))
295 #define add_opt_int_tree(tree, path, capt, name, flags, min, max, def, desc) \
296 add_opt(tree, path, capt, name, flags, OPT_INT, min, max, (longptr_T) def, DESC(desc))
298 #define add_opt_long_tree(tree, path, capt, name, flags, min, max, def, desc) \
299 add_opt(tree, path, capt, name, flags, OPT_LONG, min, max, (longptr_T) def, DESC(desc))
301 #define add_opt_str_tree(tree, path, capt, name, flags, def, desc) \
303 unsigned char *ptr = mem_alloc(MAX_STR_LEN); \
304 safe_strncpy(ptr, def, MAX_STR_LEN); \
305 add_opt(tree, path, capt, name, flags, OPT_STRING, 0, MAX_STR_LEN, (longptr_T) ptr, DESC(desc)); \
308 #define add_opt_codepage_tree(tree, path, capt, name, flags, def, desc) \
309 add_opt(tree, path, capt, name, flags, OPT_CODEPAGE, 0, 0, (longptr_T) get_cp_index(def), DESC(desc))
311 #define add_opt_lang_tree(tree, path, capt, name, flags, desc) \
312 add_opt(tree, path, capt, name, flags, OPT_LANGUAGE, 0, 0, (longptr_T) 0, DESC(desc))
314 #define add_opt_color_tree(tree, path, capt, name, flags, def, desc) \
315 add_opt(tree, path, capt, name, flags, OPT_COLOR, 0, 0, (longptr_T) def, DESC(desc))
317 #define add_opt_command_tree(tree, path, capt, name, flags, cmd, desc) \
318 add_opt(tree, path, capt, name, flags, OPT_COMMAND, 0, 0, (longptr_T) cmd, DESC(desc));
320 #define add_opt_alias_tree(tree, path, capt, name, flags, def, desc) \
321 add_opt(tree, path, capt, name, flags, OPT_ALIAS, 0, strlen(def), (longptr_T) def, DESC(desc))
323 #define add_opt_tree_tree(tree, path, capt, name, flags, desc) \
324 add_opt(tree, path, capt, name, flags, OPT_TREE, 0, 0, (longptr_T) init_options_tree(), DESC(desc));
327 /* Builtin options */
330 struct option option
;
334 extern void register_options(struct option_info info
[], struct option
*tree
);
335 extern void unregister_options(struct option_info info
[], struct option
*tree
);
337 #define NULL_OPTION_INFO \
338 { INIT_OPTION(NULL, 0, 0, 0, 0, NULL, NULL, NULL), NULL }
340 #define INIT_OPT_BOOL(path, capt, name, flags, def, desc) \
341 { INIT_OPTION(name, flags, OPT_BOOL, 0, 1, def, DESC(desc), capt), path }
343 #define INIT_OPT_INT(path, capt, name, flags, min, max, def, desc) \
344 { INIT_OPTION(name, flags, OPT_INT, min, max, def, DESC(desc), capt), path }
346 #define INIT_OPT_LONG(path, capt, name, flags, min, max, def, desc) \
347 { INIT_OPTION(name, flags, OPT_LONG, min, max, def, DESC(desc), capt), path }
349 #define INIT_OPT_STRING(path, capt, name, flags, def, desc) \
350 { INIT_OPTION(name, flags, OPT_STRING, 0, MAX_STR_LEN, def, DESC(desc), capt), path }
352 #define INIT_OPT_CODEPAGE(path, capt, name, flags, def, desc) \
353 { INIT_OPTION(name, flags, OPT_CODEPAGE, 0, 0, def, DESC(desc), capt), path }
355 #define INIT_OPT_COLOR(path, capt, name, flags, def, desc) \
356 { INIT_OPTION(name, flags, OPT_COLOR, 0, 0, def, DESC(desc), capt), path }
358 #define INIT_OPT_LANGUAGE(path, capt, name, flags, desc) \
359 { INIT_OPTION(name, flags, OPT_LANGUAGE, 0, 0, 0, DESC(desc), capt), path }
361 #define INIT_OPT_COMMAND(path, capt, name, flags, cmd, desc) \
362 { INIT_OPTION(name, flags, OPT_COMMAND, 0, 0, cmd, DESC(desc), capt), path }
364 #define INIT_OPT_CMDALIAS(path, capt, name, flags, def, desc) \
365 { INIT_OPTION(name, flags, OPT_ALIAS, 0, sizeof(def) - 1, def, DESC(desc), capt), path }
367 #define INIT_OPT_ALIAS(path, name, flags, def) \
368 { INIT_OPTION(name, flags, OPT_ALIAS, 0, sizeof(def) - 1, def, NULL, NULL), path }
370 #define INIT_OPT_TREE(path, capt, name, flags, desc) \
371 { INIT_OPTION(name, flags, OPT_TREE, 0, 0, NULL, DESC(desc), capt), path }
374 /* TODO: We need to do *something* with this ;). */