diff options
Diffstat (limited to 'apps/gui/option_select.c')
-rw-r--r-- | apps/gui/option_select.c | 487 |
1 files changed, 486 insertions, 1 deletions
diff --git a/apps/gui/option_select.c b/apps/gui/option_select.c index 0098cf198f..7d74e202be 100644 --- a/apps/gui/option_select.c +++ b/apps/gui/option_select.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2005 by Kevin Ferrare | 10 | * Copyright (C) 2005 by Kevin Ferrare |
11 | * Copyright (C) 2007 by Jonathan Gordon | ||
11 | * | 12 | * |
12 | * All files in this archive are subject to the GNU General Public License. | 13 | * All files in this archive are subject to the GNU General Public License. |
13 | * See the file COPYING in the source tree root for full license agreement. | 14 | * See the file COPYING in the source tree root for full license agreement. |
@@ -16,12 +17,496 @@ | |||
16 | * KIND, either express or implied. | 17 | * KIND, either express or implied. |
17 | * | 18 | * |
18 | ****************************************************************************/ | 19 | ****************************************************************************/ |
19 | 20 | #include <stdlib.h> | |
21 | #include "config.h" | ||
20 | #include "option_select.h" | 22 | #include "option_select.h" |
21 | #include "sprintf.h" | 23 | #include "sprintf.h" |
22 | #include "kernel.h" | 24 | #include "kernel.h" |
23 | #include "lang.h" | 25 | #include "lang.h" |
26 | #include "talk.h" | ||
27 | #include "settings_list.h" | ||
28 | #include "sound.h" | ||
29 | #include "list.h" | ||
30 | #include "action.h" | ||
31 | #include "statusbar.h" | ||
32 | #include "misc.h" | ||
33 | #include "splash.h" | ||
34 | |||
35 | static const char *unit_strings[] = | ||
36 | { | ||
37 | [UNIT_INT] = "", [UNIT_MS] = "ms", | ||
38 | [UNIT_SEC] = "s", [UNIT_MIN] = "min", | ||
39 | [UNIT_HOUR]= "hr", [UNIT_KHZ] = "KHz", | ||
40 | [UNIT_DB] = "dB", [UNIT_PERCENT] = "%", | ||
41 | [UNIT_MAH] = "mAh", [UNIT_PIXEL] = "px", | ||
42 | [UNIT_PER_SEC] = "per sec", | ||
43 | [UNIT_HERTZ] = "Hz", | ||
44 | [UNIT_MB] = "MB", [UNIT_KBIT] = "kb/s", | ||
45 | }; | ||
46 | |||
47 | char *option_get_valuestring(struct settings_list *setting, | ||
48 | char *buffer, int buf_len, | ||
49 | intptr_t temp_var) | ||
50 | { | ||
51 | if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) | ||
52 | { | ||
53 | bool val = (bool)temp_var; | ||
54 | snprintf(buffer, buf_len, "%s", | ||
55 | str(val? setting->bool_setting->lang_yes : | ||
56 | setting->bool_setting->lang_no)); | ||
57 | } | ||
58 | #if 0 /* probably dont need this one */ | ||
59 | else if ((setting->flags & F_FILENAME) == F_FILENAME) | ||
60 | { | ||
61 | struct filename_setting *info = setting->filename_setting; | ||
62 | snprintf(buffer, buf_len, "%s%s%s", info->prefix, | ||
63 | (char*)temp_var, info->suffix); | ||
64 | } | ||
65 | #endif | ||
66 | else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) | ||
67 | { | ||
68 | struct int_setting *info = setting->int_setting; | ||
69 | if (info->formatter) | ||
70 | info->formatter(buffer, buf_len, (int)temp_var, | ||
71 | unit_strings[info->unit]); | ||
72 | else | ||
73 | snprintf(buffer, buf_len, "%d %s", (int)temp_var, | ||
74 | unit_strings[info->unit]? | ||
75 | unit_strings[info->unit]:""); | ||
76 | } | ||
77 | else if ((setting->flags & F_T_SOUND) == F_T_SOUND) | ||
78 | { | ||
79 | char sign = ' ', *unit; | ||
80 | unit = (char*)sound_unit(setting->sound_setting->setting); | ||
81 | if (sound_numdecimals(setting->sound_setting->setting)) | ||
82 | { | ||
83 | int integer, dec; | ||
84 | int val = sound_val2phys(setting->sound_setting->setting, | ||
85 | (int)temp_var); | ||
86 | if(val < 0) | ||
87 | { | ||
88 | sign = '-'; | ||
89 | val = abs(val); | ||
90 | } | ||
91 | integer = val / 10; dec = val % 10; | ||
92 | snprintf(buffer, buf_len, "%c%d.%d %s", sign, integer, dec, unit); | ||
93 | } | ||
94 | else | ||
95 | snprintf(buffer, buf_len, "%d %s", (int)temp_var, unit); | ||
96 | } | ||
97 | else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) | ||
98 | { | ||
99 | if (setting->flags & F_CHOICETALKS) | ||
100 | { | ||
101 | int setting_id; | ||
102 | find_setting(setting->setting, &setting_id); | ||
103 | cfg_int_to_string(setting_id, (int)temp_var, buffer, buf_len); | ||
104 | } | ||
105 | else | ||
106 | { | ||
107 | int value= (int)temp_var; | ||
108 | char *val = P2STR(setting->choice_setting->desc[value]); | ||
109 | snprintf(buffer, buf_len, "%s", val); | ||
110 | } | ||
111 | } | ||
112 | return buffer; | ||
113 | } | ||
114 | |||
115 | void option_talk(struct settings_list *setting, int temp_var) | ||
116 | { | ||
117 | if (!talk_menus_enabled()) | ||
118 | return; | ||
119 | if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) | ||
120 | { | ||
121 | bool val = temp_var==1?true:false; | ||
122 | talk_id(val? setting->bool_setting->lang_yes : | ||
123 | setting->bool_setting->lang_no, false); | ||
124 | } | ||
125 | #if 0 /* probably dont need this one */ | ||
126 | else if ((setting->flags & F_FILENAME) == F_FILENAME) | ||
127 | { | ||
128 | } | ||
129 | #endif | ||
130 | else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) | ||
131 | { | ||
132 | struct int_setting *info = setting->int_setting; | ||
133 | if (info->get_talk_id) | ||
134 | talk_id(info->get_talk_id((int)temp_var), false); | ||
135 | else | ||
136 | talk_value((int)temp_var, info->unit, false); | ||
137 | } | ||
138 | else if ((setting->flags & F_T_SOUND) == F_T_SOUND) | ||
139 | { | ||
140 | int talkunit = UNIT_DB; | ||
141 | const char *unit = sound_unit(setting->sound_setting->setting); | ||
142 | /* crude reconstruction */ | ||
143 | if (*unit == '%') | ||
144 | talkunit = UNIT_PERCENT; | ||
145 | else if (*unit == 'H') | ||
146 | talkunit = UNIT_HERTZ; | ||
147 | talk_value((int)temp_var, talkunit, false); | ||
148 | } | ||
149 | else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) | ||
150 | { | ||
151 | int value = (int)temp_var; | ||
152 | if (setting->flags & F_CHOICETALKS) | ||
153 | { | ||
154 | talk_id(setting->choice_setting->talks[value], false); | ||
155 | } | ||
156 | else | ||
157 | { | ||
158 | talk_id(P2ID(setting->choice_setting->desc[value]), false); | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | #if 0 | ||
163 | int option_select_next_val(struct settings_list *setting, | ||
164 | intptr_t temp_var) | ||
165 | { | ||
166 | int val = 0; | ||
167 | if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) | ||
168 | { | ||
169 | val = (bool)temp_var ? 0 : 1; | ||
170 | } | ||
171 | else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) | ||
172 | { | ||
173 | struct int_setting *info = setting->int_setting; | ||
174 | val = (int)temp_var + info->step; | ||
175 | if (val > info->max) | ||
176 | val = info->min; | ||
177 | } | ||
178 | else if ((setting->flags & F_T_SOUND) == F_T_SOUND) | ||
179 | { | ||
180 | int setting_id = setting->sound_setting->setting; | ||
181 | int steps = sound_steps(setting_id); | ||
182 | int min = sound_min(setting_id); | ||
183 | int max = sound_max(setting_id); | ||
184 | val = (int)temp_var + steps; | ||
185 | if (val > max) | ||
186 | val = min; | ||
187 | } | ||
188 | else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) | ||
189 | { | ||
190 | struct choice_setting *info = setting->choice_setting; | ||
191 | val = (int)temp_var; | ||
192 | if (val > info->count) | ||
193 | val = 0; | ||
194 | } | ||
195 | return val; | ||
196 | } | ||
197 | |||
198 | int option_select_prev_val(struct settings_list *setting, | ||
199 | intptr_t temp_var) | ||
200 | { | ||
201 | int val = 0; | ||
202 | if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) | ||
203 | { | ||
204 | val = (bool)temp_var ? 0 : 1; | ||
205 | } | ||
206 | else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) | ||
207 | { | ||
208 | struct int_setting *info = setting->int_setting; | ||
209 | val = (int)temp_var - info->step; | ||
210 | if (val < info->min) | ||
211 | val = info->max; | ||
212 | } | ||
213 | else if ((setting->flags & F_T_SOUND) == F_T_SOUND) | ||
214 | { | ||
215 | int setting_id = setting->sound_setting->setting; | ||
216 | int steps = sound_steps(setting_id); | ||
217 | int min = sound_min(setting_id); | ||
218 | int max = sound_max(setting_id); | ||
219 | val = (int)temp_var -+ steps; | ||
220 | if (val < min) | ||
221 | val = max; | ||
222 | } | ||
223 | else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) | ||
224 | { | ||
225 | struct choice_setting *info = setting->choice_setting; | ||
226 | val = (int)temp_var; | ||
227 | if (val < 0) | ||
228 | val = info->count - 1; | ||
229 | } | ||
230 | return val; | ||
231 | } | ||
232 | #endif | ||
233 | |||
234 | static int selection_to_val(struct settings_list *setting, int selection) | ||
235 | { | ||
236 | int min = 0, max = 0, step = 1; | ||
237 | if (((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) || | ||
238 | ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING)) | ||
239 | return selection; | ||
240 | else if ((setting->flags & F_T_SOUND) == F_T_SOUND) | ||
241 | { | ||
242 | int setting_id = setting->sound_setting->setting; | ||
243 | step = sound_steps(setting_id); | ||
244 | max = sound_max(setting_id); | ||
245 | min = sound_min(setting_id); | ||
246 | } | ||
247 | else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) | ||
248 | { | ||
249 | struct int_setting *info = setting->int_setting; | ||
250 | min = info->min; | ||
251 | max = info->max; | ||
252 | step = info->step; | ||
253 | } | ||
254 | if (setting->flags & F_FLIPLIST) | ||
255 | { | ||
256 | int a; | ||
257 | a = min; min = max; max = a; | ||
258 | step = -step; | ||
259 | } | ||
260 | return max- (selection * step); | ||
261 | } | ||
262 | static char * value_setting_get_name_cb(int selected_item, | ||
263 | void * data, char *buffer) | ||
264 | { | ||
265 | selected_item = selection_to_val(data, selected_item); | ||
266 | return option_get_valuestring(data, buffer, MAX_PATH, selected_item); | ||
267 | } | ||
268 | |||
269 | /* wrapper to convert from int param to bool param in option_screen */ | ||
270 | static void (*boolfunction)(bool); | ||
271 | static void bool_funcwrapper(int value) | ||
272 | { | ||
273 | if (value) | ||
274 | boolfunction(true); | ||
275 | else | ||
276 | boolfunction(false); | ||
277 | } | ||
278 | |||
279 | bool option_screen(struct settings_list *setting, bool use_temp_var) | ||
280 | { | ||
281 | int action; | ||
282 | bool done = false; | ||
283 | struct gui_synclist lists; | ||
284 | int oldvalue, nb_items = 0, selected = 0, temp_var; | ||
285 | int *variable; | ||
286 | bool allow_wrap = ((int*)setting->setting != &global_settings.volume); | ||
287 | int var_type = setting->flags&F_T_MASK; | ||
288 | void (*function)(int) = NULL; | ||
289 | |||
290 | if (var_type == F_T_INT || var_type == F_T_UINT) | ||
291 | { | ||
292 | variable = use_temp_var ? &temp_var: (int*)setting->setting; | ||
293 | temp_var = oldvalue = *(int*)setting->setting; | ||
294 | } | ||
295 | else if (var_type == F_T_BOOL) | ||
296 | { | ||
297 | /* bools always use the temp variable... | ||
298 | if use_temp_var is false it will be copied to setting->setting every change */ | ||
299 | variable = &temp_var; | ||
300 | temp_var = oldvalue = *(bool*)setting->setting?1:0; | ||
301 | } | ||
302 | else return false; /* only int/bools can go here */ | ||
303 | gui_synclist_init(&lists, value_setting_get_name_cb, | ||
304 | (void*)setting, false, 1); | ||
305 | if (setting->lang_id == -1) | ||
306 | gui_synclist_set_title(&lists, | ||
307 | (char*)setting->cfg_vals, Icon_Questionmark); | ||
308 | else | ||
309 | gui_synclist_set_title(&lists, | ||
310 | str(setting->lang_id), Icon_Questionmark); | ||
311 | gui_synclist_set_icon_callback(&lists, NULL); | ||
312 | |||
313 | /* set the number of items and current selection */ | ||
314 | if (var_type == F_T_INT || var_type == F_T_UINT) | ||
315 | { | ||
316 | if (setting->flags&F_CHOICE_SETTING) | ||
317 | { | ||
318 | nb_items = setting->choice_setting->count; | ||
319 | selected = oldvalue; | ||
320 | function = setting->choice_setting->option_callback; | ||
321 | } | ||
322 | else if (setting->flags&F_T_SOUND) | ||
323 | { | ||
324 | int setting_id = setting->sound_setting->setting; | ||
325 | int steps = sound_steps(setting_id); | ||
326 | int min = sound_min(setting_id); | ||
327 | int max = sound_max(setting_id); | ||
328 | nb_items = (max-min)/steps + 1; | ||
329 | selected = (max-oldvalue)/steps; | ||
330 | function = sound_get_fn(setting_id); | ||
331 | } | ||
332 | else | ||
333 | { | ||
334 | struct int_setting *info = setting->int_setting; | ||
335 | int min, max, step; | ||
336 | if (setting->flags&F_FLIPLIST) | ||
337 | { | ||
338 | min = info->max; | ||
339 | max = info->min; | ||
340 | step = -info->step; | ||
341 | } | ||
342 | else | ||
343 | { | ||
344 | max = info->max; | ||
345 | min = info->min; | ||
346 | step = info->step; | ||
347 | } | ||
348 | nb_items = (max-min)/step + 1; | ||
349 | selected = (max - oldvalue)/step; | ||
350 | function = info->option_callback; | ||
351 | } | ||
352 | } | ||
353 | else if (var_type == F_T_BOOL) | ||
354 | { | ||
355 | selected = oldvalue; | ||
356 | nb_items = 2; | ||
357 | boolfunction = setting->bool_setting->option_callback; | ||
358 | if (boolfunction) | ||
359 | function = bool_funcwrapper; | ||
360 | } | ||
361 | |||
362 | gui_synclist_set_nb_items(&lists, nb_items); | ||
363 | gui_synclist_select_item(&lists, selected); | ||
364 | |||
365 | gui_synclist_limit_scroll(&lists, true); | ||
366 | gui_synclist_draw(&lists); | ||
367 | action_signalscreenchange(); | ||
368 | /* talk the item */ | ||
369 | option_talk(setting, *variable); | ||
370 | while (!done) | ||
371 | { | ||
372 | action = get_action(CONTEXT_LIST, TIMEOUT_BLOCK); | ||
373 | if (action == ACTION_NONE) | ||
374 | continue; | ||
375 | if (gui_synclist_do_button(&lists,action, | ||
376 | allow_wrap? LIST_WRAP_UNLESS_HELD: LIST_WRAP_OFF)) | ||
377 | { | ||
378 | selected = gui_synclist_get_sel_pos(&lists); | ||
379 | *variable = selection_to_val(setting, selected); | ||
380 | if (var_type == F_T_BOOL) | ||
381 | { | ||
382 | if (!use_temp_var) | ||
383 | *(bool*)setting->setting = selected==1?true:false; | ||
384 | } | ||
385 | /* talk */ | ||
386 | option_talk(setting, *variable); | ||
387 | } | ||
388 | else if (action == ACTION_STD_CANCEL) | ||
389 | { | ||
390 | bool show_cancel = false; | ||
391 | if (use_temp_var) | ||
392 | show_cancel = true; | ||
393 | else if (var_type == F_T_INT || var_type == F_T_UINT) | ||
394 | { | ||
395 | if (*variable != oldvalue) | ||
396 | { | ||
397 | show_cancel = true; | ||
398 | *variable = oldvalue; | ||
399 | } | ||
400 | } | ||
401 | else | ||
402 | { | ||
403 | if (*variable != oldvalue) | ||
404 | { | ||
405 | show_cancel = true; | ||
406 | if (!use_temp_var) | ||
407 | *(bool*)setting->setting = oldvalue==1?true:false; | ||
408 | *variable = oldvalue; | ||
409 | } | ||
410 | } | ||
411 | if (show_cancel) | ||
412 | gui_syncsplash(HZ/2, str(LANG_MENU_SETTING_CANCEL)); | ||
413 | done = true; | ||
414 | } | ||
415 | else if (action == ACTION_STD_OK) | ||
416 | { | ||
417 | done = true; | ||
418 | } | ||
419 | else if(default_event_handler(action) == SYS_USB_CONNECTED) | ||
420 | return true; | ||
421 | gui_syncstatusbar_draw(&statusbars, false); | ||
422 | /* callback */ | ||
423 | if ( function ) | ||
424 | function(*variable); | ||
425 | } | ||
426 | |||
427 | if (use_temp_var) | ||
428 | { | ||
429 | if (var_type == F_T_INT || var_type == F_T_UINT) | ||
430 | { | ||
431 | if (oldvalue != *variable) | ||
432 | { | ||
433 | *(int*)setting->setting = *variable; | ||
434 | settings_save(); | ||
435 | } | ||
436 | } | ||
437 | else if (oldvalue != *variable) | ||
438 | { | ||
439 | *(bool*)setting->setting = *variable?true:false; | ||
440 | settings_save(); | ||
441 | } | ||
442 | } | ||
443 | |||
444 | action_signalscreenchange(); | ||
445 | return false; | ||
446 | } | ||
447 | |||
448 | /****************************************************** | ||
449 | Compatability functions | ||
450 | *******************************************************/ | ||
451 | #define MAX_OPTIONS 32 | ||
452 | bool set_option(const char* string, void* variable, enum optiontype type, | ||
453 | const struct opt_items* options, | ||
454 | int numoptions, void (*function)(int)) | ||
455 | { | ||
456 | int temp; | ||
457 | char *strings[MAX_OPTIONS]; | ||
458 | struct choice_setting data; | ||
459 | struct settings_list item; | ||
460 | for (temp=0; temp<MAX_OPTIONS && temp<numoptions; temp++) | ||
461 | strings[temp] = (char*)options[temp].string; | ||
462 | if (type == BOOL) | ||
463 | { | ||
464 | temp = *(bool*)variable? 1: 0; | ||
465 | item.setting = &temp; | ||
466 | } | ||
467 | else | ||
468 | item.setting = variable; | ||
469 | item.flags = F_CHOICE_SETTING|F_T_INT; | ||
470 | item.lang_id = -1; | ||
471 | item.cfg_vals = (char*)string; | ||
472 | data.count = numoptions<MAX_OPTIONS ? numoptions: MAX_OPTIONS; | ||
473 | data.desc = (void*)strings; /* shutup gcc... */ | ||
474 | data.option_callback = function; | ||
475 | item.choice_setting = &data; | ||
476 | option_screen(&item, false); | ||
477 | if (type == BOOL) | ||
478 | { | ||
479 | *(bool*)variable = (temp == 1? true: false); | ||
480 | } | ||
481 | return false; | ||
482 | } | ||
483 | |||
484 | bool set_int_ex(const unsigned char* string, | ||
485 | const char* unit, | ||
486 | int voice_unit, | ||
487 | int* variable, | ||
488 | void (*function)(int), | ||
489 | int step, | ||
490 | int min, | ||
491 | int max, | ||
492 | void (*formatter)(char*, int, int, const char*), | ||
493 | long (*get_talk_id)(int)) | ||
494 | { | ||
495 | (void)unit; | ||
496 | struct settings_list item; | ||
497 | struct int_setting data = { | ||
498 | function, voice_unit, min, max, step, | ||
499 | formatter, get_talk_id | ||
500 | }; | ||
501 | item.int_setting = &data; | ||
502 | item.flags = F_INT_SETTING|F_T_INT; | ||
503 | item.lang_id = -1; | ||
504 | item.cfg_vals = (char*)string; | ||
505 | item.setting = variable; | ||
506 | return option_screen(&item, false); | ||
507 | } | ||
24 | 508 | ||
509 | /* to be replaced */ | ||
25 | void option_select_init_items(struct option_select * opt, | 510 | void option_select_init_items(struct option_select * opt, |
26 | const char * title, | 511 | const char * title, |
27 | int selected, | 512 | int selected, |