Add src/register/gtable.[ch], an implemtation of a dyamic 2-d array.

Reimplement the CellBlock and Table using this structure.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2860 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2000-09-16 08:14:30 +00:00
parent 9a0bafd217
commit 3e4b20679d
16 changed files with 1507 additions and 1350 deletions

View File

@ -3069,7 +3069,7 @@ xaccSRCountRows (SplitRegister *reg,
* +p where p is the sum total of all the splits in the transaction
* +2 an editable transaction and split at the end.
*/
num_phys_rows = reg->header->numRows;
num_phys_rows = reg->header->num_rows;
num_virt_rows = 1;
/* Look for the transaction split */
@ -3153,13 +3153,13 @@ xaccSRCountRows (SplitRegister *reg,
/* add one row for a transaction */
num_virt_rows ++;
num_phys_rows += reg->trans_cursor->numRows;
num_phys_rows += reg->trans_cursor->num_rows;
/* Add a row for each split, minus one, plus one.
* Essentially, do the following:
* j = xaccTransCountSplits (trans);
* num_virt_rows += j;
* num_phys_rows += j * reg->split_cursor->numRows;
* num_phys_rows += j * reg->split_cursor->num_rows;
* except that we also have to find the saved cursor row,
* Thus, we need a real loop over the splits.
* The do..while will automaticaly put a blank (null)
@ -3186,19 +3186,19 @@ xaccSRCountRows (SplitRegister *reg,
}
num_virt_rows ++;
num_phys_rows += reg->split_cursor->numRows;
num_phys_rows += reg->split_cursor->num_rows;
}
j++;
} while (secondary);
} else {
/* Try to get as close as possible to the original cell row. */
if (found_split && (split == find_split) &&
(save_cell_row < lead_cursor->numRows))
(save_cell_row < lead_cursor->num_rows))
save_cursor_phys_row += save_cell_row;
/* the simple case ... add one row for a transaction */
num_virt_rows ++;
num_phys_rows += lead_cursor->numRows;
num_phys_rows += lead_cursor->num_rows;
}
}
i++;
@ -3241,7 +3241,7 @@ xaccSRCountRows (SplitRegister *reg,
/* add one row for a transaction */
num_virt_rows ++;
num_phys_rows += reg->trans_cursor->numRows;
num_phys_rows += reg->trans_cursor->num_rows;
/* add in the splits */
trans = xaccSplitGetParent (split);
@ -3264,30 +3264,30 @@ xaccSRCountRows (SplitRegister *reg,
}
num_virt_rows ++;
num_phys_rows += reg->split_cursor->numRows;
num_phys_rows += reg->split_cursor->num_rows;
}
j++;
} while (secondary);
}
else {
num_virt_rows += 1;
num_phys_rows += reg->trans_cursor->numRows;
num_phys_rows += reg->trans_cursor->num_rows;
}
} else {
num_virt_rows += 1;
num_phys_rows += lead_cursor->numRows;
num_phys_rows += lead_cursor->num_rows;
}
/* check to make sure we got a good cursor position */
if ((num_phys_rows <= save_cursor_phys_row) ||
(num_virt_rows <= save_cursor_virt_row)) {
save_cursor_phys_row = num_phys_rows - reg->split_cursor->numRows;
save_cursor_phys_row = num_phys_rows - reg->split_cursor->num_rows;
save_cursor_virt_row = num_virt_rows;
}
if ((save_cursor_phys_row < (reg->header->numRows)) ||
if ((save_cursor_phys_row < (reg->header->num_rows)) ||
(save_cursor_virt_row < 1)) {
save_cursor_phys_row = reg->header->numRows;
save_cursor_phys_row = reg->header->num_rows;
save_cursor_virt_row = 1;
}
@ -3433,7 +3433,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
/* populate the table */
i=0;
vcell_loc.virt_row = 1; /* header is vrow zero */
phys_loc.phys_row = reg->header->numRows;
phys_loc.phys_row = reg->header->num_rows;
if (slist)
split = slist[0];
@ -3483,7 +3483,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, split);
vcell_loc.virt_row ++;
phys_loc.phys_row += reg->trans_cursor->numRows;
phys_loc.phys_row += reg->trans_cursor->num_rows;
/* loop over all of the splits in the transaction. The
* do..while will automatically put a blank (null) split
@ -3500,7 +3500,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
PINFO ("load split %d at phys row %d addr=%p \n",
j, phys_loc.phys_row, secondary);
vcell_loc.virt_row ++;
phys_loc.phys_row += reg->split_cursor->numRows;
phys_loc.phys_row += reg->split_cursor->num_rows;
}
j++;
@ -3512,7 +3512,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, split);
vcell_loc.virt_row ++;
phys_loc.phys_row += lead_cursor->numRows;
phys_loc.phys_row += lead_cursor->num_rows;
}
}
else {
@ -3535,7 +3535,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, split);
vcell_loc.virt_row ++;
phys_loc.phys_row += reg->trans_cursor->numRows;
phys_loc.phys_row += reg->trans_cursor->num_rows;
if (multi_line || (dynamic && on_blank_split)) {
Transaction *trans;
@ -3555,7 +3555,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
PINFO ("load split %d at phys row %d addr=%p \n",
j, phys_loc.phys_row, secondary);
vcell_loc.virt_row ++;
phys_loc.phys_row += reg->split_cursor->numRows;
phys_loc.phys_row += reg->split_cursor->num_rows;
}
j++;
@ -3566,7 +3566,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
gnc_table_move_cursor (table, phys_loc);
xaccSRLoadRegEntry (reg, split);
vcell_loc.virt_row ++;
phys_loc.phys_row += lead_cursor->numRows;
phys_loc.phys_row += lead_cursor->num_rows;
}
/* restore the cursor to its rightful position */

View File

@ -6,6 +6,7 @@ libgncregister_a_SOURCES = \
basiccell.c \
cellblock.c \
datecell.c \
gtable.c \
numcell.c \
pricecell.c \
quickfillcell.c \
@ -21,6 +22,7 @@ noinst_HEADERS = \
cellblock.h \
combocell.h \
datecell.h \
gtable.h \
numcell.h \
pricecell.h \
quickfillcell.h \

View File

