Bug #567709: Register: Don't assume that cells outside the cursor are valid.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18177 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Charles Day 2009-07-05 22:16:03 +00:00
parent c18ab75030
commit 677aa0cc6f
3 changed files with 140 additions and 27 deletions

View File

@ -1142,6 +1142,69 @@ gnc_split_register_get_cell_date (SplitRegister *reg, const char *cell_name)
return ts; return ts;
} }
/* Creates a transfer dialog and fills its values from register cells (if
* available) or from the provided transaction and split.
*/
static XferDialog *
gnc_split_register_xfer_dialog(SplitRegister *reg, Transaction *txn,
Split *split)
{
XferDialog *xfer;
CellBlock *cur;
BasicCell *cell;
g_return_val_if_fail(reg, NULL);
g_return_val_if_fail(reg->table, NULL);
cur = reg->table->current_cursor;
/* Create the exchange rate dialog. */
xfer = gnc_xfer_dialog(NULL, NULL);
g_return_val_if_fail(xfer, NULL);
/* Set the description. */
cell = gnc_cellblock_get_cell_by_name(cur, DESC_CELL, NULL, NULL);
if (cell)
gnc_xfer_dialog_set_description(xfer, gnc_basic_cell_get_value(cell));
else
{
const char *str = xaccTransGetDescription(txn);
gnc_xfer_dialog_set_description(xfer, str? str : "");
}
/* Set the memo. */
cell = gnc_cellblock_get_cell_by_name(cur, MEMO_CELL, NULL, NULL);
if (cell)
gnc_xfer_dialog_set_memo(xfer, gnc_basic_cell_get_value(cell));
else
{
const char *str = xaccSplitGetMemo(split);
gnc_xfer_dialog_set_memo(xfer, str? str : "");
}
/* Set the num. */
cell = gnc_cellblock_get_cell_by_name(cur, NUM_CELL, NULL, NULL);
if (cell)
gnc_xfer_dialog_set_num(xfer, gnc_basic_cell_get_value(cell));
else
{
const char *str = xaccTransGetNum(txn);
gnc_xfer_dialog_set_num(xfer, str? str : "");
}
/* Set the date. */
cell = gnc_cellblock_get_cell_by_name(cur, DATE_CELL, NULL, NULL);
if (cell)
{
Timespec ts;
gnc_date_cell_get_date((DateCell*) cell, &ts);
gnc_xfer_dialog_set_date(xfer, timespecToTime_t(ts));
}
else
gnc_xfer_dialog_set_date(xfer, xaccTransGetDate(txn));
return xfer;
}
/* This function checks to see if we need to determine an exchange rate. /* This function checks to see if we need to determine an exchange rate.
* If we need to determine an exchange rate, then pop up the dialog. * If we need to determine an exchange rate, then pop up the dialog.
* If the dialog does not complete successfully, then return TRUE. * If the dialog does not complete successfully, then return TRUE.
@ -1348,27 +1411,17 @@ gnc_split_register_handle_exchange (SplitRegister *reg, gboolean force_dialog)
return FALSE; return FALSE;
} }
/* create the exchange-rate dialog */ /* Show the exchange-rate dialog */
xfer = gnc_xfer_dialog (NULL, NULL); /* XXX */ xfer = gnc_split_register_xfer_dialog(reg, txn, split);
gnc_xfer_dialog_is_exchange_dialog (xfer, &exch_rate); gnc_xfer_dialog_is_exchange_dialog(xfer, &exch_rate);
/* fill in the dialog entries */
gnc_xfer_dialog_set_description(
xfer, gnc_split_register_get_cell_string (reg, DESC_CELL));
gnc_xfer_dialog_set_memo(
xfer, gnc_split_register_get_cell_string (reg, MEMO_CELL));
gnc_xfer_dialog_set_num(
xfer, gnc_split_register_get_cell_string (reg, NUM_CELL));
gnc_xfer_dialog_set_date(
xfer, timespecToTime_t(
gnc_split_register_get_cell_date(reg, DATE_CELL)));
if (gnc_xfer_dialog_run_exchange_dialog( if (gnc_xfer_dialog_run_exchange_dialog(
xfer, &exch_rate, amount, reg_acc, txn, xfer_com)) xfer, &exch_rate, amount, reg_acc, txn, xfer_com))
{ {
/* FIXME: How should the dialog be destroyed? */
LEAVE("leaving rate unchanged"); LEAVE("leaving rate unchanged");
return TRUE; return TRUE;
} }
/* FIXME: How should the dialog be destroyed? */
/* Set the RATE_CELL on this cursor and mark it changed */ /* Set the RATE_CELL on this cursor and mark it changed */
gnc_price_cell_set_value (rate_cell, exch_rate); gnc_price_cell_set_value (rate_cell, exch_rate);

