[gnumeric] Code cleanups.



commit 74ede8cf22301d9d43a7e9343833b6708bab5b9f
Author: Morten Welinder <terra gnome org>
Date:   Thu Apr 26 12:37:49 2018 -0400

    Code cleanups.

 ChangeLog                            |   10 ++
 plugins/html/latex.c                 |    4 +-
 plugins/sylk/sylk-write.c            |   10 +-
 src/cell.c                           |    2 +-
 src/clipboard.c                      |    7 +-
 src/colrow.c                         |   95 ++-----------
 src/colrow.h                         |   14 --
 src/commands.c                       |   32 ++---
 src/dialogs/dialog-cell-format.c     |    6 +-
 src/dialogs/dialog-function-select.c |    3 +-
 src/graph.c                          |   44 ++++---
 src/sheet-filter.c                   |   18 ++--
 src/sheet.c                          |  261 ++++++++++++++++++++++++----------
 src/sheet.h                          |   19 +++-
 src/stf.c                            |    7 +-
 src/tools/dao.c                      |   12 +-
 src/tools/filter.c                   |    2 +-
 src/tools/scenarios.c                |    4 +-
 src/undo.c                           |    2 +-
 src/wbc-gtk-actions.c                |    5 +-
 src/widgets/gnm-filter-combo-view.c  |   11 +-
 src/workbook-cmd-format.c            |    4 +-
 src/workbook.c                       |    6 +-
 src/workbook.h                       |    2 +-
 src/xml-sax-read.c                   |    2 +-
 src/xml-sax-write.c                  |   12 +-
 26 files changed, 317 insertions(+), 277 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 993aeed..b554fc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2018-04-26  Morten Welinder  <terra gnome org>
+
+       * src/colrow.c (col_row_collection_foreach): move to...
+       * src/sheet.c (sheet_colrow_foreach): ...here.  Allow -1 to mean
+       last column or row.
+       (sheet_foreach_cell_in_range): Change to take a range.
+       (sheet_foreach_cell_in_region): Preserve the old
+       sheet_foreach_cell_in_range api.  Most callers changed.  Allow -1
+       to mean last column or row.
+
 2018-04-25  Morten Welinder  <terra gnome org>
 
        * src/xml-sax-read.c (xml_sax_cell_content): Read shared array
diff --git a/plugins/html/latex.c b/plugins/html/latex.c
index 8c0a8a2..0afc47b 100644
--- a/plugins/html/latex.c
+++ b/plugins/html/latex.c
@@ -456,9 +456,7 @@ latex2e_write_font_encodings (GsfOutput *output, Sheet *sheet, GnmRange const *r
        gboolean *fonts = g_new0 (gboolean, G_UNICODE_SCRIPT_MANDAIC + 1);
 
        sheet_foreach_cell_in_range
-               (sheet, CELL_ITER_IGNORE_BLANK | CELL_ITER_IGNORE_HIDDEN,
-                range->start.col, range->start.row,
-                range->end.col, range->end.row,
+               (sheet, CELL_ITER_IGNORE_BLANK | CELL_ITER_IGNORE_HIDDEN, range,
                 (CellIterFunc)&cb_find_font_encodings, fonts);
 
        if (fonts[G_UNICODE_SCRIPT_CYRILLIC])
diff --git a/plugins/sylk/sylk-write.c b/plugins/sylk/sylk-write.c
index 3080335..5448ea9 100644
--- a/plugins/sylk/sylk-write.c
+++ b/plugins/sylk/sylk-write.c
@@ -312,9 +312,7 @@ sylk_write_sheet (SylkWriter *state)
 
        // Cell styles
        state->cur_row = -1;
-       sheet_foreach_cell_in_range (sheet, 0,
-               extent.start.col, extent.start.row,
-               extent.end.col,   extent.end.row,
+       sheet_foreach_cell_in_range (sheet, 0, &extent,
                (CellIterFunc) cb_sylk_write_cell_style, state);
 
        // Column widths
@@ -363,10 +361,8 @@ sylk_write_sheet (SylkWriter *state)
 
 /* dump content */
        state->cur_row = -1;
-       sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK,
-               extent.start.col, extent.start.row,
-               extent.end.col,   extent.end.row,
-               (CellIterFunc) cb_sylk_write_cell, state);
+       sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK, &extent,
+                                    (CellIterFunc) cb_sylk_write_cell, state);
 
        g_free (col_defs);
 }
diff --git a/src/cell.c b/src/cell.c
index fc96324..9fd53de 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -1079,7 +1079,7 @@ gnm_cell_convert_expr_to_value (GnmCell *cell)
 
                gnm_expr_top_get_array_size (texpr, &cols, &rows);
 
