merge in big branch that implements (more or less) the auto-dynamic-expansion

of the current edied split.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@1116 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 1998-09-08 07:33:12 +00:00
parent 1e10ba84e2
commit e93e06b4b4
12 changed files with 1195 additions and 906 deletions

View File

@ -184,8 +184,7 @@ xaccLedgerDisplaySimple (Account *acc)
}
/* default to single-line display */
reg_type |= REG_SHOW_TAMOUNT;
reg_type |= REG_SHOW_TXFRM;
reg_type |= REG_SINGLE_LINE;
retval = xaccLedgerDisplayGeneral (acc, NULL, reg_type);
return retval;
@ -258,8 +257,7 @@ xaccLedgerDisplayAccGroup (Account *acc)
}
/* default to single-line display */
ledger_type |= REG_SHOW_TAMOUNT;
ledger_type |= REG_SHOW_TXFRM;
ledger_type |= REG_SINGLE_LINE;
retval = xaccLedgerDisplayGeneral (acc, list, ledger_type);
@ -424,6 +422,29 @@ xaccRegisterRefresh (SplitRegister *splitreg)
}
}
/********************************************************************\
* sort of a quick hack involving the layout of the register.
\********************************************************************/
void
xaccRegisterCountHack (SplitRegister *splitreg)
{
xaccLedgerDisplay *regData;
int n;
/* find the ledger which contains this register */
n = 0; regData = fullList[n];
while (regData) {
if (splitreg == regData->ledger) {
xaccSRCountRows (splitreg,
xaccAccountGetSplitList (regData->leader),
regData->leader);
return;
}
n++; regData = fullList[n];
}
}
/********************************************************************\
* mark dirty *all* register windows which contain this account *
\********************************************************************/
@ -561,7 +582,7 @@ xaccDestroyLedgerDisplay (Account *acc)
}
/********************************************************************\
* closexaccLedgerDisplay *
* xaccLedgerDisplayClose *
* frees memory allocated for an regWindow, and other cleanup *
* stuff *
* *
@ -578,6 +599,9 @@ xaccLedgerDisplayClose (xaccLedgerDisplay *regData)
/* Save any unsaved changes */
xaccSRSaveRegEntry (regData->ledger);
/* refresh the register windows if there were changes */
xaccSRRedrawRegEntry (regData->ledger);
xaccDestroySplitRegister (regData->ledger);
/* whether this is a single or multi-account window, remove it */

View File

