GnuCash  4.8a-134-g214de30c7+
option-util.c
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 
63 {
64  char * section_name;
65 
66  GSList * options;
67 };
68 
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
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
143 gnc_option_get_widget (GNCOption *option)
144 {
145  if (!option) return NULL;
146  return option->widget;
147 }
148 
149 void
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
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
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
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
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 *
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
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
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 *
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
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
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
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
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
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
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
512 gncp_option_invoke_callback (GNCOptionChangeCallback callback, void *data)
513 {
514  callback (data);
515 }
516 
517 static void
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
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 *
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 *
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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 *
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 \********************************************************************/
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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 *
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 *
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, &section_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 *
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
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*
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
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*
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
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
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 *
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
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
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 *
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 *
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 *
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
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 \********************************************************************/
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 \********************************************************************/
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 *
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 *
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
2186 free_helper (gpointer string, gpointer not_used)
2187 {
2188  if (string)
2189  free (string);
2190 }
2191 
2192 void
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
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
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
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
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
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 *
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 *
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
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
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 *
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
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 *
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
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 *
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
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 *
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
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
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
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
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
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 *
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
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 
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 
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
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 }
gboolean gnc_date_string_to_monthformat(const gchar *format_string, GNCDateMonthFormat *format)
Converts the month format to a printable string.
const char * gnc_date_dateformat_to_string(QofDateFormat format)
The string->value versions return FALSE on success and TRUE on failure.
Definition: gnc-date.cpp:291
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
const gchar * QofIdType
QofIdType declaration.
Definition: qofid.h:85
Account handling public routines.
GNCDateMonthFormat
This is how to format the month, as a number, an abbreviated string, or the full name.
Definition: gnc-date.h:158
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
Definition: Account.h:105
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
gboolean gnc_date_string_to_dateformat(const gchar *format_string, QofDateFormat *format)
Converts the date format to a printable string.
QofDateFormat
Enum for determining a date format.
Definition: gnc-date.h:128