-               sheet_foreach_cell_in_range (cell->base.sheet, CELL_ITER_ALL,
+               sheet_foreach_cell_in_region (cell->base.sheet, CELL_ITER_ALL,
                                             cell->pos.col, cell->pos.row,
                                             cell->pos.col + cols - 1,
                                             cell->pos.row + rows - 1,
diff --git a/src/clipboard.c b/src/clipboard.c
index 97c44f6..26da5b5 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -738,10 +738,9 @@ clipboard_copy_range (Sheet *sheet, GnmRange const *r)
        cr->row_state = colrow_get_states (sheet,
                FALSE, r->start.row, r->end.row);
 
-       sheet_foreach_cell_in_range ( sheet, CELL_ITER_IGNORE_NONEXISTENT,
-               r->start.col, r->start.row,
-               r->end.col, r->end.row,
-               (CellIterFunc) cb_clipboard_prepend_cell, cr);
+       sheet_foreach_cell_in_range ( sheet, CELL_ITER_IGNORE_NONEXISTENT, r,
+                                     (CellIterFunc) cb_clipboard_prepend_cell,
+                                     cr);
        objects = sheet_objects_get (sheet, r, G_TYPE_NONE);
        g_slist_foreach (objects, (GFunc)cb_dup_objects, cr);
        g_slist_free (objects);
diff --git a/src/colrow.c b/src/colrow.c
index f4e5d8d..080ec37 100644
--- a/src/colrow.c
+++ b/src/colrow.c
@@ -183,52 +183,6 @@ colrow_free (ColRowInfo *cri)
        g_slice_free1 (sizeof (*cri), cri);
 }
 
-/**
- * col_row_collection_foreach:
- * @infos:     The Row or Column collection.
- * @first:     start position (inclusive)
- * @last:      stop column (inclusive)
- * @callback: (scope call): A callback function which should return %TRUE to stop
- *              the iteration.
- * @user_data: A baggage pointer.
- *
- * Iterates through the existing rows or columns within the range supplied.
- * Currently only support left -> right iteration.  If a callback returns
- * %TRUE iteration stops.
- **/
-gboolean
-col_row_collection_foreach (ColRowCollection const *infos, int first, int last,
-                           ColRowHandler callback, gpointer user_data)
-{
-       GnmColRowIter iter;
-       ColRowSegment const *segment;
-       int sub, inner_last, i;
-
-       /* TODO : Do we need to support right -> left as an option */
-
-       /* clip */
-       if (last > infos->max_used)
-               last = infos->max_used;
-
-       for (i = first; i <= last ; ) {
-               segment = COLROW_GET_SEGMENT (infos, i);
-               sub = COLROW_SUB_INDEX(i);
-               inner_last = (COLROW_SEGMENT_INDEX (last) == COLROW_SEGMENT_INDEX (i))
-                       ? COLROW_SUB_INDEX (last)+1 : COLROW_SEGMENT_SIZE;
-               iter.pos = i;
-               i += COLROW_SEGMENT_SIZE - sub;
-               if (segment == NULL)
-                       continue;
-
-               for (; sub < inner_last; sub++, iter.pos++) {
-                       iter.cri = segment->info[sub];
-                       if (iter.cri != NULL && (*callback)(&iter, user_data))
-                               return TRUE;
-               }
-       }
-       return FALSE;
-}
-
 
 /**
  * colrow_state_list_foreach:
@@ -637,19 +591,19 @@ colrow_set_sizes (Sheet *sheet, gboolean is_cols,
                        if (is_cols) {
                                rles->state.size_pts = sheet_col_get_default_size_pts (sheet);
                                sheet_col_set_default_size_pixels (sheet, new_size);
-                               col_row_collection_foreach (&sheet->cols, 0, gnm_sheet_get_last_col (sheet),
+                               sheet_colrow_foreach (sheet, TRUE, 0, -1,
                                        &cb_set_colrow_size, &closure);
                        } else {
                                rles->state.size_pts = sheet_row_get_default_size_pts (sheet);
                                sheet_row_set_default_size_pixels (sheet, new_size);
-                               col_row_collection_foreach (&sheet->rows, 0, gnm_sheet_get_last_row (sheet),
+                               sheet_colrow_foreach (sheet, FALSE, 0, -1,
                                        &cb_set_colrow_size, &closure);
                        }
 
                        /* force a re-render of cells with expanding formats */
                        if (is_cols)
-                               sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK,
-                                       0, 0, gnm_sheet_get_last_col (sheet), gnm_sheet_get_last_row (sheet),
+                               sheet_foreach_cell_in_region (sheet, CELL_ITER_IGNORE_BLANK,
+                                                             0, 0, -1, -1,
                                        (CellIterFunc) &cb_clear_variable_width_content, NULL);
 
                        /* Result is a magic 'default' record + >= 1 normal */
@@ -658,8 +612,8 @@ colrow_set_sizes (Sheet *sheet, gboolean is_cols,
 
                if (is_cols) {
                        /* force a re-render of cells with expanding formats */
-                       sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK,
-                               index->first, 0, index->last, gnm_sheet_get_last_row (sheet),
+                       sheet_foreach_cell_in_region (sheet, CELL_ITER_IGNORE_BLANK,
+                               index->first, 0, index->last, -1,
                                (CellIterFunc) &cb_clear_variable_width_content, NULL);
 
                        /* In order to properly reposition cell comments in
@@ -818,8 +772,8 @@ colrow_restore_state_group (Sheet *sheet, gboolean is_cols,
                colrow_set_states (sheet, is_cols, index->first, ptr->data);
                /* force a re-render of cells with expanding formats */
                if (is_cols)
-                       sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK,
-                               index->first, 0, index->last, gnm_sheet_get_last_row (sheet),
+                       sheet_foreach_cell_in_region (sheet, CELL_ITER_IGNORE_BLANK,
+                               index->first, 0, index->last, -1,
                                (CellIterFunc) &cb_clear_variable_width_content, NULL);
                selection = selection->prev;
        }
@@ -936,7 +890,6 @@ colrow_autofit (Sheet *sheet, const GnmRange *range, gboolean is_cols,
 {
        struct cb_autofit data;
        int a, b;
-       ColRowCollection *crs;
        ColRowHandler handler;
 
        data.sheet = sheet;
@@ -948,12 +901,10 @@ colrow_autofit (Sheet *sheet, const GnmRange *range, gboolean is_cols,
        if (is_cols) {
                a = range->start.col;
                b = range->end.col;
-               crs = &sheet->cols;
                handler = cb_autofit_col;
        } else {
                a = range->start.row;
                b = range->end.row;
-               crs = &sheet->rows;
                handler = cb_autofit_row;
        }
 
@@ -966,7 +917,7 @@ colrow_autofit (Sheet *sheet, const GnmRange *range, gboolean is_cols,
           stuff that caches sub-computations see the whole thing instead
           of clearing between cells.  */
        gnm_app_recalc_start ();
-       col_row_collection_foreach (crs, a, b, handler, &data);
+       sheet_colrow_foreach (sheet, is_cols, a, b, handler, &data);
        gnm_app_recalc_finish ();
 }
 
@@ -980,11 +931,11 @@ colrow_autofit_col (Sheet *sheet, GnmRange *r)
 {
        colrow_autofit (sheet, r, TRUE, TRUE,
                        TRUE, FALSE, NULL, NULL);
-       sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK,
-                                    r->start.col, 0,
-                                    r->end.col, gnm_sheet_get_last_row (sheet),
-                                    (CellIterFunc) &cb_clear_variable_width_content,
-                                    NULL);
+       sheet_foreach_cell_in_region (sheet, CELL_ITER_IGNORE_BLANK,
+                                     r->start.col, 0,
+                                     r->end.col, -1,
+                                     (CellIterFunc) &cb_clear_variable_width_content,
+                                     NULL);
 }
 
 /**
@@ -1375,21 +1326,3 @@ colrow_get_global_outline (Sheet const *sheet, gboolean is_cols, int depth,
        *show = g_slist_reverse (*show);
        *hide = g_slist_reverse (*hide);
 }
-
-void
-col_row_collection_resize (ColRowCollection *infos, int size)
-{
-       int end_idx = COLROW_SEGMENT_INDEX (size);
-       int i = infos->info->len - 1;
-
-       while (i >= end_idx) {
-               ColRowSegment *segment = g_ptr_array_index (infos->info, i);
-               if (segment) {
-                       g_free (segment);
-                       g_ptr_array_index (infos->info, i) = NULL;
-               }
-               i--;
-       }
-
-       g_ptr_array_set_size (infos->info, end_idx);
-}
diff --git a/src/colrow.h b/src/colrow.h
index 126744a..78f55e8 100644
--- a/src/colrow.h
+++ b/src/colrow.h
@@ -26,13 +26,6 @@ struct _ColRowInfo {
 };
 GType col_row_info_get_type (void);
 
-struct _ColRowCollection {
-       int         max_used;
-       ColRowInfo  default_style;
-       GPtrArray * info;
-       int         max_outline_level;
-};
-
 /* We never did get around to support 'thick' borders so these are effectively
  * unitless (margins do not scale) constants . */
 #define        GNM_COL_MARGIN  2
@@ -88,13 +81,6 @@ typedef struct {
 } GnmColRowIter;
 
 typedef gboolean (*ColRowHandler)(GnmColRowIter const *iter, gpointer user_data);
-gboolean col_row_collection_foreach       (ColRowCollection const *infos,
-                                           int first, int last,
-                                           ColRowHandler callback,
-                                           gpointer user_data);
-
-void col_row_collection_resize (ColRowCollection *infos, int size);
-
 #define colrow_index_list_destroy(l) g_list_free_full ((l), g_free)
 
 GString         *colrow_index_list_to_string (ColRowIndexList *list,
diff --git a/src/commands.c b/src/commands.c
index b289cd2..c11f30c 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -863,9 +863,7 @@ cmd_set_text_full (WorkbookControl *wbc, GSList *selection, GnmEvalPos *ep,
                        GnmRange *r = l->data;
                        GnmValue *val =
                                sheet_foreach_cell_in_range
-                               (sheet, CELL_ITER_ALL,
-                                r->start.col, r->start.row,
-                                r->end.col, r->end.row,
+                               (sheet, CELL_ITER_ALL, r,
                                 (CellIterFunc) cmd_set_text_full_check_texpr,
                                 (gpointer) texpr);
 
@@ -934,9 +932,7 @@ cmd_set_text_full (WorkbookControl *wbc, GSList *selection, GnmEvalPos *ep,
                        GnmRange *r = l->data;
                        GnmValue *val =
                                sheet_foreach_cell_in_range
-                               (sheet, CELL_ITER_ALL,
-                                r->start.col, r->start.row,
-                                r->end.col, r->end.row,
+                               (sheet, CELL_ITER_ALL, r,
                                 (CellIterFunc) cmd_set_text_full_check_text,
                                 (gpointer) corrected);
 
@@ -957,9 +953,7 @@ cmd_set_text_full (WorkbookControl *wbc, GSList *selection, GnmEvalPos *ep,
                                GnmRange *r = l->data;
                                GnmValue *val =
                                        sheet_foreach_cell_in_range
-                                       (sheet, CELL_ITER_IGNORE_BLANK,
-                                        r->start.col, r->start.row,
-                                        r->end.col, r->end.row,
+                                       (sheet, CELL_ITER_IGNORE_BLANK, r,
                                         (CellIterFunc) cmd_set_text_full_check_markup,
                                         (gpointer) markup);
 
@@ -1582,8 +1576,11 @@ cmd_selection_clear (WorkbookControl *wbc, int clear_flags)
                        filter = gnm_sheet_filter_intersect_rows
                                (sheet, data.r->start.row, data.r->end.row);
                        if (filter) {
-                               col_row_collection_foreach (&sheet->rows, data.r->start.row, data.r->end.row,
-                                               (ColRowHandler) cmd_selection_clear_row_handler, &data);
+                               sheet_colrow_foreach (sheet, FALSE,
+                                                     data.r->start.row,
+                                                     data.r->end.row,
+                                                     (ColRowHandler) cmd_selection_clear_row_handler,
+                                                     &data);
                                g_free (ranges->data);
                                ranges->data = NULL;
                        }
@@ -1990,11 +1987,10 @@ cmd_selection_format_toggle_font_style (WorkbookControl *wbc,
                        csftfs closure;
                        closure.undo = NULL;
                        closure.pt = pt;
-                       sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK,
-                                                    sr->range.start.col, sr->range.start.row,
-                                                    sr->range.end.col, sr->range.end.row,
-                                                    (CellIterFunc) cmd_selection_format_toggle_font_style_cb,
-                                                    &closure);
+                       sheet_foreach_cell_in_range
+                               (sheet, CELL_ITER_IGNORE_BLANK, &sr->range,
+                                (CellIterFunc) cmd_selection_format_toggle_font_style_cb,
+                                &closure);
                        redo = go_undo_combine (redo, closure.undo);
                }
        }
@@ -7157,9 +7153,7 @@ cmd_hyperlink_redo (GnmCommand *cmd, WorkbookControl *wbc)
                }
 
                if (me->opt_content) {
-                       sheet_foreach_cell_in_range (sheet, CELL_ITER_ALL,
-                                                    r->start.col, r->start.row,
-                                                    r->end.col, r->end.row,
+                       sheet_foreach_cell_in_range (sheet, CELL_ITER_ALL, r,
                                                     cb_hyperlink_set_text,
                                                     me);
                }
diff --git a/src/dialogs/dialog-cell-format.c b/src/dialogs/dialog-cell-format.c
index 4490732..5663d0a 100644
--- a/src/dialogs/dialog-cell-format.c
+++ b/src/dialogs/dialog-cell-format.c
@@ -2542,9 +2542,9 @@ fmt_dialog_selection_type (SheetView *sv,
 
        if ((state->conflicts & MSTYLE_FORMAT) == 0 &&
            go_format_is_general (gnm_style_get_format (state->style))) {
-               sheet_foreach_cell_in_range (state->sheet, CELL_ITER_IGNORE_BLANK,
-                                            r.start.col, r.start.row,
-                                            r.end.col,   r.end.row,
+               sheet_foreach_cell_in_range (state->sheet,
+                                            CELL_ITER_IGNORE_BLANK,
+                                            &r,
                                             cb_check_cell_format,
                                             state);
        }
diff --git a/src/dialogs/dialog-function-select.c b/src/dialogs/dialog-function-select.c
index 8d90816..3328fbc 100644
--- a/src/dialogs/dialog-function-select.c
+++ b/src/dialogs/dialog-function-select.c
@@ -703,8 +703,7 @@ make_expr_example (Sheet *sheet, const char *text,
        }
 
        g_free (tmp_text);
-       if (fmt)
-               go_format_unref (fmt);
+       go_format_unref (fmt);
 
        return res;
 }
diff --git a/src/graph.c b/src/graph.c
index 17fa654..0356999 100644
--- a/src/graph.c
+++ b/src/graph.c
@@ -724,9 +724,10 @@ gnm_go_data_vector_load_values (GODataVector *dat)
                                                                (CellIterFunc)cb_assign_val,
                                                                &closure);
                        else
-                               sheet_foreach_cell_in_range (start_sheet, CELL_ITER_IGNORE_FILTERED,
-                                       r.start.col, r.start.row, r.end.col, r.end.row,
-                                       (CellIterFunc)cb_assign_val, &closure);
+                               sheet_foreach_cell_in_range
+                                       (start_sheet, CELL_ITER_IGNORE_FILTERED,
+                                        &r,
+                                        (CellIterFunc)cb_assign_val, &closure);
                        dat->len = closure.last + 1; /* clip */
                        minimum = closure.minimum;
                        maximum = closure.maximum;
@@ -774,9 +775,10 @@ gnm_go_data_vector_load_values (GODataVector *dat)
                                                                                (CellIterFunc)cb_assign_val,
                                                                                &closure);
                                        else
-                                               sheet_foreach_cell_in_range (start_sheet, 
CELL_ITER_IGNORE_FILTERED,
-                                                       r.start.col, r.start.row, r.end.col, r.end.row,
-                                                       (CellIterFunc)cb_assign_val, &closure);
+                                               sheet_foreach_cell_in_range (start_sheet,
+                                                                            CELL_ITER_IGNORE_FILTERED,
+                                                                            &r,
+                                                                            (CellIterFunc)cb_assign_val, 
&closure);
                                        last = dat->len = closure.last + 1; /* clip */
                                        if (minimum > closure.minimum)
                                            minimum = closure.minimum;
@@ -937,9 +939,10 @@ gnm_go_data_vector_get_str (GODataVector *dat, unsigned i)
                                                r.end.col = start_sheet->cols.max_used;
 
                                        if (r.start.col <= r.end.col && r.start.row <= r.end.row)
-                                               sheet_foreach_cell_in_range (start_sheet, 
CELL_ITER_IGNORE_FILTERED,
-                                                       r.start.col, r.start.row, r.end.col, r.end.row,
-                                                       (CellIterFunc)cb_assign_string, &closure);
+                                               sheet_foreach_cell_in_range (start_sheet,
+                                                                            CELL_ITER_IGNORE_FILTERED,
+                                                                            &r,
+                                                                            (CellIterFunc)cb_assign_string, 
&closure);
                                }
                        }
                }
@@ -966,9 +969,10 @@ gnm_go_data_vector_get_str (GODataVector *dat, unsigned i)
                                r.end.col = start_sheet->cols.max_used;
 
                        if (r.start.col <= r.end.col && r.start.row <= r.end.row)
-                               sheet_foreach_cell_in_range (start_sheet, CELL_ITER_IGNORE_FILTERED,
-                                       r.start.col, r.start.row, r.end.col, r.end.row,
-                                       (CellIterFunc)cb_assign_string, &closure);
+                               sheet_foreach_cell_in_range (start_sheet,
+                                                            CELL_ITER_IGNORE_FILTERED,
+                                                            &r,
+                                                            (CellIterFunc)cb_assign_string, &closure);
                }
                if (vec->strs && vec->strs->len > i)
                        ret = g_ptr_array_index (vec->strs, i);
@@ -1038,9 +1042,10 @@ gnm_go_data_vector_get_markup (GODataVector *dat, unsigned i)
 
                        /* In case the sheet is empty */
                        if (r.start.col <= r.end.col && r.start.row <= r.end.row) {
-                               sheet_foreach_cell_in_range (start_sheet, CELL_ITER_ALL,
-                                       r.start.col, r.start.row, r.end.col, r.end.row,
-                                       (CellIterFunc)cb_assign_markup, vec->markup);
+                               sheet_foreach_cell_in_range (start_sheet,
+                                                            CELL_ITER_ALL,
+                                                            &r,
+                                                            (CellIterFunc)cb_assign_markup, vec->markup);
                        }
                        break;
 
@@ -1064,9 +1069,10 @@ gnm_go_data_vector_get_markup (GODataVector *dat, unsigned i)
                                                r.end.col = start_sheet->cols.max_used;
 
                                        if (r.start.col <= r.end.col && r.start.row <= r.end.row)
-                                               sheet_foreach_cell_in_range (start_sheet, CELL_ITER_ALL,
-                                                       r.start.col, r.start.row, r.end.col, r.end.row,
-                                                       (CellIterFunc)cb_assign_markup, vec->markup);
+                                               sheet_foreach_cell_in_range (start_sheet,
+                                                                            CELL_ITER_ALL,
+                                                                            &r,
+                                                                            (CellIterFunc)cb_assign_markup, 
vec->markup);
                                }
                        }
                        break;
@@ -1333,7 +1339,7 @@ gnm_go_data_matrix_load_values (GODataMatrix *dat)
                        closure.first_col = closure.last_col = -1;
                        closure.row = closure.col = 0;
                        closure.columns = dat->size.columns;
-                       sheet_foreach_cell_in_range (start_sheet, CELL_ITER_ALL,
+                       sheet_foreach_cell_in_region (start_sheet, CELL_ITER_ALL,
                                r.start.col, r.start.row,
                                r.start.col + dat->size.columns - 1,
                                r.start.row + dat->size.rows - 1,
diff --git a/src/sheet-filter.c b/src/sheet-filter.c
index efb2f6b..2b5aaa7 100644
--- a/src/sheet-filter.c
+++ b/src/sheet-filter.c
@@ -483,7 +483,7 @@ gnm_filter_combo_apply (GnmFilterCombo *fcombo, Sheet *target_sheet)
                if (cond->op[1] != GNM_FILTER_UNUSED)
                        filter_expr_init (&data, 1, cond, filter);
 
-               sheet_foreach_cell_in_range (filter->sheet,
+               sheet_foreach_cell_in_region (filter->sheet,
                        iter_flags,
                        col, start_row, col, end_row,
                        (CellIterFunc) cb_filter_expr, &data);
@@ -492,12 +492,12 @@ gnm_filter_combo_apply (GnmFilterCombo *fcombo, Sheet *target_sheet)
                if (cond->op[1] != GNM_FILTER_UNUSED)
                        filter_expr_release (&data, 1);
        } else if (cond->op[0] == GNM_FILTER_OP_BLANKS)
-               sheet_foreach_cell_in_range (filter->sheet,
+               sheet_foreach_cell_in_region (filter->sheet,
                        CELL_ITER_IGNORE_HIDDEN,
                        col, start_row, col, end_row,
                        (CellIterFunc) cb_filter_blanks, target_sheet);
        else if (cond->op[0] == GNM_FILTER_OP_NON_BLANKS)
-               sheet_foreach_cell_in_range (filter->sheet,
+               sheet_foreach_cell_in_region (filter->sheet,
                        CELL_ITER_IGNORE_HIDDEN,
                        col, start_row, col, end_row,
                        (CellIterFunc) cb_filter_non_blanks, target_sheet);
@@ -511,12 +511,12 @@ gnm_filter_combo_apply (GnmFilterCombo *fcombo, Sheet *target_sheet)
                                if (data.count < 1)
                                        data.count = 1;
                                data.vals   = g_new (GnmValue const *, data.count);
-                               sheet_foreach_cell_in_range (filter->sheet,
+                               sheet_foreach_cell_in_region (filter->sheet,
                                                             CELL_ITER_IGNORE_HIDDEN | CELL_ITER_IGNORE_BLANK,
                                                             col, start_row, col, end_row,
                                                             (CellIterFunc) cb_filter_find_items, &data);
                                data.target_sheet = target_sheet;
-                               sheet_foreach_cell_in_range (filter->sheet,
+                               sheet_foreach_cell_in_region (filter->sheet,
                                                             CELL_ITER_IGNORE_HIDDEN,
                                                             col, start_row, col, end_row,
                                                             (CellIterFunc) cb_hide_unwanted_items, &data);
@@ -527,7 +527,7 @@ gnm_filter_combo_apply (GnmFilterCombo *fcombo, Sheet *target_sheet)
 
                                data.find_max = (cond->op[0] & 0x1) ? FALSE : TRUE;
                                data.initialized = FALSE;
-                               sheet_foreach_cell_in_range (filter->sheet,
+                               sheet_foreach_cell_in_region (filter->sheet,
                                                             CELL_ITER_IGNORE_HIDDEN | CELL_ITER_IGNORE_BLANK,
                                                             col, start_row, col, end_row,
                                                             (CellIterFunc) cb_filter_find_percentage, &data);
@@ -535,7 +535,7 @@ gnm_filter_combo_apply (GnmFilterCombo *fcombo, Sheet *target_sheet)
                                data.high -= offset;
                                data.low  += offset;
                                data.target_sheet = target_sheet;
-                               sheet_foreach_cell_in_range (filter->sheet,
+                               sheet_foreach_cell_in_region (filter->sheet,
                                                             CELL_ITER_IGNORE_HIDDEN,
                                                             col, start_row, col, end_row,
                                                             (CellIterFunc) cb_hide_unwanted_percentage, 
&data);
@@ -547,12 +547,12 @@ gnm_filter_combo_apply (GnmFilterCombo *fcombo, Sheet *target_sheet)
                        data.count  = cond->count;
                        data.vals   = g_new (GnmValue const *, data.count);
 
-                       sheet_foreach_cell_in_range (filter->sheet,
+                       sheet_foreach_cell_in_region (filter->sheet,
                                CELL_ITER_IGNORE_HIDDEN | CELL_ITER_IGNORE_BLANK,
                                col, start_row, col, end_row,
                                (CellIterFunc) cb_filter_find_items, &data);
                        data.target_sheet = target_sheet;
-                       sheet_foreach_cell_in_range (filter->sheet,
+                       sheet_foreach_cell_in_region (filter->sheet,
                                CELL_ITER_IGNORE_HIDDEN,
                                col, start_row, col, end_row,
                                (CellIterFunc) cb_hide_unwanted_items, &data);
diff --git a/src/sheet.c b/src/sheet.c
index 410ede7..9f53d80 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -156,6 +156,24 @@ static void gnm_sheet_finalize (GObject *obj);
 static GObjectClass *parent_class;
 
 static void
+col_row_collection_resize (ColRowCollection *infos, int size)
+{
+       int end_idx = COLROW_SEGMENT_INDEX (size);
+       int i = infos->info->len - 1;
+
+       while (i >= end_idx) {
+               ColRowSegment *segment = g_ptr_array_index (infos->info, i);
+               if (segment) {
+                       g_free (segment);
+                       g_ptr_array_index (infos->info, i) = NULL;
+               }
+               i--;
+       }
+
+       g_ptr_array_set_size (infos->info, end_idx);
+}
+
+static void
 sheet_set_direction (Sheet *sheet, gboolean text_is_rtl)
 {
        GnmRange r;
@@ -332,8 +350,9 @@ struct resize_colrow {
 
 static gboolean
 cb_colrow_compute_pixels_from_pts (GnmColRowIter const *iter,
-                                  struct resize_colrow *data)
+                                  gpointer data_)
 {
+       struct resize_colrow *data = data_;
        colrow_compute_pixels_from_pts ((ColRowInfo *)iter->cri,
                                        data->sheet, data->is_cols,
                                        data->scale);
@@ -364,9 +383,9 @@ sheet_scale_changed (Sheet *sheet, gboolean cols_rescaled, gboolean rows_rescale
 
                colrow_compute_pixels_from_pts (&sheet->cols.default_style,
                                                sheet, TRUE, closure.scale);
-               col_row_collection_foreach (&sheet->cols,
-                                           0, gnm_sheet_get_last_col (sheet),
-                       (ColRowHandler)&cb_colrow_compute_pixels_from_pts, &closure);
+               sheet_colrow_foreach (sheet, TRUE, 0, -1,
+                                     cb_colrow_compute_pixels_from_pts,
+                                     &closure);
        }
        if (rows_rescaled) {
                struct resize_colrow closure;
@@ -377,8 +396,9 @@ sheet_scale_changed (Sheet *sheet, gboolean cols_rescaled, gboolean rows_rescale
 
                colrow_compute_pixels_from_pts (&sheet->rows.default_style,
                                                sheet, FALSE, closure.scale);
-               col_row_collection_foreach (&sheet->rows, 0, gnm_sheet_get_last_row (sheet),
-                       (ColRowHandler)&cb_colrow_compute_pixels_from_pts, &closure);
+               sheet_colrow_foreach (sheet, FALSE, 0, -1,
+                                     cb_colrow_compute_pixels_from_pts,
+                                     &closure);
        }
 
        sheet_cell_foreach (sheet, (GHFunc)&cb_clear_rendered_cells, NULL);
@@ -1563,9 +1583,9 @@ void
 sheet_range_calc_spans (Sheet *sheet, GnmRange const *r, GnmSpanCalcFlags flags)
 {
        if (flags & GNM_SPANCALC_RE_RENDER)
-               sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_NONEXISTENT,
-                       r->start.col, r->start.row, r->end.col, r->end.row,
-                       cb_clear_rendered_values, NULL);
+               sheet_foreach_cell_in_range
+                       (sheet, CELL_ITER_IGNORE_NONEXISTENT, r,
+                        cb_clear_rendered_values, NULL);
        sheet_queue_respan (sheet, r->start.row, r->end.row);
 
        /* Redraw the new region in case the span changes */
@@ -1915,8 +1935,9 @@ sheet_flag_recompute_spans (Sheet const *sheet)
 }
 
 static gboolean
-cb_outline_level (GnmColRowIter const *iter, int *outline_level)
+cb_outline_level (GnmColRowIter const *iter, gpointer data)
 {
+       int *outline_level = data;
        if (*outline_level < iter->cri->outline_level)
                *outline_level  = iter->cri->outline_level;
        return FALSE;
@@ -1933,9 +1954,8 @@ static int
 sheet_colrow_fit_gutter (Sheet const *sheet, gboolean is_cols)
 {
        int outline_level = 0;
-       col_row_collection_foreach (is_cols ? &sheet->cols : &sheet->rows,
-                       0, colrow_max (is_cols, sheet) - 1,
-               (ColRowHandler)cb_outline_level, &outline_level);
+       sheet_colrow_foreach (sheet, is_cols, 0, -1,
+                             cb_outline_level, &outline_level);
        return outline_level;
 }
 
@@ -2499,7 +2519,7 @@ sheet_col_size_fit_pixels (Sheet *sheet, int col, int srow, int erow,
 
        data.max = -1;
        data.ignore_strings = ignore_strings;
-       sheet_foreach_cell_in_range (sheet,
+       sheet_foreach_cell_in_region (sheet,
                CELL_ITER_IGNORE_NONEXISTENT |
                CELL_ITER_IGNORE_HIDDEN |
                CELL_ITER_IGNORE_FILTERED,
@@ -2585,7 +2605,7 @@ sheet_row_size_fit_pixels (Sheet *sheet, int row, int scol, int ecol,
 
        data.max = -1;
        data.ignore_strings = ignore_strings;
-       sheet_foreach_cell_in_range (sheet,
+       sheet_foreach_cell_in_region (sheet,
                CELL_ITER_IGNORE_NONEXISTENT |
                CELL_ITER_IGNORE_HIDDEN |
                CELL_ITER_IGNORE_FILTERED,
@@ -2650,8 +2670,8 @@ sheet_recompute_spans_for_col (Sheet *sheet, int col)
        closure.sheet = sheet;
        closure.col = col;
 
-       col_row_collection_foreach (&sheet->rows, 0, gnm_sheet_get_last_row (sheet),
-                       &cb_recalc_spans_in_col, &closure);
+       sheet_colrow_foreach (sheet, FALSE, 0, -1,
+                             &cb_recalc_spans_in_col, &closure);
 }
 
 /****************************************************************************/
@@ -2736,18 +2756,14 @@ sheet_range_set_expr_cb (GnmSheetRange const *sr, GnmExprTop const *texpr)
        sheet_region_queue_recalc (sr->sheet, &sr->range);
        /* Store the parsed result creating any cells necessary */
        sheet_foreach_cell_in_range
-               (sr->sheet, CELL_ITER_ALL,
-                sr->range.start.col, sr->range.start.row,
-                sr->range.end.col, sr->range.end.row,
+               (sr->sheet, CELL_ITER_ALL, &sr->range,
                 (CellIterFunc)&cb_set_cell_content, &closure);
 
        merged = gnm_sheet_merge_get_overlap (sr->sheet, &sr->range);
        for (ptr = merged ; ptr != NULL ; ptr = ptr->next) {
                GnmRange const *tmp = ptr->data;
                sheet_foreach_cell_in_range
-                       (sr->sheet, CELL_ITER_IGNORE_BLANK,
-                        tmp->start.col, tmp->start.row,
-                        tmp->end.col, tmp->end.row,
+                       (sr->sheet, CELL_ITER_IGNORE_BLANK, tmp,
                         (CellIterFunc)&cb_clear_non_corner,
                         (gpointer)tmp);
        }
@@ -2810,16 +2826,13 @@ sheet_range_set_text (GnmParsePos const *pos, GnmRange const *r, char const *str
                                              &closure.expr_bound);
 
        /* Store the parsed result creating any cells necessary */
-       sheet_foreach_cell_in_range (sheet, CELL_ITER_ALL,
-               r->start.col, r->start.row, r->end.col, r->end.row,
+       sheet_foreach_cell_in_range (sheet, CELL_ITER_ALL, r,
                (CellIterFunc)&cb_set_cell_content, &closure);
 
        merged = gnm_sheet_merge_get_overlap (sheet, r);
        for (ptr = merged ; ptr != NULL ; ptr = ptr->next) {
                GnmRange const *tmp = ptr->data;
-               sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK,
-                       tmp->start.col, tmp->start.row,
-                       tmp->end.col, tmp->end.row,
+               sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_BLANK, tmp,
                        (CellIterFunc)&cb_clear_non_corner, (gpointer)tmp);
        }
        g_slist_free (merged);
@@ -2896,9 +2909,7 @@ static void
 sheet_range_set_markup_cb (GnmSheetRange const *sr, PangoAttrList *markup)
 {
        sheet_foreach_cell_in_range
-               (sr->sheet, CELL_ITER_ALL,
-                sr->range.start.col, sr->range.start.row,
-                sr->range.end.col, sr->range.end.row,
+               (sr->sheet, CELL_ITER_ALL, &sr->range,
                 (CellIterFunc)&cb_set_markup, markup);
 
        sheet_region_queue_recalc (sr->sheet, &sr->range);
@@ -3455,8 +3466,9 @@ typedef struct {
 } ArrayCheckData;
 
 static gboolean
-cb_check_array_horizontal (GnmColRowIter const *iter, ArrayCheckData *data)
+cb_check_array_horizontal (GnmColRowIter const *iter, gpointer data_)
 {
+       ArrayCheckData *data = data_;
        gboolean is_array = FALSE;
 
        if (data->flags & CHECK_AND_LOAD_START  &&      /* Top */
@@ -3481,8 +3493,9 @@ cb_check_array_horizontal (GnmColRowIter const *iter, ArrayCheckData *data)
 }
 
 static gboolean
-cb_check_array_vertical (GnmColRowIter const *iter, ArrayCheckData *data)
+cb_check_array_vertical (GnmColRowIter const *iter, gpointer data_)
 {
+       ArrayCheckData *data = data_;
        gboolean is_array = FALSE;
 
        if (data->flags & CHECK_AND_LOAD_START &&       /* Left */
@@ -3547,8 +3560,9 @@ sheet_range_splits_array (Sheet const *sheet,
                closure.flags = CHECK_AND_LOAD_START;
 
        if (closure.flags &&
-           col_row_collection_foreach (&sheet->cols, r->start.col, r->end.col,
-                           (ColRowHandler) cb_check_array_horizontal, &closure)) {
+           sheet_colrow_foreach (sheet, TRUE,
+                                 r->start.col, r->end.col,
+                                 cb_check_array_horizontal, &closure)) {
                if (cc)
                        gnm_cmd_context_error_splits_array (cc,
                                cmd, &closure.error);
@@ -3569,8 +3583,9 @@ sheet_range_splits_array (Sheet const *sheet,
                closure.flags = CHECK_AND_LOAD_START;
 
        if (closure.flags &&
-           col_row_collection_foreach (&sheet->rows, r->start.row, r->end.row,
-                           (ColRowHandler) cb_check_array_vertical, &closure)) {
+           sheet_colrow_foreach (sheet, FALSE,
+                                 r->start.row, r->end.row,
+                                 cb_check_array_vertical, &closure)) {
                if (cc)
                        gnm_cmd_context_error_splits_array (cc,
                                cmd, &closure.error);
@@ -3693,8 +3708,7 @@ sheet_range_contains_merges_or_arrays (Sheet const *sheet, GnmRange const *r,
 
        if (arrays) {
                if (sheet_foreach_cell_in_range (
-                           (Sheet *)sheet, CELL_ITER_IGNORE_NONEXISTENT,
-                           r->start.col, r->start.row, r->end.col, r->end.row,
+                           (Sheet *)sheet, CELL_ITER_IGNORE_NONEXISTENT, r,
                            cb_cell_is_array, NULL)) {
                        if (cc != NULL)
                                go_cmd_context_error_invalid
@@ -3914,6 +3928,62 @@ sheet_colrow_get_info (Sheet const *sheet, int colrow, gboolean is_cols)
                : sheet_row_get_info (sheet, colrow);
 }
 
+/**
+ * sheet_colrow_foreach:
+ * @sheet: #Sheet
+ * @is_cols: %TRUE for columns, %FALSE for rows.
+ * @first:     start position (inclusive)
+ * @last:      stop position (inclusive), -1 meaning end-of-sheet
+ * @callback: (scope call): A callback function which should return %TRUE
+ *    to stop the iteration.
+ * @user_data: A baggage pointer.
+ *
+ * Iterates through the existing rows or columns within the range supplied.
+ * If a callback returns %TRUE, iteration stops.
+ **/
+gboolean
+sheet_colrow_foreach (Sheet const *sheet,
+                     gboolean is_cols,
+                     int first, int last,
+                     ColRowHandler callback,
+                     gpointer user_data)
+{
+       ColRowCollection const *infos;
+       GnmColRowIter iter;
+       ColRowSegment const *segment;
+       int sub, inner_last, i;
+
+       g_return_val_if_fail (IS_SHEET (sheet), TRUE);
+
+       if (last == -1)
+               last = colrow_max (is_cols, sheet) - 1;
+       infos = is_cols ? &sheet->cols : &sheet->rows;
+
+       /* clip */
+       if (last > infos->max_used)
+               last = infos->max_used;
+
+       for (i = first; i <= last ; ) {
+               segment = COLROW_GET_SEGMENT (infos, i);
+               sub = COLROW_SUB_INDEX(i);
+               inner_last = (COLROW_SEGMENT_INDEX (last) == COLROW_SEGMENT_INDEX (i))
+                       ? COLROW_SUB_INDEX (last)+1 : COLROW_SEGMENT_SIZE;
+               iter.pos = i;
+               i += COLROW_SEGMENT_SIZE - sub;
+               if (segment == NULL)
+                       continue;
+
+               for (; sub < inner_last; sub++, iter.pos++) {
+                       iter.cri = segment->info[sub];
+                       if (iter.cri != NULL && (*callback)(&iter, user_data))
+                               return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+
 /*****************************************************************************/
 
 static gint
@@ -3962,11 +4032,8 @@ sheet_cells (Sheet *sheet, const GnmRange *r)
  * sheet_foreach_cell_in_range:
  * @sheet: #Sheet
  * @flags:
- * @start_col:
- * @start_row:
- * @end_col:
- * @end_row:
- * @callback: (scope call): #CellFiletrFunc
+ * @r: #GnmRange
+ * @callback: (scope call): #CellFilterFunc
  * @closure: user data.
  *
  * For each existing cell in the range specified, invoke the
@@ -3991,6 +4058,50 @@ sheet_cells (Sheet *sheet, const GnmRange *r)
  */
 GnmValue *
 sheet_foreach_cell_in_range (Sheet *sheet, CellIterFlags flags,
+                            GnmRange const *r,
+                            CellIterFunc callback,
+                            gpointer     closure)
+{
+       return sheet_foreach_cell_in_region (sheet, flags,
+                                            r->start.col, r->start.row,
+                                            r->end.col, r->end.row,
+                                            callback, closure);
+}
+
+
+/**
+ * sheet_foreach_cell_in_region:
+ * @sheet: #Sheet
+ * @flags:
+ * @start_col: Starting column
+ * @start_row: Starting row
+ * @end_col: Ending column, -1 meaning last
+ * @end_row: Ending row, -1 meaning last
+ * @callback: (scope call): #CellFilterFunc
+ * @closure: user data.
+ *
+ * For each existing cell in the range specified, invoke the
+ * callback routine.  If the only_existing flag is passed, then
+ * callbacks are only invoked for existing cells.
+ *
+ * Note: this function does not honour the CELL_ITER_IGNORE_SUBTOTAL flag.
+ *
+ * Returns: (transfer none): the value returned by the callback, which can be:
+ *    non-NULL on error, or VALUE_TERMINATE if some invoked routine requested
+ *    to stop (by returning non-NULL).
+ *
+ * NOTE: between 0.56 and 0.57, the traversal order changed.  The order is now
+ *
+ *        1    2    3
+ *        4    5    6
+ *        7    8    9
+ *
+ * (This appears to be the order in which XL looks at the values of ranges.)
+ * If your code depends on any particular ordering, please add a very visible
+ * comment near the call.
+ */
+GnmValue *
+sheet_foreach_cell_in_region (Sheet *sheet, CellIterFlags flags,
                             int start_col, int start_row,
                             int end_col,   int end_row,
                             CellIterFunc callback, void *closure)
@@ -4008,6 +4119,10 @@ sheet_foreach_cell_in_range (Sheet *sheet, CellIterFlags flags,
        g_return_val_if_fail (IS_SHEET (sheet), NULL);
        g_return_val_if_fail (callback != NULL, NULL);
 
+       // For convenience
+       if (end_col == -1) end_col = gnm_sheet_get_last_col (sheet);
+       if (end_row == -1) end_row = gnm_sheet_get_last_row (sheet);
+
        iter.pp.sheet = sheet;
        iter.pp.wb = sheet->workbook;
 
@@ -4247,8 +4362,7 @@ sheet_is_region_empty (Sheet *sheet, GnmRange const *r)
        g_return_val_if_fail (IS_SHEET (sheet), TRUE);
 
        return sheet_foreach_cell_in_range (
-               sheet, CELL_ITER_IGNORE_BLANK,
-               r->start.col, r->start.row, r->end.col, r->end.row,
+               sheet, CELL_ITER_IGNORE_BLANK, r,
                cb_fail_if_exist, NULL) == NULL;
 }
 
@@ -4511,9 +4625,9 @@ sheet_col_destroy (Sheet *sheet, int const col, gboolean free_cells)
                sheet->priv->recompute_max_col_group = TRUE;
 
        if (free_cells)
-               sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_NONEXISTENT,
-                       col, 0, col, gnm_sheet_get_last_row (sheet),
-                       &cb_free_cell, NULL);
+               sheet_foreach_cell_in_region (sheet, CELL_ITER_IGNORE_NONEXISTENT,
+                                             col, 0, col, -1,
+                                             &cb_free_cell, NULL);
 
        (*segment)->info[sub] = NULL;
        colrow_free (ci);
@@ -4548,9 +4662,9 @@ sheet_row_destroy (Sheet *sheet, int const row, gboolean free_cells)
                sheet->priv->recompute_max_row_group = TRUE;
 
        if (free_cells)
-               sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_NONEXISTENT,
-                       0, row, gnm_sheet_get_last_col (sheet), row,
-                       &cb_free_cell, NULL);
+               sheet_foreach_cell_in_region (sheet, CELL_ITER_IGNORE_NONEXISTENT,
+                                             0, row, -1, row,
+                                             &cb_free_cell, NULL);
 
        /* Rows have span lists, destroy them too */
        row_destroy_span (ri);
@@ -4744,7 +4858,7 @@ gnm_sheet_finalize (GObject *obj)
 /*****************************************************************************/
 
 /*
- * cb_empty_cell: A callback for sheet_foreach_cell_in_range
+ * cb_empty_cell: A callback for sheet_foreach_cell_in_region
  *     removes/clear all of the cells in the specified region.
  *     Does NOT queue a redraw.
  *
@@ -4782,7 +4896,7 @@ cb_empty_cell (GnmCellIter const *iter, gpointer user)
  * Clears are region of cells
  *
  * We assemble a list of cells to destroy, since we will be making changes
- * to the structure being manipulated by the sheet_foreach_cell_in_range routine
+ * to the structure being manipulated by the sheet_foreach_cell_in_region routine
  */
 void
 sheet_clear_region (Sheet *sheet,
@@ -4829,7 +4943,7 @@ sheet_clear_region (Sheet *sheet,
                /* Remove or empty the cells depending on
                 * whether or not there are comments
                 */
-               sheet_foreach_cell_in_range (sheet, CELL_ITER_IGNORE_NONEXISTENT,
+               sheet_foreach_cell_in_region (sheet, CELL_ITER_IGNORE_NONEXISTENT,
                        start_col, start_row, end_col, end_row,
                        &cb_empty_cell, GINT_TO_POINTER (clear_flags));
 
@@ -5285,7 +5399,7 @@ sheet_delete_rows (Sheet *sheet, int row, int count,
 }
 
 /*
- * Callback for sheet_foreach_cell_in_range to remove a cell from the sheet
+ * Callback for sheet_foreach_cell_in_region to remove a cell from the sheet
  * hash, unlink from the dependent collection and put it in a temporary list.
  */
 static GnmValue *
@@ -5404,10 +5518,10 @@ sheet_move_range (GnmExprRelocateInfo const *rinfo,
        }
 
        /* 3. Collect the cells */
-       sheet_foreach_cell_in_range (rinfo->origin_sheet, CELL_ITER_IGNORE_NONEXISTENT,
-               rinfo->origin.start.col, rinfo->origin.start.row,
-               rinfo->origin.end.col, rinfo->origin.end.row,
-               &cb_collect_cell, &cells);
+       sheet_foreach_cell_in_range (rinfo->origin_sheet,
+                                    CELL_ITER_IGNORE_NONEXISTENT,
+                                    &rinfo->origin,
+                                    &cb_collect_cell, &cells);
 
        /* Reverse list so that we start at the top left (simplifies arrays). */
        cells = g_list_reverse (cells);
@@ -5509,8 +5623,8 @@ sheet_col_get_distance_pts (Sheet const *sheet, int from, int to)
        g_return_val_if_fail (from >= 0, 1.);
        g_return_val_if_fail (to <= gnm_sheet_get_max_cols (sheet), 1.);
 
-       /* Do not use col_row_collection_foreach, it ignores empties */
-       dflt =  sheet->cols.default_style.size_pts;
+       /* Do not use sheet_colrow_foreach, it ignores empties */
+       dflt = sheet->cols.default_style.size_pts;
        for (i = from ; i < to ; ++i) {
                if (NULL == (ci = sheet_col_get (sheet, i)))
                        pts += dflt;
@@ -5549,8 +5663,8 @@ sheet_col_get_distance_pixels (Sheet const *sheet, int from, int to)
        g_return_val_if_fail (from >= 0, 1);
        g_return_val_if_fail (to <= gnm_sheet_get_max_cols (sheet), 1);
 
-       /* Do not use col_row_collection_foreach, it ignores empties */
-       dflt =  sheet_col_get_default_size_pixels (sheet);
+       /* Do not use sheet_colrow_foreach, it ignores empties */
+       dflt = sheet_col_get_default_size_pixels (sheet);
        for (i = from ; i < to ; ++i) {
                if (NULL == (ci = sheet_col_get (sheet, i)))
                        pixels += dflt;
@@ -5692,7 +5806,7 @@ sheet_row_get_distance_pts (Sheet const *sheet, int from, int to)
        g_return_val_if_fail (from >= 0, 1.);
        g_return_val_if_fail (to <= gnm_sheet_get_max_rows (sheet), 1.);
 
-       /* Do not use col_row_collection_foreach, it ignores empties.
+       /* Do not use sheet_colrow_foreach, it ignores empties.
         * Optimize this so that long jumps are not quite so horrific
         * for performance.
         */
@@ -5742,7 +5856,7 @@ sheet_row_get_distance_pixels (Sheet const *sheet, int from, int to)
        g_return_val_if_fail (from >= 0, 1);
        g_return_val_if_fail (to <= gnm_sheet_get_max_rows (sheet), 1);
 
-       /* Do not use col_row_collection_foreach, it ignores empties */
+       /* Do not use sheet_colrow_foreach, it ignores empties */
        dflt =  sheet_row_get_default_size_pixels (sheet);
        for (i = from ; i < to ; ++i) {
                if (NULL == (ci = sheet_row_get (sheet, i)))
@@ -5898,11 +6012,11 @@ sheet_dup_colrows (Sheet const *src, Sheet *dst)
 
        closure.sheet = dst;
        closure.is_column = TRUE;
-       col_row_collection_foreach (&src->cols, 0, max_col - 1,
-                       &sheet_clone_colrow_info_item, &closure);
+       sheet_colrow_foreach  (src, TRUE, 0, max_col - 1,
+                              &sheet_clone_colrow_info_item, &closure);
        closure.is_column = FALSE;
-       col_row_collection_foreach (&src->rows, 0, max_row - 1,
-                       &sheet_clone_colrow_info_item, &closure);
+       sheet_colrow_foreach (src, FALSE, 0, max_row - 1,
+                             &sheet_clone_colrow_info_item, &closure);
 
        sheet_col_set_default_size_pixels (dst,
                sheet_col_get_default_size_pixels (src));
@@ -6178,8 +6292,8 @@ cb_queue_respan (GnmColRowIter const *iter, void *user_data)
 void
 sheet_queue_respan (Sheet const *sheet, int start_row, int end_row)
 {
-       col_row_collection_foreach (&sheet->rows, start_row, end_row,
-               cb_queue_respan, NULL);
+       sheet_colrow_foreach (sheet, FALSE, start_row, end_row,
+                             cb_queue_respan, NULL);
 }
 
 void
@@ -6259,8 +6373,7 @@ sheet_range_trim (Sheet const *sheet, GnmRange *r,
        g_return_val_if_fail (r != NULL, TRUE);
 
        sheet_foreach_cell_in_range (
-               (Sheet *)sheet, CELL_ITER_IGNORE_BLANK,
-               r->start.col, r->start.row, r->end.col, r->end.row,
+               (Sheet *)sheet, CELL_ITER_IGNORE_BLANK, r,
                (CellIterFunc) cb_find_extents, &extent);
 
        if (extent.col < 0 || extent.row < 0)
diff --git a/src/sheet.h b/src/sheet.h
index a5936a3..5984fde 100644
--- a/src/sheet.h
+++ b/src/sheet.h
@@ -18,6 +18,13 @@ struct _GnmSheetSize {
 };
 GType gnm_sheet_size_get_type (void);
 
+struct _ColRowCollection {
+       int         max_used;
+       ColRowInfo  default_style;
+       GPtrArray * info;
+       int         max_outline_level;
+};
+
 typedef struct _SheetPrivate SheetPrivate;
 GType gnm_sheet_type_get_type (void);
 #define GNM_SHEET_TYPE_TYPE (gnm_sheet_type_get_type ())
@@ -157,11 +164,15 @@ struct _GnmCellIter {
        GnmParsePos  pp;
        ColRowInfo  *ci, *ri;
 };
-GnmValue *sheet_foreach_cell_in_range (Sheet *sheet, CellIterFlags flags,
+GnmValue *sheet_foreach_cell_in_region (Sheet *sheet, CellIterFlags flags,
                                       int start_col, int start_row,
                                       int end_col, int end_row,
                                       CellIterFunc callback,
                                       gpointer     closure);
+GnmValue *sheet_foreach_cell_in_range (Sheet *sheet, CellIterFlags flags,
+                                      GnmRange const *r,
+                                      CellIterFunc callback,
+                                      gpointer     closure);
 void       sheet_cell_foreach   (Sheet const *sheet,
                                  GHFunc callback, gpointer data);
 unsigned    sheet_cells_count   (Sheet const *sheet);
@@ -208,6 +219,12 @@ ColRowInfo const *sheet_row_get_info         (Sheet const *sheet, int row);
 ColRowInfo const *sheet_colrow_get_info          (Sheet const *sheet,
                                           int colrow, gboolean is_cols);
 
+gboolean          sheet_colrow_foreach    (Sheet const *sheet,
+                                           gboolean is_cols,
+                                           int first, int last,
+                                           ColRowHandler callback,
+                                           gpointer user_data);
+
 /*
  * Definitions of row/col size terminology :
  *
diff --git a/src/stf.c b/src/stf.c
index f7ca89c..189c141 100644
--- a/src/stf.c
+++ b/src/stf.c
@@ -304,11 +304,8 @@ stf_text_to_columns (WorkbookControl *wbc, GOCmdContext *cc)
        range_translate (&target, target_sheet, 1, 0);
 
        buf = gsf_output_memory_new ();
-       sheet_foreach_cell_in_range (src_sheet,
-               CELL_ITER_ALL,
-               src->start.col, src->start.row,
-               src->end.col, src->end.row,
-               (CellIterFunc) &cb_get_content, buf);
+       sheet_foreach_cell_in_range (src_sheet, CELL_ITER_ALL, src,
+                                    (CellIterFunc) &cb_get_content, buf);
 
        gsf_output_close (buf);
        data = gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (buf));
diff --git a/src/tools/dao.c b/src/tools/dao.c
index d7ccf33..3db7363 100644
--- a/src/tools/dao.c
+++ b/src/tools/dao.c
@@ -1093,12 +1093,12 @@ dao_convert_to_values (data_analysis_output_t *dao)
        if (dao->put_formulas)
                return;
 
-       sheet_foreach_cell_in_range (dao->sheet, CELL_ITER_IGNORE_BLANK,
-                                    dao->start_col, dao->start_row,
-                                    dao->start_col + dao->cols - 1,
-                                    dao->start_row + dao->rows - 1,
-                                    cb_convert_to_value,
-                                    NULL);
+       sheet_foreach_cell_in_region (dao->sheet, CELL_ITER_IGNORE_BLANK,
+                                     dao->start_col, dao->start_row,
+                                     dao->start_col + dao->cols - 1,
+                                     dao->start_row + dao->rows - 1,
+                                     cb_convert_to_value,
+                                     NULL);
 }
 
 void
diff --git a/src/tools/filter.c b/src/tools/filter.c
index a1f9c76..4ea029c 100644
--- a/src/tools/filter.c
+++ b/src/tools/filter.c
@@ -175,7 +175,7 @@ filter_show_all (WorkbookControl *wbc)
 
        /* FIXME: This is slow. We should probably have a linked list
         * containing the filtered rows in the sheet structure. */
-       col_row_collection_foreach (&sheet->rows, 0, gnm_sheet_get_last_row (sheet),
+       sheet_colrow_foreach (sheet, FALSE, 0, -1,
                        (ColRowHandler) cb_show_all, sheet);
        sheet->has_filtered_rows = FALSE;
        sheet_redraw_all (sheet, TRUE);
diff --git a/src/tools/scenarios.c b/src/tools/scenarios.c
index 45a5e26..998a9a7 100644
--- a/src/tools/scenarios.c
+++ b/src/tools/scenarios.c
@@ -228,9 +228,7 @@ gnm_scenario_add_area (GnmScenario *sc, const GnmSheetRange *sr)
        data.sc = sc;
        sheet_foreach_cell_in_range
                (eval_sheet (sr->sheet, sc->sheet),
-                CELL_ITER_IGNORE_NONEXISTENT,
-                sr->range.start.col, sr->range.start.row,
-                sr->range.end.col, sr->range.end.row,
+                CELL_ITER_IGNORE_NONEXISTENT, &sr->range,
                 cb_save_cells, &data);
        sc->items = g_slist_concat (sc->items,
                                    g_slist_reverse (data.items));
diff --git a/src/undo.c b/src/undo.c
index 0a6ad9d..f6c1a3c 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -228,7 +228,7 @@ gnm_undo_filter_set_condition_undo (GOUndo *u, G_GNUC_UNUSED gpointer data)
                                  gnm_filter_condition_dup (ua->cond), TRUE);
        sheet_update (ua->filter->sheet);
 
-       col_row_collection_foreach (&ua->filter->sheet->rows,
+       sheet_colrow_foreach (ua->filter->sheet, FALSE,
                        ua->filter->r.start.row + 1,
                        ua->filter->r.end.row,
                        (ColRowHandler) cb_filter_set_condition_undo,
diff --git a/src/wbc-gtk-actions.c b/src/wbc-gtk-actions.c
index facd4ec..24ea3d3 100644
--- a/src/wbc-gtk-actions.c
+++ b/src/wbc-gtk-actions.c
@@ -1831,10 +1831,7 @@ inc_dec (WBCGtk *wbcg,
                sheet_foreach_cell_in_range (sv_sheet (sv),
                                             CELL_ITER_IGNORE_BLANK |
                                             CELL_ITER_IGNORE_HIDDEN,
-                                            r->start.col, r->start.row,
-                                            r->end.col, r->end.row,
-                                            cb_calc_decs,
-                                            &decs);
+                                            r, cb_calc_decs, &decs);
        }
 
        new_fmt_str = g_string_new ("0");
diff --git a/src/widgets/gnm-filter-combo-view.c b/src/widgets/gnm-filter-combo-view.c
index 1b34029..d932f1f 100644
--- a/src/widgets/gnm-filter-combo-view.c
+++ b/src/widgets/gnm-filter-combo-view.c
@@ -208,14 +208,15 @@ fcombo_create_list (SheetObject *so,
                        if (i != field_num)
                                gnm_filter_combo_apply (g_ptr_array_index (filter->fields, i),
                                                        filtered_sheet);
-               sheet_foreach_cell_in_range (filtered_sheet, CELL_ITER_IGNORE_HIDDEN,
-                       r.start.col, r.start.row, r.end.col, r.end.row,
-                       (CellIterFunc)&cb_collect_content, &uc);
+               sheet_foreach_cell_in_range (filtered_sheet,
+                                            CELL_ITER_IGNORE_HIDDEN,
+                                            &r,
+                                            (CellIterFunc)&cb_collect_content, &uc);
                g_object_unref (filtered_sheet);
        } else
                sheet_foreach_cell_in_range (filter->sheet, CELL_ITER_ALL,
-                       r.start.col, r.start.row, r.end.col, r.end.row,
-                       (CellIterFunc)&cb_collect_content, &uc);
+                                            &r,
+                                            (CellIterFunc)&cb_collect_content, &uc);
 
        g_hash_table_foreach (uc.hash, (GHFunc)cb_hash_domain, sorted);
        g_ptr_array_sort (sorted, value_cmp);
diff --git a/src/workbook-cmd-format.c b/src/workbook-cmd-format.c
index c047855..dda9521 100644
--- a/src/workbook-cmd-format.c
+++ b/src/workbook-cmd-format.c
@@ -199,9 +199,7 @@ workbook_cmd_wrap_sort (WorkbookControl *wbc, int type)
        fd_array = gnm_func_lookup_or_add_placeholder ("array");
 
        sheet_foreach_cell_in_range
-               (sv->sheet, CELL_ITER_ALL,
-                cl.r->start.col, cl.r->start.row,
-                cl.r->end.col, cl.r->end.row,
+               (sv->sheet, CELL_ITER_ALL, cl.r,
                 (CellIterFunc)&cb_get_cell_content, &cl);
 
        cl.args = g_slist_reverse (cl.args);
diff --git a/src/workbook.c b/src/workbook.c
index 8b30d1b..42081f3 100644
--- a/src/workbook.c
+++ b/src/workbook.c
@@ -600,8 +600,7 @@ workbook_foreach_cell_in_range (GnmEvalPos const *pos,
 
                for (; i <= stop ; i++) {
                        res = sheet_foreach_cell_in_range (
-                               g_ptr_array_index (wb->sheets, i), flags,
-                               r.start.col, r.start.row, r.end.col, r.end.row,
+                               g_ptr_array_index (wb->sheets, i), flags, &r,
                                handler, closure);
                        if (res != NULL)
                                return res;
@@ -609,8 +608,7 @@ workbook_foreach_cell_in_range (GnmEvalPos const *pos,
                return NULL;
        }
 
-       return sheet_foreach_cell_in_range (start_sheet, flags,
-               r.start.col, r.start.row, r.end.col, r.end.row,
+       return sheet_foreach_cell_in_range (start_sheet, flags, &r,
                handler, closure);
 }
 
diff --git a/src/workbook.h b/src/workbook.h
index 157e60f..c35d0b1 100644
--- a/src/workbook.h
+++ b/src/workbook.h
@@ -57,7 +57,7 @@ gchar const *workbook_get_last_export_uri (Workbook *wb);
 void         workbook_set_file_exporter          (Workbook *wb, GOFileSaver *fs);
 void         workbook_set_last_export_uri (Workbook *wb, const gchar *uri);
 
-/* See also sheet_foreach_cell_in_range */
+/* See also sheet_foreach_cell_in_region */
 GnmValue   *workbook_foreach_cell_in_range (GnmEvalPos const  *pos,
                                            GnmValue const *cell_range,
                                            CellIterFlags   flags,
diff --git a/src/xml-sax-read.c b/src/xml-sax-read.c
index f457195..f1f2e2d 100644
--- a/src/xml-sax-read.c
+++ b/src/xml-sax-read.c
@@ -1974,7 +1974,7 @@ xml_sax_cell (GsfXMLIn *xin, xmlChar const **attrs)
                else if (attr_eq (attrs[0], "Value"))
                        value_result = CXML2C (attrs[1]);
                else if (attr_eq (attrs[0], "ValueFormat")) {
-                       if (value_fmt) go_format_unref (value_fmt);
+                       go_format_unref (value_fmt);
                        value_fmt = make_format (CXML2C (attrs[1]));
                } else
                        unknown_attr (xin, attrs);
diff --git a/src/xml-sax-write.c b/src/xml-sax-write.c
index c3c31f6..6908630 100644
--- a/src/xml-sax-write.c
+++ b/src/xml-sax-write.c
@@ -811,9 +811,8 @@ xml_write_cols_rows (GnmOutputXML *state, GnmCellRegion const *cr)
                                 (ColRowHandler)&xml_write_colrow_info,
                                 &closure);
                else
-                       col_row_collection_foreach
-                               (is_cols ? &sheet->cols : &sheet->rows,
-                                0, colrow_max(is_cols, sheet) - 1,
+                       sheet_colrow_foreach
+                               (sheet, is_cols, 0, -1,
                                 (ColRowHandler)&xml_write_colrow_info,
                                 &closure);
                xml_write_colrow_info (NULL, &closure); /* flush */
@@ -939,9 +938,10 @@ static void
 xml_write_cells (GnmOutputXML *state)
 {
        gsf_xml_out_start_element (state->output, GNM "Cells");
-       sheet_foreach_cell_in_range ((Sheet *)state->sheet, CELL_ITER_IGNORE_NONEXISTENT,
-               0, 0, gnm_sheet_get_last_col (state->sheet), gnm_sheet_get_last_row (state->sheet),
-               (CellIterFunc) cb_write_cell, state);
+       sheet_foreach_cell_in_region ((Sheet *)state->sheet,
+                                     CELL_ITER_IGNORE_NONEXISTENT,
+                                     0, 0, -1, -1,
+                                     (CellIterFunc) cb_write_cell, state);
        gsf_xml_out_end_element (state->output); /* </gnm:Cells> */
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]