Fix file descriptor leaks if init_file_download fails
[elinks/elinks-j605.git] / src / dialogs / options.c
blobf40d07d663268ac504a0ef79140d51e8d311e313
1 /* Options dialogs */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
11 #include "elinks.h"
13 #include "bfu/dialog.h"
14 #include "bfu/menu.h"
15 #include "config/conf.h"
16 #include "config/options.h"
17 #include "dialogs/options.h"
18 #include "intl/charsets.h"
19 #include "intl/gettext/libintl.h"
20 #include "osdep/osdep.h"
21 #include "session/session.h"
22 #include "terminal/color.h"
23 #include "terminal/terminal.h"
24 #include "util/conv.h"
25 #include "util/memory.h"
26 #include "util/memlist.h"
29 static void
30 display_codepage(struct terminal *term, void *name_, void *xxx)
32 unsigned char *name = name_;
33 struct option *opt = get_opt_rec(term->spec, "charset");
34 int index = get_cp_index(name);
36 assertm(index != -1, "%s", name);
38 if (opt->value.number != index) {
39 opt->value.number = index;
40 option_changed(NULL, opt);
43 cls_redraw_all_terminals();
46 void
47 charset_list(struct terminal *term, void *xxx, void *ses_)
49 struct session *ses = ses_;
50 int i, items;
51 int sel = 0;
52 const unsigned char *const sel_mime = get_cp_mime_name(
53 get_terminal_codepage(term));
54 struct menu_item *mi = new_menu(FREE_LIST);
56 if (!mi) return;
58 for (i = 0, items = 0; ; i++) {
59 unsigned char *name = get_cp_name(i);
61 if (!name) break;
63 #ifndef CONFIG_UTF8
64 if (is_cp_utf8(i)) continue;
65 #endif /* CONFIG_UTF8 */
67 /* Map the "System" codepage to the underlying one.
68 * A pointer comparison might suffice here but this
69 * code is not time-critical. */
70 if (strcmp(sel_mime, get_cp_mime_name(i)) == 0)
71 sel = items;
72 items++;
73 add_to_menu(&mi, name, NULL, ACT_MAIN_NONE,
74 display_codepage, get_cp_config_name(i), 0);
77 do_menu_selected(term, mi, ses, sel, 0);
81 /* TODO: Build this automagically. But that will need gettextted options
82 * captions not to lose translations and so on. 0.5 stuff or even later.
83 * --pasky */
85 enum termopt {
86 TERM_OPT_TYPE = 0,
87 TERM_OPT_M11_HACK,
88 TERM_OPT_RESTRICT_852,
89 TERM_OPT_BLOCK_CURSOR,
90 TERM_OPT_COLORS,
91 TERM_OPT_UTF_8_IO,
92 TERM_OPT_TRANSPARENCY,
93 TERM_OPT_UNDERLINE,
95 TERM_OPTIONS,
98 static struct option_resolver resolvers[] = {
99 { TERM_OPT_TYPE, "type" },
100 { TERM_OPT_M11_HACK, "m11_hack" },
101 { TERM_OPT_RESTRICT_852, "restrict_852" },
102 { TERM_OPT_BLOCK_CURSOR, "block_cursor" },
103 { TERM_OPT_COLORS, "colors" },
104 { TERM_OPT_TRANSPARENCY, "transparency" },
105 { TERM_OPT_UTF_8_IO, "utf_8_io" },
106 { TERM_OPT_UNDERLINE, "underline" },
109 static widget_handler_status_T
110 push_ok_button(struct dialog_data *dlg_data, struct widget_data *button)
112 struct terminal *term = dlg_data->win->term;
113 union option_value *values = dlg_data->dlg->udata;
115 update_dialog_data(dlg_data);
117 commit_option_values(resolvers, term->spec, values, TERM_OPTIONS);
119 if (button->widget->handler == push_ok_button)
120 return cancel_dialog(dlg_data, button);
122 return EVENT_PROCESSED;
125 static widget_handler_status_T
126 push_save_button(struct dialog_data *dlg_data, struct widget_data *button)
128 push_ok_button(dlg_data, button);
129 write_config(dlg_data->win->term);
131 return EVENT_PROCESSED;
134 #if defined(CONFIG_88_COLORS)
135 #define RADIO_88 1
136 #else
137 #define RADIO_88 0
138 #endif
140 #if defined(CONFIG_256_COLORS)
141 #define RADIO_256 1
142 #else
143 #define RADIO_256 0
144 #endif
146 #if defined(CONFIG_TRUE_COLOR)
147 #define RADIO_TRUE 1
148 #else
149 #define RADIO_TRUE 0
150 #endif
152 #define TERMOPT_WIDGETS_COUNT (19 + RADIO_88 + RADIO_256 + RADIO_TRUE)
154 #define TERM_OPTION_VALUE_SIZE (sizeof(union option_value) * TERM_OPTIONS)
156 void
157 terminal_options(struct terminal *term, void *xxx, struct session *ses)
159 /* [gettext_accelerator_context(terminal_options)] */
160 struct dialog *dlg;
161 union option_value *values;
162 int anonymous = get_cmd_opt_bool("anonymous");
163 unsigned char help_text[MAX_STR_LEN], *text;
164 size_t help_textlen = 0;
165 size_t add_size = TERM_OPTION_VALUE_SIZE;
167 /* XXX: we don't display help text when terminal height is too low,
168 * because then user can't change values.
169 * This should be dropped when we'll have scrollable dialog boxes.
170 * --Zas */
171 if (term->height > 30) {
172 snprintf(help_text, sizeof(help_text) - 3 /* 2 '\n' + 1 '\0' */,
173 _("The environmental variable TERM is set to '%s'.\n"
174 "\n"
175 "ELinks maintains separate sets of values for these options\n"
176 "and chooses the appropriate set based on the value of TERM.\n"
177 "This allows you to configure the settings appropriately for\n"
178 "each terminal in which you run ELinks.", term),
179 term->spec->name);
181 help_textlen = strlen(help_text);
183 /* Two newlines are needed to get a blank line between the help text and
184 * the first group of widgets. */
185 help_text[help_textlen++] = '\n';
186 help_text[help_textlen++] = '\n';
189 help_text[help_textlen++] = '\0';
191 add_size += help_textlen;
193 dlg = calloc_dialog(TERMOPT_WIDGETS_COUNT, add_size);
194 if (!dlg) return;
196 values = (union option_value *) get_dialog_offset(dlg, TERMOPT_WIDGETS_COUNT);
197 checkout_option_values(resolvers, term->spec, values, TERM_OPTIONS);
199 dlg->title = _("Terminal options", term);
200 dlg->layouter = generic_dialog_layouter;
201 dlg->layout.padding_top = 1;
202 dlg->udata = values;
204 text = ((unsigned char *) values) + TERM_OPTION_VALUE_SIZE;
205 memcpy(text, help_text, help_textlen);
206 add_dlg_text(dlg, text, ALIGN_LEFT, 1);
208 add_dlg_text(dlg, _("Frame handling:", term), ALIGN_LEFT, 1);
209 add_dlg_radio(dlg, _("No frames", term), 1, TERM_DUMB, &values[TERM_OPT_TYPE].number);
210 add_dlg_radio(dlg, _("VT 100 frames", term), 1, TERM_VT100, &values[TERM_OPT_TYPE].number);
211 add_dlg_radio(dlg, _("Linux or OS/2 frames", term), 1, TERM_LINUX, &values[TERM_OPT_TYPE].number);
212 add_dlg_radio(dlg, _("FreeBSD frames", term), 1, TERM_FREEBSD, &values[TERM_OPT_TYPE].number);
213 add_dlg_radio(dlg, _("KOI8-R frames", term), 1, TERM_KOI8, &values[TERM_OPT_TYPE].number);
215 add_dlg_text(dlg, _("Color mode:", term), ALIGN_LEFT, 1);
216 add_dlg_radio(dlg, _("No colors (mono)", term), 2, COLOR_MODE_MONO, &values[TERM_OPT_COLORS].number);
217 add_dlg_radio(dlg, _("16 colors", term), 2, COLOR_MODE_16, &values[TERM_OPT_COLORS].number);
218 #ifdef CONFIG_88_COLORS
219 add_dlg_radio(dlg, _("88 colors", term), 2, COLOR_MODE_88, &values[TERM_OPT_COLORS].number);
220 #endif
221 #ifdef CONFIG_256_COLORS
222 add_dlg_radio(dlg, _("256 colors", term), 2, COLOR_MODE_256, &values[TERM_OPT_COLORS].number);
223 #endif
224 #ifdef CONFIG_TRUE_COLOR
225 add_dlg_radio(dlg, _("true color", term), 2, COLOR_MODE_TRUE_COLOR, &values[TERM_OPT_COLORS].number);
226 #endif
227 add_dlg_checkbox(dlg, _("Switch fonts for line drawing", term), &values[TERM_OPT_M11_HACK].number);
228 add_dlg_checkbox(dlg, _("Restrict frames in cp850/852", term), &values[TERM_OPT_RESTRICT_852].number);
229 add_dlg_checkbox(dlg, _("Block cursor", term), &values[TERM_OPT_BLOCK_CURSOR].number);
230 add_dlg_checkbox(dlg, _("Transparency", term), &values[TERM_OPT_TRANSPARENCY].number);
231 add_dlg_checkbox(dlg, _("Underline", term), &values[TERM_OPT_UNDERLINE].number);
232 add_dlg_checkbox(dlg, _("UTF-8 I/O", term), &values[TERM_OPT_UTF_8_IO].number);
234 add_dlg_button(dlg, _("~OK", term), B_ENTER, push_ok_button, NULL);
235 if (!anonymous)
236 add_dlg_button(dlg, _("Sa~ve", term), B_ENTER, push_save_button, NULL);
237 add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL);
239 add_dlg_end(dlg, TERMOPT_WIDGETS_COUNT - anonymous);
241 do_dialog(term, dlg, getml(dlg, (void *) NULL));
244 #ifdef CONFIG_NLS
245 static void
246 menu_set_language(struct terminal *term, void *pcp_, void *xxx)
248 int pcp = (long) pcp_;
250 set_language(pcp);
251 cls_redraw_all_terminals();
253 #endif
255 void
256 menu_language_list(struct terminal *term, void *xxx, void *ses)
258 #ifdef CONFIG_NLS
259 int i;
260 struct menu_item *mi = new_menu(FREE_LIST);
262 if (!mi) return;
263 for (i = 0; languages[i].name; i++) {
264 add_to_menu(&mi, languages[i].name, language_to_iso639(i), ACT_MAIN_NONE,
265 menu_set_language, (void *) (long) i, 0);
268 do_menu_selected(term, mi, ses, current_language, 0);
269 #endif
273 /* FIXME: This doesn't in fact belong here at all. --pasky */
275 static unsigned char width_str[4];
276 static unsigned char height_str[4];
278 static void
279 push_resize_button(void *data)
281 struct terminal *term = data;
282 unsigned char str[MAX_STR_LEN];
284 snprintf(str, sizeof(str), "%s,%s,%d,%d",
285 width_str, height_str, term->width, term->height);
287 do_terminal_function(term, TERM_FN_RESIZE, str);
290 /* menu_func_T */
291 void
292 resize_terminal_dialog(struct terminal *term)
294 /* [gettext_accelerator_context(resize_terminal_dialog)] */
295 struct dialog *dlg;
296 int width = int_min(term->width, 999);
297 int height = int_min(term->height, 999);
299 if (!can_resize_window(term->environment))
300 return;
302 ulongcat(width_str, NULL, width, 3, ' ');
303 ulongcat(height_str, NULL, height, 3, ' ');
305 #define RESIZE_WIDGETS_COUNT 4
306 dlg = calloc_dialog(RESIZE_WIDGETS_COUNT, 0);
307 if (!dlg) return;
309 dlg->title = _("Resize terminal", term);
310 dlg->layouter = group_layouter;
312 add_dlg_field(dlg, _("Width=",term), 1, 999, check_number, 4, width_str, NULL);
313 add_dlg_field(dlg, _("Height=",term), 1, 999, check_number, 4, height_str, NULL);
315 add_dlg_ok_button(dlg, _("~OK", term), B_ENTER, push_resize_button, term);
316 add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL);
318 add_dlg_end(dlg, RESIZE_WIDGETS_COUNT);
320 do_dialog(term, dlg, getml(dlg, (void *) NULL));