Work on the register. Incorporate physical and virtual

Location abstractions.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2749 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas
2000-09-02 00:26:15 +00:00
parent c43a842818
commit ae29030ca8
29 changed files with 1566 additions and 1781 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -206,15 +206,19 @@ static GUID copied_leader_guid;
/** static prototypes *****************************************************/
static Split * xaccSRGetTransSplit (SplitRegister *reg,
int phys_row, int phys_col);
PhysicalLocation phys_loc);
static void xaccSRLoadRegEntry (SplitRegister *reg, Split *split);
static gboolean xaccSRSaveRegEntryToSCM (SplitRegister *reg,
SCM trans_scm, SCM split_scm);
static Transaction * xaccSRGetTrans (SplitRegister *reg,
int phys_row, int phys_col);
PhysicalLocation phys_loc);
static Split * xaccSRGetCurrentTransSplit (SplitRegister *reg);
static GList * xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans,
Split *split);
static gboolean xaccSRGetTransSplitVirtLoc (SplitRegister *reg,
Transaction *trans,
Split *trans_split, Split *split,
VirtualCellLocation *vcell_loc);
/** implementations *******************************************************/
@@ -543,8 +547,9 @@ gnc_find_split_in_reg_by_memo(SplitRegister *reg, const char *memo,
{
Split *split;
Transaction *trans;
VirtualCellLocation vcell_loc = { virt_row, virt_col };
split = gnc_table_get_user_data_virtual (table, virt_row, virt_col);
split = gnc_table_get_user_data_virtual (table, vcell_loc);
trans = xaccSplitGetParent(split);
if (trans == last_trans)
@@ -586,8 +591,9 @@ gnc_find_trans_in_reg_by_desc(SplitRegister *reg, const char *description)
{
Split *split;
Transaction *trans;
VirtualCellLocation vcell_loc = { virt_row, virt_col };
split = gnc_table_get_user_data_virtual (table, virt_row, virt_col);
split = gnc_table_get_user_data_virtual (table, vcell_loc);
trans = xaccSplitGetParent(split);
if (trans == last_trans)
@@ -625,12 +631,9 @@ gnc_find_trans_in_reg_by_desc(SplitRegister *reg, const char *description)
*/
static void
LedgerMoveCursor (Table *table,
int *p_new_phys_row,
int *p_new_phys_col)
LedgerMoveCursor (Table *table, PhysicalLocation *p_new_phys_loc)
{
int new_phys_row = *p_new_phys_row;
int new_phys_col = *p_new_phys_col;
PhysicalLocation new_phys_loc = *p_new_phys_loc;
SplitRegister *reg = table->user_data;
SRInfo *info = xaccSRGetInfo(reg);
Transaction *pending_trans = xaccTransLookup(&info->pending_trans_guid);
@@ -645,26 +648,28 @@ LedgerMoveCursor (Table *table,
int phys_col_offset;
gboolean saved;
PINFO ("start callback %d %d \n", new_phys_row, new_phys_col);
PINFO ("start callback %d %d \n",
new_phys_loc.phys_row, new_phys_loc.phys_col);
/* The transaction we are coming from */
trans = xaccSRGetCurrentTrans(reg);
/* The change in physical location */
phys_row_offset = new_phys_row - table->current_cursor_phys_row;
phys_col_offset = new_phys_col - table->current_cursor_phys_col;
phys_row_offset = (new_phys_loc.phys_row -
table->current_cursor_phys_loc.phys_row);
phys_col_offset = (new_phys_loc.phys_col -
table->current_cursor_phys_loc.phys_col);
if (!info->hint_set_by_traverse)
{
/* The transaction where we are moving to */
new_trans = xaccSRGetTrans(reg, new_phys_row, new_phys_col);
new_trans = xaccSRGetTrans(reg, new_phys_loc);
/* The split we are moving to */
new_split = gnc_table_get_user_data_physical(reg->table,
new_phys_row, new_phys_col);
new_split = gnc_table_get_user_data_physical(reg->table, new_phys_loc);
/* The split at the transaction line we are moving to */
trans_split = xaccSRGetTransSplit(reg, new_phys_row, new_phys_col);
trans_split = xaccSRGetTransSplit(reg, new_phys_loc);
}
else
{
@@ -674,16 +679,14 @@ LedgerMoveCursor (Table *table,
}
/* The cell offset we are moving to */
if ((new_phys_row < 0) || (new_phys_col < 0) ||
(new_phys_row >= table->num_phys_rows) ||
(new_phys_col >= table->num_phys_cols))
if (gnc_table_physical_cell_out_of_bounds(table, new_phys_loc))
{
new_cell_row = 0;
new_cell_col = 0;
}
else
{
pcell = gnc_table_get_physical_cell (table, new_phys_row, new_phys_col);
pcell = gnc_table_get_physical_cell (table, new_phys_loc);
new_cell_row = pcell->virt_loc.phys_row_offset;
new_cell_col = pcell->virt_loc.phys_col_offset;
@@ -704,59 +707,59 @@ LedgerMoveCursor (Table *table,
/* redrawing the register can muck everything up */
if (saved) {
int virt_row, virt_col;
VirtualCellLocation vcell_loc;
xaccSRRedrawRegEntry (reg);
/* if the split we were going to is still in the register,
* then it may have moved. Find out where it is now. */
if (xaccSRGetTransSplitRowCol (reg, new_trans, trans_split, new_split,
&virt_row, &virt_col)) {
if (xaccSRGetTransSplitVirtLoc (reg, new_trans, trans_split,
new_split, &vcell_loc))
{
VirtualCell *vcell;
vcell = gnc_table_get_virtual_cell (table, virt_row, virt_col);
vcell = gnc_table_get_virtual_cell (table, vcell_loc);
new_phys_row = vcell->phys_loc.phys_row;
new_phys_col = vcell->phys_loc.phys_col;
new_phys_loc = vcell->phys_loc;
new_phys_row += new_cell_row;
new_phys_col += new_cell_col;
new_phys_loc.phys_row += new_cell_row;
new_phys_loc.phys_col += new_cell_col;
}
/* otherwise, the split is not in the register and we
* have to figure out where to go. We make a guess based
* on the change in physical location that was going to
* happen before the refresh. */
else {
new_phys_row = table->current_cursor_phys_row + phys_row_offset;
new_phys_col = table->current_cursor_phys_col + phys_col_offset;
new_phys_loc = table->current_cursor_phys_loc;
new_phys_loc.phys_row += phys_row_offset;
new_phys_loc.phys_col += phys_col_offset;
}
}
/* just because I'm paranoid doesn't
* mean they're not out to get me! */
if (new_phys_row < reg->num_header_rows)
new_phys_row = reg->num_header_rows;
else if (new_phys_row >= table->num_phys_rows)
new_phys_row = table->num_phys_rows - 1;
if (new_phys_loc.phys_row < reg->num_header_rows)
new_phys_loc.phys_row = reg->num_header_rows;
else if (new_phys_loc.phys_row >= table->num_phys_rows)
new_phys_loc.phys_row = table->num_phys_rows - 1;
if (new_phys_col < 0)
new_phys_col = 0;
else if (new_phys_col >= table->num_phys_cols)
new_phys_col = table->num_phys_cols - 1;
if (new_phys_loc.phys_col < 0)
new_phys_loc.phys_col = 0;
else if (new_phys_loc.phys_col >= table->num_phys_cols)
new_phys_loc.phys_col = table->num_phys_cols - 1;
gnc_table_find_valid_cell_horiz(table, &new_phys_row, &new_phys_col,
info->exact_traversal);
gnc_table_find_valid_cell_horiz(table, &new_phys_loc, info->exact_traversal);
*p_new_phys_row = new_phys_row;
*p_new_phys_col = new_phys_col;
*p_new_phys_loc = new_phys_loc;
PINFO ("after redraw %d %d \n",
new_phys_row, new_phys_col);
new_phys_loc.phys_row, new_phys_loc.phys_col);
reg->cursor_phys_row = new_phys_row;
reg->cursor_phys_row = new_phys_loc.phys_row;
pcell = gnc_table_get_physical_cell (table, new_phys_row, new_phys_col);
reg->cursor_virt_row = pcell->virt_loc.virt_row;
pcell = gnc_table_get_physical_cell (table, new_phys_loc);
reg->cursor_virt_row = pcell->virt_loc.vcell_loc.virt_row;
/* if auto-expansion is enabled, we need to redraw the register
* to expand out the splits at the new location. We use the
@@ -765,23 +768,21 @@ LedgerMoveCursor (Table *table,
if ((REG_SINGLE_DYNAMIC == reg->style) ||
(REG_DOUBLE_DYNAMIC == reg->style))
{
new_trans = xaccSRGetTrans(reg, new_phys_row, new_phys_col);
new_trans = xaccSRGetTrans(reg, new_phys_loc);
info->cursor_hint_trans = new_trans;
trans_split = xaccSRGetTransSplit(reg, new_phys_row, new_phys_col);
trans_split = xaccSRGetTransSplit(reg, new_phys_loc);
info->cursor_hint_trans_split = trans_split;
new_split = gnc_table_get_user_data_physical (reg->table,
new_phys_row, new_phys_col);
new_split = gnc_table_get_user_data_physical (reg->table, new_phys_loc);
info->cursor_hint_split = new_split;
info->cursor_hint_phys_col = new_phys_col;
info->cursor_hint_phys_col = new_phys_loc.phys_col;
xaccRegisterRefresh (reg);
/* indicate what row we should go to */
*p_new_phys_row = table->current_cursor_phys_row;
*p_new_phys_col = table->current_cursor_phys_col;
*p_new_phys_loc = table->current_cursor_phys_loc;
info->cursor_hint_trans = xaccSRGetCurrentTrans (reg);
info->cursor_hint_split = xaccSRGetCurrentSplit (reg);
@@ -789,7 +790,8 @@ LedgerMoveCursor (Table *table,
info->cursor_hint_phys_col = -1;
PINFO ("after dynamic %d %d stored val %d\n",
*p_new_phys_row, *p_new_phys_col, reg->cursor_phys_row);
p_new_phys_loc->phys_row, p_new_phys_loc->phys_col,
reg->cursor_phys_row);
}
else
{
@@ -806,19 +808,18 @@ LedgerMoveCursor (Table *table,
* if so, performs it. This should only be called by LedgerTraverse. */
static void
LedgerAutoCompletion(SplitRegister *reg, gncTableTraversalDir dir,
int *p_new_phys_row, int *p_new_phys_col)
PhysicalLocation *p_new_phys_loc)
{
SRInfo *info = xaccSRGetInfo(reg);
Split *blank_split = xaccSplitLookup(&info->blank_split_guid);
Transaction *pending_trans = xaccTransLookup(&info->pending_trans_guid);
PhysicalLocation new_phys_loc;
CursorType cursor_type;
CellType cell_type;
Transaction *trans;
guint32 changed;
double amount;
Split *split;
int new_row;
int new_col;
/* auto-completion is only triggered by a tab out */
if (dir != GNC_TABLE_TRAVERSE_RIGHT)
@@ -829,8 +830,8 @@ LedgerAutoCompletion(SplitRegister *reg, gncTableTraversalDir dir,
if (trans == NULL)
return;
cursor_type = xaccSplitRegisterGetCursorType(reg);
cell_type = xaccSplitRegisterGetCellType(reg);
cursor_type = xaccSplitRegisterGetCurrentCursorType(reg);
cell_type = xaccSplitRegisterGetCurrentCellType(reg);
changed = xaccSplitRegisterGetChangeFlag(reg);
switch (cursor_type)
@@ -933,11 +934,8 @@ LedgerAutoCompletion(SplitRegister *reg, gncTableTraversalDir dir,
amount = xaccSplitGetShareAmount (blank_split);
cell_type = (amount >= 0) ? DEBT_CELL : CRED_CELL;
if (xaccSplitRegisterGetCellRowCol (reg, cell_type, &new_row, &new_col))
{
*p_new_phys_row = new_row;
*p_new_phys_col = new_col;
}
if (xaccSplitRegisterGetCellPhysLoc (reg, cell_type, &new_phys_loc))
*p_new_phys_loc = new_phys_loc;
}
break;
@@ -970,7 +968,7 @@ LedgerAutoCompletion(SplitRegister *reg, gncTableTraversalDir dir,
/* if there is no price field, only auto-complete from splits with
* a unit share price. */
unit_price = !xaccSplitRegisterGetCellRowCol(reg, PRIC_CELL, NULL, NULL);
unit_price = !xaccSplitRegisterGetCellPhysLoc(reg, PRIC_CELL, NULL);
/* find a split to auto-complete on */
if (info->default_source_account != NULL)
@@ -1016,11 +1014,8 @@ LedgerAutoCompletion(SplitRegister *reg, gncTableTraversalDir dir,
amount = xaccSplitGetShareAmount (auto_split);
cell_type = (amount < 0) ? NDEBT_CELL : NCRED_CELL;
if (xaccSplitRegisterGetCellRowCol (reg, cell_type, &new_row, &new_col))
{
*p_new_phys_row = new_row;
*p_new_phys_col = new_col;
}
if (xaccSplitRegisterGetCellPhysLoc (reg, cell_type, &new_phys_loc))
*p_new_phys_loc = new_phys_loc;
}
break;
@@ -1039,17 +1034,15 @@ LedgerAutoCompletion(SplitRegister *reg, gncTableTraversalDir dir,
static void
LedgerTraverse (Table *table,
int *p_new_phys_row,
int *p_new_phys_col,
PhysicalLocation *p_new_phys_loc,
gncTableTraversalDir dir)
{
SplitRegister *reg = table->user_data;
SRInfo *info = xaccSRGetInfo(reg);
Transaction *pending_trans = xaccTransLookup(&info->pending_trans_guid);
PhysicalLocation phys_loc = *p_new_phys_loc;
VirtualCellLocation vcell_loc;
Transaction *trans, *new_trans;
int phys_row = *p_new_phys_row;
int phys_col = *p_new_phys_col;
int virt_row, virt_col;
GNCVerifyResult result;
guint32 changed;
Split *split;
@@ -1065,39 +1058,35 @@ LedgerTraverse (Table *table,
changed = xaccSplitRegisterGetChangeFlag(reg);
if (!changed && (pending_trans != trans))
{
if (gnc_table_physical_cell_valid(table, phys_row, phys_col, FALSE))
if (gnc_table_physical_cell_valid(table, phys_loc, FALSE))
return;
if (phys_row < reg->num_header_rows)
phys_row = reg->num_header_rows;
if (phys_row >= table->num_phys_rows)
phys_row = table->num_phys_rows - 1;
if (phys_loc.phys_row < reg->num_header_rows)
phys_loc.phys_row = reg->num_header_rows;
if (phys_loc.phys_row >= table->num_phys_rows)
phys_loc.phys_row = table->num_phys_rows - 1;
gnc_table_find_valid_cell_horiz(table, &phys_row, &phys_col,
info->exact_traversal);
gnc_table_find_valid_cell_horiz(table, &phys_loc, info->exact_traversal);
*p_new_phys_row = phys_row;
*p_new_phys_col = phys_col;
*p_new_phys_loc = phys_loc;
return;
}
/* Now see if we are changing cursors. If not, we may be able to
* auto-complete. */
if ((phys_row >= 0) && (phys_col >= 0) &&
(phys_row < table->num_phys_rows) && (phys_col < table->num_phys_cols))
if (!gnc_table_physical_cell_out_of_bounds (table, phys_loc))
{
PhysicalCell *pcell;
pcell = gnc_table_get_physical_cell (table, phys_row, phys_col);
pcell = gnc_table_get_physical_cell (table, phys_loc);
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
vcell_loc = pcell->virt_loc.vcell_loc;
if ((virt_row == table->current_cursor_virt_row) &&
(virt_col == table->current_cursor_virt_col))
if ((vcell_loc.virt_row == table->current_cursor_virt_loc.virt_row) &&
(vcell_loc.virt_col == table->current_cursor_virt_loc.virt_col))
{
LedgerAutoCompletion(reg, dir, p_new_phys_row, p_new_phys_col);
LedgerAutoCompletion(reg, dir, p_new_phys_loc);
return;
}
}
@@ -1120,25 +1109,22 @@ LedgerTraverse (Table *table,
}
/* Check for going off the end */
if (phys_row < reg->num_header_rows)
if (phys_loc.phys_row < reg->num_header_rows)
{
phys_row = reg->num_header_rows;
gnc_table_find_valid_cell_horiz(table, &phys_row, &phys_col,
info->exact_traversal);
phys_loc.phys_row = reg->num_header_rows;
gnc_table_find_valid_cell_horiz(table, &phys_loc, info->exact_traversal);
}
if (phys_row >= table->num_phys_rows)
if (phys_loc.phys_row >= table->num_phys_rows)
{
phys_row = table->num_phys_rows - 1;
gnc_table_find_valid_cell_horiz(table, &phys_row, &phys_col,
info->exact_traversal);
phys_loc.phys_row = table->num_phys_rows - 1;
gnc_table_find_valid_cell_horiz(table, &phys_loc, info->exact_traversal);
}
/* Same transaction, no problem */
new_trans = xaccSRGetTrans(reg, phys_row, phys_col);
new_trans = xaccSRGetTrans(reg, phys_loc);
if (trans == new_trans)
{
*p_new_phys_row = phys_row;
*p_new_phys_col = phys_col;
*p_new_phys_loc = phys_loc;
return;
}
@@ -1156,35 +1142,32 @@ LedgerTraverse (Table *table,
Split *new_split;
Split *trans_split;
new_split = gnc_table_get_user_data_physical(reg->table,
phys_row, phys_col);
trans_split = xaccSRGetTransSplit(reg, phys_row, phys_col);
new_split = gnc_table_get_user_data_physical(reg->table, phys_loc);
trans_split = xaccSRGetTransSplit(reg, phys_loc);
xaccSRCancelCursorTransChanges(reg);
if (xaccSRGetTransSplitRowCol (reg, new_trans, trans_split, new_split,
&virt_row, &virt_col))
if (xaccSRGetTransSplitVirtLoc (reg, new_trans, trans_split,
new_split, &vcell_loc))
{
VirtualCell *vcell;
vcell = gnc_table_get_virtual_cell (table, virt_row, virt_col);
vcell = gnc_table_get_virtual_cell (table, vcell_loc);
phys_row = vcell->phys_loc.phys_row;
phys_loc.phys_row = vcell->phys_loc.phys_row;
}
if (phys_row >= table->num_phys_rows)
phys_row = table->num_phys_rows - 1;
if (phys_col >= table->num_phys_cols)
phys_col = table->num_phys_cols - 1;
if (phys_loc.phys_row >= table->num_phys_rows)
phys_loc.phys_row = table->num_phys_rows - 1;
if (phys_loc.phys_col >= table->num_phys_cols)
phys_loc.phys_col = table->num_phys_cols - 1;
*p_new_phys_row = phys_row;
*p_new_phys_col = phys_col;
*p_new_phys_loc = phys_loc;
}
break;
case GNC_VERIFY_CANCEL:
*p_new_phys_row = table->current_cursor_phys_row;
*p_new_phys_col = table->current_cursor_phys_col;
*p_new_phys_loc = table->current_cursor_phys_loc;
break;
default:
break;
@@ -1251,35 +1234,34 @@ LedgerDestroy (SplitRegister *reg)
/* ======================================================== */
static Transaction *
xaccSRGetTrans (SplitRegister *reg, int phys_row, int phys_col)
xaccSRGetTrans (SplitRegister *reg, PhysicalLocation phys_loc)
{
Split *split;
PhysicalCell *pcell;
int virt_row, virt_col;
VirtualCellLocation vcell_loc;
if (reg == NULL)
return NULL;
pcell = gnc_table_get_physical_cell (reg->table, phys_row, phys_col);
pcell = gnc_table_get_physical_cell (reg->table, phys_loc);
if (pcell == NULL)
return NULL;
split = gnc_table_get_user_data_physical (reg->table, phys_row, phys_col);
split = gnc_table_get_user_data_physical (reg->table, phys_loc);
if (split != NULL)
return xaccSplitGetParent(split);
/* Split is blank. Assume it is the blank split of a multi-line
* transaction. Go back one row to find a split in the transaction. */
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
vcell_loc = pcell->virt_loc.vcell_loc;
virt_row --;
if ((0 > virt_row) || (0 > virt_col)) {
vcell_loc.virt_row --;
if ((0 > vcell_loc.virt_row) || (0 > vcell_loc.virt_col)) {
PERR ("bad row \n");
return NULL;
}
split = gnc_table_get_user_data_virtual (reg->table, virt_row, virt_col);
split = gnc_table_get_user_data_virtual (reg->table, vcell_loc);
if (split == NULL) {
PERR ("no parent \n");
return NULL;
@@ -1291,32 +1273,31 @@ xaccSRGetTrans (SplitRegister *reg, int phys_row, int phys_col)
/* ======================================================== */
static Split *
xaccSRGetTransSplit (SplitRegister *reg, int phys_row, int phys_col)
xaccSRGetTransSplit (SplitRegister *reg, PhysicalLocation phys_loc)
{
CursorType cursor_type;
int virt_row, virt_col;
VirtualCellLocation vcell_loc;
PhysicalCell *pcell;
if (reg == NULL)
return NULL;
pcell = gnc_table_get_physical_cell (reg->table, phys_row, phys_col);
pcell = gnc_table_get_physical_cell (reg->table, phys_loc);
if (pcell == NULL)
return NULL;
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
vcell_loc = pcell->virt_loc.vcell_loc;
while (1)
while (TRUE)
{
cursor_type = xaccSplitRegisterGetCursorTypeRowCol (reg,
virt_row, virt_col);
cursor_type = xaccSplitRegisterGetCursorType (reg, vcell_loc);
if (cursor_type == CURSOR_TRANS)
return gnc_table_get_user_data_virtual (reg->table, virt_row, virt_col);
return gnc_table_get_user_data_virtual (reg->table, vcell_loc);
virt_row --;
vcell_loc.virt_row --;
if ((0 > virt_row) || (0 > virt_col)) {
if ((0 > vcell_loc.virt_row) || (0 > vcell_loc.virt_col)) {
PERR ("bad row \n");
return NULL;
}
@@ -1331,43 +1312,41 @@ xaccSRGetCurrentTransSplit (SplitRegister *reg)
Split *split;
PhysicalCell *pcell;
CursorType cursor_type;
int phys_row, phys_col;
int virt_row, virt_col;
PhysicalLocation phys_loc;
VirtualCellLocation vcell_loc;
if (reg == NULL)
return NULL;
split = xaccSRGetCurrentSplit (reg);
cursor_type = xaccSplitRegisterGetCursorType (reg);
cursor_type = xaccSplitRegisterGetCurrentCursorType (reg);
if (cursor_type == CURSOR_TRANS)
return split;
/* Split is not associated with a transaction cursor. Assume it is a
* split of a multi-line transaction. Go back until we find one that
* is on a transaction cursor. */
phys_row = reg->table->current_cursor_phys_row;
phys_col = reg->table->current_cursor_phys_col;
phys_loc = reg->table->current_cursor_phys_loc;
pcell = gnc_table_get_physical_cell (reg->table, phys_row, phys_col);
pcell = gnc_table_get_physical_cell (reg->table, phys_loc);
if (pcell == NULL)
return NULL;
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
vcell_loc = pcell->virt_loc.vcell_loc;
while (1)
while (TRUE)
{
virt_row --;
vcell_loc.virt_row--;
if ((0 > virt_row) || (0 > virt_col)) {
if ((0 > vcell_loc.virt_row) || (0 > vcell_loc.virt_col)) {
PERR ("bad row \n");
return NULL;
}
cursor_type = xaccSplitRegisterGetCursorTypeRowCol (reg,
virt_row, virt_col);
cursor_type = xaccSplitRegisterGetCursorType (reg, vcell_loc);
if (cursor_type == CURSOR_TRANS)
return gnc_table_get_user_data_virtual (reg->table, virt_row, virt_col);
return gnc_table_get_user_data_virtual (reg->table, vcell_loc);
}
}
@@ -1378,8 +1357,8 @@ xaccSRGetCurrentTrans (SplitRegister *reg)
{
Split *split;
PhysicalCell *pcell;
int phys_row, phys_col;
int virt_row, virt_col;
PhysicalLocation phys_loc;
VirtualCellLocation vcell_loc;
if (reg == NULL)
return NULL;
@@ -1390,23 +1369,21 @@ xaccSRGetCurrentTrans (SplitRegister *reg)
/* Split is blank. Assume it is the blank split of a multi-line
* transaction. Go back one row to find a split in the transaction. */
phys_row = reg->table->current_cursor_phys_row;
phys_col = reg->table->current_cursor_phys_col;
phys_loc = reg->table->current_cursor_phys_loc;
pcell = gnc_table_get_physical_cell (reg->table, phys_row, phys_col);
pcell = gnc_table_get_physical_cell (reg->table, phys_loc);
if (pcell == NULL)
return NULL;
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
vcell_loc = pcell->virt_loc.vcell_loc;
virt_row --;
if ((0 > virt_row) || (0 > virt_col)) {
vcell_loc.virt_row --;
if ((0 > vcell_loc.virt_row) || (0 > vcell_loc.virt_col)) {
PERR ("bad row \n");
return NULL;
}
split = gnc_table_get_user_data_virtual (reg->table, virt_row, virt_col);
split = gnc_table_get_user_data_virtual (reg->table, vcell_loc);
return xaccSplitGetParent(split);
}
@@ -1441,8 +1418,8 @@ xaccSRGetBlankSplit (SplitRegister *reg)
/* ======================================================== */
gboolean
xaccSRGetSplitRowCol (SplitRegister *reg, Split *split,
int *virt_row, int *virt_col)
xaccSRGetSplitVirtLoc (SplitRegister *reg, Split *split,
VirtualCellLocation *vcell_loc)
{
Table *table = reg->table;
int v_row, v_col;
@@ -1451,14 +1428,13 @@ xaccSRGetSplitRowCol (SplitRegister *reg, Split *split,
for (v_row = 1; v_row < table->num_virt_rows; v_row++)
for (v_col = 0; v_col < table->num_virt_cols; v_col++)
{
s = gnc_table_get_user_data_virtual (table, v_row, v_col);
VirtualCellLocation vc_loc = { v_row, v_col };
if (s == split)
s = gnc_table_get_user_data_virtual (table, vc_loc);
if ((s == split) && (vcell_loc != NULL))
{
if (virt_row != NULL)
*virt_row = v_row;
if (virt_col != NULL)
*virt_col = v_col;
*vcell_loc = vc_loc;
return TRUE;
}
@@ -1469,10 +1445,10 @@ xaccSRGetSplitRowCol (SplitRegister *reg, Split *split,
/* ======================================================== */
gboolean
xaccSRGetTransSplitRowCol (SplitRegister *reg, Transaction *trans,
Split *trans_split, Split *split,
int *virt_row, int *virt_col)
static gboolean
xaccSRGetTransSplitVirtLoc (SplitRegister *reg, Transaction *trans,
Split *trans_split, Split *split,
VirtualCellLocation *vcell_loc)
{
Table *table = reg->table;
gboolean found_trans = FALSE;
@@ -1486,10 +1462,12 @@ xaccSRGetTransSplitRowCol (SplitRegister *reg, Transaction *trans,
for (v_row = 1; v_row < table->num_virt_rows; v_row++)
for (v_col = 0; v_col < table->num_virt_cols; v_col++)
{
s = gnc_table_get_user_data_virtual (table, v_row, v_col);
VirtualCellLocation vc_loc = { v_row, v_col };
s = gnc_table_get_user_data_virtual (table, vc_loc);
t = xaccSplitGetParent(s);
cursor_type = xaccSplitRegisterGetCursorTypeRowCol(reg, v_row, v_col);
cursor_type = xaccSplitRegisterGetCursorType(reg, vc_loc);
if (t == trans)
found_trans = TRUE;
@@ -1499,20 +1477,16 @@ xaccSRGetTransSplitRowCol (SplitRegister *reg, Transaction *trans,
if (found_trans && (s == split))
{
if (virt_row != NULL)
*virt_row = v_row;
if (virt_col != NULL)
*virt_col = v_col;
if (vcell_loc != NULL)
*vcell_loc = vc_loc;
found_something = TRUE;
}
if (found_trans_split && (s == split))
{
if (virt_row != NULL)
*virt_row = v_row;
if (virt_col != NULL)
*virt_col = v_col;
if (vcell_loc != NULL)
*vcell_loc = vc_loc;
return TRUE;
}
@@ -1543,7 +1517,7 @@ xaccSRDuplicateCurrent (SplitRegister *reg)
if (trans == NULL)
return NULL;
cursor_type = xaccSplitRegisterGetCursorType(reg);
cursor_type = xaccSplitRegisterGetCurrentCursorType(reg);
/* Can't do anything with this. */
if (cursor_type == CURSOR_NONE)
@@ -1666,7 +1640,7 @@ xaccSRCopyCurrent (SplitRegister *reg)
if (trans == NULL)
return;
cursor_type = xaccSplitRegisterGetCursorType(reg);
cursor_type = xaccSplitRegisterGetCurrentCursorType(reg);
/* Can't do anything with this. */
if (cursor_type == CURSOR_NONE)
@@ -1754,7 +1728,7 @@ xaccSRCutCurrent (SplitRegister *reg)
if (trans == NULL)
return;
cursor_type = xaccSplitRegisterGetCursorType(reg);
cursor_type = xaccSplitRegisterGetCurrentCursorType(reg);
/* Can't do anything with this. */
if (cursor_type == CURSOR_NONE)
@@ -1803,7 +1777,7 @@ xaccSRPasteCurrent (SplitRegister *reg)
if (trans == NULL)
return;
cursor_type = xaccSplitRegisterGetCursorType(reg);
cursor_type = xaccSplitRegisterGetCurrentCursorType(reg);
/* Can't do anything with this. */
if (cursor_type == CURSOR_NONE)
@@ -2085,8 +2059,12 @@ xaccSRCancelCursorSplitChanges (SplitRegister *reg)
{
Split * split;
guint32 changed;
int row = reg->table->current_cursor_phys_row;
int col = reg->table->current_cursor_phys_col;
PhysicalLocation phys_loc;
if (reg == NULL)
return;
phys_loc = reg->table->current_cursor_phys_loc;
changed = xaccSplitRegisterGetChangeFlag(reg);
if (!changed)
@@ -2098,8 +2076,8 @@ xaccSRCancelCursorSplitChanges (SplitRegister *reg)
xaccSRLoadRegEntry(reg, split);
xaccSplitRegisterClearChangeFlag(reg);
if (gnc_table_find_valid_cell_horiz(reg->table, &row, &col, FALSE))
gnc_table_move_cursor_gui(reg->table, row, col);
if (gnc_table_find_valid_cell_horiz(reg->table, &phys_loc, FALSE))
gnc_table_move_cursor_gui(reg->table, phys_loc);
gnc_table_refresh_gui(reg->table);
}
@@ -3018,9 +2996,7 @@ xaccSRCountRows (SplitRegister *reg,
save_cursor_virt_row = reg->cursor_virt_row;
/* save the current cell row offset */
pcell = gnc_table_get_physical_cell (table,
table->current_cursor_phys_row,
table->current_cursor_phys_col);
pcell = gnc_table_get_physical_cell (table, table->current_cursor_phys_loc);
if (pcell)
save_cell_row = pcell->virt_loc.phys_row_offset;
if (save_cell_row < 0)
@@ -3301,12 +3277,13 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
gboolean multi_line;
gboolean dynamic;
VirtualCellLocation vcell_loc;
PhysicalLocation phys_loc;
SplitRegisterType type;
SplitRegisterStyle style;
guint32 changed;
int save_phys_col;
int phys_row;
int vrow;
int i;
xaccSplitRegisterConfigColors (reg);
@@ -3335,11 +3312,10 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
multi_line = (REG_MULTI_LINE == style);
dynamic = ((REG_SINGLE_DYNAMIC == style) || (REG_DOUBLE_DYNAMIC == style));
if ((REG_SINGLE_LINE == style) ||
(REG_SINGLE_DYNAMIC == style)) {
(REG_SINGLE_DYNAMIC == style))
lead_cursor = reg->single_cursor;
} else {
else
lead_cursor = reg->double_cursor;
}
/* figure out where we are going to. */
find_trans = info->cursor_hint_trans;
@@ -3347,7 +3323,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
find_trans_split = info->cursor_hint_trans_split;
if (info->cursor_hint_phys_col < 0)
save_phys_col = table->current_cursor_phys_col;
save_phys_col = table->current_cursor_phys_loc.phys_col;
else
save_phys_col = info->cursor_hint_phys_col;
@@ -3378,22 +3354,29 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
/* disable move callback -- we don't want the cascade of
* callbacks while we are fiddling with loading the register */
table->move_cursor = NULL;
gnc_table_move_cursor_gui (table, -1, -1);
phys_loc.phys_row = -1;
phys_loc.phys_col = -1;
gnc_table_move_cursor_gui (table, phys_loc);
/* resize the table to the sizes we just counted above */
/* num_virt_cols is always one. */
gnc_table_set_size (table, reg->num_phys_rows, reg->num_cols,
gnc_table_set_size (table,
reg->num_phys_rows, reg->num_cols,
reg->num_virt_rows, 1);
/* make sure that the header is loaded */
gnc_table_set_cursor (table, reg->header, 0, 0, 0, 0);
phys_loc.phys_row = 0;
phys_loc.phys_col = 0;
vcell_loc.virt_row = 0;
vcell_loc.virt_col = 0;
gnc_table_set_cursor (table, reg->header, phys_loc, vcell_loc);
PINFO ("load register of %d phys rows ----------- \n", reg->num_phys_rows);
/* populate the table */
i=0;
vrow = 1; /* header is vrow zero */
phys_row = reg->header->numRows;
vcell_loc.virt_row = 1; /* header is vrow zero */
phys_loc.phys_row = reg->header->numRows;
if (slist)
split = slist[0];
@@ -3410,7 +3393,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
Transaction *trans;
gboolean do_expand;
PINFO ("load trans %d at phys row %d \n", i, phys_row);
PINFO ("load trans %d at phys row %d \n", i, phys_loc.phys_row);
trans = xaccSplitGetParent (split);
@@ -3422,8 +3405,8 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
do_expand = do_expand || (trans == find_trans);
if (dynamic && !found_trans && !found_trans_split &&
(vrow == reg->cursor_virt_row)) {
reg->cursor_phys_row = phys_row;
(vcell_loc.virt_row == reg->cursor_virt_row)) {
reg->cursor_phys_row = phys_loc.phys_row;
do_expand = TRUE;
}
@@ -3439,11 +3422,11 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
int j = 0;
gnc_table_set_cursor (table, reg->trans_cursor,
phys_row, 0, vrow, 0);
gnc_table_move_cursor (table, phys_row, 0);
phys_loc, vcell_loc);
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, split);
vrow ++;
phys_row += reg->trans_cursor->numRows;
vcell_loc.virt_row ++;
phys_loc.phys_row += reg->trans_cursor->numRows;
/* loop over all of the splits in the transaction. The
* do..while will automatically put a blank (null) split
@@ -3454,13 +3437,13 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
if (secondary != split) {
gnc_table_set_cursor (table, reg->split_cursor,
phys_row, 0, vrow, 0);
gnc_table_move_cursor (table, phys_row, 0);
phys_loc, vcell_loc);
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, secondary);
PINFO ("load split %d at phys row %d addr=%p \n",
j, phys_row, secondary);
vrow ++;
phys_row += reg->split_cursor->numRows;
j, phys_loc.phys_row, secondary);
vcell_loc.virt_row ++;
phys_loc.phys_row += reg->split_cursor->numRows;
}
j++;
@@ -3468,11 +3451,11 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
} else {
/* the simple case ... */
gnc_table_set_cursor (table, lead_cursor, phys_row, 0, vrow, 0);
gnc_table_move_cursor (table, phys_row, 0);
gnc_table_set_cursor (table, lead_cursor, phys_loc, vcell_loc);
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, split);
vrow ++;
phys_row += lead_cursor->numRows;
vcell_loc.virt_row ++;
phys_loc.phys_row += lead_cursor->numRows;
}
}
else {
@@ -3491,11 +3474,11 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
if (multi_line || (dynamic && info->blank_split_edited)) {
/* do the transaction row of the blank split */
gnc_table_set_cursor (table, reg->trans_cursor, phys_row, 0, vrow, 0);
gnc_table_move_cursor (table, phys_row, 0);
gnc_table_set_cursor (table, reg->trans_cursor, phys_loc, vcell_loc);
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, split);
vrow ++;
phys_row += reg->trans_cursor->numRows;
vcell_loc.virt_row ++;
phys_loc.phys_row += reg->trans_cursor->numRows;
if (multi_line || (dynamic && on_blank_split)) {
Transaction *trans;
@@ -3509,35 +3492,34 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
if (secondary != split) {
gnc_table_set_cursor (table, reg->split_cursor,
phys_row, 0, vrow, 0);
gnc_table_move_cursor (table, phys_row, 0);
phys_loc, vcell_loc);
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, secondary);
PINFO ("load split %d at phys row %d addr=%p \n",
j, phys_row, secondary);
vrow ++;
phys_row += reg->split_cursor->numRows;
j, phys_loc.phys_row, secondary);
vcell_loc.virt_row ++;
phys_loc.phys_row += reg->split_cursor->numRows;
}
j++;
} while (secondary);
}
} else {
gnc_table_set_cursor (table, lead_cursor, phys_row, 0, vrow, 0);
gnc_table_move_cursor (table, phys_row, 0);
gnc_table_set_cursor (table, lead_cursor, phys_loc, vcell_loc);
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, split);
vrow ++;
phys_row += lead_cursor->numRows;
vcell_loc.virt_row ++;
phys_loc.phys_row += lead_cursor->numRows;
}
/* restore the cursor to its rightful position */
{
int row = reg->cursor_phys_row;
int col = save_phys_col;
PhysicalLocation p_loc = { reg->cursor_phys_row, save_phys_col };
if (gnc_table_find_valid_cell_horiz(table, &row, &col, FALSE))
if (gnc_table_find_valid_cell_horiz(table, &p_loc, FALSE))
{
gnc_table_move_cursor_gui(table, row, col);
reg->cursor_phys_row = row;
gnc_table_move_cursor_gui(table, p_loc);
reg->cursor_phys_row = p_loc.phys_row;
if (reg_buffer != NULL)
{

View File

@@ -21,99 +21,6 @@
* *
\********************************************************************/
/*
* FILE:
* SplitLedger.h
*
* FUNCTION:
* Definitions for a number of functions that interface
* between the transaction engine, and the register GUI.
*
* The xaccSRSetData() method sets the user data and callback
* hooks for the register.
*
* The xaccSRSetAccountSeparator() method sets the character
* used to separate accounts in fully-qualified names.
*
* The xaccSRSetReverseBalanceCallback() method sets up
* a callback used to determine whether split balances
* should be reversed.
*
* The xaccSRGetCurrentTrans() method returns the transaction
* which is the parent of the current split (see below).
*
* The xaccSRGetCurrentSplit() method returns the split at which
* the cursor is currently located.
*
* The xaccSRGetBlankSplit() method returns the blank split or
* NULL if there is none.
*
* The xaccSRGetSplitRowCol() method searches the split register for
* the given split. If found, it returns TRUE and the virt_row
* and virt_col arguments are set to the location of the split.
* Otherwise, the method returns FALSE.
*
* The xaccSRGetTransSplitRowCol() method works as above, but searches
* first for the first split (the transaction split) and then the
* next split, and returns the location of the second split.
*
* The xaccSRDuplicateCurrent() method duplicates either the current
* transaction or the current split depending on the register mode
* and cursor position. Returns the split just created, or the
* 'main' split of the transaction just created, or NULL if
* nothing happened.
*
* The xaccSRDeleteCurrentSplit() method deletes the split associated
* with the current cursor, if both are non-NULL. If successful, all
* affected account windows are refreshed. Deleting the blank split
* just clears the cursor values.
*
* The xaccSRDeleteCurrentTrans() method deletes the transaction
* associated with the current cursor, if both are non-NULL.
* If successful, all affected account windows are refreshed.
*
* The xaccSREmptyCurrentTrans() method deletes the non-transaction
* splits associated wih the current cursor, if both are non-NULL.
* If successful, all affected account windows are refreshed.
*
* The xaccSRCancelCursorSplitChanges() method cancels any changes made
* to the current cursor, reloads the cursor from the engine, reloads
* the table from the cursor, and updates the GUI. The change flags
* are cleared.
*
* The xaccSRCancelCursorTransChanges() method cancels any changes made
* to the current pending transaction, reloads the table from the engine,
* and updates the GUI. The change flags are cleared.
*
* The xaccSRLoadRegister() subroutine will copy transaction
* information from a list of splits to the rows of the
* register GUI. The third argument, default_source_acc,
* will be used to initialize the source account of a new,
* blank split appended to the tail end of the register.
* This "blank split" is the place where the user can
* edit info to create new tranasactions.
*
* The xaccSRSaveRegEntry() method will copy the contents
* from the cursor to a split. The split/transaction
* that is updated is the one associated with the current
* cursor (register entry) position. If the do_commit flag
* is set, the transaction will also be committed. If it is
* the blank transaction, and the do_commit flag is set,
* a refresh will result in a new blank transaction.
* The method returns TRUE if something was changed.
*
* The xaccSRRedrawRegEntry() method should be called soon
* after the xaccSRSaveRegEntry() method. It checks the
* change flag for the current entry/split, and if it
* has been modified, it causes a redraw of any register
* window that could be affected. That is, it causes
* a rdraw of any window showing this split, or any other
* split that belongs to this same tansaction.
*
* The xaccSRLoadXferCells() method loads (or reloads) the transfer
* cells with appropriate entries.
*/
#ifndef __XACC_SPLIT_LEDGER_H__
#define __XACC_SPLIT_LEDGER_H__
@@ -128,45 +35,115 @@ typedef gncUIWidget (*SRGetParentCallback) (void *user_data);
typedef void (*SRSetHelpCallback) (void *user_data, const char *help_str);
typedef gboolean (*SRReverseBalanceCallback) (Account *account);
/* The xaccSRSetData() method sets the user data and callback
* hooks for the register. */
void xaccSRSetData(SplitRegister *reg, void *user_data,
SRGetParentCallback get_parent,
SRSetHelpCallback set_help);
/* The xaccSRSetAccountSeparator() method sets the character
* used to separate accounts in fully-qualified names. */
void xaccSRSetAccountSeparator(char separator);
/* The xaccSRSetReverseBalanceCallback() method sets up
* a callback used to determine whether split balances
* should be reversed. */
void xaccSRSetReverseBalanceCallback(SRReverseBalanceCallback callback);
/* The xaccSRGetCurrentTrans() method returns the transaction
* which is the parent of the current split (see below). */
Transaction * xaccSRGetCurrentTrans (SplitRegister *reg);
/* The xaccSRGetCurrentSplit() method returns the split at which
* the cursor is currently located. */
Split * xaccSRGetCurrentSplit (SplitRegister *reg);
/* The xaccSRGetBlankSplit() method returns the blank split or
* NULL if there is none. */
Split * xaccSRGetBlankSplit (SplitRegister *reg);
gboolean xaccSRGetSplitRowCol (SplitRegister *reg, Split *split,
int *virt_row, int *virt_col);
gboolean xaccSRGetTransSplitRowCol (SplitRegister *reg, Transaction *trans,
Split *trans_split, Split *split,
int *virt_row, int *virt_col);
/* The xaccSRGetSplitVirtLoc() method searches the split register for
* the given split. If found, it returns TRUE and vcell_loc
* is set to the location of the split. Otherwise, the method
* returns FALSE. */
gboolean xaccSRGetSplitVirtLoc (SplitRegister *reg, Split *split,
VirtualCellLocation *vcell_loc);
/* The xaccSRDuplicateCurrent() method duplicates either the current
* transaction or the current split depending on the register mode
* and cursor position. Returns the split just created, or the
* 'main' split of the transaction just created, or NULL if
* nothing happened. */
Split * xaccSRDuplicateCurrent (SplitRegister *reg);
void xaccSRCopyCurrent (SplitRegister *reg);
void xaccSRCutCurrent (SplitRegister *reg);
void xaccSRPasteCurrent (SplitRegister *reg);
/* The xaccSRDeleteCurrentSplit() method deletes the split associated
* with the current cursor, if both are non-NULL. If successful, all
* affected account windows are refreshed. Deleting the blank split
* just clears the cursor values. */
void xaccSRDeleteCurrentSplit (SplitRegister *reg);
/* The xaccSRDeleteCurrentTrans() method deletes the transaction
* associated with the current cursor, if both are non-NULL.
* If successful, all affected account windows are refreshed. */
void xaccSRDeleteCurrentTrans (SplitRegister *reg);
/* The xaccSREmptyCurrentTrans() method deletes the non-transaction
* splits associated wih the current cursor, if both are non-NULL.
* If successful, all affected account windows are refreshed. */
void xaccSREmptyCurrentTrans (SplitRegister *reg);
/* The xaccSRCancelCursorSplitChanges() method cancels any changes made
* to the current cursor, reloads the cursor from the engine, reloads
* the table from the cursor, and updates the GUI. The change flags
* are cleared. */
void xaccSRCancelCursorSplitChanges (SplitRegister *reg);
/* The xaccSRCancelCursorTransChanges() method cancels any changes made
* to the current pending transaction, reloads the table from the engine,
* and updates the GUI. The change flags are cleared. */
void xaccSRCancelCursorTransChanges (SplitRegister *reg);
/* The xaccSRLoadRegister() subroutine will copy transaction
* information from a list of splits to the rows of the
* register GUI. The third argument, default_source_acc,
* will be used to initialize the source account of a new,
* blank split appended to the tail end of the register.
* This "blank split" is the place where the user can
* edit info to create new tranasactions. */
void xaccSRLoadRegister (SplitRegister *reg, Split **slist,
Account *default_source_acc);
/* The xaccSRSaveRegEntry() method will copy the contents
* from the cursor to a split. The split/transaction
* that is updated is the one associated with the current
* cursor (register entry) position. If the do_commit flag
* is set, the transaction will also be committed. If it is
* the blank transaction, and the do_commit flag is set,
* a refresh will result in a new blank transaction.
* The method returns TRUE if something was changed. */
gboolean xaccSRSaveRegEntry (SplitRegister *reg, gboolean do_commit);
/* The xaccSRRedrawRegEntry() method should be called soon
* after the xaccSRSaveRegEntry() method. It checks the
* change flag for the current entry/split, and if it
* has been modified, it causes a redraw of any register
* window that could be affected. That is, it causes
* a redraw of any window showing this split, or any
* other split that belongs to this same tansaction. */
void xaccSRRedrawRegEntry (SplitRegister *reg);
void xaccSRLoadXferCells (SplitRegister *reg, Account *base_account);
/* The xaccSRLoadXferCells() method loads (or reloads) the transfer
* cells with appropriate entries. */
void xaccSRLoadXferCells (SplitRegister *reg, Account *base_account);
/* The xaccSRHasPendingChanges() method returns TRUE if the register
* has changed cells that have not been committed. */
gboolean xaccSRHasPendingChanges (SplitRegister *reg);
#endif /* __XACC_SPLIT_LEDGER_H__ */

View File

@@ -306,8 +306,8 @@
* integer designating the error encountered. The possible
* values are defined in the "finvar.h" file.
*
* var_store_ptr get_vars(
* void *vp)
* var_store_ptr parser_get_vars(
* void *vp)
*
* This function returns a pointer to the first element of a
* linked list of variable storage structures containing the
@@ -487,7 +487,7 @@ ParseError get_parse_error(parser_env_ptr pe)
} /* get_parse_error */
/* return linked list of named variables which have been defined */
var_store_ptr get_vars(parser_env_ptr pe)
var_store_ptr parser_get_vars(parser_env_ptr pe)
{
if (pe == NULL)
return NULL;

View File

@@ -120,7 +120,7 @@ void exit_parser(parser_env_ptr pe);
/* Line Number: 400 */
ParseError get_parse_error(parser_env_ptr pe);
/* Line Number: 408 */
var_store_ptr get_vars(parser_env_ptr pe);
var_store_ptr parser_get_vars(parser_env_ptr pe);
/* Line Number: 417 */
unsigned delete_var(char *var_name,
parser_env_ptr pe);

View File

@@ -203,6 +203,35 @@ make_predefined_variables (void)
return vars;
}
static void
free_predefined_variables (var_store_ptr vars)
{
var_store_ptr next;
while (vars != NULL)
{
next = vars->next_var;
g_free(vars->value);
vars->value = NULL;
g_free(vars);
vars = next;
}
}
static void
update_variables (var_store_ptr vars)
{
for ( ; vars ; vars = vars->next_var )
{
ParserNum *pnum = vars->value;
if (pnum != NULL)
gnc_exp_parser_set_value (vars->variable_name, pnum->value);
}
}
static void *
trans_numeric(const char *digit_str,
char radix_point,
@@ -322,7 +351,10 @@ gnc_exp_parser_parse (const char * expression, double *value_p,
last_error = get_parse_error (pe);
}
/* fixme: update variables and free predefined variables */
update_variables (vars);
update_variables (parser_get_vars (pe));
free_predefined_variables (vars);
exit_parser (pe);
@@ -332,5 +364,20 @@ gnc_exp_parser_parse (const char * expression, double *value_p,
const char *
gnc_exp_parser_error_string (void)
{
return NULL;
switch (last_error)
{
default:
case PARSER_NO_ERROR:
return NULL;
case UNBALANCED_PARENS:
return PARSER_UNBALANCED_PARENS;
case STACK_OVERFLOW:
return PARSER_STACK_OVERFLOW;
case STACK_UNDERFLOW:
return PARSER_STACK_OVERFLOW;
case UNDEFINED_CHARACTER:
return PARSER_UNDEFINED_CHARACTER;
case NOT_A_VARIABLE:
return PARSER_NOT_A_VARIABLE;
}
}

View File

@@ -218,7 +218,7 @@ void
gnc_register_jump_to_split(RegWindow *regData, Split *split)
{
Transaction *trans;
int vrow, vcol;
VirtualCellLocation vcell_loc;
trans = xaccSplitGetParent(split);
if (trans != NULL)
@@ -228,8 +228,8 @@ gnc_register_jump_to_split(RegWindow *regData, Split *split)
xaccLedgerDisplayRefresh(regData->ledger);
}
if (xaccSRGetSplitRowCol(regData->ledger->ledger, split, &vrow, &vcol))
gnucash_register_goto_virt_row_col(regData->reg, vrow, vcol);
if (xaccSRGetSplitVirtLoc(regData->ledger->ledger, split, &vcell_loc))
gnucash_register_goto_virt_cell(regData->reg, vcell_loc);
}
@@ -939,14 +939,14 @@ gnc_register_jump_to_blank(RegWindow *regData)
{
SplitRegister *sr = regData->ledger->ledger;
Split *blank;
int vrow, vcol;
VirtualCellLocation vcell_loc;
blank = xaccSRGetBlankSplit(sr);
if (blank == NULL)
return;
if (xaccSRGetSplitRowCol(sr, blank, &vrow, &vcol))
gnucash_register_goto_virt_row_col(regData->reg, vrow, vcol);
if (xaccSRGetSplitVirtLoc(sr, blank, &vcell_loc))
gnucash_register_goto_virt_cell(regData->reg, vcell_loc);
}
@@ -2287,7 +2287,7 @@ deleteCB(GtkWidget *widget, gpointer data)
trans = xaccSplitGetParent(split);
style = regData->ledger->ledger->style;
cursor_type = xaccSplitRegisterGetCursorType(regData->ledger->ledger);
cursor_type = xaccSplitRegisterGetCurrentCursorType(regData->ledger->ledger);
/* Deleting the blank split just cancels */
{

View File

@@ -436,6 +436,14 @@
#define TRANSFER_MENU_E_STR_N N_("_Transfer...")
/* Error messages */
#define PARSER_UNBALANCED_PARENS _("Unbalanced parenthesis")
#define PARSER_STACK_OVERFLOW _("Stack overflow")
#define PARSER_STACK_UNDERFLOW _("Stack underflow")
#define PARSER_UNDEFINED_CHARACTER _("Undefined character")
#define PARSER_NOT_A_VARIABLE _("Not a variable")
/** MISC INTERNATIONALIZATION STRINGS: ******************************/
/* phrases */

View File

@@ -25,6 +25,7 @@ noinst_HEADERS = \
pricecell.h \
quickfillcell.h \
recncell.h \
register-common.h \
splitreg.h \
table-allgui.h \
textcell.h

View File

@@ -120,7 +120,7 @@ noinst_LIBRARIES = libgncregister.a
libgncregister_a_SOURCES = QuickFill.c basiccell.c cellblock.c datecell.c numcell.c pricecell.c quickfillcell.c recncell.c splitreg.c table-allgui.c table-gnome.c textcell.c
noinst_HEADERS = QuickFill.h basiccell.h cellblock.h combocell.h datecell.h numcell.h pricecell.h quickfillcell.h recncell.h splitreg.h table-allgui.h textcell.h
noinst_HEADERS = QuickFill.h basiccell.h cellblock.h combocell.h datecell.h numcell.h pricecell.h quickfillcell.h recncell.h register-common.h splitreg.h table-allgui.h textcell.h
EXTRA_DIST = .cvsignore design.txt table-html.c table-html.h

View File

@@ -190,6 +190,7 @@
#include "gnc-common.h"
#include "gnc-ui-common.h"
#include "register-common.h"
/* define a bitmask */
@@ -234,8 +235,7 @@ typedef const char * (*CellLeaveFunc) (BasicCell *,
typedef void (*CellRealizeFunc) (BasicCell *,
void *gui_handle);
typedef void (*CellMoveFunc) (BasicCell *,
int phys_row, int phys_col);
typedef void (*CellMoveFunc) (BasicCell *, PhysicalLocation phys_loc);
typedef void (*CellDestroyFunc) (BasicCell *);

View File

@@ -1,249 +0,0 @@
The Register Object
-------------------
The register is an infrastructure for building
a modular spread-sheet/matrix/array of cells,
where each cell may have a unique/special
capability, e.g. to understand only dates, amounts
or text. The register has been designed to
be easy to extend, modular & easy to maintain,
and memory-efficient. It is intended to be used
for building financial apps and spread-sheets.
Features
--------
-- Supported cell types:
Date: display and/or edit of date, can
use accelerator keys to set date
Price/Value: display and or edit of numeric quantity
Text: arbitrary text string display and/or edit
Quickfill: auto-completes user's typed in entry
to match previous entries
Combo: pull-down menu of choices
Recncell: checkbox, click to cycle through values
-- Modular: cells are their own objects, new cells can
be invented.
-- Configurable: layout of cells is programatically
modifiable.
-- Tabular: cells are handled in groups ("blocks")
that can be manipulated as a whole.
-- Multi-tabular: multiple cell-blocks can be defined
for one table, allowing different sets
of rows to have distinct layouts
-- Tab-Groups: Tabbing order between cells is customizable
-- Engine-Independent: No assumptions made about source of
data, no predefined financial structure
required or enforced.
-- Transaction Support: Groups of cells can be treated
as a single transactional entity, allowing
all edits to be committed or rejected as
a whole.
-- C language implementation.
-- Identical function available via Motif or GTK. The GUI
code segregated, theoretically making port to
Qt easy.
Philosophy
---------
The register object, indeed, all code in this directory, does not
depend on (should not depend on) any code in the accounting engine,
or on any code in the main application. It should be possible to use
the register in a stand-alone fashion. As a result of this
"independence" philosophy, there is a very small amount of
duplicated code for date handling (i.e. there are similar functions
in src/register/datecell.c and src/engine/date.c). As cleanup
continues, this duplication will disappear.
Design Overview
---------------
The register is built of several components:
the "cell", the "cellblock", the "cursor", the
"table", and the "register".
Cell
----
The "cell" is an active cell object. This object
defines callbacks that are called when the user
enters the cell (e.g. by mouse-clicking on a cell in a
table, or tabbing to it), when the user attempts to
modify text in the cell (e.g. by typing in it), and
when the user leaves the cell (e.g. by mouse-clicking
elsewhere, or tabbing away).
Special-purpose cells can be created by "inheriting"
from the cell object. Thus, there are special-purpose
cells for handling dates, pull-down menus, text fields,
monetary amounts, etc.
Cells implementations may or may not contain GUI
code. Cells which require only that text be displayed
are completely "GUI-independent"; that is, they
depend on the underlying table to display the text.
Cells which require additional GUI elements (e.g.
pull-down menus) must implement the proper GUI
handling on their own (using e.g. Motif, GTK or Qt).
Cellblock
---------
The "cellblock" is an array of active cells. The
cells are laid out in row-column order. The
cellblock serves as a convenient container for
organizing active cells in an array. It provides
several functions. First, it defines a tab-group
(group of cells that can be traversed by hitting
the tab-key). More importantly, through the mechanism
of "cursors" (defined below), it allows a group
of cells to be treated as a single transactional entity.
That is, the cursor/cellblock allows all edits to
a groups of cells to be simultaneously committed
or rejected by underlying engines. This makes
it appropriate for use as a GUI to transaction-processing
applications with two-phase commit requirements.
Table
-----
The "table" is the displayed matrix. The table is
a complex object; it is NOT merely a cellblock.
The table provides all of the GUI infrastructure for
displaying a row-column matrix of strings.
The table provides one very important function
for minimizing memory usage for large matrixes.
It defines the notion of a "cursor". The "cursor"
is a cellblock (an array of active cells) that is
moved to the location that the user is currently
editing. The cursor "virtualizes" cell functions;
that is, it makes it seem to the user as if all
cells in the table are active, when in fact the only
cell that actually needs to be active is the one that
the user is currently editing.
The current table design allows multiple cursors
to be defined. When a user enters a cell, the appropriate
cursor is positioned within the table. Cursors
cannot overlap: any given cell can be mapped to at most
one cursor. Multiple-cursor support allows tables
to be designed that have a non-uniform layout.
For example, the multiple-cursor support can be
used to define a tree structure of headings/topics and
sub-headings/sub-topics, where the layout/format of
the heading is different from the sub-headings.
A financial example is a table which lists splits
underneath their parent transaction. This is
very different from a checkbook register, where
all entries are uniform, and can be handled with
a single repeated cursor.
Register
--------
The register is a special-purpose object aimed at
the display of financial transactions. It includes
cells for the date, prices, balances, transfer accounts,
etc. The register is where the cells, cursor and
table get put together into a unified whole. The
register defines specific, actual layouts and widths
of the date, price, etc. cells in a table. It includes
a table header, and defines more than ten specific layouts:
bank, credit-card, stock, general ledger, etc.
Portability Notes
-----------------
The register should be easily portable to Qt. Most of
the files contain no Motif or GTK code, and thus do not
require any porting. All Motif-specific code appears in
the file "table-motif.c" and "combocell.c". All that
table-motif.c does is to set up the XbaeMatrix Motif widget,
and to install callbacks for cell enter/modify/leave.
The combocell.c file defines a pull-down menu that can be
inserted into Xbae cells.
Porting hints: stub out combocell.c, and work on table-motif.c
first.
> Could you give me a (brief) overview of what's going on in
> table-motif. i.e. what's the top-level widget etc. (it looks like
> most of the functionality is provided by the XbaeMatrix which doesn't
> have a direct GTK correspondent...), and how do the parts of that
> widget that you use behave?
>
> For example, I might say "GTK's CList allows you to set up a 2d table
> where each cell contains a text field, a pixmap, or both..." That's
> the level of description I'm thinking of for the stuff you use from
> Xbae, since I don't know anything about it.
XbaeMatrix is "just" a table widget: it provides the following:
-- each cell is a "virtual" text widget. (there is really only one text
widget in Xbae, it gets dynamically mapped to the currently active
cell. This is all 100% transparent both to programmer and user.
I only mention this because it makes Xbae very efficient space and
speed wise for large tables.)
-- cells can contain pixmaps
-- cells can contain widgets (although this is kind of a hack --
I hacked this code in myself. Xbae internals are very complex).
-- cells deliver enter and leave callbacks when user enters
or leaves with mouse/tab key/arrow key. programmer is allowed
to change text upon enter/leave.
-- cells deliver modify callback. modify callback presents old and new
data as typed by the user. callback allows programmer to accept or
reject the edits. (e.g. I use this to accept only number &
punctuation in money cells, and only valid dates in date cells.
I also use this to implement accelerator keys for the date cells.)
-- allows cells to be marked read-only (not modifiable by user).
-- allows a fixed number of rows & cols on left, right, bottom, top.
(I only fix top rows).
-- automatically puts up scroll bar on the scrolling region, when
the scrolling region is larger than physical window.
-- user-defined data can be anchored to each cell, and/or row,
and/or column.
-- allows variety of highlighting features. (not used).
-- allows tab-traversal order to be set (which cells are visited
when tab key/arrows keys are hit).
-- allows rows/columns to be labeled (not used).
If you look at table-motif.c, you will see the following structure:
xaccCreateTable() initializes the table widget
cellCB () callback that is called when user enters/leaves a cell,
(by clicking on it with mouse, or with tab/arrow keys), or
when user attempts to edit the cell. This callback in turn calls
the enterCB(), leaveCB() and modifyCB() routines, which then call
GUI-independent callbacks for the register cell handlers.
Depending on the result of the cell callbacks, the string
stored in the cell is modified or not.
traverseCB() callback that is called when user tabs through sequence of
cells. This callback allows a sequence of cells to be defined
for tabbing through.
Under the covers, XbaeMatrix uses the Motif Text Widget to create
"cooked" strings out of raw key/button presses. The Motif Text
Widget automatically handles French/German/Icelandic/Cyrillic keyboards,
it handles the shift, alt & delete keys automatically, it handles
the delete/backspace keys automatically, it handles middle-mouse
paste automatically, etc. The resulting "cooked" strings are passed
to the register code (in table-motif.c) which then hands it off to the
cell handlers.
People porting this should give serious thought to finding and using
"vi" or "emacs" editing text widgets under the covers.
That's pretty much it, except for some assorted GUI-independent setup.
Apologies
---------
This is not the world's most elegant design, its
occasionally a bit of a hack, occasionally over-complex,
but it more or less works, and should be quite extensible.
Its certainly light-years ahead of its predecessor.
-- Linas Vepstas
-- March 1998

View File

@@ -77,7 +77,7 @@ typedef struct _PopBox
static void block_list_signals (ComboCell *cell);
static void unblock_list_signals (ComboCell *cell);
static void realizeCombo (BasicCell *bcell, void *w);
static void moveCombo (BasicCell *bcell, int phys_row, int phys_col);
static void moveCombo (BasicCell *bcell, PhysicalLocation phys_loc);
static void destroyCombo (BasicCell *bcell);
static const char * enterCombo (BasicCell *bcell,
const char *value,
@@ -727,7 +727,7 @@ realizeCombo (BasicCell *bcell, void *data)
/* =============================================== */
static void
moveCombo (BasicCell *bcell, int phys_row, int phys_col)
moveCombo (BasicCell *bcell, PhysicalLocation phys_loc)
{
PopBox *box = (PopBox *) bcell->gui_private;

View File

@@ -93,38 +93,37 @@ gnucash_cursor_set_style (GnucashCursor *cursor, SheetBlockStyle *style)
void
gnucash_cursor_get_phys (GnucashCursor *cursor, int *phys_row, int *phys_col)
gnucash_cursor_get_phys (GnucashCursor *cursor, PhysicalLocation *phys_loc)
{
Table *table;
VirtualCell *vcell;
int virt_row, virt_col;
int cell_row, cell_col;
VirtualLocation virt_loc;
g_return_if_fail (cursor != NULL);
g_return_if_fail (GNUCASH_IS_CURSOR (cursor));
table = cursor->sheet->table;
virt_row =
virt_loc.vcell_loc.virt_row =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_BLOCK])->row;
virt_col =
virt_loc.vcell_loc.virt_col =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_BLOCK])->col;
cell_row =
virt_loc.phys_row_offset =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_CELL])->row;
cell_col =
virt_loc.phys_col_offset =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_CELL])->col;
vcell = gnc_table_get_virtual_cell (table, virt_row, virt_col);
vcell = gnc_table_get_virtual_cell (table, virt_loc.vcell_loc);
*phys_row = vcell->phys_loc.phys_row + cell_row;
*phys_col = vcell->phys_loc.phys_col + cell_col;
*phys_loc = vcell->phys_loc;
phys_loc->phys_row += virt_loc.phys_row_offset;
phys_loc->phys_col += virt_loc.phys_col_offset;
}
void
gnucash_cursor_get_virt (GnucashCursor *cursor, int *virt_row, int *virt_col,
int *cell_row, int *cell_col)
gnucash_cursor_get_virt (GnucashCursor *cursor, VirtualLocation *virt_loc)
{
Table *table;
@@ -133,14 +132,14 @@ gnucash_cursor_get_virt (GnucashCursor *cursor, int *virt_row, int *virt_col,
table = cursor->sheet->table;
*virt_row =
virt_loc->vcell_loc.virt_row =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_BLOCK])->row;
*virt_col =
virt_loc->vcell_loc.virt_col =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_BLOCK])->col;
*cell_row =
virt_loc->phys_row_offset =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_CELL])->row;
*cell_col =
virt_loc->phys_col_offset =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_CELL])->col;
}
@@ -269,8 +268,7 @@ gnucash_item_cursor_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
static void
gnucash_cursor_set_block (GnucashCursor *cursor, gint block_row,
gint block_col)
gnucash_cursor_set_block (GnucashCursor *cursor, VirtualCellLocation vcell_loc)
{
GnucashSheet *sheet;
GnucashItemCursor *item_cursor;
@@ -282,14 +280,16 @@ gnucash_cursor_set_block (GnucashCursor *cursor, gint block_row,
item_cursor =
GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_BLOCK]);
if (block_row < 0 || block_row >= sheet->num_virt_rows
|| block_col < 0 || block_col >= sheet->num_virt_cols)
if (vcell_loc.virt_row < 0 ||
vcell_loc.virt_row >= sheet->num_virt_rows ||
vcell_loc.virt_col < 0 ||
vcell_loc.virt_col >= sheet->num_virt_cols)
return;
cursor->style = gnucash_sheet_get_style (sheet, block_row, block_col);
cursor->style = gnucash_sheet_get_style (sheet, vcell_loc);
item_cursor->row = block_row;
item_cursor->col = block_col;
item_cursor->row = vcell_loc.virt_row;
item_cursor->col = vcell_loc.virt_col;
}
@@ -307,20 +307,17 @@ gnucash_cursor_set_cell (GnucashCursor *cursor, gint cell_row, gint cell_col)
item_cursor = GNUCASH_ITEM_CURSOR(cursor->cursor[GNUCASH_CURSOR_CELL]);
style = cursor->style;
if (cell_row < 0 || cell_row >= style->nrows
|| cell_col < 0 || cell_col >= style->ncols)
if (cell_row < 0 || cell_row >= style->nrows ||
cell_col < 0 || cell_col >= style->ncols)
return;
item_cursor->row = cell_row;
item_cursor->col = cell_col;
}
void
gnucash_cursor_set (GnucashCursor *cursor, gint block_row, gint block_col,
gint cell_row, gint cell_col)
gnucash_cursor_set (GnucashCursor *cursor, VirtualLocation virt_loc)
{
GnucashSheet *sheet;
@@ -331,8 +328,10 @@ gnucash_cursor_set (GnucashCursor *cursor, gint block_row, gint block_col,
gnucash_cursor_request_redraw (cursor);
gnucash_cursor_set_block (cursor, block_row, block_col);
gnucash_cursor_set_cell (cursor, cell_row, cell_col);
gnucash_cursor_set_block (cursor, virt_loc.vcell_loc);
gnucash_cursor_set_cell (cursor,
virt_loc.phys_row_offset,
virt_loc.phys_col_offset);
gnucash_cursor_configure (cursor);

View File

@@ -92,14 +92,12 @@ typedef struct
GnomeCanvasItem *gnucash_cursor_new (GnomeCanvasGroup *parent);
void gnucash_cursor_get_phys (GnucashCursor *cursor, int *phys_row,
int *phys_col);
void gnucash_cursor_get_virt (GnucashCursor *cursor, int *virt_row,
int *virt_col, int *cell_row, int *cell_col);
void gnucash_cursor_get_phys (GnucashCursor *cursor,
PhysicalLocation *phys_loc);
void gnucash_cursor_get_virt (GnucashCursor *cursor,
VirtualLocation *virt_loc);
void gnucash_cursor_set (GnucashCursor *cursor,
gint virt_row, gint virt_col,
gint cell_row, gint cell_col);
void gnucash_cursor_set (GnucashCursor *cursor, VirtualLocation virt_loc);
void gnucash_cursor_set_style (GnucashCursor *cursor, SheetBlockStyle *style);

View File

@@ -129,78 +129,80 @@ gnucash_grid_update (GnomeCanvasItem *item, double *affine,
*
* All coordinates are with respect to the canvas origin.
*/
gint
gboolean
gnucash_grid_find_block_origin_by_pixel (GnucashGrid *grid,
gint x, gint y,
gint *virt_row, gint *virt_col,
VirtualCellLocation *vcell_loc,
gint *o_x, gint *o_y)
{
SheetBlockStyle *style;
int row = 1, col = 0;
VirtualCellLocation vc_loc = { 1, 0 };
int pixel = 0;
g_return_val_if_fail(y >= 0, FALSE);
g_return_val_if_fail(x >= 0, FALSE);
do {
style = gnucash_sheet_get_style (grid->sheet, row, col);
style = gnucash_sheet_get_style (grid->sheet, vc_loc);
if (!style || (y >= pixel && y < pixel + style->dimensions->height)){
if (!style || (y >= pixel &&
y < pixel + style->dimensions->height)) {
if (o_y)
*o_y = pixel;
if (virt_row)
*virt_row = row;
if (vcell_loc)
vcell_loc->virt_row = vc_loc.virt_row;
break;
}
pixel += style->dimensions->height;
row++;
} while (row < grid->sheet->num_virt_rows);
vc_loc.virt_row++;
} while (vc_loc.virt_row < grid->sheet->num_virt_rows);
if (row == grid->sheet->num_virt_rows)
if (vc_loc.virt_row == grid->sheet->num_virt_rows)
return FALSE;
pixel = 0;
do {
style = gnucash_sheet_get_style (grid->sheet, row, col);
if (!style || (x >= pixel && x < pixel + style->dimensions->width)){
style = gnucash_sheet_get_style (grid->sheet, vc_loc);
if (!style || (x >= pixel &&
x < pixel + style->dimensions->width)) {
if (o_x)
*o_x = pixel;
if (virt_col)
*virt_col = col;
if (vcell_loc)
vcell_loc->virt_col = vc_loc.virt_col;
break;
}
pixel += style->dimensions->height;
col++;
} while (col < grid->sheet->num_virt_cols);
vc_loc.virt_col++;
} while (vc_loc.virt_col < grid->sheet->num_virt_cols);
if (col == grid->sheet->num_virt_cols)
if (vc_loc.virt_col == grid->sheet->num_virt_cols)
return FALSE;
return TRUE;
}
gint
gnucash_grid_find_cell_by_pixel (GnucashGrid *grid,
gint x, gint y,
int *virt_row, int *virt_col,
int *cell_row, int *cell_col)
gboolean
gnucash_grid_find_cell_by_pixel (GnucashGrid *grid, gint x, gint y,
VirtualLocation *virt_loc)
{
SheetBlockStyle *style;
int block_x, block_y;
if (virt_loc == NULL)
return FALSE;
if (!gnucash_grid_find_block_origin_by_pixel (grid,
x, y,
virt_row, virt_col,
&block_x, &block_y))
x, y,
&virt_loc->vcell_loc,
&block_x, &block_y))
return FALSE;
/* now make x, y relative to the block origin */
x -= block_x;
y -= block_y;
style = gnucash_sheet_get_style (grid->sheet, *virt_row, *virt_col);
style = gnucash_sheet_get_style (grid->sheet, virt_loc->vcell_loc);
if (style) {
gint row = 0;
@@ -208,7 +210,9 @@ gnucash_grid_find_cell_by_pixel (GnucashGrid *grid,
gint pixel = 0;
do {
if ( y >= pixel && y <pixel + style->dimensions->pixel_heights[row][0])
if ( y >= pixel &&
y < pixel +
style->dimensions->pixel_heights[row][0])
break;
pixel += style->dimensions->pixel_heights[row][0];
@@ -220,7 +224,9 @@ gnucash_grid_find_cell_by_pixel (GnucashGrid *grid,
pixel = 0;
do {
if ( x >= pixel && x < pixel + style->dimensions->pixel_widths[row][col])
if ( x >= pixel &&
x < pixel +
style->dimensions->pixel_widths[row][col])
break;
pixel += style->dimensions->pixel_widths[row][col];
@@ -229,14 +235,15 @@ gnucash_grid_find_cell_by_pixel (GnucashGrid *grid,
if (col == style->ncols)
return FALSE;
if (cell_row)
*cell_row = row;
if (cell_col)
*cell_col = col;
if (virt_loc)
virt_loc->phys_row_offset = row;
if (virt_loc)
virt_loc->phys_col_offset = col;
return TRUE;
}
return FALSE;
}
@@ -252,10 +259,11 @@ draw_cell (GnucashGrid *grid, int block,
gchar *text;
GdkFont *font;
SheetBlock *sheet_block;
VirtualCellLocation vcell_loc = { block, 0 };
gdk_gc_set_background (grid->gc, &gn_white);
sheet_block = gnucash_sheet_get_block (grid->sheet, block, 0);
sheet_block = gnucash_sheet_get_block (grid->sheet, vcell_loc);
gdk_gc_set_foreground (grid->gc, sheet_block->bg_colors[i][j]);
gdk_draw_rectangle (drawable, grid->gc, TRUE, x, y, width, height);
@@ -268,11 +276,13 @@ draw_cell (GnucashGrid *grid, int block,
/* right */
if (style->borders[i][j] & STYLE_BORDER_RIGHT)
gdk_draw_line (drawable, grid->gc, x+width, y, x+width, y+height);
gdk_draw_line (drawable, grid->gc, x+width, y,
x+width, y+height);
/* bottom */
if (style->borders[i][j] & STYLE_BORDER_BOTTOM)
gdk_draw_line (drawable, grid->gc, x+width, y+height, x, y+height);
gdk_draw_line (drawable, grid->gc, x+width,
y+height, x, y+height);
/* left */
if (style->borders[i][j] & STYLE_BORDER_LEFT)
@@ -281,7 +291,8 @@ draw_cell (GnucashGrid *grid, int block,
#undef ROUNDED_CORNERS
#ifdef ROUNDED_CORNERS
gdk_gc_set_foreground (grid->gc, sheet_block->bg_colors[i][j]);
gdk_draw_rectangle (drawable, grid->gc, TRUE, x+1, y+1, width-1, height-1);
gdk_draw_rectangle (drawable, grid->gc, TRUE, x+1,
y+1, width-1, height-1);
gdk_gc_set_foreground (grid->gc, &gn_black);
@@ -320,7 +331,7 @@ draw_cell (GnucashGrid *grid, int block,
gdk_gc_set_foreground (grid->gc, sheet_block->fg_colors[i][j]);
if (table->current_cursor_virt_row == block &&
if (table->current_cursor_virt_loc.virt_row == block &&
(!text || strlen(text) == 0)) {
font = grid->italic_font;
gdk_gc_set_foreground (grid->gc, &gn_light_gray);
@@ -371,11 +382,11 @@ gnucash_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
int x, int y, int width, int height)
{
GnucashGrid *grid = GNUCASH_GRID (item);
GnucashSheet *sheet = grid->sheet;
GnucashSheet *sheet = grid->sheet;
VirtualLocation virt_loc;
SheetBlockStyle *style;
SheetBlock *sheet_block;
Table *table;
gint vrow, vcol;
gint x_paint, y_paint;
gint diff_x, diff_y;
gint cellrow, cellcol;
@@ -392,8 +403,7 @@ gnucash_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
0, 0, width, height);
/* compute our initial values where we start drawing */
if (!gnucash_grid_find_block_origin_by_pixel (grid, x, y,
NULL, NULL,
if (!gnucash_grid_find_block_origin_by_pixel (grid, x, y, NULL,
&ox, &oy))
return;
@@ -401,28 +411,32 @@ gnucash_grid_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
for (y_paint = y - diff_y; y_paint <= y + height; ) {
if (!gnucash_grid_find_cell_by_pixel (grid,
x, y_paint,
&vrow, &vcol,
&cellrow, &cellcol))
if (!gnucash_grid_find_cell_by_pixel (grid, x, y_paint,
&virt_loc))
return;
style = gnucash_sheet_get_style (sheet, vrow, 0);
sheet_block = gnucash_sheet_get_block (sheet, vrow, 0);
style = gnucash_sheet_get_style (sheet, virt_loc.vcell_loc);
sheet_block = gnucash_sheet_get_block (sheet,
virt_loc.vcell_loc);
if (!style || ! sheet_block)
return;
cellrow = virt_loc.phys_row_offset;
cellcol = virt_loc.phys_col_offset;
ox = style->dimensions->origin_x[cellrow][cellcol];
diff_x = x - ox;
for (x_paint = x - diff_x; x_paint <= x + width && cellcol < style->ncols; ) {
for (x_paint = x - diff_x;
x_paint <= x + width && cellcol < style->ncols; ) {
h = style->dimensions->pixel_heights[cellrow][0];
h = style->dimensions->pixel_heights[cellrow][0];
w = style->dimensions->pixel_widths[cellrow][cellcol];
draw_cell (grid, vrow, style, cellrow, cellcol, drawable,
draw_cell (grid, virt_loc.vcell_loc.virt_row,
style, cellrow, cellcol, drawable,
x_paint - x, y_paint - y, w, h);
x_paint += w;
cellcol++;

View File

@@ -40,7 +40,7 @@ typedef struct {
/* The first and last displayed block */
int top_block;
int bottom_block;
/* Offset from spreadsheet origin in units */
long top_offset;
long left_offset;
@@ -66,15 +66,15 @@ typedef struct {
GtkType gnucash_grid_get_type (void);
GtkWidget *gnucash_grid_new (GnucashSheet *sheet);
gint gnucash_grid_find_block_origin_by_pixel (GnucashGrid *grid,
gint x, gint y,
gint *virt_row, gint *virt_col,
gint *o_x, gint *o_y);
gboolean
gnucash_grid_find_block_origin_by_pixel (GnucashGrid *grid,
gint x, gint y,
VirtualCellLocation *vcell_loc,
gint *o_x, gint *o_y);
gint gnucash_grid_find_cell_by_pixel (GnucashGrid *grid,
gint x, gint y,
int *virt_row, int *virt_col,
int *cell_row, int *cell_col);
gboolean
gnucash_grid_find_cell_by_pixel (GnucashGrid *grid, gint x, gint y,
VirtualLocation *vcell_loc);
#endif /* GNUCASH_GRID_H */

View File

@@ -98,15 +98,14 @@ item_edit_get_pixel_coords (ItemEdit *item_edit, int *x, int *y,
int *w, int *h)
{
GnucashSheet *sheet = item_edit->sheet;
VirtualCellLocation vcell_loc = { item_edit->virt_row,
item_edit->virt_col };
int xd, yd, save;
gnome_canvas_get_scroll_offsets (GNOME_CANVAS(sheet), NULL, &yd);
save = yd;
gnucash_sheet_block_pixel_origin (sheet,
item_edit->virt_row,
item_edit->virt_col,
&xd, &yd);
gnucash_sheet_block_pixel_origin (sheet, vcell_loc, &xd, &yd);
gnucash_sheet_style_get_cell_pixel_rel_coords (item_edit->style,
item_edit->cell_row,
@@ -450,7 +449,8 @@ item_edit_destroy (GtkObject *object)
gboolean
item_edit_set_cursor_pos (ItemEdit *item_edit, int p_row, int p_col, int x,
item_edit_set_cursor_pos (ItemEdit *item_edit,
PhysicalLocation phys_loc, int x,
gboolean changed_cells, gboolean extend_selection)
{
GtkEditable *editable;
@@ -459,7 +459,8 @@ item_edit_set_cursor_pos (ItemEdit *item_edit, int p_row, int p_col, int x,
gint pos;
gint pos_x;
gint o_x, o_y;
gint virt_row, virt_col, cell_row, cell_col;
VirtualCellLocation vcell_loc;
gint cell_row, cell_col;
SheetBlockStyle *style;
PhysicalCell *pcell;
char *text;
@@ -468,22 +469,21 @@ item_edit_set_cursor_pos (ItemEdit *item_edit, int p_row, int p_col, int x,
table = item_edit->sheet->table;
pcell = gnc_table_get_physical_cell (table, p_row, p_col);
pcell = gnc_table_get_physical_cell (table, phys_loc);
if (pcell == NULL)
return FALSE;
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
vcell_loc = pcell->virt_loc.vcell_loc;
cell_row = pcell->virt_loc.phys_row_offset;
cell_col = pcell->virt_loc.phys_col_offset;
style = gnucash_sheet_get_style (item_edit->sheet, virt_row, 0);
style = gnucash_sheet_get_style (item_edit->sheet, vcell_loc);
o_x = style->dimensions->origin_x[cell_row][cell_col];
o_y = style->dimensions->origin_y[cell_row][cell_col];
if ( (virt_row != item_edit->virt_row) ||
(virt_col != item_edit->virt_col) ||
if ( (vcell_loc.virt_row != item_edit->virt_row) ||
(vcell_loc.virt_col != item_edit->virt_col) ||
(cell_row != item_edit->cell_row) ||
(cell_col != item_edit->cell_col) )
return FALSE;
@@ -593,6 +593,7 @@ item_edit_configure (ItemEdit *item_edit)
{
GnucashSheet *sheet = item_edit->sheet;
GnucashItemCursor *cursor;
VirtualCellLocation vcell_loc;
cursor = GNUCASH_ITEM_CURSOR
(GNUCASH_CURSOR(sheet->cursor)->cursor[GNUCASH_CURSOR_BLOCK]);
@@ -600,9 +601,11 @@ item_edit_configure (ItemEdit *item_edit)
item_edit->virt_row = cursor->row;
item_edit->virt_col = cursor->col;
vcell_loc.virt_row = cursor->row;
vcell_loc.virt_col = cursor->col;
item_edit->style = gnucash_sheet_get_style (item_edit->sheet,
item_edit->virt_row,
item_edit->virt_col);
vcell_loc);
cursor = GNUCASH_ITEM_CURSOR
(GNUCASH_CURSOR(sheet->cursor)->cursor[GNUCASH_CURSOR_CELL]);
@@ -642,7 +645,8 @@ item_edit_claim_selection (ItemEdit *item_edit, guint32 time)
owner = gdk_selection_owner_get (GDK_SELECTION_PRIMARY);
if (owner == GTK_WIDGET(item_edit->sheet)->window)
gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, time);
gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
time);
item_edit->has_selection = FALSE;
}
}

View File

@@ -102,7 +102,7 @@ void item_edit_show_list (ItemEdit *item_edit);
void item_edit_hide_list (ItemEdit *item_edit);
gboolean item_edit_set_cursor_pos (ItemEdit *item_edit,
int p_row, int p_col, int x,
PhysicalLocation phys_loc, int x,
gboolean changed_cells,
gboolean extend_selection);

File diff suppressed because it is too large Load Diff

View File

@@ -115,8 +115,7 @@ typedef struct
{
/* the virtual row/column in the table this block
is associated to */
gint virt_row;
gint virt_col;
VirtualCellLocation vcell_loc;
/* The style for this block, derived from the handlers for
the virt row/col */
@@ -206,7 +205,7 @@ GtkWidget *gnucash_sheet_new (Table *table);
void gnucash_sheet_table_load (GnucashSheet *sheet);
GtkType gnucash_register_get_type (void);
GtkType gnucash_register_get_type (void);
/* this already has scrollbars attached */
GtkWidget *gnucash_register_new (Table *table);
@@ -215,52 +214,48 @@ void gnucash_sheet_set_top_block (GnucashSheet *sheet, int new_top_block,
gint align);
SheetBlock *gnucash_sheet_get_block (GnucashSheet *sheet, gint vrow,
gint vcol);
gint
gnucash_sheet_col_max_width (GnucashSheet *sheet, gint virt_col, gint cell_col);
SheetBlock *gnucash_sheet_get_block (GnucashSheet *sheet,
VirtualCellLocation vcell_loc);
gint gnucash_sheet_col_get_distance(GnucashSheet *sheet, int v_row, int col_a, int col_b);
gint gnucash_sheet_col_max_width (GnucashSheet *sheet,
gint virt_col, gint cell_col);
gint gnucash_sheet_row_get_distance (GnucashSheet *sheet, int row_a,
int row_b);
gint gnucash_sheet_col_get_distance(GnucashSheet *sheet,
int v_row, int v_col_a, int v_col_b);
gint gnucash_sheet_row_get_distance (GnucashSheet *sheet,
int v_row_a, int v_row_b);
void gnucash_sheet_redraw_all (GnucashSheet *sheet);
void gnucash_sheet_redraw_block (GnucashSheet *sheet, gint row, gint col);
void gnucash_sheet_cursor_set (GnucashSheet *gsheet,
int virt_row, int virt_col,
int cell_row, int cell_col);
void gnucash_sheet_redraw_block (GnucashSheet *sheet,
VirtualCellLocation vcell_loc);
void gnucash_sheet_cursor_set (GnucashSheet *gsheet, VirtualLocation virt_loc);
const char * gnucash_sheet_modify_current_cell(GnucashSheet *sheet,
const gchar *new_text);
void gnucash_sheet_block_set_from_table (GnucashSheet *sheet, gint virt_row,
gint virt_col);
void gnucash_sheet_block_set_from_table (GnucashSheet *sheet,
VirtualCellLocation vcell_loc);
void gnucash_sheet_set_scroll_region (GnucashSheet *sheet);
void gnucash_sheet_cursor_set_from_table (GnucashSheet *sheet,
gboolean do_scroll);
void gnucash_sheet_move_cursor (GnucashSheet *sheet, int col, int row);
void gnucash_sheet_set_cursor_bounds (GnucashSheet *sheet,
int start_col, int start_row,
int end_col, int end_row);
void gnucash_sheet_compute_visible_range (GnucashSheet *sheet);
void gnucash_sheet_block_pixel_origin (GnucashSheet *sheet,
gint vrow, gint vcol,
VirtualCellLocation vcell_loc,
gint *x, gint *y);
void gnucash_sheet_make_cell_visible (GnucashSheet *sheet,
gint virt_row, gint virt_col,
gint cell_row, gint cell_col);
VirtualLocation virt_loc);
void gnucash_sheet_update_adjustments (GnucashSheet *sheet);
void gnucash_register_goto_virt_row_col (GnucashRegister *reg,
int v_row, int v_col);
void gnucash_register_goto_virt_cell (GnucashRegister *reg,
VirtualCellLocation vcell_loc);
void gnucash_register_goto_next_virt_row (GnucashRegister *reg);
@@ -274,20 +269,8 @@ void gnucash_register_copy_clipboard (GnucashRegister *reg);
void gnucash_register_paste_clipboard (GnucashRegister *reg);
typedef struct {
GnomeCanvasClass parent_class;
gint (*traverse) (GnucashSheet *sheet,
gint row, gint column,
gint *new_row, gint *new_column);
gint (*deactivate) (GnucashSheet *sheet,
gint row, gint column);
gint (*activate) (GnucashSheet *sheet,
gint row, gint column);
} GnucashSheetClass;

View File

@@ -1449,14 +1449,14 @@ gnucash_sheet_style_get_cell_pixel_rel_coords (SheetBlockStyle *style,
SheetBlockStyle *
gnucash_sheet_get_style (GnucashSheet *sheet, gint vrow, gint vcol)
gnucash_sheet_get_style (GnucashSheet *sheet, VirtualCellLocation vcell_loc)
{
SheetBlock *block;
g_return_val_if_fail (sheet != NULL, NULL);
g_return_val_if_fail (GNUCASH_IS_SHEET(sheet), NULL);
block = gnucash_sheet_get_block (sheet, vrow, vcol);
block = gnucash_sheet_get_block (sheet, vcell_loc);
if (block)
return block->style;
@@ -1466,7 +1466,8 @@ gnucash_sheet_get_style (GnucashSheet *sheet, gint vrow, gint vcol)
SheetBlockStyle *
gnucash_sheet_get_style_from_table (GnucashSheet *sheet, gint vrow, gint vcol)
gnucash_sheet_get_style_from_table (GnucashSheet *sheet,
VirtualCellLocation vcell_loc)
{
Table *table;
SplitRegister *sr;
@@ -1479,7 +1480,7 @@ gnucash_sheet_get_style_from_table (GnucashSheet *sheet, gint vrow, gint vcol)
table = sheet->table;
sr = sheet->split_register;
vcell = gnc_table_get_virtual_cell (table, vrow, vcol);
vcell = gnc_table_get_virtual_cell (table, vcell_loc);
cursor = vcell->cellblock;

View File

@@ -65,11 +65,12 @@ void gnucash_sheet_style_recompile (SheetBlockStyle *style,
SplitRegister *sr,
gint cursor_type);
SheetBlockStyle *gnucash_sheet_get_style (GnucashSheet *sheet, gint vrow,
gint vcol);
SheetBlockStyle *gnucash_sheet_get_style (GnucashSheet *sheet,
VirtualCellLocation vcell_loc);
SheetBlockStyle *gnucash_sheet_get_style_from_table (GnucashSheet *sheet,
gint vrow, gint vcol);
SheetBlockStyle *
gnucash_sheet_get_style_from_table (GnucashSheet *sheet,
VirtualCellLocation vcell_loc);
void gnucash_sheet_style_get_cell_pixel_rel_coords (SheetBlockStyle *style,
gint cell_row,

View File

@@ -0,0 +1,68 @@
/********************************************************************\
* register-common.h -- Common declarations for the register *
* Copyright (c) 2000 Dave Peticolas *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#ifndef __REGISTER_COMMON_H__
#define __REGISTER_COMMON_H__
/* The VirtualCellLocation structure contains the virtual
* location of a virtual cell.
*/
typedef struct _VirtualCellLocation VirtualCellLocation;
struct _VirtualCellLocation {
short virt_row;
short virt_col;
};
/* The VirtualLocation structure contains the virtual
* location of a physical cell.
*
* There is one instance of Locator for each physical cell.
* The virt_row and virt_col members identify the corresponding
* cellblock/virtual cell that this physical cell is a member of.
* The two phys_offsets provide the location of the physical cell
* as an offset from the cell block origin. That is, the offsets
* should never be less than zero, or greater than the size of
* the cell block.
*/
typedef struct _VirtualLocation VirtualLocation;
struct _VirtualLocation {
VirtualCellLocation vcell_loc;
short phys_row_offset;
short phys_col_offset;
};
/* The PhysicalLocation contains physical row and column coordinates.
* It is used to provide a mapping from a virtual cell block to the
* origin of the block in physical coordinates.
*
* There is one instance of a PhysicalLocation for each virtual cell. */
typedef struct _PhysicalLocation PhysicalLocation;
struct _PhysicalLocation {
short phys_row;
short phys_col;
};
#endif

View File

@@ -1150,7 +1150,12 @@ xaccInitSplitRegister (SplitRegister *reg,
table = gnc_table_new ();
gnc_table_set_size (table, phys_r, phys_c, reg->num_virt_rows, 1);
gnc_table_set_cursor (table, header, 0, 0, 0, 0);
{
PhysicalLocation ploc = { 0, 0 };
VirtualCellLocation vcell_loc = { 0, 0 };
gnc_table_set_cursor (table, header, ploc, vcell_loc);
}
/* The call below is for most practical purposes useless.
* It simply installs a cursor (the single-line cursor, but it
@@ -1159,11 +1164,18 @@ xaccInitSplitRegister (SplitRegister *reg,
* data gets loaded. Its just sort of here as a fail-safe fallback,
* in case someone just creates a register but doesn't do anything
* with it. Don't want to freak out any programmers. */
gnc_table_set_cursor (table, reg->single_cursor,
reg->cursor_phys_row, 0,
reg->cursor_virt_row, 0);
{
PhysicalLocation ploc = { reg->cursor_phys_row, 0 };
VirtualCellLocation vcell_loc = { reg->cursor_virt_row, 0 };
gnc_table_move_cursor (table, header->numRows, 0);
gnc_table_set_cursor (table, reg->single_cursor, ploc, vcell_loc);
}
{
PhysicalLocation ploc = { header->numRows, 0 };
gnc_table_move_cursor (table, ploc);
}
reg->table = table;
@@ -1337,7 +1349,7 @@ sr_cellblock_cursor_type(SplitRegister *reg, CellBlock *cursor)
/* ============================================== */
CursorType
xaccSplitRegisterGetCursorType (SplitRegister *reg)
xaccSplitRegisterGetCurrentCursorType (SplitRegister *reg)
{
Table *table;
@@ -1354,8 +1366,8 @@ xaccSplitRegisterGetCursorType (SplitRegister *reg)
/* ============================================== */
CursorType
xaccSplitRegisterGetCursorTypeRowCol (SplitRegister *reg,
int virt_row, int virt_col)
xaccSplitRegisterGetCursorType (SplitRegister *reg,
VirtualCellLocation vcell_loc)
{
VirtualCell *vcell;
Table *table;
@@ -1367,7 +1379,7 @@ xaccSplitRegisterGetCursorTypeRowCol (SplitRegister *reg,
if (table == NULL)
return CURSOR_NONE;
vcell = gnc_table_get_virtual_cell (table, virt_row, virt_col);
vcell = gnc_table_get_virtual_cell (table, vcell_loc);
if (vcell == NULL)
return CURSOR_NONE;
@@ -1436,7 +1448,7 @@ sr_cell_type (SplitRegister *reg, void * cell)
/* ============================================== */
CellType
xaccSplitRegisterGetCellType (SplitRegister *reg)
xaccSplitRegisterGetCurrentCellType (SplitRegister *reg)
{
Table *table;
@@ -1447,23 +1459,20 @@ xaccSplitRegisterGetCellType (SplitRegister *reg)
if (table == NULL)
return NO_CELL;
return xaccSplitRegisterGetCellTypeRowCol(reg,
table->current_cursor_phys_row,
table->current_cursor_phys_col);
return
xaccSplitRegisterGetCellType(reg, table->current_cursor_phys_loc);
}
/* ============================================== */
static BasicCell *
sr_current_cell (SplitRegister *reg)
sr_get_cell (SplitRegister *reg, PhysicalLocation phys_loc)
{
Table *table;
VirtualCell *vcell;
PhysicalCell *pcell;
CellBlock *cellblock;
int phys_row, phys_col;
int virt_row, virt_col;
int cell_row, cell_col;
VirtualLocation virt_loc;
if (reg == NULL)
return NULL;
@@ -1472,36 +1481,29 @@ sr_current_cell (SplitRegister *reg)
if (table == NULL)
return NULL;
phys_row = table->current_cursor_phys_row;
phys_col = table->current_cursor_phys_col;
pcell = gnc_table_get_physical_cell (table, phys_row, phys_col);
pcell = gnc_table_get_physical_cell (table, phys_loc);
if (pcell == NULL)
return NULL;
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
cell_row = pcell->virt_loc.phys_row_offset;
cell_col = pcell->virt_loc.phys_col_offset;
virt_loc = pcell->virt_loc;
vcell = gnc_table_get_virtual_cell (table, virt_row, virt_col);
vcell = gnc_table_get_virtual_cell (table, virt_loc.vcell_loc);
if (vcell == NULL)
return NULL;
cellblock = vcell->cellblock;
return cellblock->cells[cell_row][cell_col];
return cellblock->cells[virt_loc.phys_row_offset][virt_loc.phys_col_offset];
}
/* ============================================== */
CellType
xaccSplitRegisterGetCellTypeRowCol (SplitRegister *reg,
int phys_row, int phys_col)
xaccSplitRegisterGetCellType (SplitRegister *reg, PhysicalLocation phys_loc)
{
BasicCell *cell;
cell = sr_current_cell (reg);
cell = sr_get_cell (reg, phys_loc);
if (cell == NULL)
return NO_CELL;
@@ -1511,15 +1513,14 @@ xaccSplitRegisterGetCellTypeRowCol (SplitRegister *reg,
/* ============================================== */
gboolean
xaccSplitRegisterGetCellRowCol (SplitRegister *reg, CellType cell_type,
int *p_phys_row, int *p_phys_col)
xaccSplitRegisterGetCellPhysLoc (SplitRegister *reg, CellType cell_type,
PhysicalLocation *phys_loc)
{
Table *table;
VirtualCell *vcell;
PhysicalCell *pcell;
CellBlock *cellblock;
int phys_row, phys_col;
int virt_row, virt_col;
VirtualCellLocation vcell_loc;
int cell_row, cell_col;
if (reg == NULL)
@@ -1529,17 +1530,13 @@ xaccSplitRegisterGetCellRowCol (SplitRegister *reg, CellType cell_type,
if (table == NULL)
return FALSE;
phys_row = table->current_cursor_phys_row;
phys_col = table->current_cursor_phys_col;
pcell = gnc_table_get_physical_cell (table, phys_row, phys_col);
pcell = gnc_table_get_physical_cell (table, table->current_cursor_phys_loc);
if (pcell == NULL)
return FALSE;
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
vcell_loc = pcell->virt_loc.vcell_loc;
vcell = gnc_table_get_virtual_cell (table, virt_row, virt_col);
vcell = gnc_table_get_virtual_cell (table, vcell_loc);
if (vcell == NULL)
return FALSE;
@@ -1552,16 +1549,11 @@ xaccSplitRegisterGetCellRowCol (SplitRegister *reg, CellType cell_type,
if (sr_cell_type (reg, cell) == cell_type)
{
vcell = gnc_table_get_virtual_cell (table, virt_row, virt_col);
phys_row = vcell->phys_loc.phys_row + cell_row;
phys_col = vcell->phys_loc.phys_col + cell_col;
if (p_phys_row != NULL)
*p_phys_row = phys_row;
if (p_phys_col != NULL)
*p_phys_col = phys_col;
if (phys_loc != NULL)
{
phys_loc->phys_row = vcell->phys_loc.phys_row + cell_row;
phys_loc->phys_col = vcell->phys_loc.phys_col + cell_col;
}
return TRUE;
}

View File

@@ -270,27 +270,25 @@ guint32 xaccSplitRegisterGetChangeFlag (SplitRegister *reg);
void xaccSplitRegisterClearChangeFlag (SplitRegister *reg);
/* Returns the type of the current cursor */
CursorType xaccSplitRegisterGetCursorType (SplitRegister *reg);
CursorType xaccSplitRegisterGetCurrentCursorType (SplitRegister *reg);
/* Returns the type of the cursor at the given virtual row and column. */
CursorType xaccSplitRegisterGetCursorTypeRowCol (SplitRegister *reg,
int virt_row,
int virt_col);
CursorType xaccSplitRegisterGetCursorType (SplitRegister *reg,
VirtualCellLocation vcell_loc);
/* Returns the type of the current cell */
CellType xaccSplitRegisterGetCellType (SplitRegister *reg);
CellType xaccSplitRegisterGetCurrentCellType (SplitRegister *reg);
/* Returns the type of the cell at the given physical row and column. */
CellType xaccSplitRegisterGetCellTypeRowCol (SplitRegister *reg,
int phys_row,
int phys_col);
CellType xaccSplitRegisterGetCellType (SplitRegister *reg,
PhysicalLocation phys_loc);
/* Returns the physical row and column in the current cursor of the
* given cell using the pointer values. The function returns true if
* the given cell type is in the current cursor, false otherwise. */
gboolean xaccSplitRegisterGetCellRowCol (SplitRegister *reg,
CellType cell_type,
int *p_phys_row,
int *p_phys_col);
gboolean xaccSplitRegisterGetCellPhysLoc (SplitRegister *reg,
CellType cell_type,
PhysicalLocation *phys_loc);
/* Functions for working with split register buffers */
SplitRegisterBuffer * xaccMallocSplitRegisterBuffer ();

File diff suppressed because it is too large Load Diff

View File

@@ -117,38 +117,6 @@ typedef enum {
} gncTableTraversalDir;
/* The VirtualLocation structure contains the virtual
* location of a physical cell.
*
* There is one instance of Locator for each physical cell.
* The virt_row and virt_col members identify the corresponding
* cellblock/virtual cell that this physical cell is a member of.
* The two phys_offsets provide the location of the physical cell
* as an offset from the cell block origin. That is, the offsets
* should never be less than zero, or greater than the size of
* the cell block.
*/
typedef struct _VirtualLocation VirtualLocation;
struct _VirtualLocation {
short phys_row_offset;
short phys_col_offset;
short virt_row;
short virt_col;
};
/* The PhysicalLocation gives a reverse mapping from a virtual
* cell block to the origin of the block in physical coordinates.
*
* There is one instance of a PhysicalLocation for each virtual cell.
*/
typedef struct _PhysicalLocation PhysicalLocation;
struct _PhysicalLocation {
short phys_row;
short phys_col;
};
/* The VirtualCell structure holds information about each virtual cell. */
typedef struct _VirtualCell VirtualCell;
struct _VirtualCell
@@ -177,12 +145,10 @@ struct _PhysicalCell
typedef struct _Table Table;
typedef void (*TableMoveFunc) (Table *table,
int *p_new_phys_row,
int *p_new_phys_col);
PhysicalLocation *new_phys_loc);
typedef void (*TableTraverseFunc) (Table *table,
int *p_new_phys_row,
int *p_new_phys_col,
typedef void (*TableTraverseFunc) (Table *table,
PhysicalLocation *new_phys_loc,
gncTableTraversalDir dir);
typedef void (*TableSetHelpFunc) (Table *table,
@@ -208,10 +174,10 @@ typedef void (*TableDestroyFunc) (Table *table);
*/
struct _Table
{
int num_phys_rows;
int num_phys_cols;
int num_virt_rows;
int num_virt_cols;
short num_phys_rows;
short num_phys_cols;
short num_virt_rows;
short num_virt_cols;
/* The position of the current cursor in "virtual" space
* is given by the virt_row and virt_col fields below.
@@ -221,10 +187,8 @@ struct _Table
* given by the physical values. */
CellBlock *current_cursor;
int current_cursor_phys_row;
int current_cursor_phys_col;
int current_cursor_virt_row;
int current_cursor_virt_col;
PhysicalLocation current_cursor_phys_loc;
VirtualCellLocation current_cursor_virt_loc;
/* callback that is called when the cursor is moved */
TableMoveFunc move_cursor;
@@ -257,8 +221,7 @@ struct _Table
/* This class implements tab-key and arrow key traversal through the
* cells of the table. To perform this traversal, the location of
* the "previous" cell having input focus is required. */
int prev_phys_traverse_row;
int prev_phys_traverse_col;
PhysicalLocation prev_phys_traverse_loc;
void * ui_data;
@@ -270,14 +233,43 @@ struct _Table
Table * gnc_table_new (void);
void gnc_table_destroy (Table *);
/* These functions check the bounds of virtal and physical locations
* in the table and return TRUE if they are out of bounds. If possible,
* they are compiled inline. */
G_INLINE_FUNC gboolean
gnc_table_virtual_cell_out_of_bounds (Table *table,
VirtualCellLocation vcell_loc)
{
if (!table)
return TRUE;
return ((vcell_loc.virt_row < 0) ||
(vcell_loc.virt_row >= table->num_virt_rows) ||
(vcell_loc.virt_col < 0) ||
(vcell_loc.virt_col >= table->num_virt_cols));
}
G_INLINE_FUNC gboolean
gnc_table_physical_cell_out_of_bounds (Table *table,
PhysicalLocation phys_loc)
{
if (!table)
return TRUE;
return ((phys_loc.phys_row < 0) ||
(phys_loc.phys_row >= table->num_phys_rows) ||
(phys_loc.phys_col < 0) ||
(phys_loc.phys_col >= table->num_phys_cols));
}
/* These functions return the virtual/physical cell associated with a
* particular virtual/physical row & column pair. If the pair is out
* of bounds, NULL is returned. */
VirtualCell * gnc_table_get_virtual_cell (Table *table,
int virt_row, int virt_col);
VirtualCellLocation vcell_loc);
PhysicalCell * gnc_table_get_physical_cell (Table *table,
int phys_row, int phys_col);
PhysicalLocation phys_loc);
/* Return the virtual cell of the header */
VirtualCell * gnc_table_get_header_cell (Table *table);
@@ -295,21 +287,21 @@ void gnc_table_create_cursor (Table *, CellBlock *);
/* indicate what handler should be used for a given virtual block */
void gnc_table_set_cursor (Table *table, CellBlock *curs,
int phys_row_origin, int phys_col_origin,
int virt_row, int virt_col);
PhysicalLocation phys_origin,
VirtualCellLocation vcell_loc);
/* The gnc_table_move_cursor() method will move the cursor (but not
* the cursor GUI) to the indicated location. This function is
* useful when loading the table from the cursor: data can be loaded
* into the cursor, then committed to the table, all without the
* annoying screen flashing associated with GUI redraw. */
void gnc_table_move_cursor (Table *table, int phys_row, int phys_col);
void gnc_table_move_cursor (Table *table, PhysicalLocation phys_loc);
/* The gnc_table_move_cursor_gui() method will move the cursor and its
* GUI to the indicated location. Through a series of callbacks, all
* GUI elements get repositioned. */
void gnc_table_move_cursor_gui (Table *table,
int phys_row, int phys_col);
PhysicalLocation phys_loc);
/* The gnc_table_commit_cursor() method will copy text in the cursor
* cells into the table. This function is useful during the initial
@@ -329,25 +321,25 @@ void gnc_table_refresh_header (Table *table);
* and gui to the new position. Returns true if the cursor was
* repositioned. */
gboolean gnc_table_verify_cursor_position (Table *table,
int phys_row, int phys_col);
PhysicalLocation phys_loc);
/* The gnc_table_get_user_data_physical() method returns the user data
* associated with a cursor located at the given physical coords, or
* NULL if the coords are out of bounds. */
void * gnc_table_get_user_data_physical (Table *table,
int phys_row, int phys_col);
PhysicalLocation phys_loc);
/* The gnc_table_get_user_data_virtual() method returns the user data
* associated with a cursor located at the given virtual coords, or
* NULL if the coords are out of bounds. */
void * gnc_table_get_user_data_virtual (Table *table,
int virt_row, int virt_col);
VirtualCellLocation vcell_loc);
/* Find the closest valid horizontal cell. If exact_cell is true,
* cells that must be explicitly selected by the user (as opposed
* to just tabbing into), are considered valid cells. */
gboolean gnc_table_find_valid_cell_horiz(Table *table,
int *phys_row, int *phys_col,
PhysicalLocation *phys_loc,
gboolean exact_cell);
@@ -370,14 +362,14 @@ void gnc_table_refresh_gui (Table *table);
* perhaps these should go in a table-allguiP.h */
void gnc_table_wrap_verify_cursor_position (Table *table,
int phys_row, int phys_col);
PhysicalLocation phys_loc);
gboolean gnc_table_physical_cell_valid(Table *table,
int phys_row, int phys_col,
PhysicalLocation phys_loc,
gboolean exact_pointer);
void gnc_table_refresh_cursor_gui (Table * table, CellBlock *curs,
int phys_row, int phys_col,
PhysicalLocation phys_loc,
gboolean do_scroll);
@@ -396,17 +388,17 @@ void gnc_table_refresh_cursor_gui (Table * table, CellBlock *curs,
* like this semantic, cut&paste this code and change it to suit you.
* However, don't just change it, because it will break functional code. */
const char * gnc_table_enter_update(Table *table,
int phys_row, int phys_col,
PhysicalLocation phys_loc,
int *cursor_position,
int *start_selection,
int *end_selection);
const char * gnc_table_leave_update(Table *table,
int phys_row, int phys_col,
PhysicalLocation phys_loc,
const char *old_text);
const char * gnc_table_modify_update(Table *table,
int phys_row, int phys_col,
PhysicalLocation phys_loc,
const char *oldval,
const char *change,
char *newval,
@@ -415,7 +407,7 @@ const char * gnc_table_modify_update(Table *table,
int *end_selection);
gboolean gnc_table_direct_update(Table *table,
int phys_row, int phys_col,
PhysicalLocation phys_loc,
const char *oldval,
char **newval_ptr,
int *cursor_position,
@@ -424,10 +416,9 @@ gboolean gnc_table_direct_update(Table *table,
void *gui_data);
gboolean gnc_table_traverse_update(Table *table,
int phys_row, int phys_col,
PhysicalLocation phys_loc,
gncTableTraversalDir dir,
int *dest_row,
int *dest_col);
PhysicalLocation *dest_loc);
#endif /* __TABLE_ALLGUI_H__ */

View File

@@ -171,38 +171,32 @@ gnc_table_refresh_gui (Table * table)
void
gnc_table_refresh_cursor_gui (Table * table,
CellBlock *curs,
int phys_row, int phys_col,
PhysicalLocation phys_loc,
gboolean do_scroll)
{
GnucashSheet *sheet;
PhysicalCell *pcell;
gint virt_row, virt_col;
VirtualCellLocation vcell_loc;
if (!table)
return;
if (!table->ui_data)
if (!table || !table->ui_data || !curs)
return;
g_return_if_fail (GNUCASH_IS_SHEET (table->ui_data));
/* if the current cursor is undefined, there is nothing to do. */
if (!curs) return;
if ((0 > phys_row) || (0 > phys_col)) return;
if ((phys_row >= table->num_phys_rows) ||
(phys_col >= table->num_phys_cols))
if (gnc_table_physical_cell_out_of_bounds (table, phys_loc))
return;
sheet = GNUCASH_SHEET(table->ui_data);
/* compute the physical bounds of the current cursor */
pcell = gnc_table_get_physical_cell (table, phys_row, phys_col);
pcell = gnc_table_get_physical_cell (table, phys_loc);
virt_row = pcell->virt_loc.virt_row;
virt_col = pcell->virt_loc.virt_col;
vcell_loc = pcell->virt_loc.vcell_loc;
gnucash_sheet_cursor_set_from_table (sheet, do_scroll);
gnucash_sheet_block_set_from_table (sheet, virt_row, virt_col);
gnucash_sheet_redraw_block (sheet, virt_row, virt_col);
gnucash_sheet_block_set_from_table (sheet, vcell_loc);
gnucash_sheet_redraw_block (sheet, vcell_loc);
}
/* ================== end of file ======================= */