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