implement enter, leve cell callbacks

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@413 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 1998-01-12 08:59:06 +00:00
parent fba652b072
commit 349b53757f
3 changed files with 293 additions and 100 deletions

View File

@ -20,8 +20,9 @@ void xaccInitSingleCell (SingleCell *cell)
cell->width = 0;
cell->alignment = 0;
cell->value = 0x0;
cell->enter_cell = NULL;
cell->modify_verify = NULL;
cell->extdata = NULL;
cell->leave_cell = NULL;
cell->block = NULL;
}

View File

@ -14,7 +14,24 @@ enum {
};
/* The modify-verify callback is called when a user
/*
* The enter_cell() callback is called when the user first
* makes a move to enter a cell. The current value of the
* cell is passed as the argument. If the callback wishes
* to change the value of the cell, it can return a non-null
* string. Alternately, to leave the value of the cell
* unchanged, it can return NULL. If a string is returned,
* the string must be as the result of a malloc.
*
* The leave_cell() callback is called when the user exits
* a cell. The current value of the cell is passed as the
* argument. If the callback wishes to change the value of
* the cell, it can return a non-null string. Alternately,
* to leave the value of the cell unchanged, it can return
* NULL. If a string is returned, the string must be as the
* result of a malloc.
*
* The modify-verify callback is called when a user
* makes a change to a cell.
* The three arguments passed in are :
* "old", the string prior to user's attempted modification,
@ -46,13 +63,13 @@ typedef struct _SingleCell {
/* private data */
char * value; /* current value */
const char * (*enter_cell) (const char * current);
const char * (*modify_verify) (const char *old,
const char *add,
const char *new);
const char * (*leave_cell) (const char * current);
struct _CellBlock *block; /* back-pointer to parent container */
void * extdata; /* generic extension mechanism */
} SingleCell;

View File

