diff --git a/src/register/QuickFill.c b/src/register/QuickFill.c index dda95b85b46..e34655953e3 100644 --- a/src/register/QuickFill.c +++ b/src/register/QuickFill.c @@ -32,9 +32,16 @@ #include "util.h" +struct _QuickFill +{ + char * text; /* the first matching text string */ + GHashTable *matches; /* array of children in the tree */ +}; + + /** PROTOTYPES ******************************************************/ -static void qfInsertTextRec(QuickFill *qf, const char * text, int depth, - QuickFillSort sort); +static void quickfill_insert_recursive (QuickFill *qf, const char *text, + int depth, QuickFillSort sort); /* This static indicates the debugging module that this .o belongs to. */ static short module = MOD_REGISTER; @@ -42,75 +49,90 @@ static short module = MOD_REGISTER; /********************************************************************\ \********************************************************************/ -static int -CHAR_TO_INDEX(char c) +static guint +quickfill_hash (gconstpointer key) { - int index = toupper(c); + return GPOINTER_TO_UINT (key); +} - if (index >= (QFNUM - 1)) - return 0; +static gint +quickfill_compare (gconstpointer key1, gconstpointer key2) +{ + guint k1 = GPOINTER_TO_UINT (key1); + guint k2 = GPOINTER_TO_UINT (key2); - return index + 1; + return (k1 == k2); } /********************************************************************\ \********************************************************************/ QuickFill * -xaccMallocQuickFill(void) +gnc_quickfill_new (void) { QuickFill *qf; - int i; - qf = g_new(QuickFill, 1); - - for(i = 0; i < QFNUM; i++) - qf->qf[i] = NULL; + qf = g_new (QuickFill, 1); qf->text = NULL; + qf->matches = g_hash_table_new (quickfill_hash, quickfill_compare); return qf; } /********************************************************************\ \********************************************************************/ -void -xaccFreeQuickFill(QuickFill *qf) +static void +destroy_helper (gpointer key, gpointer value, gpointer data) { - int i; + gnc_quickfill_destroy (value); +} - if (qf == NULL ) +void +gnc_quickfill_destroy (QuickFill *qf) +{ + if (qf == NULL) return; - for(i = 0; i < QFNUM; i++) - { - xaccFreeQuickFill(qf->qf[i]); - qf->qf[i] = NULL; - } + g_hash_table_foreach (qf->matches, destroy_helper, NULL); + g_hash_table_destroy (qf->matches); + qf->matches = NULL; - if (qf->text != NULL) - g_free(qf->text); + g_free(qf->text); qf->text = NULL; g_free(qf); } +/********************************************************************\ +\********************************************************************/ +const char * +gnc_quickfill_string (QuickFill *qf) +{ + if (qf == NULL) + return NULL; + + return qf->text; +} + /********************************************************************\ \********************************************************************/ QuickFill * -xaccGetQuickFill(QuickFill *qf, char c) +gnc_quickfill_get_char_match (QuickFill *qf, char c) { + guint key = toupper(c); + if (qf == NULL) return NULL; - DEBUG("xaccGetQuickFill(): index = %d\n",CHAR_TO_INDEX(c)); + DEBUG ("xaccGetQuickFill(): index = %u\n", key); - return qf->qf[CHAR_TO_INDEX(c)]; + return g_hash_table_lookup (qf->matches, GUINT_TO_POINTER (key)); } /********************************************************************\ \********************************************************************/ QuickFill * -xaccGetQuickFillStrLen(QuickFill *qf, const char *str, int len) +gnc_quickfill_get_string_len_match (QuickFill *qf, const char *str, int len) { if (str == NULL) return NULL; @@ -120,7 +142,8 @@ xaccGetQuickFillStrLen(QuickFill *qf, const char *str, int len) if (qf == NULL) return NULL; - qf = qf->qf[CHAR_TO_INDEX(*str)]; + qf = gnc_quickfill_get_char_match (qf, *str); + str++; len--; } @@ -131,67 +154,66 @@ xaccGetQuickFillStrLen(QuickFill *qf, const char *str, int len) /********************************************************************\ \********************************************************************/ QuickFill * -xaccGetQuickFillStr(QuickFill *qf, const char *str) +gnc_quickfill_get_string_match (QuickFill *qf, const char *str) { if (str == NULL) return NULL; - return xaccGetQuickFillStrLen(qf, str, strlen(str)); + return gnc_quickfill_get_string_len_match (qf, str, strlen(str)); } /********************************************************************\ \********************************************************************/ -QuickFill * -xaccGetQuickFillUniqueLen( QuickFill *qf, int * length ) +static void +unique_len_helper (gpointer key, gpointer value, gpointer data) { - int last = 0; - int count; - int i; + QuickFill **qf_p = data; - *length = 0; + *qf_p = value; +} + +QuickFill * +gnc_quickfill_get_unique_len_match (QuickFill *qf, int * length) +{ + if (length != NULL) + *length = 0; if (qf == NULL) return NULL; while (1) { - count = 0; - for(i = 0; i < QFNUM; i++) - { - if (qf->qf[i] != NULL) - { - count++; - if (count > 1) - return qf; + guint count; - last = i; - } - } + count = g_hash_table_size (qf->matches); - if (count == 0) + if (count != 1) return qf; - qf = qf->qf[last]; - (*length)++; + g_hash_table_foreach (qf->matches, unique_len_helper, &qf); + + if (length != NULL) + (*length)++; } } /********************************************************************\ \********************************************************************/ void -xaccQFInsertText(QuickFill *qf, const char * text, QuickFillSort sort) +gnc_quickfill_insert (QuickFill *qf, const char * text, QuickFillSort sort) { - qfInsertTextRec(qf, text, 0, sort); + quickfill_insert_recursive (qf, text, 0, sort); } /********************************************************************\ \********************************************************************/ static void -qfInsertTextRec( QuickFill *qf, const char *text, int depth, - QuickFillSort sort ) +quickfill_insert_recursive (QuickFill *qf, const char *text, int depth, + QuickFillSort sort) { - int index; + guint key; char *old_text; + QuickFill *match_qf; if (qf == NULL) return; @@ -199,12 +221,16 @@ qfInsertTextRec( QuickFill *qf, const char *text, int depth, if ((text == NULL) || (text[depth] == '\0')) return; - index = CHAR_TO_INDEX(text[depth]); + key = toupper(text[depth]); - if( qf->qf[index] == NULL ) - qf->qf[index] = xaccMallocQuickFill(); + match_qf = g_hash_table_lookup (qf->matches, GUINT_TO_POINTER (key)); + if (match_qf == NULL) + { + match_qf = gnc_quickfill_new (); + g_hash_table_insert (qf->matches, GUINT_TO_POINTER (key), match_qf); + } - old_text = qf->qf[index]->text; + old_text = match_qf->text; switch(sort) { @@ -217,7 +243,7 @@ qfInsertTextRec( QuickFill *qf, const char *text, int depth, /* If there's no string there already, just put the new one in. */ if (old_text == NULL) { - qf->qf[index]->text = g_strdup (text); + match_qf->text = g_strdup (text); break; } @@ -227,11 +253,11 @@ qfInsertTextRec( QuickFill *qf, const char *text, int depth, break; g_free (old_text); - qf->qf[index]->text = g_strdup (text); + match_qf->text = g_strdup (text); break; } - qfInsertTextRec(qf->qf[index], text, ++depth, sort); + quickfill_insert_recursive (match_qf, text, ++depth, sort); } /********************** END OF FILE *********************************\ diff --git a/src/register/QuickFill.h b/src/register/QuickFill.h index 8e64c459299..84cc09c873a 100644 --- a/src/register/QuickFill.h +++ b/src/register/QuickFill.h @@ -28,6 +28,9 @@ #include "config.h" +#include + + /** STRUCTS *********************************************************/ /* The way quickfill works is this: the decscription field of a transaction @@ -47,29 +50,29 @@ * when the end of the descriptions string is reached. */ -#define QFNUM 257 /* 256 characters + 1 */ - typedef enum { QUICKFILL_LIFO, QUICKFILL_ALPHA } QuickFillSort; -typedef struct _quickfill { - char * text; /* the first matching text string */ - struct _quickfill *qf[QFNUM]; /* array of children in the tree */ -} QuickFill; +typedef struct _QuickFill QuickFill; /** PROTOTYPES ******************************************************/ -QuickFill *xaccMallocQuickFill( void ); -void xaccFreeQuickFill( QuickFill *qf ); -QuickFill *xaccGetQuickFill( QuickFill *qf, char c ); -QuickFill *xaccGetQuickFillStr( QuickFill *qf, const char *str ); -QuickFill *xaccGetQuickFillStrLen( QuickFill *qf, const char *str, int len ); -QuickFill *xaccGetQuickFillUniqueLen( QuickFill *qf, int *len ); -void xaccQFInsertText( QuickFill *qf, const char *text, QuickFillSort ); +QuickFill * gnc_quickfill_new (void); +void gnc_quickfill_destroy (QuickFill *qf); + +const char * gnc_quickfill_string (QuickFill *qf); + +QuickFill * gnc_quickfill_get_char_match (QuickFill *qf, char c); +QuickFill * gnc_quickfill_get_string_match (QuickFill *qf, const char *str); +QuickFill * gnc_quickfill_get_string_len_match (QuickFill *qf, + const char *str, int len); +QuickFill * gnc_quickfill_get_unique_len_match (QuickFill *qf, int *len); +void gnc_quickfill_insert (QuickFill *qf, const char *text, + QuickFillSort sort_code); #endif /* __QUICKFILL_H__ */ diff --git a/src/register/gnome/combocell-gnome.c b/src/register/gnome/combocell-gnome.c index 655393c8fb6..cd9a5b3e4fd 100644 --- a/src/register/gnome/combocell-gnome.c +++ b/src/register/gnome/combocell-gnome.c @@ -126,7 +126,7 @@ void xaccInitComboCell (ComboCell *cell) cell->cell.gui_private = box; - box->qf = xaccMallocQuickFill(); + box->qf = gnc_quickfill_new (); box->in_list_select = FALSE; box->strict = TRUE; @@ -319,7 +319,7 @@ void xaccDestroyComboCell (ComboCell *cell) g_list_free(box->menustrings); box->menustrings = NULL; - xaccFreeQuickFill(box->qf); + gnc_quickfill_destroy (box->qf); box->qf = NULL; g_free(box->ignore_string); @@ -355,8 +355,8 @@ xaccClearComboCellMenu (ComboCell * cell) g_list_free(box->menustrings); box->menustrings = NULL; - xaccFreeQuickFill(box->qf); - box->qf = xaccMallocQuickFill(); + gnc_quickfill_destroy (box->qf); + box->qf = gnc_quickfill_new (); if (box->item_list != NULL) { @@ -430,7 +430,7 @@ xaccAddComboCellMenuItem (ComboCell *cell, char * menustr) else box->list_in_sync = FALSE; - xaccQFInsertText(box->qf, menustr, QUICKFILL_ALPHA); + gnc_quickfill_insert (box->qf, menustr, QUICKFILL_ALPHA); box->list_sorted = FALSE; } @@ -456,6 +456,7 @@ ComboMV (BasicCell *_cell, { ComboCell *cell = (ComboCell *) _cell; PopBox *box = cell->cell.gui_private; + const char *match_str; const char *retval; QuickFill *match; gboolean pop_list; @@ -485,9 +486,11 @@ ComboMV (BasicCell *_cell, return newval; } - match = xaccGetQuickFillStr(box->qf, newval); + match = gnc_quickfill_get_string_match (box->qf, newval); - if ((match == NULL) || (match->text == NULL)) + match_str = gnc_quickfill_string (match); + + if ((match == NULL) || (match_str == NULL)) { xaccSetBasicCellValue (_cell, newval); @@ -498,7 +501,7 @@ ComboMV (BasicCell *_cell, return newval; } - retval = g_strdup(match->text); + retval = g_strdup(match_str); *start_selection = strlen(newval); *end_selection = -1; @@ -541,6 +544,7 @@ ComboDirect (BasicCell *bcell, gboolean keep_on_going = FALSE; gboolean extra_colon; QuickFill *match; + const char *match_str; char *search; int prefix_len; int new_pos; @@ -568,20 +572,21 @@ ComboDirect (BasicCell *bcell, !keep_on_going) return FALSE; - match = xaccGetQuickFillStrLen(box->qf, oldval, - *cursor_position); + match = gnc_quickfill_get_string_len_match (box->qf, oldval, *cursor_position); if (match == NULL) return TRUE; - match = xaccGetQuickFillUniqueLen(match, &prefix_len); + match = gnc_quickfill_get_unique_len_match (match, &prefix_len); if (match == NULL) return TRUE; - if ((match->text != NULL) && - (strncmp(match->text, oldval, length) == 0) && - (strcmp(match->text, oldval) != 0)) + match_str = gnc_quickfill_string (match); + + if ((match_str != NULL) && + (strncmp(match_str, oldval, length) == 0) && + (strcmp(match_str, oldval) != 0)) { - *newval_ptr = g_strdup(match->text); + *newval_ptr = g_strdup(match_str); assert(*newval_ptr != NULL); xaccSetBasicCellValue(bcell, *newval_ptr); @@ -637,24 +642,27 @@ ComboDirect (BasicCell *bcell, extra_colon = TRUE; } - match = xaccGetQuickFillStrLen(box->qf, oldval, new_pos); + match = gnc_quickfill_get_string_len_match (box->qf, oldval, new_pos); if (match == NULL) return FALSE; if (extra_colon) { - match = xaccGetQuickFill(match, box->complete_char); + match = gnc_quickfill_get_char_match (match, + box->complete_char); if (match == NULL) return FALSE; new_pos++; } - if ((match->text != NULL) && - (strncmp(match->text, oldval, length) == 0) && - (strcmp(match->text, oldval) != 0)) + match_str = gnc_quickfill_string (match); + + if ((match_str != NULL) && + (strncmp(match_str, oldval, length) == 0) && + (strcmp(match_str, oldval) != 0)) { - *newval_ptr = g_strdup(match->text); + *newval_ptr = g_strdup(match_str); assert(*newval_ptr != NULL); xaccSetBasicCellValue(bcell, *newval_ptr); diff --git a/src/register/gnome/quickfillcell-gnome.c b/src/register/gnome/quickfillcell-gnome.c index d90ddd60963..023d426fb6e 100644 --- a/src/register/gnome/quickfillcell-gnome.c +++ b/src/register/gnome/quickfillcell-gnome.c @@ -44,6 +44,7 @@ QuickFillDirect (BasicCell *bcell, { QuickFillCell *cell = (QuickFillCell *) bcell; GdkEventKey *event = gui_data; + const char *match_str; QuickFill *match; int prefix_len; @@ -71,19 +72,23 @@ QuickFillDirect (BasicCell *bcell, (*start_selection >= *cursor_position)) *cursor_position = *end_selection; - match = xaccGetQuickFillStrLen(cell->qfRoot, oldval, *cursor_position); + match = gnc_quickfill_get_string_len_match (cell->qfRoot, oldval, + *cursor_position); + if (match == NULL) return TRUE; - match = xaccGetQuickFillUniqueLen(match, &prefix_len); + match = gnc_quickfill_get_unique_len_match (match, &prefix_len); if (match == NULL) return TRUE; - if ((match->text != NULL) && - (strncmp(match->text, oldval, strlen(oldval)) == 0) && - (strcmp(match->text, oldval) != 0)) + match_str = gnc_quickfill_string (match); + + if ((match_str != NULL) && + (strncmp(match_str, oldval, strlen(oldval)) == 0) && + (strcmp(match_str, oldval) != 0)) { - *newval_ptr = g_strdup(match->text); + *newval_ptr = g_strdup(match_str); assert(*newval_ptr != NULL); xaccSetBasicCellValue(bcell, *newval_ptr); } diff --git a/src/register/quickfillcell.c b/src/register/quickfillcell.c index 7f239922550..b7fa055fe56 100644 --- a/src/register/quickfillcell.c +++ b/src/register/quickfillcell.c @@ -90,6 +90,7 @@ quick_modify (BasicCell *_cell, int *end_selection) { QuickFillCell *cell = (QuickFillCell *) _cell; + const char *match_str; const char *retval; QuickFill *match; @@ -133,9 +134,11 @@ quick_modify (BasicCell *_cell, cell->original = NULL; } - match = xaccGetQuickFillStr(cell->qfRoot, newval); + match = gnc_quickfill_get_string_match (cell->qfRoot, newval); - if ((match == NULL) || (match->text == NULL)) + match_str = gnc_quickfill_string (match); + + if ((match == NULL) || (match_str == NULL)) { if (cell->original != NULL) retval = g_strdup(cell->original); @@ -148,7 +151,7 @@ quick_modify (BasicCell *_cell, return retval; } - retval = g_strdup(match->text); + retval = g_strdup(match_str); *start_selection = strlen(newval); *end_selection = -1; @@ -167,7 +170,8 @@ quick_leave (BasicCell *_cell, const char *val) QuickFillCell *cell = (QuickFillCell *) _cell; cell->qf = cell->qfRoot; - xaccQFInsertText (cell->qfRoot, val, cell->sort); + gnc_quickfill_insert (cell->qfRoot, val, cell->sort); + return val; } @@ -192,7 +196,7 @@ xaccInitQuickFillCell (QuickFillCell *cell) { xaccInitBasicCell (&(cell->cell)); - cell->qfRoot = xaccMallocQuickFill(); + cell->qfRoot = gnc_quickfill_new (); cell->qf = cell->qfRoot; cell->sort = QUICKFILL_LIFO; cell->original = NULL; @@ -210,7 +214,7 @@ xaccInitQuickFillCell (QuickFillCell *cell) void xaccDestroyQuickFillCell (QuickFillCell *cell) { - xaccFreeQuickFill (cell->qfRoot); + gnc_quickfill_destroy (cell->qfRoot); cell->qfRoot = NULL; cell->qf = NULL; @@ -230,7 +234,7 @@ xaccDestroyQuickFillCell (QuickFillCell *cell) void xaccSetQuickFillCellValue (QuickFillCell *cell, const char * value) { - xaccQFInsertText (cell->qfRoot, value, cell->sort); + gnc_quickfill_insert (cell->qfRoot, value, cell->sort); SET (&(cell->cell), value); } diff --git a/src/register/quickfillcell.h b/src/register/quickfillcell.h index 51339182976..461b73058a9 100644 --- a/src/register/quickfillcell.h +++ b/src/register/quickfillcell.h @@ -62,15 +62,18 @@ typedef struct _QuickFillCell } QuickFillCell; QuickFillCell * xaccMallocQuickFillCell (void); -void xaccInitQuickFillCell (QuickFillCell *); -void xaccDestroyQuickFillCell (QuickFillCell *); +void xaccInitQuickFillCell (QuickFillCell *cell); +void xaccDestroyQuickFillCell (QuickFillCell *cell); -void xaccSetQuickFillCellValue (QuickFillCell *, const char *); -void xaccSetQuickFillSort (QuickFillCell *, QuickFillSort); -void xaccSetQuickFillOriginal (QuickFillCell *, const char *); +void xaccSetQuickFillCellValue (QuickFillCell *cell, + const char *value); +void xaccSetQuickFillSort (QuickFillCell *cell, + QuickFillSort sort); +void xaccSetQuickFillOriginal (QuickFillCell *cell, + const char *original); /* GUI-dependent */ -void xaccQuickFillGUIInit (QuickFillCell *); +void xaccQuickFillGUIInit (QuickFillCell *cell); #endif /* __QUICK_FILL_CELL_C__ */