GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
engine-helpers.c
1 /********************************************************************\
2  * engine-helpers.c -- gnucash engine helper functions *
3  * Copyright (C) 2000 Linas Vepstas <[email protected]> *
4  * Copyright (C) 2001 Linux Developers Group, Inc. *
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 [email protected] *
22  * *
23 \********************************************************************/
24 
25 #include "config.h"
26 
27 #include "swig-runtime.h"
28 #include <libguile.h>
29 #include <string.h>
30 
31 #include "Account.h"
32 #include "engine-helpers.h"
33 #include "engine-helpers-guile.h"
34 #include "glib-helpers.h"
35 #include "gnc-date.h"
36 #include "gnc-engine.h"
37 #include "gnc-session.h"
38 #include "guile-mappings.h"
39 #include "gnc-guile-utils.h"
40 #include "qof.h"
41 #include "qofbookslots.h"
46 #include "qofquery-p.h"
47 #include "qofquerycore-p.h"
48 
49 #define FUNC_NAME G_STRFUNC
50 
51 static QofLogModule log_module = GNC_MOD_ENGINE;
52 
54 gnc_transaction_get_date_posted(const Transaction *t)
55 {
56  Timespec result;
57  xaccTransGetDatePostedTS(t, &result);
58  return(result);
59 }
60 
62 gnc_transaction_get_date_entered(const Transaction *t)
63 {
64  Timespec result;
65  xaccTransGetDateEnteredTS(t, &result);
66  return(result);
67 }
68 
70 gnc_split_get_date_reconciled(const Split *s)
71 {
72  Timespec result;
73  xaccSplitGetDateReconciledTS(s, &result);
74  return(result);
75 }
76 
77 void
78 gnc_transaction_set_date(Transaction *t, Timespec ts)
79 {
81 }
82 
90 const char *
91 gnc_get_num_action (const Transaction *trans, const Split *split)
92 {
93  gboolean num_action = qof_book_use_split_action_for_num_field
94  (qof_session_get_book(gnc_get_current_session ()));
95 
96  if (trans && !split)
97  return xaccTransGetNum(trans);
98  if (split && !trans)
99  return xaccSplitGetAction(split);
100  if (trans && split)
101  {
102  if (num_action)
103  return xaccSplitGetAction(split);
104  else
105  return xaccTransGetNum(trans);
106  }
107  else return NULL;
108 }
109 
116 const char *
117 gnc_get_action_num (const Transaction *trans, const Split *split)
118 {
119  gboolean num_action = qof_book_use_split_action_for_num_field
120  (qof_session_get_book(gnc_get_current_session ()));
121 
122  if (trans && !split)
123  return xaccTransGetNum(trans);
124  if (split && !trans)
125  return xaccSplitGetAction(split);
126  if (trans && split)
127  {
128  if (num_action)
129  return xaccTransGetNum(trans);
130  else
131  return xaccSplitGetAction(split);
132  }
133  else return NULL;
134 }
135 
147 void
148 gnc_set_num_action (Transaction *trans, Split *split,
149  const char *num, const char *action)
150 {
151  gboolean num_action = qof_book_use_split_action_for_num_field
152  (qof_session_get_book(gnc_get_current_session ()));
153 
154  if (trans && num && !split && !action)
155  {
156  xaccTransSetNum (trans, num);
157  return;
158  }
159 
160  if (!trans && !num && split && action)
161  {
162  xaccSplitSetAction (split, action);
163  return;
164  }
165 
166  if (trans)
167  {
168  if (!num_action && num)
169  xaccTransSetNum (trans, num);
170  if (num_action && action)
171  xaccTransSetNum (trans, action);
172  }
173 
174  if (split)
175  {
176  if (!num_action && action)
177  xaccSplitSetAction (split, action);
178  if (num_action && num)
179  xaccSplitSetAction (split, num);
180  }
181 }
182 
183 /************************************************************/
184 /* Notification of Book Option Changes */
185 /************************************************************/
186 
187 static GOnce bo_init_once = G_ONCE_INIT;
188 static GHashTable *bo_callback_hash = NULL;
189 static GHookList *bo_final_hook_list = NULL;
190 
191 static gpointer
192 bo_init (gpointer unused)
193 {
194  bo_callback_hash = g_hash_table_new(g_str_hash, g_str_equal);
195 
196  bo_final_hook_list = g_malloc(sizeof(GHookList));
197  g_hook_list_init(bo_final_hook_list, sizeof(GHook));
198  return NULL;
199 }
200 
201 static void
202 bo_call_hook (GHook *hook, gpointer data)
203 {
204  ((GFunc)hook->func)(data, hook->data);
205 }
206 
209 void
210 gnc_book_option_num_field_source_change (gboolean num_action)
211 {
212  GHookList *hook_list;
213  const gchar *key = OPTION_NAME_NUM_FIELD_SOURCE;
214 
215  g_once(&bo_init_once, bo_init, NULL);
216 
217  hook_list = g_hash_table_lookup(bo_callback_hash, key);
218  if (hook_list != NULL)
219  g_hook_list_marshal(hook_list, TRUE, bo_call_hook, &num_action);
220  g_hook_list_invoke(bo_final_hook_list, TRUE);
221 }
222 
223 void
224 gnc_book_option_register_cb (gchar *key, GncBOCb func, gpointer user_data)
225 {
226  GHookList *hook_list;
227  GHook *hook;
228 
229  g_once(&bo_init_once, bo_init, NULL);
230  hook_list = g_hash_table_lookup(bo_callback_hash, key);
231  if (hook_list == NULL)
232  {
233  hook_list = g_malloc(sizeof(GHookList));
234  g_hook_list_init(hook_list, sizeof(GHook));
235  g_hash_table_insert(bo_callback_hash, (gpointer)key, hook_list);
236  }
237 
238  hook = g_hook_find_func_data(hook_list, TRUE, func, user_data);
239  if (hook != NULL)
240  {
241  return;
242  }
243 
244  hook = g_hook_alloc(hook_list);
245  hook->func = func;
246  hook->data = user_data;
247  g_hook_append(hook_list, hook);
248 }
249 
250 void
251 gnc_book_option_remove_cb (gchar *key, GncBOCb func, gpointer user_data)
252 {
253  GHookList *hook_list;
254  GHook *hook;
255 
256  g_once(&bo_init_once, bo_init, NULL);
257  hook_list = g_hash_table_lookup(bo_callback_hash, key);
258  if (hook_list == NULL)
259  return;
260  hook = g_hook_find_func_data(hook_list, TRUE, func, user_data);
261  if (hook == NULL)
262  return;
263 
264  g_hook_destroy_link(hook_list, hook);
265  if (hook_list->hooks == NULL)
266  {
267  g_hash_table_remove(bo_callback_hash, key);
268  g_free(hook_list);
269  }
270 }
271 
272 SCM
273 gnc_timespec2timepair(Timespec t)
274 {
275  SCM secs;
276  SCM nsecs;
277 
278  secs = scm_from_int64(t.tv_sec);
279  nsecs = scm_from_long (t.tv_nsec);
280  return(scm_cons(secs, nsecs));
281 }
282 
283 Timespec
284 gnc_timepair2timespec(SCM x)
285 {
286  Timespec result = {0, 0};
287  if (gnc_timepair_p (x))
288  {
289  result.tv_sec = scm_to_int64(SCM_CAR(x));
290  result.tv_nsec = scm_to_long(SCM_CDR(x));
291  }
292  return(result);
293 }
294 
295 GDate gnc_timepair_to_GDate(SCM x)
296 {
297  Timespec tspec = gnc_timepair2timespec(x);
298  return timespec_to_gdate(tspec);
299 }
300 
301 int
302 gnc_timepair_p(SCM x)
303 {
304  return(scm_is_pair(x) &&
305  gnc_gh_gint64_p(SCM_CAR(x)) &&
306  gnc_gh_gint64_p(SCM_CDR(x)));
307 }
308 
309 SCM
310 gnc_guid2scm(GncGUID guid)
311 {
312  char string[GUID_ENCODING_LENGTH + 1];
313 
314  if (!guid_to_string_buff(&guid, string))
315  return SCM_BOOL_F;
316 
317  return scm_from_utf8_string(string);
318 }
319 
320 GncGUID
321 gnc_scm2guid(SCM guid_scm)
322 {
323  GncGUID guid;
324  gchar * str;
325 
326  if (!scm_is_string(guid_scm)
327  || (GUID_ENCODING_LENGTH != scm_c_string_length (guid_scm)))
328  {
329  return *guid_null();
330  }
331  str = gnc_scm_to_utf8_string (guid_scm);
332  string_to_guid(str, &guid);
333  g_free (str);
334  return guid;
335 }
336 
337 int
338 gnc_guid_p(SCM guid_scm)
339 {
340  GncGUID guid;
341  gchar * str;
342  int return_int;
343 
344  if (!scm_is_string(guid_scm))
345  return FALSE;
346 
347  if (GUID_ENCODING_LENGTH != scm_c_string_length (guid_scm))
348  {
349  return FALSE;
350  }
351  str = gnc_scm_to_utf8_string (guid_scm);
352  return_int = string_to_guid(str, &guid);
353  g_free (str);
354  return return_int;
355 }
356 
357 
358 /********************************************************************
359  * type converters for query API
360  ********************************************************************/
361 
362 /* The query scm representation is a list of pairs, where the
363  * car of each pair is one of the following symbols:
364  *
365  * Symbol cdr
366  * 'terms list of OR terms
367  * 'primary-sort scm rep of sort_type_t
368  * 'secondary-sort scm rep of sort_type_t
369  * 'tertiary-sort scm rep of sort_type_t
370  * 'primary-increasing boolean
371  * 'secondary-increasing boolean
372  * 'tertiary-increasing boolean
373  * 'max-splits integer
374  *
375  * Each OR term is a list of AND terms.
376  * Each AND term is a list of one of the following forms:
377  *
378  * ('pd-date pr-type sense-bool use-start-bool start-timepair
379  * use-end-bool use-end-timepair)
380  * ('pd-amount pr-type sense-bool amt-match-how amt-match-sign amount)
381  * ('pd-account pr-type sense-bool acct-match-how list-of-account-guids)
382  * ('pd-string pr-type sense-bool case-sense-bool use-regexp-bool string)
383  * ('pd-cleared pr-type sense-bool cleared-field)
384  * ('pd-balance pr-type sense-bool balance-field)
385  */
386 
387 typedef enum
388 {
389  gnc_QUERY_v1 = 1,
390  gnc_QUERY_v2
391 } query_version_t;
392 
393 /* QofCompareFunc */
394 
395 static QofQueryCompare
396 gnc_query_scm2compare (SCM how_scm)
397 {
398  return scm_to_int(how_scm);
399 }
400 
401 /* QofStringMatch */
402 static QofStringMatch
403 gnc_query_scm2string (SCM how_scm)
404 {
405  return scm_to_int(how_scm);
406 }
407 
408 /* QofDateMatch */
409 static QofDateMatch
410 gnc_query_scm2date (SCM how_scm)
411 {
412  return scm_to_int(how_scm);
413 }
414 
415 /* QofNumericMatch */
416 static QofNumericMatch
417 gnc_query_scm2numericop (SCM how_scm)
418 {
419  return scm_to_int(how_scm);
420 }
421 
422 /* QofGuidMatch */
423 static QofGuidMatch
424 gnc_query_scm2guid (SCM how_scm)
425 {
426  return scm_to_int(how_scm);
427 }
428 
429 /* QofCharMatch */
430 static QofCharMatch
431 gnc_query_scm2char (SCM how_scm)
432 {
433  return scm_to_int(how_scm);
434 }
435 
436 static QofGuidMatch
437 gnc_scm2acct_match_how (SCM how_scm)
438 {
439  QofGuidMatch res;
440  gchar *how = gnc_scm_symbol_to_locale_string (how_scm);
441 
442  if (!g_strcmp0 (how, "acct-match-all"))
443  res = QOF_GUID_MATCH_ALL;
444  else if (!g_strcmp0 (how, "acct-match-any"))
445  res = QOF_GUID_MATCH_ANY;
446  else if (!g_strcmp0 (how, "acct-match-none"))
447  res = QOF_GUID_MATCH_NONE;
448  else
449  {
450  PINFO ("invalid account match: %s", how);
451  res = QOF_GUID_MATCH_NULL;
452  }
453 
454  g_free (how);
455  return res;
456 }
457 
458 static QofQueryCompare
459 gnc_scm2amt_match_how (SCM how_scm)
460 {
461  QofQueryCompare res;
462  gchar *how = gnc_scm_symbol_to_locale_string (how_scm);
463 
464  if (!g_strcmp0 (how, "amt-match-atleast"))
465  res = QOF_COMPARE_GTE;
466  else if (!g_strcmp0 (how, "amt-match-atmost"))
467  res = QOF_COMPARE_LTE;
468  else if (!g_strcmp0 (how, "amt-match-exactly"))
469  res = QOF_COMPARE_EQUAL;
470  else
471  {
472  PINFO ("invalid amount match: %s", how);
473  res = QOF_COMPARE_EQUAL;
474  }
475 
476  g_free (how);
477  return res;
478 }
479 
480 static QofQueryCompare
481 gnc_scm2kvp_match_how (SCM how_scm)
482 {
483  QofQueryCompare res;
484  gchar *how = gnc_scm_symbol_to_locale_string (how_scm);
485 
486  if (!g_strcmp0 (how, "kvp-match-lt"))
487  res = QOF_COMPARE_LT;
488  else if (!g_strcmp0 (how, "kvp-match-lte"))
489  res = QOF_COMPARE_LTE;
490  else if (!g_strcmp0 (how, "kvp-match-eq"))
491  res = QOF_COMPARE_EQUAL;
492  else if (!g_strcmp0 (how, "kvp-match-gte"))
493  res = QOF_COMPARE_GTE;
494  else if (!g_strcmp0 (how, "kvp-match-gt"))
495  res = QOF_COMPARE_GT;
496  else
497  {
498  PINFO ("invalid kvp match: %s", how);
499  res = QOF_COMPARE_EQUAL;
500  }
501 
502  g_free (how);
503  return res;
504 }
505 
506 static int
507 gnc_scm2bitfield (SCM field_scm)
508 {
509  int field = 0;
510 
511  if (!scm_is_list (field_scm))
512  return 0;
513 
514  while (!scm_is_null (field_scm))
515  {
516  SCM scm;
517  int bit;
518 
519  scm = SCM_CAR (field_scm);
520  field_scm = SCM_CDR (field_scm);
521 
522  bit = scm_to_int(scm);
523  field |= bit;
524  }
525 
526  return field;
527 }
528 
529 static cleared_match_t
530 gnc_scm2cleared_match_how (SCM how_scm)
531 {
532  return gnc_scm2bitfield (how_scm);
533 }
534 
535 static gboolean
536 gnc_scm2balance_match_how (SCM how_scm, gboolean *resp)
537 {
538  gchar *how;
539 
540  if (!scm_is_list (how_scm))
541  return FALSE;
542 
543  if (scm_is_null (how_scm))
544  return FALSE;
545 
546  /* Only allow a single-entry list */
547  if (!scm_is_null (SCM_CDR (how_scm)))
548  return FALSE;
549 
550  how = gnc_scm_symbol_to_locale_string (SCM_CAR(how_scm));
551 
552  if (!g_strcmp0 (how, "balance-match-balanced"))
553  *resp = TRUE;
554  else
555  *resp = FALSE;
556 
557  g_free (how);
558  return TRUE;
559 }
560 
561 static QofIdType
562 gnc_scm2kvp_match_where (SCM where_scm)
563 {
564  QofIdType res;
565  gchar *where;
566 
567  if (!scm_is_list (where_scm))
568  return NULL;
569 
570  where = gnc_scm_symbol_to_locale_string (SCM_CAR(where_scm));
571 
572  if (!g_strcmp0 (where, "kvp-match-split"))
573  res = GNC_ID_SPLIT;
574  else if (!g_strcmp0 (where, "kvp-match-trans"))
575  res = GNC_ID_TRANS;
576  else if (!g_strcmp0 (where, "kvp-match-account"))
577  res = GNC_ID_ACCOUNT;
578  else
579  {
580  PINFO ("Unknown kvp-match-where: %s", where);
581  res = NULL;
582  }
583 
584  g_free (where);
585  return res;
586 }
587 
588 static SCM
589 gnc_guid_glist2scm (const GList *account_guids)
590 {
591  SCM guids = SCM_EOL;
592  const GList *node;
593 
594  for (node = account_guids; node; node = node->next)
595  {
596  GncGUID *guid = node->data;
597 
598  if (guid)
599  guids = scm_cons (gnc_guid2scm (*guid), guids);
600  }
601 
602  return scm_reverse (guids);
603 }
604 
605 static GList *
606 gnc_scm2guid_glist (SCM guids_scm)
607 {
608  GList *guids = NULL;
609 
610  if (!scm_is_list (guids_scm))
611  return NULL;
612 
613  while (!scm_is_null (guids_scm))
614  {
615  SCM guid_scm = SCM_CAR (guids_scm);
616  GncGUID *guid = NULL;
617 
618  if (guid_scm != SCM_BOOL_F)
619  {
620  guid = guid_malloc ();
621  *guid = gnc_scm2guid (guid_scm);
622  }
623 
624  guids = g_list_prepend (guids, guid);
625 
626  guids_scm = SCM_CDR (guids_scm);
627  }
628 
629  return g_list_reverse (guids);
630 }
631 
632 static void
633 gnc_guid_glist_free (GList *guids)
634 {
635  GList *node;
636 
637  for (node = guids; node; node = node->next)
638  guid_free (node->data);
639 
640  g_list_free (guids);
641 }
642 
643 static SCM
644 gnc_query_numeric2scm (gnc_numeric val)
645 {
646  return scm_cons (scm_from_int64 (val.num),
647  scm_from_int64 (val.denom));
648 }
649 
650 static gboolean
651 gnc_query_numeric_p (SCM pair)
652 {
653  return (scm_is_pair (pair));
654 }
655 
656 static gnc_numeric
657 gnc_query_scm2numeric (SCM pair)
658 {
659  SCM denom;
660  SCM num;
661 
662  num = SCM_CAR (pair);
663  denom = SCM_CDR (pair);
664 
665  return gnc_numeric_create (scm_to_int64 (num),
666  scm_to_int64 (denom));
667 }
668 
669 static SCM
670 gnc_query_path2scm (const GSList *path)
671 {
672  SCM path_scm = SCM_EOL;
673  const GSList *node;
674 
675  for (node = path; node; node = node->next)
676  {
677  const char *key = node->data;
678 
679  if (key)
680  path_scm = scm_cons (scm_from_utf8_string (key), path_scm);
681  }
682 
683  return scm_reverse (path_scm);
684 }
685 
686 GSList *
687 gnc_query_scm2path (SCM path_scm)
688 {
689  GSList *path = NULL;
690 
691  if (!scm_is_list (path_scm))
692  return NULL;
693 
694  while (!scm_is_null (path_scm))
695  {
696  SCM key_scm = SCM_CAR (path_scm);
697  char *str;
698  char *key;
699 
700  if (!scm_is_string (key_scm))
701  break;
702 
703  key = gnc_scm_to_utf8_string(key_scm);
704  path = g_slist_prepend (path, key);
705  path_scm = SCM_CDR (path_scm);
706  }
707 
708  return g_slist_reverse (path);
709 }
710 
711 static void
712 gnc_query_path_free (GSList *path)
713 {
714  GSList *node;
715 
716  for (node = path; node; node = node->next)
717  g_free (node->data);
718 
719  g_slist_free (path);
720 }
721 
722 static KvpValueType
723 gnc_scm2KvpValueType (SCM value_type_scm)
724 {
725  return scm_to_int(value_type_scm);
726 }
727 
728 static SCM gnc_kvp_frame2scm (KvpFrame *frame);
729 
730 static SCM
731 gnc_kvp_value2scm (const KvpValue *value)
732 {
733  SCM value_scm = SCM_EOL;
734  KvpValueType value_t;
735  SCM scm;
736  const gchar *string;
737 
738  if (!value) return SCM_BOOL_F;
739 
740  value_t = kvp_value_get_type (value);
741 
742  value_scm = scm_cons (scm_from_long (value_t), value_scm);
743 
744  switch (value_t)
745  {
746  case KVP_TYPE_GINT64:
747  scm = scm_from_int64 (kvp_value_get_gint64 (value));
748  break;
749 
750  case KVP_TYPE_DOUBLE:
751  scm = scm_from_double (kvp_value_get_double (value));
752  break;
753 
754  case KVP_TYPE_STRING:
755  string = kvp_value_get_string (value);
756  scm = string ? scm_from_utf8_string (string) : SCM_BOOL_F;
757  break;
758 
759  case KVP_TYPE_GUID:
760  scm = gnc_guid2scm (*kvp_value_get_guid (value));
761  break;
762 
763  case KVP_TYPE_TIMESPEC:
764  scm = gnc_timespec2timepair (kvp_value_get_timespec (value));
765  break;
766 
767  case KVP_TYPE_NUMERIC:
768  {
769  gnc_numeric n = kvp_value_get_numeric (value);
770  scm = gnc_query_numeric2scm (n);
771  break;
772  }
773 
774  case KVP_TYPE_GLIST:
775  {
776  GList *node;
777 
778  scm = SCM_EOL;
779  for (node = kvp_value_get_glist (value); node; node = node->next)
780  scm = scm_cons (gnc_kvp_value2scm (node->data), scm);
781  scm = scm_reverse (scm);
782  break;
783  }
784 
785  case KVP_TYPE_FRAME:
786  scm = gnc_kvp_frame2scm (kvp_value_get_frame (value));
787  break;
788 
789  default:
790  scm = SCM_BOOL_F;
791  break;
792  }
793 
794  value_scm = scm_cons (scm, value_scm);
795 
796  return scm_reverse (value_scm);
797 }
798 
799 typedef struct
800 {
801  SCM scm;
802 } KVPSCMData;
803 
804 static void
805 kvp_frame_slot2scm (const char *key, KvpValue *value, gpointer data)
806 {
807  KVPSCMData *ksd = data;
808  SCM value_scm;
809  SCM key_scm;
810  SCM pair;
811 
812  key_scm = key ? scm_from_utf8_string (key) : SCM_BOOL_F;
813  value_scm = gnc_kvp_value2scm (value);
814  pair = scm_cons (key_scm, value_scm);
815 
816  ksd->scm = scm_cons (pair, ksd->scm);
817 }
818 
819 static SCM
820 gnc_kvp_frame2scm (KvpFrame *frame)
821 {
822  KVPSCMData ksd;
823 
824  if (!frame) return SCM_BOOL_F;
825 
826  ksd.scm = SCM_EOL;
827 
828  kvp_frame_for_each_slot (frame, kvp_frame_slot2scm, &ksd);
829 
830  return ksd.scm;
831 }
832 
833 static KvpFrame * gnc_scm2KvpFrame (SCM frame_scm);
834 
835 static KvpValue *
836 gnc_scm2KvpValue (SCM value_scm)
837 {
838  KvpValueType value_t;
839  KvpValue *value = NULL;
840  SCM type_scm;
841  SCM val_scm;
842 
843  if (!scm_is_list (value_scm) || scm_is_null (value_scm))
844  return NULL;
845 
846  type_scm = SCM_CAR (value_scm);
847  value_t = gnc_scm2KvpValueType (type_scm);
848 
849  value_scm = SCM_CDR (value_scm);
850  if (!scm_is_list (value_scm) || scm_is_null (value_scm))
851  return NULL;
852 
853  val_scm = SCM_CAR (value_scm);
854 
855  switch (value_t)
856  {
857  case KVP_TYPE_GINT64:
858  value = kvp_value_new_gint64 (scm_to_int64 (val_scm));
859  break;
860 
861  case KVP_TYPE_DOUBLE:
862  value = kvp_value_new_double (scm_to_double (val_scm));
863  break;
864 
865  case KVP_TYPE_STRING:
866  {
867  gchar * str;
868  str = gnc_scm_to_utf8_string (val_scm);
869  value = kvp_value_new_string (str);
870  g_free (str);
871  break;
872  }
873 
874  case KVP_TYPE_GUID:
875  {
876  if (val_scm != SCM_BOOL_F)
877  {
878  GncGUID guid = gnc_scm2guid (val_scm);
879  value = kvp_value_new_guid (&guid);
880  }
881  else
882  value = NULL;
883  break;
884  }
885 
886  case KVP_TYPE_TIMESPEC:
887  {
888  Timespec ts = gnc_timepair2timespec (val_scm);
889  value = kvp_value_new_timespec(ts);
890  break;
891  }
892 
893  case KVP_TYPE_GDATE:
894  {
895  Timespec ts = gnc_timepair2timespec (val_scm);
896  value = kvp_value_new_gdate(timespec_to_gdate(ts));
897  break;
898  }
899 
900  case KVP_TYPE_NUMERIC:
901  {
902  gnc_numeric n;
903 
904  if (!gnc_query_numeric_p (val_scm))
905  return NULL;
906 
907  n = gnc_query_scm2numeric (val_scm);
908 
909  value = kvp_value_new_gnc_numeric (n);
910  break;
911  }
912 
913  case KVP_TYPE_GLIST:
914  {
915  GList *list = NULL;
916  GList *node;
917 
918  for (; scm_is_list (val_scm) && !scm_is_null (val_scm);
919  val_scm = SCM_CDR (val_scm))
920  {
921  SCM scm = SCM_CAR (val_scm);
922 
923  list = g_list_prepend (list, gnc_scm2KvpValue (scm));
924  }
925 
926  list = g_list_reverse (list);
927 
928  value = kvp_value_new_glist (list);
929 
930  for (node = list; node; node = node->next)
931  kvp_value_delete (node->data);
932  g_list_free (list);
933  break;
934  }
935 
936  case KVP_TYPE_FRAME:
937  {
938  KvpFrame *frame;
939 
940  frame = gnc_scm2KvpFrame (val_scm);
941  value = kvp_value_new_frame (frame);
942  kvp_frame_delete (frame);
943  break;
944  }
945  default:
946  break;
947  }
948 
949  return value;
950 }
951 
952 static KvpFrame *
953 gnc_scm2KvpFrame (SCM frame_scm)
954 {
955  KvpFrame * frame;
956 
957  if (!scm_is_list (frame_scm)) return NULL;
958 
959  frame = kvp_frame_new ();
960 
961  for (; scm_is_list (frame_scm) && !scm_is_null (frame_scm);
962  frame_scm = SCM_CDR (frame_scm))
963  {
964  SCM pair = SCM_CAR (frame_scm);
965  KvpValue *value;
966  SCM key_scm;
967  SCM val_scm;
968  gchar *key;
969 
970  if (!scm_is_pair (pair))
971  continue;
972 
973  key_scm = SCM_CAR (pair);
974  val_scm = SCM_CDR (pair);
975 
976  if (!scm_is_string (key_scm))
977  continue;
978 
979  key = scm_to_utf8_string (key_scm); /* key should be freed with free !
980  This is automatically taken care
981  of by scm_dynwind_free below. */
982  scm_dynwind_begin (0);
983  scm_dynwind_free (key); /* free key whenever the dynwind context ends */
984  if (!key)
985  {
986  scm_dynwind_end ();
987  continue;
988  }
989  value = gnc_scm2KvpValue (val_scm); /* can exit non-locally so justifies
990  the use of scm_dynwind context
991  protection */
992  if (!value)
993  {
994  scm_dynwind_end ();
995  continue;
996  }
997  kvp_frame_set_slot_nc (frame, key, value);
998  scm_dynwind_end ();
999  }
1000 
1001  return frame;
1002 }
1003 
1004 static SCM
1005 gnc_queryterm2scm (const QofQueryTerm *qt)
1006 {
1007  SCM qt_scm = SCM_EOL;
1008  QofQueryPredData *pd = NULL;
1009 
1010  qt_scm = scm_cons (gnc_query_path2scm (qof_query_term_get_param_path (qt)),
1011  qt_scm);
1012  qt_scm = scm_cons (SCM_BOOL (qof_query_term_is_inverted (qt)), qt_scm);
1013 
1014  pd = qof_query_term_get_pred_data (qt);
1015  qt_scm = scm_cons (scm_from_locale_symbol (pd->type_name), qt_scm);
1016  qt_scm = scm_cons (scm_from_long (pd->how), qt_scm);
1017 
1018  if (!g_strcmp0 (pd->type_name, QOF_TYPE_STRING))
1019  {
1020  query_string_t pdata = (query_string_t) pd;
1021 
1022  qt_scm = scm_cons (scm_from_long (pdata->options), qt_scm);
1023  qt_scm = scm_cons (SCM_BOOL (pdata->is_regex), qt_scm);
1024  qt_scm = scm_cons (pdata->matchstring ? scm_from_utf8_string (pdata->matchstring) : SCM_BOOL_F, qt_scm);
1025 
1026  }
1027  else if (!g_strcmp0 (pd->type_name, QOF_TYPE_DATE))
1028  {
1029  query_date_t pdata = (query_date_t) pd;
1030 
1031  qt_scm = scm_cons (scm_from_long (pdata->options), qt_scm);
1032  qt_scm = scm_cons (gnc_timespec2timepair (pdata->date), qt_scm);
1033 
1034  }
1035  else if (!g_strcmp0 (pd->type_name, QOF_TYPE_NUMERIC))
1036  {
1037  query_numeric_t pdata = (query_numeric_t) pd;
1038 
1039  qt_scm = scm_cons (scm_from_long (pdata->options), qt_scm);
1040  qt_scm = scm_cons (gnc_query_numeric2scm (pdata->amount), qt_scm);
1041 
1042  }
1043  else if (!g_strcmp0 (pd->type_name, QOF_TYPE_GUID))
1044  {
1045  query_guid_t pdata = (query_guid_t) pd;
1046 
1047  qt_scm = scm_cons (scm_from_long (pdata->options), qt_scm);
1048  qt_scm = scm_cons (gnc_guid_glist2scm (pdata->guids), qt_scm);
1049 
1050  }
1051  else if (!g_strcmp0 (pd->type_name, QOF_TYPE_INT64))
1052  {
1053  query_int64_t pdata = (query_int64_t) pd;
1054 
1055  qt_scm = scm_cons (scm_from_int64 (pdata->val), qt_scm);
1056 
1057  }
1058  else if (!g_strcmp0 (pd->type_name, QOF_TYPE_DOUBLE))
1059  {
1060  query_double_t pdata = (query_double_t) pd;
1061 
1062  qt_scm = scm_cons (scm_from_double (pdata->val), qt_scm);
1063 
1064  }
1065  else if (!g_strcmp0 (pd->type_name, QOF_TYPE_BOOLEAN))
1066  {
1067  query_boolean_t pdata = (query_boolean_t) pd;
1068 
1069  qt_scm = scm_cons (SCM_BOOL (pdata->val), qt_scm);
1070 
1071  }
1072  else if (!g_strcmp0 (pd->type_name, QOF_TYPE_CHAR))
1073  {
1074  query_char_t pdata = (query_char_t) pd;
1075 
1076  qt_scm = scm_cons (scm_from_long (pdata->options), qt_scm);
1077  qt_scm = scm_cons (pdata->char_list ? scm_from_utf8_string (pdata->char_list) : SCM_BOOL_F, qt_scm);
1078 
1079  }
1080  else if (!g_strcmp0 (pd->type_name, QOF_TYPE_KVP))
1081  {
1082  query_kvp_t pdata = (query_kvp_t) pd;
1083 
1084  qt_scm = scm_cons (gnc_query_path2scm (pdata->path), qt_scm);
1085  qt_scm = scm_cons (gnc_kvp_value2scm (pdata->value), qt_scm);
1086 
1087  }
1088  else
1089  {
1090  PWARN ("query core type %s not supported", pd->type_name);
1091  return SCM_BOOL_F;
1092  }
1093 
1094  return scm_reverse (qt_scm);
1095 }
1096 
1097 static QofQuery *
1098 gnc_scm2query_term_query_v2 (SCM qt_scm)
1099 {
1100  QofQuery *q = NULL;
1101  QofQueryPredData *pd = NULL;
1102  SCM scm;
1103  gchar *type = NULL;
1104  GSList *path = NULL;
1105  gboolean inverted = FALSE;
1106  QofQueryCompare compare_how;
1107 
1108  if (!scm_is_list (qt_scm) || scm_is_null (qt_scm))
1109  return NULL;
1110 
1111  do
1112  {
1113  /* param path */
1114  scm = SCM_CAR (qt_scm);
1115  qt_scm = SCM_CDR (qt_scm);
1116  if (!scm_is_list (scm))
1117  break;
1118  path = gnc_query_scm2path (scm);
1119 
1120  /* inverted */
1121  scm = SCM_CAR (qt_scm);
1122  qt_scm = SCM_CDR (qt_scm);
1123  if (!scm_is_bool (scm))
1124  break;
1125  inverted = scm_is_true (scm);
1126 
1127  /* type */
1128  scm = SCM_CAR (qt_scm);
1129  qt_scm = SCM_CDR (qt_scm);
1130  if (!scm_is_symbol (scm))
1131  break;
1132  type = gnc_scm_symbol_to_locale_string (scm);
1133 
1134  /* QofCompareFunc */
1135  scm = SCM_CAR (qt_scm);
1136  qt_scm = SCM_CDR (qt_scm);
1137  if (scm_is_null (scm))
1138  break;
1139  compare_how = gnc_query_scm2compare (scm);
1140 
1141  /* Now compute the predicate */
1142 
1143  if (!g_strcmp0 (type, QOF_TYPE_STRING))
1144  {
1145  QofStringMatch options;
1146  gboolean is_regex;
1147  gchar *matchstring;
1148 
1149  scm = SCM_CAR (qt_scm);
1150  qt_scm = SCM_CDR (qt_scm);
1151  if (scm_is_null (scm)) break;
1152  options = gnc_query_scm2string (scm);
1153 
1154  scm = SCM_CAR (qt_scm);
1155  qt_scm = SCM_CDR (qt_scm);
1156  if (!scm_is_bool (scm)) break;
1157  is_regex = scm_is_true (scm);
1158 
1159  scm = SCM_CAR (qt_scm);
1160  qt_scm = SCM_CDR (qt_scm);
1161  if (!scm_is_string (scm)) break;
1162 
1163  matchstring = gnc_scm_to_utf8_string (scm);
1164 
1165  pd = qof_query_string_predicate (compare_how, matchstring,
1166  options, is_regex);
1167  g_free (matchstring);
1168  }
1169  else if (!g_strcmp0 (type, QOF_TYPE_DATE))
1170  {
1171  QofDateMatch options;
1172  Timespec date;
1173 
1174  scm = SCM_CAR (qt_scm);
1175  qt_scm = SCM_CDR (qt_scm);
1176  if (scm_is_null (scm))
1177  break;
1178  options = gnc_query_scm2date (scm);
1179 
1180  scm = SCM_CAR (qt_scm);
1181  qt_scm = SCM_CDR (qt_scm);
1182  if (scm_is_null (scm))
1183  break;
1184  date = gnc_timepair2timespec (scm);
1185 
1186  pd = qof_query_date_predicate (compare_how, options, date);
1187 
1188  }
1189  else if (!g_strcmp0 (type, QOF_TYPE_NUMERIC))
1190  {
1191  QofNumericMatch options;
1192  gnc_numeric val;
1193 
1194  scm = SCM_CAR (qt_scm);
1195  qt_scm = SCM_CDR (qt_scm);
1196  if (scm_is_null (scm))
1197  break;
1198  options = gnc_query_scm2numericop (scm);
1199 
1200  scm = SCM_CAR (qt_scm);
1201  qt_scm = SCM_CDR (qt_scm);
1202  if (!gnc_query_numeric_p (scm))
1203  break;
1204  val = gnc_query_scm2numeric (scm);
1205 
1206  pd = qof_query_numeric_predicate (compare_how, options, val);
1207 
1208  }
1209  else if (!g_strcmp0 (type, QOF_TYPE_GUID))
1210  {
1211  QofGuidMatch options;
1212  GList *guids;
1213 
1214  scm = SCM_CAR (qt_scm);
1215  qt_scm = SCM_CDR (qt_scm);
1216  if (scm_is_null (scm))
1217  break;
1218  options = gnc_query_scm2guid (scm);
1219 
1220  scm = SCM_CAR (qt_scm);
1221  qt_scm = SCM_CDR (qt_scm);
1222  if (!scm_is_list (scm))
1223  break;
1224  guids = gnc_scm2guid_glist (scm);
1225 
1226  pd = qof_query_guid_predicate (options, guids);
1227 
1228  gnc_guid_glist_free (guids);
1229 
1230  }
1231  else if (!g_strcmp0 (type, QOF_TYPE_INT64))
1232  {
1233  gint64 val;
1234 
1235  scm = SCM_CAR (qt_scm);
1236  qt_scm = SCM_CDR (qt_scm);
1237  if (scm_is_null (scm))
1238  break;
1239  val = scm_to_int64 (scm);
1240 
1241  pd = qof_query_int64_predicate (compare_how, val);
1242 
1243  }
1244  else if (!g_strcmp0 (type, QOF_TYPE_DOUBLE))
1245  {
1246  double val;
1247 
1248  scm = SCM_CAR (qt_scm);
1249  qt_scm = SCM_CDR (qt_scm);
1250  if (!scm_is_number (scm))
1251  break;
1252  val = scm_to_double (scm);
1253 
1254  pd = qof_query_double_predicate (compare_how, val);
1255 
1256  }
1257  else if (!g_strcmp0 (type, QOF_TYPE_BOOLEAN))
1258  {
1259  gboolean val;
1260 
1261  scm = SCM_CAR (qt_scm);
1262  qt_scm = SCM_CDR (qt_scm);
1263  if (!scm_is_bool (scm))
1264  break;
1265  val = scm_is_true (scm);
1266 
1267  pd = qof_query_boolean_predicate (compare_how, val);
1268 
1269  }
1270  else if (!g_strcmp0 (type, QOF_TYPE_CHAR))
1271  {
1272  QofCharMatch options;
1273  gchar *char_list;
1274 
1275  scm = SCM_CAR (qt_scm);
1276  qt_scm = SCM_CDR (qt_scm);
1277  if (scm_is_null (scm))
1278  break;
1279  options = gnc_query_scm2char (scm);
1280 
1281  scm = SCM_CAR (qt_scm);
1282  qt_scm = SCM_CDR (qt_scm);
1283  if (!scm_is_string (scm))
1284  break;
1285  char_list = gnc_scm_to_utf8_string (scm);
1286 
1287  pd = qof_query_char_predicate (options, char_list);
1288  g_free (char_list);
1289  }
1290  else if (!g_strcmp0 (type, QOF_TYPE_KVP))
1291  {
1292  GSList *kvp_path;
1293  KvpValue *value;
1294 
1295  scm = SCM_CAR (qt_scm);
1296  qt_scm = SCM_CDR (qt_scm);
1297  if (!scm_is_list (scm))
1298  break;
1299  kvp_path = gnc_query_scm2path (scm);
1300 
1301  scm = SCM_CAR (qt_scm);
1302  qt_scm = SCM_CDR (qt_scm);
1303  if (scm_is_null (scm))
1304  {
1305  gnc_query_path_free (kvp_path);
1306  break;
1307  }
1308  value = gnc_scm2KvpValue (scm);
1309 
1310  pd = qof_query_kvp_predicate (compare_how, kvp_path, value);
1311  gnc_query_path_free (kvp_path);
1312  kvp_value_delete (value);
1313 
1314  }
1315  else
1316  {
1317  PWARN ("query core type %s not supported", type);
1318  break;
1319  }
1320 
1321  g_free (type);
1322 
1323  }
1324  while (FALSE);
1325 
1326  if (pd)
1327  {
1328  q = qof_query_create ();
1329  qof_query_add_term (q, path, pd, QOF_QUERY_OR);
1330  if (inverted)
1331  {
1332  QofQuery *outq = qof_query_invert (q);
1333  qof_query_destroy (q);
1334  q = outq;
1335  }
1336  }
1337  else
1338  {
1339  gnc_query_path_free (path);
1340  }
1341 
1342  return q;
1343 }
1344 
1345 static QofQuery *
1346 gnc_scm2query_term_query_v1 (SCM query_term_scm)
1347 {
1348  gboolean ok = FALSE;
1349  gchar * pd_type = NULL;
1350  gchar * pr_type = NULL;
1351  gboolean sense = FALSE;
1352  QofQuery *q = NULL;
1353  SCM scm;
1354 
1355  if (!scm_is_list (query_term_scm) ||
1356  scm_is_null (query_term_scm))
1357  {
1358  PINFO ("null term");
1359  return NULL;
1360  }
1361 
1362  do
1363  {
1364  /* pd_type */
1365  scm = SCM_CAR (query_term_scm);
1366  query_term_scm = SCM_CDR (query_term_scm);
1367  pd_type = gnc_scm_symbol_to_locale_string (scm);
1368 
1369  /* pr_type */
1370  if (scm_is_null (query_term_scm))
1371  {
1372  PINFO ("null pr_type");
1373  break;
1374  }
1375  scm = SCM_CAR (query_term_scm);
1376  query_term_scm = SCM_CDR (query_term_scm);
1377  pr_type = gnc_scm_symbol_to_locale_string (scm);
1378 
1379  /* sense */
1380  if (scm_is_null (query_term_scm))
1381  {
1382  PINFO ("null sense");
1383  break;
1384  }
1385  scm = SCM_CAR (query_term_scm);
1386  query_term_scm = SCM_CDR (query_term_scm);
1387  sense = scm_is_true (scm);
1388 
1389  q = qof_query_create_for(GNC_ID_SPLIT);
1390 
1391  if (!g_strcmp0 (pd_type, "pd-date"))
1392  {
1393  gboolean use_start;
1394  gboolean use_end;
1395  Timespec start;
1396  Timespec end;
1397 
1398  /* use_start */
1399  if (scm_is_null (query_term_scm))
1400  {
1401  PINFO ("null use_start");
1402  break;
1403  }
1404 
1405  scm = SCM_CAR (query_term_scm);
1406  query_term_scm = SCM_CDR (query_term_scm);
1407  use_start = scm_is_true (scm);
1408 
1409  /* start */
1410  if (scm_is_null (query_term_scm))
1411  break;
1412 
1413  scm = SCM_CAR (query_term_scm);
1414  query_term_scm = SCM_CDR (query_term_scm);
1415  start = gnc_timepair2timespec (scm);
1416 
1417  /* use_end */
1418  if (scm_is_null (query_term_scm))
1419  break;
1420 
1421  scm = SCM_CAR (query_term_scm);
1422  query_term_scm = SCM_CDR (query_term_scm);
1423  use_end = scm_is_true (scm);
1424 
1425  /* end */
1426  if (scm_is_null (query_term_scm))
1427  break;
1428 
1429  scm = SCM_CAR (query_term_scm);
1430  query_term_scm = SCM_CDR (query_term_scm);
1431  end = gnc_timepair2timespec (scm);
1432 
1433  xaccQueryAddDateMatchTS (q, use_start, start, use_end, end, QOF_QUERY_OR);
1434 
1435  ok = TRUE;
1436 
1437  }
1438  else if (!g_strcmp0 (pd_type, "pd-amount"))
1439  {
1440  QofQueryCompare how;
1441  QofNumericMatch amt_sgn;
1442  double amount;
1443  gnc_numeric val;
1444 
1445  /* how */
1446  if (scm_is_null (query_term_scm))
1447  break;
1448  scm = SCM_CAR (query_term_scm);
1449  query_term_scm = SCM_CDR (query_term_scm);
1450  how = gnc_scm2amt_match_how (scm);
1451 
1452  /* amt_sgn */
1453  if (scm_is_null (query_term_scm))
1454  break;
1455  scm = SCM_CAR (query_term_scm);
1456  query_term_scm = SCM_CDR (query_term_scm);
1457  amt_sgn = gnc_query_scm2numericop (scm);
1458 
1459  /* amount */
1460  if (scm_is_null (query_term_scm))
1461  break;
1462  scm = SCM_CAR (query_term_scm);
1463  query_term_scm = SCM_CDR (query_term_scm);
1464  amount = scm_to_double (scm);
1465 
1466  val = double_to_gnc_numeric (amount, GNC_DENOM_AUTO,
1468 
1469  if (!g_strcmp0 (pr_type, "pr-price"))
1470  {
1471  xaccQueryAddSharePriceMatch (q, val, how, QOF_QUERY_OR);
1472  ok = TRUE;
1473 
1474  }
1475  else if (!g_strcmp0 (pr_type, "pr-shares"))
1476  {
1477  xaccQueryAddSharesMatch (q, val, how, QOF_QUERY_OR);
1478  ok = TRUE;
1479 
1480  }
1481  else if (!g_strcmp0 (pr_type, "pr-value"))
1482  {
1483  xaccQueryAddValueMatch (q, val, amt_sgn, how, QOF_QUERY_OR);
1484  ok = TRUE;
1485 
1486  }
1487  else
1488  {
1489  PINFO ("unknown amount predicate: %s", pr_type);
1490  }
1491 
1492  }
1493  else if (!g_strcmp0 (pd_type, "pd-account"))
1494  {
1495  QofGuidMatch how;
1496  GList *account_guids;
1497 
1498  /* how */
1499  if (scm_is_null (query_term_scm))
1500  {
1501  PINFO ("pd-account: null how");
1502  break;
1503  }
1504 
1505  scm = SCM_CAR (query_term_scm);
1506  query_term_scm = SCM_CDR (query_term_scm);
1507  how = gnc_scm2acct_match_how (scm);
1508 
1509  /* account guids */
1510  if (scm_is_null (query_term_scm))
1511  {
1512  PINFO ("pd-account: null guids");
1513  break;
1514  }
1515 
1516  scm = SCM_CAR (query_term_scm);
1517  query_term_scm = SCM_CDR (query_term_scm);
1518 
1519  account_guids = gnc_scm2guid_glist (scm);
1520 
1521  xaccQueryAddAccountGUIDMatch (q, account_guids, how, QOF_QUERY_OR);
1522 
1523  gnc_guid_glist_free (account_guids);
1524 
1525  ok = TRUE;
1526 
1527  }
1528  else if (!g_strcmp0 (pd_type, "pd-string"))
1529  {
1530  gboolean case_sens;
1531  gboolean use_regexp;
1532  gchar *matchstring;
1533 
1534  /* case_sens */
1535  if (scm_is_null (query_term_scm))
1536  break;
1537 
1538  scm = SCM_CAR (query_term_scm);
1539  query_term_scm = SCM_CDR (query_term_scm);
1540  case_sens = scm_is_true (scm);
1541 
1542  /* use_regexp */
1543  if (scm_is_null (query_term_scm))
1544  break;
1545 
1546  scm = SCM_CAR (query_term_scm);
1547  query_term_scm = SCM_CDR (query_term_scm);
1548  use_regexp = scm_is_true (scm);
1549 
1550  /* matchstring */
1551  if (scm_is_null (query_term_scm))
1552  break;
1553 
1554  scm = SCM_CAR (query_term_scm);
1555  query_term_scm = SCM_CDR (query_term_scm);
1556  matchstring = gnc_scm_to_utf8_string (scm);
1557 
1558  if (!g_strcmp0 (pr_type, "pr-action"))
1559  {
1560  xaccQueryAddActionMatch (q, matchstring, case_sens, use_regexp,
1561  QOF_COMPARE_CONTAINS, QOF_QUERY_OR);
1562  ok = TRUE;
1563 
1564  }
1565  else if (!g_strcmp0 (pr_type, "pr-desc"))
1566  {
1567  xaccQueryAddDescriptionMatch (q, matchstring, case_sens,
1568  use_regexp, QOF_COMPARE_CONTAINS, QOF_QUERY_OR);
1569  ok = TRUE;
1570 
1571  }
1572  else if (!g_strcmp0 (pr_type, "pr-memo"))
1573  {
1574  xaccQueryAddMemoMatch (q, matchstring, case_sens, use_regexp,
1575  QOF_COMPARE_CONTAINS, QOF_QUERY_OR);
1576  ok = TRUE;
1577 
1578  }
1579  else if (!g_strcmp0 (pr_type, "pr-num"))
1580  {
1581  xaccQueryAddNumberMatch (q, matchstring, case_sens, use_regexp,
1582  QOF_COMPARE_CONTAINS, QOF_QUERY_OR);
1583  ok = TRUE;
1584 
1585  }
1586  else
1587  {
1588  PINFO ("Unknown string predicate: %s", pr_type);
1589  }
1590  g_free (matchstring);
1591 
1592  }
1593  else if (!g_strcmp0 (pd_type, "pd-cleared"))
1594  {
1595  cleared_match_t how;
1596 
1597  /* how */
1598  if (scm_is_null (query_term_scm))
1599  break;
1600 
1601  scm = SCM_CAR (query_term_scm);
1602  query_term_scm = SCM_CDR (query_term_scm);
1603  how = gnc_scm2cleared_match_how (scm);
1604 
1605  xaccQueryAddClearedMatch (q, how, QOF_QUERY_OR);
1606  ok = TRUE;
1607 
1608  }
1609  else if (!g_strcmp0 (pd_type, "pd-balance"))
1610  {
1611  gboolean how;
1612 
1613  /* how */
1614  if (scm_is_null (query_term_scm))
1615  break;
1616 
1617  scm = SCM_CAR (query_term_scm);
1618  query_term_scm = SCM_CDR (query_term_scm);
1619  if (gnc_scm2balance_match_how (scm, &how) == FALSE)
1620  break;
1621 
1622  xaccQueryAddBalanceMatch (q, how, QOF_QUERY_OR);
1623  ok = TRUE;
1624 
1625  }
1626  else if (!g_strcmp0 (pd_type, "pd-guid"))
1627  {
1628  GncGUID guid;
1629  QofIdType id_type;
1630 
1631  /* guid */
1632  if (scm_is_null (query_term_scm))
1633  break;
1634 
1635  scm = SCM_CAR (query_term_scm);
1636  query_term_scm = SCM_CDR (query_term_scm);
1637  guid = gnc_scm2guid (scm);
1638 
1639  /* id type */
1640  scm = SCM_CAR (query_term_scm);
1641  query_term_scm = SCM_CDR (query_term_scm);
1642  id_type = (QofIdType) gnc_scm_to_utf8_string (scm);
1643 
1644  xaccQueryAddGUIDMatch (q, &guid, id_type, QOF_QUERY_OR);
1645  g_free ((void *) id_type);
1646  ok = TRUE;
1647 
1648  }
1649  else if (!g_strcmp0 (pd_type, "pd-kvp"))
1650  {
1651  GSList *path;
1652  KvpValue *value;
1653  QofQueryCompare how;
1654  QofIdType where;
1655 
1656  /* how */
1657  if (scm_is_null (query_term_scm))
1658  break;
1659  scm = SCM_CAR (query_term_scm);
1660  query_term_scm = SCM_CDR (query_term_scm);
1661  how = gnc_scm2kvp_match_how (scm);
1662 
1663  /* where */
1664  if (scm_is_null (query_term_scm))
1665  break;
1666  scm = SCM_CAR (query_term_scm);
1667  query_term_scm = SCM_CDR (query_term_scm);
1668  where = gnc_scm2kvp_match_where (scm);
1669 
1670  /* path */
1671  if (scm_is_null (query_term_scm))
1672  break;
1673  scm = SCM_CAR (query_term_scm);
1674  query_term_scm = SCM_CDR (query_term_scm);
1675  path = gnc_query_scm2path (scm);
1676 
1677  /* value */
1678  if (scm_is_null (query_term_scm))
1679  break;
1680  scm = SCM_CAR (query_term_scm);
1681  query_term_scm = SCM_CDR (query_term_scm);
1682  value = gnc_scm2KvpValue (scm);
1683 
1684  xaccQueryAddKVPMatch (q, path, value, how, where, QOF_QUERY_OR);
1685 
1686  gnc_query_path_free (path);
1687  kvp_value_delete (value);
1688  ok = TRUE;
1689 
1690  }
1691  else
1692  {
1693  PINFO ("Unknown Predicate: %s", pd_type);
1694  }
1695 
1696  g_free (pd_type);
1697  g_free (pr_type);
1698 
1699  }
1700  while (FALSE);
1701 
1702  if (ok)
1703  {
1704  QofQuery *out_q;
1705 
1706  if (sense)
1707  out_q = q;
1708  else
1709  {
1710  out_q = qof_query_invert (q);
1711  qof_query_destroy (q);
1712  }
1713 
1714  return out_q;
1715  }
1716 
1717  qof_query_destroy (q);
1718  return NULL;
1719 }
1720 
1721 static QofQuery *
1722 gnc_scm2query_term_query (SCM query_term_scm, query_version_t vers)
1723 {
1724  switch (vers)
1725  {
1726  case gnc_QUERY_v1:
1727  return gnc_scm2query_term_query_v1 (query_term_scm);
1728  case gnc_QUERY_v2:
1729  return gnc_scm2query_term_query_v2 (query_term_scm);
1730  default:
1731  return NULL;
1732  }
1733 }
1734 
1735 static SCM
1736 gnc_query_terms2scm (const GList *terms)
1737 {
1738  SCM or_terms = SCM_EOL;
1739  const GList *or_node;
1740 
1741  for (or_node = terms; or_node; or_node = or_node->next)
1742  {
1743  SCM and_terms = SCM_EOL;
1744  GList *and_node;
1745 
1746  for (and_node = or_node->data; and_node; and_node = and_node->next)
1747  {
1748  QofQueryTerm *qt = and_node->data;
1749  SCM qt_scm;
1750 
1751  qt_scm = gnc_queryterm2scm (qt);
1752 
1753  and_terms = scm_cons (qt_scm, and_terms);
1754  }
1755 
1756  and_terms = scm_reverse (and_terms);
1757 
1758  or_terms = scm_cons (and_terms, or_terms);
1759  }
1760 
1761  return scm_reverse (or_terms);
1762 }
1763 
1764 static QofQuery *
1765 gnc_scm2query_and_terms (SCM and_terms, query_version_t vers)
1766 {
1767  QofQuery *q = NULL;
1768 
1769  if (!scm_is_list (and_terms))
1770  return NULL;
1771 
1772  while (!scm_is_null (and_terms))
1773  {
1774  SCM term;
1775 
1776  term = SCM_CAR (and_terms);
1777  and_terms = SCM_CDR (and_terms);
1778 
1779  if (!q)
1780  q = gnc_scm2query_term_query (term, vers);
1781  else
1782  {
1783  QofQuery *q_and;
1784  QofQuery *q_new;
1785 
1786  q_and = gnc_scm2query_term_query (term, vers);
1787 
1788  if (q_and)
1789  {
1790  q_new = qof_query_merge (q, q_and, QOF_QUERY_AND);
1791 
1792  if (q_new)
1793  {
1794  qof_query_destroy (q);
1795  q = q_new;
1796  }
1797  }
1798  }
1799  }
1800 
1801  return q;
1802 }
1803 
1804 static QofQuery *
1805 gnc_scm2query_or_terms (SCM or_terms, query_version_t vers)
1806 {
1807  QofQuery *q = NULL;
1808 
1809  if (!scm_is_list (or_terms))
1810  return NULL;
1811 
1812  q = qof_query_create_for(GNC_ID_SPLIT);
1813 
1814  while (!scm_is_null (or_terms))
1815  {
1816  SCM and_terms;
1817 
1818  and_terms = SCM_CAR (or_terms);
1819  or_terms = SCM_CDR (or_terms);
1820 
1821  if (!q)
1822  q = gnc_scm2query_and_terms (and_terms, vers);
1823  else
1824  {
1825  QofQuery *q_or;
1826  QofQuery *q_new;
1827 
1828  q_or = gnc_scm2query_and_terms (and_terms, vers);
1829 
1830  if (q_or)
1831  {
1832  q_new = qof_query_merge (q, q_or, QOF_QUERY_OR);
1833 
1834  if (q_new)
1835  {
1836  qof_query_destroy (q);
1837  q = q_new;
1838  }
1839  }
1840  }
1841  }
1842 
1843  return q;
1844 }
1845 
1846 static SCM
1847 gnc_query_sort2scm (const QofQuerySort *qs)
1848 {
1849  SCM sort_scm = SCM_EOL;
1850  GSList *path;
1851 
1852  path = qof_query_sort_get_param_path (qs);
1853  if (path == NULL)
1854  return SCM_BOOL_F;
1855 
1856  sort_scm = scm_cons (gnc_query_path2scm (path), sort_scm);
1857  sort_scm = scm_cons (scm_from_int (qof_query_sort_get_sort_options (qs)), sort_scm);
1858  sort_scm = scm_cons (SCM_BOOL (qof_query_sort_get_increasing (qs)), sort_scm);
1859 
1860  return scm_reverse (sort_scm);
1861 }
1862 
1863 static gboolean
1864 gnc_query_scm2sort (SCM sort_scm, GSList **path, gint *options, gboolean *inc)
1865 {
1866  SCM val;
1867  GSList *p;
1868  gint o;
1869  gboolean i;
1870 
1871  g_return_val_if_fail (path && options && inc, FALSE);
1872  g_return_val_if_fail (*path == NULL, FALSE);
1873 
1874  /* This is ok -- it means we have an empty sort. Don't do anything */
1875  if (scm_is_bool (sort_scm))
1876  return TRUE;
1877 
1878  /* Ok, this had better be a list */
1879  if (!scm_is_list (sort_scm))
1880  return FALSE;
1881 
1882  /* Parse the path, options, and increasing */
1883  val = SCM_CAR (sort_scm);
1884  sort_scm = SCM_CDR (sort_scm);
1885  if (!scm_is_list (val))
1886  return FALSE;
1887  p = gnc_query_scm2path (val);
1888 
1889  /* options */
1890  val = SCM_CAR (sort_scm);
1891  sort_scm = SCM_CDR (sort_scm);
1892  if (!scm_is_number (val))
1893  {
1894  gnc_query_path_free (p);
1895  return FALSE;
1896  }
1897  o = scm_to_int (val);
1898 
1899  /* increasing */
1900  val = SCM_CAR (sort_scm);
1901  sort_scm = SCM_CDR (sort_scm);
1902  if (!scm_is_bool (val))
1903  {
1904  gnc_query_path_free (p);
1905  return FALSE;
1906  }
1907  i = scm_is_true (val);
1908 
1909  /* EOL */
1910  if (!scm_is_null (sort_scm))
1911  {
1912  gnc_query_path_free (p);
1913  return FALSE;
1914  }
1915  *path = p;
1916  *options = o;
1917  *inc = i;
1918 
1919  return TRUE;
1920 }
1921 
1922 SCM
1923 gnc_query2scm (QofQuery *q)
1924 {
1925  SCM query_scm = SCM_EOL;
1926  SCM pair;
1927  QofQuerySort *s1, *s2, *s3;
1928 
1929  if (!q) return SCM_BOOL_F;
1930 
1931  /* terms */
1932  pair = scm_cons (gnc_query_terms2scm (qof_query_get_terms (q)), SCM_EOL);
1933  pair = scm_cons (scm_from_locale_symbol ("terms"), pair);
1934  query_scm = scm_cons (pair, query_scm);
1935 
1936  /* search-for */
1937  pair = scm_cons (scm_from_locale_symbol (qof_query_get_search_for (q)), SCM_EOL);
1938  pair = scm_cons (scm_from_locale_symbol ("search-for"), pair);
1939  query_scm = scm_cons (pair, query_scm);
1940 
1941  /* sorts... */
1942  qof_query_get_sorts (q, &s1, &s2, &s3);
1943 
1944  /* primary-sort */
1945  pair = scm_cons (gnc_query_sort2scm (s1), SCM_EOL);
1946  pair = scm_cons (scm_from_locale_symbol ("primary-sort"), pair);
1947  query_scm = scm_cons (pair, query_scm);
1948 
1949  /* secondary-sort */
1950  pair = scm_cons (gnc_query_sort2scm (s2), SCM_EOL);
1951  pair = scm_cons (scm_from_locale_symbol ("secondary-sort"), pair);
1952  query_scm = scm_cons (pair, query_scm);
1953 
1954  /* tertiary-sort */
1955  pair = scm_cons (gnc_query_sort2scm (s3), SCM_EOL);
1956  pair = scm_cons (scm_from_locale_symbol ("tertiary-sort"), pair);
1957  query_scm = scm_cons (pair, query_scm);
1958 
1959  /* max results */
1960  pair = scm_cons (scm_from_int (qof_query_get_max_results (q)), SCM_EOL);
1961  pair = scm_cons (scm_from_locale_symbol ("max-results"), pair);
1962  query_scm = scm_cons (pair, query_scm);
1963 
1964  /* Reverse this list; tag it as 'query-v2' */
1965  pair = scm_reverse (query_scm);
1966  return scm_cons (scm_from_locale_symbol ("query-v2"), pair);
1967 }
1968 
1969 static GSList *
1970 gnc_query_sort_to_list (const gchar * symbol)
1971 {
1972  GSList *path = NULL;
1973 
1974  if (!symbol)
1975  return NULL;
1976 
1977  if (!g_strcmp0 (symbol, "by-none"))
1978  {
1979  path = NULL;
1980  }
1981  else if (!g_strcmp0 (symbol, "by-standard"))
1982  {
1983  path = g_slist_prepend (path, QUERY_DEFAULT_SORT);
1984 
1985  }
1986  else if (!g_strcmp0 (symbol, "by-date") ||
1987  !g_strcmp0 (symbol, "by-date-rounded"))
1988  {
1989  path = g_slist_prepend (path, TRANS_DATE_POSTED);
1990  path = g_slist_prepend (path, SPLIT_TRANS);
1991 
1992  }
1993  else if (!g_strcmp0 (symbol, "by-date-entered") ||
1994  !g_strcmp0 (symbol, "by-date-entered-rounded"))
1995  {
1996  path = g_slist_prepend (path, TRANS_DATE_ENTERED);
1997  path = g_slist_prepend (path, SPLIT_TRANS);
1998 
1999  }
2000  else if (!g_strcmp0 (symbol, "by-date-reconciled") ||
2001  !g_strcmp0 (symbol, "by-date-reconciled-rounded"))
2002  {
2003  path = g_slist_prepend (path, SPLIT_DATE_RECONCILED);
2004 
2005  }
2006  else if (!g_strcmp0 (symbol, "by-num"))
2007  {
2008  path = g_slist_prepend (path, TRANS_NUM);
2009  path = g_slist_prepend (path, SPLIT_TRANS);
2010 
2011  }
2012  else if (!g_strcmp0 (symbol, "by-amount"))
2013  {
2014  path = g_slist_prepend (path, SPLIT_VALUE);
2015 
2016  }
2017  else if (!g_strcmp0 (symbol, "by-memo"))
2018  {
2019  path = g_slist_prepend (path, SPLIT_MEMO);
2020 
2021  }
2022  else if (!g_strcmp0 (symbol, "by-desc"))
2023  {
2024  path = g_slist_prepend (path, TRANS_DESCRIPTION);
2025  path = g_slist_prepend (path, SPLIT_TRANS);
2026 
2027  }
2028  else if (!g_strcmp0 (symbol, "by-reconcile"))
2029  {
2030  path = g_slist_prepend (path, SPLIT_RECONCILE);
2031 
2032  }
2033  else if (!g_strcmp0 (symbol, "by-account-full-name"))
2034  {
2035  path = g_slist_prepend (path, SPLIT_ACCT_FULLNAME);
2036 
2037  }
2038  else if (!g_strcmp0 (symbol, "by-account-code"))
2039  {
2040  path = g_slist_prepend (path, ACCOUNT_CODE_);
2041  path = g_slist_prepend (path, SPLIT_ACCOUNT);
2042 
2043  }
2044  else if (!g_strcmp0 (symbol, "by-corr-account-full-name"))
2045  {
2046  path = g_slist_prepend (path, SPLIT_CORR_ACCT_NAME);
2047 
2048  }
2049  else if (!g_strcmp0 (symbol, "by-corr-account-code"))
2050  {
2051  path = g_slist_prepend (path, SPLIT_CORR_ACCT_CODE);
2052 
2053  }
2054  else
2055  {
2056  PERR ("Unknown sort-type, %s", symbol);
2057  }
2058 
2059  return path;
2060 }
2061 
2062 static QofQuery *
2063 gnc_scm2query_v1 (SCM query_scm)
2064 {
2065  QofQuery *q = NULL;
2066  gboolean ok = TRUE;
2067  gchar * primary_sort = NULL;
2068  gchar * secondary_sort = NULL;
2069  gchar * tertiary_sort = NULL;
2070  gboolean primary_increasing = TRUE;
2071  gboolean secondary_increasing = TRUE;
2072  gboolean tertiary_increasing = TRUE;
2073  int max_splits = -1;
2074 
2075  while (!scm_is_null (query_scm))
2076  {
2077  gchar *symbol;
2078  SCM sym_scm;
2079  SCM value;
2080  SCM pair;
2081 
2082  pair = SCM_CAR (query_scm);
2083  query_scm = SCM_CDR (query_scm);
2084 
2085  if (!scm_is_pair (pair))
2086  {
2087  PERR ("Not a Pair");
2088  ok = FALSE;
2089  break;
2090  }
2091 
2092  sym_scm = SCM_CAR (pair);
2093  value = SCM_CADR (pair);
2094 
2095  if (!scm_is_symbol (sym_scm))
2096  {
2097  PERR ("Not a symbol");
2098  ok = FALSE;
2099  break;
2100  }
2101 
2102  symbol = gnc_scm_symbol_to_locale_string (sym_scm);
2103  if (!symbol)
2104  {
2105  PERR ("No string found");
2106  ok = FALSE;
2107  break;
2108  }
2109 
2110  if (g_strcmp0 ("terms", symbol) == 0)
2111  {
2112  if (q)
2113  qof_query_destroy (q);
2114 
2115  q = gnc_scm2query_or_terms (value, gnc_QUERY_v1);
2116  if (!q)
2117  {
2118  PINFO ("invalid terms");
2119  ok = FALSE;
2120  break;
2121  }
2122 
2123  }
2124  else if (g_strcmp0 ("primary-sort", symbol) == 0)
2125  {
2126  if (!scm_is_symbol (value))
2127  {
2128  PINFO ("Invalid primary sort");
2129  ok = FALSE;
2130  break;
2131  }
2132 
2133  primary_sort = gnc_scm_symbol_to_locale_string (value);
2134 
2135  }
2136  else if (g_strcmp0 ("secondary-sort", symbol) == 0)
2137  {
2138  if (!scm_is_symbol (value))
2139  {
2140  PINFO ("Invalid secondary sort");
2141  ok = FALSE;
2142  break;
2143  }
2144 
2145  secondary_sort = gnc_scm_symbol_to_locale_string (value);
2146 
2147  }
2148  else if (g_strcmp0 ("tertiary-sort", symbol) == 0)
2149  {
2150  if (!scm_is_symbol (value))
2151  {
2152  PINFO ("Invalid tertiary sort");
2153  ok = FALSE;
2154  break;
2155  }
2156 
2157  tertiary_sort = gnc_scm_symbol_to_locale_string (value);
2158 
2159  }
2160  else if (g_strcmp0 ("primary-increasing", symbol) == 0)
2161  {
2162  primary_increasing = scm_is_true (value);
2163 
2164  }
2165  else if (g_strcmp0 ("secondary-increasing", symbol) == 0)
2166  {
2167  secondary_increasing = scm_is_true (value);
2168 
2169  }
2170  else if (g_strcmp0 ("tertiary-increasing", symbol) == 0)
2171  {
2172  tertiary_increasing = scm_is_true (value);
2173 
2174  }
2175  else if (g_strcmp0 ("max-splits", symbol) == 0)
2176  {
2177  if (!scm_is_number (value))
2178  {
2179  PERR ("invalid max-splits");
2180  ok = FALSE;
2181  break;
2182  }
2183 
2184  max_splits = scm_to_int (value);
2185 
2186  }
2187  else
2188  {
2189  PERR ("Unknown symbol: %s", symbol);
2190  ok = FALSE;
2191  break;
2192  }
2193 
2194  g_free (symbol);
2195  }
2196 
2197  if (ok)
2198  {
2199  GSList *s1, *s2, *s3;
2200  s1 = gnc_query_sort_to_list (primary_sort);
2201  s2 = gnc_query_sort_to_list (secondary_sort);
2202  s3 = gnc_query_sort_to_list (tertiary_sort);
2203 
2204  qof_query_set_sort_order (q, s1, s2, s3);
2205  qof_query_set_sort_increasing (q, primary_increasing, secondary_increasing,
2206  tertiary_increasing);
2207  qof_query_set_max_results (q, max_splits);
2208  }
2209  else
2210  {
2211  qof_query_destroy (q);
2212  q = NULL;
2213  }
2214 
2215  g_free (primary_sort);
2216  g_free (secondary_sort);
2217  g_free (tertiary_sort);
2218 
2219  return q;
2220 }
2221 
2222 static QofQuery *
2223 gnc_scm2query_v2 (SCM query_scm)
2224 {
2225  QofQuery *q = NULL;
2226  gboolean ok = TRUE;
2227  gchar * search_for = NULL;
2228  GSList *sp1 = NULL, *sp2 = NULL, *sp3 = NULL;
2229  gint so1 = 0, so2 = 0, so3 = 0;
2230  gboolean si1 = TRUE, si2 = TRUE, si3 = TRUE;
2231  int max_results = -1;
2232 
2233  while (!scm_is_null (query_scm))
2234  {
2235  gchar *symbol;
2236  SCM sym_scm;
2237  SCM value;
2238  SCM pair;
2239 
2240  pair = SCM_CAR (query_scm);
2241  query_scm = SCM_CDR (query_scm);
2242 
2243  if (!scm_is_pair (pair))
2244  {
2245  ok = FALSE;
2246  break;
2247  }
2248 
2249  sym_scm = SCM_CAR (pair);
2250  value = SCM_CADR (pair);
2251 
2252  if (!scm_is_symbol (sym_scm))
2253  {
2254  ok = FALSE;
2255  break;
2256  }
2257 
2258  symbol = gnc_scm_symbol_to_locale_string (sym_scm);
2259  if (!symbol)
2260  {
2261  ok = FALSE;
2262  break;
2263  }
2264 
2265  if (!g_strcmp0 ("terms", symbol))
2266  {
2267  if (q)
2268  qof_query_destroy (q);
2269 
2270  q = gnc_scm2query_or_terms (value, gnc_QUERY_v2);
2271  if (!q)
2272  {
2273  ok = FALSE;
2274  break;
2275  }
2276 
2277  }
2278  else if (!g_strcmp0 ("search-for", symbol))
2279  {
2280  if (!scm_is_symbol (value))
2281  {
2282  ok = FALSE;
2283  break;
2284  }
2285  search_for = gnc_scm_symbol_to_locale_string (value);
2286 
2287  }
2288  else if (g_strcmp0 ("primary-sort", symbol) == 0)
2289  {
2290  if (! gnc_query_scm2sort (value, &sp1, &so1, &si1))
2291  {
2292  ok = FALSE;
2293  break;
2294  }
2295 
2296  }
2297  else if (!g_strcmp0 ("secondary-sort", symbol))
2298  {
2299  if (! gnc_query_scm2sort (value, &sp2, &so2, &si2))
2300  {
2301  ok = FALSE;
2302  break;
2303  }
2304 
2305  }
2306  else if (!g_strcmp0 ("tertiary-sort", symbol))
2307  {
2308  if (! gnc_query_scm2sort (value, &sp3, &so3, &si3))
2309  {
2310  ok = FALSE;
2311  break;
2312  }
2313 
2314  }
2315  else if (!g_strcmp0 ("max-results", symbol))
2316  {
2317  if (!scm_is_number (value))
2318  {
2319  ok = FALSE;
2320  break;
2321  }
2322 
2323  max_results = scm_to_int (value);
2324 
2325  }
2326  else
2327  {
2328  ok = FALSE;
2329  break;
2330  }
2331 
2332  g_free (symbol);
2333  }
2334 
2335  if (ok && search_for)
2336  {
2337  qof_query_search_for (q, search_for);
2338  qof_query_set_sort_order (q, sp1, sp2, sp3);
2339  qof_query_set_sort_options (q, so1, so2, so3);
2340  qof_query_set_sort_increasing (q, si1, si2, si3);
2341  qof_query_set_max_results (q, max_results);
2342  }
2343  else
2344  {
2345  qof_query_destroy (q);
2346  q = NULL;
2347  }
2348 
2349  g_free (search_for);
2350 
2351  return q;
2352 }
2353 
2354 QofQuery *
2355 gnc_scm2query (SCM query_scm)
2356 {
2357  SCM q_type;
2358  gchar *type;
2359  QofQuery *q = NULL;
2360 
2361  /* Not a list or NULL? No need to go further */
2362  if (!scm_is_list (query_scm) || scm_is_null (query_scm))
2363  return NULL;
2364 
2365  /* Grab the 'type' (for v2 and above) */
2366  q_type = SCM_CAR (query_scm);
2367 
2368  if (!scm_is_symbol (q_type))
2369  {
2370  if (scm_is_pair (q_type))
2371  {
2372  /* Version-1 queries are just a list */
2373  return gnc_scm2query_v1 (query_scm);
2374  }
2375  else
2376  {
2377  return NULL;
2378  }
2379  }
2380 
2381  /* Ok, the LHS is the version and the RHS is the actual query list */
2382  type = gnc_scm_symbol_to_locale_string (q_type);
2383  if (!type)
2384  return NULL;
2385 
2386  if (!g_strcmp0 (type, "query-v2"))
2387  q = gnc_scm2query_v2 (SCM_CDR (query_scm));
2388 
2389  g_free (type);
2390  return q;
2391 }
2392 
2393 int
2394 gnc_gh_gint64_p(SCM num)
2395 {
2396  static int initialized = 0;
2397  static SCM maxval;
2398  static SCM minval;
2399 
2400  if (!initialized)
2401  {
2402  /* to be super safe, we have to build these manually because
2403  though we know that we have gint64's here, we *don't* know how
2404  to portably specify a 64bit constant to the compiler (i.e. like
2405  0x7FFFFFFFFFFFFFFF). */
2406  gint64 tmp;
2407 
2408  tmp = 0x7FFFFFFF;
2409  tmp <<= 32;
2410  tmp |= 0xFFFFFFFF;
2411  maxval = scm_from_int64(tmp);
2412 
2413  tmp = 0x80000000;
2414  tmp <<= 32;
2415  minval = scm_from_int64(tmp);
2416 
2417  scm_gc_protect_object(maxval);
2418  scm_gc_protect_object(minval);
2419  initialized = 1;
2420  }
2421 
2422  return (scm_is_exact(num) &&
2423  (scm_geq_p(num, minval) != SCM_BOOL_F) &&
2424  (scm_leq_p(num, maxval) != SCM_BOOL_F));
2425 }
2426 
2428 gnc_scm_to_numeric(SCM gncnum)
2429 {
2430  static SCM get_num = SCM_BOOL_F;
2431  static SCM get_denom = SCM_BOOL_F;
2432 
2433  if (get_num == SCM_BOOL_F)
2434  {
2435  get_num = scm_c_eval_string("gnc:gnc-numeric-num");
2436  }
2437  if (get_denom == SCM_BOOL_F)
2438  {
2439  get_denom = scm_c_eval_string("gnc:gnc-numeric-denom");
2440  }
2441 
2442  return gnc_numeric_create(scm_to_int64(scm_call_1(get_num, gncnum)),
2443  scm_to_int64(scm_call_1(get_denom, gncnum)));
2444 }
2445 
2446 SCM
2447 gnc_numeric_to_scm(gnc_numeric arg)
2448 {
2449  static SCM maker = SCM_BOOL_F;
2450 
2451  if (maker == SCM_BOOL_F)
2452  {
2453  maker = scm_c_eval_string("gnc:make-gnc-numeric");
2454  }
2455 
2456  return scm_call_2(maker, scm_from_int64(gnc_numeric_num(arg)),
2457  scm_from_int64(gnc_numeric_denom(arg)));
2458 }
2459 
2460 int
2461 gnc_numeric_p(SCM arg)
2462 {
2463  static SCM type_p = SCM_BOOL_F;
2464  SCM ret = SCM_BOOL_F;
2465 
2466  if (type_p == SCM_BOOL_F)
2467  {
2468  type_p = scm_c_eval_string("gnc:gnc-numeric?");
2469  }
2470  ret = scm_call_1(type_p, arg);
2471 
2472  if (ret == SCM_BOOL_F)
2473  {
2474  return FALSE;
2475  }
2476  else
2477  {
2478  return TRUE;
2479  }
2480 }
2481 
2482 
2483 static SCM
2484 gnc_generic_to_scm(const void *cx, const gchar *type_str)
2485 {
2486  swig_type_info * stype = NULL;
2487  void *x = (void*) cx;
2488 
2489  if (!x) return SCM_BOOL_F;
2490  stype = SWIG_TypeQuery(type_str);
2491 
2492  if (!stype)
2493  {
2494  PERR("Unknown SWIG Type: %s ", type_str);
2495  return SCM_BOOL_F;
2496  }
2497 
2498  return SWIG_NewPointerObj(x, stype, 0);
2499 }
2500 
2501 static void *
2502 gnc_scm_to_generic(SCM scm, const gchar *type_str)
2503 {
2504  swig_type_info * stype = NULL;
2505 
2506  stype = SWIG_TypeQuery(type_str);
2507  if (!stype)
2508  {
2509  PERR("Unknown SWIG Type: %s ", type_str);
2510  return NULL;
2511  }
2512 
2513  if (!SWIG_IsPointerOfType(scm, stype))
2514  return NULL;
2515 
2516  return SWIG_MustGetPtr(scm, stype, 1, 0);
2517 }
2518 
2519 gnc_commodity *
2520 gnc_scm_to_commodity(SCM scm)
2521 {
2522  return gnc_scm_to_generic(scm, "_p_gnc_commodity");
2523 }
2524 
2525 SCM
2526 gnc_commodity_to_scm (const gnc_commodity *commodity)
2527 {
2528  return gnc_generic_to_scm(commodity, "_p_gnc_commodity");
2529 }
2530 
2531 SCM
2532 gnc_book_to_scm (const QofBook *book)
2533 {
2534  return gnc_generic_to_scm(book, "_p_QofBook");
2535 }
void qof_query_add_term(QofQuery *query, QofQueryParamList *param_list, QofQueryPredData *pred_data, QofQueryOp op)
void xaccSplitSetAction(Split *split, const char *actn)
Definition: Split.c:1793
Date and Time handling routines.
QofQueryPredData * qof_query_kvp_predicate(QofQueryCompare how, QofQueryParamList *path, const KvpValue *value)
gnc_numeric double_to_gnc_numeric(double n, gint64 denom, gint how)
#define PINFO(format, args...)
Definition: qoflog.h:249
void qof_query_set_sort_order(QofQuery *q, QofQueryParamList *primary_sort_params, QofQueryParamList *secondary_sort_params, QofQueryParamList *tertiary_sort_params)
KvpValueType
possible types in the union KvpValue
Definition: kvp_frame.h:93
void xaccTransGetDateEnteredTS(const Transaction *trans, Timespec *ts)
Definition: Transaction.c:2236
gboolean string_to_guid(const gchar *string, GncGUID *guid)
gboolean qof_book_use_split_action_for_num_field(const QofBook *book)
void xaccTransSetNum(Transaction *trans, const char *xnum)
Definition: Transaction.c:2065
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
gchar * guid_to_string_buff(const GncGUID *guid, gchar *buff)
QofStringMatch
Definition: qofquerycore.h:71
void qof_query_set_sort_increasing(QofQuery *q, gboolean prim_inc, gboolean sec_inc, gboolean tert_inc)
const char * xaccTransGetNum(const Transaction *trans)
Definition: Transaction.c:2178
#define PERR(format, args...)
Definition: qoflog.h:237
struct _QofQuery QofQuery
Definition: qofquery.h:90
void xaccSplitGetDateReconciledTS(const Split *split, Timespec *ts)
Definition: Split.c:1877
void kvp_frame_delete(KvpFrame *frame)
Definition: guid.h:65
gint64 kvp_value_get_gint64(const KvpValue *value)
void qof_query_set_max_results(QofQuery *q, int n)
#define PWARN(format, args...)
Definition: qoflog.h:243
const gchar * QofIdType
Definition: qofid.h:85
GDate timespec_to_gdate(Timespec ts)
QofBook * qof_session_get_book(const QofSession *session)
Account handling public routines.
void qof_query_destroy(QofQuery *q)
char * kvp_value_get_string(const KvpValue *value)
QofGuidMatch
Definition: qofquerycore.h:110
GncGUID * guid_malloc(void)
#define GUID_ENCODING_LENGTH
Definition: guid.h:74
void kvp_frame_set_slot_nc(KvpFrame *frame, const gchar *key, KvpValue *value)
#define kvp_value_new_gnc_numeric
Definition: kvp_frame.h:466
GList * kvp_value_get_glist(const KvpValue *value)
QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
QofQueryCompare
Definition: qofquerycore.h:55
GncGUID * kvp_value_get_guid(const KvpValue *value)
QofCharMatch
Definition: qofquerycore.h:133
QofQuery * qof_query_invert(QofQuery *q)
All type declarations for the whole Gnucash engine.
KvpValue * kvp_value_new_glist(const GList *value)
void kvp_frame_for_each_slot(KvpFrame *f, void(*proc)(const gchar *key, KvpValue *value, gpointer data), gpointer data)
Definition: SplitP.h:71
const GncGUID * guid_null(void)
QofIdType qof_query_get_search_for(const QofQuery *q)
QofDateMatch
Definition: qofquerycore.h:84
struct KvpFrameImpl KvpFrame
Definition: kvp_frame.h:76
#define QUERY_DEFAULT_SORT
Definition: qofquery.h:106
KvpFrame * kvp_frame_new(void)
const char * xaccSplitGetAction(const Split *split)
Definition: Split.c:1974
KvpFrame * kvp_value_get_frame(const KvpValue *value)
void kvp_value_delete(KvpValue *value)
#define GNC_DENOM_AUTO
Definition: gnc-numeric.h:246
QofNumericMatch
Definition: qofquerycore.h:102
QofQuery * qof_query_create(void)
struct KvpValueImpl KvpValue
Definition: kvp_frame.h:80
#define GNC_HOW_DENOM_SIGFIGS(n)
Definition: gnc-numeric.h:218
void qof_query_search_for(QofQuery *query, QofIdTypeConst obj_type)
void xaccTransGetDatePostedTS(const Transaction *trans, Timespec *ts)
Definition: Transaction.c:2229
const gchar * QofLogModule
Definition: qofid.h:89
void xaccTransSetDatePostedTS(Transaction *trans, const Timespec *ts)
Definition: Transaction.c:1970