/* * cellspan.c: Keep track of the columns on which a cell * displays information. * * Author: * Miguel de Icaza (miguel@gnu.org) * * The information on cell spanning is attached in the row ColRowInfo * structures. The actual representation of this information is * opaque to the code that uses it (the idea is: this first * implementation is not really awesome). * * The reason we need this is that the Grid draw code expects to find * the "owner" of the cell to be able to repaint its contents. * */ #include #include #include "gnumeric.h" #include "gnumeric-sheet.h" #include "eval.h" #include "format.h" static guint col_hash (gconstpointer key) { const int *col = key; return *col; } static gint col_compare (gconstpointer a, gconstpointer b) { const int *col_a = a; const int *col_b = b; if (*col_a == *col_b) return 1; return 0; } /* * Initializes the hash table in the RowInfo for keeping track * of cell spans (ie, which cells on the spreadsheet are displayed * by which cell). */ void row_init_span (ColRowInfo *ri) { g_return_if_fail (ri != NULL); ri->data = g_hash_table_new (col_hash, col_compare); } static void free_hash_key (gpointer key, gpointer value, gpointer user_data) { g_free (key); } void row_destroy_span (ColRowInfo *ri) { g_return_if_fail (ri != NULL); g_hash_table_foreach (ri->data, free_hash_key, NULL); g_hash_table_destroy (ri->data); } /* * sheet_cell_register_span * @cell: The cell to register the span * @left: the leftmost column used by the cell * @right: the rightmost column used by the cell * * Registers the region */ void cell_register_span (Cell *cell, int left, int right) { ColRowInfo *ri; int col, i; g_return_if_fail (cell != NULL); g_return_if_fail (left <= right); ri = cell->row; col = cell->col->pos; for (i = left; i <= right; i++){ int *key; /* Do not register our column, as we already keep this on the main hash */ if (i == col) continue; key = g_new (int, 1); *key = i; g_hash_table_insert (ri->data, key, cell); } } typedef struct { Cell *cell; GList *list_of_keys; } unregister_closure_t; static void assemble_unregister_span_list (gpointer key, gpointer value, gpointer user_data) { unregister_closure_t *c = user_data; if (c->cell == value) c->list_of_keys = g_list_prepend (c->list_of_keys, key); } /* * sheet_cell_unregister_span * @cell: The cell to remove from the span information * * Remove all of the references to this cell on the span hash * table */ void cell_unregister_span (Cell *cell) { unregister_closure_t c; GList *l; g_return_if_fail (cell != NULL); c.cell = cell; c.list_of_keys = NULL; if (cell->row->data) g_hash_table_foreach (cell->row->data, assemble_unregister_span_list, &c); for (l = c.list_of_keys; l; l = l->next){ int *key = l->data; g_hash_table_remove (cell->row->data, key); g_free (key); } g_list_free (c.list_of_keys); } /* * row_cell_get_displayed_at * @ri: The ColRowInfo for the row we are looking up * @col: the column position * * Returns the Cell* which happens to display at the column */ Cell * row_cell_get_displayed_at (ColRowInfo *ri, int col) { g_return_val_if_fail (ri != NULL, NULL); if (ri->data) return g_hash_table_lookup (ri->data, &col); else return NULL; }