@ -58,15 +58,42 @@
/* this callback gets called when the user clicks on the gui
* in such a way as to leave the current transaction, and to
* go to a new one. So, save the current transaction.
*
* This callback is centrally involved in the redraw sequence.
* When the user moves from one cell to another, the following
* sequence of events get triggered and cascade down:
* enterCB () {
* VerifyCursorPosition() {
* MoveCursor() {
* callback for move() which is this function (LedgerMoveCursor) {
* SaveRegEntry() {...}
* RedrawRegEntry() {
* SRLoadRegister() {
* SRLoadRegEntry() {
* MoveCursor () { }
* }
* }
* } }}}}
*/
static void
LedgerMoveCursor (Table *table, int new_phys_row, int new_phys_col, void * client_data)
LedgerMoveCursor (Table *table,
int *p_new_phys_row,
int *p_new_phys_col,
void * client_data)
{
int new_phys_row = *p_new_phys_row;
int new_phys_col = *p_new_phys_col;
SplitRegister *reg = (SplitRegister *) client_data;
int style;
printf ("LedgerMoveCursor start calback %d %d \n",
new_phys_row, new_phys_col);
/* commit the contents of the cursor into the database */
xaccSRSaveRegEntry (reg);
xaccSRRedrawRegEntry (reg);
printf ("LedgerMoveCursor after redraw %d %d \n",
new_phys_row, new_phys_col);
/* if auto-expansion is enabled, we need to redraw the register
* to expand out the splits at the new location. We do some
@ -75,11 +102,80 @@ LedgerMoveCursor (Table *table, int new_phys_row, int new_phys_col, void * clie
* LoadRegister code into expanding the appropriate split.
*
*/
if ((reg->type) & REG_DYNAMIC) {
Split * split;
style = ((reg->type) & REG_STYLE_MASK);
if ((REG_SINGLE_DYNAMIC == style) ||
(REG_DOUBLE_DYNAMIC == style))
{
Split *split, *oldsplit;
oldsplit = xaccSRGetCurrentSplit (reg);
split = xaccGetUserData (reg->table, new_phys_row, new_phys_col);
reg->table->current_cursor->user_data = (void *) split;
/* if a null split, provide a hint for where the cursor should go */
if (NULL == split) {
reg->cursor_phys_row = new_phys_row;
// reg->cursor_virt_row = reg->table->current_cursor_virt_row;
reg->user_hack = (void *) xaccSplitGetParent (oldsplit);
}
xaccRegisterRefresh (reg);
/* indicate what row we *should* have gone to */
*p_new_phys_row = table->current_cursor_phys_row;
printf ("LedgerMoveCursor after dynamic %d %d stored val %d\n",
*p_new_phys_row, new_phys_col,
reg->cursor_phys_row
);
}
}
/* ======================================================== */
/* this callback gets called when the user clicks on the gui
* in such a way as to leave the current transaction, and to
* go to a new one. It is called to verify what the cordinates
* of the new cell will be. It really applies only for auto-expansion,
* where we need to calculate the coords of the target cell.
*/
static void
LedgerTraverse (Table *table,
int *p_new_phys_row,
int *p_new_phys_col,
void * client_data)
{
int new_phys_row = *p_new_phys_row;
int new_phys_col = *p_new_phys_col;
SplitRegister *reg = (SplitRegister *) client_data;
int style;
/* if auto-expansion is enabled, we need to redraw the register
* to expand out the splits at the new location. We do some
* tomfoolery here to trick the code into expanding the new location.
* This little futz is sleazy, but it does suceed in getting the
* LoadRegister code into expanding the appropriate split.
*/
style = ((reg->type) & REG_STYLE_MASK);
if ((REG_SINGLE_DYNAMIC == style) ||
(REG_DOUBLE_DYNAMIC == style))
{
Split *split, *oldsplit;
printf ("enter LedgerTraverse with %d %d \n", new_phys_row , new_phys_col);
oldsplit = xaccSRGetCurrentSplit (reg);
split = xaccGetUserData (reg->table, new_phys_row, new_phys_col);
reg->table->current_cursor->user_data = (void *) split;
/* if a null split, provide a hint for where the cursor should go */
if (NULL == split) {
reg->cursor_phys_row = new_phys_row;
// reg->cursor_virt_row = reg->table->current_cursor_virt_row;
reg->user_hack = (void *) xaccSplitGetParent (oldsplit);
}
xaccRegisterCountHack (reg);
reg->table->current_cursor->user_data = (void *) oldsplit;
printf ("leave LedgerTraverse with %d \n", reg->cursor_phys_row);
/* indicate what row we *should* go to */
*p_new_phys_row = reg->cursor_phys_row;
}
}
@ -117,6 +213,42 @@ xaccSRGetCurrentSplit (SplitRegister *reg)
return split;
}
/* ======================================================== */
void
xaccSRRedrawRegEntry (SplitRegister *reg)
{
Split *split;
Transaction *trans;
Account * acc;
unsigned int changed;
int i;
/* use the changed flag to avoid heavy-weight redraws
* This will help cut down on uneccessary register redraws. */
changed = xaccSplitRegisterGetChangeFlag (reg);
if (!changed) return;
split = xaccSRGetCurrentSplit (reg);
trans = xaccSplitGetParent (split);
/* refresh the register windows */
/* This split belongs to a transaction that might be displayed
* in any number of windows. Changing any one split is likely
* to affect any account windows associated with the other splits
* in this transaction. So basically, send redraw events to all
* of the splits.
*/
i = 0;
split = xaccTransGetSplit (trans, i);
while (split) {
acc = xaccSplitGetAccount (split);
xaccAccountDisplayRefresh (acc);
i++;
split = xaccTransGetSplit (trans, i);
}
}
/* ======================================================== */
/* Copy from the register object to the engine */
@ -127,7 +259,7 @@ xaccSRSaveRegEntry (SplitRegister *reg)
Transaction *trans;
Account * acc;
unsigned int changed;
int i;
int style;
/* use the changed flag to avoid heavy-weight updates
* of the split & transaction fields. This will help
@ -135,6 +267,8 @@ xaccSRSaveRegEntry (SplitRegister *reg)
changed = xaccSplitRegisterGetChangeFlag (reg);
if (!changed) return;
style = (reg->type) & REG_STYLE_MASK;
/* get the handle to the current split and transaction */
split = xaccSRGetCurrentSplit (reg);
printf ("save split is %p \n", split);
@ -170,6 +304,10 @@ printf ("save split is %p \n", split);
xaccTransBeginEdit (trans);
xaccTransAppendSplit (trans, split);
xaccAccountInsertSplit (acc, split);
assert (reg->table->current_cursor);
reg->table->current_cursor->user_data = (void *) split;
} else {
trans = xaccSplitGetParent (split);
xaccTransBeginEdit (trans);
@ -191,43 +329,24 @@ printf ("save split is %p \n", split);
xaccSplitSetReconcile (split, reg->recnCell->value[0]);
}
if (MOD_TAMNT & changed) {
double new_amount;
new_amount = (reg->creditTransCell->amount) - (reg->debitTransCell->amount);
if ((EQUITY_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(STOCK_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(PORTFOLIO == (reg->type & REG_TYPE_MASK)))
{
xaccSplitSetShareAmount (split, new_amount);
} else {
xaccSplitSetValue (split, new_amount);
}
}
if (MOD_TPRIC & changed) {
xaccSplitSetSharePrice (split, reg->priceTransCell->amount);
}
if (MOD_TVALU & changed) {
xaccSplitSetValue (split, -(reg->valueTransCell->amount));
}
/* -------------------------------------------------------------- */
if (MOD_ACTN & changed)
xaccSplitSetAction (split, reg->actionCell->cell.value);
/* -------------------------------------------------------------- */
/* OK, the handling of transfers gets complicated because it
* depends on what was displayed to the user. For a multi-line
* display, we just reparent the indicated split, its it,
* and that's that. For a two-line display, we want to reparent
* the "other" split, but only if there is one ...
*/
if ((MOD_XFRM | MOD_TXFRM) & changed) {
if (MOD_XFRM & changed) {
Account *old_acc=NULL, *new_acc=NULL;
Split *split_to_modify = NULL;
if (reg->type & REG_MULTI_LINE) {
if ((REG_MULTI_LINE == style) ||
(REG_SINGLE_DYNAMIC == style) ||
(REG_DOUBLE_DYNAMIC == style))
{
split_to_modify = split;
} else {
split_to_modify = xaccGetOtherSplit(split);
@ -239,11 +358,7 @@ printf ("save split is %p \n", split);
/* do some reparenting. Insertion into new account will automatically
* delete from the old account */
old_acc = xaccSplitGetAccount (split_to_modify);
if (MOD_XFRM & changed) {
new_acc = xaccGetAccountByName (trans, reg->xfrmCell->cell.value);
} else {
new_acc = xaccGetAccountByName (trans, reg->xfrmTransCell->cell.value);
}
new_acc = xaccGetAccountByName (trans, reg->xfrmCell->cell.value);
xaccAccountInsertSplit (new_acc, split_to_modify);
/* make sure any open windows of the old account get redrawn */
@ -258,10 +373,18 @@ printf ("save split is %p \n", split);
if (MOD_MEMO & changed)
xaccSplitSetMemo (split, reg->memoCell->value);
if (MOD_AMNT & changed) {
/* The AMNT and NAMNT updates only differ by sign. Basically,
* the split and transaction cursors show minus the quants that
* the single and double cursors show, and so when updates happen,
* the extra minus sign must also be handled.
*/
if ((MOD_AMNT | MOD_NAMNT) & changed) {
double new_amount;
new_amount = (reg->creditCell->amount) - (reg->debitCell->amount);
new_amount = -new_amount;
if (MOD_AMNT & changed) {
new_amount = (reg->creditCell->amount) - (reg->debitCell->amount);
} else {
new_amount = (reg->ndebitCell->amount) - (reg->ncreditCell->amount);
}
if ((EQUITY_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(STOCK_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(PORTFOLIO == (reg->type & REG_TYPE_MASK)))
@ -277,10 +400,9 @@ printf ("save split is %p \n", split);
}
if (MOD_VALU & changed) {
xaccSplitSetValue (split, reg->valueCell->amount);
xaccSplitSetValue (split, (reg->valueCell->amount));
}
xaccTransCommitEdit (trans);
printf ("finished saving split %s of trans %s \n",
@ -296,46 +418,6 @@ xaccTransGetDescription(trans));
if (split == ((Split *) (reg->user_hook))) {
reg->user_hook = NULL;
}
/* refresh the register windows */
/* This split belongs to a transaction that might be displayed
* in any number of windows. Changing any one split is likely
* to affect any account windows associated with the other splits
* in this transaction. So basically, send redraw events to all
* of the splits.
*/
i = 0;
split = xaccTransGetSplit (trans, i);
while (split) {
acc = xaccSplitGetAccount (split);
xaccAccountDisplayRefresh (acc);
i++;
split = xaccTransGetSplit (trans, i);
}
}
/* ======================================================== */
#define LOAD_XFRM(cellname) { \
char * accname=NULL; \
\
/* Show the transfer-from account name. */ \
/* What gets displayed depends on the display format. */ \
/* For a multi-line display, show the account for each member split. */ \
/* For a one or two-line display, show the other account, but only */ \
/* if there are exactly two splits. */ \
if (reg->type & REG_MULTI_LINE) { \
accname = xaccAccountGetName (xaccSplitGetAccount (split)); \
xaccSetComboCellValue (reg->cellname, accname); \
} else { \
Split *s = xaccGetOtherSplit (split); \
if (s) { \
accname = xaccAccountGetName (xaccSplitGetAccount (s)); \
} else { \
accname = SPLIT_STR; \
} \
xaccSetComboCellValue (reg->cellname, accname); \
} \
}
/* ======================================================== */
@ -346,6 +428,8 @@ xaccSRLoadTransEntry (SplitRegister *reg, Split *split, int do_commit)
char buff[2];
time_t secs;
double baln;
int typo = reg->type & REG_TYPE_MASK;
int style = reg->type & REG_STYLE_MASK;
/* don't even bother doing a load if there is no current cursor */
if (!(reg->table->current_cursor)) return;
@ -354,56 +438,92 @@ xaccSRLoadTransEntry (SplitRegister *reg, Split *split, int do_commit)
/* we interpret a NULL split as a blank split */
xaccSetDateCellValueSecs (reg->dateCell, 0);
xaccSetBasicCellValue (reg->numCell, "");
xaccSetComboCellValue (reg->xfrmTransCell, "");
xaccSetQuickFillCellValue (reg->descCell, "");
xaccSetBasicCellValue (reg->recnCell, "");
xaccSetDebCredCellValue (reg->debitTransCell,
reg->creditTransCell, 0.0);
xaccSetPriceCellValue (reg->priceTransCell, 0.0);
xaccSetPriceCellValue (reg->valueTransCell, 0.0);
xaccSetPriceCellValue (reg->shrsCell, 0.0);
xaccSetPriceCellValue (reg->balanceCell, 0.0);
xaccSetComboCellValue (reg->actionCell, "");
xaccSetBasicCellValue (reg->memoCell, "");
xaccSetComboCellValue (reg->xfrmCell, "");
xaccSetDebCredCellValue (reg->debitCell,
reg->creditCell, 0.0);
xaccSetDebCredCellValue (reg->ndebitCell,
reg->ncreditCell, 0.0);
xaccSetPriceCellValue (reg->priceCell, 0.0);
xaccSetPriceCellValue (reg->valueCell, 0.0);
} else {
double amt;
char * accname=NULL;
Transaction *trans = xaccSplitGetParent (split);
secs = xaccTransGetDate (trans);
xaccSetDateCellValueSecs (reg->dateCell, secs);
xaccSetBasicCellValue (reg->numCell, xaccTransGetNum (trans));
LOAD_XFRM (xfrmTransCell);
xaccSetQuickFillCellValue (reg->descCell, xaccTransGetDescription (trans));
buff[0] = xaccSplitGetReconcile (split);
buff[1] = 0x0;
xaccSetBasicCellValue (reg->recnCell, buff);
if ((EQUITY_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(STOCK_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(PORTFOLIO == (reg->type & REG_TYPE_MASK)))
{
amt = xaccSplitGetShareAmount (split);
} else {
amt = xaccSplitGetValue (split);
}
xaccSetDebCredCellValue (reg->debitTransCell, reg->creditTransCell, amt);
xaccSetPriceCellValue (reg->priceTransCell, xaccSplitGetSharePrice (split));
xaccSetPriceCellValue (reg->valueTransCell, xaccSplitGetValue (split));
/* For income and expense acounts, we have to reverse
* the meaning of balance, since, in a dual entry
* system, income will show up as a credit to a
* bank account, and a debit to the income account.
* Thus, positive and negative are interchanged */
baln = xaccSplitGetBalance (split);
if ((INCOME_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(EXPENSE_REGISTER == (reg->type & REG_TYPE_MASK))) {
if ((INCOME_REGISTER == typo) ||
(EXPENSE_REGISTER == typo)) {
baln = -baln;
}
xaccSetPriceCellValue (reg->balanceCell, baln);
xaccSetPriceCellValue (reg->shrsCell, xaccSplitGetShareBalance (split));
xaccSetComboCellValue (reg->actionCell, xaccSplitGetAction (split));
/* Show the transfer-from account name.
* What gets displayed depends on the display format.
* For a multi-line display, show the account for each member split.
* For a one or two-line display, show the other account, but only
* if there are exactly two splits.
*/
if ((REG_MULTI_LINE == style) ||
(REG_SINGLE_DYNAMIC == style) ||
(REG_DOUBLE_DYNAMIC == style))
{
accname = xaccAccountGetName (xaccSplitGetAccount (split));
xaccSetComboCellValue (reg->xfrmCell, accname);
} else {
Split *s = xaccGetOtherSplit (split);
if (s) {
accname = xaccAccountGetName (xaccSplitGetAccount (s));
} else {
accname = SPLIT_STR;
}
xaccSetComboCellValue (reg->xfrmCell, accname);
}
xaccSetBasicCellValue (reg->memoCell, xaccSplitGetMemo (split));
buff[0] = xaccSplitGetReconcile (split);
buff[1] = 0x0;
xaccSetBasicCellValue (reg->recnCell, buff);
if ((EQUITY_REGISTER == typo) ||
(STOCK_REGISTER == typo) ||
(PORTFOLIO == typo))
{
amt = xaccSplitGetShareAmount (split);
} else {
amt = xaccSplitGetValue (split);
}
xaccSetDebCredCellValue (reg->debitCell, reg->creditCell, amt);
xaccSetDebCredCellValue (reg->ndebitCell, reg->ncreditCell, -amt);
xaccSetPriceCellValue (reg->priceCell, xaccSplitGetSharePrice (split));
xaccSetPriceCellValue (reg->valueCell, xaccSplitGetValue (split));
}
reg->table->current_cursor->user_data = (void *) split;
@ -416,46 +536,16 @@ xaccSRLoadTransEntry (SplitRegister *reg, Split *split, int do_commit)
/* ======================================================== */
#define xaccSRLoadSplitEntry xaccSRLoadTransEntry
#ifdef LATER
static void
xaccSRLoadSplitEntry (SplitRegister *reg, Split *split, int do_commit)
{
char buff[2];
/* don't even bother doing a load if there is no current cursor */
if (!(reg->table->current_cursor)) return;
if (!split) {
/* we interpret a NULL split as a blank split */
xaccSetComboCellValue (reg->actionCell, "");
xaccSetBasicCellValue (reg->memoCell, "");
xaccSetComboCellValue (reg->xfrmCell, "");
xaccSetDebCredCellValue (reg->debitCell,
reg->creditCell, 0.0);
xaccSetPriceCellValue (reg->priceCell, 0.0);
xaccSetPriceCellValue (reg->valueCell, 0.0);
} else {
double amt;
xaccSetComboCellValue (reg->actionCell, xaccSplitGetAction (split));
LOAD_XFRM (xfrmCell);
xaccSetBasicCellValue (reg->memoCell, xaccSplitGetMemo (split));
buff[0] = xaccSplitGetReconcile (split);
buff[1] = 0x0;
xaccSetBasicCellValue (reg->recsCell, buff);
if ((EQUITY_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(STOCK_REGISTER == (reg->type & REG_TYPE_MASK)) ||
(PORTFOLIO == (reg->type & REG_TYPE_MASK)))
{
amt = xaccSplitGetShareAmount (split);
} else {
amt = xaccSplitGetValue (split);
}
xaccSetDebCredCellValue (reg->debitCell, reg->creditCell, -amt);
xaccSetPriceCellValue (reg->priceCell, xaccSplitGetSharePrice (split));
xaccSetPriceCellValue (reg->valueCell, -xaccSplitGetValue (split));
}
reg->table->current_cursor->user_data = (void *) split;
@ -465,6 +555,7 @@ xaccSRLoadSplitEntry (SplitRegister *reg, Split *split, int do_commit)
xaccCommitCursor (reg->table);
}
}
#endif
/* ======================================================== */
@ -472,7 +563,7 @@ void
xaccSRLoadRegEntry (SplitRegister *reg, Split *split)
{
xaccSRLoadTransEntry (reg, split, 0);
xaccSRLoadSplitEntry (reg, split, 0);
/* xaccSRLoadSplitEntry (reg, split, 0); */
/* copy cursor contents into the table */
xaccCommitCursor (reg->table);
@ -481,143 +572,216 @@ xaccSRLoadRegEntry (SplitRegister *reg, Split *split)
/* ======================================================== */
void
xaccSRLoadRegister (SplitRegister *reg, Split **slist,
xaccSRCountRows (SplitRegister *reg, Split **slist,
Account *default_source_acc)
{
int i;
Split *split=NULL, *last_split=NULL;
Split *split=NULL;
Split *save_current_split=NULL;
int save_cursor_phys_row = -1;
int save_cursor_virt_row = -1;
Table *table;
int num_phys_rows;
int num_phys_cols;
int num_virt_rows;
int phys_row;
int vrow;
int double_line, multi_line, dynamic;
int style;
int multi_line, dynamic;
CellBlock *lead_cursor;
table = reg->table;
double_line = (reg->type) & REG_DOUBLE_LINE;
multi_line = (reg->type) & REG_MULTI_LINE;
dynamic = (reg->type) & REG_DYNAMIC;
style = (reg->type) & REG_STYLE_MASK;
multi_line = (REG_MULTI_LINE == style);
dynamic = ((REG_SINGLE_DYNAMIC == style) || (REG_DOUBLE_DYNAMIC == style));
if ((REG_SINGLE_LINE == style) ||
(REG_SINGLE_DYNAMIC == style)) {
lead_cursor = reg->single_cursor;
} else {
lead_cursor = reg->double_cursor;
}
/* save the current cursor location; we do this by saving
* a pointer to the currently edited split; we restore the
* cursor to this location when we are done. */
if (reg->table->current_cursor) {
save_current_split = (Split *) (reg->table->current_cursor->user_data);
save_current_split = xaccSRGetCurrentSplit (reg);
if (NULL == save_current_split) {
save_cursor_phys_row = reg->cursor_phys_row;
save_cursor_virt_row = reg->cursor_virt_row;
}
/* disable move callback -- we con't want the cascade of
* callbacks while we are fiddling with loading the register */
table->move_cursor = NULL;
xaccMoveCursorGUI (table, -1, -1);
/* set table size to number of items in list */
/* compute the corresponding number of physical & virtual rows. */
/* num_phys_cols is easy ... just the total number of columns
* in the header */
num_phys_cols = reg->header->numCols;
/* num_phys_rows is the number of rows in all the cursors */
num_phys_rows = reg->header->numRows;
/* Count the number of rows needed.
* the count will be equal to
/* num_phys_rows is the number of rows in all the cursors.
* num_virt_rows is the number of cursors (including the header).
* Count the number of rows needed.
* the phys row count will be equal to
* +1 for the header
* +n that is, one (transaction) row for each split passed in,
* +n one blank edit row for each transaction
* +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_virt_rows = 1;
i=0;
split = slist[0];
while (split) {
Transaction *trans;
int j;
/* do not count the blank split */
if (split != ((Split *) reg->user_hook)) {
Transaction *trans;
int do_expand = 0;
trans = xaccSplitGetParent (split);
if (!trans) {
/* hack assert */
printf ("Internal Error: xaccSRLoadRegister(): "
"Split without a parent \n");
break;
}
/* lets determine where to locate the cursor ... */
if (split == save_current_split) {
save_cursor_phys_row = num_phys_rows;
save_cursor_virt_row = num_virt_rows;
}
/* add one row for a transaction */
num_virt_rows ++;
num_phys_rows += reg->trans_cursor->numRows;
/* if multi-line, then show all splits. If dynamic then
* show all splits only if this is the hot split.
*/
do_expand = multi_line;
do_expand = do_expand ||
(dynamic && xaccIsPeerSplit(split,save_current_split));
if (NULL == save_current_split) {
trans = xaccSplitGetParent (split);
do_expand = do_expand || (trans == reg->user_hack);
}
if (double_line) {
/* add one split row for each transaction */
num_virt_rows ++;
num_phys_rows += reg->split_cursor->numRows;
}
if (do_expand)
{
Split * secondary;
int j = 0;
/* if multi-line, then show all splits. If dynamic then
* show all splits only if this is the hot split.
*/
if (multi_line || (dynamic && (split == save_current_split))) {
/* add a row for each split, minus one, plus one */
j = xaccTransCountSplits (trans);
num_virt_rows += j;
num_phys_rows += j * reg->split_cursor->numRows;
if (double_line) {
/* fix prior double-counting */
num_virt_rows --;
num_phys_rows -= reg->split_cursor->numRows;
/* add one row for a transaction */
num_virt_rows ++;
num_phys_rows += reg->trans_cursor->numRows;
/* 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;
* except that we also have to find teh saved cursor row,
* Thus, we need a real looop over the splits.
* The do..while will automaticaly put a blank (null)
* split at the end
*/
trans = xaccSplitGetParent (split);
j = 0;
do {
secondary = xaccTransGetSplit (trans, j);
if (secondary != split) {
/* lets determine where to locate the cursor ... */
if (secondary == save_current_split) {
save_cursor_phys_row = num_phys_rows;
save_cursor_virt_row = num_virt_rows;
}
num_virt_rows ++;
num_phys_rows += reg->split_cursor->numRows;
}
j++;
} while (secondary);
} else {
/* the simple case ... add one row for a transaction */
num_virt_rows ++;
num_phys_rows += lead_cursor->numRows;
}
}
i++;
split = slist[i];
}
/* If user_hook is null, then we haven't set up the blank split yet,
* so add two lines for it: one blank transaction, one blank split.
* But if we have set it up yet, then we've counted one split too
* many: the blank-blank at the very end. Subtract it back out.
*/
/* ---------------------------------------------------------- */
/* the "blank split", if it exists, is at the end */
if (reg->user_hook) {
split = (Split *) reg->user_hook;
/* lets determine where to locate the cursor ... */
if (split == save_current_split) {
save_cursor_phys_row = num_phys_rows;
save_cursor_virt_row = num_virt_rows;
}
}
if (multi_line) {
if (!(reg->user_hook)) {
i++;
num_virt_rows += 2;
num_phys_rows += reg->trans_cursor->numRows;
num_phys_rows += reg->split_cursor->numRows;
} else {
num_virt_rows -= 1;
num_phys_rows -= reg->split_cursor->numRows;
}
num_virt_rows += 2;
num_phys_rows += reg->trans_cursor->numRows;
num_phys_rows += reg->split_cursor->numRows;
} else {
num_virt_rows += 1;
num_phys_rows += lead_cursor->numRows;
}
if (double_line) {
/* add two rows */
if (!(reg->user_hook)) {
i++;
num_virt_rows ++;
num_phys_rows += reg->trans_cursor->numRows;
num_virt_rows ++;
num_phys_rows += reg->split_cursor->numRows;
}
/* 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_virt_row = num_virt_rows - 1;
}
if ((save_cursor_phys_row < (reg->header->numRows)) ||
(save_cursor_virt_row < 1))
{
save_cursor_phys_row = reg->header->numRows;
save_cursor_virt_row = 1;
}
if (!multi_line && !double_line) {
if (!(reg->user_hook)) {
i++;
num_virt_rows += 1;
num_phys_rows += reg->trans_cursor->numRows;
}
/* finally, record the values */
reg->num_phys_rows = num_phys_rows;
reg->num_virt_rows = num_virt_rows;
reg->cursor_phys_row = save_cursor_phys_row;
reg->cursor_virt_row = save_cursor_virt_row;
}
/* ======================================================== */
void
xaccSRLoadRegister (SplitRegister *reg, Split **slist,
Account *default_source_acc)
{
int i = 0;
Split *split=NULL, *last_split=NULL;
Split *save_current_split=NULL;
Table *table;
int phys_row;
int vrow;
int style;
int multi_line, dynamic;
CellBlock *lead_cursor;
table = reg->table;
style = (reg->type) & REG_STYLE_MASK;
multi_line = (REG_MULTI_LINE == style);
dynamic = ((REG_SINGLE_DYNAMIC == style) || (REG_DOUBLE_DYNAMIC == style));
if ((REG_SINGLE_LINE == style) ||
(REG_SINGLE_DYNAMIC == style)) {
lead_cursor = reg->single_cursor;
} else {
lead_cursor = reg->double_cursor;
}
/* count the number of rows */
xaccSRCountRows (reg, slist, default_source_acc);
/* save the current cursor location; we do this by saving
* a pointer to the currently edited split; we restore the
* cursor to this location when we are done. */
save_current_split = xaccSRGetCurrentSplit (reg);
/* disable move callback -- we con't want the cascade of
* callbacks while we are fiddling with loading the register */
table->move_cursor = NULL;
xaccMoveCursorGUI (table, -1, -1);
/* num_virt_cols is always one. */
xaccSetTableSize (table, num_phys_rows, num_phys_cols, num_virt_rows, 1);
xaccSetTableSize (table, reg->num_phys_rows, reg->num_cols,
reg->num_virt_rows, 1);
/* make sure that the header is loaded */
xaccSetCursor (table, reg->header, 0, 0, 0, 0);
printf ("load register of %d virtual entries %d phys rows ----------- \n", i, num_phys_rows);
printf ("load register of %d phys rows ----------- \n", reg->num_phys_rows);
/* populate the table */
i=0;
vrow = 1; /* header is vrow zero */
@ -625,33 +789,35 @@ printf ("load register of %d virtual entries %d phys rows ----------- \n", i, nu
split = slist[0];
while (split) {
/* lets determine where to locate the cursor ... */
if (split == save_current_split) {
save_cursor_phys_row = phys_row;
}
/* do not load the blank split */
if (split != ((Split *) reg->user_hook)) {
Transaction *trans;
Split * secondary;
int j = 0;
int do_expand;
printf ("load trans %d at phys row %d \n", i, phys_row);
xaccSetCursor (table, reg->trans_cursor, phys_row, 0, vrow, 0);
xaccMoveCursor (table, phys_row, 0);
xaccSRLoadTransEntry (reg, split, 1);
vrow ++;
phys_row += reg->trans_cursor->numRows;
if (double_line) {
xaccSetCursor (table, reg->split_cursor, phys_row, 0, vrow, 0);
xaccMoveCursor (table, phys_row, 0);
xaccSRLoadSplitEntry (reg, split, 1);
vrow ++;
phys_row += reg->split_cursor->numRows;
/* if multi-line, then show all splits. If dynamic then
* show all splits only if this is the hot split.
*/
do_expand = multi_line;
do_expand = do_expand ||
(dynamic && xaccIsPeerSplit(split,save_current_split));
if (NULL == save_current_split) {
trans = xaccSplitGetParent (split);
do_expand = do_expand || (trans == reg->user_hack);
}
if (multi_line || (dynamic && (split == save_current_split))) {
if (do_expand)
{
Split * secondary;
int j = 0;
xaccSetCursor (table, reg->trans_cursor, phys_row, 0, vrow, 0);
xaccMoveCursor (table, phys_row, 0);
xaccSRLoadTransEntry (reg, split, 1);
vrow ++;
phys_row += reg->trans_cursor->numRows;
/* loop over all of the splits in the transaction */
/* the do..while will automaticaly put a blank (null) split at the end */
trans = xaccSplitGetParent (split);
@ -659,11 +825,6 @@ printf ("load trans %d at phys row %d \n", i, phys_row);
do {
secondary = xaccTransGetSplit (trans, j);
/* lets determine where to locate the cursor ... */
if (secondary == save_current_split) {
save_cursor_phys_row = phys_row;
}
if (secondary != split) {
printf ("load split %d at phys row %d \n", j, phys_row);
xaccSetCursor (table, reg->split_cursor, phys_row, 0, vrow, 0);
@ -675,6 +836,14 @@ printf ("load split %d at phys row %d \n", j, phys_row);
j++;
} while (secondary);
} else {
/* the simple case ... */
xaccSetCursor (table, lead_cursor, phys_row, 0, vrow, 0);
xaccMoveCursor (table, phys_row, 0);
xaccSRLoadTransEntry (reg, split, 1);
vrow ++;
phys_row += lead_cursor->numRows;
}
}
@ -709,21 +878,17 @@ printf ("load split %d at phys row %d \n", j, phys_row);
xaccSplitSetSharePrice (split, last_price);
}
/* lets determine where to locate the cursor ... */
if (split == save_current_split) {
save_cursor_phys_row = phys_row;
}
/* do the transaction row of the blank split */
xaccSetCursor (table, reg->trans_cursor, phys_row, 0, vrow, 0);
xaccMoveCursor (table, phys_row, 0);
xaccSRLoadTransEntry (reg, split, 1);
vrow ++;
phys_row += reg->trans_cursor->numRows;
/* do the split row of the blank split */
if (double_line || multi_line) {
if (multi_line) {
Transaction *trans;
/* do the transaction row of the blank split */
xaccSetCursor (table, reg->trans_cursor, phys_row, 0, vrow, 0);
xaccMoveCursor (table, phys_row, 0);
xaccSRLoadTransEntry (reg, split, 1);
vrow ++;
phys_row += reg->trans_cursor->numRows;
trans = xaccSplitGetParent (split);
split = xaccTransGetSplit (trans, 1);
xaccSetCursor (table, reg->split_cursor, phys_row, 0, vrow, 0);
@ -731,20 +896,21 @@ printf ("load split %d at phys row %d \n", j, phys_row);
xaccSRLoadSplitEntry (reg, split, 1);
vrow ++;
phys_row += reg->split_cursor->numRows;
} else {
xaccSetCursor (table, lead_cursor, phys_row, 0, vrow, 0);
xaccMoveCursor (table, phys_row, 0);
xaccSRLoadTransEntry (reg, split, 1);
vrow ++;
phys_row += lead_cursor->numRows;
}
/* restore the cursor to its original location */
if (!save_current_split || (phys_row <= save_cursor_phys_row)) {
save_cursor_phys_row = phys_row - reg->split_cursor->numRows;
}
if (save_cursor_phys_row < (reg->header->numRows)) {
save_cursor_phys_row = reg->header->numRows;
}
xaccMoveCursorGUI (table, save_cursor_phys_row, 0);
/* restor the cursor to its rightful position */
xaccMoveCursorGUI (table, reg->cursor_phys_row, 0);
xaccRefreshTableGUI (table);
/* enable callback for cursor user-driven moves */
table->move_cursor = LedgerMoveCursor;
table->traverse = LedgerTraverse;
table->client_data = (void *) reg;
}

View File

@ -359,7 +359,6 @@ regWindowLedger( xaccLedgerDisplay *ledger)
if (!grp) grp = xaccGetAccountRoot (ledger->displayed_accounts[0]);
xaccLoadXferCell (ledger->ledger->xfrmCell, grp);
/* xaccLoadXferCell (ledger->ledger->xtoCell, grp); */
xaccLoadXferCell (ledger->ledger->xfrmTransCell, grp);
}
#if 0
@ -712,6 +711,7 @@ recordCB( GtkWidget *w, gpointer data)
RegWindow *regData = (RegWindow *) data;
xaccSRSaveRegEntry (regData->ledger->ledger);
xaccSRRedrawRegEntry (regData->ledger->ledger);
}
/********************************************************************\

View File

@ -77,7 +77,12 @@ void xaccInitComboCell (ComboCell *cell)
{
xaccInitBasicCell ( &(cell->cell));
cell->cell.realize = realizeCombo;
cell->cell.set_value = setComboValue;
/* calling setComboValue attemtps to load Xbae with values ...
* but these values may be out of bounds because the table has been
* resized, but Xbae hasn't been told the new size yet ...
* So comment this line out ...
*/
/* cell->cell.set_value = setComboValue; */
cell->cell.destroy = destroyCombo;
cell->menuitems = (char **) malloc (sizeof (char *));
cell->menuitems[0] = NULL;

View File

@ -56,6 +56,8 @@ static void PriceSetValue (BasicCell *, const char *);
(cell)->value = strdup (str); \
}
#define PRTBUF 40
/* ================================================ */
/* This callback only allows numbers with a single
* decimal point in them */
@ -131,14 +133,14 @@ xaccDestroyPriceCell (PriceCell *cell)
void xaccSetPriceCellValue (PriceCell * cell, double amt)
{
char buff[40];
char buff[PRTBUF];
cell->amount = amt;
/* if amount is zero, and blanking is set, then print blank */
if (cell->blank_zero && (VERY_SMALL > amt) && ((-VERY_SMALL) < amt)) {
buff[0] = 0x0;
} else {
sprintf (buff, cell->prt_format, amt);
snprintf (buff, PRTBUF, cell->prt_format, amt);
}
SET ( &(cell->cell), buff);
@ -162,7 +164,7 @@ void xaccSetPriceCellFormat (PriceCell * cell, char * fmt)
void xaccSetDebCredCellValue (PriceCell * deb,
PriceCell * cred, double amt)
{
char buff[40];
char buff[PRTBUF];
deb->amount = -amt;
cred->amount = amt;
@ -174,11 +176,11 @@ void xaccSetDebCredCellValue (PriceCell * deb,
SET ( &(deb->cell), "");
} else
if (0.0 < amt) {
sprintf (buff, cred->prt_format, amt);
snprintf (buff, PRTBUF, cred->prt_format, amt);
SET ( &(cred->cell), buff);
SET ( &(deb->cell), "");
} else {
sprintf (buff, deb->prt_format, -amt);
snprintf (buff, PRTBUF, deb->prt_format, -amt);
SET ( &(cred->cell), "");
SET ( &(deb->cell), buff);
}

File diff suppressed because it is too large Load Diff

View File

@ -58,59 +58,52 @@
/* defined register types */
/* "registers" are single-account display windows.
* "ledgers" are multiple-account display windows */
#define BANK_REGISTER 0
#define CASH_REGISTER 1
#define ASSET_REGISTER 2
#define CREDIT_REGISTER 3
#define LIABILITY_REGISTER 4
#define INCOME_REGISTER 5
#define EXPENSE_REGISTER 6
#define EQUITY_REGISTER 7
#define STOCK_REGISTER 8
#define BANK_REGISTER 1
#define CASH_REGISTER 2
#define ASSET_REGISTER 3
#define CREDIT_REGISTER 4
#define LIABILITY_REGISTER 5
#define INCOME_REGISTER 6
#define EXPENSE_REGISTER 7
#define EQUITY_REGISTER 8
#define STOCK_REGISTER 9
#define GENERAL_LEDGER 9
#define INCOME_LEDGER 10
#define PORTFOLIO 11
#define GENERAL_LEDGER 10
#define INCOME_LEDGER 11
#define PORTFOLIO 12
#define REG_TYPE_MASK 0xff
/*
* REG_SHOW_TAMOUNT -- show debit, credit, price, value cells on the transaction line
* REG_SHOW_SAMOUNT -- show debit, credit, price, value cells on the split line
* REG_SHOW_TXFRM -- show transfer-from cell on transaction line
* REG_SHOW_RECS -- show reconcile cell on split line
* enumerated display styles
* REG_DOUBLE_LINE -- show two lines per transaction
* REG_MULTI_LINE -- show multiple lines per transaction
* REG_DYNAMIC -- dynamically expand edited transaction
*/
#define REG_SHOW_TAMOUNT 0x0100
#define REG_SHOW_SAMOUNT 0x0200
#define REG_SHOW_TXFRM 0x0400
#define REG_SHOW_RECS 0x0800
#define REG_DOUBLE_LINE 0x1000
#define REG_MULTI_LINE 0x2000
#define REG_DYNAMIC 0x4000
#define REG_SINGLE_LINE (1 << 8)
#define REG_DOUBLE_LINE (2 << 8)
#define REG_MULTI_LINE (3 << 8)
#define REG_SINGLE_DYNAMIC (4 << 8)
#define REG_DOUBLE_DYNAMIC (5 << 8)
#define REG_STYLE_MASK (0xff << 8)
/* modified flags -- indicate which cell values have been modified by user */
#define MOD_NONE 0x0000
#define MOD_DATE 0x0001
#define MOD_NUM 0x0002
#define MOD_TXFRM 0x0004
#define MOD_DESC 0x0008
#define MOD_RECN 0x0010
#define MOD_TAMNT 0x0020
#define MOD_TPRIC 0x0040
#define MOD_TVALU 0x0080
#define MOD_DESC 0x0004
#define MOD_RECN 0x0008
#define MOD_ACTN 0x0100
#define MOD_XFRM 0x0200
#define MOD_XTO 0x0400
#define MOD_MEMO 0x0800
#define MOD_AMNT 0x1000
#define MOD_PRIC 0x2000
#define MOD_VALU 0x4000
#define MOD_NEW 0x8000
#define MOD_ALL 0xffff
#define MOD_ACTN 0x0010
#define MOD_XFRM 0x0020
#define MOD_XTO 0x0040
#define MOD_MEMO 0x0080
#define MOD_AMNT 0x0100
#define MOD_NAMNT 0x0200
#define MOD_PRIC 0x0400
#define MOD_VALU 0x0800
#define MOD_NEW 0x1000
#define MOD_ALL 0x1fff
/* The value of NUM_CELLS should be larger than the number of
* cells defined in the structure below!
@ -124,37 +117,31 @@ struct _SplitRegister {
Table * table;
/* the cursors that define the currently edited row */
CellBlock * single_cursor;
CellBlock * double_cursor;
CellBlock * trans_cursor;
CellBlock * split_cursor;
CellBlock * header;
/* transaction cells */
/* these are handled only by the transaction cursor */
DateCell * dateCell;
BasicCell * numCell;
ComboCell * xfrmTransCell;
QuickFillCell * descCell;
BasicCell * recnCell; /* main transaction line reconcile */
PriceCell * creditTransCell;
PriceCell * debitTransCell;
PriceCell * priceTransCell;
PriceCell * valueTransCell;
PriceCell * shrsCell;
PriceCell * balanceCell;
BasicCell * nullTransCell;
BasicCell * nullCell;
/* split cells */
/* these are handled only by the split cursor */
ComboCell * actionCell;
ComboCell * xfrmCell;
ComboCell * xtoCell;
BasicCell * memoCell;
BasicCell * recsCell; /* subsidiary split reconcile */
PriceCell * creditCell;
PriceCell * debitCell;
PriceCell * priceCell;
PriceCell * valueCell;
BasicCell * nullSplitCell;
PriceCell * ncreditCell;
PriceCell * ndebitCell;
/* the type of the register, must be one of the enumerated types
* above *_REGISTER, *_LEDGER, above */
@ -163,10 +150,14 @@ struct _SplitRegister {
/* some private data; outsiders should not access this */
short num_cols;
short num_header_rows;
char *labels[NUM_CELLS];
short cols[NUM_CELLS];
short rows[NUM_CELLS];
short wids[NUM_CELLS];
short num_phys_rows;
short num_virt_rows;
short cursor_phys_row;
short cursor_virt_row;
void * user_hack;
BasicCell *header_label_cells[NUM_CELLS];
/* user_hook allows users of this object to hang
* private data onto it */

View File

@ -65,6 +65,7 @@ xaccInitTable (Table * table)
table->current_cursor_phys_col = -1;
table->move_cursor = NULL;
table->traverse = NULL;
table->client_data = NULL;
table->entries = NULL;
@ -78,6 +79,9 @@ xaccInitTable (Table * table)
table->prev_phys_traverse_row = -1;
table->prev_phys_traverse_col = -1;
table->reverify_phys_row = -1;
table->reverify_phys_col = -1;
/* call the "derived" class constructor */
TABLE_PRIVATE_DATA_INIT (table);
}
@ -325,6 +329,51 @@ xaccSetCursor (Table *table, CellBlock *curs,
}
}
/* ==================================================== */
static void
makePassive (Table *table)
{
int i,j;
CellBlock *curs;
int phys_row = table->current_cursor_phys_row;
int phys_col = table->current_cursor_phys_col;
int r_origin, c_origin;
/* Change the cell background colors to thier "passive" values.
* This denotes that the cursor has left this location (which means more or
* less the same thing as "the current location is no longer being edited.")
* (But only do this if the cursor has a valid current location)
*/
if ((0 > phys_row) || (0 > phys_col)) return;
r_origin = phys_row;
c_origin = phys_col;
r_origin -= table->locators[phys_row][phys_col]->phys_row_offset;
c_origin -= table->locators[phys_row][phys_col]->phys_col_offset;
curs = table->current_cursor;
for (i=0; i<curs->numRows; i++) {
for (j=0; j<curs->numCols; j++) {
BasicCell *cell;
table->bg_colors[i+r_origin][j+c_origin] = curs->passive_bg_color;
cell = curs->cells[i][j];
if (cell) {
if (cell->use_bg_color) {
table->bg_colors[i+r_origin][j+c_origin] = cell->bg_color;
}
if (cell->use_fg_color) {
table->fg_colors[i+r_origin][j+c_origin] = cell->fg_color;
}
}
}
}
}
/* ==================================================== */
static void
@ -338,38 +387,21 @@ doMoveCursor (Table *table, int new_phys_row, int new_phys_col, int do_move_gui)
/* Change the cell background colors to thier "passive" values.
* This denotes that the cursor has left this location (which means more or
* less the same thing as "the current location is no longer being edited.")
* (But only do this if the cursor has a valid current location)
*/
if ((0 <= table->current_cursor_phys_row) &&
(0 <= table->current_cursor_phys_col))
{
int r_origin = table->current_cursor_phys_row;
int c_origin = table->current_cursor_phys_col;
curs = table->current_cursor;
for (i=0; i<curs->numRows; i++) {
for (j=0; j<curs->numCols; j++) {
BasicCell *cell;
table->bg_colors[i+r_origin][j+c_origin] = curs->passive_bg_color;
cell = curs->cells[i][j];
if (cell) {
if (cell->use_bg_color) {
table->bg_colors[i+r_origin][j+c_origin] = cell->bg_color;
}
if (cell->use_fg_color) {
table->fg_colors[i+r_origin][j+c_origin] = cell->fg_color;
}
}
}
}
}
makePassive (table);
/* call the callback, allowing the app to commit any changes
* associated with the current location of the cursor. */
* associated with the current location of the cursor.
* Note that this callback may recursively call this routine. */
if (table->move_cursor) {
(table->move_cursor) (table, new_phys_row, new_phys_col,
(table->move_cursor) (table, &new_phys_row, &new_phys_col,
table->client_data);
/* The above callback can cause this routine to be called recursively.
* As a result of this recursion, the cursor may have gotten repositioned.
* we need to make sure we make passive again.
*/
makePassive (table);
}
/* check for out-of-bounds conditions (which may be deliberate) */
@ -425,9 +457,11 @@ doMoveCursor (Table *table, int new_phys_row, int new_phys_col, int do_move_gui)
curs = table->handlers[new_virt_row][new_virt_col];
table->current_cursor = curs;
/* record the new virtual position ... */
/* record the new position ... */
table->current_cursor_virt_row = new_virt_row;
table->current_cursor_virt_col = new_virt_col;
table->current_cursor_phys_row = new_phys_row;
table->current_cursor_phys_col = new_phys_col;
/* compute some useful offsets ... */
phys_row_origin = new_phys_row;
@ -436,9 +470,6 @@ doMoveCursor (Table *table, int new_phys_row, int new_phys_col, int do_move_gui)
phys_col_origin = new_phys_col;
phys_col_origin -= table->locators[new_phys_row][new_phys_col]->phys_col_offset;
table->current_cursor_phys_row = phys_row_origin;
table->current_cursor_phys_col = phys_col_origin;
/* setting the previous traversal value to the last of a traversal chain will
* gaurentee that first entry into a register will occur at the first cell */
table->prev_phys_traverse_row = phys_row_origin + curs->last_reenter_traverse_row;
@ -506,6 +537,8 @@ void xaccCommitCursor (Table *table)
int i,j;
int virt_row, virt_col;
CellBlock *curs;
int phys_row, phys_col;
int phys_row_origin, phys_col_origin;
curs = table->current_cursor;
if (!curs) return;
@ -518,20 +551,32 @@ void xaccCommitCursor (Table *table)
if (virt_row >= table->num_virt_rows) return;
if (virt_col >= table->num_virt_cols) return;
/* compute the true origin of the cell block */
phys_row = table->current_cursor_phys_row;
phys_col = table->current_cursor_phys_col;
phys_row_origin = table->current_cursor_phys_row;
phys_col_origin = table->current_cursor_phys_col;
phys_row_origin -= table->locators[phys_row][phys_col]->phys_row_offset;
phys_col_origin -= table->locators[phys_row][phys_col]->phys_col_offset;
for (i=0; i<curs->numRows; i++) {
for (j=0; j<curs->numCols; j++) {
BasicCell *cell;
cell = curs->cells[i][j];
if (cell) {
int iphys = i + table->current_cursor_phys_row;
int jphys = j + table->current_cursor_phys_col;
int iphys = i + phys_row_origin;
int jphys = j + phys_col_origin;
if (table->entries[iphys][jphys]) {
free (table->entries[iphys][jphys]);
}
table->entries[iphys][jphys] = strdup (cell->value);
table->bg_colors[iphys][jphys] = cell->bg_color;
table->fg_colors[iphys][jphys] = cell->fg_color;
if (cell->use_bg_color) {
table->bg_colors[iphys][jphys] = cell->bg_color;
}
if (cell->use_fg_color) {
table->fg_colors[iphys][jphys] = cell->fg_color;
}
}
}
}
@ -540,7 +585,6 @@ void xaccCommitCursor (Table *table)
}
/* ==================================================== */
/* hack alert -- will core dump if numrows has changed, etc. */
/* hack alert -- assumes that first block is header. */
/* hack alert -- this routine is *just like* that above,
* except that its's committing the very first cursor.
@ -618,6 +662,17 @@ xaccVerifyCursorPosition (Table *table, int phys_row, int phys_col)
* in the cursor */
xaccCommitCursor (table);
xaccMoveCursorGUI (table, phys_row, phys_col);
} else {
/* The request might be to move to a cell that is one column over.
* If so, then do_commit will be zero, as there will have been no
* reason to actually move a cursor. However, we want to keep
* positions accurate, so record the new location. (The move may
* may also be one row up or down, which, for a two-row cursor,
* also might not require a cursor movement).
*/
table->current_cursor_phys_row = phys_row;
table->current_cursor_phys_col = phys_col;
}
}

View File

@ -124,7 +124,13 @@ struct _Table {
/* callback that is called when the cursor is moved */
/* hack alert -- this should be a callback list, actually */
void (*move_cursor) (Table *, int new_phys_row, int new_phys_col, void *client_data);
void (*move_cursor) (Table *, int *p_new_phys_row,
int *p_new_phys_col,
void *client_data);
/* callback that is called to determine traversal */
void (*traverse) (Table *, int *p_new_phys_row,
int *p_new_phys_col,
void *client_data);
void * client_data;
/* string values for each cell,
@ -160,6 +166,9 @@ struct _Table {
int prev_phys_traverse_row;
int prev_phys_traverse_col;
int reverify_phys_row;
int reverify_phys_col;
/* Since we are using C not C++, but we need inheritance,
* cock it up with a #defined thingy that the "derived class"
* can specify.
@ -180,6 +189,11 @@ void xaccDestroyTable (Table *);
void xaccSetTableSize (Table * table, int phys_rows, int phys_cols,
int virt_rows, int virt_cols);
/* The xaccCreateCursor() method can be called whenever a reconfig
* of the cursor may require new gui elements to be initialized.
*/
void xaccCreateCursor (Table *, CellBlock *);
/* indicate what handler should be used for a given virtual block */
void
xaccSetCursor (Table *table, CellBlock *curs,

View File

@ -677,36 +677,44 @@ xaccCreateTable (Table *table, GtkWidget * parent)
}
}
/* if any of the cells have GUI specific components that
* need initialization, initialize them now.
* The cell realize method, if present on a cell,
* is how that cell can find out that now is the time to
* initialize that GUI.
*/
/* initialize any cell gui elements now, if any */
xaccCreateCursor (table, table->current_cursor);
curs = table->current_cursor;
if (curs) {
int i,j;
return (table->table_widget);
}
for (i=0; i<curs->numRows; i++) {
for (j=0; j<curs->numCols; j++) {
BasicCell *cell;
cell = curs->cells[i][j];
if (cell) {
void (*xt_realize) (BasicCell *, void *gui, int pixel_width);
xt_realize = cell->realize;
if (xt_realize) {
int pixel_width;
/* cl->column[col].width */
/*pixel_width = XbaeMatrixGetColumnPixelWidth (reg, j);*/
xt_realize (cell, ((void *) table), 0);
/*xt_realize (cell, ((void *) reg), pixel_width);*/
}
/* ==================================================== */
/* if any of the cells have GUI specific components that
* need initialization, initialize them now.
* The cell realize method, if present on a cell,
* is how that cell can find out that now is the time to
* initialize that GUI.
*/
void
xaccCreateCursor (Table * table, CellBlock *curs)
{
int i,j;
if (!curs || !table) return;
for (i=0; i<curs->numRows; i++) {
for (j=0; j<curs->numCols; j++) {
BasicCell *cell;
cell = curs->cells[i][j];
if (cell) {
void (*gtk_realize) (BasicCell *, void *gui, int pixel_width);
gtk_realize = cell->realize;
if (gtk_realize) {
int pixel_width;
/* cl->column[col].width */
/*pixel_width = XbaeMatrixGetColumnPixelWidth (reg, j);*/
/*gtk_realize (cell, ((void *) reg), pixel_width);*/
gtk_realize (cell, ((void *) table), 0);
}
}
}
}
return (table->table_widget);
}
/* ==================================================== */

View File

@ -224,7 +224,7 @@ xaccTableWebServeHTML (Table * table, unsigned short port)
/* count the number of chars, for content-length */
cnt = xaccTablePrintHTML (table, "/dev/null");
sprintf (buff,
snprintf (buff, 255,
"HTTP/1.0 200 OK\n"
"Connection: close\n"
"Content-Length: %d\n"

View File

@ -27,6 +27,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
\********************************************************************/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@ -58,6 +59,23 @@ xaccNextTabGroup (Table *table, Widget w)
table->next_tab_group = w;
}
/* ==================================================== */
static void
wrapVerifyCursorPosition (Table *table, int row, int col)
{
CellBlock *save_curs = table->current_cursor;
int save_phys_row = table->current_cursor_phys_row;
int save_phys_col = table->current_cursor_phys_col;
/* VerifyCursor will do all sorts of gui-independent machinations */
xaccVerifyCursorPosition (table, row, col);
/* make sure *both* the old and the new cursor rows get redrawn */
xaccRefreshCursorGUI (table);
doRefreshCursorGUI (table, save_curs, save_phys_row, save_phys_col);
}
/* ==================================================== */
/* this routine calls the individual cell callbacks */
@ -77,23 +95,25 @@ cellCB (Widget mw, XtPointer cd, XtPointer cb)
row = cbs->row;
col = cbs->column;
/* if we are entering this cell, make sure that we've
/* If we are entering this cell, make sure that we've
* moved the cursor, and that any subsidiary GUI elements
* properly positioned. Do this *before* we examine the
* value of the "current cursor".
* value of the "current cursor". Note that this check
* could suck up massive cpu, as potentially it may trigger
* a redraw of the entire register.
*
* Hmmm ... actually, theoretically, this is not neeeded.
* Before we get to here, we *should* have gone through
* a traverse callback the determine which cell to enter,
* and then, after the leavecell, the cursor should
* have been automagically repositioned. This, the
* call below should always no-op out. However, if/when
* things go berzerk, the call below does at least a partial
* butt-save for us, so lets leave it in for now.
*/
if (XbaeEnterCellReason == cbs->reason)
{
CellBlock *save_curs = table->current_cursor;
int save_phys_row = table->current_cursor_phys_row;
int save_phys_col = table->current_cursor_phys_col;
/* VerifyCursor will do all sorts of gui-independent machinations */
xaccVerifyCursorPosition (table, row, col);
/* make sure *both* the old and the new cursor rows get redrawn */
xaccRefreshCursorGUI (table);
doRefreshCursorGUI (table, save_curs, save_phys_row, save_phys_col);
wrapVerifyCursorPosition (table, row, col);
}
/* can't edit outside of the physical space */
@ -179,6 +199,8 @@ cellCB (Widget mw, XtPointer cd, XtPointer cb)
}
case XbaeLeaveCellReason: {
leaveCB (mw, cd, cb);
wrapVerifyCursorPosition (table, table->reverify_phys_row,
table->reverify_phys_col);
break;
}
default:
@ -453,32 +475,33 @@ traverseCB (Widget mw, XtPointer cd, XtPointer cb)
}
}
/* Don't do a thing unless we verify that the row and column
* are in bounds. Ordinarily, they are always in bounds, except
* in an unusual, arguably buggy situation: If the table has
* been recently resized smaller, then the Xbae code might report
* a traverse out of a cell that was in the larger array, but not
* in the smaller array. This is probably an Xbae bug. It
* will core dump array access.
*/
if ((row >= table->num_phys_rows) ||
(col >= table->num_phys_cols)) {
table->prev_phys_traverse_row = cbs->next_row;
table->prev_phys_traverse_col = cbs->next_column;
return;
}
xaccVerifyCursorPosition (table, row, col);
/* compute the cell location */
rel_row = table->locators[row][col]->phys_row_offset;
rel_col = table->locators[row][col]->phys_col_offset;
/* process right-moving traversals */
if (QRight == cbs->qparam) {
int next_row = arr->right_traverse_r[rel_row][rel_col];
int next_col = arr->right_traverse_c[rel_row][rel_col];
int next_row, next_col;
/* Don't do a thing unless we verify that the row and column
* are in bounds. Ordinarily, they are always in bounds, except
* in an unusual, arguably buggy situation: If the table has
* been recently resized smaller, then the Xbae code might report
* a traverse out of a cell that was in the larger array, but not
* in the smaller array. This is probably an Xbae bug. It
* will core dump array access.
*/
if ((row >= table->num_phys_rows) ||
(col >= table->num_phys_cols)) {
assert (0);
table->prev_phys_traverse_row = cbs->next_row;
table->prev_phys_traverse_col = cbs->next_column;
return;
}
/* compute the cell location */
rel_row = table->locators[row][col]->phys_row_offset;
rel_col = table->locators[row][col]->phys_col_offset;
next_row = arr->right_traverse_r[rel_row][rel_col];
next_col = arr->right_traverse_c[rel_row][rel_col];
/* if we are at the end of the traversal chain,
* hop out of this tab group, and into the next.
@ -498,6 +521,21 @@ traverseCB (Widget mw, XtPointer cd, XtPointer cb)
}
}
/*
xxxxxxxxxxx
hack alert --
this may work,. but document it ...
*/
if (table->traverse) {
int nr = cbs->next_row;
int nc = cbs->next_column;
table->reverify_phys_row = nr;
table->reverify_phys_col = nc;
(table->traverse) (table, &nr, &nc, table->client_data);
cbs->next_row = nr;
cbs->next_column = nc;
}
table->prev_phys_traverse_row = cbs->next_row;
table->prev_phys_traverse_col = cbs->next_column;
}
@ -526,7 +564,7 @@ xaccCreateTable (Table *table, Widget parent, char * name)
haveQuarks = True;
}
/* The 0'th row of the handlers is defeined as the header */
/* The 0'th row of the handlers is defined as the header */
alignments = NULL;
widths = NULL;
curs = table->handlers[0][0];
@ -581,9 +619,12 @@ void
xaccCreateCursor (Table *table, CellBlock *curs)
{
int i,j;
Widget reg = table->table_widget;
Widget reg;
if (!curs || !table) return;
if (!curs) return;
/* if Xbae itself is not yet created, then we can't go here either */
reg = table->table_widget;
if (!reg) return;
for (i=0; i<curs->numRows; i++) {
for (j=0; j<curs->numCols; j++) {
@ -823,6 +864,7 @@ table->entries[i][5]);
static void
doRefreshCursorGUI (Table * table, CellBlock *curs, int from_row, int from_col)
{
int phys_row, phys_col;
int to_row, to_col;
int i,j;
@ -831,6 +873,10 @@ doRefreshCursorGUI (Table * table, CellBlock *curs, int from_row, int from_col)
if ((0 > from_row) || (0 > from_col)) return;
/* compute the physical bounds of the current cursor */
phys_row = from_row;
phys_col = from_col;
from_row -= table->locators[phys_row][phys_col]->phys_row_offset;
from_col -= table->locators[phys_row][phys_col]->phys_col_offset;
to_row = from_row + curs->numRows;
to_col = from_col + curs->numCols;