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