View File

@ -120,6 +120,39 @@ gnc_cellblock_get_cell (CellBlock *cellblock, int row, int col)
return cellblock->cells->pdata[(row * cellblock->num_cols) + col]; return cellblock->cells->pdata[(row * cellblock->num_cols) + col];
} }
BasicCell *
gnc_cellblock_get_cell_by_name(CellBlock *cellblock,
const char *cell_name,
int *row, int *col)
{
int r, c, num_rows, num_cols;
if (cellblock == NULL)
return NULL;
if (cell_name == NULL)
return NULL;
num_rows = cellblock->num_rows;
num_cols = cellblock->num_cols;
for (r = 0; r < num_rows; r++)
for (c = 0; c < num_cols; c++)
{
BasicCell *cell = cellblock->cells->pdata[(r * num_cols) + c];
if (!cell) continue;
if (gnc_cell_name_equal(cell->cell_name, cell_name))
{
if (row)
*row = r;
if (col)
*col = c;
return cell;
}
}
return NULL;
}
int int
gnc_cellblock_changed (CellBlock *cursor, gboolean include_conditional) gnc_cellblock_changed (CellBlock *cursor, gboolean include_conditional)
{ {

View File

@ -19,19 +19,24 @@
* Boston, MA 02110-1301, USA gnu@gnu.org * * Boston, MA 02110-1301, USA gnu@gnu.org *
* * * *
\********************************************************************/ \********************************************************************/
/** @addtogroup GUI
/* * @{
* FILE: */
* cellblock.h /** @addtogroup Register Registers, Ledgers and Journals
* @{
*/
/** @addtogroup RegisterCore Register Core
* @{
*/
/** @file cellblock.h
* @brief Declarations for the CellBlock object
* @author Copyright (c) 1988 Linas Vepstas
* @author Copyright (c) 2000-2001 Dave Peticolas <dave@krondo.com>
* *
* FUNCTION: * @details
* The CellBlock struct is a rectangular grid of cells that * The CellBlock struct is a rectangular grid of cells that
* define an arrangement of cells. It is typically used to * define an arrangement of cells. It is typically used to
* define a virtual cursor within a larger table of cells. * define a virtual cursor within a larger table of cells.
*
* HISTORY:
* Copyright (c) 1988 Linas Vepstas
* Copyright (c) 2000-2001 Dave Peticolas <dave@krondo.com>
*/ */
#ifndef XACC_CELL_BLOCK_H #ifndef XACC_CELL_BLOCK_H
@ -66,6 +71,25 @@ void gnc_cellblock_set_cell (CellBlock *cellblock,
BasicCell * gnc_cellblock_get_cell (CellBlock *cellblock, BasicCell * gnc_cellblock_get_cell (CellBlock *cellblock,
int row, int col); int row, int col);
/** Searches by name for a particular cell in a CellBlock. Parameters @row
* and/or @col may be @c NULL.
*
* @param cellblock a ::CellBlock to search
*
* @param cell_name the name of the cell to find
*
* @param row pointer for returning the row in which the cell was
* found, or @c NULL
*
* @param col pointer for returning the column in which the cell was
* found, or @c NULL
*
* @return the matching cell, or @c NULL
*/
BasicCell * gnc_cellblock_get_cell_by_name(CellBlock *cellblock,
const char *cell_name,
int *row, int *col);
/* Return number of changed cells. */ /* Return number of changed cells. */
int gnc_cellblock_changed (CellBlock *cursor, int gnc_cellblock_changed (CellBlock *cursor,
gboolean include_conditional); gboolean include_conditional);
@ -73,3 +97,6 @@ int gnc_cellblock_changed (CellBlock *cursor,
void gnc_cellblock_clear_changes (CellBlock *cursor); void gnc_cellblock_clear_changes (CellBlock *cursor);
#endif #endif
/** @} */
/** @} */
/** @} */