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