a4f8fb9792b0d8dd4a199583badbe0d575f757c1
[chaz/homebank] / src / hb-filter.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "homebank.h"
21 #include "hb-filter.h"
22
23 /****************************************************************************/
24 /* Debug macros */
25 /****************************************************************************/
26 #define MYDEBUG 0
27
28 #if MYDEBUG
29 #define DB(x) (x);
30 #else
31 #define DB(x);
32 #endif
33
34 /* our global datas */
35 extern struct HomeBank *GLOBALS;
36 extern struct Preferences *PREFS;
37
38
39 /* = = = = = = = = = = = = = = = = */
40
41 void da_flt_free(Filter *flt)
42 {
43 DB( g_print("da_flt_free\n") );
44 if(flt != NULL)
45 {
46 g_free(flt->memo);
47 g_free(flt->info);
48 g_free(flt->tag);
49 g_free(flt);
50 }
51 }
52
53
54 Filter *da_flt_malloc(void)
55 {
56 DB( g_print("da_flt_malloc\n") );
57 return g_malloc0(sizeof(Filter));
58 }
59
60
61 /* = = = = = = = = = = = = = = = = = = = = */
62
63
64 void filter_status_acc_clear_except(Filter *flt, guint32 selkey)
65 {
66 GHashTableIter iter;
67 gpointer key, value;
68
69 // set all account
70 g_hash_table_iter_init (&iter, GLOBALS->h_acc);
71 while (g_hash_table_iter_next (&iter, &key, &value))
72 {
73 Account *item = value;
74 item->flt_select = item->key == selkey ? TRUE : FALSE;
75 }
76
77 }
78
79
80 void filter_status_pay_clear_except(Filter *flt, guint32 selkey)
81 {
82 GHashTableIter iter;
83 gpointer key, value;
84
85 // set all payee
86 g_hash_table_iter_init (&iter, GLOBALS->h_pay);
87 while (g_hash_table_iter_next (&iter, &key, &value))
88 {
89 Payee *item = value;
90 item->flt_select = item->key == selkey ? TRUE : FALSE;
91 }
92
93 }
94
95
96 void filter_status_cat_clear_except(Filter *flt, guint32 selkey)
97 {
98 GHashTableIter iter;
99 gpointer key, value;
100
101 // set all category
102 g_hash_table_iter_init (&iter, GLOBALS->h_cat);
103 while (g_hash_table_iter_next (&iter, &key, &value))
104 {
105 Category *item = value;
106
107
108 item->flt_select = FALSE;
109 if( (item->key == selkey)
110 //#1824561 don't forget subcat
111 //#1829076 but not when selkey is 0
112 || ((item->parent == selkey) && selkey > 0)
113 )
114 item->flt_select = TRUE;
115 }
116
117 }
118
119
120 /* = = = = = = = = = = = = = = = = */
121
122
123 void filter_reset(Filter *flt)
124 {
125 gint i;
126
127 DB( g_print("\n[filter] default reset all %p\n", flt) );
128
129 for(i=0;i<FILTER_MAX;i++)
130 {
131 flt->option[i] = 0;
132 }
133
134 flt->option[FILTER_DATE] = 1;
135 flt->range = FLT_RANGE_LAST12MONTHS;
136 filter_preset_daterange_set(flt, flt->range, 0);
137
138 for(i=0;i<NUM_PAYMODE_MAX;i++)
139 flt->paymode[i] = TRUE;
140
141 g_free(flt->info);
142 g_free(flt->memo);
143 g_free(flt->tag);
144 flt->info = NULL;
145 flt->memo = NULL;
146 flt->tag = NULL;
147
148 //unsaved
149 flt->nbdaysfuture = 0;
150 flt->type = FLT_TYPE_ALL;
151 flt->status = FLT_STATUS_ALL;
152 flt->forceremind = PREFS->showremind;
153
154 *flt->last_tab = '\0';
155 }
156
157
158 void filter_set_tag_by_id(Filter *flt, guint32 key)
159 {
160 Tag *tag;
161
162 DB( g_print("\n[filter] set tag by id\n") );
163
164 if(flt->tag)
165 {
166 g_free(flt->tag);
167 flt->tag = NULL;
168 }
169
170 tag = da_tag_get(key);
171 if(tag)
172 {
173 flt->tag = g_strdup(tag->name);
174 }
175 }
176
177
178 static void filter_set_date_bounds(Filter *flt, guint32 kacc)
179 {
180 GList *lst_acc, *lnk_acc;
181 GList *lnk_txn;
182
183 DB( g_print("\n[filter] set date bounds %p\n", flt) );
184
185 flt->mindate = 0;
186 flt->maxdate = 0;
187
188 lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
189 lnk_acc = g_list_first(lst_acc);
190 while (lnk_acc != NULL)
191 {
192 Account *acc = lnk_acc->data;
193
194 //#1674045 only rely on nosummary
195 //if( !(acc->flags & AF_CLOSED) )
196 {
197 Transaction *txn;
198
199 DB( g_print(" - do '%s'\n", acc->name) );
200
201 lnk_txn = g_queue_peek_head_link(acc->txn_queue);
202 if(lnk_txn) {
203 txn = lnk_txn->data;
204 if( (kacc == 0) || (txn->kacc == kacc) )
205 {
206 if( flt->mindate == 0 )
207 flt->mindate = txn->date;
208 else
209 flt->mindate = MIN(flt->mindate, txn->date);
210 }
211 }
212
213 lnk_txn = g_queue_peek_tail_link(acc->txn_queue);
214 if(lnk_txn) {
215 txn = lnk_txn->data;
216 if( (kacc == 0) || (txn->kacc == kacc) )
217 {
218 if( flt->maxdate == 0 )
219 flt->maxdate = txn->date;
220 else
221 flt->maxdate = MAX(flt->maxdate, txn->date);
222 }
223 }
224
225 }
226 lnk_acc = g_list_next(lnk_acc);
227 }
228
229 if( flt->mindate == 0 )
230 //changed 5.3
231 //flt->mindate = HB_MINDATE;
232 flt->mindate = GLOBALS->today - 365;
233
234 if( flt->maxdate == 0 )
235 //changed 5.3
236 //flt->maxdate = HB_MAXDATE;
237 flt->maxdate = GLOBALS->today + flt->nbdaysfuture;
238
239 g_list_free(lst_acc);
240 }
241
242
243 void filter_preset_daterange_add_futuregap(Filter *filter, gint nbdays)
244 {
245
246 DB( g_print("\n[filter] range add future gap\n") );
247
248 //fixed > 5.1.7
249 /*if( nbdays <= 0 )
250 {
251 filter->nbdaysfuture = 0;
252 return;
253 }*/
254
255 filter->nbdaysfuture = 0;
256
257 switch( filter->range )
258 {
259 case FLT_RANGE_THISMONTH:
260 case FLT_RANGE_THISQUARTER:
261 case FLT_RANGE_THISYEAR:
262 case FLT_RANGE_LAST30DAYS:
263 case FLT_RANGE_LAST60DAYS:
264 case FLT_RANGE_LAST90DAYS:
265 case FLT_RANGE_LAST12MONTHS:
266 filter->nbdaysfuture = nbdays;
267 break;
268 }
269 }
270
271
272 void filter_preset_daterange_set(Filter *flt, gint range, guint32 kacc)
273 {
274 GDate *tmpdate;
275 guint32 jtoday, jfiscal;
276 guint16 month, year, yfiscal, qnum;
277
278 DB( g_print("\n[filter] daterange set %p %d\n", flt, range) );
279
280 flt->range = range;
281
282 jtoday = GLOBALS->today;
283
284 tmpdate = g_date_new_julian(jtoday);
285
286 month = g_date_get_month(tmpdate);
287 year = g_date_get_year(tmpdate);
288 DB( hb_print_date(jtoday , "today ") );
289
290 g_date_set_dmy(tmpdate, PREFS->fisc_year_day, PREFS->fisc_year_month, year);
291 jfiscal = g_date_get_julian(tmpdate);
292 DB( hb_print_date(jfiscal, "fiscal") );
293
294 yfiscal = (jtoday >= jfiscal) ? year : year-1;
295 qnum = 0;
296
297 if( range == FLT_RANGE_THISQUARTER || range == FLT_RANGE_LASTQUARTER )
298 {
299 g_date_set_dmy(tmpdate, PREFS->fisc_year_day, PREFS->fisc_year_month, yfiscal);
300 while( (qnum < 5) && (g_date_get_julian(tmpdate) < jtoday) )
301 {
302 qnum++;
303 g_date_add_months (tmpdate, 3);
304 }
305 DB( g_print(" qnum: %d\n", qnum ) );
306 }
307
308 switch( range )
309 {
310 case FLT_RANGE_THISMONTH:
311 case FLT_RANGE_LASTMONTH:
312 g_date_set_dmy(tmpdate, 1, month, year);
313 if( range == FLT_RANGE_LASTMONTH )
314 g_date_subtract_months(tmpdate, 1);
315 flt->mindate = g_date_get_julian(tmpdate);
316 month = g_date_get_month(tmpdate);
317 year = g_date_get_year(tmpdate);
318 g_date_add_days(tmpdate, g_date_get_days_in_month(month, year));
319 flt->maxdate = g_date_get_julian(tmpdate) - 1;
320 break;
321
322 case FLT_RANGE_THISQUARTER:
323 case FLT_RANGE_LASTQUARTER:
324 g_date_set_dmy(tmpdate, PREFS->fisc_year_day, PREFS->fisc_year_month, yfiscal);
325 if( range == FLT_RANGE_LASTQUARTER )
326 g_date_subtract_months(tmpdate, 3);
327 g_date_add_months(tmpdate, 3 * (qnum-1) );
328 flt->mindate = g_date_get_julian(tmpdate);
329 g_date_add_months(tmpdate, 3);
330 flt->maxdate = g_date_get_julian(tmpdate) - 1;
331 break;
332
333 case FLT_RANGE_THISYEAR:
334 case FLT_RANGE_LASTYEAR:
335 g_date_set_dmy(tmpdate, PREFS->fisc_year_day, PREFS->fisc_year_month, yfiscal);
336 if( range == FLT_RANGE_LASTYEAR )
337 g_date_subtract_years(tmpdate, 1);
338 flt->mindate = g_date_get_julian(tmpdate);
339 g_date_add_years (tmpdate, 1);
340 flt->maxdate = g_date_get_julian(tmpdate) - 1;
341 break;
342
343 case FLT_RANGE_LAST30DAYS:
344 flt->mindate = jtoday - 30;
345 flt->maxdate = jtoday;
346 break;
347
348 case FLT_RANGE_LAST60DAYS:
349 flt->mindate = jtoday - 60;
350 flt->maxdate = jtoday;
351 break;
352
353 case FLT_RANGE_LAST90DAYS:
354 flt->mindate = jtoday - 90;
355 flt->maxdate = jtoday;
356 break;
357
358 case FLT_RANGE_LAST12MONTHS:
359 g_date_set_julian (tmpdate, jtoday);
360 g_date_subtract_months(tmpdate, 12);
361 flt->mindate = g_date_get_julian(tmpdate);
362 flt->maxdate = jtoday;
363 break;
364
365 // case FLT_RANGE_OTHER:
366 //nothing to do
367
368 case FLT_RANGE_ALLDATE:
369 filter_set_date_bounds(flt, kacc);
370 break;
371 }
372 g_date_free(tmpdate);
373 }
374
375
376 void filter_preset_type_set(Filter *flt, gint type)
377 {
378
379 DB( g_print("\n[filter] preset type set\n") );
380
381 /* any type */
382 flt->type = type;
383 flt->option[FILTER_AMOUNT] = 0;
384 flt->minamount = G_MINDOUBLE;
385 flt->maxamount = G_MINDOUBLE;
386
387 switch( type )
388 {
389 case FLT_TYPE_EXPENSE:
390 flt->option[FILTER_AMOUNT] = 1;
391 flt->minamount = -G_MAXDOUBLE;
392 flt->maxamount = G_MINDOUBLE;
393 break;
394
395 case FLT_TYPE_INCOME:
396 flt->option[FILTER_AMOUNT] = 1;
397 flt->minamount = G_MINDOUBLE;
398 flt->maxamount = G_MAXDOUBLE;
399 break;
400 }
401
402 }
403
404
405 void filter_preset_status_set(Filter *flt, gint status)
406 {
407
408 DB( g_print("\n[filter] preset status set\n") );
409
410 /* any status */
411 flt->status = status;
412 flt->option[FILTER_STATUS] = 0;
413 flt->option[FILTER_CATEGORY] = 0;
414 flt->option[FILTER_PAYMODE] = 0;
415 flt->reconciled = TRUE;
416 flt->cleared = TRUE;
417 //#1602835 fautly set
418 //flt->forceadd = TRUE;
419 //flt->forcechg = TRUE;
420
421 switch( status )
422 {
423 case FLT_STATUS_UNCATEGORIZED:
424 flt->option[FILTER_CATEGORY] = 1;
425 filter_status_cat_clear_except(flt, 0);
426 flt->option[FILTER_PAYMODE] = 1;
427 flt->paymode[PAYMODE_INTXFER] = FALSE;
428 break;
429
430 case FLT_STATUS_UNRECONCILED:
431 flt->option[FILTER_STATUS] = 2;
432 flt->reconciled = TRUE;
433 flt->cleared = FALSE;
434 break;
435
436 case FLT_STATUS_UNCLEARED:
437 flt->option[FILTER_STATUS] = 2;
438 flt->reconciled = FALSE;
439 flt->cleared = TRUE;
440 break;
441
442 case FLT_STATUS_RECONCILED:
443 flt->option[FILTER_STATUS] = 1;
444 flt->reconciled = TRUE;
445 flt->cleared = FALSE;
446 break;
447
448 case FLT_STATUS_CLEARED:
449 flt->option[FILTER_STATUS] = 1;
450 flt->reconciled = FALSE;
451 flt->cleared = TRUE;
452 break;
453
454 }
455 }
456
457
458 gchar *filter_daterange_text_get(Filter *flt)
459 {
460 gchar buffer1[128];
461 gchar buffer2[128];
462 gchar buffer3[128];
463 GDate *date;
464 gchar *retval = NULL;
465
466 DB( g_print("\n[filter] daterange text get\n") );
467
468 date = g_date_new_julian(flt->mindate);
469 g_date_strftime (buffer1, 128-1, PREFS->date_format, date);
470
471 g_date_set_julian(date, flt->maxdate);
472 g_date_strftime (buffer2, 128-1, PREFS->date_format, date);
473
474 if( flt->nbdaysfuture > 0 )
475 {
476 g_date_set_julian(date, flt->maxdate + flt->nbdaysfuture);
477 g_date_strftime (buffer3, 128-1, PREFS->date_format, date);
478 retval = g_strdup_printf("%s — <s>%s</s> %s", buffer1, buffer2, buffer3);
479 }
480 else
481 retval = g_strdup_printf("%s — %s", buffer1, buffer2);
482
483 g_date_free(date);
484
485 //return g_strdup_printf(_("<i>from</i> %s <i>to</i> %s — "), buffer1, buffer2);
486 return retval;
487 }
488
489
490 /* used for quicksearch text into transaction */
491 gboolean filter_txn_search_match(gchar *needle, Transaction *txn, gint flags)
492 {
493 gboolean retval = FALSE;
494 Payee *payitem;
495 Category *catitem;
496 gchar *tags;
497
498 DB( g_print("\n[filter] tnx search match\n") );
499
500 if(flags & FLT_QSEARCH_MEMO)
501 {
502 //#1668036 always try match on txn memo first
503 if(txn->memo)
504 {
505 retval |= hb_string_utf8_strstr(txn->memo, needle, FALSE);
506 }
507 if(retval) goto end;
508
509 //#1509485
510 if(txn->flags & OF_SPLIT)
511 {
512 guint count, i;
513 Split *split;
514
515 count = da_splits_length(txn->splits);
516 for(i=0;i<count;i++)
517 {
518 gint tmpinsert = 0;
519
520 split = da_splits_get(txn->splits, i);
521 tmpinsert = hb_string_utf8_strstr(split->memo, needle, FALSE);
522 retval |= tmpinsert;
523 if( tmpinsert )
524 break;
525 }
526 }
527 if(retval) goto end;
528 }
529
530 if(flags & FLT_QSEARCH_INFO)
531 {
532 if(txn->info)
533 {
534 retval |= hb_string_utf8_strstr(txn->info, needle, FALSE);
535 }
536 if(retval) goto end;
537 }
538
539 if(flags & FLT_QSEARCH_PAYEE)
540 {
541 payitem = da_pay_get(txn->kpay);
542 if(payitem)
543 {
544 retval |= hb_string_utf8_strstr(payitem->name, needle, FALSE);
545 }
546 if(retval) goto end;
547 }
548
549 if(flags & FLT_QSEARCH_CATEGORY)
550 {
551 //#1509485
552 if(txn->flags & OF_SPLIT)
553 {
554 guint count, i;
555 Split *split;
556
557 count = da_splits_length(txn->splits);
558 for(i=0;i<count;i++)
559 {
560 gint tmpinsert = 0;
561
562 split = da_splits_get(txn->splits, i);
563 catitem = da_cat_get(split->kcat);
564 if(catitem)
565 {
566 tmpinsert = hb_string_utf8_strstr(catitem->fullname, needle, FALSE);
567 retval |= tmpinsert;
568 }
569
570 if( tmpinsert )
571 break;
572 }
573 }
574 else
575 {
576 catitem = da_cat_get(txn->kcat);
577 if(catitem)
578 {
579 retval |= hb_string_utf8_strstr(catitem->fullname, needle, FALSE);
580 }
581 }
582 if(retval) goto end;
583 }
584
585 if(flags & FLT_QSEARCH_TAGS)
586 {
587 tags = tags_tostring(txn->tags);
588 if(tags)
589 {
590 retval |= hb_string_utf8_strstr(tags, needle, FALSE);
591 }
592 g_free(tags);
593 if(retval) goto end;
594 }
595
596 //#1741339 add quicksearch for amount
597 if(flags & FLT_QSEARCH_AMOUNT)
598 {
599 gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
600
601 hb_strfnum(formatd_buf, G_ASCII_DTOSTR_BUF_SIZE-1, txn->amount, txn->kcur, FALSE);
602 retval |= hb_string_utf8_strstr(formatd_buf, needle, FALSE);
603 }
604
605
606 end:
607 return retval;
608 }
609
610
611 gint filter_txn_match(Filter *flt, Transaction *txn)
612 {
613 Account *accitem;
614 Payee *payitem;
615 Category *catitem;
616 gint insert;
617
618 //DB( g_print("\n[filter] txn match\n") );
619
620 insert = 1;
621
622 /*** start filtering ***/
623
624 /* force display */
625 if(flt->forceadd == TRUE && (txn->flags & OF_ADDED))
626 goto end;
627
628 if(flt->forcechg == TRUE && (txn->flags & OF_CHANGED))
629 goto end;
630
631 /* force remind if not filter on status */
632 if(flt->forceremind == TRUE && (txn->status == TXN_STATUS_REMIND))
633 goto end;
634
635 /* date */
636 if(flt->option[FILTER_DATE]) {
637 insert = ( (txn->date >= flt->mindate) && (txn->date <= (flt->maxdate + flt->nbdaysfuture) ) ) ? 1 : 0;
638 if(flt->option[FILTER_DATE] == 2) insert ^= 1;
639 }
640 if(!insert) goto end;
641
642 /* account */
643 if(flt->option[FILTER_ACCOUNT]) {
644 accitem = da_acc_get(txn->kacc);
645 if(accitem)
646 {
647 insert = ( accitem->flt_select == TRUE ) ? 1 : 0;
648 if(flt->option[FILTER_ACCOUNT] == 2) insert ^= 1;
649 }
650 }
651 if(!insert) goto end;
652
653 /* payee */
654 if(flt->option[FILTER_PAYEE]) {
655 payitem = da_pay_get(txn->kpay);
656 if(payitem)
657 {
658 insert = ( payitem->flt_select == TRUE ) ? 1 : 0;
659 if(flt->option[FILTER_PAYEE] == 2) insert ^= 1;
660 }
661 }
662 if(!insert) goto end;
663
664 /* category */
665 if(flt->option[FILTER_CATEGORY]) {
666 if(txn->flags & OF_SPLIT)
667 {
668 guint count, i;
669 Split *split;
670
671 insert = 0; //fix: 1151259
672 count = da_splits_length(txn->splits);
673 for(i=0;i<count;i++)
674 {
675 gint tmpinsert = 0;
676
677 split = da_splits_get(txn->splits, i);
678 catitem = da_cat_get(split->kcat);
679 if(catitem)
680 {
681 tmpinsert = ( catitem->flt_select == TRUE ) ? 1 : 0;
682 if(flt->option[FILTER_CATEGORY] == 2) tmpinsert ^= 1;
683 }
684 insert |= tmpinsert;
685 }
686 }
687 else
688 {
689 catitem = da_cat_get(txn->kcat);
690 if(catitem)
691 {
692 insert = ( catitem->flt_select == TRUE ) ? 1 : 0;
693 if(flt->option[FILTER_CATEGORY] == 2) insert ^= 1;
694 }
695 }
696 }
697 if(!insert) goto end;
698
699 /* status */
700 if(flt->option[FILTER_STATUS]) {
701 gint insert1 = 0, insert2 = 0;
702
703 if(flt->reconciled)
704 insert1 = ( txn->status == TXN_STATUS_RECONCILED ) ? 1 : 0;
705 if(flt->cleared)
706 insert2 = ( txn->status == TXN_STATUS_CLEARED ) ? 1 : 0;
707
708 insert = insert1 | insert2;
709 if(flt->option[FILTER_STATUS] == 2) insert ^= 1;
710 }
711 if(!insert) goto end;
712
713 /* paymode */
714 if(flt->option[FILTER_PAYMODE]) {
715 insert = ( flt->paymode[txn->paymode] == TRUE) ? 1 : 0;
716 if(flt->option[FILTER_PAYMODE] == 2) insert ^= 1;
717 }
718 if(!insert) goto end;
719
720 /* amount */
721 if(flt->option[FILTER_AMOUNT]) {
722 insert = ( (txn->amount >= flt->minamount) && (txn->amount <= flt->maxamount) ) ? 1 : 0;
723
724 if(flt->option[FILTER_AMOUNT] == 2) insert ^= 1;
725 }
726 if(!insert) goto end;
727
728 /* info/memo/tag */
729 if(flt->option[FILTER_TEXT])
730 {
731 gchar *tags;
732 gint insert1, insert2, insert3;
733
734 insert1 = insert2 = insert3 = 0;
735 if(flt->info)
736 {
737 if(txn->info)
738 {
739 insert1 = hb_string_utf8_strstr(txn->info, flt->info, flt->exact);
740 }
741 }
742 else
743 insert1 = 1;
744
745 if(flt->memo)
746 {
747 //#1668036 always try match on txn memo first
748 if(txn->memo)
749 {
750 insert2 = hb_string_utf8_strstr(txn->memo, flt->memo, flt->exact);
751 }
752
753 if( (insert2 == 0) && (txn->flags & OF_SPLIT) )
754 {
755 guint count, i;
756 Split *split;
757
758 count = da_splits_length(txn->splits);
759 for(i=0;i<count;i++)
760 {
761 gint tmpinsert = 0;
762
763 split = da_splits_get(txn->splits, i);
764 tmpinsert = hb_string_utf8_strstr(split->memo, flt->memo, flt->exact);
765 insert2 |= tmpinsert;
766 if( tmpinsert )
767 break;
768 }
769 }
770 }
771 else
772 insert2 = 1;
773
774 if(flt->tag)
775 {
776 tags = tags_tostring(txn->tags);
777 if(tags)
778 {
779 insert3 = hb_string_utf8_strstr(tags, flt->tag, flt->exact);
780 }
781 g_free(tags);
782 }
783 else
784 insert3 = 1;
785
786 insert = insert1 && insert2 && insert3 ? 1 : 0;
787
788 if(flt->option[FILTER_TEXT] == 2) insert ^= 1;
789
790 }
791 if(!insert) goto end;
792
793 end:
794 // DB( g_print(" %d :: %d :: %d\n", flt->mindate, txn->date, flt->maxdate) );
795 // DB( g_print(" [%d] %s => %d (%d)\n", txn->account, txn->memo, insert, count) );
796 return(insert);
797 }
798
This page took 0.07819 seconds and 4 git commands to generate.