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