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