diff --git a/src/SplitLedger.c b/src/SplitLedger.c index 54450dfb00..cbf61c6737 100644 --- a/src/SplitLedger.c +++ b/src/SplitLedger.c @@ -922,9 +922,10 @@ LedgerAutoCompletion(SplitRegister *reg, gncTableTraversalDir dir, if (trans == NULL) return FALSE; - cursor_class = xaccSplitRegisterGetCurrentCursorClass(reg); - cell_type = xaccSplitRegisterGetCurrentCellType(reg); - changed = xaccSplitRegisterGetChangeFlag(reg); + cursor_class = xaccSplitRegisterGetCurrentCursorClass (reg); + cell_type = xaccSplitRegisterGetCurrentCellType (reg); + changed = xaccSplitRegisterGetChangeFlag (reg); + changed |= xaccSplitRegisterGetConditionalChangeFlag (reg); switch (cursor_class) { @@ -1154,7 +1155,7 @@ LedgerTraverse (Table *table, return; /* no changes, make sure we aren't going off the end */ - changed = xaccSplitRegisterGetChangeFlag(reg); + changed = xaccSplitRegisterGetChangeFlag (reg); if (!changed && (pending_trans != trans)) { gnc_table_find_close_valid_cell (table, &virt_loc, info->exact_traversal); @@ -2281,6 +2282,7 @@ static gboolean xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm, gboolean use_cut_semantics) { + SCM other_split_scm = SCM_UNDEFINED; Transaction *trans; guint32 changed; @@ -2291,6 +2293,8 @@ xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm, if (!changed) return FALSE; + changed |= xaccSplitRegisterGetConditionalChangeFlag (reg); + /* get the handle to the current split and transaction */ trans = xaccSRGetCurrentTrans (reg); if (trans == NULL) @@ -2336,15 +2340,12 @@ xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm, } if (MOD_MXFRM & changed) { - SCM other_split_scm; - other_split_scm = gnc_trans_scm_get_other_split_scm(trans_scm, split_scm); if (other_split_scm == SCM_UNDEFINED) { if (gnc_trans_scm_get_num_splits(trans_scm) == 1) { Split *temp_split; char *temp_string; - gnc_numeric num; temp_split = xaccMallocSplit (); other_split_scm = gnc_copy_split(temp_split, use_cut_semantics); @@ -2362,12 +2363,6 @@ xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm, free(temp_string); } - num = gnc_split_scm_get_quantity (split_scm); - gnc_split_scm_set_quantity (other_split_scm, gnc_numeric_neg (num)); - - num = gnc_split_scm_get_value (split_scm); - gnc_split_scm_set_value (other_split_scm, gnc_numeric_neg (num)); - gnc_trans_scm_append_split_scm(trans_scm, other_split_scm); } } @@ -2388,8 +2383,8 @@ xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm, gnc_numeric credit; gnc_numeric debit; - credit = xaccGetPriceCellValue(reg->creditCell); - debit = xaccGetPriceCellValue(reg->debitCell); + credit = xaccGetPriceCellValue (reg->creditCell); + debit = xaccGetPriceCellValue (reg->debitCell); new_value = gnc_numeric_sub_fixed (debit, credit); gnc_split_scm_set_value (split_scm, new_value); @@ -2405,6 +2400,20 @@ xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm, gnc_split_scm_set_quantity (split_scm, shares); } + if ((MOD_AMNT | MOD_PRIC | MOD_SHRS) & changed) + { + if (other_split_scm != SCM_UNDEFINED) + { + gnc_numeric num; + + num = gnc_split_scm_get_quantity (split_scm); + gnc_split_scm_set_quantity (other_split_scm, gnc_numeric_neg (num)); + + num = gnc_split_scm_get_value (split_scm); + gnc_split_scm_set_value (other_split_scm, gnc_numeric_neg (num)); + } + } + return TRUE; } @@ -2569,6 +2578,7 @@ xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split) guint32 changed; changed = xaccSplitRegisterGetChangeFlag (reg); + changed |= xaccSplitRegisterGetConditionalChangeFlag (reg); /* copy the contents from the cursor to the split */ if (MOD_DATE & changed) { @@ -3034,7 +3044,7 @@ get_trans_total_balance (SplitRegister *reg, Transaction *trans) const char * xaccSRGetEntryHandler (VirtualLocation virt_loc, short _cell_type, - gboolean *changed, gpointer user_data) + gboolean *conditionally_changed, gpointer user_data) { CellType cell_type = _cell_type; SplitRegister *reg = user_data; @@ -3042,8 +3052,8 @@ xaccSRGetEntryHandler (VirtualLocation virt_loc, short _cell_type, Transaction *trans; Split *split; - if (changed) - *changed = FALSE; + if (conditionally_changed) + *conditionally_changed = FALSE; split = sr_get_split (reg, virt_loc.vcell_loc); if (split == NULL) @@ -3068,8 +3078,8 @@ xaccSRGetEntryHandler (VirtualLocation virt_loc, short _cell_type, if (gnc_numeric_positive_p (imbalance) && (cell_type == CRED_CELL)) return ""; - if (changed) - *changed = TRUE; + if (conditionally_changed) + *conditionally_changed = TRUE; imbalance = gnc_numeric_abs (imbalance); @@ -3612,11 +3622,12 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist, /* If the current cursor has changed we save the values for later * possible restoration. */ - changed = xaccSplitRegisterGetChangeFlag(reg); - if (changed && find_split && (find_split == xaccSRGetCurrentSplit(reg))) + changed = xaccSplitRegisterGetChangeFlag (reg); + changed |= xaccSplitRegisterGetConditionalChangeFlag (reg); + if (changed && find_split && (find_split == xaccSRGetCurrentSplit (reg))) { - reg_buffer = xaccMallocSplitRegisterBuffer(); - xaccSplitRegisterSaveCursor(reg, reg_buffer); + reg_buffer = xaccMallocSplitRegisterBuffer (); + xaccSplitRegisterSaveCursor (reg, reg_buffer); } else reg_buffer = NULL; @@ -3772,6 +3783,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist, if (reg_buffer != NULL) xaccDestroySplitRegisterBuffer(reg_buffer); + reg_buffer = NULL; } diff --git a/src/register/basiccell.c b/src/register/basiccell.c index d42fb5c91c..81a4e0332a 100644 --- a/src/register/basiccell.c +++ b/src/register/basiccell.c @@ -68,8 +68,9 @@ BasicCellHelpValue(BasicCell *cell) void xaccInitBasicCell (BasicCell *cell) { - cell->input_output = XACC_CELL_ALLOW_ALL; cell->changed = 0; + cell->conditionally_changed = 0; + cell->input_output = XACC_CELL_ALLOW_ALL; cell->value = g_strdup(""); cell->blank_help = NULL; diff --git a/src/register/basiccell.h b/src/register/basiccell.h index 626b81da6b..dd17b710b6 100644 --- a/src/register/basiccell.h +++ b/src/register/basiccell.h @@ -217,11 +217,12 @@ typedef char * (*CellGetHelpFunc) (BasicCell *cell); struct _BasicCell { - char * value; /* current value */ - char * blank_help; /* help when value is blank */ + char * value; /* current value */ + char * blank_help; /* help when value is blank */ - guint32 changed; /* 2^32-1 if value modified */ - guint8 input_output; /* allowed behavior flags */ + guint32 changed; /* 2^32-1 if value modified */ + guint32 conditionally_changed; /* value if modified conditionally */ + guint8 input_output; /* allowed behavior flags */ /* "virtual", overloaded set-value method */ CellSetValueFunc set_value; diff --git a/src/register/splitreg.c b/src/register/splitreg.c index 1f00cae133..e737c704f1 100644 --- a/src/register/splitreg.c +++ b/src/register/splitreg.c @@ -59,7 +59,8 @@ typedef struct _CellBuffer CellBuffer; struct _CellBuffer { char * value; - unsigned int changed; + guint32 changed; + guint32 conditionally_changed; }; struct _SplitRegisterBuffer @@ -1071,6 +1072,30 @@ xaccSplitRegisterGetChangeFlag (SplitRegister *reg) return changed; } +guint32 +xaccSplitRegisterGetConditionalChangeFlag (SplitRegister *reg) +{ + guint32 changed = 0; + + /* be careful to use bitwise ands and ors to assemble bit flag */ + changed |= MOD_DATE & reg->dateCell->cell.conditionally_changed; + changed |= MOD_NUM & reg->numCell->cell.conditionally_changed; + changed |= MOD_DESC & reg->descCell->cell.conditionally_changed; + changed |= MOD_RECN & reg->recnCell->cell.conditionally_changed; + + changed |= MOD_ACTN & reg->actionCell->cell.conditionally_changed; + changed |= MOD_XFRM & reg->xfrmCell->cell.conditionally_changed; + changed |= MOD_MXFRM & reg->mxfrmCell->cell.conditionally_changed; + changed |= MOD_XTO & reg->xtoCell->cell.conditionally_changed; + changed |= MOD_MEMO & reg->memoCell->cell.conditionally_changed; + changed |= MOD_AMNT & reg->creditCell->cell.conditionally_changed; + changed |= MOD_AMNT & reg->debitCell->cell.conditionally_changed; + changed |= MOD_PRIC & reg->priceCell->cell.conditionally_changed; + changed |= MOD_SHRS & reg->sharesCell->cell.conditionally_changed; + + return changed; +} + /* ============================================== */ void @@ -1400,6 +1425,7 @@ saveCell(BasicCell *bcell, CellBuffer *cb) cb->value = g_strdup(bcell->value); cb->changed = bcell->changed; + cb->conditionally_changed = bcell->conditionally_changed; } void @@ -1435,7 +1461,7 @@ restoreCellChanged(BasicCell *bcell, CellBuffer *cb, CellBlock *cursor) if ((bcell == NULL) || (cb == NULL)) return; - if (!cb->changed) + if (!cb->changed && !cb->conditionally_changed) return; /* only restore if it's in the current cursor */ @@ -1452,6 +1478,7 @@ restoreCellChanged(BasicCell *bcell, CellBuffer *cb, CellBlock *cursor) { xaccSetBasicCellValue(bcell, cb->value); bcell->changed = cb->changed; + bcell->conditionally_changed = cb->conditionally_changed; return; } } diff --git a/src/register/splitreg.h b/src/register/splitreg.h index ec1da7c20e..a7a48574c7 100644 --- a/src/register/splitreg.h +++ b/src/register/splitreg.h @@ -239,6 +239,7 @@ void xaccDestroySplitRegister (SplitRegister *reg); /* returns non-zero value if updates have been made to data */ guint32 xaccSplitRegisterGetChangeFlag (SplitRegister *reg); +guint32 xaccSplitRegisterGetConditionalChangeFlag (SplitRegister *reg); /* Clears all change flags in the register. Does not alter values */ void xaccSplitRegisterClearChangeFlag (SplitRegister *reg); diff --git a/src/register/table-allgui.c b/src/register/table-allgui.c index ff651de798..3d6c193965 100644 --- a/src/register/table-allgui.c +++ b/src/register/table-allgui.c @@ -168,7 +168,7 @@ gnc_table_get_header_cell (Table *table) static const char * gnc_table_get_entry_internal (Table *table, VirtualLocation virt_loc, - gboolean *changed) + gboolean *conditionally_changed) { VirtualCell *vcell; CellBlockCell *cb_cell; @@ -185,7 +185,8 @@ gnc_table_get_entry_internal (Table *table, VirtualLocation virt_loc, if (cb_cell->cell_type < 0) return ""; - return table->entry_handler (virt_loc, cb_cell->cell_type, changed, + return table->entry_handler (virt_loc, cb_cell->cell_type, + conditionally_changed, table->handler_user_data); } @@ -540,6 +541,8 @@ gnc_table_move_cursor_internal (Table *table, BasicCell *cell = cb_cell->cell; cell->changed = 0; + cell->conditionally_changed = 0; + if (cell->move) { VirtualLocation vloc; @@ -549,7 +552,7 @@ gnc_table_move_cursor_internal (Table *table, vloc.phys_row_offset = -1; vloc.phys_col_offset = -1; - (cell->move) (cell, vloc); + cell->move (cell, vloc); } } } @@ -596,20 +599,23 @@ gnc_table_move_cursor_internal (Table *table, * new values in the old cell locations, and that would * lead to confusion of all sorts. */ if (do_move_gui && cell->move) - (cell->move) (cell, virt_loc); + cell->move (cell, virt_loc); /* OK, now copy the string value from the table at large * into the cell handler. */ if (XACC_CELL_ALLOW_SHADOW & (cell->input_output)) { const char *entry; - gboolean changed = FALSE; + gboolean conditionally_changed = FALSE; - entry = gnc_table_get_entry_internal (table, virt_loc, &changed); + entry = gnc_table_get_entry_internal (table, virt_loc, + &conditionally_changed); xaccSetBasicCellValue (cell, entry); - cell->changed = changed ? GNC_CELL_CHANGED : 0; + cell->changed = 0; + cell->conditionally_changed = + conditionally_changed ? GNC_CELL_CHANGED : 0; } } } diff --git a/src/register/table-allgui.h b/src/register/table-allgui.h index ee3ced22ed..a2ec51c6a7 100644 --- a/src/register/table-allgui.h +++ b/src/register/table-allgui.h @@ -152,7 +152,7 @@ typedef void (*TableDestroyFunc) (Table *table); typedef const char * (*TableGetEntryHandler) (VirtualLocation virt_loc, short cell_type, - gboolean *changed, + gboolean *conditionally_changed, gpointer user_data); typedef guint32 (*TableGetFGColorHandler) (VirtualLocation virt_loc,