From 2a808469172d1f161b68260964ccc223cf358cbd Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Sun, 11 Jan 1998 06:23:51 +0000 Subject: [PATCH] got modify verify callback working as desired. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@406 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/register/basiccell.h | 15 +++++- src/register/main.c | 6 +++ src/register/pricecell.c | 8 +-- src/register/table.c | 106 ++++++++++++++++++++++++++++----------- 4 files changed, 101 insertions(+), 34 deletions(-) diff --git a/src/register/basiccell.h b/src/register/basiccell.h index 0fa1608534..894cc1d0a9 100644 --- a/src/register/basiccell.h +++ b/src/register/basiccell.h @@ -23,7 +23,16 @@ enum { * "new", the string that would result is user's changes * are accepted. * It must return a string, or void if it rejects the change. - * The returned string will be the next cell value. + * The returned string will be used to update the cell value. + * + * Some memory management rules: + * (1) the callback must not modify the values of old, change, new + * (2) if the callback likes the new string, it may return the + * pointer to "new". It must *not* return the pointer to + * "change" or "old" + * (3) if the callback chooses to not return "new", it must + * malloc the memory for a new string. It does not need + * to worry about garbage collection. */ typedef struct _SingleCell { @@ -36,7 +45,9 @@ typedef struct _SingleCell { char * value; /* current value */ - char * (*modify_verify) (char *old, char *add, char *new); /* modify verify callback */ + const char * (*modify_verify) (const char *old, + const char *add, + const char *new); } SingleCell; diff --git a/src/register/main.c b/src/register/main.c index 5d8e1bcb83..df85dcdf95 100644 --- a/src/register/main.c +++ b/src/register/main.c @@ -28,6 +28,12 @@ CreateReg(Widget parent ) { cell->width = 9; xaccAddCell (header, cell); + cell = xaccMallocPriceCell(); + cell->row = 0; + cell->col = 4; + cell->width = 9; + xaccAddCell (curs, cell); + table = xaccMallocTable (0, 0); table -> cursor = curs; diff --git a/src/register/pricecell.c b/src/register/pricecell.c index d8ac1e5f61..234e973ea6 100644 --- a/src/register/pricecell.c +++ b/src/register/pricecell.c @@ -4,11 +4,11 @@ #include "price.h" #include "single.h" -static char * -PriceMV (char * old, char *change, char *new) +static const char * +PriceMV (const char * old, const char *change, const char *new) { - printf (" price mv called %s %s %s \n", old, change, new); - return strdup (new); + printf (" price mv called old:%s change:%s new:%s \n", old, change, new); + return new; } /* ================================================ */ diff --git a/src/register/table.c b/src/register/table.c index 7035499a23..a0613d6865 100644 --- a/src/register/table.c +++ b/src/register/table.c @@ -57,6 +57,7 @@ xaccInitTable (Table * table, int tile_rows, int tile_cols) } table->num_phys_rows = num_phys_rows; table->num_phys_cols = num_phys_cols; + table->num_header_rows = num_header_rows; table->num_tile_rows = tile_rows; table->num_tile_cols = tile_cols; @@ -66,7 +67,9 @@ xaccInitTable (Table * table, int tile_rows, int tile_cols) for (i=0; ientries[i] = (char **) malloc (num_phys_cols * sizeof (char *)); for (j=0; jentries[i][j] = NULL; /* hack alert ... */ + /* the Xbae matrix hates null cell values, so lets + * accomodate it by letting empty cells have empty + * strings */ table->entries[i][j] = strdup (""); } } @@ -131,6 +134,7 @@ modifyCB (Widget mw, XtPointer cd, XtPointer cb) Table *table; XbaeMatrixModifyVerifyCallbackStruct *cbs; int row, col; + int rel_row, rel_col; CellBlock *arr; table = (Table *) cd; @@ -146,39 +150,85 @@ modifyCB (Widget mw, XtPointer cd, XtPointer cb) /* 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; + + /* header rows cannot be modified */ + if (row < table->num_header_rows) return; + /* compute the cell location */ + rel_row = row; + rel_col = col; + /* remove offset for the header rows */ - arr = table->header; - if (arr) { - /* header rows cannot be modified */ - if (row < arr->numRows) return; - row -= arr->numRows; - } + rel_row -= table->num_header_rows; - /* call the cell callback */ + /* prepare to call the cell callback */ arr = table->cursor; if (arr) { - row %= arr->numRows; - col %= arr->numCols; -printf ("arr %p cells %p %d %d \n", arr, arr->cells, row, col); -printf ("cell row %p \n", arr->cells[row]); -printf ("cell col %p \n", arr->cells[row][col]); - if (arr->cells[row][col]) { - char * (*mv) (char *, char *, char *); - mv = arr->cells[row][col]->modify_verify; - if (mv) { - char * tmp; - tmp = (*mv) ("old", "haha", "new"); - - /* if the callback returned a non-null value, allow the edit */ - if (tmp) { - cbs->verify->doit = True; - } - } - } + 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; + + /* 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); + } + } + } } - - } /* ==================================================== */