1 /********************************************************************\
2 * option-util.c -- GNOME<->guile option interface *
3 * Copyright (C) 2000 Dave Peticolas *
4 * Copyright (C) 2017 Aaron Laws *
5 * *
6 * This program is free software; you can redistribute it and/or *
7 * modify it under the terms of the GNU General Public License as *
8 * published by the Free Software Foundation; either version 2 of *
9 * the License, or (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License*
17 * along with this program; if not, contact: *
18 * *
19 * Free Software Foundation Voice: +1-617-542-5942 *
20 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21 * Boston, MA 02110-1301, USA gnu@gnu.org *
22 \********************************************************************/
23
24 #include <config.h>
25
26 #include <glib/gi18n.h>
27 #include <time.h>
28 #include <string.h>
29
30 #include "Account.h"
31 #include "option-util.h"
32 #include "gnc-guile-utils.h"
33 #include "qof.h"
34 #include "swig-runtime.h"
35 #include "guile-mappings.h"
36
37
38 /* TODO:
39
40 - for make-date-option, there seems to be only support for getting,
41 not for setting.
42 */
43
44
45 /****** Structures *************************************************/
46
47 struct gnc_option
48 {
49 /* Handle to the scheme-side option */
50 SCM guile_option;
51
52 /* Flag to indicate change by the UI */
53 gboolean changed;
54
55 /* The widget which is holding this option */
56 gpointer widget;
57
58 /* The option db which holds this option */
59 GNCOptionDB *odb;
60 };
61
62 struct gnc_option_section
63 {
64 char * section_name;
65
66 GSList * options;
67 };
68
69 struct gnc_option_db
70 {
71 SCM guile_options;
72
73 GSList *option_sections;
74
75 gboolean options_dirty;
76
77 GNCOptionDBHandle handle;
78
79 GNCOptionGetUIValue get_ui_value;
80 GNCOptionSetUIValue set_ui_value;
81 GNCOptionSetSelectable set_selectable;
82 };
83
84 typedef struct _Getters Getters;
85 struct _Getters
86 {
87 SCM section;
88 SCM name;
89 SCM type;
90 SCM sort_tag;
91 SCM documentation;
92 SCM getter;
93 SCM setter;
94 SCM default_getter;
95 SCM value_validator;
96 SCM option_data;
97 SCM index_to_name;
98 SCM index_to_value;
99 SCM value_to_index;
100 SCM number_of_indices;
101 SCM option_widget_changed_cb;
102 SCM date_option_subtype;
103 SCM date_option_show_time;
104 SCM date_option_value_type;
105 SCM date_option_value_absolute;
106 SCM date_option_value_relative;
107 SCM plot_size_option_value_type;
108 SCM plot_size_option_value;
109 SCM currency_accounting_option_currency_doc_string;
110 SCM currency_accounting_option_default_currency;
111 SCM currency_accounting_option_policy_doc_string;
112 SCM currency_accounting_option_default_policy;
113 SCM currency_accounting_option_gain_loss_account_doc_string;
114 SCM currency_accounting_option_method;
115 SCM currency_accounting_option_book_currency;
116 SCM currency_accounting_option_selected_default_policy;
117 SCM currency_accounting_option_selected_default_gain_loss_account;
118 };
119
120
121 /****** Globals ****************************************************/
122
123 static Getters getters = {0, 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0, 0
125 };
126
127 /* This static indicates the debugging module this .o belongs to. */
128 static QofLogModule log_module = GNC_MOD_GUI;
129
130 static GHashTable *option_dbs = NULL;
131 static int last_db_handle = 0;
132
133
134 /*******************************************************************/
135 void
gnc_option_set_changed(GNCOption * option,gboolean changed)136 gnc_option_set_changed (GNCOption *option, gboolean changed)
137 {
138 g_return_if_fail (option != NULL);
139 option->changed = changed;
140 }
141
142 gpointer
gnc_option_get_widget(GNCOption * option)143 gnc_option_get_widget (GNCOption *option)
144 {
145 if (!option) return NULL;
146 return option->widget;
147 }
148
149 void
gnc_option_set_widget(GNCOption * option,gpointer widget)150 gnc_option_set_widget (GNCOption *option, gpointer widget)
151 {
152 g_return_if_fail (option != NULL);
153 option->widget = widget;
154 }
155
156 SCM
gnc_option_get_ui_value(GNCOption * option)157 gnc_option_get_ui_value (GNCOption *option)
158 {
159 g_return_val_if_fail (option != NULL, SCM_UNDEFINED);
160 g_return_val_if_fail (option->odb != NULL, SCM_UNDEFINED);
161 g_return_val_if_fail (option->odb->get_ui_value != NULL, SCM_UNDEFINED);
162
163 return option->odb->get_ui_value (option);
164 }
165
166 void
gnc_option_set_ui_value(GNCOption * option,gboolean use_default)167 gnc_option_set_ui_value (GNCOption *option, gboolean use_default)
168 {
169 g_return_if_fail (option != NULL);
170 g_return_if_fail (option->odb != NULL);
171
172 if (!option->odb->set_ui_value)
173 return;
174
175 option->odb->set_ui_value (option, use_default);
176 }
177
178 void
gnc_option_set_selectable(GNCOption * option,gboolean selectable)179 gnc_option_set_selectable (GNCOption *option, gboolean selectable)
180 {
181 g_return_if_fail (option != NULL);
182 g_return_if_fail (option->odb != NULL);
183 g_return_if_fail (option->odb->set_selectable != NULL);
184
185 option->odb->set_selectable (option, selectable);
186 }
187
188 /********************************************************************\
189 * gnc_option_db_init *
190 * initialize the options structures from the guile side *
191 * *
192 * Args: odb - the option database to initialize *
193 * Returns: nothing *
194 \********************************************************************/
195 static void
gnc_option_db_init(GNCOptionDB * odb)196 gnc_option_db_init (GNCOptionDB *odb)
197 {
198 SCM func = scm_c_eval_string ("gnc:send-options");
199
200 scm_call_2 (func, scm_from_int (odb->handle), odb->guile_options);
201 }
202
203 /********************************************************************\
204 * gnc_option_db_new *
205 * allocate a new option database and initialize its values *
206 * *
207 * Args: guile_options - SCM handle to options *
208 * Returns: a new option database *
209 \********************************************************************/
210 GNCOptionDB *
gnc_option_db_new(SCM guile_options)211 gnc_option_db_new (SCM guile_options)
212 {
213 GNCOptionDB *odb;
214 GNCOptionDB *lookup;
215
216 odb = g_new0 (GNCOptionDB, 1);
217
218 odb->guile_options = guile_options;
219 scm_gc_protect_object (guile_options);
220
221 odb->option_sections = NULL;
222 odb->options_dirty = FALSE;
223
224 if (option_dbs == NULL)
225 option_dbs = g_hash_table_new (g_int_hash, g_int_equal);
226
227 do
228 {
229 odb->handle = last_db_handle++;
230 lookup = g_hash_table_lookup (option_dbs, &odb->handle);
231 }
232 while (lookup != NULL);
233
234 g_hash_table_insert (option_dbs, &odb->handle, odb);
235
236 gnc_option_db_init (odb);
237
238 return odb;
239 }
240
241 /* Create an option DB for a particular data type */
242 /* For now, this is global, just like when it was in guile.
243 But, it should be make per-book. */
244 static GHashTable *kvp_registry = NULL;
245
246 static void
init_table(void)247 init_table(void)
248 {
249 if (!kvp_registry)
250 kvp_registry = g_hash_table_new (g_str_hash, g_str_equal);
251 }
252
253
254 /* create a new options object for the requested type */
255 static SCM
gnc_make_kvp_options(QofIdType id_type)256 gnc_make_kvp_options (QofIdType id_type)
257 {
258 GList *list, *p;
259 SCM gnc_new_options = SCM_UNDEFINED;
260 SCM options = SCM_UNDEFINED;
261
262 init_table();
263 list = g_hash_table_lookup (kvp_registry, id_type);
264 gnc_new_options = scm_c_eval_string ("gnc:new-options");
265 options = scm_call_0 (gnc_new_options);
266
267 for (p = list; p; p = p->next)
268 {
269 SCM generator = p->data;
270 scm_call_1 (generator, options);
271 }
272 return options;
273 }
274
275 GNCOptionDB *
gnc_option_db_new_for_type(QofIdType id_type)276 gnc_option_db_new_for_type (QofIdType id_type)
277 {
278 SCM options;
279
280 if (!id_type) return NULL;
281 options = gnc_make_kvp_options (id_type);
282 return gnc_option_db_new (options);
283 }
284
285 void
gnc_option_db_load(GNCOptionDB * odb,QofBook * book)286 gnc_option_db_load (GNCOptionDB* odb, QofBook *book)
287 {
288 static SCM kvp_to_scm = SCM_UNDEFINED;
289 SCM scm_book;
290
291 if (!odb || !book) return;
292
293 if (kvp_to_scm == SCM_UNDEFINED)
294 {
295 kvp_to_scm = scm_c_eval_string ("gnc:options-kvp->scm");
296 if (!scm_is_procedure (kvp_to_scm))
297 {
298 PERR ("not a procedure\n");
299 kvp_to_scm = SCM_UNDEFINED;
300 return;
301 }
302 }
303
304 scm_book = SWIG_NewPointerObj (book, SWIG_TypeQuery ("_p_QofBook"), 0);
305
306 scm_call_2 (kvp_to_scm, odb->guile_options, scm_book);
307 }
308
309 void
gnc_option_db_save(GNCOptionDB * odb,QofBook * book,gboolean clear_all)310 gnc_option_db_save (GNCOptionDB* odb, QofBook *book, gboolean clear_all)
311 {
312 static SCM scm_to_kvp = SCM_UNDEFINED;
313 SCM scm_book;
314 SCM scm_clear_all;
315
316 if (!odb || !book) return;
317
318 if (scm_to_kvp == SCM_UNDEFINED)
319 {
320 scm_to_kvp = scm_c_eval_string ("gnc:options-scm->kvp");
321 if (!scm_is_procedure (scm_to_kvp))
322 {
323 PERR ("not a procedure\n");
324 scm_to_kvp = SCM_UNDEFINED;
325 return;
326 }
327 }
328
329 scm_book = SWIG_NewPointerObj (book, SWIG_TypeQuery ("_p_QofBook"), 0);
330 scm_clear_all = scm_from_bool (clear_all);
331
332 scm_call_3 (scm_to_kvp, odb->guile_options, scm_book, scm_clear_all);
333 }
334
335 /********************************************************************\
336 * gnc_option_db_destroy *
337 * unregister the scheme options and free all the memory *
338 * associated with an option database, including the database *
339 * itself *
340 * *
341 * Args: options database to destroy *
342 * Returns: nothing *
343 \********************************************************************/
344 void
gnc_option_db_destroy(GNCOptionDB * odb)345 gnc_option_db_destroy (GNCOptionDB *odb)
346 {
347 GSList *snode;
348
349 if (odb == NULL)
350 return;
351
352 for (snode = odb->option_sections; snode; snode = snode->next)
353 {
354 GNCOptionSection *section = snode->data;
355 GSList *onode;
356
357 for (onode = section->options; onode; onode = onode->next)
358 {
359 GNCOption *option = onode->data;
360
361 scm_gc_unprotect_object (option->guile_option);
362 g_free (option);
363 }
364
365 /* Free the option list */
366 g_slist_free (section->options);
367 section->options = NULL;
368
369 if (section->section_name != NULL)
370 free (section->section_name);
371 section->section_name = NULL;
372
373 g_free (section);
374 }
375
376 g_slist_free (odb->option_sections);
377
378 odb->option_sections = NULL;
379 odb->options_dirty = FALSE;
380
381 g_hash_table_remove (option_dbs, &odb->handle);
382
383 if (g_hash_table_size (option_dbs) == 0)
384 {
385 g_hash_table_destroy (option_dbs);
386 option_dbs = NULL;
387 }
388
389 scm_gc_unprotect_object (odb->guile_options);
390 odb->guile_options = SCM_UNDEFINED;
391
392 g_free(odb);
393 }
394
395 void
gnc_option_db_set_ui_callbacks(GNCOptionDB * odb,GNCOptionGetUIValue get_ui_value,GNCOptionSetUIValue set_ui_value,GNCOptionSetSelectable set_selectable)396 gnc_option_db_set_ui_callbacks (GNCOptionDB *odb,
397 GNCOptionGetUIValue get_ui_value,
398 GNCOptionSetUIValue set_ui_value,
399 GNCOptionSetSelectable set_selectable)
400 {
401 g_return_if_fail (odb != NULL);
402
403 odb->get_ui_value = get_ui_value;
404 odb->set_ui_value = set_ui_value;
405 odb->set_selectable = set_selectable;
406 }
407
408 /********************************************************************\
409 * gnc_option_db_register_change_callback *
410 * register a callback to be called whenever an option changes *
411 * *
412 * Args: odb - the option database to register with *
413 * callback - the callback function to register *
414 * user_data - the user data for the callback *
415 * section - the section to get callbacks for. *
416 * If NULL, get callbacks for any section changes.*
417 * name - the option name to get callbacks for. *
418 * If NULL, get callbacks for any option in the *
419 * section. Only used if section is non-NULL. *
420 * Returns: SCM handle for unregistering *
421 \********************************************************************/
422 SCM
gnc_option_db_register_change_callback(GNCOptionDB * odb,GNCOptionChangeCallback callback,gpointer data,const char * section,const char * name)423 gnc_option_db_register_change_callback (GNCOptionDB *odb,
424 GNCOptionChangeCallback callback,
425 gpointer data,
426 const char *section,
427 const char *name)
428 {
429 SCM register_proc;
430 SCM arg;
431 SCM args;
432
433 if (!odb || !callback)
434 return SCM_UNDEFINED;
435
436 /* Get the register procedure */
437 register_proc = scm_c_eval_string ("gnc:options-register-c-callback");
438 if (!scm_is_procedure (register_proc))
439 {
440 PERR("not a procedure\n");
441 return SCM_UNDEFINED;
442 }
443
444 /* Now build the args list for apply */
445 args = SCM_EOL;
446
447 /* first the guile options database */
448 args = scm_cons (odb->guile_options, args);
449
450 /* next the data */
451 arg = SWIG_NewPointerObj (data, SWIG_TypeQuery ("_p_void"), 0);
452 args = scm_cons (arg, args);
453
454 /* next the callback */
455 arg = SWIG_NewPointerObj (
456 callback, SWIG_TypeQuery ("GNCOptionChangeCallback"), 0);
457 args = scm_cons (arg, args);
458
459 /* next the name */
460 if (name == NULL)
461 {
462 arg = SCM_BOOL_F;
463 }
464 else
465 {
466 arg = scm_from_utf8_string (name);
467 }
468 args = scm_cons (arg, args);
469
470 /* next the section */
471 if (section == NULL)
472 {
473 arg = SCM_BOOL_F;
474 }
475 else
476 {
477 arg = scm_from_utf8_string (section);
478 }
479 args = scm_cons (arg, args);
480
481 /* now apply the procedure */
482 return scm_apply (register_proc, args, SCM_EOL);
483 }
484
485 /********************************************************************\
486 * gnc_option_db_unregister_change_callback_id *
487 * unregister the change callback associated with the given id *
488 * *
489 * Args: odb - the option database to register with *
490 * callback - the callback function to register *
491 * Returns: nothing *
492 \********************************************************************/
493 void
gnc_option_db_unregister_change_callback_id(GNCOptionDB * odb,SCM callback_id)494 gnc_option_db_unregister_change_callback_id (GNCOptionDB *odb, SCM callback_id)
495 {
496 SCM proc;
497
498 if (callback_id == SCM_UNDEFINED)
499 return;
500
501 proc = scm_c_eval_string ("gnc:options-unregister-callback-id");
502 if (!scm_is_procedure (proc))
503 {
504 PERR("not a procedure\n");
505 return;
506 }
507
508 scm_call_2 (proc, callback_id, odb->guile_options);
509 }
510
511 void
gncp_option_invoke_callback(GNCOptionChangeCallback callback,void * data)512 gncp_option_invoke_callback (GNCOptionChangeCallback callback, void *data)
513 {
514 callback (data);
515 }
516
517 static void
gnc_call_option_change_callbacks(GNCOptionDB * odb)518 gnc_call_option_change_callbacks (GNCOptionDB *odb)
519 {
520 SCM proc;
521
522 proc = scm_c_eval_string ("gnc:options-run-callbacks");
523 if (!scm_is_procedure (proc))
524 {
525 PERR("not a procedure\n");
526 return;
527 }
528
529 scm_call_1 (proc, odb->guile_options);
530 }
531
532 static void
initialize_getters(void)533 initialize_getters(void)
534 {
535 static gboolean getters_initialized = FALSE;
536
537 if (getters_initialized)
538 return;
539
540 getters.section = scm_c_eval_string ("gnc:option-section");
541 getters.name = scm_c_eval_string ("gnc:option-name");
542 getters.type = scm_c_eval_string ("gnc:option-type");
543 getters.sort_tag = scm_c_eval_string ("gnc:option-sort-tag");
544 getters.documentation =
545 scm_c_eval_string ("gnc:option-documentation");
546 getters.getter = scm_c_eval_string ("gnc:option-getter");
547 getters.setter = scm_c_eval_string ("gnc:option-setter");
548 getters.default_getter =
549 scm_c_eval_string ("gnc:option-default-getter");
550 getters.value_validator =
551 scm_c_eval_string ("gnc:option-value-validator");
552 getters.option_data = scm_c_eval_string ("gnc:option-data");
553 getters.index_to_name = scm_c_eval_string ("gnc:option-index-get-name");
554 getters.number_of_indices = scm_c_eval_string ("gnc:option-number-of-indices");
555 getters.index_to_value = scm_c_eval_string ("gnc:option-index-get-value");
556 getters.value_to_index = scm_c_eval_string ("gnc:option-value-get-index");
557 getters.option_widget_changed_cb =
558 scm_c_eval_string ("gnc:option-widget-changed-proc");
559 getters.date_option_subtype = scm_c_eval_string ("gnc:date-option-get-subtype");
560 getters.date_option_show_time = scm_c_eval_string ("gnc:date-option-show-time?");
561 getters.date_option_value_type = scm_c_eval_string ("gnc:date-option-value-type");
562 getters.date_option_value_absolute =
563 scm_c_eval_string ("gnc:date-option-absolute-time");
564 getters.date_option_value_relative =
565 scm_c_eval_string ("gnc:date-option-relative-time");
566 getters.plot_size_option_value_type = scm_c_eval_string ("gnc:plot-size-option-value-type");
567 getters.plot_size_option_value = scm_c_eval_string ("gnc:plot-size-option-value");
568 getters.currency_accounting_option_currency_doc_string =
569 scm_c_eval_string ("gnc:currency-accounting-option-get-curr-doc-string");
570 getters.currency_accounting_option_default_currency =
571 scm_c_eval_string ("gnc:currency-accounting-option-get-default-curr");
572 getters.currency_accounting_option_policy_doc_string =
573 scm_c_eval_string ("gnc:currency-accounting-option-get-policy-doc-string");
574 getters.currency_accounting_option_default_policy =
575 scm_c_eval_string ("gnc:currency-accounting-option-get-default-policy");
576 getters.currency_accounting_option_gain_loss_account_doc_string =
577 scm_c_eval_string ("gnc:currency-accounting-option-get-gain-loss-account-doc-string");
578 getters.currency_accounting_option_method =
579 scm_c_eval_string ("gnc:currency-accounting-option-selected-method");
580 getters.currency_accounting_option_book_currency =
581 scm_c_eval_string ("gnc:currency-accounting-option-selected-currency");
582 getters.currency_accounting_option_selected_default_policy =
583 scm_c_eval_string ("gnc:currency-accounting-option-selected-policy");
584 getters.currency_accounting_option_selected_default_gain_loss_account =
585 scm_c_eval_string ("gnc:currency-accounting-option-selected-gain-loss-account");
586
587 getters_initialized = TRUE;
588 }
589
590 /********************************************************************\
591 * gnc_option_section *
592 * returns the malloc'ed section name of the option, or NULL *
593 * if it can't be retrieved. *
594 * *
595 * Args: option - the GNCOption *
596 * Returns: malloc'ed char * or NULL *
597 \********************************************************************/
598 char *
gnc_option_section(GNCOption * option)599 gnc_option_section (GNCOption *option)
600 {
601 initialize_getters ();
602
603 return gnc_scm_call_1_to_string (getters.section, option->guile_option);
604 }
605
606 /********************************************************************\
607 * gnc_option_name *
608 * returns the malloc'ed name of the option, or NULL *
609 * if it can't be retrieved. *
610 * *
611 * Args: option - the GNCOption *
612 * Returns: malloc'ed char * or NULL *
613 \********************************************************************/
614 char *
gnc_option_name(GNCOption * option)615 gnc_option_name (GNCOption *option)
616 {
617 initialize_getters ();
618
619 return gnc_scm_call_1_to_string (getters.name, option->guile_option);
620 }
621
622 /********************************************************************\
623 * gnc_option_type *
624 * returns the malloc'ed type of the option, or NULL *
625 * if it can't be retrieved. *
626 * *
627 * Args: option - the GNCOption *
628 * Returns: malloc'ed char * or NULL *
629 \********************************************************************/
630 char *
gnc_option_type(GNCOption * option)631 gnc_option_type (GNCOption *option)
632 {
633 initialize_getters ();
634
635 return gnc_scm_call_1_symbol_to_string (getters.type,
636 option->guile_option);
637 }
638
639 /********************************************************************\
640 * gnc_option_sort_tag *
641 * returns the malloc'ed sort tag of the option, or NULL *
642 * if it can't be retrieved. *
643 * *
644 * Args: option - the GNCOption *
645 * Returns: malloc'ed char * or NULL *
646 \********************************************************************/
647 char *
gnc_option_sort_tag(GNCOption * option)648 gnc_option_sort_tag (GNCOption *option)
649 {
650 initialize_getters ();
651
652 return gnc_scm_call_1_to_string (getters.sort_tag, option->guile_option);
653 }
654
655 /********************************************************************\
656 * gnc_option_documentation *
657 * returns the malloc'ed documentation string of the option, or *
658 * NULL if it can't be retrieved. *
659 * *
660 * Args: option - the GNCOption *
661 * Returns: malloc'ed char * or NULL *
662 \********************************************************************/
663 char *
gnc_option_documentation(GNCOption * option)664 gnc_option_documentation (GNCOption *option)
665 {
666 initialize_getters ();
667
668 return gnc_scm_call_1_to_string (getters.documentation,
669 option->guile_option);
670 }
671
672 /********************************************************************\
673 * gnc_option_getter *
674 * returns the SCM handle for the option getter function. *
675 * This value should be tested with scm_procedure_p before use. *
676 * *
677 * Args: option - the GNCOption *
678 * Returns: SCM handle to function *
679 \********************************************************************/
680 SCM
gnc_option_getter(GNCOption * option)681 gnc_option_getter (GNCOption *option)
682 {
683 initialize_getters ();
684
685 return gnc_scm_call_1_to_procedure (getters.getter,
686 option->guile_option);
687 }
688
689 /********************************************************************\
690 * gnc_option_setter *
691 * returns the SCM handle for the option setter function. *
692 * This value should be tested with scm_procedure_p before use. *
693 * *
694 * Args: option - the GNCOption *
695 * Returns: SCM handle to function *
696 \********************************************************************/
697 SCM
gnc_option_setter(GNCOption * option)698 gnc_option_setter (GNCOption *option)
699 {
700 initialize_getters ();
701
702 return gnc_scm_call_1_to_procedure (getters.setter,
703 option->guile_option);
704 }
705
706 /********************************************************************\
707 * gnc_option_default_getter *
708 * returns the SCM handle for the option default_getter function. *
709 * This value should be tested with scm_procedure_p before use. *
710 * *
711 * Args: option - the GNCOption *
712 * Returns: SCM handle to function *
713 \********************************************************************/
714 SCM
gnc_option_default_getter(GNCOption * option)715 gnc_option_default_getter (GNCOption *option)
716 {
717 initialize_getters ();
718
719 return gnc_scm_call_1_to_procedure (getters.default_getter,
720 option->guile_option);
721 }
722
723 /********************************************************************\
724 * gnc_option_value_validator *
725 * returns the SCM handle for the option value validator function.*
726 * This value should be tested with scm_procedure_p before use. *
727 * *
728 * Args: option - the GNCOption *
729 * Returns: SCM handle to function *
730 \********************************************************************/
731 SCM
gnc_option_value_validator(GNCOption * option)732 gnc_option_value_validator (GNCOption *option)
733 {
734 initialize_getters ();
735
736 return gnc_scm_call_1_to_procedure (getters.value_validator,
737 option->guile_option);
738 }
739
740 /********************************************************************\
741 * gnc_option_widget_changed_proc_getter *
742 * returns the SCM handle for the function to be called if the *
743 * GUI widget representing the option is changed. *
744 * This value should be tested with scm_procedure_p before use. *
745 * If no such function exists, returns SCM_UNDEFINED. *
746 * *
747 * Args: option - the GNCOption *
748 * Returns: SCM handle to function *
749 * If no such function exists, returns SCM_UNDEFINED. *
750 \********************************************************************/
751 SCM
gnc_option_widget_changed_proc_getter(GNCOption * option)752 gnc_option_widget_changed_proc_getter (GNCOption *option)
753 {
754 SCM cb;
755
756 initialize_getters ();
757
758 if (scm_is_procedure (getters.option_widget_changed_cb))
759 {
760 /* call the callback function getter to get the actual callback function */
761 cb = scm_call_1 (getters.option_widget_changed_cb, option->guile_option);
762
763 if (scm_is_procedure (cb)) /* a callback exists */
764 {
765 return (cb);
766 }
767 /* else no callback exists - this is a legal situation */
768 }
769 else /* getters not set up correctly? */
770 {
771 PERR("getters.option_widget_changed_cb is not a valid procedure\n");
772 }
773
774 return( SCM_UNDEFINED );
775 }
776
777 /**********************************************************************\
778 * gnc_option_call_option_widget_changed_proc *
779 * If there is an option_widget_changed_cb for this option, call *
780 * it with the SCM value of the option that is passed in. If *
781 * there is no such callback function or value, do nothing. *
782 * *
783 * Args: option - the GNCOption *
784 * reset_changed - whether to reset the changed flag afterwards *
785 * Returns: void *
786 \**********************************************************************/
787 void
gnc_option_call_option_widget_changed_proc(GNCOption * option,gboolean reset_changed)788 gnc_option_call_option_widget_changed_proc (GNCOption *option,
789 gboolean reset_changed)
790 {
791 SCM cb, value;
792
793 cb = gnc_option_widget_changed_proc_getter (option);
794
795 if (cb != SCM_UNDEFINED)
796 {
797 value = gnc_option_get_ui_value (option);
798
799 if (value != SCM_UNDEFINED)
800 {
801 scm_call_1 (cb, value);
802 }
803 }
804 if (reset_changed)
805 option->changed = FALSE;
806 }
807
808 /********************************************************************\
809 * gnc_option_num_permissible_values *
810 * returns the number of permissible values in the option, or *
811 * -1 if there are no values available. *
812 * *
813 * Args: option - the GNCOption *
814 * Returns: number of permissible options or -1 *
815 \********************************************************************/
816 int
gnc_option_num_permissible_values(GNCOption * option)817 gnc_option_num_permissible_values (GNCOption *option)
818 {
819 SCM value;
820
821 initialize_getters ();
822
823 value = scm_call_1 (getters.number_of_indices, option->guile_option);
824
825 if (scm_is_exact (value))
826 {
827 return scm_to_int (value);
828 }
829 else
830 {
831 return -1;
832 }
833 }
834
835 /********************************************************************\
836 * gnc_option_permissible_value_index *
837 * returns the index of the permissible value matching the *
838 * provided value, or -1 if it couldn't be found *
839 * *
840 * Args: option - the GNCOption *
841 * value - the SCM handle of the value *
842 * Returns: index of permissible value, or -1 *
843 \********************************************************************/
844 int
gnc_option_permissible_value_index(GNCOption * option,SCM search_value)845 gnc_option_permissible_value_index (GNCOption *option, SCM search_value)
846 {
847 SCM value;
848 value = scm_call_2 (getters.value_to_index, option->guile_option, search_value);
849 if (value == SCM_BOOL_F)
850 {
851 return -1;
852 }
853 else
854 {
855 return scm_to_int (value);
856 }
857 }
858
859 /********************************************************************\
860 * gnc_option_permissible_value *
861 * returns the SCM handle to the indexth permissible value in the *
862 * option, or SCM_UNDEFINED if the index was out of range or *
863 * there was some other problem. *
864 * *
865 * Args: option - the GNCOption *
866 * index - the index of the permissible value *
867 * Returns: SCM handle to option value or SCM_UNDEFINED *
868 \********************************************************************/
869 SCM
gnc_option_permissible_value(GNCOption * option,int index)870 gnc_option_permissible_value (GNCOption *option, int index)
871 {
872 SCM value;
873
874 if (index < 0)
875 return SCM_UNDEFINED;
876
877 initialize_getters ();
878
879 value = scm_call_2 (getters.index_to_value, option->guile_option,
880 scm_from_int (index));
881
882 return value;
883 }
884
885 /********************************************************************\
886 * gnc_option_permissible_value_name *
887 * returns the malloc'd name of the indexth permissible value in *
888 * the option, or NULL if the index was out of range or there are *
889 * no values available. *
890 * *
891 * Args: option - the GNCOption *
892 * index - the index of the permissible value *
893 * Returns: malloc'd name of permissible value or NULL *
894 \********************************************************************/
895 char *
gnc_option_permissible_value_name(GNCOption * option,int index)896 gnc_option_permissible_value_name (GNCOption *option, int index)
897 {
898 SCM name;
899
900 if (index < 0)
901 return NULL;
902
903 initialize_getters ();
904
905 name = scm_call_2 (getters.index_to_name, option->guile_option,
906 scm_from_int (index));
907 if (name == SCM_UNDEFINED)
908 return NULL;
909 if (!scm_is_string (name))
910 return NULL;
911
912 return gnc_scm_to_utf8_string (name);
913 }
914
915 /********************************************************************\
916 * gnc_option_show_time *
917 * returns true if the gui should display the time as well as *
918 * the date for this option. Only use this for date options. *
919 * *
920 * Args: option - the GNCOption *
921 * Returns: true if time should be shown *
922 \********************************************************************/
923 gboolean
gnc_option_show_time(GNCOption * option)924 gnc_option_show_time (GNCOption *option)
925 {
926 SCM value;
927
928 initialize_getters ();
929
930 value = scm_call_1 (getters.date_option_show_time, option->guile_option);
931
932 return scm_is_true (value);
933 }
934
935 /********************************************************************\
936 * gnc_option_get_option_data *
937 * returns the option data of this option *
938 * *
939 * Args: option - the GNCOption *
940 * Returns: the option data *
941 \********************************************************************/
942 SCM
gnc_option_get_option_data(GNCOption * option)943 gnc_option_get_option_data (GNCOption *option)
944 {
945 initialize_getters ();
946
947 return scm_call_1 (getters.option_data, option->guile_option);
948 }
949
950 /********************************************************************\
951 * gnc_option_multiple_selection *
952 * returns true if the gui should allow multiple selection of *
953 * accounts. Only use this for account options. *
954 * *
955 * Args: option - the GNCOption *
956 * Returns: true if multiple selection allowed *
957 \********************************************************************/
958 gboolean
gnc_option_multiple_selection(GNCOption * option)959 gnc_option_multiple_selection (GNCOption *option)
960 {
961 SCM pair;
962
963 initialize_getters ();
964
965 pair = scm_call_1 (getters.option_data, option->guile_option);
966
967 return !scm_is_true (scm_not (SCM_CAR(pair)));
968 }
969
970 /********************************************************************\
971 * gnc_option_get_account_type_list *
972 * returns the list of account_types in the option (or NULL if *
973 * no special list is provided). Only use this for account *
974 * options. *
975 * *
976 * Args: option - the GNCOption *
977 * Returns: GList of account types (must be freed by caller) *
978 \********************************************************************/
979 GList *
gnc_option_get_account_type_list(GNCOption * option)980 gnc_option_get_account_type_list (GNCOption *option)
981 {
982 SCM pair;
983 SCM lst;
984 GList *type_list = NULL;
985
986 initialize_getters ();
987
988 pair = scm_call_1 (getters.option_data, option->guile_option);
989 lst = SCM_CDR(pair);
990
991 while (!scm_is_null (lst))
992 {
993 GNCAccountType type;
994 SCM item;
995
996 /* Compute this item and the rest of the list */
997 item = SCM_CAR(lst);
998 lst = SCM_CDR(lst);
999
1000 if (scm_is_false (scm_integer_p (item)))
1001 {
1002 PERR("Invalid type");
1003 }
1004 else
1005 {
1006 type = scm_to_long (item);
1007 type_list = g_list_prepend (type_list, GINT_TO_POINTER (type));
1008 }
1009 }
1010
1011 return g_list_reverse (type_list);
1012 }
1013
1014 /********************************************************************\
1015 * gnc_option_get_range_info *
1016 * returns the range info for a number range option in the pointer*
1017 * arguments. NULL arguments are ignored. Use only for number *
1018 * range options. *
1019 * *
1020 * Args: option - the GNCOption *
1021 * Returns: true if everything went ok :) *
1022 \********************************************************************/
gnc_option_get_range_info(GNCOption * option,double * lower_bound,double * upper_bound,int * num_decimals,double * step_size)1023 gboolean gnc_option_get_range_info (GNCOption *option,
1024 double *lower_bound,
1025 double *upper_bound,
1026 int *num_decimals,
1027 double *step_size)
1028 {
1029 SCM list;
1030 SCM value;
1031
1032 initialize_getters ();
1033
1034 list = scm_call_1 (getters.option_data, option->guile_option);
1035
1036 if (!scm_is_list (list) || scm_is_null (list))
1037 return FALSE;
1038
1039 /* lower bound */
1040 value = SCM_CAR(list);
1041 list = SCM_CDR(list);
1042
1043 if (!scm_is_number (value))
1044 return FALSE;
1045
1046 if (lower_bound != NULL)
1047 *lower_bound = scm_to_double (value);
1048
1049 if (!scm_is_list (list) || scm_is_null (list))
1050 return FALSE;
1051
1052 /* upper bound */
1053 value = SCM_CAR(list);
1054 list = SCM_CDR(list);
1055
1056 if (!scm_is_number (value))
1057 return FALSE;
1058
1059 if (upper_bound != NULL)
1060 *upper_bound = scm_to_double (value);
1061
1062 if (!scm_is_list (list) || scm_is_null (list))
1063 return FALSE;
1064
1065 /* number of decimals */
1066 value = SCM_CAR(list);
1067 list = SCM_CDR(list);
1068
1069 if (!scm_is_number (value))
1070 return FALSE;
1071
1072 /* Guile-1.6 returns this as a double, so let's use that in all cases.
1073 * This is still safe for earlier guiles, too -- tested with 1.3.4.
1074 */
1075 if (num_decimals != NULL)
1076 {
1077 double decimals = scm_to_double (value);
1078 *num_decimals = (int)decimals;
1079 }
1080
1081 if (!scm_is_list (list) || scm_is_null (list))
1082 return FALSE;
1083
1084 /* step size */
1085 value = SCM_CAR(list);
1086
1087 if (!scm_is_number (value))
1088 return FALSE;
1089
1090 if (step_size != NULL)
1091 *step_size = scm_to_double (value);
1092
1093 return TRUE;
1094 }
1095
1096 /********************************************************************\
1097 * gnc_option_color_range *
1098 * returns the color range for rgba values. *
1099 * Only use this for color options. *
1100 * *
1101 * Args: option - the GNCOption *
1102 * Returns: color range for the option *
1103 \********************************************************************/
1104 gdouble
gnc_option_color_range(GNCOption * option)1105 gnc_option_color_range (GNCOption *option)
1106 {
1107 SCM list;
1108 SCM value;
1109
1110 initialize_getters ();
1111
1112 list = scm_call_1 (getters.option_data, option->guile_option);
1113 if (!scm_is_list (list) || scm_is_null (list))
1114 return 0.0;
1115
1116 value = SCM_CAR(list);
1117 if (!scm_is_number (value))
1118 return 0.0;
1119
1120 return scm_to_double (value);
1121 }
1122
1123 /********************************************************************\
1124 * gnc_option_use_alpha *
1125 * returns true if the color option should use alpha transparency *
1126 * Only use this for color options. *
1127 * *
1128 * Args: option - the GNCOption *
1129 * Returns: true if alpha transparency should be used *
1130 \********************************************************************/
1131 gdouble
gnc_option_use_alpha(GNCOption * option)1132 gnc_option_use_alpha (GNCOption *option)
1133 {
1134 SCM list;
1135 SCM value;
1136
1137 initialize_getters ();
1138
1139 list = scm_call_1 (getters.option_data, option->guile_option);
1140 if (!scm_is_list (list) || scm_is_null (list))
1141 return FALSE;
1142
1143 list = SCM_CDR(list);
1144 if (!scm_is_list (list) || scm_is_null (list))
1145 return FALSE;
1146
1147 value = SCM_CAR(list);
1148 if (!scm_is_bool (value))
1149 return FALSE;
1150
1151 return scm_is_true (value);
1152 }
1153
1154 /********************************************************************\
1155 * gnc_option_get_color_argb *
1156 * returns the argb value of a color option *
1157 * *
1158 * Args: option - the GNCOption *
1159 * Returns: argb value of option *
1160 \********************************************************************/
1161 guint32
gnc_option_get_color_argb(GNCOption * option)1162 gnc_option_get_color_argb (GNCOption *option)
1163 {
1164 gdouble red, green, blue, alpha;
1165 guint32 color = 0;
1166
1167 if (!gnc_option_get_color_info (option, FALSE, &red, &green, &blue, &alpha))
1168 return 0;
1169
1170 color |= (guint32) (alpha * 255.0);
1171 color <<= 8;
1172
1173 color |= (guint32) (red * 255.0);
1174 color <<= 8;
1175
1176 color |= (guint32) (green * 255.0);
1177 color <<= 8;
1178
1179 color |= (guint32) (blue * 255.0);
1180
1181 return color;
1182 }
1183
1184 /********************************************************************\
1185 * gnc_option_get_color_info *
1186 * gets the color information from a color option. rgba values *
1187 * returned are between 0.0 and 1.0. *
1188 * *
1189 * Args: option - option to get info from *
1190 * use_default - use the default or current value *
1191 * red - where to store the red value *
1192 * blue - where to store the blue value *
1193 * green - where to store the green value *
1194 * alpha - where to store the alpha value *
1195 * Return: true if everything went ok *
1196 \********************************************************************/
1197 gboolean
gnc_option_get_color_info(GNCOption * option,gboolean use_default,gdouble * red,gdouble * green,gdouble * blue,gdouble * alpha)1198 gnc_option_get_color_info (GNCOption *option,
1199 gboolean use_default,
1200 gdouble *red,
1201 gdouble *green,
1202 gdouble *blue,
1203 gdouble *alpha)
1204 {
1205 gdouble scale;
1206 gdouble rgba;
1207 SCM getter;
1208 SCM value;
1209
1210 if (option == NULL)
1211 return FALSE;
1212
1213 if (use_default)
1214 getter = gnc_option_default_getter (option);
1215 else
1216 getter = gnc_option_getter (option);
1217 if (getter == SCM_UNDEFINED)
1218 return FALSE;
1219
1220 value = scm_call_0 (getter);
1221 if (!scm_is_list (value) || scm_is_null (value) || !scm_is_number (SCM_CAR(value)))
1222 return FALSE;
1223
1224 scale = gnc_option_color_range (option);
1225 if (scale <= 0.0)
1226 return FALSE;
1227
1228 scale = 1.0 / scale;
1229
1230 rgba = scm_to_double (SCM_CAR(value));
1231 if (red != NULL)
1232 *red = MIN(1.0, rgba * scale);
1233
1234 value = SCM_CDR(value);
1235 if (!scm_is_list (value) || scm_is_null (value) || !scm_is_number (SCM_CAR(value)))
1236 return FALSE;
1237
1238 rgba = scm_to_double (SCM_CAR(value));
1239 if (green != NULL)
1240 *green = MIN(1.0, rgba * scale);
1241
1242 value = SCM_CDR(value);
1243 if (!scm_is_list (value) || scm_is_null (value) || !scm_is_number (SCM_CAR(value)))
1244 return FALSE;
1245
1246 rgba = scm_to_double (SCM_CAR(value));
1247 if (blue != NULL)
1248 *blue = MIN(1.0, rgba * scale);
1249
1250 value = SCM_CDR(value);
1251 if (!scm_is_list (value) || scm_is_null (value) || !scm_is_number (SCM_CAR(value)))
1252 return FALSE;
1253
1254 rgba = scm_to_double (SCM_CAR(value));
1255 if (alpha != NULL)
1256 *alpha = MIN(1.0, rgba * scale);
1257
1258 return TRUE;
1259 }
1260
1261 /********************************************************************\
1262 * gnc_option_set_default *
1263 * set the option to its default value *
1264 * *
1265 * Args: option - the GNCOption *
1266 * Returns: nothing *
1267 \********************************************************************/
1268 void
gnc_option_set_default(GNCOption * option)1269 gnc_option_set_default (GNCOption *option)
1270 {
1271 SCM default_getter;
1272 SCM setter;
1273 SCM value;
1274
1275 if (option == NULL)
1276 return;
1277
1278 default_getter = gnc_option_default_getter (option);
1279 if (default_getter == SCM_UNDEFINED)
1280 return;
1281
1282 value = scm_call_0 (default_getter);
1283
1284 setter = gnc_option_setter (option);
1285 if (setter == SCM_UNDEFINED)
1286 return;
1287
1288 scm_call_1 (setter, value);
1289 }
1290
1291 static gint
compare_sections(gconstpointer a,gconstpointer b)1292 compare_sections (gconstpointer a, gconstpointer b)
1293 {
1294 const GNCOptionSection *sa = a;
1295 const GNCOptionSection *sb = b;
1296
1297 return g_strcmp0 (sa->section_name, sb->section_name);
1298 }
1299
1300 static gint
compare_option_tags(gconstpointer a,gconstpointer b)1301 compare_option_tags (gconstpointer a, gconstpointer b)
1302 {
1303 GNCOption *oa = (GNCOption *) a;
1304 GNCOption *ob = (GNCOption *) b;
1305 char *tag_a = gnc_option_sort_tag (oa);
1306 char *tag_b = gnc_option_sort_tag (ob);
1307 gint result;
1308
1309 result = g_strcmp0 (tag_a, tag_b);
1310
1311 if (tag_a != NULL)
1312 free (tag_a);
1313
1314 if (tag_b != NULL)
1315 free (tag_b);
1316
1317 return result;
1318 }
1319
1320 /********************************************************************\
1321 * gnc_option_db_dirty *
1322 * returns true if guile has registered more options into the *
1323 * database since the last time the database was cleaned. *
1324 * *
1325 * Returns: dirty flag *
1326 \********************************************************************/
1327 gboolean
gnc_option_db_dirty(GNCOptionDB * odb)1328 gnc_option_db_dirty (GNCOptionDB *odb)
1329 {
1330 g_return_val_if_fail (odb, FALSE);
1331
1332 return odb->options_dirty;
1333 }
1334
1335 /********************************************************************\
1336 * gnc_option_db_clean *
1337 * resets the dirty flag of the option database *
1338 * *
1339 \********************************************************************/
1340 void
gnc_option_db_clean(GNCOptionDB * odb)1341 gnc_option_db_clean (GNCOptionDB *odb)
1342 {
1343 g_return_if_fail (odb);
1344
1345 odb->options_dirty = FALSE;
1346 }
1347
1348 /********************************************************************\
1349 * _gnc_option_db_register_option *
1350 * registers an option with an option database. Intended to be *
1351 * called from guile. *
1352 * *
1353 * Args: odb - the option database *
1354 * option - the guile option *
1355 * Returns: nothing *
1356 \********************************************************************/
1357 void
gnc_option_db_register_option(GNCOptionDBHandle handle,SCM guile_option)1358 gnc_option_db_register_option (GNCOptionDBHandle handle, SCM guile_option)
1359 {
1360 GNCOptionDB *odb;
1361 GNCOption *option;
1362 GNCOptionSection *section;
1363
1364 odb = g_hash_table_lookup (option_dbs, &handle);
1365
1366 g_return_if_fail (odb != NULL);
1367
1368 odb->options_dirty = TRUE;
1369
1370 /* Make the option structure */
1371 option = g_new0 (GNCOption, 1);
1372 option->guile_option = guile_option;
1373 option->changed = FALSE;
1374 option->widget = NULL;
1375 option->odb = odb;
1376
1377 /* Prevent guile from garbage collecting the option */
1378 scm_gc_protect_object (guile_option);
1379
1380 /* Make the section structure */
1381 section = g_new0 (GNCOptionSection, 1);
1382 section->section_name = gnc_option_section (option);
1383 section->options = NULL;
1384
1385 /* See if the section is already there */
1386 {
1387 GSList *old;
1388
1389 old = g_slist_find_custom (odb->option_sections, section, compare_sections);
1390
1391 if (old != NULL)
1392 {
1393 if (section->section_name != NULL)
1394 free (section->section_name);
1395 g_free (section);
1396 section = old->data;
1397 }
1398 else
1399 odb->option_sections = g_slist_insert_sorted (odb->option_sections,
1400 section,
1401 compare_sections);
1402 }
1403
1404 section->options = g_slist_insert_sorted (section->options, option,
1405 compare_option_tags);
1406 }
1407
1408 /********************************************************************\
1409 * gnc_option_db_num_sections *
1410 * returns the number of option sections registered so far in the *
1411 * database *
1412 * *
1413 * Args: odb - the database to count sections for *
1414 * Returns: number of option sections *
1415 \********************************************************************/
1416 guint
gnc_option_db_num_sections(GNCOptionDB * odb)1417 gnc_option_db_num_sections (GNCOptionDB *odb)
1418 {
1419 return g_slist_length (odb->option_sections);
1420 }
1421
1422 /********************************************************************\
1423 * gnc_option_db_get_section *
1424 * returns the ith option section in the database, or NULL *
1425 * *
1426 * Args: odb - the option database *
1427 * i - index of section *
1428 * Returns: ith option sectioin *
1429 \********************************************************************/
1430 GNCOptionSection *
gnc_option_db_get_section(GNCOptionDB * odb,gint i)1431 gnc_option_db_get_section (GNCOptionDB *odb, gint i)
1432 {
1433 return g_slist_nth_data (odb->option_sections, i);
1434 }
1435
1436 /********************************************************************\
1437 * gnc_option_section_name *
1438 * returns the name of the options section *
1439 * *
1440 * Args: section - section to get name of *
1441 * Returns: name of option section *
1442 \********************************************************************/
1443 const char *
gnc_option_section_name(GNCOptionSection * section)1444 gnc_option_section_name (GNCOptionSection *section)
1445 {
1446 return section->section_name;
1447 }
1448
1449 /********************************************************************\
1450 * gnc_option_section_num_options *
1451 * returns the number of options in a given section *
1452 * *
1453 * Args: section - section to count options for *
1454 * Returns: number of options in section *
1455 \********************************************************************/
1456 guint
gnc_option_section_num_options(GNCOptionSection * section)1457 gnc_option_section_num_options (GNCOptionSection *section)
1458 {
1459 return g_slist_length (section->options);
1460 }
1461
1462 /********************************************************************\
1463 * gnc_get_option_section_option *
1464 * returns the ith option in a given section *
1465 * *
1466 * Args: section - section to retrieve option for *
1467 * i - index of option *
1468 * Returns: ith option in section *
1469 \********************************************************************/
1470 GNCOption *
gnc_get_option_section_option(GNCOptionSection * section,int i)1471 gnc_get_option_section_option (GNCOptionSection *section, int i)
1472 {
1473 return g_slist_nth_data (section->options, i);
1474 }
1475
1476 /********************************************************************\
1477 * gnc_option_db_get_option_by_name *
1478 * returns an option given section name and name *
1479 * *
1480 * Args: odb - option database to search in *
1481 * section_name - name of section to search for *
1482 * name - name to search for *
1483 * Returns: given option, or NULL if none *
1484 \********************************************************************/
1485 GNCOption *
gnc_option_db_get_option_by_name(GNCOptionDB * odb,const char * section_name,const char * name)1486 gnc_option_db_get_option_by_name (GNCOptionDB *odb,
1487 const char *section_name,
1488 const char *name)
1489 {
1490 GSList *section_node;
1491 GSList *option_node;
1492 GNCOptionSection section_key;
1493 GNCOptionSection *section;
1494 GNCOption *option;
1495 gint result;
1496 char *node_name;
1497
1498 if (odb == NULL)
1499 return NULL;
1500
1501 section_key.section_name = (char *) section_name;
1502
1503 section_node = g_slist_find_custom (odb->option_sections, §ion_key,
1504 compare_sections);
1505
1506 if (section_node == NULL)
1507 return NULL;
1508
1509 section = section_node->data;
1510 option_node = section->options;
1511
1512 while (option_node != NULL)
1513 {
1514 option = option_node->data;
1515
1516 node_name = gnc_option_name (option);
1517 result = g_strcmp0 (name, node_name);
1518 free (node_name);
1519
1520 if (result == 0)
1521 return option;
1522
1523 option_node = option_node->next;
1524 }
1525 return NULL;
1526 }
1527
1528 /********************************************************************\
1529 * gnc_option_db_get_option_by_SCM *
1530 * returns an option given SCM handle. Uses section and name. *
1531 * *
1532 * Args: odb - option database to search in *
1533 * guile_option - SCM handle of option *
1534 * Returns: given option, or NULL if none *
1535 \********************************************************************/
1536 GNCOption *
gnc_option_db_get_option_by_SCM(GNCOptionDB * odb,SCM guile_option)1537 gnc_option_db_get_option_by_SCM (GNCOptionDB *odb, SCM guile_option)
1538 {
1539 GNCOption option_key;
1540 GNCOption *option;
1541 char *section_name;
1542 char *name;
1543
1544 option_key.guile_option = guile_option;
1545
1546 section_name = gnc_option_section (&option_key);
1547 name = gnc_option_name (&option_key);
1548
1549 option = gnc_option_db_get_option_by_name (odb, section_name, name);
1550
1551 if (section_name != NULL)
1552 free (section_name);
1553
1554 if (name != NULL)
1555 free (name);
1556
1557 return option;
1558 }
1559
1560 static SCM
gnc_option_valid_value(GNCOption * option,SCM value)1561 gnc_option_valid_value (GNCOption *option, SCM value)
1562 {
1563 SCM validator;
1564 SCM result, ok;
1565
1566 validator = gnc_option_value_validator (option);
1567
1568 result = scm_call_1 (validator, value);
1569 if (!scm_is_list (result) || scm_is_null (result))
1570 return SCM_UNDEFINED;
1571
1572 ok = SCM_CAR(result);
1573 if (!scm_is_bool (ok))
1574 return SCM_UNDEFINED;
1575
1576 if (!scm_is_true (ok))
1577 return SCM_UNDEFINED;
1578
1579 result = SCM_CDR(result);
1580 if (!scm_is_list (result) || scm_is_null (result))
1581 return SCM_UNDEFINED;
1582
1583 return SCM_CAR(result);
1584 }
1585
1586 static char*
gnc_commit_option(GNCOption * option)1587 gnc_commit_option (GNCOption *option)
1588 {
1589 SCM validator, setter, value;
1590 SCM result, ok;
1591 char* retval = NULL;
1592
1593 /* Validate the ui's value */
1594 value = gnc_option_get_ui_value (option);
1595 if (value == SCM_UNDEFINED)
1596 return NULL;
1597
1598 validator = gnc_option_value_validator (option);
1599
1600 result = scm_call_1(validator, value);
1601 if (!scm_is_list (result) || scm_is_null (result))
1602 {
1603 PERR("bad validation result\n");
1604 return NULL;
1605 }
1606
1607 /* First element determines validity */
1608 ok = SCM_CAR(result);
1609 if (!scm_is_bool (ok))
1610 {
1611 PERR("bad validation result\n");
1612 return NULL;
1613 }
1614
1615 if (scm_is_true (ok))
1616 {
1617 /* Second element is value to use */
1618 value = SCM_CADR(result);
1619 setter = gnc_option_setter (option);
1620
1621 scm_call_1 (setter, value);
1622
1623 gnc_option_set_ui_value (option, FALSE);
1624 }
1625 else
1626 {
1627 SCM oops;
1628 char *section, *name;
1629 const char *message = NULL;
1630 const char *format = _("There is a problem with option %s:%s.\n%s");
1631 const char *bad_value = _("Invalid option value");
1632
1633 name = gnc_option_name (option);
1634 section = gnc_option_section (option);
1635
1636 /* Second element is error message */
1637 oops = SCM_CADR(result);
1638 if (!scm_is_string (oops))
1639 {
1640 PERR("bad validation result\n");
1641 retval = g_strdup_printf (format,
1642 section ? section : "(null)",
1643 name ? name : "(null)",
1644 bad_value);
1645 }
1646 else
1647 {
1648 message = gnc_scm_to_utf8_string (oops);
1649 retval = g_strdup_printf (format,
1650 section ? section : "(null)",
1651 name ? name : "(null)",
1652 message ? message : "(null)");
1653 }
1654 if (name != NULL)
1655 free (name);
1656 if (section != NULL)
1657 free (section);
1658 g_free ((gpointer *) message);
1659 }
1660 return retval;
1661 }
1662
1663 /********************************************************************\
1664 * gnc_option_db_get_changed *
1665 * returns a boolean value, TRUE if any option has changed, *
1666 * FALSE is none of the options have changed *
1667 * *
1668 * Args: odb - option database to check *
1669 * Return: boolean *
1670 \********************************************************************/
1671 gboolean
gnc_option_db_get_changed(GNCOptionDB * odb)1672 gnc_option_db_get_changed (GNCOptionDB *odb)
1673 {
1674 GSList *section_node;
1675 GSList *option_node;
1676 GNCOptionSection *section;
1677 GNCOption *option;
1678
1679 g_return_val_if_fail (odb, FALSE);
1680
1681 for (section_node = odb->option_sections; section_node;
1682 section_node = section_node->next)
1683 {
1684 section = section_node->data;
1685
1686 for (option_node = section->options; option_node;
1687 option_node = option_node->next)
1688 {
1689 option = option_node->data;
1690
1691 if (option->changed)
1692 return TRUE;
1693 }
1694 }
1695 return FALSE;
1696 }
1697
1698 /********************************************************************\
1699 * gnc_option_db_commit *
1700 * commits the options which have changed, and which are valid *
1701 * for those which are not valid, error dialogs are shown. *
1702 * *
1703 * Args: odb - option database to commit *
1704 * Return: nothing *
1705 \********************************************************************/
1706 GList*
gnc_option_db_commit(GNCOptionDB * odb)1707 gnc_option_db_commit (GNCOptionDB *odb)
1708 {
1709 GSList *section_node;
1710 GSList *option_node;
1711 GNCOptionSection *section;
1712 GNCOption *option;
1713 gboolean changed_something = FALSE;
1714 GList *commit_errors = NULL;
1715
1716 g_return_val_if_fail (odb, NULL);
1717
1718 section_node = odb->option_sections;
1719 while (section_node != NULL)
1720 {
1721 section = section_node->data;
1722
1723 option_node = section->options;
1724 while (option_node != NULL)
1725 {
1726 option = option_node->data;
1727
1728 if (option->changed)
1729 {
1730 char *result = NULL;
1731 result = gnc_commit_option (option_node->data);
1732 if (result)
1733 commit_errors = g_list_append (commit_errors, result);
1734 changed_something = TRUE;
1735 option->changed = FALSE;
1736 }
1737 option_node = option_node->next;
1738 }
1739 section_node = section_node->next;
1740 }
1741 if (changed_something)
1742 gnc_call_option_change_callbacks (odb);
1743
1744 return commit_errors;
1745 }
1746
1747 /********************************************************************\
1748 * gnc_option_db_section_reset_widgets *
1749 * reset all option widgets in one section to their default. *
1750 * values *
1751 * *
1752 * Args: odb - option database to reset *
1753 * Return: nothing *
1754 \********************************************************************/
1755 void
gnc_option_db_section_reset_widgets(GNCOptionSection * section)1756 gnc_option_db_section_reset_widgets (GNCOptionSection *section)
1757 {
1758 GSList *option_node;
1759 GNCOption *option;
1760
1761 g_return_if_fail (section);
1762
1763 /* Don't reset "invisible" options.
1764 * If the section name begins "__" we should not reset
1765 */
1766 if (section->section_name == NULL ||
1767 strncmp (section->section_name, "__", 2) == 0)
1768 return;
1769
1770 for (option_node = section->options;
1771 option_node != NULL;
1772 option_node = option_node->next)
1773 {
1774 option = option_node->data;
1775 gnc_option_set_ui_value (option, TRUE);
1776 }
1777 }
1778
1779 /********************************************************************\
1780 * gnc_option_db_reset_widgets *
1781 * reset all option widgets to their default values. *
1782 * *
1783 * Args: odb - option database to reset *
1784 * Return: nothing *
1785 \********************************************************************/
1786 void
gnc_option_db_reset_widgets(GNCOptionDB * odb)1787 gnc_option_db_reset_widgets (GNCOptionDB *odb)
1788 {
1789 GSList *section_node;
1790 GNCOptionSection *section;
1791
1792 g_return_if_fail (odb);
1793
1794 for (section_node = odb->option_sections;
1795 section_node != NULL;
1796 section_node = section_node->next)
1797 {
1798 section = section_node->data;
1799 gnc_option_db_section_reset_widgets (section);
1800 }
1801 }
1802
1803 /********************************************************************\
1804 * gnc_option_db_get_default_section *
1805 * returns the malloc'd section name of the default section, *
1806 * or NULL if there is none. *
1807 * *
1808 * Args: odb - option database to get default page for *
1809 * Return: g_malloc'd default section name *
1810 \********************************************************************/
1811 char *
gnc_option_db_get_default_section(GNCOptionDB * odb)1812 gnc_option_db_get_default_section (GNCOptionDB *odb)
1813 {
1814 SCM getter;
1815 SCM value;
1816
1817 if (odb == NULL)
1818 return NULL;
1819
1820 getter = scm_c_eval_string ("gnc:options-get-default-section");
1821 if (!scm_is_procedure (getter))
1822 return NULL;
1823
1824 value = scm_call_1 (getter, odb->guile_options);
1825 if (!scm_is_string (value))
1826 return NULL;
1827
1828 return gnc_scm_to_utf8_string (value);
1829 }
1830
1831 /********************************************************************\
1832 * gnc_option_db_lookup_option *
1833 * looks up an option. If present, returns its SCM value, *
1834 * otherwise returns the default. *
1835 * *
1836 * Args: odb - option database to search in *
1837 * section - section name of option *
1838 * name - name of option *
1839 * default - default value if not found *
1840 * Return: option value *
1841 \********************************************************************/
1842 SCM
gnc_option_db_lookup_option(GNCOptionDB * odb,const char * section,const char * name,SCM default_value)1843 gnc_option_db_lookup_option (GNCOptionDB *odb,
1844 const char *section,
1845 const char *name,
1846 SCM default_value)
1847 {
1848 GNCOption *option;
1849 SCM getter;
1850
1851 option = gnc_option_db_get_option_by_name (odb, section, name);
1852
1853 if (option == NULL)
1854 return default_value;
1855
1856 getter = gnc_option_getter (option);
1857 if (getter == SCM_UNDEFINED)
1858 return default_value;
1859
1860 return scm_call_0 (getter);
1861 }
1862
1863 /********************************************************************\
1864 * gnc_option_db_lookup_boolean_option *
1865 * looks up a boolean option. If present, returns its value, *
1866 * otherwise returns the default. *
1867 * *
1868 * Args: odb - option database to search in *
1869 * section - section name of option *
1870 * name - name of option *
1871 * default - default value if not found *
1872 * Return: gboolean option value *
1873 \********************************************************************/
1874 gboolean
gnc_option_db_lookup_boolean_option(GNCOptionDB * odb,const char * section,const char * name,gboolean default_value)1875 gnc_option_db_lookup_boolean_option (GNCOptionDB *odb,
1876 const char *section,
1877 const char *name,
1878 gboolean default_value)
1879 {
1880 GNCOption *option;
1881 SCM getter;
1882 SCM value;
1883
1884 option = gnc_option_db_get_option_by_name (odb, section, name);
1885
1886 if (option == NULL)
1887 return default_value;
1888
1889 getter = gnc_option_getter (option);
1890 if (getter == SCM_UNDEFINED)
1891 return default_value;
1892
1893 value = scm_call_0 (getter);
1894
1895 if (scm_is_bool (value))
1896 return scm_is_true (value);
1897 else
1898 return default_value;
1899 }
1900
1901 /********************************************************************\
1902 * gnc_option_db_lookup_string_option *
1903 * looks up a string option. If present, returns its malloc'ed *
1904 * value, otherwise returns the strdup'ed default, or NULL if *
1905 * default was NULL. *
1906 * *
1907 * Args: odb - option database to search in *
1908 * section - section name of option *
1909 * name - name of option *
1910 * default - default value if not found *
1911 * Return: char * option value *
1912 \********************************************************************/
1913 char *
gnc_option_db_lookup_string_option(GNCOptionDB * odb,const char * section,const char * name,const char * default_value)1914 gnc_option_db_lookup_string_option (GNCOptionDB *odb,
1915 const char *section,
1916 const char *name,
1917 const char *default_value)
1918 {
1919 GNCOption *option;
1920 SCM getter;
1921 SCM value;
1922
1923 option = gnc_option_db_get_option_by_name (odb, section, name);
1924
1925 if (option != NULL)
1926 {
1927 getter = gnc_option_getter (option);
1928 if (getter != SCM_UNDEFINED)
1929 {
1930 value = scm_call_0 (getter);
1931 if (scm_is_string (value))
1932 return gnc_scm_to_utf8_string (value);
1933 }
1934 }
1935
1936 if (default_value == NULL)
1937 return NULL;
1938
1939 return strdup (default_value);
1940 }
1941
1942 /********************************************************************\
1943 * gnc_option_db_lookup_font_option *
1944 * looks up a font option. If present, returns its malloc'ed *
1945 * string value, otherwise returns the strdup'ed default, or NULL *
1946 * if default was NULL. *
1947 * *
1948 * Args: odb - option database to search in *
1949 * section - section name of option *
1950 * name - name of option *
1951 * default - default value if not found *
1952 * Return: char * option value *
1953 \********************************************************************/
1954 char *
gnc_option_db_lookup_font_option(GNCOptionDB * odb,const char * section,const char * name,const char * default_value)1955 gnc_option_db_lookup_font_option (GNCOptionDB *odb,
1956 const char *section,
1957 const char *name,
1958 const char *default_value)
1959 {
1960 return gnc_option_db_lookup_string_option (odb, section, name, default_value);
1961 }
1962
1963 /********************************************************************\
1964 * gnc_option_db_lookup_multichoice_option *
1965 * looks up a multichoice option. If present, returns its *
1966 * name as a malloc'ed string *
1967 * value, otherwise returns the strdup'ed default, or NULL if *
1968 * default was NULL. *
1969 * *
1970 * Args: odb - option database to search in *
1971 * section - section name of option *
1972 * name - name of option *
1973 * default - default value if not found *
1974 * Return: char * option value *
1975 \********************************************************************/
1976 char *
gnc_option_db_lookup_multichoice_option(GNCOptionDB * odb,const char * section,const char * name,const char * default_value)1977 gnc_option_db_lookup_multichoice_option (GNCOptionDB *odb,
1978 const char *section,
1979 const char *name,
1980 const char *default_value)
1981 {
1982 GNCOption *option;
1983 SCM getter;
1984 SCM value;
1985
1986 option = gnc_option_db_get_option_by_name (odb, section, name);
1987
1988 if (option != NULL)
1989 {
1990 getter = gnc_option_getter (option);
1991 if (getter != SCM_UNDEFINED)
1992 {
1993 value = scm_call_0 (getter);
1994 if (scm_is_symbol (value))
1995 return gnc_scm_symbol_to_locale_string (value);
1996 }
1997 }
1998
1999 if (default_value == NULL)
2000 return NULL;
2001
2002 return strdup (default_value);
2003 }
2004
2005 /********************************************************************\
2006 * gnc_option_db_lookup_number_option *
2007 * looks up a number option. If present, returns its value *
2008 * as a gdouble, otherwise returns the default_value. *
2009 * *
2010 * Args: odb - option database to search in *
2011 * section - section name of option *
2012 * name - name of option *
2013 * default - default value if not found *
2014 * Return: gdouble representation of value *
2015 \********************************************************************/
2016 gdouble
gnc_option_db_lookup_number_option(GNCOptionDB * odb,const char * section,const char * name,gdouble default_value)2017 gnc_option_db_lookup_number_option (GNCOptionDB *odb,
2018 const char *section,
2019 const char *name,
2020 gdouble default_value)
2021 {
2022 GNCOption *option;
2023 SCM getter;
2024 SCM value;
2025
2026 option = gnc_option_db_get_option_by_name (odb, section, name);
2027
2028 if (option != NULL)
2029 {
2030 getter = gnc_option_getter (option);
2031 if (getter != SCM_UNDEFINED)
2032 {
2033 value = scm_call_0 (getter);
2034 if (scm_is_number (value))
2035 return scm_to_double (value);
2036 }
2037 }
2038 return default_value;
2039 }
2040
2041 /********************************************************************\
2042 * gnc_option_db_lookup_color_option *
2043 * looks up a color option. If present, returns its value in the *
2044 * color variable, otherwise leaves the color variable alone. *
2045 * *
2046 * Args: odb - option database to search in *
2047 * section - section name of option *
2048 * name - name of option *
2049 * red - where to store the red value *
2050 * blue - where to store the blue value *
2051 * green - where to store the green value *
2052 * alpha - where to store the alpha value *
2053 * Return: true if option was found *
2054 \********************************************************************/
gnc_option_db_lookup_color_option(GNCOptionDB * odb,const char * section,const char * name,gdouble * red,gdouble * green,gdouble * blue,gdouble * alpha)2055 gboolean gnc_option_db_lookup_color_option (GNCOptionDB *odb,
2056 const char *section,
2057 const char *name,
2058 gdouble *red,
2059 gdouble *green,
2060 gdouble *blue,
2061 gdouble *alpha)
2062 {
2063 GNCOption *option;
2064
2065 option = gnc_option_db_get_option_by_name (odb, section, name);
2066
2067 return gnc_option_get_color_info (option, FALSE, red, green, blue, alpha);
2068 }
2069
2070 /********************************************************************\
2071 * gnc_option_db_lookup_color_option_argb *
2072 * looks up a color option. If present, returns its argb value, *
2073 * otherwise returns the given default value. *
2074 * *
2075 * Args: odb - option database to search in *
2076 * section - section name of option *
2077 * name - name of option *
2078 * default_value - default value to return if problem *
2079 * Return: argb value *
2080 \********************************************************************/
gnc_option_db_lookup_color_option_argb(GNCOptionDB * odb,const char * section,const char * name,guint32 default_value)2081 guint32 gnc_option_db_lookup_color_option_argb (GNCOptionDB *odb,
2082 const char *section,
2083 const char *name,
2084 guint32 default_value)
2085 {
2086 GNCOption *option;
2087
2088 option = gnc_option_db_get_option_by_name (odb, section, name);
2089 if (option == NULL)
2090 return default_value;
2091
2092 return gnc_option_get_color_argb (option);
2093 }
2094
2095 /********************************************************************\
2096 * gnc_option_db_lookup_list_option *
2097 * looks up a list option. If present, returns its value as a *
2098 * list of strings representing the symbols. *
2099 * *
2100 * Args: odb - option database to search in *
2101 * section - section name of option *
2102 * name - name of option *
2103 * default_value - default value to return if problem *
2104 * Return: list of values *
2105 \********************************************************************/
2106 GSList *
gnc_option_db_lookup_list_option(GNCOptionDB * odb,const char * section,const char * name,GSList * default_value)2107 gnc_option_db_lookup_list_option (GNCOptionDB *odb,
2108 const char *section,
2109 const char *name,
2110 GSList *default_value)
2111 {
2112 GNCOption *option;
2113 GSList *list = NULL;
2114 SCM getter;
2115 SCM value;
2116 SCM item;
2117
2118 option = gnc_option_db_get_option_by_name (odb, section, name);
2119 if (option == NULL)
2120 return default_value;
2121
2122 getter = gnc_option_getter (option);
2123 if (getter == SCM_UNDEFINED)
2124 return default_value;
2125
2126 value = scm_call_0 (getter);
2127 while (scm_is_list (value) && !scm_is_null (value))
2128 {
2129 item = SCM_CAR(value);
2130 value = SCM_CDR(value);
2131
2132 if (!scm_is_symbol (item))
2133 {
2134 gnc_free_list_option_value (list);
2135
2136 return default_value;
2137 }
2138
2139 list = g_slist_prepend (list, gnc_scm_symbol_to_locale_string (item));
2140 }
2141
2142 if (!scm_is_list (value) || !scm_is_null (value))
2143 {
2144 gnc_free_list_option_value (list);
2145
2146 return default_value;
2147 }
2148 return list;
2149 }
2150
2151 /********************************************************************\
2152 * gnc_option_db_lookup_currency_option *
2153 * looks up a currency option. If present, returns its value as a *
2154 * gnc_commodity object. *
2155 * *
2156 * Args: odb - option database to search in *
2157 * section - section name of option *
2158 * name - name of option *
2159 * default_value - default value to return if problem *
2160 * Return: commodity or NULL if no commodity found *
2161 \********************************************************************/
2162 gnc_commodity *
gnc_option_db_lookup_currency_option(GNCOptionDB * odb,const char * section,const char * name,gnc_commodity * default_value)2163 gnc_option_db_lookup_currency_option (GNCOptionDB *odb,
2164 const char *section,
2165 const char *name,
2166 gnc_commodity *default_value)
2167 {
2168 GNCOption *option;
2169 SCM getter;
2170 SCM value;
2171
2172 option = gnc_option_db_get_option_by_name (odb, section, name);
2173 if (option == NULL)
2174 return default_value;
2175
2176 getter = gnc_option_getter (option);
2177 if (getter == SCM_UNDEFINED)
2178 return default_value;
2179
2180 value = scm_call_0 (getter);
2181
2182 return gnc_scm_to_commodity (value);
2183 }
2184
2185 static void
free_helper(gpointer string,gpointer not_used)2186 free_helper (gpointer string, gpointer not_used)
2187 {
2188 if (string)
2189 free (string);
2190 }
2191
2192 void
gnc_free_list_option_value(GSList * list)2193 gnc_free_list_option_value (GSList *list)
2194 {
2195 g_slist_foreach (list, free_helper, NULL);
2196 g_slist_free (list);
2197 }
2198
2199 /********************************************************************\
2200 * gnc_option_db_set_option_default *
2201 * set the option to its default value *
2202 * *
2203 * Args: odb - option database to search in *
2204 * section - section name of option *
2205 * name - name of option *
2206 * Returns: nothing *
2207 \********************************************************************/
2208 void
gnc_option_db_set_option_default(GNCOptionDB * odb,const char * section,const char * name)2209 gnc_option_db_set_option_default (GNCOptionDB *odb,
2210 const char *section,
2211 const char *name)
2212 {
2213 GNCOption *option;
2214
2215 option = gnc_option_db_get_option_by_name (odb, section, name);
2216
2217 gnc_option_set_default (option);
2218 }
2219
2220 /********************************************************************\
2221 * gnc_option_db_set_option *
2222 * sets the option to the given value. If successful *
2223 * returns TRUE, otherwise FALSE. *
2224 * *
2225 * Args: odb - option database to search in *
2226 * section - section name of option *
2227 * name - name of option *
2228 * value - value to set to *
2229 * Return: success indicator *
2230 \********************************************************************/
2231 gboolean
gnc_option_db_set_option(GNCOptionDB * odb,const char * section,const char * name,SCM value)2232 gnc_option_db_set_option (GNCOptionDB *odb,
2233 const char *section,
2234 const char *name,
2235 SCM value)
2236 {
2237 GNCOption *option;
2238 SCM setter;
2239
2240 option = gnc_option_db_get_option_by_name (odb, section, name);
2241 if (option == NULL)
2242 return FALSE;
2243
2244 value = gnc_option_valid_value (option, value);
2245 if (value == SCM_UNDEFINED)
2246 return FALSE;
2247
2248 setter = gnc_option_setter (option);
2249 if (setter == SCM_UNDEFINED)
2250 return FALSE;
2251
2252 scm_call_1 (setter, value);
2253
2254 return TRUE;
2255 }
2256
2257 /********************************************************************\
2258 * gnc_option_db_set_number_option *
2259 * sets the number option to the given value. If successful *
2260 * returns TRUE, otherwise FALSE. *
2261 * *
2262 * Args: odb - option database to search in *
2263 * section - section name of option *
2264 * name - name of option *
2265 * value - value to set to *
2266 * Return: success indicator *
2267 \********************************************************************/
2268 gboolean
gnc_option_db_set_number_option(GNCOptionDB * odb,const char * section,const char * name,gdouble value)2269 gnc_option_db_set_number_option (GNCOptionDB *odb,
2270 const char *section,
2271 const char *name,
2272 gdouble value)
2273 {
2274 GNCOption *option;
2275 SCM scm_value;
2276 SCM setter;
2277
2278 option = gnc_option_db_get_option_by_name (odb, section, name);
2279 if (option == NULL)
2280 return FALSE;
2281
2282 scm_value = scm_from_double (value);
2283
2284 scm_value = gnc_option_valid_value (option, scm_value);
2285 if (scm_value == SCM_UNDEFINED)
2286 return FALSE;
2287
2288 setter = gnc_option_setter (option);
2289 if (setter == SCM_UNDEFINED)
2290 return FALSE;
2291
2292 scm_call_1 (setter, scm_value);
2293
2294 return TRUE;
2295 }
2296
2297 /********************************************************************\
2298 * gnc_option_db_set_boolean_option *
2299 * sets the boolean option to the given value. If successful *
2300 * returns TRUE, otherwise FALSE. *
2301 * *
2302 * Args: odb - option database to search in *
2303 * section - section name of option *
2304 * name - name of option *
2305 * value - value to set to *
2306 * Return: success indicator *
2307 \********************************************************************/
2308 gboolean
gnc_option_db_set_boolean_option(GNCOptionDB * odb,const char * section,const char * name,gboolean value)2309 gnc_option_db_set_boolean_option (GNCOptionDB *odb,
2310 const char *section,
2311 const char *name,
2312 gboolean value)
2313 {
2314 GNCOption *option;
2315 SCM scm_value;
2316 SCM setter;
2317
2318 option = gnc_option_db_get_option_by_name (odb, section, name);
2319 if (option == NULL)
2320 return FALSE;
2321
2322 scm_value = SCM_BOOL(value);
2323
2324 scm_value = gnc_option_valid_value (option, scm_value);
2325 if (scm_value == SCM_UNDEFINED)
2326 return FALSE;
2327
2328 setter = gnc_option_setter (option);
2329 if (setter == SCM_UNDEFINED)
2330 return FALSE;
2331
2332 scm_call_1 (setter, scm_value);
2333
2334 return TRUE;
2335 }
2336
2337 /********************************************************************\
2338 * gnc_option_db_set_string_option *
2339 * sets the string option to the given value. If successful *
2340 * returns TRUE, otherwise FALSE. *
2341 * *
2342 * Args: odb - option database to search in *
2343 * section - section name of option *
2344 * name - name of option *
2345 * value - value to set to *
2346 * Return: success indicator *
2347 \********************************************************************/
2348 gboolean
gnc_option_db_set_string_option(GNCOptionDB * odb,const char * section,const char * name,const char * value)2349 gnc_option_db_set_string_option (GNCOptionDB *odb,
2350 const char *section,
2351 const char *name,
2352 const char *value)
2353 {
2354 GNCOption *option;
2355 SCM scm_value;
2356 SCM setter;
2357
2358 option = gnc_option_db_get_option_by_name (odb, section, name);
2359 if (option == NULL)
2360 return FALSE;
2361
2362 if (value)
2363 scm_value = scm_from_utf8_string (value);
2364 else
2365 scm_value = SCM_BOOL_F;
2366
2367 scm_value = gnc_option_valid_value (option, scm_value);
2368 if (scm_value == SCM_UNDEFINED)
2369 return FALSE;
2370
2371 setter = gnc_option_setter (option);
2372 if (setter == SCM_UNDEFINED)
2373 return FALSE;
2374
2375 scm_call_1 (setter, scm_value);
2376
2377 return TRUE;
2378 }
2379
2380 /*******************************************************************\
2381 * gnc_option_date_option_get_subtype *
2382 * find out whether a date option is a relative or absolute date *
2383 * *
2384 * Args: option - option to get date subtype for *
2385 * Return: newly allocated subtype string or NULL *
2386 \*******************************************************************/
2387 char *
gnc_option_date_option_get_subtype(GNCOption * option)2388 gnc_option_date_option_get_subtype (GNCOption *option)
2389 {
2390 initialize_getters ();
2391
2392 return gnc_scm_call_1_symbol_to_string (getters.date_option_subtype, option->guile_option);
2393 }
2394
2395 /*******************************************************************\
2396 * gnc_date_option_value_get_type *
2397 * get the type of a date option value *
2398 * *
2399 * Args: option_value - option value to get type of *
2400 * Return: newly allocated type string or NULL *
2401 \*******************************************************************/
2402 char *
gnc_date_option_value_get_type(SCM option_value)2403 gnc_date_option_value_get_type (SCM option_value)
2404 {
2405 initialize_getters ();
2406
2407 return gnc_scm_call_1_symbol_to_string (getters.date_option_value_type, option_value);
2408 }
2409
2410 /*******************************************************************\
2411 * gnc_date_option_value_get_absolute *
2412 * get the absolute time of a date option value *
2413 * *
2414 * Args: option_value - option value to get absolute time of *
2415 * Return: time64 value *
2416 \*******************************************************************/
2417 time64
gnc_date_option_value_get_absolute(SCM option_value)2418 gnc_date_option_value_get_absolute (SCM option_value)
2419 {
2420 SCM value;
2421 initialize_getters ();
2422 value = scm_call_1 (getters.date_option_value_absolute, option_value);
2423 return scm_to_int64 (value);
2424 }
2425
2426 /*******************************************************************\
2427 * gnc_date_option_value_get_relative *
2428 * get the relative time of a date option value *
2429 * *
2430 * Args: option_value - option value to get relative time of *
2431 * Return: SCM value *
2432 \*******************************************************************/
2433 SCM
gnc_date_option_value_get_relative(SCM option_value)2434 gnc_date_option_value_get_relative (SCM option_value)
2435 {
2436 initialize_getters ();
2437
2438 return scm_call_1 (getters.date_option_value_relative, option_value);
2439 }
2440
2441 /*******************************************************************\
2442 * gnc_plot_size_option_value_get_type *
2443 * get the type of a plot size option value *
2444 * *
2445 * Args: option_value - option value to get type of *
2446 * Return: newly allocated type string or NULL *
2447 \*******************************************************************/
2448 char *
gnc_plot_size_option_value_get_type(SCM option_value)2449 gnc_plot_size_option_value_get_type (SCM option_value)
2450 {
2451 initialize_getters ();
2452
2453 return gnc_scm_call_1_symbol_to_string (getters.plot_size_option_value_type, option_value);
2454 }
2455
2456 /*******************************************************************\
2457 * gnc_plot_size_option_value_get_value *
2458 * get the plot size option value *
2459 * *
2460 * Args: option_value - option value to get the plot size of *
2461 * Return: double value *
2462 \*******************************************************************/
2463 gdouble
gnc_plot_size_option_value_get_value(SCM option_value)2464 gnc_plot_size_option_value_get_value (SCM option_value)
2465 {
2466 SCM value;
2467
2468 initialize_getters ();
2469
2470 value = scm_call_1 (getters.plot_size_option_value, option_value);
2471
2472 if (scm_is_number (value))
2473 return scm_to_double (value);
2474 else
2475 return 1.0;
2476 }
2477
2478 /********************************************************************\
2479 * gnc_currency_accounting_option_currency_documentation *
2480 * returns the malloc'ed documentation string for currency *
2481 * selector of the currency-accounting option, or NULL if it *
2482 * can't be retrieved. *
2483 * *
2484 * Args: option - the GNCOption *
2485 * Returns: malloc'ed char * or NULL *
2486 \********************************************************************/
2487 char *
gnc_currency_accounting_option_currency_documentation(GNCOption * option)2488 gnc_currency_accounting_option_currency_documentation (GNCOption *option)
2489 {
2490 initialize_getters ();
2491
2492 return gnc_scm_call_1_to_string
2493 (getters.currency_accounting_option_currency_doc_string,
2494 option->guile_option);
2495 }
2496
2497 /********************************************************************\
2498 * gnc_currency_accounting_option_get_default_currency *
2499 * returns the SCM value for the currency-accounting option *
2500 * default currency. *
2501 * *
2502 * Args: option - the GNCOption *
2503 * Returns: SCM value *
2504 \********************************************************************/
2505 SCM
gnc_currency_accounting_option_get_default_currency(GNCOption * option)2506 gnc_currency_accounting_option_get_default_currency (GNCOption *option)
2507 {
2508 initialize_getters ();
2509
2510 return scm_call_1
2511 (getters.currency_accounting_option_default_currency,
2512 option->guile_option);
2513 }
2514
2515 /********************************************************************\
2516 * gnc_currency_accounting_option_policy_documentation *
2517 * returns the malloc'ed documentation string for policy *
2518 * selector of the currency-accounting option, or NULL if it *
2519 * can't be retrieved. *
2520 * *
2521 * Args: option - the GNCOption *
2522 * Returns: malloc'ed char * or NULL *
2523 \********************************************************************/
2524 char *
gnc_currency_accounting_option_policy_documentation(GNCOption * option)2525 gnc_currency_accounting_option_policy_documentation (GNCOption *option)
2526 {
2527 initialize_getters ();
2528
2529 return gnc_scm_call_1_to_string
2530 (getters.currency_accounting_option_policy_doc_string,
2531 option->guile_option);
2532 }
2533
2534 /********************************************************************\
2535 * gnc_currency_accounting_option_get_default_policy *
2536 * returns the SCM value for the currency-accounting option *
2537 * default policy. *
2538 * *
2539 * Args: option - the GNCOption *
2540 * Returns: SCM value *
2541 \********************************************************************/
2542 SCM
gnc_currency_accounting_option_get_default_policy(GNCOption * option)2543 gnc_currency_accounting_option_get_default_policy (GNCOption *option)
2544 {
2545 initialize_getters ();
2546
2547 return scm_call_1
2548 (getters.currency_accounting_option_default_policy,
2549 option->guile_option);
2550 }
2551
2552 /********************************************************************\
2553 * gnc_currency_accounting_option_gain_loss_account_documentation *
2554 * returns the malloc'ed documentation string for account *
2555 * selector of the currency-accounting option, or NULL if it *
2556 * can't be retrieved. *
2557 * *
2558 * Args: option - the GNCOption *
2559 * Returns: malloc'ed char * or NULL *
2560 \********************************************************************/
2561 char *
gnc_currency_accounting_option_gain_loss_account_documentation(GNCOption * option)2562 gnc_currency_accounting_option_gain_loss_account_documentation (GNCOption *option)
2563 {
2564 initialize_getters ();
2565
2566 return gnc_scm_call_1_to_string
2567 (getters.currency_accounting_option_gain_loss_account_doc_string,
2568 option->guile_option);
2569 }
2570
2571 /*******************************************************************\
2572 * gnc_currency_accounting_option_value_get_method *
2573 * get the currency accounting method of the option as a symbol *
2574 * *
2575 * Args: option_value - option value to get method of *
2576 * Return: SCM value *
2577 \*******************************************************************/
2578 SCM
gnc_currency_accounting_option_value_get_method(SCM option_value)2579 gnc_currency_accounting_option_value_get_method (SCM option_value)
2580 {
2581 initialize_getters ();
2582
2583 return scm_call_1 (getters.currency_accounting_option_method,
2584 option_value);
2585 }
2586
2587 /*******************************************************************\
2588 * gnc_currency_accounting_option_value_get_book_currency *
2589 * get the book-currency if that is the currency accounting *
2590 * method of the option as a symbol *
2591 * *
2592 * Args: option_value - option value to get method of *
2593 * Return: SCM value *
2594 \*******************************************************************/
2595 SCM
gnc_currency_accounting_option_value_get_book_currency(SCM option_value)2596 gnc_currency_accounting_option_value_get_book_currency (SCM option_value)
2597 {
2598 initialize_getters ();
2599
2600 return scm_call_1 (getters.currency_accounting_option_book_currency,
2601 option_value);
2602 }
2603
2604 /*******************************************************************\
2605 * gnc_currency_accounting_option_value_get_default_policy *
2606 * get the default policy if book-currency is the currency *
2607 * accounting method of the option as a symbol *
2608 * *
2609 * Args: option_value - option value to get method of *
2610 * Return: SCM value *
2611 \*******************************************************************/
2612 SCM
gnc_currency_accounting_option_value_get_default_policy(SCM option_value)2613 gnc_currency_accounting_option_value_get_default_policy (SCM option_value)
2614 {
2615 initialize_getters ();
2616
2617 return scm_call_1
2618 (getters.currency_accounting_option_selected_default_policy,
2619 option_value);
2620 }
2621
2622 /*******************************************************************\
2623 * gnc_currency_accounting_option_value_get_default_account *
2624 * get the default gain/loss account if book-currency is the *
2625 * currency accounting method, if one is specified, of the *
2626 * option as a symbol *
2627 * *
2628 * Args: option_value - option value to get method of *
2629 * Return: SCM value *
2630 \*******************************************************************/
2631 SCM
gnc_currency_accounting_option_value_get_default_account(SCM option_value)2632 gnc_currency_accounting_option_value_get_default_account (SCM option_value)
2633 {
2634 initialize_getters ();
2635
2636 return scm_call_1
2637 (getters.currency_accounting_option_selected_default_gain_loss_account,
2638 option_value);
2639 }
2640
2641 static int
find_option_db_with_selectable_pred(gpointer key,gpointer value,gpointer data)2642 find_option_db_with_selectable_pred (gpointer key, gpointer value, gpointer data)
2643 {
2644 SCM guile_options = data;
2645 GNCOptionDB *odb = value;
2646
2647 if (odb && (odb->guile_options == guile_options) && odb->set_selectable)
2648 return TRUE;
2649
2650 return FALSE;
2651 }
2652
2653 static GNCOptionDB *
find_option_db_with_selectable(SCM guile_options)2654 find_option_db_with_selectable (SCM guile_options)
2655 {
2656 return g_hash_table_find (option_dbs, find_option_db_with_selectable_pred,
2657 guile_options);
2658 }
2659
2660 /*******************************************************************\
2661 * gnc_option_db_set_option_selectable_by_name *
2662 * set the sensitivity of the option widget *
2663 * *
2664 * Args: guile_options - guile side option db *
2665 * section - section of option *
2666 * name - name of option *
2667 * selectable - selectable status *
2668 * Return: SCM value *
2669 \*******************************************************************/
2670 void
gnc_option_db_set_option_selectable_by_name(SCM guile_options,const char * section,const char * name,gboolean selectable)2671 gnc_option_db_set_option_selectable_by_name (SCM guile_options,
2672 const char *section,
2673 const char *name,
2674 gboolean selectable)
2675 {
2676 GNCOptionDB *odb;
2677 GNCOption *option;
2678
2679 odb = find_option_db_with_selectable (guile_options);
2680 if (!odb)
2681 return;
2682
2683 option = gnc_option_db_get_option_by_name (odb, section, name);
2684 if (!option)
2685 return;
2686
2687 gnc_option_set_selectable (option, selectable);
2688 }
2689
2690 /* the value is a list of:
2691 * format(symbol), month(symbol), include-years(bool), custom-string(string)
2692 */
2693
gnc_dateformat_option_value_parse(SCM value,QofDateFormat * format,GNCDateMonthFormat * months,gboolean * years,char ** custom)2694 gboolean gnc_dateformat_option_value_parse (SCM value,
2695 QofDateFormat *format,
2696 GNCDateMonthFormat *months,
2697 gboolean *years,
2698 char **custom)
2699 {
2700 SCM val;
2701 gchar *str;
2702
2703 if (!scm_is_list (value) || scm_is_null (value))
2704 return TRUE;
2705
2706 do
2707 {
2708 /* Parse the format */
2709 val = SCM_CAR(value);
2710 value = SCM_CDR(value);
2711 if (!scm_is_symbol (val))
2712 break;
2713 str = gnc_scm_symbol_to_locale_string (val);
2714 if (!str)
2715 break;
2716
2717 if (format)
2718 {
2719 if (gnc_date_string_to_dateformat (str, format))
2720 {
2721 g_free (str);
2722 break;
2723 }
2724 }
2725 g_free (str);
2726
2727 /* parse the months */
2728 val = SCM_CAR(value);
2729 value = SCM_CDR(value);
2730 if (!scm_is_symbol (val))
2731 break;
2732 str = gnc_scm_symbol_to_locale_string (val);
2733 if (!str)
2734 break;
2735
2736 if (months)
2737 {
2738 if (gnc_date_string_to_monthformat (str, months))
2739 {
2740 g_free (str);
2741 break;
2742 }
2743 }
2744 g_free (str);
2745
2746 /* parse the years */
2747 val = SCM_CAR(value);
2748 value = SCM_CDR(value);
2749 if (!scm_is_bool (val))
2750 break;
2751
2752 if (years)
2753 *years = scm_is_true (val);
2754
2755 /* parse the custom */
2756 val = SCM_CAR(value);
2757 value = SCM_CDR(value);
2758 if (!scm_is_string (val))
2759 break;
2760 if (!scm_is_null (value))
2761 break;
2762
2763 if (custom)
2764 *custom = gnc_scm_to_utf8_string (val);
2765
2766 return FALSE;
2767 }
2768 while (FALSE);
2769
2770 return TRUE;
2771 }
2772
gnc_dateformat_option_set_value(QofDateFormat format,GNCDateMonthFormat months,gboolean years,const char * custom)2773 SCM gnc_dateformat_option_set_value (QofDateFormat format,
2774 GNCDateMonthFormat months,
2775 gboolean years,
2776 const char *custom)
2777 {
2778 SCM value = SCM_EOL;
2779 SCM val;
2780 const char *str;
2781
2782 /* build the list in reverse order */
2783 if (custom)
2784 val = scm_from_utf8_string (custom);
2785 else
2786 val = SCM_BOOL_F;
2787 value = scm_cons (val, value);
2788
2789 val = SCM_BOOL(years);
2790 value = scm_cons (val, value);
2791
2792 str = gnc_date_monthformat_to_string (months);
2793 if (str)
2794 val = scm_from_locale_symbol (str);
2795 else
2796 val = SCM_BOOL_F;
2797 value = scm_cons (val, value);
2798
2799 str = gnc_date_dateformat_to_string (format);
2800 if (str)
2801 val = scm_from_locale_symbol (str);
2802 else
2803 val = SCM_BOOL_F;
2804 value = scm_cons (val, value);
2805
2806 return value;
2807 }
2808
2809 /*
2810 * the generator should be a procedure that takes one argument,
2811 * an options object. The procedure should fill in the options with
2812 * its defined kvp options.
2813 */
2814 void
gnc_register_kvp_option_generator(QofIdType id_type,SCM generator)2815 gnc_register_kvp_option_generator (QofIdType id_type, SCM generator)
2816 {
2817 GList *list;
2818 init_table();
2819 list = g_hash_table_lookup (kvp_registry, id_type);
2820 list = g_list_prepend (list, generator);
2821 g_hash_table_insert (kvp_registry, (gpointer) id_type, list);
2822 scm_gc_protect_object (generator);
2823 }
2824