diff --git a/src/register/basiccell.c b/src/register/basiccell.c index f3d62e7a20..48edaf9b0a 100644 --- a/src/register/basiccell.c +++ b/src/register/basiccell.c @@ -4,6 +4,8 @@ #include "basiccell.h" +/* ===================================================== */ + BasicCell * xaccMallocBasicCell (void) { BasicCell * cell; @@ -12,12 +14,15 @@ BasicCell * xaccMallocBasicCell (void) return cell; } +/* ===================================================== */ + void xaccInitBasicCell (BasicCell *cell) { cell->input_output = 1; cell->width = 0; cell->alignment = 0; cell->value = 0x0; + cell->set_value = NULL; cell->enter_cell = NULL; cell->modify_verify = NULL; cell->leave_cell = NULL; @@ -27,10 +32,23 @@ void xaccInitBasicCell (BasicCell *cell) cell->gui_private = NULL; } +/* ===================================================== */ + void xaccSetBasicCellValue (BasicCell *cell, const char *val) { - if (cell->value) free (cell->value); - cell->value = strdup (val); + void (*cb) (struct _BasicCell *, const char *); + + cb = cell->set_value; + if (cb) { + /* avoid recursion by disabling the + * callback while it'sbeing called. */ + cell->set_value = NULL; + (*cb) (cell, val); + cell->set_value = cb; + } else { + if (cell->value) free (cell->value); + cell->value = strdup (val); + } } -/* ------------------ end of file ---------------------- */ +/* ================== end of file ====================== */ diff --git a/src/register/basiccell.h b/src/register/basiccell.h index 5cb5ae88bf..7dfe6ffc2e 100644 --- a/src/register/basiccell.h +++ b/src/register/basiccell.h @@ -3,44 +3,70 @@ * basiccell.h * * FUNCTION: - * The BasicCell struct provides an abstract base class + * The BasicCell class provides an abstract base class * defining the handling of the editing of a cell of a table. * Classes that provide the actual handling for different * cell types should inherit from this class. * + * The BasicCell class encapsulates a single string value + * which can be set & read by the programmer, and edited + * by the "user". In the text below, the "user" is the + * person controlling the mouse and keyboard. Thus, when + * the user makes a move, it means that they have somehow + * intereacted with the cell, by clikcing with mouse or by + * typing at the keyboard. This class provides three + * callbacks which allow the programmer to understand what + * the user is doing. + * + * The programmer can create a custom GUI for editing the + * contents of the cell. There are three callbacks to allow + * a custom GUI to be created, destroyed and moved about. + * + * Since this class is implemented in C not C++, there is + * a "minor" problem with inheritance. To emulate the + * overloading of a virtual "SetValues" method, there is + * a set_value() callback, which will be called whenever + * the xaccSetBasicCellValue() subroutine is called. + * + * VIRTUAL/OVERLOADED METHODS: + * The set_value() callback will be called whenever the + * xaccSetBasicCellValue() method is called. Derived + * classes should provide a callback here if they need + * to understand special cell formats. + * * MEMBERS: * The input_output member is zero if the cell is supposed * to only display values, but not accept user input. If * non-zero, then the callbacks below are used to when the * cell is entered. * - * CALLBACKS: + * + * USER CALLBACKS: * 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. + * 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. + * 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, - * "add", the string the user is attemptiong to add - * (will be null if text is being deleted). - * "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 used to update the cell value. + * 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, + * "add", the string the user is attemptiong to add + * (will be null if text is being deleted). + * "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 used to update the cell value. * * Some memory management rules: * (1) the callback must not modify the values of old, change, new @@ -51,12 +77,32 @@ * malloc the memory for a new string. It does not need * to worry about garbage collection. * - * GUI STUFF: - * The realize callback will be called when GUI-specific - * initalization needs to be done. For Xt/Motif, the second - * argument will be cast to the parent widget. * - * HACK ALERT NOTES: + * GUI CALLBACKS: + * The cell may have some specific GUI elements which need + * to be initialized/positioned/etc. There are three GUI + * callbacks that allow the programmer to perform GUI-specific + * initialization & changes. + * + * The realize() callback will be called when GUI-specific + * initalization needs to be done. For Xt/Motif, the second + * argument will be cast to the parent widget. The third + * argument passes in the desired pixel-width for the GUI + * element. (Yes, the pixel-size thing is a hack that we + * allow for the moment. See below for more info.) + * + * The destroy() callback will be called when the GUI associated + * with the cell needs to be destroyed. + * + * The move() callback will be called when the GUI element needs + * to be positioned to a new location within the table grid. + * The second and third arguments are the physical (not virtual) + * row and column that the GUI elemnt should be moved to. + * + * The gui_private member may be used by the derived class to + * store any additional GUI-specific data. + * + * GUI HACK ALERT NOTES: * The realize method takes a width argument only as a hack * to work around the fact that the combo-box requires a width * in pixels, rather than in characters. It would be nice if @@ -74,24 +120,26 @@ typedef struct _BasicCell { char * value; /* current value */ - const char * (*enter_cell) (struct _BasicCell *, - const char * current); + /* "virtual", overloaded set-value method */ + void (*set_value) (struct _BasicCell *, + const char * new_value); + + /* cell-editing callbacks */ + const char * (*enter_cell) (struct _BasicCell *, + const char * current); const char * (*modify_verify) (struct _BasicCell *, const char *old, const char *add, const char *new); - const char * (*leave_cell) (struct _BasicCell *, - const char * current); + const char * (*leave_cell) (struct _BasicCell *, + const char * current); - /* private, GUI-specific initializer */ + /* private, GUI-specific callbacks */ void (* realize) (struct _BasicCell *, void *gui_handle, int pixel_width); - - /* private, GUI-specific callback to move gui element */ - void (* move) (struct _BasicCell *, int phys_row, int phys_col); - - /* private, GUI-specific callback to detroy gui element */ + void (* move) (struct _BasicCell *, + int phys_row, int phys_col); void (* destroy) (struct _BasicCell *); /* general hook for gui-private data */ diff --git a/src/register/combocell.c b/src/register/combocell.c index 1235172301..bff804a78c 100644 --- a/src/register/combocell.c +++ b/src/register/combocell.c @@ -24,9 +24,14 @@ static void dropDownCB (Widget w, XtPointer cd, XtPointer cb ); static void realizeCombo (struct _BasicCell *bcell, void *w, int width); static void moveCombo (struct _BasicCell *bcell, int phys_row, int phys_col); static void destroyCombo (struct _BasicCell *bcell); +static void setComboValue (struct _BasicCell *bcell, const char *value); static const char * enterCombo (struct _BasicCell *bcell, const char *value); static const char * leaveCombo (struct _BasicCell *bcell, const char *value); +#define SET(cell,str) { \ + if ((cell)->value) free ((cell)->value); \ + (cell)->value = strdup (str); \ +} /* =============================================== */ @@ -42,6 +47,7 @@ void xaccInitComboCell (ComboCell *cell) { xaccInitBasicCell ( &(cell->cell)); cell->cell.realize = realizeCombo; + cell->cell.set_value = setComboValue; cell->menuitems = (char **) malloc (sizeof (char *)); cell->menuitems[0] = NULL; } @@ -97,7 +103,7 @@ xaccSetComboCellValue (ComboCell *cell, const char * str) { PopBox * box; - xaccSetBasicCellValue (&(cell->cell), str); + SET (&(cell->cell), str); box = (PopBox *) (cell->cell.gui_private); if (str) { @@ -117,6 +123,15 @@ xaccSetComboCellValue (ComboCell *cell, const char * str) /* =============================================== */ +static void +setComboValue (struct _BasicCell *_cell, const char *str) +{ + ComboCell * cell = (ComboCell *) _cell; + xaccSetComboCellValue (cell, str); +} + +/* =============================================== */ + static void realizeCombo (struct _BasicCell *bcell, void *w, int pixel_width) { @@ -341,6 +356,12 @@ static void selectCB (Widget w, XtPointer cd, XtPointer cb ) cell = (ComboCell *) cd; box = (PopBox *) (cell->cell.gui_private); + if ((0 > box->currow) || (0 > box->curcol)) { +/* + printf ("Internal Error: ComboBox: incorrect cell location \n"); + return; +*/ + } /* check the reason, because the unslect callback * doesn't even have a value field! */ if ( (XmCR_SINGLE_SELECT == selection->reason) || @@ -349,9 +370,9 @@ static void selectCB (Widget w, XtPointer cd, XtPointer cb ) } if (!choice) choice = XtNewString (""); +printf ("combo selectcb choice %s at %d %d \n", choice, box->currow, box->curcol); XbaeMatrixSetCell (box->parent, box->currow, box->curcol, choice); - xaccSetBasicCellValue (&(cell->cell), choice); -printf ("celectcb choice %s \n", choice); + SET (&(cell->cell), choice); XtFree (choice); /* a diffeent way of getting the user's selection ... */ diff --git a/src/register/datecell.c b/src/register/datecell.c index 8cfd2bda04..650d6f3975 100644 --- a/src/register/datecell.c +++ b/src/register/datecell.c @@ -1,10 +1,25 @@ +/* + * FILE: + * datecell.c + * + * HISTORY: + * Copyright (c) 1998 Linas Vepstas + */ + #include #include #include "basiccell.h" #include "datecell.h" +static void setDateCellValue (struct _BasicCell *, const char *); + +#define SET(cell,str) { \ + if ((cell)->value) free ((cell)->value); \ + (cell)->value = strdup (str); \ +} + #define DATE_SEP '/' /* ================================================ */ @@ -256,7 +271,9 @@ DateMV (struct _BasicCell *_cell, prtDate (buff, date->tm_mday, date->tm_mon+1, date->tm_year+1900); - xaccSetBasicCellValue (&(cell->cell), buff); + if (cell->cell.value) free (cell->cell.value); + cell->cell.value = strdup (buff); + datestr = strdup (buff); return datestr; @@ -279,7 +296,9 @@ DateLeave (struct _BasicCell *_cell, const char * curr) cell->date.tm_mon+1, cell->date.tm_year+1900); - xaccSetBasicCellValue (&(cell->cell), buff); + if (cell->cell.value) free (cell->cell.value); + cell->cell.value = strdup (buff); + retval = strdup (buff); return retval; } @@ -312,11 +331,12 @@ xaccInitDateCell (DateCell *cell) cell->date = *now; prtDate (buff, now->tm_mday, now->tm_mon+1, now->tm_year+1900); - xaccSetBasicCellValue (&(cell->cell), buff); + SET (&(cell->cell), buff); cell->cell.enter_cell = DateEnter; cell->cell.modify_verify = DateMV; cell->cell.leave_cell = DateLeave; + cell->cell.set_value = setDateCellValue; } /* ================================================ */ @@ -337,7 +357,27 @@ xaccSetDateCellValue (DateCell *cell, int day, int mon, int year) cell->date.tm_year = dada.tm_year; prtDate (buff, dada.tm_mday, dada.tm_mon+1, dada.tm_year+1900); - xaccSetBasicCellValue (&(cell->cell), buff); + + if (cell->cell.value) free (cell->cell.value); + cell->cell.value = strdup (buff); +} + +/* ================================================ */ + +static void +setDateCellValue (struct _BasicCell *_cell, const char *str) +{ + DateCell *cell = (DateCell *) _cell; + char buff[30]; + + xaccParseDate (&(cell->date), str); + + prtDate (buff, cell->date.tm_mday, + cell->date.tm_mon+1, + cell->date.tm_year+1900); + + if (cell->cell.value) free (cell->cell.value); + cell->cell.value = strdup (buff); } /* ============== END OF FILE ===================== */ diff --git a/src/register/pricecell.c b/src/register/pricecell.c index e7582bd202..ff849ba835 100644 --- a/src/register/pricecell.c +++ b/src/register/pricecell.c @@ -1,11 +1,22 @@ #include +#include "util.h" + #include "basiccell.h" #include "pricecell.h" +static void PriceSetValue (struct _BasicCell *, const char *); +static void Set (BasicCell *, const char *); + #define DECIMAL_PT '.' + +#define SET(cell,str) { \ + if ((cell)->value) free ((cell)->value); \ + (cell)->value = strdup (str); \ +} + /* ================================================ */ /* This callback only allows numbers with a single * decimal point in them */ @@ -16,7 +27,7 @@ PriceMV (struct _BasicCell *_cell, const char *change, const char *newval) { - BasicCell *cell = (BasicCell *) _cell; + PriceCell *cell = (PriceCell *) _cell; /* accept the newval string if user action was delete, etc. */ if (change) { @@ -33,8 +44,9 @@ PriceMV (struct _BasicCell *_cell, } } - /* hack alert - should parse the float pt value */ - xaccSetBasicCellValue (cell, newval); + /* parse the float pt value and store it */ + cell->amount = xaccParseUSAmount (newval); + SET ((&(cell->cell)), newval); return newval; } @@ -57,9 +69,10 @@ xaccInitPriceCell (PriceCell *cell) xaccInitBasicCell( &(cell->cell)); cell->amount = 0.0; - xaccSetBasicCellValue ( &(cell->cell), "0.0"); + SET ( &(cell->cell), "0.0"); cell->cell.modify_verify = PriceMV; + cell->cell.set_value = PriceSetValue; } /* ================================================ */ @@ -69,7 +82,7 @@ void xaccSetPriceCellValue (PriceCell * cell, double amt) char buff[40]; cell->amount = amt; sprintf (buff, "%.3f", amt); - xaccSetBasicCellValue ( &(cell->cell), buff); + SET ( &(cell->cell), buff); } /* ================================================ */ @@ -79,7 +92,7 @@ void xaccSetAmountCellValue (PriceCell * cell, double amt) char buff[40]; cell->amount = amt; sprintf (buff, "%.2f", amt); - xaccSetBasicCellValue ( &(cell->cell), buff); + SET ( &(cell->cell), buff); } /* ================================================ */ @@ -93,13 +106,29 @@ void xaccSetDebCredCellValue (PriceCell * deb, if (0.0 <= amt) { sprintf (buff, "%.2f", amt); - xaccSetBasicCellValue ( &(cred->cell), buff); - xaccSetBasicCellValue ( &(deb->cell), ""); + SET ( &(cred->cell), buff); + SET ( &(deb->cell), ""); } else { sprintf (buff, "%.2f", -amt); - xaccSetBasicCellValue ( &(cred->cell), ""); - xaccSetBasicCellValue ( &(deb->cell), buff); + SET ( &(cred->cell), ""); + SET ( &(deb->cell), buff); } } +/* ================================================ */ + +static void +PriceSetValue (struct _BasicCell *_cell, const char *str) +{ + char buff[40]; + PriceCell *cell = (PriceCell *) _cell; + + SET (((BasicCell *)_cell), str); + + cell->amount = xaccParseUSAmount (str); + + sprintf (buff, "%.2f", cell->amount); + SET ( &(cell->cell), buff); +} + /* --------------- end of file ---------------------- */ diff --git a/src/register/quickfillcell.c b/src/register/quickfillcell.c index 454f08214f..4d7755cd8b 100644 --- a/src/register/quickfillcell.c +++ b/src/register/quickfillcell.c @@ -4,6 +4,21 @@ #include "basiccell.h" #include "quickfillcell.h" +#define SET(cell,str) { \ + if ((cell)->value) free ((cell)->value); \ + (cell)->value = strdup (str); \ +} + +/* ================================================ */ + +static void +quick_set (struct _BasicCell *_cell, + const char *val) +{ + QuickFillCell *cell = (QuickFillCell *) _cell; + xaccSetQuickFillCellValue (cell, val); +} + /* ================================================ */ /* when entering new cell, reset pointer to root */ @@ -61,7 +76,7 @@ quick_modify (struct _BasicCell *_cell, if (cell->qf) retval = strdup (cell->qf->text); } - xaccSetBasicCellValue (&(cell->cell), retval); + SET (&(cell->cell), retval); return retval; } @@ -104,15 +119,16 @@ xaccInitQuickFillCell (QuickFillCell *cell) cell->cell.enter_cell = quick_enter; cell->cell.modify_verify = quick_modify; cell->cell.leave_cell = quick_leave; + cell->cell.set_value = quick_set; } /* ================================================ */ void -xaccSetQuickFillCellValue (QuickFillCell *cell, char * value) +xaccSetQuickFillCellValue (QuickFillCell *cell, const char * value) { xaccQFInsertText (cell->qfRoot, value); - xaccSetBasicCellValue (&(cell->cell), value); + SET (&(cell->cell), value); } /* =============== END OF FILE ==================== */ diff --git a/src/register/quickfillcell.h b/src/register/quickfillcell.h index fcdddb957e..5b84f5ba4d 100644 --- a/src/register/quickfillcell.h +++ b/src/register/quickfillcell.h @@ -32,7 +32,7 @@ typedef struct _QuickFillCell { QuickFillCell * xaccMallocQuickFillCell (void); void xaccInitQuickFillCell (QuickFillCell *); -void xaccSetQuickFillCellValue (QuickFillCell *, char *); +void xaccSetQuickFillCellValue (QuickFillCell *, const char *); #endif /* __XACC_FILL_CELL_C__ */ diff --git a/src/register/table.c b/src/register/table.c index 8ce28e4437..5076e774fc 100644 --- a/src/register/table.c +++ b/src/register/table.c @@ -473,7 +473,7 @@ table->current_cursor_col, virt_row, virt_col); /* before leaving, the current virtual position, - * commit any aedits that have been accumulated + * commit any edits that have been accumulated * in the cursor */ xaccCommitCursor (table); xaccMoveCursorGUI (table, virt_row, virt_col);