@ -244,7 +244,6 @@ typedef char * (*CellGetHelpFunc) (BasicCell *);
struct _BasicCell
{
/* cell attributes */
/* hack alert -- may want to redesign color to use named color strings. */
guint32 bg_color; /* background color, ARGB format */
guint32 fg_color; /* forground (text) color ARGB format */
@ -255,7 +254,7 @@ struct _BasicCell
char * blank_help; /* help when value is blank */
guint32 changed; /* 2^32-1 if value modified */
guint8 input_output; /* zero if output-only */
guint8 input_output; /* allowed behavior flags */
/* "virtual", overloaded set-value method */
CellSetValueFunc set_value;
@ -279,14 +278,14 @@ struct _BasicCell
BasicCell * xaccMallocBasicCell (void);
void xaccInitBasicCell (BasicCell *);
void xaccDestroyBasicCell (BasicCell *);
void xaccInitBasicCell (BasicCell *bcell);
void xaccDestroyBasicCell (BasicCell *bcell);
void xaccSetBasicCellValue (BasicCell *, const char *);
void xaccSetBasicCellBlankHelp (BasicCell *, const char *);
char * xaccBasicCellGetHelp (BasicCell *);
void xaccSetBasicCellValue (BasicCell *bcell, const char *value);
void xaccBasicCellSetChanged (BasicCell *, gboolean);
void xaccSetBasicCellBlankHelp (BasicCell *bcell, const char *help);
char * xaccBasicCellGetHelp (BasicCell *bcell);
void xaccBasicCellSetChanged (BasicCell *bcell, gboolean changed);
#endif /* __BASIC_CELL_H__ */
/* ------------------ end of file ---------------------- */

View File

@ -31,260 +31,257 @@
* Copyright (c) 2000 Dave Peticolas
*/
#include <stdlib.h>
#include "cellblock.h"
static void gnc_cellblock_init (CellBlock *cellblock, int rows, int cols);
/* =================================================== */
CellBlock *
xaccMallocCellBlock (int numrows, int numcols)
gnc_cellblock_new (int rows, int cols)
{
CellBlock *cellblock;
CellBlock *cellblock;
cellblock = g_new0(CellBlock, 1);
cellblock = g_new(CellBlock, 1);
gnc_cellblock_init (cellblock, rows, cols);
cellblock->numRows = 0;
cellblock->numCols = 0;
return cellblock;
}
cellblock->active_bg_color = 0xffffff; /* white */
cellblock->passive_bg_color = 0xffffff; /* white */
cellblock->passive_bg_color2 = 0xffffff; /* white */
/* =================================================== */
cellblock->user_data = NULL;
cellblock->cells = NULL;
cellblock->cell_types = NULL;
cellblock->right_traverse_r = NULL;
cellblock->right_traverse_c = NULL;
cellblock->left_traverse_r = NULL;
cellblock->left_traverse_c = NULL;
cellblock->alignments = NULL;
static gpointer
gnc_cellblock_cell_new (void)
{
CellBlockCell *cb_cell;
xaccInitCellBlock (cellblock, numrows, numcols);
cb_cell = g_new0(CellBlockCell, 1);
return cellblock;
cb_cell->cell_type = -1;
cb_cell->alignment = CELL_ALIGN_LEFT;
cb_cell->resizable = TRUE;
return cb_cell;
}
/* =================================================== */
static void
gnc_cellblock_cell_free (gpointer _cb_cell)
{
CellBlockCell *cb_cell = _cb_cell;
if (cb_cell == NULL)
return;
g_free(cb_cell->sample_text);
cb_cell->sample_text = NULL;
g_free(cb_cell);
return;
}
/* =================================================== */
static gpointer
gnc_cell_traverse_info_new (void)
{
CellTraverseInfo *ct_info;
ct_info = g_new0(CellTraverseInfo, 1);
return ct_info;
}
/* =================================================== */
static void
gnc_cell_traverse_info_free (gpointer ct_info)
{
g_free (ct_info);
}
/* =================================================== */
static void
FreeCellBlockMem (CellBlock *cellblock)
gnc_cellblock_init (CellBlock *cellblock, int rows, int cols)
{
int oldrows, oldcols;
int i;
CellTraverseInfo *ct_info;
int row, col;
oldrows = cellblock->numRows;
oldcols = cellblock->numCols;
if (!cellblock) return;
/* free cell array, if any */
if (cellblock->cells)
{
for (i = 0; i < oldrows; i++)
g_free (cellblock->cells[i]);
g_free (cellblock->cells);
cellblock->cells = NULL;
}
/* init colors */
cellblock->active_bg_color = 0xffffff; /* white */
cellblock->passive_bg_color = 0xffffff; /* white */
cellblock->passive_bg_color2 = 0xffffff; /* white */
/* free cell type array, if any */
if (cellblock->cell_types)
{
for (i = 0; i < oldrows; i++)
g_free (cellblock->cell_types[i]);
g_free (cellblock->cell_types);
cellblock->cell_types = NULL;
}
/* record new size */
cellblock->num_rows = rows;
cellblock->num_cols = cols;
/* free right traversal chain */
if (cellblock->right_traverse_r)
{
for (i = 0; i < oldrows; i++)
g_free (cellblock->right_traverse_r[i]);
g_free(cellblock->right_traverse_r);
cellblock->right_traverse_r = NULL;
}
if (cellblock->right_traverse_c)
{
for (i = 0; i < oldrows; i++)
g_free (cellblock->right_traverse_c[i]);
g_free(cellblock->right_traverse_c);
cellblock->right_traverse_c = NULL;
}
/* malloc new cell table */
cellblock->cb_cells = g_table_new (gnc_cellblock_cell_new,
gnc_cellblock_cell_free);
g_table_resize (cellblock->cb_cells, rows, cols);
/* free left traversal chain */
if (cellblock->left_traverse_r)
{
for (i = 0; i < oldrows; i++)
g_free (cellblock->left_traverse_r[i]);
g_free(cellblock->left_traverse_r);
cellblock->left_traverse_r = NULL;
}
if (cellblock->left_traverse_c)
{
for (i = 0; i < oldrows; i++)
g_free (cellblock->left_traverse_c[i]);
g_free(cellblock->left_traverse_c);
cellblock->left_traverse_c = NULL;
}
/* malloc new traversal table */
cellblock->traverse_info = g_table_new (gnc_cell_traverse_info_new,
gnc_cell_traverse_info_free);
g_table_resize (cellblock->traverse_info, rows, cols);
/* free alignments */
g_free (cellblock->alignments);
cellblock->alignments = NULL;
for (row = 0; row < rows; row++)
{
for (col = 0; col < cols; col++)
{
ct_info = g_table_index (cellblock->traverse_info, row, col);
/* default right traversal is same row, next column */
ct_info->right_traverse_row = row;
ct_info->right_traverse_col = col + 1;
/* default left traversal is same row, previous column */
ct_info->left_traverse_row = row;
ct_info->left_traverse_col = col - 1;
}
/* at end of row, wrap to next row */
ct_info = g_table_index (cellblock->traverse_info, row, cols - 1);
ct_info->right_traverse_row = row + 1;
ct_info->right_traverse_col = 0;
/* at start of row, wrap to previous row */
ct_info = g_table_index (cellblock->traverse_info, row, 0);
ct_info->left_traverse_row = row - 1;
ct_info->left_traverse_col = cols - 1;
}
/* at end of block, wrap back to begining */
ct_info = g_table_index (cellblock->traverse_info, rows - 1, cols - 1);
ct_info->right_traverse_row = 0;
ct_info->right_traverse_col = 0;
/* at start of block, wrap back to end */
ct_info = g_table_index (cellblock->traverse_info, 0, 0);
ct_info->left_traverse_row = rows - 1;
ct_info->left_traverse_col = cols - 1;
/* last is last ... */
cellblock->last_reenter_traverse_row = rows - 1;
cellblock->last_reenter_traverse_col = cols - 1;
/* first is last ... */
cellblock->last_left_reenter_traverse_row = 0;
cellblock->last_left_reenter_traverse_col = 0;
}
/* =================================================== */
void
xaccInitCellBlock (CellBlock *cellblock, int numrows, int numcols)
{
int i, j;
if (!cellblock) return;
FreeCellBlockMem (cellblock);
/* record new size */
cellblock->numRows = numrows;
cellblock->numCols = numcols;
/* malloc new cell array */
cellblock->cells = g_new(BasicCell **, numrows);
cellblock->cell_types = g_new(short *, numrows);
for (i = 0; i < numrows; i++) {
(cellblock->cells)[i] = g_new(BasicCell *, numcols);
(cellblock->cell_types)[i] = g_new(short, numcols);
for (j=0; j<numcols; j++) {
(cellblock->cells)[i][j] = NULL;
(cellblock->cell_types)[i][j] = -1;
}
}
/* malloc new right traversal arrays */
cellblock->right_traverse_r = g_new(short *, numrows);
cellblock->right_traverse_c = g_new(short *, numrows);
for (i = 0; i < numrows; i++) {
(cellblock->right_traverse_r)[i] = g_new(short, numcols);
(cellblock->right_traverse_c)[i] = g_new(short, numcols);
for (j = 0; j < numcols - 1; j++) {
/* default traversal is same row, next column */
(cellblock->right_traverse_r)[i][j] = i;
(cellblock->right_traverse_c)[i][j] = j+1;
}
/* at end of row, wrap to next row */
(cellblock->right_traverse_r)[i][numcols-1] = i+1;
(cellblock->right_traverse_c)[i][numcols-1] = 0;
}
/* at end of block, wrap back to begining */
(cellblock->right_traverse_r)[numrows-1][numcols-1] = 0;
(cellblock->right_traverse_c)[numrows-1][numcols-1] = 0;
/* last is last ... */
cellblock->last_reenter_traverse_row = numrows - 1;
cellblock->last_reenter_traverse_col = numcols - 1;
/* malloc new left traversal arrays */
cellblock->left_traverse_r = g_new(short *, numrows);
cellblock->left_traverse_c = g_new(short *, numrows);
for (i = 0; i < numrows; i++) {
(cellblock->left_traverse_r)[i] = g_new(short, numcols);
(cellblock->left_traverse_c)[i] = g_new(short, numcols);
for (j = 0; j < numcols-1; j++) {
/* default traversal is same row, previous column */
(cellblock->left_traverse_r)[i][j] = i;
(cellblock->left_traverse_c)[i][j] = j-1;
}
/* at start of row, wrap to previous row */
(cellblock->left_traverse_r)[i][numcols-1] = i-1;
(cellblock->left_traverse_c)[i][numcols-1] = numcols-1;
}
/* at start of block, wrap back to end */
(cellblock->right_traverse_r)[0][0] = numrows-1;
(cellblock->right_traverse_c)[0][0] = numcols-1;
/* first is last ... */
cellblock->last_left_reenter_traverse_row = 0;
cellblock->last_left_reenter_traverse_col = 0;
cellblock->alignments = g_new(Alignments, numcols);
for (j = 0; j < numcols; j++)
cellblock->alignments[j] = ALIGN_RIGHT;
}
/* =================================================== */
void
xaccDestroyCellBlock (CellBlock *cellblock)
gnc_cellblock_destroy (CellBlock *cellblock)
{
if (!cellblock) return;
FreeCellBlockMem (cellblock);
g_table_destroy (cellblock->cb_cells);
cellblock->cb_cells = NULL;
g_table_destroy (cellblock->traverse_info);
cellblock->traverse_info = NULL;
/* finally, free this object itself */
g_free (cellblock);
}
/* =================================================== */
void
xaccNextRight (CellBlock *cellblock,
int row, int col,
int next_row, int next_col)
CellBlockCell *
gnc_cellblock_get_cell (CellBlock *cellblock, int row, int col)
{
if (!cellblock) return;
/* avoid embarrasement if cell incorrectly specified */
if ((0 > row) || (0 > col)) return;
if ((row >= cellblock->numRows) || (col >= cellblock->numCols)) return;
/* -1 is a valid value for next ... it signifies that traversal
* should go to next tab group, so do not check for neg values.
*/
/* if the "next" location to hop to is larger than the cursor, that
* just means that we should hop to the next cursor. Thus, large
* values for next *are* valid.
*/
(cellblock->right_traverse_r)[row][col] = next_row;
(cellblock->right_traverse_c)[row][col] = next_col;
/* if traversing out (neg values) record this as the last ... */
if ((0 > next_row) || (0 > next_col)) {
cellblock->last_reenter_traverse_row = row;
cellblock->last_reenter_traverse_col = col;
}
if (cellblock == NULL)
return NULL;
return g_table_index (cellblock->cb_cells, row, col);
}
/* =================================================== */
CellTraverseInfo *
gnc_cellblock_get_traverse (CellBlock *cellblock, int row, int col)
{
if (cellblock == NULL)
return NULL;
return g_table_index (cellblock->traverse_info, row, col);
}
/* =================================================== */
void
xaccNextLeft (CellBlock *cellblock, int row, int col,
int next_row, int next_col)
gnc_cellblock_next_right (CellBlock *cellblock,
int row, int col,
int next_row, int next_col)
{
if (!cellblock) return;
CellTraverseInfo *ct_info;
/* avoid embarrasement if cell incorrectly specified */
if ((0 > row) || (0 > col)) return;
if ((row >= cellblock->numRows) || (col >= cellblock->numCols)) return;
if (!cellblock) return;
/* -1 is a valid value for next ... it signifies that traversal
* should go to next tab group, so do not check for neg values.
*/
/* avoid embarrasement if cell incorrectly specified */
if ((0 > row) || (0 > col)) return;
if ((row >= cellblock->num_rows) || (col >= cellblock->num_cols)) return;
/* if the "next" location to hop to is larger than the cursor, that
* just means that we should hop to the next cursor. Thus, large
* values for next *are* valid.
*/
ct_info = gnc_cellblock_get_traverse (cellblock, row, col);
(cellblock->left_traverse_r)[row][col] = next_row;
(cellblock->left_traverse_c)[row][col] = next_col;
/* -1 is a valid value for next_*, signifying that traversal should
* go to next tab group, so do not check for neg values. */
/* if traversing out (neg values) record this as the last ... */
if ((0 > next_row) || (0 > next_col)) {
cellblock->last_left_reenter_traverse_row = row;
cellblock->last_left_reenter_traverse_col = col;
}
/* if the "next" location to hop to is larger than the cursor, that
* just means that we should hop to the next cursor. Thus, large
* values for next *are* valid. */
ct_info->right_traverse_row = next_row;
ct_info->right_traverse_col = next_col;
/* if traversing out (neg values) record this as the last ... */
if ((0 > next_row) || (0 > next_col))
{
cellblock->last_reenter_traverse_row = row;
cellblock->last_reenter_traverse_col = col;
}
}
void
gnc_cellblock_next_left (CellBlock *cellblock,
int row, int col,
int next_row, int next_col)
{
CellTraverseInfo *ct_info;
if (!cellblock) return;
/* avoid embarrasement if cell incorrectly specified */
if ((0 > row) || (0 > col)) return;
if ((row >= cellblock->num_rows) || (col >= cellblock->num_cols)) return;
ct_info = gnc_cellblock_get_traverse (cellblock, row, col);
/* -1 is a valid value for next ... it signifies that traversal
* should go to next tab group, so do not check for neg values. */
/* if the "next" location to hop to is larger than the cursor, that
* just means that we should hop to the next cursor. Thus, large
* values for next *are* valid. */
ct_info->left_traverse_row = next_row;
ct_info->left_traverse_col = next_col;
/* if traversing out (neg values) record this as the last ... */
if ((0 > next_row) || (0 > next_col))
{
cellblock->last_left_reenter_traverse_row = row;
cellblock->last_left_reenter_traverse_col = col;
}
}
/* --------------- end of file ----------------- */

View File

@ -61,94 +61,96 @@
#include "basiccell.h"
enum _Alignments {
ALIGN_RIGHT,
ALIGN_CENTER,
ALIGN_LEFT,
ALIGN_FILL,
};
#include "gtable.h"
typedef enum _Alignments Alignments;
struct _CellBlock {
typedef enum
{
CELL_ALIGN_RIGHT,
CELL_ALIGN_CENTER,
CELL_ALIGN_LEFT,
CELL_ALIGN_FILL,
} CellAlignment;
short numRows;
short numCols;
typedef struct
{
BasicCell *cell; /* cell handler */
short cell_type; /* cell type from splitreg.h */
/* The array "cells" of pointers to cells has dimensions of numRows*numCols.
* It is automatically created and managed by the routines below.
* It contains pointers to the cell handlers that are a part of
* this "block".
*/
BasicCell ***cells; /* row-col array */
/* GUI layout information */
char *sample_text; /* sample text for sizing purposes */
CellAlignment alignment;
gboolean resizable;
} CellBlockCell;
short **cell_types; /* row-col array of the cell types in splitreg.h */
typedef struct
{
short right_traverse_row;
short right_traverse_col;
short left_traverse_row;
short left_traverse_col;
} CellTraverseInfo;
typedef struct
{
short num_rows;
short num_cols;
GTable *cb_cells; /* Holds the CellBlockCell data */
/* The active_bg_color is the default color (in argb) for the cell
* backgrounds when this cell block needs to be "highlighted" in
* some way (typically, when this cellblock represents the
* the currently active cursor).
* backgrounds when this cell block needs to be "highlighted" in
* some way (typically, when this cellblock represents the the
* currently active cursor).
*
* The passive_bg_color is the default color for the cell background
* (in argb format) of the first row when the cell block is not highlighted.
*
* The passive_bg_color2 is the default color for cell backgrounds
* in other rows of the cellblock when it is not highlighted.
*/
* in other rows of the cellblock when it is not highlighted. */
guint32 active_bg_color;
guint32 passive_bg_color;
guint32 passive_bg_color2;
/* other attributes */
Alignments *alignments; /* column text alignments */
short **right_traverse_r;
short **right_traverse_c;
short **left_traverse_r;
short **left_traverse_c;
short right_exit_r;
short right_exit_c;
short left_exit_r;
short left_exit_c;
/* the above arrays have dimension of numRows*numCols.
* the are automatically created and managed by the routines below.
* The control the tab-traversal order through this cell block.
* If the cell (i,j) has input-focus, then hitting the tab key
* on the keyboard will take input-focus to cell (inext,jnext), where
* inext = right_traverse_r[i][j] and jnext = right_traverse_c[i][j].
/* The traverse and exit information is automatically created and
* managed by the routines below. They control the tab-traversal
* order through this cell block. If the cell (i,j) has
* input-focus, then hitting the tab key on the keyboard will take
* input-focus to cell (inext,jnext), where inext =
* right_traverse_r[i][j] and jnext = right_traverse_c[i][j].
*
* (exit_r, exit_c) is the last cell of this tab group.
*/
* (*_exit_r, *_exit_c) is the last cell of this tab group. */
GTable *traverse_info;
/* the last-reenter row and column should contain the very last
* cell when the cursor was traversed out of. They determine
* the first cell that will be entered (since the first follows
* the last).
*/
/* the last-reenter row and column should contain the very last cell
* when the cursor was traversed out of. They determine the first
* cell that will be entered (since the first follows the last). */
short last_reenter_traverse_row;
short last_reenter_traverse_col;
short last_left_reenter_traverse_row;
short last_left_reenter_traverse_col;
void * user_data;
/* above is a pointer to anything the programmer-user of this struct
* wants it to be. Handy for stuff. */
};
void * user_data; /* for user code use */
} CellBlock;
typedef struct _CellBlock CellBlock;
CellBlock * xaccMallocCellBlock (int numrows, int numcols);
void xaccInitCellBlock (CellBlock *, int numrows, int numcols);
void xaccDestroyCellBlock (CellBlock *);
CellBlock * gnc_cellblock_new (int rows, int cols);
void gnc_cellblock_destroy (CellBlock *cellblock);
CellBlockCell * gnc_cellblock_get_cell (CellBlock *cellblock,
int row, int col);
CellTraverseInfo * gnc_cellblock_get_traverse (CellBlock *cellblock,
int row, int col);
/* define next cell to traverse to */
void xaccNextRight (CellBlock *cellblock,
int row, int col,
int next_row, int next_col);
void gnc_cellblock_next_right (CellBlock *cellblock,
int row, int col,
int next_row, int next_col);
void xaccNextLeft (CellBlock *cellblock,
int row, int col,
int next_row, int next_col);
void gnc_cellblock_next_left (CellBlock *cellblock,
int row, int col,
int next_row, int next_col);
#endif /* __XACC_CELL_BLOCK_H__ */

View File

@ -321,13 +321,10 @@ draw_cell (GnucashGrid *grid, int block,
10, 10,
180*64, 90*64);
#endif /* ROUNDED_CORNERS */
text = sheet_block->entries[i][j];
if (style->fonts[i][j])
font = style->fonts[i][j];
else
font = grid->normal_font;
font = grid->normal_font;
gdk_gc_set_foreground (grid->gc, sheet_block->fg_colors[i][j]);

View File

@ -133,10 +133,7 @@ item_edit_draw_info(ItemEdit *item_edit, int x, int y, TextDrawInfo *info)
style = item_edit->style;
if (style->fonts[item_edit->cell_row][item_edit->cell_col])
info->font = style->fonts[item_edit->cell_row][item_edit->cell_col];
else
info->font = GNUCASH_GRID(item_edit->sheet->grid)->normal_font;
info->font = GNUCASH_GRID(item_edit->sheet->grid)->normal_font;
info->bg_color = style->active_bg_color[item_edit->cell_row]
[item_edit->cell_col];

View File

@ -1640,7 +1640,7 @@ gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
new_phys_loc.phys_row =
MAX(cur_phys_loc.phys_row -
(sheet->bottom_block - sheet->top_block),
header->numRows);
header->num_rows);
break;
case GDK_KP_Page_Down:
case GDK_Page_Down:
@ -1656,7 +1656,7 @@ gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
direction = GNC_TABLE_TRAVERSE_UP;
new_phys_loc.phys_col = cur_phys_loc.phys_col;
new_phys_loc.phys_row = MAX(cur_phys_loc.phys_row - 1,
header->numRows);
header->num_rows);
break;
case GDK_KP_Down:
case GDK_Down:
@ -2120,16 +2120,13 @@ gnucash_sheet_col_max_width (GnucashSheet *sheet, gint virt_col, gint cell_col)
text = gnucash_sheet_block_get_text (sheet,
virt_loc);
if (style->fonts[cell_row][cell_col])
font = style->fonts[cell_row][cell_col];
else
font = GNUCASH_GRID(sheet->grid)->normal_font;
font = GNUCASH_GRID(sheet->grid)->normal_font;
if (!text || strlen(text) == 0) {
text = style->labels[cell_row][cell_col];
font = style->header_font;
}
width = gdk_string_measure (font, text) + 2*CELL_HPADDING;
max = MAX (max, width);
}