@ -6,6 +6,11 @@
#include "cell.h"
#include "table.h"
static void enterCB (Widget mw, XtPointer cd, XtPointer cb);
static void leaveCB (Widget mw, XtPointer cd, XtPointer cb);
static void modifyCB (Widget mw, XtPointer cd, XtPointer cb);
static void traverseCB (Widget mw, XtPointer cd, XtPointer cb);
Table *
xaccMallocTable (int tile_rows, int tile_cols)
{
@ -123,56 +128,31 @@ xaccRefreshHeader (Table *table)
}
/* ==================================================== */
/* this routine calls the individual cell callbacks */
static void
enterCB (Widget mw, XtPointer cd, XtPointer cb)
cellCB (Widget mw, XtPointer cd, XtPointer cb)
{
Table *table;
XbaeMatrixDefaultActionCallbackStruct *cbs;
int row, col;
table = (Table *) cd;
cbs = (XbaeMatrixDefaultActionCallbackStruct *)cb;
row = cbs->row;
col = cbs->column;
if (XbaeEnterCellReason != cbs->reason) return;
printf ("enter %d %d \n", row, col);
}
/* ==================================================== */
/* this routine calls the individual cell callbacks */
static void
modifyCB (Widget mw, XtPointer cd, XtPointer cb)
{
Table *table;
XbaeMatrixModifyVerifyCallbackStruct *cbs;
int row, col;
int rel_row, rel_col;
CellBlock *arr;
int invalid = 0;
table = (Table *) cd;
cbs = (XbaeMatrixModifyVerifyCallbackStruct *) cb;
cbs = (XbaeMatrixDefaultActionCallbackStruct *) cb;
row = cbs->row;
col = cbs->column;
if (XbaeModifyVerifyReason != cbs->reason) return;
printf ("modify %d %d %s \n", row, col, cbs->verify->text->ptr);
/* reject edits by default, unless the cell handler allows them */
cbs->verify->doit = False;
/* can't edit outside of the physical space */
if ((0 > row) || (0 > col)) return;
if ((row >= table->num_phys_rows) || (col >= table->num_phys_cols)) return;
invalid = (0 > row) || (0 > col) ;
invalid = invalid || (row >= table->num_phys_rows);
invalid = invalid || (col >= table->num_phys_cols);
/* header rows cannot be modified */
if (row < table->num_header_rows) return;
invalid = invalid || (row < table->num_header_rows);
/* compute the cell location */
rel_row = row;
@ -186,86 +166,280 @@ modifyCB (Widget mw, XtPointer cd, XtPointer cb)
if (arr) {
rel_row %= (arr->numRows);
rel_col %= (arr->numCols);
if (arr->cells[rel_row][rel_col]) {
const char * (*mv) (const char *, const char *, const char *);
mv = arr->cells[rel_row][rel_col]->modify_verify;
if (! (arr->cells[rel_row][rel_col])) invalid = TRUE;
} else {
invalid = TRUE;
}
/* OK, if there is a callback for this cell, call it */
if (mv) {
const char *old, *change;
char *new;
const char *retval;
int len;
old = cbs->prev_text;
change = cbs->verify->text->ptr;
/* but first, compute the new string */
len = 1;
if (old) len += strlen (old);
if (change) len += strlen (change);
new = (char *) malloc (len);
/* text may be inserted, or deleted, or replaced ... */
new[0] = 0;
strncat (new, old, cbs->verify->startPos);
if (change) strcat (new, change);
strcat (new, &old[(cbs->verify->endPos)]);
retval = (*mv) (old, change, new);
/* if the callback returned a non-null value, allow the edit */
if (retval) {
/* update data. bounds check done earlier */
free (table->entries[row][col]);
table->entries[row][col] = (char *) retval;
/* if the callback modified the display string,
* update the display cell as well */
if (retval != new) {
XbaeMatrixSetCell (mw, row, col, (char *) retval);
XbaeMatrixRefreshCell (mw, row, col);
XbaeMatrixSetCursorPosition (mw, (cbs->verify->endPos) +1);
/* the default update has already been overridden,
* so don't allow Xbae to update */
cbs->verify->doit = False;
/* avoid wasting memory */
free (new);
} else {
/* the proposed edit was accepted! */
cbs->verify->doit = True;
}
} else {
/* avoid wasting memory */
free(new);
}
/* oops the callback failed for some reason ...
* reject the enter/edit/leave and return */
if (invalid) {
switch (cbs->reason) {
case XbaeEnterCellReason: {
XbaeMatrixEnterCellCallbackStruct *ecbs;
ecbs = (XbaeMatrixEnterCellCallbackStruct *) cbs;
ecbs->doit = False;
ecbs->map = False;
break;
}
case XbaeModifyVerifyReason: {
XbaeMatrixModifyVerifyCallbackStruct *mvcbs;
mvcbs = (XbaeMatrixModifyVerifyCallbackStruct *) cbs;
mvcbs->verify->doit = False;
break;
}
case XbaeTraverseCellReason: {
XbaeMatrixTraverseCellCallbackStruct *tcbs;
tcbs = (XbaeMatrixTraverseCellCallbackStruct *) cbs;
tcbs->next_row = 0;
tcbs->next_column = 0;
break;
}
case XbaeLeaveCellReason: {
XbaeMatrixLeaveCellCallbackStruct *lcbs;
lcbs = (XbaeMatrixLeaveCellCallbackStruct *) cbs;
lcbs->doit = False;
break;
}
}
return;
}
/* if we got to here, then there is a cell handler for
* this cell. Dispatch for processing. */
switch (cbs->reason) {
case XbaeEnterCellReason: {
enterCB (mw, cd, cb);
break;
}
case XbaeModifyVerifyReason: {
modifyCB (mw, cd, cb);
break;
}
case XbaeLeaveCellReason: {
leaveCB (mw, cd, cb);
break;
}
case XbaeTraverseCellReason: {
traverseCB (mw, cd, cb);
break;
}
}
}
/* ==================================================== */
/* this callback assumes that basic error checking has already
* been performed. */
static void
enterCB (Widget mw, XtPointer cd, XtPointer cb)
{
Table *table;
CellBlock *arr;
XbaeMatrixEnterCellCallbackStruct *cbs;
int row, col;
int rel_row, rel_col;
const char * (*enter) (const char *);
table = (Table *) cd;
arr = table->cursor;
cbs = (XbaeMatrixEnterCellCallbackStruct *) cb;
/* compute the cell location */
row = cbs->row;
col = cbs->column;
rel_row = row - table->num_header_rows;
rel_col = col;
rel_row %= (arr->numRows);
rel_col %= (arr->numCols);
printf ("enter %d %d \n", row, col);
/* since we are here, there must be a cell handler.
* therefore, we accept entry into the cell by default,
*/
cbs->doit = True;
cbs->map = True;
/* OK, if there is a callback for this cell, call it */
enter = arr->cells[rel_row][rel_col]->enter_cell;
if (enter) {
const char *val, *retval;
val = table->entries[row][col];
retval = enter (val);
if (val != retval) {
if (table->entries[row][col]) free (table->entries[row][col]);
table->entries[row][col] = (char *) retval;
XbaeMatrixSetCell (mw, row, col, (char *) retval);
XbaeMatrixRefreshCell (mw, row, col);
}
}
}
/* ==================================================== */
/* this routine calls the individual cell callbacks */
static void
modifyCB (Widget mw, XtPointer cd, XtPointer cb)
{
Table *table;
CellBlock *arr;
XbaeMatrixModifyVerifyCallbackStruct *cbs;
int row, col;
int rel_row, rel_col;
const char * (*mv) (const char *, const char *, const char *);
const char *oldval, *change;
char *newval;
const char *retval;
int len;
table = (Table *) cd;
arr = table->cursor;
cbs = (XbaeMatrixModifyVerifyCallbackStruct *) cb;
/* compute the cell location */
row = cbs->row;
col = cbs->column;
rel_row = row;
rel_col = col;
rel_row -= table->num_header_rows;
rel_row %= (arr->numRows);
rel_col %= (arr->numCols);
/* accept edits by default, unless the cell handler rejects them */
cbs->verify->doit = True;
oldval = cbs->prev_text;
change = cbs->verify->text->ptr;
/* first, compute the newval string */
len = 1;
if (oldval) len += strlen (oldval);
if (change) len += strlen (change);
newval = (char *) malloc (len);
/* text may be inserted, or deleted, or replaced ... */
newval[0] = 0;
strncat (newval, oldval, cbs->verify->startPos);
if (change) strcat (newval, change);
strcat (newval, &oldval[(cbs->verify->endPos)]);
/* OK, if there is a callback for this cell, call it */
mv = arr->cells[rel_row][rel_col]->modify_verify;
if (mv) {
retval = (*mv) (oldval, change, newval);
/* if the callback returned a non-null value, allow the edit */
if (retval) {
/* update data. bounds check done earlier */
free (table->entries[row][col]);
table->entries[row][col] = (char *) retval;
/* if the callback modified the display string,
* update the display cell as well */
if (retval != newval) {
XbaeMatrixSetCell (mw, row, col, (char *) retval);
XbaeMatrixRefreshCell (mw, row, col);
XbaeMatrixSetCursorPosition (mw, (cbs->verify->endPos) +1);
/* the default update has already been overridden,
* so don't allow Xbae to update */
cbs->verify->doit = False;
/* avoid wasting memory */
free (newval);
}
} else {
/* NULL return value means the edit was rejected */
cbs->verify->doit = False;
/* avoid wasting memory */
free(newval);
}
} else {
/* update data. bounds check done earlier */
free (table->entries[row][col]);
table->entries[row][col] = strdup (newval);
}
}
/* ==================================================== */
static void
leaveCB (Widget mw, XtPointer cd, XtPointer cb)
{
Table *table;
CellBlock *arr;
XbaeMatrixLeaveCellCallbackStruct *cbs;
int row, col;
int rel_row, rel_col;
const char * (*leave) (const char *);
table = (Table *) cd;
arr = table->cursor;
cbs = (XbaeMatrixLeaveCellCallbackStruct *) cb;
/* compute the cell location */
row = cbs->row;
col = cbs->column;
rel_row = row - table->num_header_rows;
rel_col = col;
rel_row %= (arr->numRows);
rel_col %= (arr->numCols);
printf ("leave %d %d \n", row, col);
/* by default, accept whateve the final roposed edit is */
cbs->doit = True;
/* OK, if there is a callback for this cell, call it */
leave = arr->cells[rel_row][rel_col]->leave_cell;
if (leave) {
const char *val, *retval;
val = cbs->value;
retval = leave (val);
if (val != retval) {
if (table->entries[row][col]) free (table->entries[row][col]);
table->entries[row][col] = (char *) retval;
cbs->value = strdup (retval);
}
} else {
if (table->entries[row][col]) free (table->entries[row][col]);
table->entries[row][col] = strdup (cbs->value);
}
}
/* ==================================================== */
static void
traverseCB (Widget mw, XtPointer cd, XtPointer cb)
{
Table *table;
XbaeMatrixDefaultActionCallbackStruct *cbs;
CellBlock *arr;
XbaeMatrixTraverseCellCallbackStruct *cbs;
int row, col;
int rel_row, rel_col;
table = (Table *) cd;
cbs = (XbaeMatrixDefaultActionCallbackStruct *)cb;
arr = table->cursor;
cbs = (XbaeMatrixTraverseCellCallbackStruct *) cb;
/* compute the cell location */
row = cbs->row;
col = cbs->column;
if (XbaeTraverseCellReason != cbs->reason) return;
rel_row = row - table->num_header_rows;
rel_col = col;
rel_row %= (arr->numRows);
rel_col %= (arr->numCols);
printf ("traverse %d %d \n", row, col);
}
@ -319,9 +493,10 @@ xaccCreateTable (Table *table, Widget parent, char * name)
XtManageChild (reg);
XtAddCallback (reg, XmNenterCellCallback, enterCB, (XtPointer)table);
XtAddCallback (reg, XmNmodifyVerifyCallback, modifyCB, (XtPointer)table);
XtAddCallback (reg, XmNtraverseCellCallback, traverseCB, (XtPointer)table);
XtAddCallback (reg, XmNenterCellCallback, cellCB, (XtPointer)table);
XtAddCallback (reg, XmNleaveCellCallback, cellCB, (XtPointer)table);
XtAddCallback (reg, XmNmodifyVerifyCallback, cellCB, (XtPointer)table);
XtAddCallback (reg, XmNtraverseCellCallback, cellCB, (XtPointer)table);
table->reg = reg;
return (reg);