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