View File

@ -68,7 +68,6 @@ typedef struct
gint width;
/* per cell parameters */
gint **pixel_heights; /* in pixels, may be zero if
row/column not displayed */
gint **pixel_widths;
@ -78,7 +77,6 @@ typedef struct
gint nrows, ncols;
gint refcount;
} CellDimensions;
typedef struct
@ -94,11 +92,8 @@ typedef struct
gchar ***labels; /* for the header */
GdkFont *header_font;
GtkJustification **alignments;
/* per cell fonts; if NULL, use the grid normal font */
GdkFont ***fonts;
GtkJustification **alignments;
GdkColor ***active_bg_color;
GdkColor ***inactive_bg_color;

View File

@ -571,8 +571,6 @@ layout_init_stock_ledger_double(GnucashSheet *sheet, SheetBlockStyle *style)
layout_info->refcount++;
}
/* FIXME: read this from a config file */
/* keep this in sync with splitreg.c */
static void
gnucash_style_layout_init (GnucashSheet *sheet, SheetBlockStyle *style)
{
@ -682,13 +680,11 @@ style_dimensions_new (SheetBlockStyle *style)
for (j = 0; j < style->ncols; j++)
dimensions->pixel_widths[i][j] = -1;
dimensions->origin_x[i] = g_new0 (gint, style->ncols);
dimensions->origin_y[i] = g_new0 (gint, style->ncols);
}
return dimensions;
}
@ -761,16 +757,15 @@ set_dimensions_pass_one (GnucashSheet *sheet, CellLayoutInfo *layout_info,
GdkFont *font = GNUCASH_GRID(sheet->grid)->normal_font;
g_return_if_fail (font != NULL);
for (j = 0; j < layout_info->ncols; j++) {
for (j = 0; j < layout_info->ncols; j++) {
if (dimensions->pixel_widths[i][j] < 0)
dimensions->pixel_widths[i][j] = layout_info->cell_perc[i][j] * dimensions->width + 0.5;
dimensions->pixel_heights[i][j] =
font->ascent + font->descent +
2*CELL_VPADDING;
}
dimensions->height += dimensions->pixel_heights[i][0];
}
dimensions->height += dimensions->pixel_heights[i][0];
}
/* Attempt to convert character width to pixels */
@ -1078,9 +1073,14 @@ sheet_recompute_style_dimensions_internal (gpointer _key,
gchar *key = _key;
CellLayoutInfo *layout_info = _layout_info;
GnucashSheet *sheet = _data;
CellDimensions *dimensions;
int width;
dimensions = g_hash_table_lookup (sheet->dimensions_hash_table, key);
width = dimensions->width;
style_recompute_layout_dimensions (sheet, layout_info,
g_hash_table_lookup (sheet->dimensions_hash_table, key));
dimensions, width);
}
@ -1091,7 +1091,8 @@ gnucash_sheet_recompute_style_dimensions (GnucashSheet *sheet)
g_return_if_fail (GNUCASH_IS_SHEET (sheet));
g_hash_table_foreach (sheet->layout_info_hash_table,
sheet_recompute_style_dimensions_internal, sheet);
sheet_recompute_style_dimensions_internal,
sheet);
}
#endif
@ -1115,7 +1116,7 @@ gnucash_style_col_is_resizable (SheetBlockStyle *style, int col)
return (style->layout_info->user_flags[0][col] & RESIZABLE);
}
/*
* Set width of a specified cell and set the PIXEL_FIXED flag.
* If same_size is TRUE, also set the width of any
@ -1133,40 +1134,41 @@ gnucash_sheet_style_set_col_width (GnucashSheet *sheet, SheetBlockStyle *style,
g_return_if_fail (col >= 0);
g_return_if_fail (col < style->ncols);
if (width >= 0) {
if (width < 0)
return;
style->layout_info->flags[0][col] = (style->layout_info->flags[0][col] & FILL);
style->layout_info->flags[0][col] = (style->layout_info->flags[0][col] & FILL);
/* adjust the overall width of this style */
style->dimensions->width -= style->dimensions->pixel_widths[0][col] - width;
/* adjust the overall width of this style */
style->dimensions->width -= style->dimensions->pixel_widths[0][col] - width;
style->dimensions->pixel_widths[0][col] = width;
style->dimensions->pixel_widths[0][col] = width;
for (i = 0; i < style->nrows; i++) {
for (j = 0; j < style->ncols; j++) {
if ((style->layout_info->flags[i][j] & SAME_SIZE)
&& (style->layout_info->size_r[i][j] == 0)
&& (style->layout_info->size_c[i][j] == col)) {
if (same_size) {
/* adjust the overall width of this style */
style->dimensions->width -= style->dimensions->pixel_widths[0][col] - width;
style->dimensions->pixel_widths[i][j] = width;
}
else
{
style->layout_info->flags[i][j] = CELL_FIXED;
}
for (i = 0; i < style->nrows; i++) {
for (j = 0; j < style->ncols; j++) {
if ((style->layout_info->flags[i][j] & SAME_SIZE)
&& (style->layout_info->size_r[i][j] == 0)
&& (style->layout_info->size_c[i][j] == col)) {
if (same_size) {
/* adjust the overall width of this style */
style->dimensions->width -= style->dimensions->pixel_widths[0][col] - width;
style->dimensions->pixel_widths[i][j] = width;
}
else
{
style->layout_info->flags[i][j] = CELL_FIXED;
}
}
}
style->dimensions->width = compute_row_width (style->dimensions, 0, 0, style->ncols - 1);
compute_cell_origins_x (style->dimensions, 0);
for (i = 1; i < style->nrows; i++)
set_dimensions_pass_four (sheet, style->layout_info, style->dimensions, i);
}
style->dimensions->width = compute_row_width (style->dimensions, 0, 0, style->ncols - 1);
compute_cell_origins_x (style->dimensions, 0);
for (i = 1; i < style->nrows; i++)
set_dimensions_pass_four (sheet, style->layout_info,
style->dimensions, i);
}
@ -1179,7 +1181,6 @@ gnucash_sheet_style_destroy (GnucashSheet *sheet, SheetBlockStyle *style)
for ( i = 0; i < style->nrows; i++) {
g_free(style->alignments[i]);
g_free(style->fonts[i]);
g_free(style->active_bg_color[i]);
g_free(style->inactive_bg_color[i]);
for (j = 0; j < style->ncols; j++)
@ -1189,7 +1190,6 @@ gnucash_sheet_style_destroy (GnucashSheet *sheet, SheetBlockStyle *style)
}
g_free(style->alignments);
g_free(style->fonts);
g_free(style->active_bg_color);
g_free(style->inactive_bg_color);
g_free(style->labels);
@ -1228,9 +1228,12 @@ gnucash_sheet_style_recompile(SheetBlockStyle *style, CellBlock *cellblock,
for (i = 0; i < style->nrows; i++) {
for (j = 0; j < style->ncols; j++) {
type = cellblock->cell_types[i][j];
CellBlockCell *cb_cell;
cb_cell = gnc_cellblock_get_cell (cellblock, i, j);
type = cb_cell->cell_type;
style->fonts[i][j] = NULL;
style->header_font = gnucash_register_font;
gnucash_style_set_borders (style, reg_borders);
@ -1238,7 +1241,7 @@ gnucash_sheet_style_recompile(SheetBlockStyle *style, CellBlock *cellblock,
if (type > -1)
label = sr->header_label_cells[type]->value;
else if (cursor_type == GNUCASH_CURSOR_HEADER)
label = cellblock->cells[i][j]->value;
label = cb_cell->cell->value;
else
label = "";
@ -1253,18 +1256,18 @@ gnucash_sheet_style_recompile(SheetBlockStyle *style, CellBlock *cellblock,
gnucash_color_argb_to_gdk
(cellblock->passive_bg_color);
switch (cellblock->alignments[j]) {
case ALIGN_RIGHT:
switch (cb_cell->alignment) {
case CELL_ALIGN_RIGHT:
style->alignments[i][j] =
GTK_JUSTIFY_RIGHT;
break;
case ALIGN_CENTER:
case CELL_ALIGN_CENTER:
style->alignments[i][j] =
GTK_JUSTIFY_CENTER;
break;
default:
case ALIGN_FILL:
case ALIGN_LEFT:
case CELL_ALIGN_FILL:
case CELL_ALIGN_LEFT:
style->alignments[i][j] =
GTK_JUSTIFY_LEFT;
break;
@ -1301,7 +1304,7 @@ gnucash_style_set_borders (SheetBlockStyle *style, int border)
for (col = 0; col < style->ncols; col++)
gnucash_style_set_cell_borders (style, row, col,
border);
style->borders[row][0] |= STYLE_BORDER_LEFT;
style->borders[row][style->ncols - 1] |= STYLE_BORDER_RIGHT;
}
@ -1338,11 +1341,10 @@ gnucash_sheet_style_compile (GnucashSheet *sheet, CellBlock *cellblock,
style->reg_type = sr->type;
style->cursor_type = cursor_type;
style->nrows = cellblock->numRows;
style->ncols = cellblock->numCols;
style->nrows = cellblock->num_rows;
style->ncols = cellblock->num_cols;
style->alignments = g_new0 (GtkJustification *, style->nrows);
style->fonts = g_new0 (GdkFont **, style->nrows);
style->active_bg_color = g_new0 (GdkColor **, style->nrows);
style->inactive_bg_color = g_new0 (GdkColor **, style->nrows);
style->labels = g_new0 (char **, style->nrows);
@ -1350,7 +1352,6 @@ gnucash_sheet_style_compile (GnucashSheet *sheet, CellBlock *cellblock,
for ( i = 0; i < style->nrows; i++) {
style->alignments[i] = g_new0 (GtkJustification, style->ncols);
style->fonts[i] = g_new0 (GdkFont *, style->ncols);
style->active_bg_color[i] = g_new0 (GdkColor *, style->ncols);
style->inactive_bg_color[i] = g_new0(GdkColor *, style->ncols);
style->labels[i] = g_new0 (char *, style->ncols);
@ -1362,6 +1363,7 @@ gnucash_sheet_style_compile (GnucashSheet *sheet, CellBlock *cellblock,
gnucash_style_layout_init (sheet, style);
gnucash_style_dimensions_init (sheet, style);
gnucash_sheet_style_set_dimensions (sheet, style, DEFAULT_STYLE_WIDTH);
return style;
}
@ -1374,11 +1376,11 @@ gnucash_sheet_style_get_cell_pixel_rel_coords (SheetBlockStyle *style,
gint *w, gint *h)
{
gint i;
g_return_if_fail (style != NULL);
g_return_if_fail (cell_row >= 0 && cell_row <= style->nrows);
g_return_if_fail (cell_col >= 0 && cell_col <= style->ncols);
*y = 0;
for (i = 0; i < cell_row; i++)
*y += style->dimensions->pixel_heights[i][0];
@ -1397,7 +1399,7 @@ SheetBlockStyle *
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);

137
src/register/gtable.c Normal file
View File

@ -0,0 +1,137 @@
/********************************************************************\
* 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 *
* *
\********************************************************************/
#include "config.h"
#include "gtable.h"
struct GTable
{
GPtrArray *array;
int rows;
int cols;
g_table_allocator allocator;
g_table_deallocator deallocator;
};
GTable *
g_table_new (g_table_allocator allocator,
g_table_deallocator deallocator)
{
GTable *gtable;
g_assert (allocator);
g_assert (deallocator);
gtable = g_new(GTable, 1);
gtable->array = g_ptr_array_new();
gtable->rows = 0;
gtable->cols = 0;
gtable->allocator = allocator;
gtable->deallocator = deallocator;
return gtable;
}
void
g_table_destroy (GTable *gtable)
{
if (gtable == NULL)
return;
g_table_resize (gtable, 0, 0);
g_ptr_array_free (gtable->array, FALSE);
gtable->array = NULL;
g_free(gtable);
}
gpointer
g_table_index (GTable *gtable, int row, int col)
{
guint index;
if (gtable == NULL)
return NULL;
if ((row < 0) || (col < 0))
return NULL;
if (row >= gtable->rows)
return NULL;
if (col >= gtable->cols)
return NULL;
index = (row * gtable->cols) + col;
return gtable->array->pdata[index];
}
void
g_table_resize (GTable *gtable, int rows, int cols)
{
guint old_len;
guint new_len;
if (gtable == NULL)
return;
if ((rows < 0) || (cols < 0))
return;
old_len = gtable->array->len;
new_len = rows * cols;
if (new_len == old_len)
return;
/* If shrinking, free extra cells */
if (new_len < old_len)
{
gpointer *tcp;
guint i;
tcp = &gtable->array->pdata[new_len];
for (i = new_len; i < old_len; i++, tcp++)
gtable->deallocator(*tcp);
}
/* Change the size */
g_ptr_array_set_size(gtable->array, new_len);
/* If expanding, create the new cells */
if (new_len > old_len)
{
gpointer *tcp;
guint i;
tcp = &gtable->array->pdata[old_len];
for (i = old_len; i < new_len; i++, tcp++)
*tcp = gtable->allocator();
}
gtable->rows = rows;
gtable->cols = cols;
}

56
src/register/gtable.h Normal file
View File

@ -0,0 +1,56 @@
/********************************************************************\
* 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 __G_TABLE_H__
#define __G_TABLE_H__
#include "config.h"
#include <glib.h>
/* This is the API for GTables, a datatype for 2-dimensional tables
* with automatic resizing and memory management. */
typedef struct GTable GTable;
typedef gpointer (*g_table_allocator) (void);
typedef void (*g_table_deallocator) (gpointer);
/* Create a new table with the given allocator and deallocator.
* Both functions must be given. They are used to populate the
* table and free extra members when resizing and destroying. */
GTable * g_table_new (g_table_allocator allocator,
g_table_deallocator deallocator);
/* Free the table and all associated table elements. */
void g_table_destroy (GTable *gtable);
/* Return the element at the given row and column. If the coordinates
* are out-of-bounds, return NULL */
gpointer g_table_index (GTable *gtable, int row, int col);
/* Resize the table, allocating and deallocating extra table
* members if needed. The relationship between table members
* before and after resizing is undefined. */
void g_table_resize (GTable *gtable, int rows, int cols);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -63,8 +63,10 @@ static GMemChunk *cell_mem_chunk = NULL;
/** Prototypes *********************************************************/
static void gnc_table_init (Table * table);
static void gnc_table_free_data (Table * table);
static void gnc_virtual_cell_free (TableCell *tcell);
static void gnc_physical_cell_free (TableCell *tcell);
static gpointer gnc_virtual_cell_new (void);
static gpointer gnc_physical_cell_new (void);
static void gnc_virtual_cell_free (gpointer tcell);
static void gnc_physical_cell_free (gpointer tcell);
static void gnc_table_resize (Table * table,
int new_phys_rows, int new_phys_cols,
int new_virt_rows, int new_virt_cols);
@ -85,8 +87,11 @@ gnc_table_new (void)
gnc_table_init (table);
table->virt_cells = g_ptr_array_new();
table->phys_cells = g_ptr_array_new();
table->virt_cells = g_table_new(gnc_virtual_cell_new,
gnc_virtual_cell_free);
table->phys_cells = g_table_new(gnc_physical_cell_new,
gnc_physical_cell_free);
return table;
}
@ -114,7 +119,6 @@ gnc_table_init (Table * table)
table->alternate_bg_colors = FALSE;
/* initialize private data */
table->virt_cells = NULL;
@ -140,11 +144,9 @@ gnc_table_destroy (Table * table)
/* free the dynamic structures */
gnc_table_free_data (table);
/* free the pointer arrays */
if (table->virt_cells != NULL)
g_ptr_array_free(table->virt_cells, FALSE);
if (table->phys_cells != NULL)
g_ptr_array_free(table->phys_cells, FALSE);
/* free the cell tables */
g_table_destroy(table->virt_cells);
g_table_destroy(table->phys_cells);
/* intialize vars to null value so that any access is voided. */
gnc_table_init (table);
@ -158,18 +160,16 @@ VirtualCell *
gnc_table_get_virtual_cell (Table *table, VirtualCellLocation vcell_loc)
{
TableCell *tcell;
guint index;
if (table == NULL)
return NULL;
if (gnc_table_virtual_cell_out_of_bounds (table, vcell_loc))
tcell = g_table_index (table->virt_cells,
vcell_loc.virt_row, vcell_loc.virt_col);
if (tcell == NULL)
return NULL;
index = (vcell_loc.virt_row * table->num_virt_cols) + vcell_loc.virt_col;
tcell = table->virt_cells->pdata[index];
return &tcell->virt_cell;
}
@ -179,18 +179,16 @@ PhysicalCell *
gnc_table_get_physical_cell (Table *table, PhysicalLocation phys_loc)
{
TableCell *tcell;
guint index;
if (table == NULL)
return NULL;
if (gnc_table_physical_cell_out_of_bounds (table, phys_loc))
tcell = g_table_index (table->phys_cells,
phys_loc.phys_row, phys_loc.phys_col);
if (tcell == NULL)
return NULL;
index = (phys_loc.phys_row * table->num_phys_cols) + phys_loc.phys_col;
tcell = table->phys_cells->pdata[index];
return &tcell->phys_cell;
}
@ -199,7 +197,7 @@ gnc_table_get_physical_cell (Table *table, PhysicalLocation phys_loc)
VirtualCell *
gnc_table_get_header_cell (Table *table)
{
VirtualCellLocation vcell_loc = { 0, 0};
VirtualCellLocation vcell_loc = { 0, 0 };
return gnc_table_get_virtual_cell (table, vcell_loc);
}
@ -251,41 +249,8 @@ gnc_table_free_data (Table * table)
if (table == NULL)
return;
if (table->virt_cells != NULL)
{
gpointer *tcp;
guint len;
tcp = table->virt_cells->pdata;
len = table->virt_cells->len;
while (len > 0)
{
gnc_virtual_cell_free(*tcp);
tcp++;
len--;
}
g_ptr_array_set_size(table->virt_cells, 0);
}
if (table->phys_cells != NULL)
{
gpointer *tcp;
guint len;
tcp = table->phys_cells->pdata;
len = table->phys_cells->len;
while (len > 0)
{
gnc_physical_cell_free(*tcp);
tcp++;
len--;
}
g_ptr_array_set_size(table->phys_cells, 0);
}
g_table_resize (table->virt_cells, 0, 0);
g_table_resize (table->phys_cells, 0, 0);
}
/* ==================================================== */
@ -316,7 +281,7 @@ gnc_physical_location_init (PhysicalLocation *ploc)
/* ==================================================== */
static TableCell *
static gpointer
gnc_virtual_cell_new (void)
{
TableCell *tcell;
@ -337,7 +302,7 @@ gnc_virtual_cell_new (void)
/* ==================================================== */
static void
gnc_virtual_cell_free (TableCell *tcell)
gnc_virtual_cell_free (gpointer tcell)
{
if (tcell == NULL)
return;
@ -347,7 +312,7 @@ gnc_virtual_cell_free (TableCell *tcell)
/* ==================================================== */
static TableCell *
static gpointer
gnc_physical_cell_new (void)
{
TableCell *tcell;
@ -371,8 +336,10 @@ gnc_physical_cell_new (void)
/* ==================================================== */
static void
gnc_physical_cell_free (TableCell *tcell)
gnc_physical_cell_free (gpointer _tcell)
{
TableCell *tcell = _tcell;
if (tcell == NULL)
return;
@ -384,49 +351,6 @@ gnc_physical_cell_free (TableCell *tcell)
/* ==================================================== */
typedef TableCell * (*CellAllocator) (void);
typedef void (*CellDeAllocator) (TableCell *);
static void
gnc_array_resize (GPtrArray *array,
int rows, int cols,
CellAllocator allocator,
CellDeAllocator deallocator)
{
guint old_len = array->len;
guint new_len = rows * cols;
if (new_len == old_len)
return;
/* If shrinking, free extra cells */
if (new_len < old_len)
{
gpointer *tcp;
guint i;
tcp = &array->pdata[new_len];
for (i = new_len; i < old_len; i++, tcp++)
deallocator(*tcp);
}
/* Change the size */
g_ptr_array_set_size(array, new_len);
/* If expanding, create the new cells */
if (new_len > old_len)
{
gpointer *tcp;
guint i;
tcp = &array->pdata[old_len];
for (i = old_len; i < new_len; i++, tcp++)
*tcp = allocator();
}
}
/* ==================================================== */
static void
gnc_table_resize (Table * table,
int new_phys_rows, int new_phys_cols,
@ -444,15 +368,8 @@ gnc_table_resize (Table * table,
exit (1);
}
gnc_array_resize (table->virt_cells,
new_virt_rows, new_virt_cols,
gnc_virtual_cell_new,
gnc_virtual_cell_free);
gnc_array_resize (table->phys_cells,
new_phys_rows, new_phys_cols,
gnc_physical_cell_new,
gnc_physical_cell_free);
g_table_resize (table->virt_cells, new_virt_rows, new_virt_cols);
g_table_resize (table->phys_cells, new_phys_rows, new_phys_cols);
table->num_phys_rows = new_phys_rows;
table->num_phys_cols = new_phys_cols;
@ -488,8 +405,8 @@ gnc_table_set_cursor (Table *table, CellBlock *curs,
/* intialize the mapping so that we will be able to find
* the handler, given this range of physical cell addresses */
for (cell_row = 0; cell_row < curs->numRows; cell_row++)
for (cell_col = 0; cell_col < curs->numCols; cell_col++)
for (cell_row = 0; cell_row < curs->num_rows; cell_row++)
for (cell_col = 0; cell_col < curs->num_cols; cell_col++)
{
PhysicalCell *pcell;
PhysicalLocation ploc = { phys_origin.phys_row + cell_row,
@ -530,12 +447,12 @@ gnc_table_make_passive (Table *table)
curs = table->current_cursor;
for (cell_row=0; cell_row < curs->numRows; cell_row++)
for (cell_col = 0; cell_col < curs->numCols; cell_col++)
for (cell_row=0; cell_row < curs->num_rows; cell_row++)
for (cell_col = 0; cell_col < curs->num_cols; cell_col++)
{
PhysicalLocation ploc = { phys_origin.phys_row + cell_row,
phys_origin.phys_col + cell_col };
BasicCell *cell;
CellBlockCell *cb_cell;
guint32 color;
pcell = gnc_table_get_physical_cell (table, ploc);
@ -554,12 +471,14 @@ gnc_table_make_passive (Table *table)
pcell->bg_color = color;
cell = curs->cells[cell_row][cell_col];
if (cell)
cb_cell = gnc_cellblock_get_cell (curs, cell_row, cell_col);
if (cb_cell && cb_cell->cell)
{
BasicCell *cell = cb_cell->cell;
if (cell->use_bg_color)
pcell->bg_color = cell->bg_color;
if (cell->use_fg_color)
if (cb_cell->cell->use_fg_color)
pcell->fg_color = cell->fg_color;
}
}
@ -635,14 +554,16 @@ gnc_table_move_cursor_internal (Table *table,
* as a command to unmap the cursor gui. So do it .. */
if (do_move_gui && curs)
{
for (cell_row = 0; cell_row < curs->numRows; cell_row++)
for (cell_col = 0; cell_col < curs->numCols; cell_col++)
for (cell_row = 0; cell_row < curs->num_rows; cell_row++)
for (cell_col = 0; cell_col < curs->num_cols; cell_col++)
{
BasicCell *cell;
CellBlockCell *cb_cell;
cell = curs->cells[cell_row][cell_col];
if (cell)
cb_cell = gnc_cellblock_get_cell (curs, cell_row, cell_col);
if (cb_cell && cb_cell->cell)
{
BasicCell *cell = cb_cell->cell;
cell->changed = 0;
if (cell->move)
{
@ -686,10 +607,10 @@ gnc_table_move_cursor_internal (Table *table,
table->prev_phys_traverse_loc.phys_col += curs->last_reenter_traverse_col;
/* update the cell values to reflect the new position */
for (cell_row = 0; cell_row < curs->numRows; cell_row++)
for (cell_col = 0; cell_col < curs->numCols; cell_col++)
for (cell_row = 0; cell_row < curs->num_rows; cell_row++)
for (cell_col = 0; cell_col < curs->num_cols; cell_col++)
{
BasicCell *cell;
CellBlockCell *cb_cell;
PhysicalLocation ploc = { phys_origin.phys_row + cell_row,
phys_origin.phys_col + cell_col };
@ -698,9 +619,11 @@ gnc_table_move_cursor_internal (Table *table,
/* change the cursor row to the active color */
pcell->bg_color = curs->active_bg_color;
cell = curs->cells[cell_row][cell_col];
if (cell)
cb_cell = gnc_cellblock_get_cell(curs, cell_row, cell_col);
if (cb_cell && cb_cell->cell)
{
BasicCell *cell = cb_cell->cell;
/* if a cell has a GUI, move that first, before setting
* the cell value. Otherwise, we'll end up putting the
* new values in the old cell locations, and that would
@ -781,16 +704,18 @@ gnc_table_commit_cursor (Table *table)
phys_origin.phys_row -= pcell->virt_loc.phys_row_offset;
phys_origin.phys_col -= pcell->virt_loc.phys_col_offset;
for (cell_row = 0; cell_row < curs->numRows; cell_row++)
for (cell_col = 0; cell_col < curs->numCols; cell_col++)
for (cell_row = 0; cell_row < curs->num_rows; cell_row++)
for (cell_col = 0; cell_col < curs->num_cols; cell_col++)
{
BasicCell *cell;
CellBlockCell *cb_cell;
PhysicalLocation ploc = { phys_origin.phys_row + cell_row,
phys_origin.phys_col + cell_col };
cell = curs->cells[cell_row][cell_col];
if (cell)
cb_cell = gnc_cellblock_get_cell(curs, cell_row, cell_col);
if (cb_cell && cb_cell->cell)
{
BasicCell *cell = cb_cell->cell;
pcell = gnc_table_get_physical_cell (table, ploc);
g_free (pcell->entry);
@ -823,22 +748,22 @@ gnc_table_refresh_header (Table *table)
cb = vcell->cellblock;
if (cb == NULL) return;
for (cell_row = 0; cell_row < cb->numRows; cell_row++)
for (cell_col = 0; cell_col < cb->numCols; cell_col++)
for (cell_row = 0; cell_row < cb->num_rows; cell_row++)
for (cell_col = 0; cell_col < cb->num_cols; cell_col++)
{
PhysicalLocation ploc = { cell_row, cell_col };
CellBlockCell *cb_cell;
PhysicalCell *pcell;
BasicCell *cell;
/* Assumes header starts at physical (0, 0) */
pcell = gnc_table_get_physical_cell (table, ploc);
g_free(pcell->entry);
cell = cb->cells[cell_row][cell_col];
cb_cell = gnc_cellblock_get_cell(cb, cell_row, cell_col);
if (cell && cell->value)
pcell->entry = g_strdup (cell->value);
if (cb_cell && cb_cell->cell && cb_cell->cell->value)
pcell->entry = g_strdup (cb_cell->cell->value);
else
pcell->entry = g_strdup ("");
}
@ -965,13 +890,15 @@ gnc_table_create_cursor (Table * table, CellBlock *curs)
if (!curs || !table) return;
if (!table->ui_data) return;
for (cell_row = 0; cell_row < curs->numRows; cell_row++)
for (cell_col = 0; cell_col < curs->numCols; cell_col++)
for (cell_row = 0; cell_row < curs->num_rows; cell_row++)
for (cell_col = 0; cell_col < curs->num_cols; cell_col++)
{
BasicCell *cell;
cell = curs->cells[cell_row][cell_col];
if (cell && cell->realize)
cell->realize (cell, table->ui_data);
CellBlockCell *cb_cell;
cb_cell = gnc_cellblock_get_cell (curs, cell_row, cell_col);
if (cb_cell && cb_cell->cell && cb_cell->cell->realize)
cb_cell->cell->realize (cb_cell->cell, table->ui_data);
}
}
@ -1022,12 +949,11 @@ gnc_table_physical_cell_valid(Table *table,
PhysicalLocation phys_loc,
gboolean exact_cell)
{
CellBlock *cb;
BasicCell *cell;
VirtualCell *vcell;
PhysicalCell *pcell;
gboolean invalid = FALSE;
CellBlockCell *cb_cell;
VirtualLocation virt_loc;
int io_flag;
if (!table) return FALSE;
@ -1042,7 +968,8 @@ gnc_table_physical_cell_valid(Table *table,
if (vcell == NULL)
return FALSE;
invalid = invalid || (phys_loc.phys_row < vcell->cellblock->numRows);
if (phys_loc.phys_row < vcell->cellblock->num_rows)
return FALSE;
/* compute the cell location */
virt_loc = pcell->virt_loc;
@ -1054,30 +981,30 @@ gnc_table_physical_cell_valid(Table *table,
/* verify that offsets are valid. This may occur if the app that is
* using the table has a paritally initialized cursor. (probably due
* to a programming error, but maybe they meant to do this). */
invalid = invalid || (0 > virt_loc.phys_row_offset);
invalid = invalid || (0 > virt_loc.phys_col_offset);
if (invalid) return FALSE;
cb = vcell->cellblock;
if ((0 > virt_loc.phys_row_offset) || (0 > virt_loc.phys_col_offset))
return FALSE;
/* check for a cell handler, but only if cell address is valid */
if (cb == NULL) return FALSE;
if (cb->cells[virt_loc.phys_row_offset]
[virt_loc.phys_col_offset] == NULL) return FALSE;
if (vcell->cellblock == NULL) return FALSE;
cb_cell = gnc_cellblock_get_cell (vcell->cellblock,
virt_loc.phys_row_offset,
virt_loc.phys_col_offset);
if (cb_cell == NULL)
return FALSE;
cell = cb_cell->cell;
if (cell == NULL)
return FALSE;
/* if cell is marked as output-only, you can't enter */
io_flag = cb->cells[virt_loc.phys_row_offset]
[virt_loc.phys_col_offset]->input_output;
if (0 == (XACC_CELL_ALLOW_INPUT & io_flag)) return FALSE;
if (0 == (XACC_CELL_ALLOW_INPUT & cell->input_output)) return FALSE;
/* if cell is pointer only and this is not an exact pointer test,
* it cannot be entered. */
if (!exact_cell && ((XACC_CELL_ALLOW_EXACT_ONLY & io_flag) != 0))
if (!exact_cell && ((XACC_CELL_ALLOW_EXACT_ONLY & cell->input_output) != 0))
return FALSE;
if (invalid) return FALSE;
return TRUE;
}
@ -1094,6 +1021,8 @@ gnc_table_enter_update(Table *table,
const char *retval = NULL;
PhysicalCell *pcell;
CellEnterFunc enter;
CellBlockCell *cb_cell;
BasicCell *cell;
CellBlock *cb;
int cell_row;
int cell_col;
@ -1110,12 +1039,14 @@ gnc_table_enter_update(Table *table,
cell_row = pcell->virt_loc.phys_row_offset;
cell_col = pcell->virt_loc.phys_col_offset;
ENTER("enter %d %d (relrow=%d relcol=%d) cell=%p val=%s\n",
phys_loc.phys_row, phys_loc.phys_col, cell_row, cell_col,
cb->cells[cell_row][cell_col], pcell->entry);
ENTER("enter %d %d (relrow=%d relcol=%d) val=%s\n",
phys_loc.phys_row, phys_loc.phys_col,
cell_row, cell_col, pcell->entry);
/* OK, if there is a callback for this cell, call it */
enter = cb->cells[cell_row][cell_col]->enter_cell;
cb_cell = gnc_cellblock_get_cell (cb, cell_row, cell_col);
cell = cb_cell->cell;
enter = cell->enter_cell;
if (enter)
{
@ -1125,8 +1056,8 @@ gnc_table_enter_update(Table *table,
cell_row, cell_col);
val = pcell->entry;
retval = enter(cb->cells[cell_row][cell_col], val,
cursor_position, start_selection, end_selection);
retval = enter(cell, val, cursor_position, start_selection, end_selection);
/* enter() might return null, or it might return a pointer to val,
* or it might return a new pointer (to newly malloc memory).
@ -1136,7 +1067,7 @@ gnc_table_enter_update(Table *table,
if (retval && (val != retval))
{
if (safe_strcmp(retval, val) != 0)
(cb->cells[cell_row][cell_col])->changed = GNC_CELL_CHANGED;
cell->changed = GNC_CELL_CHANGED;
g_free (pcell->entry);
pcell->entry = (char *) retval;
}
@ -1146,10 +1077,8 @@ gnc_table_enter_update(Table *table,
if (table->set_help)
{
BasicCell *cell;
char *help_str;
cell = cb->cells[cell_row][cell_col];
help_str = xaccBasicCellGetHelp(cell);
table->set_help(table, help_str);
@ -1176,6 +1105,8 @@ gnc_table_leave_update(Table *table,
const char *retval = NULL;
PhysicalCell *pcell;
CellLeaveFunc leave;
CellBlockCell *cb_cell;
BasicCell *cell;
CellBlock *cb;
int cell_row;
int cell_col;
@ -1200,10 +1131,13 @@ gnc_table_leave_update(Table *table,
callback_text = "";
/* OK, if there is a callback for this cell, call it */
leave = cb->cells[cell_row][cell_col]->leave_cell;
cb_cell = gnc_cellblock_get_cell (cb, cell_row, cell_col);
cell = cb_cell->cell;
leave = cell->leave_cell;
if (leave)
{
retval = leave(cb->cells[cell_row][cell_col], callback_text);
retval = leave(cell, callback_text);
/* leave() might return null, or it might return a pointer to
* callback_text, or it might return a new pointer (to newly
@ -1223,7 +1157,7 @@ gnc_table_leave_update(Table *table,
{
g_free (pcell->entry);
pcell->entry = (char *) retval;
(cb->cells[cell_row][cell_col])->changed = GNC_CELL_CHANGED;
cell->changed = GNC_CELL_CHANGED;
}
else
{
@ -1235,7 +1169,7 @@ gnc_table_leave_update(Table *table,
else
{
pcell->entry = (char *) retval;
(cb->cells[cell_row][cell_col])->changed = GNC_CELL_CHANGED;
cell->changed = GNC_CELL_CHANGED;
}
/* return the result of the final decisionmaking */
@ -1266,6 +1200,8 @@ gnc_table_modify_update(Table *table,
const char *retval = NULL;
CellModifyVerifyFunc mv;
PhysicalCell *pcell;
CellBlockCell *cb_cell;
BasicCell *cell;
CellBlock *cb;
int cell_row;
int cell_col;
@ -1285,11 +1221,13 @@ gnc_table_modify_update(Table *table,
ENTER ("\n");
/* OK, if there is a callback for this cell, call it */
mv = cb->cells[cell_row][cell_col]->modify_verify;
cb_cell = gnc_cellblock_get_cell (cb, cell_row, cell_col);
cell = cb_cell->cell;
mv = cell->modify_verify;
if (mv)
{
retval = mv (cb->cells[cell_row][cell_col],
oldval, change, newval, cursor_position,
retval = mv (cell, oldval, change, newval, cursor_position,
start_selection, end_selection);
/* if the callback returned a non-null value, allow the edit */
@ -1298,7 +1236,7 @@ gnc_table_modify_update(Table *table,
/* update data. bounds check done earlier */
g_free (pcell->entry);
pcell->entry = (char *) retval;
(cb->cells[cell_row][cell_col])->changed = GNC_CELL_CHANGED;
cell->changed = GNC_CELL_CHANGED;
}
}
else
@ -1307,15 +1245,13 @@ gnc_table_modify_update(Table *table,
g_free (pcell->entry);
pcell->entry = newval;
retval = newval;
(cb->cells[cell_row][cell_col])->changed = GNC_CELL_CHANGED;
cell->changed = GNC_CELL_CHANGED;
}
if (table->set_help)
{
BasicCell *cell;
char *help_str;
cell = cb->cells[cell_row][cell_col];
help_str = xaccBasicCellGetHelp(cell);
table->set_help(table, help_str);
@ -1323,9 +1259,9 @@ gnc_table_modify_update(Table *table,
g_free(help_str);
}
LEAVE ("change %d %d (relrow=%d relcol=%d) cell=%p val=%s\n",
phys_loc.phys_row, phys_loc.phys_col, cell_row, cell_col,
cb->cells[cell_row][cell_col], pcell->entry);
LEAVE ("change %d %d (relrow=%d relcol=%d) val=%s\n",
phys_loc.phys_row, phys_loc.phys_col,
cell_row, cell_col, pcell->entry);
return retval;
}
@ -1342,6 +1278,7 @@ gnc_table_direct_update(Table *table,
int *end_selection,
void *gui_data)
{
CellBlockCell *cb_cell;
PhysicalCell *pcell;
gboolean result;
BasicCell *cell;
@ -1361,7 +1298,8 @@ gnc_table_direct_update(Table *table,
cell_row = pcell->virt_loc.phys_row_offset;
cell_col = pcell->virt_loc.phys_col_offset;
cell = cb->cells[cell_row][cell_col];
cb_cell = gnc_cellblock_get_cell (cb, cell_row, cell_col);
cell = cb_cell->cell;
ENTER ("\n");
@ -1371,7 +1309,8 @@ gnc_table_direct_update(Table *table,
result = cell->direct_update(cell, oldval, newval_ptr, cursor_position,
start_selection, end_selection, gui_data);
if ((*newval_ptr != oldval) && (*newval_ptr != NULL)) {
if ((*newval_ptr != oldval) && (*newval_ptr != NULL))
{
g_free (pcell->entry);
pcell->entry = *newval_ptr;
cell->changed = GNC_CELL_CHANGED;
@ -1488,6 +1427,7 @@ gnc_table_traverse_update(Table *table,
case GNC_TABLE_TRAVERSE_RIGHT:
case GNC_TABLE_TRAVERSE_LEFT:
{
CellTraverseInfo *ct_info;
PhysicalCell *pcell;
int cell_row, cell_col;
@ -1501,19 +1441,21 @@ gnc_table_traverse_update(Table *table,
cell_row = pcell->virt_loc.phys_row_offset;
cell_col = pcell->virt_loc.phys_col_offset;
ct_info = gnc_cellblock_get_traverse (cb, cell_row, cell_col);
if (dir == GNC_TABLE_TRAVERSE_RIGHT)
{
dest_loc->phys_row = (phys_loc.phys_row - cell_row +
cb->right_traverse_r[cell_row][cell_col]);
ct_info->right_traverse_row);
dest_loc->phys_col = (phys_loc.phys_col - cell_col +
cb->right_traverse_c[cell_row][cell_col]);
ct_info->right_traverse_col);
}
else
{
dest_loc->phys_row = (phys_loc.phys_row - cell_row +
cb->left_traverse_r[cell_row][cell_col]);
ct_info->left_traverse_row);
dest_loc->phys_col = (phys_loc.phys_col - cell_col +
cb->left_traverse_c[cell_row][cell_col]);
ct_info->left_traverse_col);
}
}
@ -1543,7 +1485,7 @@ gnc_table_traverse_update(Table *table,
break;
}
if ((new_loc.phys_row < header->numRows) ||
if ((new_loc.phys_row < header->num_rows) ||
(new_loc.phys_row >= table->num_phys_rows))
{
increment *= -1;

View File

@ -106,6 +106,7 @@
#include "basiccell.h"
#include "cellblock.h"
#include "gtable.h"
typedef enum {
@ -215,8 +216,8 @@ struct _Table
/* This is black-box stuff that higher-level code should not access */
/* The virtual and physical cell information */
GPtrArray *virt_cells;
GPtrArray *phys_cells;
GTable *virt_cells;
GTable *phys_cells;
/* This class implements tab-key and arrow key traversal through the
* cells of the table. To perform this traversal, the location of

View File

@ -78,7 +78,7 @@ gnc_table_init_gui (gncUIWidget widget, void *data)
g_return_if_fail (GNUCASH_IS_REGISTER (widget));
g_return_if_fail (data != NULL);
sr = (SplitRegister *) data;
sr = data;
greg = GNUCASH_REGISTER(widget);
sheet = GNUCASH_SHEET(greg->sheet);