GnuCash c935c2f+
Loading...
Searching...
No Matches
split-register-model.c
1/********************************************************************\
2 * split-register-model.c -- split register model object *
3 * *
4 * This program is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU General Public License as *
6 * published by the Free Software Foundation; either version 2 of *
7 * the License, or (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License*
15 * along with this program; if not, contact: *
16 * *
17 * Free Software Foundation Voice: +1-617-542-5942 *
18 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19 * Boston, MA 02110-1301, USA gnu@gnu.org *
20 * *
21\********************************************************************/
22
23#include <config.h>
24
25#include <glib.h>
26#include <glib/gi18n.h>
27
28#include "datecell.h"
29#include "dialog-utils.h"
30#include "dialog-doclink-utils.h"
31#include "gnc-engine.h"
32#include "gnc-prefs.h"
33#include "gnc-ui.h"
34#include "gnc-uri-utils.h"
35#include "gnc-glib-utils.h"
36#include "gnc-filepath-utils.h"
37#include "gnc-warnings.h"
38#include "doclinkcell.h"
39#include "pricecell.h"
40#include "recncell.h"
41#include "split-register.h"
44#include "split-register-p.h"
45#include "engine-helpers.h"
46
47/* This static indicates the debugging module that this .o belongs to. */
48static QofLogModule log_module = GNC_MOD_LEDGER;
49
50/* Flag for determining colorization of negative amounts. */
51static gboolean use_red_for_negative = TRUE;
52
53/* This returns the balance at runtime of a register at the split defined by virt_loc regardless of
54 * sort order. It always assumes that the first txn in the register is starting from a 0 balance.
55 * If gboolean subaccounts is TRUE, then it will return the total balance of the parent account
56 * and all its subaccounts. FALSE will return the balance of just the parent account of the register. */
57static gnc_numeric
58gnc_split_register_get_rbaln (VirtualLocation virt_loc, gpointer user_data,
59 gboolean subaccounts)
60{
61 SplitRegister* reg = user_data;
62 Split* split;
63 SRInfo* info = gnc_split_register_get_info (reg);
64 gnc_numeric balance;
65 Account* account = NULL;
66 Transaction* trans;
67 GList* node, *child;
68 GList* children = NULL;
69 int i, row;
70
71 balance = gnc_numeric_zero();
72
73 /* Return NULL if this is a blank transaction. */
74 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
75 if (split == xaccSplitLookup (&info->blank_split_guid,
76 gnc_get_current_book()))
77 return gnc_numeric_zero();
78
79 trans = xaccSplitGetParent (split);
80 if (!trans)
81 return gnc_numeric_zero();
82
83 /* Get a list of accounts for matching */
84 account = gnc_split_register_get_default_account (reg);
85 if (!account)
86 /* Register has no account (perhaps general journal) so it has no
87 well defined balance, return zero. */
88 return balance;
89
90 if (subaccounts)
91 {
92 children = gnc_account_get_descendants (account);
93 children = g_list_prepend (children, account);
94 }
95
96 /* Get the row number we're on, then start with the first row. */
97 row = virt_loc.vcell_loc.virt_row;
98 virt_loc.vcell_loc.virt_row = 0;
99
100 while (virt_loc.vcell_loc.virt_row <= row)
101 {
102 /* Get new temporary split and its parent transaction */
103 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
104 trans = xaccSplitGetParent (split);
105
106 i = 1;
107 for (node = xaccTransGetSplitList (trans); node; node = node->next)
108 {
109 Split* secondary = node->data;
110
111 if (!xaccTransStillHasSplit (trans, secondary))
112 continue;
113
114 i++;
115
116 if (subaccounts)
117 {
118 /* Add up the splits that belong to the transaction if they are
119 * from the lead account or one of the subaccounts. */
120 account = xaccSplitGetAccount (secondary);
121
122 for (child = children; child; child = child->next)
123 {
124 if (account == child->data)
125 {
126 balance = gnc_numeric_add_fixed (balance, xaccSplitGetAmount (secondary));
127 break;
128 }
129 }
130 }
131 else
132 {
133 if (account == xaccSplitGetAccount (secondary))
134 balance = gnc_numeric_add_fixed (balance, xaccSplitGetAmount (secondary));
135 }
136 }
137 virt_loc.vcell_loc.virt_row += i;
138 }
139
140 if (subaccounts)
141 g_list_free (children);
142
143 return balance;
144}
145
146static gnc_commodity*
147gnc_split_register_get_split_commodity (SplitRegister* reg,
148 VirtualLocation virt_loc)
149{
150 CursorClass cursor_class;
151 Account* account;
152 Split* split;
153
154 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
155 if (!split)
156 return NULL;
157
158 cursor_class = gnc_split_register_get_cursor_class (reg,
159 virt_loc.vcell_loc);
160 if (cursor_class != CURSOR_CLASS_SPLIT)
161 return NULL;
162
163 account = NULL;
164
165 if (virt_cell_loc_equal (virt_loc.vcell_loc,
166 reg->table->current_cursor_loc.vcell_loc) &&
167 gnc_table_layout_get_cell_changed (reg->table->layout, XFRM_CELL, FALSE))
168 {
169 const char* name;
170
171 name = gnc_table_layout_get_cell_value (reg->table->layout, XFRM_CELL);
172 account = gnc_account_lookup_for_register (gnc_get_current_root_account(),
173 name);
174 }
175
176 if (!account)
177 account = xaccSplitGetAccount (split);
178
179 if (!account)
180 return NULL;
181
182 return xaccAccountGetCommodity (account);
183}
184
185static gboolean
186gnc_split_register_use_security_cells (SplitRegister* reg,
187 VirtualLocation virt_loc)
188{
189 CursorClass cursor_class;
190 Account* account;
191 Split* split;
192
193 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
194 if (!split)
195 return TRUE;
196
197 cursor_class = gnc_split_register_get_cursor_class (reg,
198 virt_loc.vcell_loc);
199 if (cursor_class != CURSOR_CLASS_SPLIT)
200 return TRUE;
201
202 account = NULL;
203
204 if (virt_cell_loc_equal (virt_loc.vcell_loc,
205 reg->table->current_cursor_loc.vcell_loc) &&
206 gnc_table_layout_get_cell_changed (reg->table->layout, XFRM_CELL, FALSE))
207 {
208 const char* name;
209
210 name = gnc_table_layout_get_cell_value (reg->table->layout, XFRM_CELL);
211 account = gnc_account_lookup_for_register (gnc_get_current_root_account(),
212 name);
213 }
214
215 if (!account)
216 account = xaccSplitGetAccount (split);
217
218 if (!account)
219 return TRUE;
220
222 {
223 gnc_commodity* commod = xaccAccountGetCommodity (account);
224 if (!gnc_commodity_is_iso (commod) ||
225 !gnc_commodity_equal (commod,
227 return TRUE;
228 }
229
230 return xaccAccountIsPriced (account);
231}
232
233static const char*
234gnc_split_register_get_date_label (VirtualLocation virt_loc,
235 gpointer user_data)
236{
237 return _ ("Date");
238}
239
240static const char*
241gnc_split_register_get_due_date_label (VirtualLocation virt_loc,
242 gpointer user_data)
243{
244 return _ ("Due Date");
245}
246
247static const char*
248gnc_split_register_get_num_label (VirtualLocation virt_loc,
249 gpointer user_data)
250{
251 SplitRegister* reg = user_data;
252
253 switch (reg->type)
254 {
255 case RECEIVABLE_REGISTER:
256 case PAYABLE_REGISTER:
257 /* Column label for Invoice IDs in A/P & A/R accounts */
258 /* Translators: Ref is the column header in Accounts Payable and
259 * Accounts Receivable ledgers for the number of the invoice or bill
260 * associated with the transaction.
261 */
262 return _ ("Ref");
263 default:
264 return _ ("Num");
265 }
266}
267
268static const char*
269gnc_split_register_get_tran_num_label (VirtualLocation virt_loc,
270 gpointer user_data)
271{
272 SplitRegister* reg = user_data;
273
274 switch (reg->type)
275 {
276 case RECEIVABLE_REGISTER:
277 case PAYABLE_REGISTER:
278 return _ ("T-Ref");
279 case GENERAL_JOURNAL:
280 case INCOME_LEDGER:
281 case SEARCH_LEDGER:
282 {
283 if (reg->use_tran_num_for_num_field)
284 return _ ("Num");
285 }
286 default:
287 return _ ("T-Num");
288 }
289}
290
291static const char*
292gnc_split_register_get_desc_label (VirtualLocation virt_loc,
293 gpointer user_data)
294{
295 SplitRegister* reg = user_data;
296
297 switch (reg->type)
298 {
299 case RECEIVABLE_REGISTER:
300 return _ ("Customer");
301 case PAYABLE_REGISTER:
302 return _ ("Vendor");
303 default:
304 return _ ("Description");
305 }
306}
307
308static const char*
309gnc_split_register_get_recn_label (VirtualLocation virt_loc,
310 gpointer user_data)
311{
312 SplitRegister* reg = user_data;
313
314 switch (reg->type)
315 {
316 case RECEIVABLE_REGISTER:
317 case PAYABLE_REGISTER:
318 return _ ("Paid");
319
320 default:
321 return C_ ("Column header for 'Reconciled'", "R");
322 }
323}
324
325static const char*
326gnc_split_register_get_baln_label (VirtualLocation virt_loc,
327 gpointer user_data)
328{
329 return _ ("Balance");
330}
331
332static const char*
333gnc_split_register_get_action_label (VirtualLocation virt_loc,
334 gpointer user_data)
335{
336 return _ ("Action");
337}
338
339static const char*
340gnc_split_register_get_doclink_label (VirtualLocation virt_loc,
341 gpointer user_data)
342{
343 return C_ ("Column header for 'Document Link'", "L");
344}
345
346static const char*
347gnc_split_register_get_xfrm_label (VirtualLocation virt_loc,
348 gpointer user_data)
349{
350 return _ ("Account");
351}
352
353static const char*
354gnc_split_register_get_mxfrm_label (VirtualLocation virt_loc,
355 gpointer user_data)
356{
357 return _ ("Transfer");
358}
359
360static const char*
361gnc_split_register_get_memo_label (VirtualLocation virt_loc,
362 gpointer user_data)
363{
364 return _ ("Memo");
365}
366
367static const char*
368gnc_split_register_get_type_label (VirtualLocation virt_loc,
369 gpointer user_data)
370{
371 return _ ("Type");
372}
373
374static const char*
375gnc_split_register_get_rate_label (VirtualLocation virt_loc,
376 gpointer user_data)
377{
378 return _ ("Rate");
379}
380
381static const char*
382gnc_split_register_get_debit_label (VirtualLocation virt_loc,
383 gpointer user_data)
384{
385 SplitRegister* reg = user_data;
386
388}
389
390static const char*
391gnc_split_register_get_credit_label (VirtualLocation virt_loc,
392 gpointer user_data)
393{
394 SplitRegister* reg = user_data;
395
397}
398
399static const char*
400gnc_split_register_get_price_label (VirtualLocation virt_loc,
401 gpointer user_data)
402{
403 SplitRegister* reg = user_data;
404 gnc_commodity* commod;
405
406 if (!gnc_split_register_use_security_cells (reg, virt_loc))
407 return NULL;
408
409 commod = gnc_split_register_get_split_commodity (reg, virt_loc);
410 if (!commod || !gnc_commodity_is_iso (commod))
411 return _ ("Price");
412 else
413 return _ ("Exch. Rate");
414}
415
416static const char*
417gnc_split_register_get_shares_label (VirtualLocation virt_loc,
418 gpointer user_data)
419{
420 SplitRegister* reg = user_data;
421 gnc_commodity* commod;
422
423 if (!gnc_split_register_use_security_cells (reg, virt_loc))
424 return NULL;
425
426 commod = gnc_split_register_get_split_commodity (reg, virt_loc);
427 if (!commod || !gnc_commodity_is_iso (commod))
428 return _ ("Shares");
429 else
430 return _ ("Oth. Curr.");
431}
432
433static const char*
434gnc_split_register_get_tcredit_label (VirtualLocation virt_loc,
435 gpointer user_data)
436{
437 SplitRegister* reg = user_data;
438 SRInfo* info = gnc_split_register_get_info (reg);
439
440 if (reg->is_template)
441 return "";
442
443 if (info->tcredit_str)
444 return info->tcredit_str;
445
446 {
447 const char* string = gnc_split_register_get_credit_string (reg);
448
449 if (string)
450 info->tcredit_str = g_strdup_printf (_ ("Tot %s"), string);
451 }
452
453 if (info->tcredit_str)
454 return info->tcredit_str;
455
456 info->tcredit_str = g_strdup (_ ("Tot Credit"));
457
458 return info->tcredit_str;
459}
460
461static const char*
462gnc_split_register_get_tdebit_label (VirtualLocation virt_loc,
463 gpointer user_data)
464{
465 SplitRegister* reg = user_data;
466 SRInfo* info = gnc_split_register_get_info (reg);
467
468 if (reg->is_template)
469 return "";
470
471 if (info->tdebit_str)
472 return info->tdebit_str;
473
474 {
475 const char* string = gnc_split_register_get_debit_string (reg);
476 if (string)
477 info->tdebit_str = g_strdup_printf (_ ("Tot %s"), string);
478 }
479
480 if (info->tdebit_str)
481 return info->tdebit_str;
482
483 info->tdebit_str = g_strdup (_ ("Tot Debit"));
484
485 return info->tdebit_str;
486}
487
488static const char*
489gnc_split_register_get_tshares_label (VirtualLocation virt_loc,
490 gpointer user_data)
491{
492 SplitRegister* reg = user_data;
493
494 if (reg->is_template)
495 return "";
496
497 return _ ("Tot Shares");
498}
499
500static const char*
501gnc_split_register_get_tbalance_label (VirtualLocation virt_loc,
502 gpointer user_data)
503{
504 SplitRegister* reg = user_data;
505
506 if (reg->is_template)
507 return "";
508
509 return _ ("Balance");
510}
511
512static const char*
513gnc_split_register_get_notes_label (VirtualLocation virt_loc,
514 gpointer user_data)
515{
516 return _ ("Notes");
517}
518
519static const char*
520gnc_split_register_get_fdebit_label (VirtualLocation virt_loc,
521 gpointer user_data)
522{
523 return _ ("Debit Formula");
524}
525
526static const char*
527gnc_split_register_get_fcredit_label (VirtualLocation virt_loc,
528 gpointer user_data)
529{
530 return _ ("Credit Formula");
531}
532
533
534
535static char*
536gnc_split_register_get_recn_tooltip (VirtualLocation virt_loc,
537 gpointer user_data)
538{
539 SplitRegister* reg = user_data;
540 Split* split;
541
542 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
543 if (!split)
544 return NULL;
545
546 if (xaccSplitGetReconcile (split) == YREC)
547 {
548 char datebuff[MAX_DATE_LENGTH + 1];
549 time64 time = xaccSplitGetDateReconciled (split);
550 memset (datebuff, 0, sizeof (datebuff));
551 qof_print_date_buff (datebuff, MAX_DATE_LENGTH, time);
552 return g_strdup_printf (_ ("Reconciled on %s"), datebuff);
553 }
554 else if (xaccSplitGetReconcile (split) == VREC)
555 {
556 Transaction* trans = xaccSplitGetParent (split);
557 return g_strdup (xaccTransGetVoidReason (trans));
558 }
559 else
560 return NULL;
561}
562
563static char*
564gnc_split_register_get_doclink_tooltip (VirtualLocation virt_loc,
565 gpointer user_data)
566{
567 SplitRegister* reg = user_data;
568 Transaction* trans;
569 const char* uri;
570
571 trans = gnc_split_register_get_trans (reg, virt_loc.vcell_loc);
572 if (!trans)
573 return NULL;
574
575 // get the existing uri
576 uri = xaccTransGetDocLink (trans);
577
578 // Check for uri is empty or NULL
579 if (uri && *uri)
580 return gnc_doclink_get_unescaped_just_uri (uri);
581 else
582 return NULL;
583}
584
585static gnc_numeric
586get_trans_total_amount (SplitRegister* reg, Transaction* trans)
587{
588 Account* account = gnc_split_register_get_default_account (reg);
589 return xaccTransGetAccountAmount (trans, account);
590}
591
592static gnc_numeric
593get_trans_total_balance (SplitRegister* reg, Transaction* trans)
594{
595 Account* account;
596
597 account = gnc_split_register_get_default_account (reg);
598 if (!trans || !account) return gnc_numeric_zero();
599
600 return xaccTransGetAccountBalance (trans, account);
601}
602
603static gboolean
604gnc_split_register_use_negative_color (VirtualLocation virt_loc,
605 SplitRegister* reg)
606{
607 const char* cell_name;
608 gnc_numeric value = gnc_numeric_zero();
609 Split* split;
610
611 if (!use_red_for_negative)
612 return FALSE;
613
614 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
615 if (!split)
616 return FALSE;
617
618 cell_name = gnc_table_get_cell_name (reg->table, virt_loc);
619
620 if (gnc_cell_name_equal (cell_name, TSHRS_CELL))
621 value = get_trans_total_amount (reg, xaccSplitGetParent (split));
622 else if (gnc_cell_name_equal (cell_name, SHRS_CELL))
623 {
624 if (virt_cell_loc_equal (reg->table->current_cursor_loc.vcell_loc,
625 virt_loc.vcell_loc))
627 ((PriceCell*) gnc_table_layout_get_cell (reg->table->layout,
628 SHRS_CELL));
629 else
630 value = xaccSplitGetAmount (split);
631 }
632 else if (gnc_cell_name_equal (cell_name, BALN_CELL))
633 value = xaccSplitGetBalance (split);
634 else if (gnc_cell_name_equal (cell_name, RBALN_CELL))
635 value = gnc_split_register_get_rbaln (virt_loc, reg, TRUE);
636 else if (gnc_cell_name_equal (cell_name, TBALN_CELL))
637 value = get_trans_total_balance (reg, xaccSplitGetParent (split));
638
639 if ((gnc_cell_name_equal (cell_name, BALN_CELL)) ||
640 (gnc_cell_name_equal (cell_name, RBALN_CELL)) ||
641 (gnc_cell_name_equal (cell_name, TBALN_CELL)))
642 {
643 Account* account = xaccSplitGetAccount (split);
644 if (gnc_reverse_balance (account))
645 value = gnc_numeric_neg (value);
646 }
647
648 if (gnc_numeric_negative_p (value))
649 return TRUE;
650
651 return FALSE;
652}
653
654static guint32
655gnc_split_register_get_cell_color_internal (VirtualLocation virt_loc,
656 SplitRegister* reg)
657{
658 const char* cursor_name;
659 VirtualCell* vcell;
660 gboolean is_current;
661 guint32 colorbase = 0;
662
663 /* a bit of enum arithmetic */
664
665 if (gnc_split_register_use_negative_color (virt_loc, reg))
666 colorbase = COLOR_NEGATIVE; // Requires Negative fg color
667
668 if (!reg)
669 return (colorbase + COLOR_UNDEFINED);
670
671 if (gnc_table_virtual_location_in_header (reg->table, virt_loc))
672 return (colorbase + COLOR_HEADER);
673
674 vcell = gnc_table_get_virtual_cell (reg->table, virt_loc.vcell_loc);
675 if (!vcell || !vcell->cellblock)
676 return (colorbase + COLOR_UNDEFINED);
677
678 if ((virt_loc.phys_col_offset < vcell->cellblock->start_col) ||
679 (virt_loc.phys_col_offset > vcell->cellblock->stop_col))
680 return (colorbase + COLOR_UNDEFINED);
681
682 is_current = virt_cell_loc_equal (reg->table->current_cursor_loc.vcell_loc,
683 virt_loc.vcell_loc);
684
685 cursor_name = vcell->cellblock->cursor_name;
686
687 if (g_strcmp0 (cursor_name, CURSOR_SINGLE_JOURNAL) == 0 ||
688 g_strcmp0 (cursor_name, CURSOR_SINGLE_LEDGER) == 0)
689 {
690 if (is_current)
691 return vcell->start_primary_color ?
692 (colorbase + COLOR_PRIMARY_ACTIVE) :
693 (colorbase + COLOR_SECONDARY_ACTIVE);
694
695 return vcell->start_primary_color ?
696 (colorbase + COLOR_PRIMARY) : (colorbase + COLOR_SECONDARY);
697 }
698
699 if (g_strcmp0 (cursor_name, CURSOR_DOUBLE_JOURNAL) == 0 ||
700 g_strcmp0 (cursor_name, CURSOR_DOUBLE_JOURNAL_NUM_ACTN) == 0 ||
701 g_strcmp0 (cursor_name, CURSOR_DOUBLE_LEDGER) == 0 ||
702 g_strcmp0 (cursor_name, CURSOR_DOUBLE_LEDGER_NUM_ACTN) == 0)
703 {
704 if (is_current)
705 {
706 if (reg->double_alt_color)
707 return vcell->start_primary_color ?
708 (colorbase + COLOR_PRIMARY_ACTIVE) :
709 (colorbase + COLOR_SECONDARY_ACTIVE);
710
711 return (virt_loc.phys_row_offset % 2 == 0) ?
712 (colorbase + COLOR_PRIMARY_ACTIVE) :
713 (colorbase + COLOR_SECONDARY_ACTIVE);
714 }
715
716 if (reg->double_alt_color)
717 return vcell->start_primary_color ?
718 (colorbase + COLOR_PRIMARY) :
719 (colorbase + COLOR_SECONDARY);
720
721 return (virt_loc.phys_row_offset % 2 == 0) ?
722 (colorbase + COLOR_PRIMARY) :
723 (colorbase + COLOR_SECONDARY);
724 }
725
726 if (g_strcmp0 (cursor_name, CURSOR_SPLIT) == 0)
727 {
728 if (is_current)
729 return (colorbase + COLOR_SPLIT_ACTIVE);
730
731 return (colorbase + COLOR_SPLIT);
732 }
733
734 PWARN ("Unexpected cursor: %s\n", cursor_name);
735
736 return (colorbase + COLOR_UNDEFINED);
737}
738
739// Get Color for non numeric cells, no hatching required
740static guint32
741gnc_split_register_get_cell_color (VirtualLocation virt_loc,
742 gboolean* hatching,
743 gpointer user_data)
744{
745 SplitRegister* reg = user_data;
746
747 if (hatching)
748 *hatching = FALSE;
749
750 return gnc_split_register_get_cell_color_internal (virt_loc, reg);
751}
752
753// Get Color for numeric cells, update hatching
754static guint32
755gnc_split_register_get_debcred_color (VirtualLocation virt_loc,
756 gboolean* hatching,
757 gpointer user_data)
758{
759 SplitRegister* reg = user_data;
760
761 if (hatching)
762 {
763 Transaction* trans;
764
765 trans = gnc_split_register_get_trans (reg, virt_loc.vcell_loc);
766
767 if (trans)
768 *hatching = !xaccTransIsBalanced (trans);
769 else
770 *hatching = FALSE;
771 }
772 return gnc_split_register_get_cell_color_internal (virt_loc, reg);
773}
774
775static void
776gnc_split_register_get_border (VirtualLocation virt_loc,
777 PhysicalCellBorders* borders,
778 gpointer user_data)
779{
780 SplitRegister* reg = user_data;
781 CursorClass cursor_class;
782 VirtualCell* vcell;
783
784 vcell = gnc_table_get_virtual_cell (reg->table, virt_loc.vcell_loc);
785 if (!vcell || !vcell->cellblock)
786 return;
787
788 if (virt_loc.phys_col_offset < vcell->cellblock->start_col ||
789 virt_loc.phys_col_offset > vcell->cellblock->stop_col)
790 {
791 borders->top = CELL_BORDER_LINE_NONE;
792 borders->bottom = CELL_BORDER_LINE_NONE;
793 borders->left = CELL_BORDER_LINE_NONE;
794 borders->right = CELL_BORDER_LINE_NONE;
795 return;
796 }
797
798 cursor_class =
799 gnc_split_register_cursor_name_to_class (vcell->cellblock->cursor_name);
800
801 if (cursor_class == CURSOR_CLASS_SPLIT)
802 {
803 borders->top = CELL_BORDER_LINE_LIGHT;
804 borders->bottom = CELL_BORDER_LINE_LIGHT;
805 borders->left = MIN (borders->left, CELL_BORDER_LINE_LIGHT);
806 borders->right = MIN (borders->right, CELL_BORDER_LINE_LIGHT);
807
808 if (virt_loc.phys_col_offset == vcell->cellblock->start_col)
809 borders->left = CELL_BORDER_LINE_NORMAL;
810 if (virt_loc.phys_col_offset == vcell->cellblock->stop_col)
811 borders->right = CELL_BORDER_LINE_NORMAL;
812 }
813}
814
815static const char*
816gnc_split_register_get_doclink_entry (VirtualLocation virt_loc,
817 gboolean translate,
818 gboolean* conditionally_changed,
819 gpointer user_data)
820{
821 SplitRegister* reg = user_data;
822 Transaction* trans;
823 char link_flag;
824 const char* uri;
825 Doclinkcell *cell;
826
827 cell = (Doclinkcell *)gnc_table_layout_get_cell (reg->table->layout, DOCLINK_CELL);
828
829 if (!cell)
830 return NULL;
831
832 trans = gnc_split_register_get_trans (reg, virt_loc.vcell_loc);
833 if (!trans)
834 return NULL;
835
836 // get the existing uri
837 uri = xaccTransGetDocLink (trans);
838
839 // Check for uri is empty or NULL
840 if (uri && *uri)
841 {
842 gchar* scheme = gnc_uri_get_scheme (uri);
843
844 if (!scheme || g_strcmp0 (scheme, "file") == 0)
845 link_flag = FLINK;
846 else
847 link_flag = WLINK;
848
849 g_free (scheme);
850 }
851 else
852 link_flag = ' ';
853
854 if (gnc_doclink_get_use_glyphs (cell))
855 return gnc_doclink_get_glyph_from_flag (link_flag);
856
857 if (translate)
858 return gnc_get_doclink_str (link_flag);
859 else
860 {
861 static char s[2];
862
863 s[0] = link_flag;
864 s[1] = '\0';
865 return s;
866 }
867}
868
869static char *
870gnc_split_register_get_doclink_help (VirtualLocation virt_loc,
871 gpointer user_data)
872{
873 // do not want contents displayed as help so return space
874 return g_strdup (" ");
875}
876
877#if 0
878// this code is not used yet
879static char
880gnc_split_register_get_doclink_value (SplitRegister* reg,
881 VirtualLocation virt_loc)
882{
883 Doclinkcell *cell;
884
885 cell = (Doclinkcell *)gnc_table_layout_get_cell (reg->table->layout, DOCLINK_CELL);
886 if (!cell)
887 return '\0';
888
889 return gnc_doclink_cell_get_flag (cell);
890}
891#endif
892
893static const char*
894gnc_split_register_get_type_entry (VirtualLocation virt_loc,
895 gboolean translate,
896 gboolean* conditionally_changed,
897 gpointer user_data)
898{
899 SplitRegister* reg = user_data;
900 Transaction* trans;
901 char type;
902 static char s[2];
903
904 trans = gnc_split_register_get_trans (reg, virt_loc.vcell_loc);
905 if (!trans)
906 return NULL;
907
908 type = xaccTransGetTxnType (trans);
909
910 if (type == TXN_TYPE_NONE)
911 type = '?';
912
913 s[0] = type;
914 s[1] = '\0';
915
916 return s;
917}
918
919static char
920gnc_split_register_get_type_value (SplitRegister* reg,
921 VirtualLocation virt_loc)
922{
923 RecnCell* cell;
924
925 cell = (RecnCell*)gnc_table_layout_get_cell (reg->table->layout, TYPE_CELL);
926 if (!cell)
927 return '\0';
928
929 return gnc_recn_cell_get_flag (cell);
930}
931
932static const char*
933gnc_split_register_get_due_date_entry (VirtualLocation virt_loc,
934 gboolean translate,
935 gboolean* conditionally_changed,
936 gpointer user_data)
937{
938 SplitRegister* reg = user_data;
939 Transaction* trans;
940 Split* split;
941 gboolean is_current;
942 char type;
943 static gchar dateBuff [MAX_DATE_LENGTH+1];
944
945 is_current = virt_cell_loc_equal (reg->table->current_cursor_loc.vcell_loc,
946 virt_loc.vcell_loc);
947
948 if (is_current)
949 {
950 type = gnc_split_register_get_type_value (reg, virt_loc);
951 }
952 else
953 {
954 const char* typestr =
955 gnc_split_register_get_type_entry (virt_loc, translate,
956 conditionally_changed, user_data);
957 if (typestr != NULL)
958 type = *typestr;
959 else
960 type = '\0';
961 }
962
963 /* Only print the due date for invoice transactions */
964 if (type != TXN_TYPE_INVOICE)
965 {
966 //PWARN ("returning NULL due_date entry");
967 return NULL;
968 }
969
970 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
971 trans = xaccSplitGetParent (split);
972 if (!trans)
973 {
974 //PWARN ("No transaction in due_date entry");
975 return NULL;
976 }
977
978 //PWARN ("returning valid due_date entry");
979
980 memset (dateBuff, 0, sizeof (dateBuff));
982 return dateBuff;
983}
984
985static const char*
986gnc_split_register_get_date_entry (VirtualLocation virt_loc,
987 gboolean translate,
988 gboolean* conditionally_changed,
989 gpointer user_data)
990{
991 SplitRegister* reg = user_data;
992 Transaction* trans;
993 Split* split;
994 static gchar dateBuff [MAX_DATE_LENGTH+1];
995
996 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
997 trans = xaccSplitGetParent (split);
998 if (!trans)
999 return NULL;
1000
1001 memset (dateBuff, 0, sizeof (dateBuff));
1003 return dateBuff;
1004}
1005
1006static char*
1007gnc_split_register_get_date_help (VirtualLocation virt_loc,
1008 gpointer user_data)
1009{
1010 SplitRegister* reg = user_data;
1011 BasicCell* cell;
1012 time64 cell_time;
1013
1014 cell = gnc_table_get_cell (reg->table, virt_loc);
1015 if (!cell || !cell->value || *cell->value == '\0')
1016 return NULL;
1017
1018 gnc_date_cell_get_date ((DateCell*) cell, &cell_time, FALSE);
1019
1020 /* Translators: This is a date format, see i.e.
1021 https://www.gnu.org/software/libc/manual/html_node/Formatting-Calendar-Time.html */
1022 return gnc_print_time64 (cell_time, _("%A %d %B %Y"));
1023}
1024
1025static const char*
1026gnc_split_register_get_inactive_date_entry (VirtualLocation virt_loc,
1027 gboolean translate,
1028 gboolean* conditionally_changed,
1029 gpointer user_data)
1030{
1031 /* This seems to be the one that initially gets used, the InactiveDateCell
1032 is set to, and subsequently displayed. */
1033 return _ ("Scheduled");
1034}
1035
1036static const char*
1037gnc_split_register_get_num_entry (VirtualLocation virt_loc,
1038 gboolean translate,
1039 gboolean* conditionally_changed,
1040 gpointer user_data)
1041{
1042 SplitRegister* reg = user_data;
1043 Transaction* trans;
1044 Split* split;
1045
1046 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1047 trans = xaccSplitGetParent (split);
1048
1049 return gnc_get_num_action (trans, split);
1050}
1051
1052static const char*
1053gnc_split_register_get_tran_num_entry (VirtualLocation virt_loc,
1054 gboolean translate,
1055 gboolean* conditionally_changed,
1056 gpointer user_data)
1057{
1058 SplitRegister* reg = user_data;
1059 Transaction* trans;
1060 Split* split;
1061
1062 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1063 trans = xaccSplitGetParent (split);
1064
1065 return gnc_get_num_action (trans, NULL);
1066}
1067
1068static char*
1069gnc_split_register_get_num_help (VirtualLocation virt_loc,
1070 gpointer user_data)
1071{
1072 SplitRegister* reg = user_data;
1073 const char* help;
1074
1075 help = gnc_table_get_entry (reg->table, virt_loc);
1076 if (!help || *help == '\0')
1077 switch (reg->type)
1078 {
1079 case RECEIVABLE_REGISTER:
1080 case PAYABLE_REGISTER:
1081 help = reg->use_tran_num_for_num_field ?
1082 _ ("Enter a reference, such as an invoice or check number, "
1083 "common to all entry lines (splits)") :
1084 _ ("Enter a reference, such as an invoice or check number, "
1085 "unique to each entry line (split)");
1086 break;
1087 default:
1088 help = reg->use_tran_num_for_num_field ?
1089 _ ("Enter a reference, such as a check number, "
1090 "common to all entry lines (splits)") :
1091 _ ("Enter a reference, such as a check number, "
1092 "unique to each entry line (split)");
1093 break;
1094 }
1095
1096 return g_strdup (help);
1097}
1098
1099static char*
1100gnc_split_register_get_tran_num_help (VirtualLocation virt_loc,
1101 gpointer user_data)
1102{
1103 SplitRegister* reg = user_data;
1104 const char* help;
1105
1106 help = gnc_table_get_entry (reg->table, virt_loc);
1107 if (!help || *help == '\0')
1108 switch (reg->type)
1109 {
1110 case RECEIVABLE_REGISTER:
1111 case PAYABLE_REGISTER:
1112 help = _ ("Enter a transaction reference, such as an invoice "
1113 "or check number, common to all entry lines (splits)");
1114 break;
1115 default:
1116 help = _ ("Enter a transaction reference "
1117 "that will be common to all entry lines (splits)");
1118 break;
1119 }
1120
1121 return g_strdup (help);
1122}
1123
1124static const char*
1125gnc_split_register_get_desc_entry (VirtualLocation virt_loc,
1126 gboolean translate,
1127 gboolean* conditionally_changed,
1128 gpointer user_data)
1129{
1130 SplitRegister* reg = user_data;
1131 Transaction* trans;
1132 Split* split;
1133
1134 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1135 trans = xaccSplitGetParent (split);
1136
1137 return xaccTransGetDescription (trans);
1138}
1139
1140static char*
1141gnc_split_register_get_desc_help (VirtualLocation virt_loc,
1142 gpointer user_data)
1143{
1144 SplitRegister* reg = user_data;
1145 const char* help;
1146
1147 help = gnc_table_get_entry (reg->table, virt_loc);
1148 if (!help || *help == '\0')
1149 switch (reg->type)
1150 {
1151 case RECEIVABLE_REGISTER:
1152 help = _ ("Enter the name of the Customer");
1153 break;
1154 case PAYABLE_REGISTER:
1155 help = _ ("Enter the name of the Vendor");
1156 break;
1157 default:
1158 help = _ ("Enter a description of the transaction");
1159 break;
1160 }
1161 return g_strdup (help);
1162}
1163
1164static const char*
1165gnc_split_register_get_notes_entry (VirtualLocation virt_loc,
1166 gboolean translate,
1167 gboolean* conditionally_changed,
1168 gpointer user_data)
1169{
1170 SplitRegister* reg = user_data;
1171 Transaction* trans;
1172 Split* split;
1173
1174 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1175 trans = xaccSplitGetParent (split);
1176
1177 return xaccTransGetNotes (trans);
1178}
1179
1180static char*
1181gnc_split_register_get_notes_help (VirtualLocation virt_loc,
1182 gpointer user_data)
1183{
1184 SplitRegister* reg = user_data;
1185 const char* help;
1186
1187 help = gnc_table_get_entry (reg->table, virt_loc);
1188 if (!help || *help == '\0')
1189 help = _ ("Enter notes for the transaction");
1190
1191 return g_strdup (help);
1192}
1193
1194static const char*
1195gnc_split_register_get_vnotes_entry (VirtualLocation virt_loc,
1196 gboolean translate,
1197 gboolean* conditionally_changed,
1198 gpointer user_data)
1199{
1200 SplitRegister* reg = user_data;
1201 Transaction* trans;
1202 Split* split;
1203
1204 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1205 trans = xaccSplitGetParent (split);
1206
1207 if (trans == NULL)
1208 return NULL;
1209 else
1210 return xaccTransGetVoidReason (trans);
1211}
1212
1213static char*
1214gnc_split_register_get_vnotes_help (VirtualLocation virt_loc,
1215 gpointer user_data)
1216{
1217 SplitRegister* reg = user_data;
1218 const char* help;
1219
1220 help = gnc_table_get_entry (reg->table, virt_loc);
1221 if (!help || *help == '\0')
1222 help = _ ("Reason the transaction was voided");
1223
1224 return g_strdup (help);
1225}
1226
1227static const char*
1228gnc_split_register_get_rate_entry (VirtualLocation virt_loc,
1229 gboolean translate,
1230 gboolean* conditionally_changed,
1231 gpointer user_data)
1232{
1233 SplitRegister* reg = user_data;
1234 Split* split, *osplit;
1235 Transaction* txn;
1236 gnc_numeric amount, value, convrate;
1237 gnc_commodity* curr;
1238 SRInfo* info = gnc_split_register_get_info (reg);
1239
1240 if (info->rate_reset == RATE_RESET_REQD && info->auto_complete)
1241 return "0";
1242
1243 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1244 if (!split)
1245 return NULL;
1246
1247 /* If this is a basic, non-expanded ledger with exactly two splits,
1248 * and split->txn->curr == split->acc->comm, then use the OTHER
1249 * split for the rate.
1250 */
1251 osplit = xaccSplitGetOtherSplit (split);
1252 txn = gnc_split_register_get_trans (reg, virt_loc.vcell_loc);
1254 if (!gnc_split_register_current_trans_expanded (reg) && osplit &&
1255 !gnc_split_register_needs_conv_rate (reg, txn,
1256 xaccSplitGetAccount (split)))
1257 {
1258 split = osplit;
1259 }
1260
1261 amount = xaccSplitGetAmount (split);
1262 value = xaccSplitGetValue (split);
1263
1264 if (gnc_numeric_zero_p (value))
1265 return "0";
1266
1267 convrate = gnc_numeric_div (amount, value, GNC_DENOM_AUTO,
1268 GNC_HOW_DENOM_REDUCE);
1269
1270 return xaccPrintAmount (convrate, gnc_default_price_print_info (curr));
1271}
1272
1273static const char*
1274gnc_split_register_get_recn_entry (VirtualLocation virt_loc,
1275 gboolean translate,
1276 gboolean* conditionally_changed,
1277 gpointer user_data)
1278{
1279 SplitRegister* reg = user_data;
1280 Split* split;
1281
1282 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1283 if (!split)
1284 return NULL;
1285
1286 if (translate)
1287 return gnc_get_reconcile_str (xaccSplitGetReconcile (split));
1288 else
1289 {
1290 static char s[2];
1291
1292 s[0] = xaccSplitGetReconcile (split);
1293 s[1] = '\0';
1294
1295 return s;
1296 }
1297}
1298
1299static const char*
1300gnc_split_register_get_action_entry (VirtualLocation virt_loc,
1301 gboolean translate,
1302 gboolean* conditionally_changed,
1303 gpointer user_data)
1304{
1305 SplitRegister* reg = user_data;
1306 Split* split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1307
1308 return gnc_get_num_action (NULL, split);
1309}
1310
1311static char*
1312gnc_split_register_get_action_help (VirtualLocation virt_loc,
1313 gpointer user_data)
1314{
1315 SplitRegister* reg = user_data;
1316 const char* help;
1317
1318 help = gnc_table_get_entry (reg->table, virt_loc);
1319 if (!help || *help == '\0')
1320 help = reg->use_tran_num_for_num_field ?
1321 _ ("Enter an action type, or choose one from the list") :
1322 _ ("Enter a reference number, such as the next check number, or choose an action type from the list");
1323
1324 return g_strdup (help);
1325}
1326
1327static const char*
1328gnc_split_register_get_memo_entry (VirtualLocation virt_loc,
1329 gboolean translate,
1330 gboolean* conditionally_changed,
1331 gpointer user_data)
1332{
1333 SplitRegister* reg = user_data;
1334 Split* split;
1335
1336 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1337
1338 return xaccSplitGetMemo (split);
1339}
1340
1341static char*
1342gnc_split_register_get_memo_help (VirtualLocation virt_loc,
1343 gpointer user_data)
1344{
1345 SplitRegister* reg = user_data;
1346 const char* help;
1347
1348 help = gnc_table_get_entry (reg->table, virt_loc);
1349 if (!help || *help == '\0')
1350 help = _ ("Enter a description of the split");
1351 return g_strdup (help);
1352}
1353
1354static const char*
1355gnc_split_register_get_balance_entry (VirtualLocation virt_loc,
1356 gboolean translate,
1357 gboolean* conditionally_changed,
1358 gpointer user_data)
1359{
1360 SplitRegister* reg = user_data;
1361 SRInfo* info = gnc_split_register_get_info (reg);
1362 gnc_numeric balance;
1363 gboolean is_trans;
1364 Split* split;
1365 Account* account;
1366
1367 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1368 if (split == xaccSplitLookup (&info->blank_split_guid,
1369 gnc_get_current_book()))
1370 return NULL;
1371
1372 is_trans = gnc_cell_name_equal
1373 (gnc_table_get_cell_name (reg->table, virt_loc), TBALN_CELL);
1374
1375 if (is_trans)
1376 balance = get_trans_total_balance (reg, xaccSplitGetParent (split));
1377 else
1378 balance = xaccSplitGetBalance (split);
1379
1380 account = xaccSplitGetAccount (split);
1381 if (!account)
1382 account = gnc_split_register_get_default_account (reg);
1383
1384 if (gnc_reverse_balance (account))
1385 balance = gnc_numeric_neg (balance);
1386
1387 return xaccPrintAmount (balance, gnc_account_print_info (account,
1388 reg->mismatched_commodities));
1389}
1390
1391static const char*
1392gnc_split_register_get_price_entry (VirtualLocation virt_loc,
1393 gboolean translate,
1394 gboolean* conditionally_changed,
1395 gpointer user_data)
1396{
1397 SplitRegister* reg = user_data;
1398 gnc_numeric price;
1399 gnc_commodity* curr;
1400 Split* split;
1401
1402 if (!gnc_split_register_use_security_cells (reg, virt_loc))
1403 return NULL;
1404
1405 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1406
1407 price = xaccSplitGetSharePrice (split);
1409 if (gnc_numeric_zero_p (price))
1410 return NULL;
1411
1412 return xaccPrintAmount (price, gnc_default_price_print_info (curr));
1413}
1414
1415static char*
1416gnc_split_register_get_price_help (VirtualLocation virt_loc,
1417 gpointer user_data)
1418{
1419 SplitRegister* reg = user_data;
1420 const char* help;
1421
1422 help = gnc_table_get_entry (reg->table, virt_loc);
1423 if (!help || *help == '\0')
1424 help = _ ("Enter the effective share price");
1425
1426 return g_strdup (help);
1427}
1428
1429static const char*
1430gnc_split_register_get_shares_entry (VirtualLocation virt_loc,
1431 gboolean translate,
1432 gboolean* conditionally_changed,
1433 gpointer user_data)
1434{
1435 SplitRegister* reg = user_data;
1436 gnc_numeric shares;
1437 Split* split;
1438
1439 if (!gnc_split_register_use_security_cells (reg, virt_loc))
1440 return NULL;
1441
1442 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1443
1444 shares = xaccSplitGetAmount (split);
1445 if (gnc_numeric_zero_p (shares))
1446 return NULL;
1447
1448 return xaccPrintAmount (shares, gnc_split_amount_print_info (split, FALSE));
1449}
1450
1451static char*
1452gnc_split_register_get_shares_help (VirtualLocation virt_loc,
1453 gpointer user_data)
1454{
1455 SplitRegister* reg = user_data;
1456 const char* help;
1457
1458 help = gnc_table_get_entry (reg->table, virt_loc);
1459 if (!help || *help == '\0')
1460 help = _ ("Enter the number of shares bought or sold");
1461
1462 return g_strdup (help);
1463}
1464
1465static const char*
1466gnc_split_register_get_tshares_entry (VirtualLocation virt_loc,
1467 gboolean translate,
1468 gboolean* conditionally_changed,
1469 gpointer user_data)
1470{
1471 SplitRegister* reg = user_data;
1472 gnc_numeric total;
1473 Split* split;
1474
1475 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1476
1477 total = get_trans_total_amount (reg, xaccSplitGetParent (split));
1478
1479 return xaccPrintAmount (total, gnc_split_amount_print_info (split, FALSE));
1480}
1481
1482static const char*
1483gnc_split_register_get_xfrm_entry (VirtualLocation virt_loc,
1484 gboolean translate,
1485 gboolean* conditionally_changed,
1486 gpointer user_data)
1487{
1488 static char* name = NULL;
1489
1490 SplitRegister* reg = user_data;
1491 Split* split;
1492
1493 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1494
1495 g_free (name);
1496
1498 reg->show_leaf_accounts);
1499
1500 return name;
1501}
1502
1503static char*
1504gnc_split_register_get_xfrm_help (VirtualLocation virt_loc,
1505 gpointer user_data)
1506{
1507 SplitRegister* reg = user_data;
1508 const char* help;
1509
1510 help = gnc_table_get_entry (reg->table, virt_loc);
1511 if (!help || *help == '\0')
1512 help = _ ("Enter the account to transfer from, "
1513 "or choose one from the list");
1514
1515 return g_strdup (help);
1516}
1517
1518static const char*
1519gnc_split_register_get_mxfrm_entry (VirtualLocation virt_loc,
1520 gboolean translate,
1521 gboolean* conditionally_changed,
1522 gpointer user_data)
1523{
1524 static char* name = NULL;
1525
1526 SplitRegister* reg = user_data;
1527 Split* split;
1528 Split* s;
1529
1530 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1531 if (!split)
1532 return NULL;
1533
1534 s = xaccSplitGetOtherSplit (split);
1535
1536 g_free (name);
1537
1538 if (s)
1540 reg->show_leaf_accounts);
1541 else
1542 {
1543 /* For multi-split transactions and stock splits,
1544 * use a special value. */
1545 s = xaccTransGetSplit (xaccSplitGetParent (split), 1);
1546
1547 if (s)
1548 name = g_strdup (SPLIT_TRANS_STR);
1549 else if (xaccSplitIsStockSplit (split))
1550 name = g_strdup (STOCK_SPLIT_STR);
1551 else
1552 name = g_strdup ("");
1553 }
1554
1555 return name;
1556}
1557
1558static char*
1559gnc_split_register_get_mxfrm_help (VirtualLocation virt_loc,
1560 gpointer user_data)
1561{
1562 const char* help;
1563
1564 SplitRegister* reg = user_data;
1565 Split* split;
1566 Split* s;
1567
1568 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1569 if (!split)
1570 return NULL;
1571
1572 s = xaccSplitGetOtherSplit (split);
1573
1574 if (s)
1575 {
1576 help = gnc_split_register_get_mxfrm_entry (virt_loc, FALSE,
1577 NULL, user_data);
1578 if (!help || *help == '\0')
1579 help = _ ("Enter the account to transfer from, "
1580 "or choose one from the list");
1581 }
1582 else
1583 {
1584 /* For multi-split transactions and stock splits,
1585 * use a special value. */
1586 s = xaccTransGetSplit (xaccSplitGetParent (split), 1);
1587
1588 if (s)
1589 help = _ ("This transaction has multiple splits; "
1590 "press the Split button to see them all");
1591 else if (xaccSplitIsStockSplit (split))
1592 help = _ ("This transaction is a stock split; "
1593 "press the Split button to see details");
1594 else
1595 help = "";
1596 }
1597
1598 return g_strdup (help);
1599}
1600
1601/* Return the total value in the register currency of the transaction
1602 * for splits of default account and all subaccounts of the register.
1603 */
1604static gnc_numeric
1605get_trans_total_value_subaccounts (SplitRegister* reg, Transaction* trans)
1606{
1607 GList* children, *child;
1608 Account* parent;
1609 gnc_numeric total = gnc_numeric_zero();
1610
1611 /* Get a list of all subaccounts for matching */
1612 parent = gnc_split_register_get_default_account (reg);
1613 if (!parent)
1614 /* Register has no account, perhaps it's the general journal. If it
1615 has no account then we have no way of picking out the desired splits,
1616 return zero. */
1617 return total;
1618
1619 children = gnc_account_get_descendants (parent);
1620 children = g_list_prepend (children, parent);
1621
1622 for (child = children; child; child = child->next)
1623 {
1624 total = gnc_numeric_add_fixed (total, xaccTransGetAccountValue (trans,
1625 child->data));
1626 }
1627
1628 g_list_free (children);
1629
1630 return total;
1631}
1632
1633static const char*
1634gnc_split_register_get_tdebcred_entry (VirtualLocation virt_loc,
1635 gboolean translate,
1636 gboolean* conditionally_changed,
1637 gpointer user_data)
1638{
1639 SplitRegister* reg = user_data;
1640 const char* cell_name;
1641 gnc_numeric total;
1642 Split* split;
1643
1644 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1645 if (!split)
1646 return NULL;
1647
1648 cell_name = gnc_table_get_cell_name (reg->table, virt_loc);
1649
1650 switch (reg->type)
1651 {
1652 case GENERAL_JOURNAL:
1653 case INCOME_LEDGER:
1654 total = get_trans_total_value_subaccounts (reg, xaccSplitGetParent (split));
1655 break;
1656 default:
1657 total = get_trans_total_amount (reg, xaccSplitGetParent (split));
1658 break;
1659 }
1660
1661 if (gnc_numeric_zero_p (total))
1662 return NULL;
1663
1664 if (gnc_numeric_negative_p (total) &&
1665 gnc_cell_name_equal (cell_name, TDEBT_CELL))
1666 return NULL;
1667
1668 if (gnc_numeric_positive_p (total) &&
1669 gnc_cell_name_equal (cell_name, TCRED_CELL))
1670 return NULL;
1671
1672 total = gnc_numeric_abs (total);
1673
1674 return xaccPrintAmount (total, gnc_split_amount_print_info (split,
1675 reg->mismatched_commodities));
1676}
1677
1678/* return TRUE if we have a RATE_CELL; return FALSE if we do not.
1679 * (note: should match split-register-layout.c)
1680 */
1681gboolean
1683{
1684 switch (type)
1685 {
1686 case BANK_REGISTER:
1687 case CASH_REGISTER:
1688 case ASSET_REGISTER:
1689 case CREDIT_REGISTER:
1690 case LIABILITY_REGISTER:
1691 case INCOME_REGISTER:
1692 case EXPENSE_REGISTER:
1693 case EQUITY_REGISTER:
1694 case TRADING_REGISTER:
1695 case GENERAL_JOURNAL:
1696 case INCOME_LEDGER:
1697 case SEARCH_LEDGER:
1698 case RECEIVABLE_REGISTER:
1699 case PAYABLE_REGISTER:
1700 return TRUE;
1701
1702 case STOCK_REGISTER:
1703 case CURRENCY_REGISTER:
1704 case PORTFOLIO_LEDGER:
1705 default:
1706 return FALSE;
1707 }
1708}
1709
1710/* returns TRUE if you need to convert the split's value to the local
1711 * (account) display currency. Returns FALSE if you can just use the
1712 * split->value directly.
1713 */
1714gboolean
1715gnc_split_register_needs_conv_rate (SplitRegister* reg,
1716 Transaction* txn, Account* acc)
1717{
1718 gnc_commodity* txn_cur, *acc_com;
1719
1720 /* If there is not a RATE_CELL, then don't do anything */
1721 if (!gnc_split_reg_has_rate_cell (reg->type))
1722 return FALSE;
1723
1724 /* if txn->currency == acc->commodity, then return FALSE */
1725 acc_com = xaccAccountGetCommodity (acc);
1726 txn_cur = xaccTransGetCurrency (txn);
1727 if (txn_cur && acc_com && gnc_commodity_equal (txn_cur, acc_com))
1728 return FALSE;
1729
1730 return TRUE;
1731}
1732
1733static const char*
1734gnc_split_register_get_debcred_entry (VirtualLocation virt_loc,
1735 gboolean translate,
1736 gboolean* conditionally_changed,
1737 gpointer user_data)
1738{
1739 SplitRegister* reg = user_data;
1740 gboolean is_debit;
1741 Split* split;
1742 Transaction* trans;
1743 gnc_commodity* currency;
1744
1745 is_debit = gnc_cell_name_equal
1746 (gnc_table_get_cell_name (reg->table, virt_loc), DEBT_CELL);
1747
1748 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1749 trans = gnc_split_register_get_trans (reg, virt_loc.vcell_loc);
1750
1751 currency = xaccTransGetCurrency (trans);
1752 if (!currency)
1753 currency = gnc_default_currency();
1754
1755 if (!split)
1756 {
1757 gnc_numeric imbalance;
1758 Account* acc;
1759
1760 imbalance = xaccTransGetImbalanceValue (trans);
1761
1762 if (gnc_numeric_zero_p (imbalance))
1763 return NULL;
1764
1765 if (xaccTransUseTradingAccounts (trans))
1766 {
1767 MonetaryList* imbal_list;
1768 gnc_monetary* imbal_mon;
1769 imbal_list = xaccTransGetImbalance (trans);
1770
1771 if (!imbal_list)
1772 {
1773 /* No commodity imbalance, there shouldn't be a value imablance. */
1774 return NULL;
1775 }
1776
1777 if (imbal_list->next)
1778 {
1779 /* Multiple currency imbalance. */
1780 gnc_monetary_list_free (imbal_list);
1781 return NULL;
1782 }
1783
1784 imbal_mon = imbal_list->data;
1785 if (!gnc_commodity_equal (gnc_monetary_commodity (*imbal_mon), currency))
1786 {
1787 /* Imbalance is in wrong currency */
1788 gnc_monetary_list_free (imbal_list);
1789 return NULL;
1790 }
1791
1792 if (!gnc_numeric_equal (gnc_monetary_value (*imbal_mon), imbalance))
1793 {
1794 /* Value and commodity imbalances differ */
1795 gnc_monetary_list_free (imbal_list);
1796 return NULL;
1797 }
1798
1799 /* Done with the imbalance list */
1800 gnc_monetary_list_free (imbal_list);
1801 }
1802
1803 imbalance = gnc_numeric_neg (imbalance);
1804
1805 if (gnc_numeric_negative_p (imbalance) && is_debit)
1806 return NULL;
1807
1808 if (gnc_numeric_positive_p (imbalance) && !is_debit)
1809 return NULL;
1810
1811 if (conditionally_changed)
1812 *conditionally_changed = TRUE;
1813
1814 imbalance = gnc_numeric_abs (imbalance);
1815
1816 acc = gnc_split_register_get_default_account (reg);
1817 if (gnc_split_register_needs_conv_rate (reg, trans, acc))
1818 {
1819 imbalance = gnc_numeric_mul (imbalance,
1820 xaccTransGetAccountConvRate (trans, acc),
1821 gnc_commodity_get_fraction (currency),
1822 GNC_HOW_RND_ROUND_HALF_UP);
1823 }
1824 else
1825 {
1826 imbalance = gnc_numeric_convert (imbalance,
1827 gnc_commodity_get_fraction (currency),
1828 GNC_HOW_RND_ROUND_HALF_UP);
1829 }
1830
1831 return xaccPrintAmount (imbalance, gnc_account_print_info (acc,
1832 reg->mismatched_commodities));
1833 }
1834
1835 {
1836 gnc_numeric amount;
1837 gnc_commodity* split_commodity;
1838 GNCPrintAmountInfo print_info;
1839 Account* account;
1840 gnc_commodity* commodity;
1841
1842 account = gnc_split_register_get_default_account (reg);
1843 commodity = xaccAccountGetCommodity (account);
1844 split_commodity = xaccAccountGetCommodity (xaccSplitGetAccount (split));
1845
1846 if (xaccTransUseTradingAccounts (trans))
1847 {
1848 gboolean use_symbol, is_current;
1849 is_current = virt_cell_loc_equal (reg->table->current_cursor_loc.vcell_loc,
1850 virt_loc.vcell_loc);
1851
1852 if (reg->type == STOCK_REGISTER ||
1853 reg->type == CURRENCY_REGISTER ||
1854 reg->type == PORTFOLIO_LEDGER)
1855 {
1856 gnc_commodity* amount_commodity;
1857 /* security register. If this split has price and shares columns,
1858 use the value, otherwise use the amount. */
1859 if (gnc_split_register_use_security_cells (reg, virt_loc))
1860 {
1861 amount = xaccSplitGetValue (split);
1862 amount_commodity = currency;
1863 }
1864 else
1865 {
1866 amount = xaccSplitGetAmount (split);
1867 amount_commodity = split_commodity;
1868 }
1869 /* Show the currency if it is not the default currency */
1870 if (is_current ||
1871 gnc_commodity_equiv (amount_commodity, gnc_default_currency()))
1872 use_symbol = FALSE;
1873 else
1874 use_symbol = TRUE;
1875 print_info = gnc_commodity_print_info (amount_commodity, use_symbol);
1876 }
1877 else
1878 {
1879 /* non-security register, always use the split amount. */
1880 amount = xaccSplitGetAmount (split);
1881 if (is_current ||
1882 gnc_commodity_equiv (split_commodity, commodity))
1883 use_symbol = FALSE;
1884 else
1885 use_symbol = TRUE;
1886 print_info = gnc_commodity_print_info (split_commodity, use_symbol);
1887 }
1888 }
1889 else
1890 {
1891 switch (reg->type)
1892 {
1893 case STOCK_REGISTER:
1894 case CURRENCY_REGISTER:
1895 case PORTFOLIO_LEDGER:
1896 amount = xaccSplitGetValue (split);
1897 print_info = gnc_commodity_print_info (currency, reg->mismatched_commodities);
1898 break;
1899
1900 /* If the register is not a stock/fund register that
1901 * displays both amount and value, display the split value
1902 * in the register's currency instead of the transaction's
1903 * currency. Note that we don't want the split amount as
1904 * some splits will be in a different currency.
1905 */
1906 default:
1907 if (commodity && !gnc_commodity_equal (commodity, currency))
1908 /* Convert this to the "local" value */
1909 amount = xaccSplitConvertAmount(split, account);
1910 else
1911 amount = xaccSplitGetValue (split);
1912
1913 print_info = gnc_account_print_info (account, reg->mismatched_commodities);
1914 print_info.commodity = commodity;
1915 break;
1916 }
1917 }
1918
1919 if (gnc_numeric_zero_p (amount))
1920 return NULL;
1921
1922 if (gnc_numeric_negative_p (amount) && is_debit)
1923 return NULL;
1924
1925 if (gnc_numeric_positive_p (amount) && !is_debit)
1926 return NULL;
1927
1928 amount = gnc_numeric_abs (amount);
1929
1930 return xaccPrintAmount (amount, print_info);
1931 }
1932}
1933
1934/* Calculates the register balance for each split at runtime.
1935 * This works regardless of the sort order. */
1936static const char*
1937gnc_split_register_get_rbaln_entry (VirtualLocation virt_loc,
1938 gboolean translate,
1939 gboolean* conditionally_changed,
1940 gpointer user_data)
1941{
1942 SplitRegister* reg = user_data;
1943 SRInfo* info = gnc_split_register_get_info (reg);
1944 Split* split;
1945 Transaction* trans;
1946 gnc_numeric balance;
1947 Account* account;
1948
1949 /* Return NULL if this is a blank transaction. */
1950 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1951 if (split == xaccSplitLookup (&info->blank_split_guid,
1952 gnc_get_current_book()))
1953 return NULL;
1954
1955 trans = xaccSplitGetParent (split);
1956 if (!trans)
1957 return NULL;
1958
1959 balance = gnc_split_register_get_rbaln (virt_loc, user_data, TRUE);
1960
1961 account = xaccSplitGetAccount (split);
1962 if (!account)
1963 account = gnc_split_register_get_default_account (reg);
1964
1965 if (gnc_reverse_balance (account))
1966 balance = gnc_numeric_neg (balance);
1967
1968 return xaccPrintAmount (balance, gnc_account_print_info (account, FALSE));
1969}
1970
1971static gboolean
1972gnc_split_register_cursor_is_readonly (VirtualLocation virt_loc,
1973 gpointer user_data)
1974{
1975 SplitRegister* reg = user_data;
1976 Split* split;
1977 Transaction* txn;
1978 char type;
1979
1980 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
1981
1982 if (!split) // this could be the blank split
1983 {
1985
1986 if (txn) // get the current trans and see if read_only required
1987 {
1988 if (xaccTransGetReadOnly (txn)
1990 return (TRUE);
1991 }
1992 return FALSE;
1993 }
1994
1995 txn = xaccSplitGetParent (split);
1996 if (!txn) return FALSE;
1997
1998 if (xaccTransGetReadOnly (txn)
2000 return (TRUE);
2001
2002 type = xaccTransGetTxnType (txn);
2003 return (type == TXN_TYPE_INVOICE);
2004}
2005
2006static CellIOFlags
2007gnc_split_register_get_inactive_io_flags (VirtualLocation virt_loc,
2008 gpointer user_data)
2009{
2010 if (gnc_split_register_cursor_is_readonly (virt_loc, user_data))
2011 return XACC_CELL_ALLOW_READ_ONLY;
2012
2013 return XACC_CELL_ALLOW_NONE;
2014}
2015
2016static CellIOFlags
2017gnc_split_register_get_standard_io_flags (VirtualLocation virt_loc,
2018 gpointer user_data)
2019{
2020 if (gnc_split_register_cursor_is_readonly (virt_loc, user_data))
2021 return XACC_CELL_ALLOW_READ_ONLY;
2022
2023 return XACC_CELL_ALLOW_ALL;
2024}
2025
2026static CellIOFlags
2027gnc_split_register_get_recn_io_flags (VirtualLocation virt_loc,
2028 gpointer user_data)
2029{
2030 if (gnc_split_register_cursor_is_readonly (virt_loc, user_data))
2031 return XACC_CELL_ALLOW_READ_ONLY;
2032
2033 return XACC_CELL_ALLOW_ALL | XACC_CELL_ALLOW_EXACT_ONLY;
2034}
2035
2036static CellIOFlags
2037gnc_split_register_get_doclink_io_flags (VirtualLocation virt_loc,
2038 gpointer user_data)
2039{
2040 if (gnc_split_register_cursor_is_readonly (virt_loc, user_data))
2041 return XACC_CELL_ALLOW_READ_ONLY;
2042
2043 return XACC_CELL_ALLOW_ALL | XACC_CELL_ALLOW_EXACT_ONLY;
2044}
2045
2046static CellIOFlags
2047gnc_split_register_get_ddue_io_flags (VirtualLocation virt_loc,
2048 gpointer user_data)
2049{
2050 SplitRegister* reg = user_data;
2051 char type;
2052
2053 type = gnc_split_register_get_type_value (reg, virt_loc);
2054
2055 /* Only print the due date for invoice transactions */
2056 if (type != TXN_TYPE_INVOICE)
2057 {
2058 return XACC_CELL_ALLOW_NONE;
2059 }
2060
2061 return XACC_CELL_ALLOW_READ_ONLY;
2062}
2063
2064static CellIOFlags
2065gnc_split_register_get_rate_io_flags (VirtualLocation virt_loc,
2066 gpointer user_data)
2067{
2068 return XACC_CELL_ALLOW_SHADOW;
2069}
2070
2071static CellIOFlags
2072gnc_split_register_get_debcred_io_flags (VirtualLocation virt_loc,
2073 gpointer user_data)
2074{
2075 SplitRegister* reg = user_data;
2076 Split* split;
2077
2078 if (gnc_split_register_cursor_is_readonly (virt_loc, user_data))
2079 return XACC_CELL_ALLOW_READ_ONLY;
2080
2081 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
2082
2083 if (xaccSplitIsStockSplit (split))
2084 return XACC_CELL_ALLOW_NONE;
2085
2086 return XACC_CELL_ALLOW_ALL;
2087}
2088
2089static CellIOFlags
2090gnc_split_register_get_security_io_flags (VirtualLocation virt_loc,
2091 gpointer user_data)
2092{
2093 SplitRegister* reg = user_data;
2094
2095 if (gnc_split_register_cursor_is_readonly (virt_loc, user_data))
2096 return XACC_CELL_ALLOW_READ_ONLY;
2097
2098 if (gnc_split_register_use_security_cells (reg, virt_loc))
2099 return XACC_CELL_ALLOW_ALL;
2100
2101 return XACC_CELL_ALLOW_SHADOW;
2102}
2103
2104static gboolean
2105xaccTransWarnReadOnly (GtkWidget* parent, Transaction* trans)
2106{
2107 GtkWidget* dialog;
2108 const gchar* reason;
2109 const gchar* format =
2110 _ ("Cannot modify or delete this transaction. This transaction is "
2111 "marked read-only because:\n\n'%s'");
2112
2113 if (!trans) return FALSE;
2114
2115 reason = xaccTransGetReadOnly (trans);
2116 if (reason)
2117 {
2118 dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
2119 0,
2120 GTK_MESSAGE_ERROR,
2121 GTK_BUTTONS_OK,
2122 format,
2123 reason);
2124 gtk_dialog_run (GTK_DIALOG (dialog));
2125 gtk_widget_destroy (dialog);
2126 return TRUE;
2127 }
2128 return FALSE;
2129}
2130
2131static gboolean reg_trans_has_reconciled_splits (SplitRegister* reg,
2132 Transaction* trans)
2133{
2134 GList* node;
2135
2136 for (node = xaccTransGetSplitList (trans); node; node = node->next)
2137 {
2138 Split* split = node->data;
2139
2140 if (!xaccTransStillHasSplit (trans, split))
2141 continue;
2142
2143 if ((xaccSplitGetReconcile (split) == YREC) &&
2144 (g_list_index (reg->unrecn_splits, split) == -1))
2145 return TRUE;
2146 }
2147
2148 return FALSE;
2149}
2150
2151static gboolean
2152gnc_split_register_confirm (VirtualLocation virt_loc, gpointer user_data)
2153{
2154 SplitRegister* reg = user_data;
2155 SRInfo* info = gnc_split_register_get_info (reg);
2156 Transaction* trans;
2157 Split* split;
2158 char recn;
2159 const char* cell_name;
2160 gboolean protected_split_cell, protected_trans_cell;
2161 const gchar* title = NULL;
2162 const gchar* message = NULL;
2163
2164 /* This assumes we reset the flag whenever we change splits.
2165 * This happens in gnc_split_register_move_cursor(). */
2166 if (info->change_confirmed)
2167 return TRUE;
2168
2169 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
2170 if (!split)
2171 return TRUE;
2172
2173 trans = xaccSplitGetParent (split);
2174 if (xaccTransWarnReadOnly (gnc_split_register_get_parent (reg), trans))
2175 return FALSE;
2176
2177 if (!reg_trans_has_reconciled_splits (reg, trans))
2178 return TRUE;
2179
2180 if (gnc_table_layout_get_cell_changed (reg->table->layout, RECN_CELL, FALSE))
2181 recn = gnc_recn_cell_get_flag
2182 ((RecnCell*) gnc_table_layout_get_cell (reg->table->layout, RECN_CELL));
2183 else if (g_list_index (reg->unrecn_splits, split) != -1)
2184 recn = NREC; /* A previous run of this function marked this split for unreconciling */
2185 else
2186 recn = xaccSplitGetReconcile (split);
2187
2188 /* What Cell are we in */
2189 cell_name = gnc_table_get_cell_name (reg->table, virt_loc);
2190
2191 /* if we change a transfer cell, we want the other split */
2192 if (g_strcmp0 (cell_name, "transfer") == 0)
2194
2195 /* These cells can not be changed */
2196 protected_split_cell = (g_strcmp0 (cell_name, "account") == 0) ||
2197 (g_strcmp0 (cell_name, "transfer") == 0) ||
2198 (g_strcmp0 (cell_name, "debit") == 0) ||
2199 (g_strcmp0 (cell_name, "credit") == 0);
2200 protected_trans_cell = (g_strcmp0 (cell_name, "date") == 0) ||
2201 (g_strcmp0 (cell_name, "num") == 0) ||
2202 (g_strcmp0 (cell_name, "description") == 0);
2203
2204 PINFO ("Protected transaction cell %d, Protected split cell %d, Cell is %s",
2205 protected_trans_cell, protected_split_cell, cell_name);
2206
2207 if (protected_trans_cell)
2208 {
2209 GList* acc_g_list = NULL;
2210 gchar* acc_list = NULL;
2211 gchar* message_format;
2212
2213 for (GList *node = xaccTransGetSplitList (trans); node; node = node->next)
2214 {
2215 Split* split = node->data;
2216
2217 if (!xaccTransStillHasSplit (trans, split))
2218 continue;
2219
2220 if (xaccSplitGetReconcile (split) == YREC)
2221 {
2222 gchar* name = gnc_account_get_full_name (xaccSplitGetAccount (split));
2223 acc_g_list = g_list_prepend (acc_g_list, name);
2224 }
2225 }
2226 acc_list = gnc_g_list_stringjoin (acc_g_list, "\n");
2227 title = _ ("Change transaction containing a reconciled split?");
2228 message_format =
2229 _ ("The transaction you are about to change contains reconciled splits in the following accounts:\n%s"
2230 "\n\nAre you sure you want to continue with this change?");
2231
2232 message = g_strdup_printf (message_format, acc_list);
2233 g_list_free_full (acc_g_list, g_free);
2234 g_free (acc_list);
2235 }
2236
2237 if (protected_split_cell)
2238 {
2239 title = _ ("Change reconciled split?");
2240 message =
2241 _ ("You are about to change a protected field of a reconciled split. "
2242 "If you continue editing this split it will be unreconciled. "
2243 "This might make future reconciliation difficult! Continue with this change?");
2244 }
2245
2246 if ((recn == YREC && protected_split_cell) || protected_trans_cell)
2247 {
2248 GtkWidget* dialog, *window;
2249 gint response;
2250
2251 /* Does the user want to be warned? */
2252 window = gnc_split_register_get_parent (reg);
2253 dialog =
2254 gtk_message_dialog_new (GTK_WINDOW (window),
2255 GTK_DIALOG_DESTROY_WITH_PARENT,
2256 GTK_MESSAGE_WARNING,
2257 GTK_BUTTONS_CANCEL,
2258 "%s", title);
2259 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
2260 "%s", message);
2261
2262 if (protected_split_cell)
2263 gtk_dialog_add_button (GTK_DIALOG (dialog), _ ("Chan_ge Split"),
2264 GTK_RESPONSE_YES);
2265 else
2266 gtk_dialog_add_button (GTK_DIALOG (dialog), _ ("Chan_ge Transaction"),
2267 GTK_RESPONSE_YES);
2268 response = gnc_dialog_run (GTK_DIALOG (dialog),
2269 GNC_PREF_WARN_REG_RECD_SPLIT_MOD);
2270 gtk_widget_destroy (dialog);
2271 if (response != GTK_RESPONSE_YES)
2272 return FALSE;
2273
2274 // Response is Change, so record the splits
2275 if (recn == YREC && protected_split_cell)
2276 {
2277 if (g_list_index (reg->unrecn_splits, split) == -1)
2278 {
2279 reg->unrecn_splits = g_list_append (reg->unrecn_splits, split);
2280 gnc_recn_cell_set_flag
2281 ((RecnCell*) gnc_table_layout_get_cell (reg->table->layout, RECN_CELL),
2282 NREC);
2283 }
2284 }
2285
2286 PINFO ("Unreconcile split list length is %d",
2287 g_list_length (reg->unrecn_splits));
2288 info->change_confirmed = TRUE;
2289 }
2290 return TRUE;
2291}
2292
2293static gpointer
2294gnc_split_register_guid_malloc (void)
2295{
2296 GncGUID* guid;
2297
2298 guid = guid_malloc();
2299
2300 *guid = *guid_null();
2301
2302 return guid;
2303}
2304
2305static const char*
2306gnc_template_register_get_xfrm_entry (VirtualLocation virt_loc,
2307 gboolean translate,
2308 gboolean* conditionally_changed,
2309 gpointer user_data)
2310{
2311 static char* name = NULL;
2312
2313 SplitRegister* reg = user_data;
2314 Split* split;
2315 Account* account;
2316 GncGUID* guid = NULL;
2317
2318 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
2319 if (!split)
2320 return NULL;
2321 /* Caller either uses the return as a temporary in a boolean
2322 * expression or g_strdups it, so we keep it static and free the
2323 * old one on every call to avoid leaks. Ugly, but it works.
2324 */
2325 g_free (name);
2326 qof_instance_get (QOF_INSTANCE (split),
2327 "sx-account", &guid,
2328 NULL);
2329 account = xaccAccountLookup (guid, gnc_get_current_book());
2330 name = account ? gnc_get_account_name_for_split_register (account,
2331 reg->show_leaf_accounts) : NULL;
2332 guid_free (guid);
2333 return name;
2334}
2335
2336static const char*
2337gnc_template_register_get_fdebt_entry (VirtualLocation virt_loc,
2338 gboolean translate,
2339 gboolean* conditionally_changed,
2340 gpointer user_data)
2341{
2342 SplitRegister* reg = user_data;
2343 Split* split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
2344 static char* formula = NULL;
2345
2346 g_free (formula);
2347 formula = NULL;
2348 if (split)
2349 {
2350 qof_instance_get (QOF_INSTANCE (split),
2351 "sx-debit-formula", &formula,
2352 NULL);
2353 }
2354
2355 return formula;
2356}
2357
2358static char*
2359gnc_split_register_get_fdebt_help (VirtualLocation virt_loc,
2360 gpointer user_data)
2361{
2362 SplitRegister* reg = user_data;
2363 const char* help;
2364
2365 help = gnc_table_get_entry (reg->table, virt_loc);
2366 if (!help || *help == '\0')
2367 help = _ ("Enter debit formula for real transaction");
2368
2369 return g_strdup (help);
2370}
2371
2372static const char*
2373gnc_template_register_get_fcred_entry (VirtualLocation virt_loc,
2374 gboolean translate,
2375 gboolean* conditionally_changed,
2376 gpointer user_data)
2377{
2378 SplitRegister* reg = user_data;
2379 Split* split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
2380 static char* formula = NULL;
2381
2382 g_free (formula);
2383 formula = NULL;
2384 if (split)
2385 {
2386 qof_instance_get (QOF_INSTANCE (split),
2387 "sx-credit-formula", &formula,
2388 NULL);
2389 }
2390
2391 return formula;
2392
2393}
2394
2395static char*
2396gnc_split_register_get_fcred_help (VirtualLocation virt_loc,
2397 gpointer user_data)
2398{
2399 SplitRegister* reg = user_data;
2400 const char* help = gnc_table_get_entry (reg->table, virt_loc);
2401
2402 if (!help || *help == '\0')
2403 help = _ ("Enter credit formula for real transaction");
2404
2405 return g_strdup (help);
2406}
2407
2408static char*
2409gnc_split_register_get_default_help (VirtualLocation virt_loc,
2410 gpointer user_data)
2411{
2412 SplitRegister* reg = user_data;
2413 const char* help = gnc_table_get_entry (reg->table, virt_loc);
2414
2415 return g_strdup (help);
2416}
2417
2418/* This function has been #if-zeroed for a year; in all released versions since
2419 * 2001 it has issued dire warnings about being wrong, and returned nothing
2420 * because it was querying a non-existent slot.
2421 *
2422 * Now it retrieves the sx-debit-numeric or sx-credit-numeric properties from
2423 * the split. I'm not sure that it's what was originally intended, but at least
2424 * it can do something now. <jralls, 8 June 2015>
2425 */
2426static const char*
2427gnc_template_register_get_debcred_entry (VirtualLocation virt_loc,
2428 gboolean translate,
2429 gboolean* conditionally_changed,
2430 gpointer user_data)
2431{
2432 SplitRegister* reg = user_data;
2433 Split* split;
2434 gnc_numeric* amount, amount2;
2435 const char* cell_name;
2436
2437 split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
2438 if (!split)
2439 return gnc_split_register_get_debcred_entry (virt_loc,
2440 translate,
2441 conditionally_changed,
2442 user_data);
2443
2444 cell_name = gnc_table_get_cell_name (reg->table, virt_loc);
2445 if (gnc_cell_name_equal (cell_name, DEBT_CELL))
2446 qof_instance_get (QOF_INSTANCE (split),
2447 "sx-debit-numeric", &amount,
2448 NULL);
2449 else
2450 qof_instance_get (QOF_INSTANCE (split),
2451 "sx-credit-numeric", &amount,
2452 NULL);
2453 if (!amount)
2454 return "";
2455
2456 if (gnc_numeric_zero_p (*amount))
2457 {
2458 g_free (amount);
2459 return "";
2460 }
2461
2462 amount2 = gnc_numeric_abs (*amount);
2463 g_free (amount);
2464 return xaccPrintAmount (amount2,
2465 gnc_default_print_info (reg->mismatched_commodities));
2466}
2467
2468static void
2469gnc_split_register_guid_free (gpointer guid)
2470{
2471 guid_free (guid);
2472}
2473
2474static void
2475gnc_split_register_guid_copy (gpointer p_to, gconstpointer p_from)
2476{
2477 GncGUID* to = p_to;
2478 const GncGUID* from = p_from;
2479
2480 g_return_if_fail (to != NULL);
2481 *to = from ? *from : *guid_null();
2482}
2483
2484
2485static void
2486gnc_split_register_colorize_negative (gpointer gsettings, gchar* key,
2487 gpointer unused)
2488{
2489 use_red_for_negative = gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL,
2490 GNC_PREF_NEGATIVE_IN_RED);
2491}
2492
2493
2494static gpointer
2495gnc_split_register_model_add_hooks (gpointer unused)
2496{
2497 gulong id = gnc_prefs_register_cb (GNC_PREFS_GROUP_GENERAL,
2498 GNC_PREF_NEGATIVE_IN_RED,
2499 gnc_split_register_colorize_negative,
2500 NULL);
2501
2502 gnc_prefs_set_reg_negative_color_pref_id (id);
2503
2504 /* Get the initial value */
2505 use_red_for_negative = gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL,
2506 GNC_PREF_NEGATIVE_IN_RED);
2507 return NULL;
2508}
2509
2510
2512gnc_split_register_model_new (void)
2513{
2514 TableModel* model;
2515 static GOnce once = G_ONCE_INIT;
2516
2517 g_once (&once, gnc_split_register_model_add_hooks, NULL);
2518
2519 model = gnc_table_model_new();
2520
2521 // entry handlers
2522 gnc_table_model_set_entry_handler (model,
2523 gnc_split_register_get_date_entry,
2524 DATE_CELL);
2525
2526 gnc_table_model_set_entry_handler (model,
2527 gnc_split_register_get_due_date_entry,
2528 DDUE_CELL);
2529
2530 gnc_table_model_set_entry_handler (model,
2531 gnc_split_register_get_num_entry,
2532 NUM_CELL);
2533
2534 gnc_table_model_set_entry_handler (model,
2535 gnc_split_register_get_tran_num_entry,
2536 TNUM_CELL);
2537
2538 gnc_table_model_set_entry_handler (model,
2539 gnc_split_register_get_desc_entry,
2540 DESC_CELL);
2541
2542 gnc_table_model_set_entry_handler (model,
2543 gnc_split_register_get_notes_entry,
2544 NOTES_CELL);
2545
2546 gnc_table_model_set_entry_handler (model,
2547 gnc_split_register_get_vnotes_entry,
2548 VNOTES_CELL);
2549
2550 gnc_table_model_set_entry_handler (model,
2551 gnc_split_register_get_rate_entry,
2552 RATE_CELL);
2553
2554 gnc_table_model_set_entry_handler (model,
2555 gnc_split_register_get_recn_entry,
2556 RECN_CELL);
2557
2558 gnc_table_model_set_entry_handler (model,
2559 gnc_split_register_get_action_entry,
2560 ACTN_CELL);
2561
2562 gnc_table_model_set_entry_handler (model,
2563 gnc_split_register_get_memo_entry,
2564 MEMO_CELL);
2565
2566 gnc_table_model_set_entry_handler (model,
2567 gnc_split_register_get_balance_entry,
2568 BALN_CELL);
2569
2570 gnc_table_model_set_entry_handler (model,
2571 gnc_split_register_get_balance_entry,
2572 TBALN_CELL);
2573
2574 gnc_table_model_set_entry_handler (model,
2575 gnc_split_register_get_price_entry,
2576 PRIC_CELL);
2577
2578 gnc_table_model_set_entry_handler (model,
2579 gnc_split_register_get_shares_entry,
2580 SHRS_CELL);
2581
2582 gnc_table_model_set_entry_handler (model,
2583 gnc_split_register_get_tshares_entry,
2584 TSHRS_CELL);
2585
2586 gnc_table_model_set_entry_handler (model,
2587 gnc_split_register_get_xfrm_entry,
2588 XFRM_CELL);
2589
2590 gnc_table_model_set_entry_handler (model,
2591 gnc_split_register_get_mxfrm_entry,
2592 MXFRM_CELL);
2593
2594 gnc_table_model_set_entry_handler (model,
2595 gnc_split_register_get_tdebcred_entry,
2596 TDEBT_CELL);
2597
2598 gnc_table_model_set_entry_handler (model,
2599 gnc_split_register_get_tdebcred_entry,
2600 TCRED_CELL);
2601
2602 gnc_table_model_set_entry_handler (model,
2603 gnc_split_register_get_doclink_entry,
2604 DOCLINK_CELL);
2605
2606 gnc_table_model_set_entry_handler (model,
2607 gnc_split_register_get_type_entry,
2608 TYPE_CELL);
2609
2610 gnc_table_model_set_entry_handler (model,
2611 gnc_split_register_get_debcred_entry,
2612 DEBT_CELL);
2613
2614 gnc_table_model_set_entry_handler (model,
2615 gnc_split_register_get_debcred_entry,
2616 CRED_CELL);
2617
2618 gnc_table_model_set_entry_handler (model,
2619 gnc_split_register_get_rbaln_entry,
2620 RBALN_CELL);
2621
2622 // label handlers
2623 gnc_table_model_set_label_handler (model,
2624 gnc_split_register_get_date_label,
2625 DATE_CELL);
2626
2627 gnc_table_model_set_label_handler (model,
2628 gnc_split_register_get_due_date_label,
2629 DDUE_CELL);
2630
2631 gnc_table_model_set_label_handler (model,
2632 gnc_split_register_get_num_label,
2633 NUM_CELL);
2634
2635 gnc_table_model_set_label_handler (model,
2636 gnc_split_register_get_tran_num_label,
2637 TNUM_CELL);
2638
2639 gnc_table_model_set_label_handler (model,
2640 gnc_split_register_get_desc_label,
2641 DESC_CELL);
2642
2643 gnc_table_model_set_label_handler (model,
2644 gnc_split_register_get_recn_label,
2645 RECN_CELL);
2646
2647 gnc_table_model_set_label_handler (model,
2648 gnc_split_register_get_baln_label,
2649 BALN_CELL);
2650
2651 gnc_table_model_set_label_handler (model,
2652 gnc_split_register_get_action_label,
2653 ACTN_CELL);
2654
2655 gnc_table_model_set_label_handler (model,
2656 gnc_split_register_get_xfrm_label,
2657 XFRM_CELL);
2658
2659 gnc_table_model_set_label_handler (model,
2660 gnc_split_register_get_memo_label,
2661 MEMO_CELL);
2662
2663 gnc_table_model_set_label_handler (model,
2664 gnc_split_register_get_debit_label,
2665 DEBT_CELL);
2666
2667 gnc_table_model_set_label_handler (model,
2668 gnc_split_register_get_credit_label,
2669 CRED_CELL);
2670
2671 gnc_table_model_set_label_handler (model,
2672 gnc_split_register_get_price_label,
2673 PRIC_CELL);
2674
2675 gnc_table_model_set_label_handler (model,
2676 gnc_split_register_get_rate_label,
2677 RATE_CELL);
2678
2679 gnc_table_model_set_label_handler (model,
2680 gnc_split_register_get_shares_label,
2681 SHRS_CELL);
2682
2683 gnc_table_model_set_label_handler (model,
2684 gnc_split_register_get_mxfrm_label,
2685 MXFRM_CELL);
2686
2687 gnc_table_model_set_label_handler (model,
2688 gnc_split_register_get_tcredit_label,
2689 TCRED_CELL);
2690
2691 gnc_table_model_set_label_handler (model,
2692 gnc_split_register_get_tdebit_label,
2693 TDEBT_CELL);
2694
2695 gnc_table_model_set_label_handler (model,
2696 gnc_split_register_get_tshares_label,
2697 TSHRS_CELL);
2698
2699 gnc_table_model_set_label_handler (model,
2700 gnc_split_register_get_tbalance_label,
2701 TBALN_CELL);
2702
2703 gnc_table_model_set_label_handler (model,
2704 gnc_split_register_get_doclink_label,
2705 DOCLINK_CELL);
2706
2707 gnc_table_model_set_label_handler (model,
2708 gnc_split_register_get_type_label,
2709 TYPE_CELL);
2710
2711 gnc_table_model_set_label_handler (model,
2712 gnc_split_register_get_notes_label,
2713 NOTES_CELL);
2714
2715 gnc_table_model_set_label_handler (model,
2716 gnc_split_register_get_fdebit_label,
2717 FDEBT_CELL);
2718
2719 gnc_table_model_set_label_handler (model,
2720 gnc_split_register_get_fcredit_label,
2721 FCRED_CELL);
2722
2723 gnc_table_model_set_label_handler (model,
2724 gnc_split_register_get_tbalance_label,
2725 RBALN_CELL);
2726
2727 // tooltip handlers
2728
2729 gnc_table_model_set_tooltip_handler (model,
2730 gnc_split_register_get_recn_tooltip,
2731 RECN_CELL);
2732
2733 gnc_table_model_set_tooltip_handler (model,
2734 gnc_split_register_get_doclink_tooltip,
2735 DOCLINK_CELL);
2736
2737
2738 // help handlers
2739 gnc_table_model_set_default_help_handler (
2740 model, gnc_split_register_get_default_help);
2741
2742 gnc_table_model_set_help_handler (model,
2743 gnc_split_register_get_date_help,
2744 DATE_CELL);
2745
2746 gnc_table_model_set_help_handler (model,
2747 gnc_split_register_get_date_help,
2748 DDUE_CELL);
2749
2750 gnc_table_model_set_help_handler (model,
2751 gnc_split_register_get_num_help,
2752 NUM_CELL);
2753
2754 gnc_table_model_set_help_handler (model,
2755 gnc_split_register_get_tran_num_help,
2756 TNUM_CELL);
2757
2758 gnc_table_model_set_help_handler (model,
2759 gnc_split_register_get_desc_help,
2760 DESC_CELL);
2761
2762 gnc_table_model_set_help_handler (model,
2763 gnc_split_register_get_price_help,
2764 PRIC_CELL);
2765
2766 gnc_table_model_set_help_handler (model,
2767 gnc_split_register_get_shares_help,
2768 SHRS_CELL);
2769
2770 gnc_table_model_set_help_handler (model,
2771 gnc_split_register_get_action_help,
2772 ACTN_CELL);
2773
2774 gnc_table_model_set_help_handler (model,
2775 gnc_split_register_get_memo_help,
2776 MEMO_CELL);
2777
2778 gnc_table_model_set_help_handler (model,
2779 gnc_split_register_get_notes_help,
2780 NOTES_CELL);
2781
2782 gnc_table_model_set_help_handler (model,
2783 gnc_split_register_get_vnotes_help,
2784 VNOTES_CELL);
2785
2786 gnc_table_model_set_help_handler (model,
2787 gnc_split_register_get_xfrm_help,
2788 XFRM_CELL);
2789
2790 gnc_table_model_set_help_handler (model,
2791 gnc_split_register_get_mxfrm_help,
2792 MXFRM_CELL);
2793
2794 gnc_table_model_set_help_handler (model,
2795 gnc_split_register_get_fcred_help,
2796 FCRED_CELL);
2797
2798 gnc_table_model_set_help_handler (model,
2799 gnc_split_register_get_fdebt_help,
2800 FDEBT_CELL);
2801
2802 gnc_table_model_set_help_handler (model,
2803 gnc_split_register_get_doclink_help,
2804 DOCLINK_CELL);
2805
2806 // io flag handlers
2807 gnc_table_model_set_io_flags_handler (
2808 model, gnc_split_register_get_standard_io_flags, DATE_CELL);
2809
2810 /* FIXME: We really only need a due date for 'invoices', not for
2811 * 'payments' or 'receipts'. This implies we really only need the
2812 * due-date for transactions that credit the ACCT_TYPE_RECEIVABLE or
2813 * debit the ACCT_TYPE_PAYABLE account type.
2814 */
2815 gnc_table_model_set_io_flags_handler (
2816 model, gnc_split_register_get_rate_io_flags, RATE_CELL);
2817
2818 gnc_table_model_set_io_flags_handler (
2819 model, gnc_split_register_get_ddue_io_flags, DDUE_CELL);
2820
2821 gnc_table_model_set_io_flags_handler (
2822 model, gnc_split_register_get_standard_io_flags, NUM_CELL);
2823
2824 gnc_table_model_set_io_flags_handler (
2825 model, gnc_split_register_get_standard_io_flags, TNUM_CELL);
2826
2827 gnc_table_model_set_io_flags_handler (
2828 model, gnc_split_register_get_standard_io_flags, DESC_CELL);
2829
2830 gnc_table_model_set_io_flags_handler (
2831 model, gnc_split_register_get_standard_io_flags, ACTN_CELL);
2832
2833 gnc_table_model_set_io_flags_handler (
2834 model, gnc_split_register_get_standard_io_flags, XFRM_CELL);
2835
2836 gnc_table_model_set_io_flags_handler (
2837 model, gnc_split_register_get_standard_io_flags, MEMO_CELL);
2838
2839 gnc_table_model_set_io_flags_handler (
2840 model, gnc_split_register_get_standard_io_flags, MXFRM_CELL);
2841
2842 gnc_table_model_set_io_flags_handler (
2843 model, gnc_split_register_get_standard_io_flags, NOTES_CELL);
2844
2845 gnc_table_model_set_io_flags_handler (
2846 model, gnc_split_register_get_inactive_io_flags, VNOTES_CELL);
2847
2848 gnc_table_model_set_io_flags_handler (
2849 model, gnc_split_register_get_debcred_io_flags, CRED_CELL);
2850
2851 gnc_table_model_set_io_flags_handler (
2852 model, gnc_split_register_get_debcred_io_flags, DEBT_CELL);
2853
2854 gnc_table_model_set_io_flags_handler (
2855 model, gnc_split_register_get_recn_io_flags, RECN_CELL);
2856
2857 gnc_table_model_set_io_flags_handler (
2858 model, gnc_split_register_get_doclink_io_flags, DOCLINK_CELL);
2859
2860 gnc_table_model_set_io_flags_handler (
2861 model, gnc_split_register_get_recn_io_flags, TYPE_CELL);
2862
2863 gnc_table_model_set_io_flags_handler (
2864 model, gnc_split_register_get_security_io_flags, PRIC_CELL);
2865
2866 gnc_table_model_set_io_flags_handler (
2867 model, gnc_split_register_get_security_io_flags, SHRS_CELL);
2868
2869
2870 gnc_table_model_set_default_cell_color_handler (
2871 model, gnc_split_register_get_cell_color);
2872
2873 gnc_table_model_set_cell_color_handler (
2874 model, gnc_split_register_get_debcred_color, DEBT_CELL);
2875
2876 gnc_table_model_set_cell_color_handler (
2877 model, gnc_split_register_get_debcred_color, CRED_CELL);
2878
2879 gnc_table_model_set_cell_color_handler (
2880 model, gnc_split_register_get_debcred_color, TDEBT_CELL);
2881
2882 gnc_table_model_set_cell_color_handler (
2883 model, gnc_split_register_get_debcred_color, TCRED_CELL);
2884
2885 gnc_table_model_set_cell_color_handler (
2886 model, gnc_split_register_get_debcred_color, FCRED_CELL);
2887
2888 gnc_table_model_set_cell_color_handler (
2889 model, gnc_split_register_get_debcred_color, FDEBT_CELL);
2890
2891
2892 gnc_table_model_set_default_cell_border_handler (
2893 model, gnc_split_register_get_border);
2894
2895
2896 gnc_table_model_set_default_confirm_handler (
2897 model, gnc_split_register_confirm);
2898
2899 model->cell_data_allocator = gnc_split_register_guid_malloc;
2900 model->cell_data_deallocator = gnc_split_register_guid_free;
2901 model->cell_data_copy = gnc_split_register_guid_copy;
2902
2903 gnc_split_register_model_add_save_handlers (model);
2904
2905 return model;
2906}
2907
2909gnc_template_register_model_new (void)
2910{
2911 TableModel* model;
2912
2913 model = gnc_split_register_model_new();
2914
2915 gnc_table_model_set_entry_handler (
2916 model, gnc_split_register_get_inactive_date_entry, DATE_CELL);
2917
2918 gnc_table_model_set_entry_handler (
2919 model, gnc_split_register_get_inactive_date_entry, DDUE_CELL);
2920
2921 gnc_table_model_set_io_flags_handler (
2922 model, gnc_split_register_get_inactive_io_flags, DATE_CELL);
2923
2924 gnc_table_model_set_io_flags_handler (
2925 model, gnc_split_register_get_inactive_io_flags, DDUE_CELL);
2926
2927 gnc_table_model_set_entry_handler (
2928 model, gnc_template_register_get_xfrm_entry, XFRM_CELL);
2929
2930 gnc_table_model_set_entry_handler (
2931 model, gnc_template_register_get_fdebt_entry, FDEBT_CELL);
2932
2933 gnc_table_model_set_entry_handler (
2934 model, gnc_template_register_get_fcred_entry, FCRED_CELL);
2935
2936 gnc_table_model_set_entry_handler (
2937 model, gnc_template_register_get_debcred_entry, DEBT_CELL);
2938
2939 gnc_table_model_set_entry_handler (
2940 model, gnc_template_register_get_debcred_entry, CRED_CELL);
2941
2942 gnc_table_model_set_io_flags_handler (
2943 model, gnc_split_register_get_standard_io_flags, FCRED_CELL);
2944
2945 gnc_table_model_set_io_flags_handler (
2946 model, gnc_split_register_get_standard_io_flags, FDEBT_CELL);
2947
2948 gnc_template_register_model_add_save_handlers (model);
2949
2950 return model;
2951}
All type declarations for the whole Gnucash engine.
File path resolution utility functions.
GLib helper routines.
Generic api to store and retrieve preferences.
Utility functions for convert uri in separate components and back.
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Definition Account.cpp:3305
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
Definition Account.cpp:3044
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false.
Definition Account.cpp:4551
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
Definition Account.cpp:3408
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id,...
Definition Account.cpp:2050
gnc_numeric gnc_price_cell_get_value(PriceCell *cell)
return the value of a price cell
Definition pricecell.c:208
void gnc_date_cell_get_date(DateCell *cell, time64 *time, gboolean warn)
Set a time64 to the value in the DateCell.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
void gnc_monetary_list_free(MonetaryList *list)
Free a MonetaryList and all the monetaries it points to.
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency.
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
Definition gnc-date.h:108
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
size_t qof_print_date_buff(char *buff, const size_t len, time64 t)
Convenience: calls through to qof_print_date_dmy_buff().
Definition gnc-date.cpp:574
char * gnc_print_time64(time64 time, const char *format)
print a time64 as a date string per format
Definition gnc-date.cpp:370
const char * xaccTransGetVoidReason(const Transaction *trans)
Returns the user supplied textual reason why a transaction was voided.
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
char xaccTransGetTxnType(Transaction *trans)
Returns the Transaction Type: note this type will be derived from the transaction splits,...
const char * xaccTransGetDocLink(const Transaction *trans)
Gets the transaction Document Link.
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
MonetaryList * xaccTransGetImbalance(const Transaction *trans)
The xaccTransGetImbalance method returns a list giving the value of the transaction in each currency ...
#define TXN_TYPE_NONE
No transaction type
gboolean xaccTransIsBalanced(const Transaction *trans)
Returns true if the transaction is balanced according to the rules currently in effect.
#define TXN_TYPE_INVOICE
Transaction is an invoice.
Split * xaccTransGetSplit(const Transaction *trans, int i)
Return a pointer to the indexed split in this transaction's split list.
time64 xaccTransRetDatePosted(const Transaction *trans)
Retrieve the posted date of the transaction.
const char * xaccTransGetNotes(const Transaction *trans)
Gets the transaction Notes.
gnc_numeric xaccTransGetAccountValue(const Transaction *trans, const Account *acc)
The xaccTransGetAccountValue() method returns the total value applied to a particular account.
gnc_numeric xaccTransGetAccountAmount(const Transaction *trans, const Account *acc)
Same as xaccTransGetAccountValue, but uses the Account's commodity.
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
gboolean xaccTransUseTradingAccounts(const Transaction *trans)
Determine whether this transaction should use commodity trading accounts.
time64 xaccTransRetDateDue(const Transaction *trans)
Dates and txn-type for A/R and A/P "invoice" postings.
gboolean xaccTransIsReadonlyByPostedDate(const Transaction *trans)
Returns TRUE if this Transaction is read-only because its posted-date is older than the "auto-readonl...
const char * xaccTransGetReadOnly(Transaction *trans)
Returns a non-NULL value if this Transaction was marked as read-only with some specific "reason" text...
gnc_numeric xaccTransGetAccountBalance(const Transaction *trans, const Account *account)
Get the account balance for the specified account after the last split in the specified transaction.
gnc_numeric xaccTransGetImbalanceValue(const Transaction *trans)
The xaccTransGetImbalanceValue() method returns the total value of the transaction.
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition guid.cpp:165
GncGUID * guid_malloc(void)
Allocate memory for a GUID.
Definition guid.cpp:139
Account * gnc_account_lookup_for_register(const Account *base_account, const char *name)
Retrieve the account matching the given name starting from the descendants of base_account.
const char * xaccPrintAmount(gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
char * gnc_get_account_name_for_split_register(const Account *account, gboolean show_leaf_accounts)
Get either the full name of the account or the simple name, depending on the show_leaf_accounts.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
const char * gnc_get_doclink_str(char link_flag)
Get a string representing the document link type.
gchar * gnc_g_list_stringjoin(GList *list_of_strings, const gchar *sep)
Return a string joining a GList whose elements are gchar* strings.
void qof_instance_get(const QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_get.
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256
#define PWARN(format, args...)
Log a warning.
Definition qoflog.h:250
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
gnc_numeric gnc_numeric_div(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Division.
gnc_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value.
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gnc_numeric gnc_numeric_neg(gnc_numeric a)
Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value.
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
gulong gnc_prefs_register_cb(const char *group, const gchar *pref_name, gpointer func, gpointer user_data)
Register a callback that gets triggered when the given preference changes.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
gboolean gnc_split_register_current_trans_expanded(SplitRegister *reg)
Return TRUE if current trans is expanded and style is REG_STYLE_LEDGER.
CursorClass gnc_split_register_get_cursor_class(SplitRegister *reg, VirtualCellLocation vcell_loc)
Returns the class of the cursor at the given virtual cell location.
SplitRegisterType
Register types.
Transaction * gnc_split_register_get_current_trans(SplitRegister *reg)
Gets the transaction at the current cursor location, which may be on the transaction itself or on any...
const char * gnc_split_register_get_credit_string(SplitRegister *reg)
Return the credit string used in the register.
const char * gnc_split_register_get_debit_string(SplitRegister *reg)
Return the debit string used in the register.
gboolean gnc_split_reg_has_rate_cell(SplitRegisterType type)
Determine if we need to perform any conversion on the splits in this transaction, and if so,...
CursorClass
Types of cursors.
VirtualCell * gnc_table_get_virtual_cell(Table *table, VirtualCellLocation vcell_loc)
returns the virtual cell associated with a particular virtual location.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
char xaccSplitGetReconcile(const Split *split)
Returns the value of the reconcile flag.
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
The xaccSplitLookup() subroutine will return the split associated with the given id,...
Definition Split.cpp:1091
#define VREC
split is void
Definition Split.h:77
time64 xaccSplitGetDateReconciled(const Split *split)
Retrieve the date when the Split was reconciled.
Definition Split.cpp:1859
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction's commodity.
gnc_numeric xaccSplitGetSharePrice(const Split *split)
Returns the price of the split, that is, the value divided by the amount.
Definition Split.cpp:1995
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
#define NREC
not reconciled or cleared
Definition Split.h:76
Split * xaccSplitGetOtherSplit(const Split *split)
The xaccSplitGetOtherSplit() is a convenience routine that returns the other of a pair of splits.
gnc_numeric xaccSplitGetBalance(const Split *s)
Returns the running balance up to and including the indicated split.
Definition Split.cpp:1316
#define YREC
The Split has been reconciled.
Definition Split.h:74
gboolean xaccSplitIsStockSplit(Split *s)
Returns true if the split is of type stock split.
Definition Split.cpp:2078
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.
gchar * gnc_uri_get_scheme(const gchar *uri)
Extracts the scheme from a uri.
Save handlers for the SplitRegister Model and Template SplitRegister model.
TableModels specialized for SplitRegister and template SplitRegister.
private declarations for SplitRegister
API for checkbook register display area.
STRUCTS.
The DateCell object implements a date handling cell.
Definition datecell.h:92
The Doclinkcell object implements a cell handler that will cycle through a series of single-character...
Definition doclinkcell.h:53
The type used to store guids in C.
Definition guid.h:75
The PriceCell object implements a cell handler that stores a single double-precision value,...
Definition pricecell.h:55
The RecnCell object implements a cell handler that will cycle through a series of single-character va...
Definition recncell.h:48
holds information about each virtual cell.
unsigned int start_primary_color
visible in the GUI