iconv: Bail out of the loop when an illegal sequence of bytes occurs.
[elinks/elinks-j605.git] / src / dialogs / options.c
blob0f59843e35cef39e4d96d60502dc3120de820f15
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,
94 TERM_OPT_ITALIC,
95 #ifdef CONFIG_COMBINE
96 TERM_OPT_COMBINE,
97 #endif
99 TERM_OPTIONS,
102 static struct option_resolver resolvers[] = {
103 { TERM_OPT_TYPE, "type" },
104 { TERM_OPT_M11_HACK, "m11_hack" },
105 { TERM_OPT_RESTRICT_852, "restrict_852" },
106 { TERM_OPT_BLOCK_CURSOR, "block_cursor" },
107 { TERM_OPT_COLORS, "colors" },
108 { TERM_OPT_TRANSPARENCY, "transparency" },
109 { TERM_OPT_UTF_8_IO, "utf_8_io" },
110 { TERM_OPT_UNDERLINE, "underline" },
111 { TERM_OPT_ITALIC, "italic" },
112 #ifdef CONFIG_COMBINE
113 { TERM_OPT_COMBINE, "combine" },
114 #endif
117 static widget_handler_status_T
118 push_ok_button(struct dialog_data *dlg_data, struct widget_data *button)
120 struct terminal *term = dlg_data->win->term;
121 union option_value *values = dlg_data->dlg->udata;
123 update_dialog_data(dlg_data);
125 commit_option_values(resolvers, term->spec, values, TERM_OPTIONS);
127 if (button->widget->handler == push_ok_button)
128 return cancel_dialog(dlg_data, button);
130 return EVENT_PROCESSED;
133 static widget_handler_status_T
134 push_save_button(struct dialog_data *dlg_data, struct widget_data *button)
136 push_ok_button(dlg_data, button);
137 write_config(dlg_data->win->term);
139 return EVENT_PROCESSED;
142 #if defined(CONFIG_88_COLORS)
143 #define RADIO_88 1
144 #else
145 #define RADIO_88 0
146 #endif
148 #if defined(CONFIG_256_COLORS)
149 #define RADIO_256 1
150 #else
151 #define RADIO_256 0
152 #endif
154 #if defined(CONFIG_TRUE_COLOR)
155 #define RADIO_TRUE 1
156 #else
157 #define RADIO_TRUE 0
158 #endif
160 #define TERMOPT_WIDGETS_COUNT (12 + TERM_OPTIONS + RADIO_88 + RADIO_256 + RADIO_TRUE)
162 #define TERM_OPTION_VALUE_SIZE (sizeof(union option_value) * TERM_OPTIONS)
164 void
165 terminal_options(struct terminal *term, void *xxx, struct session *ses)
167 /* [gettext_accelerator_context(terminal_options)] */
168 struct dialog *dlg;
169 union option_value *values;
170 int anonymous = get_cmd_opt_bool("anonymous");
171 unsigned char help_text[MAX_STR_LEN], *text;
172 size_t help_textlen = 0;
173 size_t add_size = TERM_OPTION_VALUE_SIZE;
175 snprintf(help_text, sizeof(help_text) - 3 /* 2 '\n' + 1 '\0' */,
176 _("The environmental variable TERM is set to '%s'.\n"
177 "\n"
178 "ELinks maintains separate sets of values for these options\n"
179 "and chooses the appropriate set based on the value of TERM.\n"
180 "This allows you to configure the settings appropriately for\n"
181 "each terminal in which you run ELinks.", term),
182 term->spec->name);
184 help_textlen = strlen(help_text);
186 /* Two newlines are needed to get a blank line between the help text and
187 * the first group of widgets. */
188 help_text[help_textlen++] = '\n';
189 help_text[help_textlen++] = '\n';
191 help_text[help_textlen++] = '\0';
193 add_size += help_textlen;
195 dlg = calloc_dialog(TERMOPT_WIDGETS_COUNT, add_size);
196 if (!dlg) return;
198 values = (union option_value *) get_dialog_offset(dlg, TERMOPT_WIDGETS_COUNT);
199 checkout_option_values(resolvers, term->spec, values, TERM_OPTIONS);
201 dlg->title = _("Terminal options", term);
202 dlg->layouter = generic_dialog_layouter;
203 dlg->layout.padding_top = 1;
204 dlg->udata = values;
206 text = ((unsigned char *) values) + TERM_OPTION_VALUE_SIZE;
207 memcpy(text, help_text, help_textlen);
208 add_dlg_text(dlg, text, ALIGN_LEFT, 1);
210 add_dlg_text(dlg, _("Frame handling:", term), ALIGN_LEFT, 1);
211 add_dlg_radio(dlg, _("No frames", term), 1, TERM_DUMB, &values[TERM_OPT_TYPE].number);
212 add_dlg_radio(dlg, _("VT 100 frames", term), 1, TERM_VT100, &values[TERM_OPT_TYPE].number);
213 add_dlg_radio(dlg, _("Linux or OS/2 frames", term), 1, TERM_LINUX, &values[TERM_OPT_TYPE].number);
214 add_dlg_radio(dlg, _("Linux frames with fbterm colors", term), 1, TERM_FBTERM, &values[TERM_OPT_TYPE].number);
215 add_dlg_radio(dlg, _("FreeBSD frames", term), 1, TERM_FREEBSD, &values[TERM_OPT_TYPE].number);
216 add_dlg_radio(dlg, _("KOI8-R frames", term), 1, TERM_KOI8, &values[TERM_OPT_TYPE].number);
218 add_dlg_text(dlg, _("Color mode:", term), ALIGN_LEFT, 1);
219 add_dlg_radio(dlg, _("No colors (mono)", term), 2, COLOR_MODE_MONO, &values[TERM_OPT_COLORS].number);
220 add_dlg_radio(dlg, _("16 colors", term), 2, COLOR_MODE_16, &values[TERM_OPT_COLORS].number);
221 #ifdef CONFIG_88_COLORS
222 add_dlg_radio(dlg, _("88 colors", term), 2, COLOR_MODE_88, &values[TERM_OPT_COLORS].number);
223 #endif
224 #ifdef CONFIG_256_COLORS
225 add_dlg_radio(dlg, _("256 colors", term), 2, COLOR_MODE_256, &values[TERM_OPT_COLORS].number);
226 #endif
227 #ifdef CONFIG_TRUE_COLOR
228 add_dlg_radio(dlg, _("true color", term), 2, COLOR_MODE_TRUE_COLOR, &values[TERM_OPT_COLORS].number);
229 #endif
230 add_dlg_checkbox(dlg, _("Switch fonts for line drawing", term), &values[TERM_OPT_M11_HACK].number);
231 add_dlg_checkbox(dlg, _("Restrict frames in cp850/852", term), &values[TERM_OPT_RESTRICT_852].number);
232 add_dlg_checkbox(dlg, _("Block cursor", term), &values[TERM_OPT_BLOCK_CURSOR].number);
233 add_dlg_checkbox(dlg, _("Italic", term), &values[TERM_OPT_ITALIC].number);
234 add_dlg_checkbox(dlg, _("Transparency", term), &values[TERM_OPT_TRANSPARENCY].number);
235 add_dlg_checkbox(dlg, _("Underline", term), &values[TERM_OPT_UNDERLINE].number);
236 add_dlg_checkbox(dlg, _("UTF-8 I/O", term), &values[TERM_OPT_UTF_8_IO].number);
237 #ifdef CONFIG_COMBINE
238 add_dlg_checkbox(dlg, _("Combining characters", term), &values[TERM_OPT_COMBINE].number);
239 #endif
241 add_dlg_button(dlg, _("~OK", term), B_ENTER, push_ok_button, NULL);
242 if (!anonymous)
243 add_dlg_button(dlg, _("Sa~ve", term), B_ENTER, push_save_button, NULL);
244 add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL);
246 add_dlg_end(dlg, TERMOPT_WIDGETS_COUNT - anonymous);
248 do_dialog(term, dlg, getml(dlg, (void *) NULL));
251 #ifdef CONFIG_NLS
252 static void
253 menu_set_language(struct terminal *term, void *pcp_, void *xxx)
255 int pcp = (long) pcp_;
257 set_language(pcp);
258 cls_redraw_all_terminals();
260 #endif
262 void
263 menu_language_list(struct terminal *term, void *xxx, void *ses)
265 #ifdef CONFIG_NLS
266 int i;
267 struct menu_item *mi = new_menu(FREE_LIST);
269 if (!mi) return;
270 for (i = 0; languages[i].name; i++) {
271 add_to_menu(&mi, languages[i].name, language_to_iso639(i), ACT_MAIN_NONE,
272 menu_set_language, (void *) (long) i, 0);
275 do_menu_selected(term, mi, ses, current_language, 0);
276 #endif
280 /* FIXME: This doesn't in fact belong here at all. --pasky */
282 static unsigned char width_str[4];
283 static unsigned char height_str[4];
285 static void
286 push_resize_button(void *data)
288 struct terminal *term = data;
289 unsigned char str[MAX_STR_LEN];
291 snprintf(str, sizeof(str), "%s,%s,%d,%d",
292 width_str, height_str, term->width, term->height);
294 do_terminal_function(term, TERM_FN_RESIZE, str);
297 /* menu_func_T */
298 void
299 resize_terminal_dialog(struct terminal *term)
301 /* [gettext_accelerator_context(resize_terminal_dialog)] */
302 struct dialog *dlg;
303 int width = int_min(term->width, 999);
304 int height = int_min(term->height, 999);
306 if (!can_resize_window(term->environment))
307 return;
309 ulongcat(width_str, NULL, width, 3, ' ');
310 ulongcat(height_str, NULL, height, 3, ' ');
312 #define RESIZE_WIDGETS_COUNT 4
313 dlg = calloc_dialog(RESIZE_WIDGETS_COUNT, 0);
314 if (!dlg) return;
316 dlg->title = _("Resize terminal", term);
317 dlg->layouter = group_layouter;
319 add_dlg_field(dlg, _("Width=",term), 1, 999, check_number, 4, width_str, NULL);
320 add_dlg_field(dlg, _("Height=",term), 1, 999, check_number, 4, height_str, NULL);
322 add_dlg_ok_button(dlg, _("~OK", term), B_ENTER, push_resize_button, term);
323 add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL);
325 add_dlg_end(dlg, RESIZE_WIDGETS_COUNT);
327 do_dialog(term, dlg, getml(dlg, (void *) NULL));