[gnumeric] [slicers] Misc



commit d0559e77ec4791d15ee7a151a91793be2e91ce25
Author: Jody Goldberg <jody gnome org>
Date:   Tue Dec 29 13:52:16 2009 -0500

    [slicers] Misc
    
        - print hidden col/row items in xls import
        - fix for new canvas and support blank
        - Start to implement the slicer dialog
        - Prep for creation
        - add buttons to combo
    
        - <Tab> cursor movement
        Have it work the same way when entering content as when just moving
        around

 BUGS                                      |   57 ++++++--------------
 ChangeLog                                 |    5 ++
 plugins/excel/ChangeLog                   |    6 ++
 plugins/excel/xls-read-pivot.c            |   50 +++++++++++++++++-
 plugins/excel/xls-write-pivot.c           |    2 +-
 plugins/excel/xlsx-write-pivot.c          |    2 +-
 samples/slicers/groups-xl.xls             |  Bin 30208 -> 30208 bytes
 src/commands.c                            |    3 +-
 src/dialogs/ChangeLog                     |    4 ++
 src/dialogs/data-slicer.glade             |   14 +++--
 src/dialogs/dialog-data-slicer.c          |   83 +++++++++++++++++++++-------
 src/gnm-pane.c                            |    9 +++-
 src/gnm-sheet-slicer.c                    |   39 ++++++++++----
 src/go-data-cache-field.c                 |   31 +++++++++++
 src/go-data-cache-field.h                 |   10 ++--
 src/go-data-cache-impl.h                  |    3 +
 src/go-data-cache.c                       |   27 +---------
 src/go-data-cache.h                       |    3 +-
 src/sheet-control-gui.c                   |   51 ++++++-----------
 src/widgets/ChangeLog                     |    8 +++
 src/widgets/gnm-cell-combo-view-impl.h    |    7 ++-
 src/widgets/gnm-cell-combo-view.c         |   69 +++++++++++++++---------
 src/widgets/gnm-filter-combo-view.c       |    7 ++-
 src/widgets/gnm-sheet-slicer-combo-view.c |   41 +++++++++------
 src/widgets/gnm-validation-combo-view.c   |   15 +++---
 src/widgets/gnumeric-expr-entry.c         |   66 +++++++++++-----------
 tools/win32/Makefile.am                   |    6 +-
 27 files changed, 379 insertions(+), 239 deletions(-)
---
diff --git a/BUGS b/BUGS
index fb1c65a..82b791c 100644
--- a/BUGS
+++ b/BUGS
@@ -10,22 +10,18 @@ For 1.10
 
 Release Critical
 ----------------
-    - move xml probe to gsf				(DONE)
-    - poi open-pkg in gsf				(DONE)
-    - merge autosave tree				(DONE)
-    - win32 build issues				(DONE)
-    - coverity fixes					(DONE)
+    - hidding col/row headers should not hide outline symbols
+    - header selection broken when there are groups
 
 In Progress
 -----------
     Jody
 	- xlsx chart axis export
 	- data slicers
-	- move clipboard to SAX interfaces
 	- CELL translation & array handling
 	- INDEX range res, iteration
 	- ExprEntry extensions
-	- Filter dups (does this make sense ?)
+	- Tool to filter dups
 	- python wrapper for libspreadsheet
 	- mis-export of array expr
 	    http://bugzilla.gnome.org/show_bug.cgi?id=322096
@@ -35,8 +31,6 @@ In Progress
 Review
 ------
     - func name translation		{Manny}
-    - merge hdate functions
-    	http://bugzilla.gnome.org/show_bug.cgi?id=153738
     - merge libgda port
 
 Target Features
@@ -76,7 +70,7 @@ Misc stuff that should be fixed
 
 Worries
 -------
-    : range_translate in stf.c looks suspecious.
+    : range_translate in stf.c looks suspicous.
     : Add bounds checking of integers on the xml based importers
     : do bounds check in excel_get_text
     : provide undo for dropped objects from sheet_objects_clear
@@ -87,10 +81,6 @@ Worries
     - Create new type string/double/int (not bool) for BIN2DEC etc.
     - Allow missing arguments that are not '?' for ACCRINT.
 
-    - GETPIVOTDATA signature
-
-    - Reading /local/info/test-xls/Desktop\ \&\ Collaboration\ Products\ Weekly\ Invoice.xls
-	: getpivotdata
     - TestForBiffConsumer : #REF ??
     - accrint-test.xls : why fail ?
     - BAHT functions
@@ -111,7 +101,6 @@ Worries
     - named-expr-97.xls
     - operand.xls
     - pivot-edited.xls : odd colours in the 'the range that contains' box
-    - hidding col/row headers should not hide outline symbols
     - store and persist view modes
     - fix bogosity of 'ant' cursors being in sheet_view and having the app contact them.
 
@@ -247,6 +236,8 @@ Architecture Changes
 	    5.5.4.3) support toggles				(DONE)
 	    5.5.4.4) Add ok/cancel buttons
 	    5.5.4.5) filter/sort options
+    5.6) Functions
+	5.6.1) GETPIVOTDATA signature
 
 6) Undo/redo improvements
     6.1) Keep a .swp style log of user actions			{Dan Hall}
@@ -824,37 +815,23 @@ Architecture Changes
 41) win32
     41.1) Fix preview [#533795]
 	41.1.1) port over evince based preview from unix
-	    41.1.1.1) port it					(DONE)
+	    41.1.1.1) port it
 	    41.1.1.2) patch glib [#566348]
     41.2) python installation [#549387]
-	41.2.1) pygobject build fix				(DONE)
-	41.2.2) automate pygobject build fix			(DONE)
+	41.2.1) pygobject build fix
+	41.2.2) automate pygobject build fix
 	41.2.3) package pygobject
 	41.2.4) install pygobject
-    41.3) libbz2 not found for libgsf				(DONE)
-    41.4) hhmap
-	41.4.1) how to generate
-	41.4.2) include in the installer
-    41.5) optionally add quicklaunch & desktop links
+    41.3) Docs
+	41.3.1) Generation of hhmap 				(DONE)
+	41.3.2) include hhmap with installer			(DONE)
+	41.3.3) Include chm/hhmap build in build process
+	41.3.4) Generate chm package during build
     41.6) long pause between license and screen ?
     41.7) version dll.a the same way the .dll is handled
-    41.8) Fix Paradox build
-	41.8.1) find solution					(DONE)
-	41.8.2) automate solution
-    41.9) Add MS Office processing instruction hooks for us
-    41.10) freetype
-	41.10.1) fix build					(DONE)
-	41.10.2) extend jhbuild to automate fix			(DONE)
-	41.10.3) get patch into mainline [#566437]
-    41.11) fontconfig
-	41.11.1) jpg not found
-	41.11.2) zlib not found
-	41.11.3) CPPFLAGS patch
-    41.12) evince
-	41.12.1) totem screensaver disable
-	    41.12.1.1) make patch
-	41.12.2) session management
-	41.12.3) direct connection to unix print backend
+    41.8) Add MS Office processing instruction hooks for us
+    41.9) Increase stack size
+    41.10) Check registry/gconf wrapper
 
 autoformat
 ----------
diff --git a/ChangeLog b/ChangeLog
index 59d7cf4..bc0287c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-12-29  Jody Goldberg <jody gnome org>
+
+	* src/gnm-pane.c (gnm_pane_key_mode_sheet) : Support autoiterating
+	  through a region with <Tab>.
+
 2009-12-29  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* src/sheet-object-widget.c (sheet_widget_draw_cairo): only use 
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index e9b29d4..0213b88 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,9 @@
+2009-12-29  Jody Goldberg <jody gnome org>
+
+	* xls-read-pivot.c (xls_read_SXVI) : new stub.  Currently only notices
+	  when XL wants to hide things.
+	(xls_read_SXVD) : used from here.
+
 2009-12-24  Jean Brefort  <jean brefort normalesup org>
 
 	* xlsx-read-pivot.c (xlsx_CT_Number),
diff --git a/plugins/excel/xls-read-pivot.c b/plugins/excel/xls-read-pivot.c
index 5186fd1..4f27383 100644
--- a/plugins/excel/xls-read-pivot.c
+++ b/plugins/excel/xls-read-pivot.c
@@ -612,6 +612,54 @@ xls_read_SXIVD (BiffQuery *q, ExcelReadSheet *esheet)
 	}
 }
 
+static void
+xls_read_SXVI (BiffQuery *q, ExcelReadSheet *esheet, unsigned int i)
+{
+	guint16 const type	  = GSF_LE_GET_GUINT16 (q->data + 0);
+	guint16 const flags	  = GSF_LE_GET_GUINT16 (q->data + 2);
+	guint16 const cache_index = GSF_LE_GET_GUINT16 (q->data + 4);
+	// guint16 const name_len	  = GSF_LE_GET_GUINT16 (q->data + 6);
+	GnmXLImporter *imp = esheet->container.importer;
+	GODataCacheField *dcf = go_data_slicer_field_get_cache_field (imp->pivot.slicer_field);
+	char const *type_str = "unknown";
+
+	XL_CHECK_CONDITION (NULL != dcf);
+
+	d(0, { switch (type) {
+	case 0xFE: type_str = "Page"; break;
+	case 0xFF: type_str = "Null"; break;
+	case 0x00: type_str = "Data"; break;
+	case 0x01: type_str = "Default"; break;
+	case 0x02: type_str = "SUM"; break;
+	case 0x03: type_str = "COUNTA"; break;
+	case 0x04: type_str = "COUNT"; break;
+	case 0x05: type_str = "AVERAGE"; break;
+	case 0x06: type_str = "MAX"; break;
+	case 0x07: type_str = "MIN"; break;
+	case 0x08: type_str = "PRODUCT"; break;
+	case 0x09: type_str = "STDEV"; break;
+	case 0x0A: type_str = "STDEVP"; break;
+	case 0x0B: type_str = "VAR"; break;
+	case 0x0C: type_str = "VARP"; break;
+	case 0x0D: type_str = "Grand total"; break;
+	default :  type_str = "UNKNOWN"; break;
+	}
+	g_print ("[%u] %s %s %s %s %s = %hu\n", i, type_str,
+		 (flags & 1) ? "hidden " : "",
+		 (flags & 2) ? "detailHid " : "",
+		 (flags & 4) ? "calc " : "",
+		 (flags & 8) ? "missing " : "", cache_index);
+	});
+
+	if (type == 0x00 && (flags & 1))
+	{
+		XL_CHECK_CONDITION (cache_index != 0xffff);
+		g_print ("hide : ");
+		go_data_cache_dump_value (go_data_cache_field_get_val (dcf, cache_index));
+		g_print ("\n");
+	}
+}
+
 void
 xls_read_SXVD (BiffQuery *q, ExcelReadSheet *esheet)
 {
@@ -657,7 +705,7 @@ xls_read_SXVD (BiffQuery *q, ExcelReadSheet *esheet)
 	for (i = 0 ; i < num_items ; i++)
 		if (ms_biff_query_peek_next (q, &opcode) && BIFF_SXVI == opcode &&
 		    check_next_min (q, 8)) {
-			/* Ignore */
+			xls_read_SXVI (q, esheet, i);
 		}
 	if (ms_biff_query_peek_next (q, &opcode) && BIFF_SXVDEX == opcode &&
 	    check_next_min (q, 12)) {
diff --git a/plugins/excel/xls-write-pivot.c b/plugins/excel/xls-write-pivot.c
index 8dcbfa8..ab717e7 100644
--- a/plugins/excel/xls-write-pivot.c
+++ b/plugins/excel/xls-write-pivot.c
@@ -250,7 +250,7 @@ xls_write_cache_row (ExcelWriteState *ewb, GODataCache const *cache, unsigned in
 
 	for (i = 0 ; i < inlined->len ; i++)
 		xls_write_pivot_cache_value (ewb,
-			go_data_cache_get_val (cache, g_ptr_array_index (inlined, i), n));
+			go_data_cache_field_get_val (g_ptr_array_index (inlined, i), n));
 }
 
 static void
diff --git a/plugins/excel/xlsx-write-pivot.c b/plugins/excel/xlsx-write-pivot.c
index 1b69643..4ba8e17 100644
--- a/plugins/excel/xlsx-write-pivot.c
+++ b/plugins/excel/xlsx-write-pivot.c
@@ -117,7 +117,7 @@ xlsx_write_pivot_cache_records (XLSXWriteState *state, GODataCache const *cache,
 
 			case GO_DATA_CACHE_FIELD_TYPE_INLINE :
 				xlsx_write_pivot_val (state, xml,
-					go_data_cache_get_val (cache, field, j));
+					go_data_cache_field_get_val (field, j));
 			break;
 
 			case GO_DATA_CACHE_FIELD_TYPE_NONE :
diff --git a/samples/slicers/groups-xl.xls b/samples/slicers/groups-xl.xls
index 6a92c18..7a7d9c5 100644
Binary files a/samples/slicers/groups-xl.xls and b/samples/slicers/groups-xl.xls differ
diff --git a/src/commands.c b/src/commands.c
index d53ce62..b5b52ec 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -736,7 +736,7 @@ typedef struct {
 	GnmEvalPos pos;
 	gchar *text;
 	PangoAttrList *markup;
-	gboolean has_user_format;
+	gboolean has_user_format, first_time;
 	GnmCellRegion *old_contents;
 	ColRowIndexList *columns, *rows;
 	ColRowStateGroup *old_widths, *old_heights;
@@ -978,6 +978,7 @@ cmd_set_text (WorkbookControl *wbc,
 	g_free (where);
 	g_free (text);
 
+	me->first_time = TRUE;
 	me->has_user_format = !go_format_is_general (
 		gnm_style_get_format (sheet_style_get (sheet, pos->col, pos->row)));
 
diff --git a/src/dialogs/ChangeLog b/src/dialogs/ChangeLog
index b2686e5..5352245 100644
--- a/src/dialogs/ChangeLog
+++ b/src/dialogs/ChangeLog
@@ -1,3 +1,7 @@
+2009-12-29  Jody Goldberg <jody gnome org>
+
+	* dialog-data-slicer.c : some incomplete work towards creating sources
+
 2009-12-29 Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* formula-guru.glade: add quote button
diff --git a/src/dialogs/data-slicer.glade b/src/dialogs/data-slicer.glade
index a7e70d2..4281dd9 100644
--- a/src/dialogs/data-slicer.glade
+++ b/src/dialogs/data-slicer.glade
@@ -91,12 +91,14 @@
 	  <property name="enable_popup">False</property>
 
 	  <child>
-	    <widget class="Custom" id="custom1">
+	    <widget class="GtkVBox" id="source_vbox">
 	      <property name="visible">True</property>
-	      <property name="creation_function">gnm_expr_entry_new_glade</property>
-	      <property name="int1">0</property>
-	      <property name="int2">0</property>
-	      <property name="last_modification_time">Sun, 03 May 2009 22:57:16 GMT</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<placeholder/>
+	      </child>
 	    </widget>
 	    <packing>
 	      <property name="tab_expand">False</property>
@@ -107,7 +109,7 @@
 	  <child>
 	    <widget class="GtkLabel" id="label1">
 	      <property name="visible">True</property>
-	      <property name="label" translatable="yes">Data</property>
+	      <property name="label" translatable="yes">Source</property>
 	      <property name="use_underline">False</property>
 	      <property name="use_markup">False</property>
 	      <property name="justify">GTK_JUSTIFY_LEFT</property>
diff --git a/src/dialogs/dialog-data-slicer.c b/src/dialogs/dialog-data-slicer.c
index dfc681e..5533311 100644
--- a/src/dialogs/dialog-data-slicer.c
+++ b/src/dialogs/dialog-data-slicer.c
@@ -34,17 +34,24 @@
 #include <gnm-sheet-slicer.h>
 #include <go-data-slicer.h>
 #include <go-data-slicer-field.h>
+#include <go-data-cache.h>
 
 #include <glade/glade.h>
 
 typedef struct {
-	GtkWidget	*dialog;
-	GladeXML	*gui;
-	WBCGtk		*wbcg;
-	SheetView	*sv;
-	GnmSheetSlicer	*slicer;
+	GtkWidget		*dialog;
+	GladeXML		*gui;
+	WBCGtk			*wbcg;
+	SheetView		*sv;
 
-	GtkTreeView	*treeview;
+	GnmSheetSlicer		*slicer;
+	GODataCache		*cache;
+	GODataCacheSource	*source;
+
+	GtkWidget		*notebook;
+	GnmExprEntry		*source_expr;
+
+	GtkTreeView		*treeview;
 	GtkTreeSelection	*selection;
 } DialogDataSlicer;
 
@@ -60,8 +67,10 @@ enum {
 static void
 cb_dialog_data_slicer_destroy (DialogDataSlicer *state)
 {
-	if (NULL != state->gui) { g_object_unref (G_OBJECT (state->gui)); state->gui = NULL; }
-	if (NULL != state->slicer) { g_object_unref (G_OBJECT (state->slicer)); state->slicer = NULL; }
+	if (NULL != state->gui)		{ g_object_unref (G_OBJECT (state->gui));	state->gui = NULL; }
+	if (NULL != state->slicer)	{ g_object_unref (G_OBJECT (state->slicer));	state->slicer = NULL; }
+	if (NULL != state->cache)	{ g_object_unref (G_OBJECT (state->cache));	state->cache = NULL; }
+	if (NULL != state->source)	{ g_object_unref (G_OBJECT (state->source));	state->source = NULL; }
 	state->dialog = NULL;
 	g_free (state);
 }
@@ -134,6 +143,7 @@ cb_dialog_data_slicer_create_model (DialogDataSlicer *state)
 		{ GDS_FIELD_TYPE_ROW,	N_("Row") },
 		{ GDS_FIELD_TYPE_COL,	N_("Column") },
 		{ GDS_FIELD_TYPE_DATA,	N_("Data") },
+		/* Must be last */
 		{ GDS_FIELD_TYPE_UNSET,	N_("Unused") }
 	};
 
@@ -164,24 +174,26 @@ cb_dialog_data_slicer_create_model (DialogDataSlicer *state)
 	n = go_data_slicer_num_fields (GO_DATA_SLICER (state->slicer));
 	for (i = 0 ; i < n ; i++) {
 		GtkTreeIter child_iter;
-		unsigned int field_types;
-		int header_indx;
 		GODataSlicerField *field =
 			go_data_slicer_get_field (GO_DATA_SLICER (state->slicer), i);
 		GOString *name = go_data_slicer_field_get_name (field);
-
-		g_object_get (field, "field-types", &field_types, "header-index", &header_indx, NULL);
-
-		for (j = 0 ; j < G_N_ELEMENTS (field_type_labels) ; j++)
-		       	if ((field_types & (1 << field_type_labels[j].type))) {
+		gboolean used = FALSE;
+
+		for (j = 0 ; j < G_N_ELEMENTS (field_type_labels) ; j++) {
+			int header_index = (GDS_FIELD_TYPE_UNSET != field_type_labels[j].type)
+				? go_data_slicer_field_get_field_type_pos (field, field_type_labels[j].type)
+				: (used ? -1 : 0);
+			if (header_index >= 0) {
+				used = TRUE;
 				gtk_tree_store_append (model, &child_iter, &field_type_labels[j].iter);
 				gtk_tree_store_set (model, &child_iter,
-					FIELD,			NULL,
+					FIELD,			field,
 					FIELD_TYPE,		field_type_labels[j].type,
 					FIELD_NAME,		name->str,
-					FIELD_HEADER_INDEX,	header_indx,
+					FIELD_HEADER_INDEX,	header_index,
 					-1);
 			}
+		}
 	}
 	gtk_tree_view_set_model (state->treeview, smodel);
 }
@@ -192,6 +204,14 @@ cb_dialog_data_slicer_selection_changed (GtkTreeSelection *selection,
 {
 }
 
+static void
+cb_source_expr_changed (DialogDataSlicer *state)
+{
+        GnmValue *range;
+       	range = gnm_expr_entry_parse_as_value
+		(GNM_EXPR_ENTRY (state->source_expr), sv_sheet (state->sv));
+}
+
 void
 dialog_data_slicer (WBCGtk *wbcg, gboolean create)
 {
@@ -211,16 +231,35 @@ dialog_data_slicer (WBCGtk *wbcg, gboolean create)
 	if (NULL == gui)
 		return;
 
-	state = g_new (DialogDataSlicer, 1);
+	state = g_new0 (DialogDataSlicer, 1);
 	state->wbcg	= wbcg;
 	state->sv	= wb_control_cur_sheet_view (WORKBOOK_CONTROL (wbcg));
 	state->gui	= gui;
-	state->slicer	= sv_editpos_in_slicer (state->sv);
+
+	state->dialog	= glade_xml_get_widget (state->gui, "dialog_data_slicer");
+	state->notebook = glade_xml_get_widget (state->gui, "notebook");
+	state->slicer	= create ? NULL : sv_editpos_in_slicer (state->sv);
+	state->cache	= NULL;
+	state->source	= NULL;
+
 	if (NULL == state->slicer) {
-	} else
+		state->slicer = g_object_new (GNM_SHEET_SLICER_TYPE, NULL);
+	} else {
 		g_object_ref (G_OBJECT (state->slicer));
+		g_object_get (G_OBJECT (state->slicer), "cache", &state->cache, NULL);
+		if (NULL != state->cache &&
+		    NULL != (state->source = go_data_cache_get_source (state->cache)))
+		    g_object_ref (G_OBJECT (state->source));
+	}
 
-	state->dialog = glade_xml_get_widget (state->gui, "dialog_data_slicer");
+	state->source_expr = gnm_expr_entry_new (state->wbcg, TRUE);
+	gnm_expr_entry_set_flags (state->source_expr,
+		GNM_EE_SINGLE_RANGE, GNM_EE_MASK);
+	g_signal_connect_swapped (G_OBJECT (state->source_expr),
+		"changed", G_CALLBACK (cb_source_expr_changed), state);
+	w = glade_xml_get_widget (state->gui, "source_vbox");
+	gtk_box_pack_start (GTK_BOX (w), GTK_WIDGET (state->source_expr), FALSE, FALSE, 0);
+	gtk_widget_show (GTK_WIDGET (state->source_expr));
 
 	w = glade_xml_get_widget (state->gui, "ok_button");
 	g_signal_connect (G_OBJECT (w), "clicked",
@@ -246,6 +285,8 @@ dialog_data_slicer (WBCGtk *wbcg, gboolean create)
 
 	g_signal_connect (state->treeview, "realize", G_CALLBACK (gtk_tree_view_expand_all), NULL);
 
+	gtk_notebook_set_current_page (GTK_NOTEBOOK (state->notebook), create ? 0 : 1);
+
 	/* a candidate for merging into attach guru */
 	gnumeric_init_help_button (glade_xml_get_widget (state->gui, "help_button"),
 		GNUMERIC_HELP_LINK_DATA_SLICER);
diff --git a/src/gnm-pane.c b/src/gnm-pane.c
index cec7d3a..865eb3b 100644
--- a/src/gnm-pane.c
+++ b/src/gnm-pane.c
@@ -159,6 +159,7 @@ gnm_pane_key_mode_sheet (GnmPane *pane, GdkEventKey *event,
 	gboolean delayed_movement = FALSE;
 	gboolean jump_to_bounds = event->state & GDK_CONTROL_MASK;
 	gboolean is_enter = FALSE;
+	int first_tab_col;
 	int state = gnumeric_filter_modifiers (event->state);
 	void (*movefn) (SheetControlGUI *, int n, gboolean jump, gboolean horiz);
 
@@ -386,8 +387,14 @@ gnm_pane_key_mode_sheet (GnmPane *pane, GdkEventKey *event,
 		if (wbcg_is_editing (wbcg))
 			sheet = wbcg->editing_sheet;
 
+	       	/* registering the cmd clears it,  restore it afterwards */
+		first_tab_col = sv->first_tab_col;
+
 		if (wbcg_edit_finish (wbcg, WBC_EDIT_ACCEPT, NULL)) {
 			GODirection dir = gnm_conf_get_core_gui_editing_enter_moves_dir ();
+
+			sv->first_tab_col = first_tab_col;
+
 			if ((event->state & GDK_MOD1_MASK) &&
 			    (event->state & GDK_CONTROL_MASK) &&
 			    !is_enter) {
@@ -395,7 +402,7 @@ gnm_pane_key_mode_sheet (GnmPane *pane, GdkEventKey *event,
 					workbook_cmd_dec_indent (sc->wbc);
 				else
 					workbook_cmd_inc_indent	(sc->wbc);
-			} else if (dir != GO_DIRECTION_NONE) {
+			} else if (!is_enter || dir != GO_DIRECTION_NONE) {
 				gboolean forward = TRUE;
 				gboolean horizontal = TRUE;
 				if (is_enter) {
diff --git a/src/gnm-sheet-slicer.c b/src/gnm-sheet-slicer.c
index eb496d3..b70da2a 100644
--- a/src/gnm-sheet-slicer.c
+++ b/src/gnm-sheet-slicer.c
@@ -321,6 +321,7 @@ gnm_sheet_slicers_at_pos (Sheet const *sheet, GnmCellPos const *pos)
 	return NULL;
 }
 
+#if 0
 static void
 gss_append_field_indicies (GnmSheetSlicer const *gss, GODataSlicerFieldType type,
 			   GArray *field_order)
@@ -331,6 +332,29 @@ gss_append_field_indicies (GnmSheetSlicer const *gss, GODataSlicerFieldType type
 		g_array_append_val (field_order, g_array_index (tmp, int, i));
 }
 
+static void
+gnm_sheet_slicer_test_sort (GnmSheetSlicer *gss)
+{
+	/* quick test to sort the cache based on the row/col */
+	GArray *permutation, *field_order;
+	unsigned int i, n;
+
+	field_order = g_array_sized_new (FALSE, FALSE, sizeof (unsigned int), gss->base.all_fields->len);
+	gss_append_field_indicies (gss, GDS_FIELD_TYPE_ROW, field_order);
+	gss_append_field_indicies (gss, GDS_FIELD_TYPE_COL, field_order);
+
+	n = go_data_cache_num_items (gss->base.cache);
+	permutation = g_array_sized_new (FALSE, FALSE, sizeof (int), n);
+	for (i = 0 ; i < n ; i++)
+		g_array_append_val (permutation, i);
+	go_data_cache_permute (gss->base.cache, field_order, permutation);
+	go_data_cache_dump (gss->base.cache, field_order, permutation);
+
+	g_array_free (field_order, TRUE);
+	g_array_free (permutation, TRUE);
+}
+#endif
+
 /**
  * gnm_sheet_slicer_regenerate:
  * @gss : #GnmSheetSlicer
@@ -342,27 +366,20 @@ gss_append_field_indicies (GnmSheetSlicer const *gss, GODataSlicerFieldType type
 void
 gnm_sheet_slicer_regenerate (GnmSheetSlicer *gss)
 {
-	GArray *permutation, *field_order;
+#if 0
+	GArray *permutation, *rows;
 	unsigned int i, n;
 
 	g_return_if_fail (IS_GNM_SHEET_SLICER (gss));
 	g_return_if_fail (IS_SHEET (gss->sheet));
+	g_return_if_fail (NULL != gss->base.cache);
 
 	field_order = g_array_sized_new (FALSE, FALSE, sizeof (unsigned int), gss->base.all_fields->len);
 	gss_append_field_indicies (gss, GDS_FIELD_TYPE_ROW, field_order);
 	gss_append_field_indicies (gss, GDS_FIELD_TYPE_COL, field_order);
 
 	n = go_data_cache_num_items (gss->base.cache);
-	permutation = g_array_sized_new (FALSE, FALSE, sizeof (int), n);
-	for (i = 0 ; i < n ; i++)
-		g_array_append_val (permutation, i);
-
-	/* TODO : apply page filters */
-	go_data_cache_permute (gss->base.cache, field_order, permutation);
-	go_data_cache_dump (gss->base.cache, field_order, permutation);
-
-	g_array_free (field_order, TRUE);
-	g_array_free (permutation, TRUE);
+#endif
 }
 
 GnmSheetSlicerLayout
diff --git a/src/go-data-cache-field.c b/src/go-data-cache-field.c
index d77f632..62ed573 100644
--- a/src/go-data-cache-field.c
+++ b/src/go-data-cache-field.c
@@ -23,6 +23,7 @@
 
 #include <gnumeric-config.h>
 #include "go-data-cache-field-impl.h"
+#include "go-data-cache-impl.h"
 #include "go-data-cache.h"
 
 #include <go-val.h>
@@ -152,6 +153,13 @@ GSF_CLASS (GODataCacheField, go_data_cache_field,
 	   go_data_cache_field_class_init, go_data_cache_field_init,
 	   G_TYPE_OBJECT)
 
+GODataCache *
+go_data_cache_field_get_cache (GODataCacheField const *field)
+{
+	g_return_val_if_fail (IS_GO_DATA_CACHE_FIELD (field), NULL);
+	return field->cache;
+}
+
 GOString *
 go_data_cache_field_get_name (GODataCacheField const *field)
 {
@@ -194,3 +202,26 @@ go_data_cache_field_ref_type (GODataCacheField const *field)
 	g_return_val_if_fail (IS_GO_DATA_CACHE_FIELD (field), GO_DATA_CACHE_FIELD_TYPE_NONE);
 	return field->ref_type;
 }
+
+GOVal const *
+go_data_cache_field_get_val (GODataCacheField const *field, unsigned int record_num)
+{
+	gpointer p;
+	unsigned int idx;
+
+	g_return_val_if_fail (IS_GO_DATA_CACHE_FIELD (field), NULL);
+
+	p = go_data_cache_records_index (field->cache, record_num) + field->offset;
+	switch (field->ref_type) {
+	case GO_DATA_CACHE_FIELD_TYPE_NONE   : return NULL;
+	case GO_DATA_CACHE_FIELD_TYPE_INLINE : return *((GOVal **)p);
+	case GO_DATA_CACHE_FIELD_TYPE_INDEXED_I8  : idx = *(guint8 *)p; break;
+	case GO_DATA_CACHE_FIELD_TYPE_INDEXED_I16 : idx = *(guint16 *)p; break;
+	case GO_DATA_CACHE_FIELD_TYPE_INDEXED_I32 : idx = *(guint32 *)p; break;
+	default :
+		g_warning ("unknown field type %d", field->ref_type);
+		return NULL;
+	}
+
+	return (idx-- > 0) ? g_ptr_array_index (field->indexed, idx) : NULL;
+}
diff --git a/src/go-data-cache-field.h b/src/go-data-cache-field.h
index 63e4e5a..d8e7d2b 100644
--- a/src/go-data-cache-field.h
+++ b/src/go-data-cache-field.h
@@ -44,10 +44,12 @@ typedef enum {
 
 GType go_data_cache_field_get_type (void);
 
-GOString 	 *go_data_cache_field_get_name (GODataCacheField const *field);
-GOValArray const *go_data_cache_field_get_vals (GODataCacheField const *field, gboolean group_val);
-void		  go_data_cache_field_set_vals (GODataCacheField       *field, gboolean group_val,
-						GOValArray *a);
+GODataCache	 *go_data_cache_field_get_cache (GODataCacheField const *field);
+GOVal const	 *go_data_cache_field_get_val   (GODataCacheField const *field, unsigned int record_num);
+GOString 	 *go_data_cache_field_get_name  (GODataCacheField const *field);
+GOValArray const *go_data_cache_field_get_vals  (GODataCacheField const *field, gboolean group_val);
+void		  go_data_cache_field_set_vals  (GODataCacheField       *field, gboolean group_val,
+						 GOValArray *a);
 
 gboolean 	  go_data_cache_field_is_base (GODataCacheField const *field);
 GODataCacheFieldType
diff --git a/src/go-data-cache-impl.h b/src/go-data-cache-impl.h
index 9e7be49..44dcf29 100644
--- a/src/go-data-cache-impl.h
+++ b/src/go-data-cache-impl.h
@@ -48,6 +48,9 @@ typedef struct {
 	GObjectClass base;
 } GODataCacheClass;
 
+/* utility macro */
+#define go_data_cache_records_index(c, i)	((c)->records + ((c)->record_size * (i)))
+
 G_END_DECLS
 
 #endif /* GO_DATA_CACHE_IMPL_H */
diff --git a/src/go-data-cache.c b/src/go-data-cache.c
index 178fb4e..d3facff 100644
--- a/src/go-data-cache.c
+++ b/src/go-data-cache.c
@@ -42,7 +42,6 @@ enum {
 };
 
 /*****************************************************************/
-#define go_data_cache_records_index(c, i)	((c)->records + ((c)->record_size * (i)))
 
 static void
 go_data_cache_records_set_size (GODataCache *cache, unsigned int n)
@@ -296,7 +295,7 @@ go_data_cache_import_start (GODataCache *cache, unsigned int n)
 	go_data_cache_records_init (cache, n, offset);
 }
 
-static void
+void
 go_data_cache_dump_value (GOVal const *v)
 {
 	if (NULL == v) {
@@ -426,30 +425,6 @@ go_data_cache_get_field (GODataCache const *cache, int i)
 	return g_ptr_array_index (cache->fields, i);
 }
 
-GOVal const *
-go_data_cache_get_val (GODataCache const *cache,
-		       GODataCacheField const *field, unsigned int record_num)
-{
-	gpointer p;
-	unsigned int idx;
-
-	g_return_val_if_fail (IS_GO_DATA_CACHE (cache), NULL);
-
-	p = go_data_cache_records_index (cache, record_num) + field->offset;
-	switch (field->ref_type) {
-	case GO_DATA_CACHE_FIELD_TYPE_NONE   : return NULL;
-	case GO_DATA_CACHE_FIELD_TYPE_INLINE : return *((GOVal **)p);
-	case GO_DATA_CACHE_FIELD_TYPE_INDEXED_I8  : idx = *(guint8 *)p; break;
-	case GO_DATA_CACHE_FIELD_TYPE_INDEXED_I16 : idx = *(guint16 *)p; break;
-	case GO_DATA_CACHE_FIELD_TYPE_INDEXED_I32 : idx = *(guint32 *)p; break;
-	default :
-		g_warning ("unknown field type %d", field->ref_type);
-		return NULL;
-	}
-
-	return (idx-- > 0) ? g_ptr_array_index (field->indexed, idx) : NULL;
-}
-
 int
 go_data_cache_get_index (GODataCache const *cache,
 			 GODataCacheField const *field, unsigned int record_num)
diff --git a/src/go-data-cache.h b/src/go-data-cache.h
index c36d845..dd1b7cc 100644
--- a/src/go-data-cache.h
+++ b/src/go-data-cache.h
@@ -47,8 +47,6 @@ void	     go_data_cache_set_val   (GODataCache *dc,
 				      int field, unsigned int record_num, GOVal *v);
 int	     go_data_cache_get_index (GODataCache const *dc,
 				      GODataCacheField const *field, unsigned int record_num);
-GOVal const *go_data_cache_get_val   (GODataCache const *dc,
-				      GODataCacheField const *field, unsigned int record_num);
 
 /* Data Access */
 unsigned int	  go_data_cache_num_items  (GODataCache const *dc);
@@ -64,6 +62,7 @@ void go_data_cache_permute (GODataCache const *dc,
 void go_data_cache_dump (GODataCache *dc,
 			 GArray const *field_order,
 			 GArray const *permutation);
+void go_data_cache_dump_value (GOVal const *v);
 
 G_END_DECLS
 
diff --git a/src/sheet-control-gui.c b/src/sheet-control-gui.c
index e386c06..779ffc6 100644
--- a/src/sheet-control-gui.c
+++ b/src/sheet-control-gui.c
@@ -1141,37 +1141,23 @@ cb_wbc_destroyed (SheetControlGUI *scg)
 }
 
 static void
-cb_scg_prefs (G_GNUC_UNUSED Sheet *sheet,
-	      G_GNUC_UNUSED GParamSpec *pspec,
-	      SheetControlGUI *scg)
+cb_scg_redraw (SheetControlGUI *scg)
 {
 	scg_adjust_preferences (scg);
-}
-
-static void
-cb_scg_redraw (Sheet *sheet,
-	       GParamSpec *pspec,
-	       SheetControlGUI *scg)
-{
-	cb_scg_prefs (sheet, pspec, scg);
 	scg_redraw_all (&scg->sheet_control, TRUE);
 }
 
 static void
-cb_scg_redraw_resize (Sheet *sheet,
-		      GParamSpec *pspec,
-		      SheetControlGUI *scg)
+cb_scg_redraw_resize (SheetControlGUI *scg)
 {
-	cb_scg_redraw (sheet, pspec, scg);
+	cb_scg_redraw (scg);
 	scg_resize (scg, FALSE);
 }
 
 static void
-cb_scg_sheet_resized (Sheet *sheet,
-		      GParamSpec *pspec,
-		      SheetControlGUI *scg)
+cb_scg_sheet_resized (SheetControlGUI *scg)
 {
-	cb_scg_redraw_resize (sheet, pspec, scg);
+	cb_scg_redraw_resize (scg);
 	sc_set_panes (&scg->sheet_control);
 }
 
@@ -1535,20 +1521,19 @@ sheet_control_gui_new (SheetView *sv, WBCGtk *wbcg)
 
 	sv_attach_control (sv, SHEET_CONTROL (scg));
 
-	g_object_connect
-		(G_OBJECT (sheet),
+	g_object_connect (G_OBJECT (sheet),
 		 "swapped_signal::notify::text-is-rtl", cb_scg_direction_changed, scg,
-		 "signal::notify::display-formulas", cb_scg_redraw, scg,
-		 "signal::notify::display-zeros", cb_scg_redraw, scg,
-		 "signal::notify::display-grid", cb_scg_redraw, scg,
-		 "signal::notify::display-column-header", cb_scg_prefs, scg,
-		 "signal::notify::display-row-header", cb_scg_prefs, scg,
-		 "signal::notify::use-r1c1", cb_scg_redraw, scg,
-		 "signal::notify::display-outlines", cb_scg_redraw_resize, scg,
-		 "signal::notify::display-outlines-below", cb_scg_redraw_resize, scg,
-		 "signal::notify::display-outlines-right", cb_scg_redraw_resize, scg,
-		 "signal::notify::columns", cb_scg_sheet_resized, scg,
-		 "signal::notify::rows", cb_scg_sheet_resized, scg,
+		 "swapped_signal::notify::display-formulas", cb_scg_redraw, scg,
+		 "swapped_signal::notify::display-zeros", cb_scg_redraw, scg,
+		 "swapped_signal::notify::display-grid", cb_scg_redraw, scg,
+		 "swapped_signal::notify::display-column-header", scg_adjust_preferences, scg,
+		 "swapped_signal::notify::display-row-header", scg_adjust_preferences, scg,
+		 "swapped_signal::notify::use-r1c1", cb_scg_redraw, scg,
+		 "swapped_signal::notify::display-outlines", cb_scg_redraw_resize, scg,
+		 "swapped_signal::notify::display-outlines-below", cb_scg_redraw_resize, scg,
+		 "swapped_signal::notify::display-outlines-right", cb_scg_redraw_resize, scg,
+		 "swapped_signal::notify::columns", cb_scg_sheet_resized, scg,
+		 "swapped_signal::notify::rows", cb_scg_sheet_resized, scg,
 		 NULL);
 
 	scg->label = editable_label_new
@@ -1601,7 +1586,7 @@ scg_finalize (GObject *object)
 
 	if (sc->view) {
 		Sheet *sheet = sv_sheet (sc->view);
-		g_signal_handlers_disconnect_by_func (sheet, cb_scg_prefs, scg);
+		g_signal_handlers_disconnect_by_func (sheet, scg_adjust_preferences, scg);
 		g_signal_handlers_disconnect_by_func (sheet, cb_scg_redraw, scg);
 		g_signal_handlers_disconnect_by_func (sheet, cb_scg_redraw_resize, scg);
 		g_signal_handlers_disconnect_by_func (sheet, cb_scg_sheet_resized, scg);
diff --git a/src/widgets/ChangeLog b/src/widgets/ChangeLog
index 8393acc..fe18a9b 100644
--- a/src/widgets/ChangeLog
+++ b/src/widgets/ChangeLog
@@ -1,3 +1,11 @@
+2009-12-29  Jody Goldberg <jody gnome org>
+
+	* gnumeric-expr-entry.c (cb_gee_key_press_event) : handle auto
+	  iteration in region with <Tab>.
+
+	* gnm-cell-combo-view.c (ccombo_activate) : hooks to support Ok/Cancel
+	  buttons in combos
+
 2009-12-23  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* gnumeric-expr-entry.c (cb_gee_key_press_event):  handle tab key
diff --git a/src/widgets/gnm-cell-combo-view-impl.h b/src/widgets/gnm-cell-combo-view-impl.h
index 2e34b92..1d83b25 100644
--- a/src/widgets/gnm-cell-combo-view-impl.h
+++ b/src/widgets/gnm-cell-combo-view-impl.h
@@ -9,9 +9,10 @@ typedef SheetObjectView GnmCComboView;
 typedef struct {
 	SheetObjectViewClass base;
 
-	gboolean	(*activate)	(SheetObject *so, GtkWidget *popup,   GtkTreeView *list,
-					 WBCGtk *wbcg);
-	GtkWidget *	(*create_list)  (SheetObject *so, GtkTreePath **clip, GtkTreePath **select);
+	gboolean	(*activate)	(SheetObject *so, GtkTreeView *list,
+					 WBCGtk *wbcg, gboolean button);
+	GtkWidget *	(*create_list)  (SheetObject *so, GtkTreePath **clip, GtkTreePath **select,
+					 gboolean *add_buttons);
 	GtkWidget *	(*create_arrow) (SheetObject *so);
 } GnmCComboViewClass;
 
diff --git a/src/widgets/gnm-cell-combo-view.c b/src/widgets/gnm-cell-combo-view.c
index 3dc38e4..d00a407 100644
--- a/src/widgets/gnm-cell-combo-view.c
+++ b/src/widgets/gnm-cell-combo-view.c
@@ -39,7 +39,7 @@
 #define	AUTOSCROLL_ID	"autoscroll-id"
 #define	AUTOSCROLL_DIR	"autoscroll-dir"
 
-static void ccombo_popup_destroy (GtkWidget *popup, GtkWidget *list);
+static void ccombo_popup_destroy (GtkWidget *list);
 
 static GtkWidget *
 ccombo_create_arrow (GnmCComboView *ccombo, SheetObject *so)
@@ -49,28 +49,28 @@ ccombo_create_arrow (GnmCComboView *ccombo, SheetObject *so)
 }
 
 static gboolean
-ccombo_activate (GtkWidget *popup, GtkTreeView *list)
+ccombo_activate (GtkTreeView *list, gboolean button)
 {
 	SheetObjectView		*sov    = g_object_get_data (G_OBJECT (list), SOV_ID);
 	GocItem			*view   = GOC_ITEM (sov);
 	GnmPane			*pane   = GNM_PANE (view->canvas);
 	GnmCComboViewClass	*klass  = GNM_CCOMBO_VIEW_GET_CLASS (sov);
 
-	if ((klass->activate) (sheet_object_view_get_so (sov), popup, list,
-			      scg_wbcg (pane->simple.scg)))
+	if ((klass->activate) (sheet_object_view_get_so (sov), list,
+			       scg_wbcg (pane->simple.scg), button))
 	{
-		ccombo_popup_destroy (popup, GTK_WIDGET (list));
+		ccombo_popup_destroy (GTK_WIDGET (list));
 		return TRUE;
 	}
 	return FALSE;
 }
 
 static GtkWidget *
-ccombo_create_list (GnmCComboView *ccombo,
-		    SheetObject *so, GtkTreePath **clip, GtkTreePath **select)
+ccombo_create_list (GnmCComboView *ccombo, SheetObject *so,
+		    GtkTreePath **clip, GtkTreePath **select, gboolean *make_buttons)
 {
 	GnmCComboViewClass *klass = GNM_CCOMBO_VIEW_GET_CLASS (ccombo);
-	return (klass->create_list) (so, clip, select);
+	return (klass->create_list) (so, clip, select, make_buttons);
 }
 
 /****************************************************************************/
@@ -143,11 +143,11 @@ ccombo_autoscroll_set (GObject *list, int dir)
 }
 
 static void
-ccombo_popup_destroy (GtkWidget *popup, GtkWidget *list)
+ccombo_popup_destroy (GtkWidget *list)
 {
 	ccombo_autoscroll_set (G_OBJECT (list), 0);
 	ccombo_focus_change (list, FALSE);
-	gtk_widget_destroy (popup);
+	gtk_widget_destroy (gtk_widget_get_toplevel (list));
 }
 
 static gint
@@ -155,7 +155,7 @@ cb_ccombo_key_press (GtkWidget *popup, GdkEventKey *event, GtkWidget *list)
 {
 	switch (event->keyval) {
 	case GDK_Escape :
-		ccombo_popup_destroy (popup, list);
+		ccombo_popup_destroy (list);
 		return TRUE;
 
 	case GDK_KP_Down :
@@ -168,7 +168,7 @@ cb_ccombo_key_press (GtkWidget *popup, GdkEventKey *event, GtkWidget *list)
 
 	case GDK_KP_Enter :
 	case GDK_Return :
-		ccombo_activate (popup, GTK_TREE_VIEW (list));
+		ccombo_activate (GTK_TREE_VIEW (list), FALSE);
 		return TRUE;
 	default :
 		;
@@ -228,7 +228,7 @@ cb_ccombo_button_press (GtkWidget *popup, GdkEventButton *event,
 {
 	/* btn1 down outside the popup cancels */
 	if (event->button == 1 && event->window != popup->window) {
-		ccombo_popup_destroy (popup, list);
+		ccombo_popup_destroy (list);
 		return TRUE;
 	}
 	return FALSE;
@@ -239,22 +239,19 @@ cb_ccombo_button_release (GtkWidget *popup, GdkEventButton *event,
 			  GtkTreeView *list)
 {
 	if (event->button == 1) {
-	    if (gtk_get_event_widget ((GdkEvent *) event) == GTK_WIDGET (list))
-		    return ccombo_activate (popup, list);
+		if (gtk_get_event_widget ((GdkEvent *) event) == GTK_WIDGET (list))
+			return ccombo_activate (list, FALSE);
 
-	    g_signal_handlers_disconnect_by_func (popup,
-			G_CALLBACK (cb_ccombo_popup_motion), list);
-	    ccombo_autoscroll_set (G_OBJECT (list), 0);
+		g_signal_handlers_disconnect_by_func (popup,
+						      G_CALLBACK (cb_ccombo_popup_motion), list);
+		ccombo_autoscroll_set (G_OBJECT (list), 0);
 	}
 	return FALSE;
 }
 
-static void
-cb_ccombo_button_pressed (G_GNUC_UNUSED GtkButton *button,
-			  SheetObjectView *sov)
-{
-	gnm_cell_combo_view_popdown (sov, GDK_CURRENT_TIME);
-}
+static void cb_ccombo_button_pressed	(SheetObjectView *sov)	{ gnm_cell_combo_view_popdown (sov, GDK_CURRENT_TIME); }
+static void cb_ccombo_ok_button		(GtkTreeView *list)	{ ccombo_activate (list, TRUE); }
+static void cb_ccombo_cancel_button	(GtkWidget *list)	{ ccombo_popup_destroy (list); }
 
 /**
  * gnm_cell_combo_view_popdown:
@@ -273,6 +270,7 @@ gnm_cell_combo_view_popdown (SheetObjectView *sov, guint32 activate_time)
 	Sheet const	   *sheet  = sheet_object_get_sheet (so);
 	GtkWidget *frame,  *popup, *list, *container;
 	int root_x, root_y;
+	gboolean 	make_buttons = FALSE;
 	GtkTreePath	  *clip = NULL, *select = NULL;
 	GtkRequisition	req;
 	GtkWindow *toplevel = wbcg_toplevel (scg_wbcg (scg));
@@ -286,7 +284,7 @@ gnm_cell_combo_view_popdown (SheetObjectView *sov, guint32 activate_time)
 	gtk_window_set_screen (GTK_WINDOW (popup),
 		gtk_widget_get_screen (GTK_WIDGET (toplevel)));
 
-	list = ccombo_create_list (GNM_CCOMBO_VIEW (sov), so, &clip, &select);
+	list = ccombo_create_list (GNM_CCOMBO_VIEW (sov), so, &clip, &select, &make_buttons);
 
 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE);
 	gtk_widget_size_request (GTK_WIDGET (list), &req);
@@ -317,6 +315,25 @@ gnm_cell_combo_view_popdown (SheetObjectView *sov, guint32 activate_time)
 	} else
 		container = list;
 
+	if (make_buttons) {
+		GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
+		GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
+
+		GtkWidget *button;
+		button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+		g_signal_connect_swapped (button, "clicked",
+			G_CALLBACK (cb_ccombo_cancel_button), list);
+		gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 6);
+		button = gtk_button_new_from_stock (GTK_STOCK_OK);
+		g_signal_connect_swapped (button, "clicked",
+			G_CALLBACK (cb_ccombo_ok_button), list);
+		gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 6);
+
+		gtk_box_pack_start (GTK_BOX (vbox), container, FALSE, TRUE, 6);
+		gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 6);
+		container = vbox;
+	}
+
 	gtk_container_add (GTK_CONTAINER (frame), container);
 
 	/* do the popup */
@@ -402,7 +419,7 @@ gnm_cell_combo_view_new (SheetObject *so, GType type,
 
 	gtk_container_add (GTK_CONTAINER (view_widget),
 		ccombo_create_arrow (GNM_CCOMBO_VIEW (ccombo), so));
-	g_signal_connect (view_widget, "pressed",
+	g_signal_connect_swapped (view_widget, "pressed",
 		G_CALLBACK (cb_ccombo_button_pressed), ccombo);
 	gtk_widget_show_all (view_widget);
 
diff --git a/src/widgets/gnm-filter-combo-view.c b/src/widgets/gnm-filter-combo-view.c
index 6f34e98..50281c5 100644
--- a/src/widgets/gnm-filter-combo-view.c
+++ b/src/widgets/gnm-filter-combo-view.c
@@ -44,8 +44,8 @@
 #include <string.h>
 
 static gboolean
-fcombo_activate (SheetObject *so, GtkWidget *popup, GtkTreeView *list,
-		 WBCGtk *wbcg)
+fcombo_activate (SheetObject *so, GtkTreeView *list, WBCGtk *wbcg,
+		 G_GNUC_UNUSED gboolean button)
 {
 	GnmFilterCombo *fcombo = GNM_FILTER_COMBO (so);
 	GtkTreeIter     iter;
@@ -142,7 +142,8 @@ formatted_value_equal (GnmValue const *a, GnmValue const *b)
 }
 
 static GtkWidget *
-fcombo_create_list (SheetObject *so,  GtkTreePath **clip, GtkTreePath **select)
+fcombo_create_list (SheetObject *so,
+		    GtkTreePath **clip, GtkTreePath **select, gboolean *make_buttons)
 {
 	GnmFilterCombo  *fcombo = GNM_FILTER_COMBO (so);
 	GnmFilter const *filter = fcombo->filter;
diff --git a/src/widgets/gnm-sheet-slicer-combo-view.c b/src/widgets/gnm-sheet-slicer-combo-view.c
index 4104d4b..dc43618 100644
--- a/src/widgets/gnm-sheet-slicer-combo-view.c
+++ b/src/widgets/gnm-sheet-slicer-combo-view.c
@@ -46,11 +46,13 @@ enum {
 };
 
 static gboolean
-sscombo_activate (SheetObject *so, GtkWidget *popup, GtkTreeView *list,
-		 WBCGtk *wbcg)
+sscombo_activate (SheetObject *so, GtkTreeView *list, WBCGtk *wbcg, gboolean button)
 {
 	GtkTreeIter	    iter;
 
+	if (!button)
+		return FALSE;
+
 	if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (list), NULL, &iter)) {
 		char		*strval;
 		gtk_tree_model_get (gtk_tree_view_get_model (list), &iter,
@@ -64,7 +66,7 @@ sscombo_activate (SheetObject *so, GtkWidget *popup, GtkTreeView *list,
 #endif
 		g_free (strval);
 	}
-	return FALSE;
+	return TRUE;
 }
 
 static void
@@ -84,7 +86,8 @@ cb_filter_toggle (GtkCellRendererToggle *cell,
 }
 
 static GtkWidget *
-sscombo_create_list (SheetObject *so, GtkTreePath **clip, GtkTreePath **select)
+sscombo_create_list (SheetObject *so,
+		     GtkTreePath **clip, GtkTreePath **select, gboolean *make_buttons)
 {
 	GnmSheetSlicerCombo *sscombo = GNM_SHEET_SLICER_COMBO (so);
 	GODataCacheField const *dcf  = go_data_slicer_field_get_cache_field (sscombo->dsf);
@@ -92,9 +95,11 @@ sscombo_create_list (SheetObject *so, GtkTreePath **clip, GtkTreePath **select)
 	GtkTreeIter	 iter;
 	GtkCellRenderer *renderer;
 	GtkWidget	*list;
-	GOValArray const *vals;
+	GOValArray const*vals;
+	GOVal const	*v;
 	GString		*str;
 	unsigned i;
+	GODateConventions const *dconv = workbook_date_conv (sscombo->parent.sv->sheet->workbook);
 
 	vals = go_data_cache_field_get_vals (dcf, TRUE);
 	if (NULL == vals)
@@ -105,13 +110,14 @@ sscombo_create_list (SheetObject *so, GtkTreePath **clip, GtkTreePath **select)
 		G_TYPE_BOOLEAN, G_TYPE_STRING);
 	str = g_string_sized_new (20);
 	for (i = 0; i < vals->len ; i++) {
-		if (GO_FORMAT_NUMBER_OK == format_value_gstring (str, NULL,
-			g_ptr_array_index (vals, i), NULL, -1,
-			workbook_date_conv (sscombo->parent.sv->sheet->workbook))) {
-			gtk_list_store_append (model, &iter);
-			gtk_list_store_set (model, &iter, 0, TRUE, 1, str->str, -1);
-			g_string_truncate (str, 0);
-		}
+		v = g_ptr_array_index (vals, i);
+		gtk_list_store_append (model, &iter);
+		if (VALUE_IS_EMPTY(v))
+			g_string_assign (str, _("<Blank>"));
+		else if (GO_FORMAT_NUMBER_OK != format_value_gstring (str, NULL, v, NULL, -1, dconv))
+			g_string_assign (str, "<ERROR>");
+		gtk_list_store_set (model, &iter, 0, TRUE, 1, str->str, -1);
+		g_string_truncate (str, 0);
 	}
 	list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
 	g_object_unref (model);
@@ -127,6 +133,9 @@ sscombo_create_list (SheetObject *so, GtkTreePath **clip, GtkTreePath **select)
 		gtk_tree_view_column_new_with_attributes ("ID",
 			gtk_cell_renderer_text_new (), "text", SSCOMBO_COL_NAME,
 			NULL));
+
+	*make_buttons = TRUE;
+
 	return list;
 }
 
@@ -151,22 +160,22 @@ sscombo_ccombo_init (GnmCComboViewIface void *ccombo_iface)
 static void
 sscombo_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	GocItem *view = GOC_ITEM (sov);
+	GocGroup *view = GOC_GROUP (sov);
 
 	if (visible) {
 		double h = (coords[3] - coords[1]) + 1.;
 		if (h > 20.)	/* clip vertically */
 			h = 20.;
-		goc_item_set (view,
+		goc_item_set (GOC_ITEM (view->children->data),
 			/* put it outside the cell */
 			"x",	  ((coords[2] >= 0.) ? coords[2] : (coords[0]-h+1.)),
 			"y",	  coords [3] - h + 1.,
 			"width",  h,	/* force a square, use h for width too */
 			"height", h,
 			NULL);
-		goc_item_show (view);
+		goc_item_show (GOC_ITEM (view));
 	} else
-		goc_item_hide (view);
+		goc_item_hide (GOC_ITEM (view));
 }
 
 static void
diff --git a/src/widgets/gnm-validation-combo-view.c b/src/widgets/gnm-validation-combo-view.c
index b0c77e9..db5f897 100644
--- a/src/widgets/gnm-validation-combo-view.c
+++ b/src/widgets/gnm-validation-combo-view.c
@@ -46,8 +46,8 @@
 #include <string.h>
 
 static gboolean
-vcombo_activate (SheetObject *so, GtkWidget *popup, GtkTreeView *list,
-		 WBCGtk *wbcg)
+vcombo_activate (SheetObject *so, GtkTreeView *list, WBCGtk *wbcg,
+		 G_GNUC_UNUSED gboolean button)
 {
 	GnmValidationCombo *vcombo = GNM_VALIDATION_COMBO (so);
 	GtkTreeIter	    iter;
@@ -88,7 +88,8 @@ cb_hash_domain (GnmValue *key, gpointer value, gpointer accum)
 }
 
 static GtkWidget *
-vcombo_create_list (SheetObject *so, GtkTreePath **clip, GtkTreePath **select)
+vcombo_create_list (SheetObject *so,
+		    GtkTreePath **clip, GtkTreePath **select, gboolean *make_buttons)
 {
 	GnmValidationCombo *vcombo = GNM_VALIDATION_COMBO (so);
 	unsigned	 i;
@@ -185,22 +186,22 @@ vcombo_create_arrow (G_GNUC_UNUSED SheetObject *so)
 static void
 vcombo_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	GocItem *view = GOC_ITEM (sov);
+	GocGroup *view = GOC_GROUP (sov);
 
 	if (visible) {
 		double h = (coords[3] - coords[1]) + 1.;
 		if (h > 20.)	/* clip vertically */
 			h = 20.;
-		goc_item_set (view,
+		goc_item_set (GOC_ITEM (view->children->data),
 			/* put it outside the cell */
 			"x",	  ((coords[2] >= 0.) ? coords[2] : (coords[0]-h+1.)),
 			"y",	  coords [3] - h + 1.,
 			"width",  h,	/* force a square, use h for width too */
 			"height", h,
 			NULL);
-		goc_item_show (view);
+		goc_item_show (GOC_ITEM (view));
 	} else
-		goc_item_hide (view);
+		goc_item_hide (GOC_ITEM (view));
 }
 
 /****************************************************************************/
diff --git a/src/widgets/gnumeric-expr-entry.c b/src/widgets/gnumeric-expr-entry.c
index 1b5bc7d..6daf732 100644
--- a/src/widgets/gnumeric-expr-entry.c
+++ b/src/widgets/gnumeric-expr-entry.c
@@ -31,6 +31,7 @@
 #include <gnm-format.h>
 #include <number-match.h>
 #include <gnm-datetime.h>
+#include <gnumeric-gconf.h>
 #include <goffice/goffice.h>
 
 #include <gsf/gsf-impl-utils.h>
@@ -548,6 +549,7 @@ cb_gee_key_press_event (GtkEntry	*entry,
 			GnmExprEntry	*gee)
 {
 	WBCGtk *wbcg  = gee->wbcg;
+	gboolean is_enter = FALSE;
 	int state = gnumeric_filter_modifiers (event->state);
 
 	switch (event->keyval) {
@@ -603,10 +605,7 @@ cb_gee_key_press_event (GtkEntry	*entry,
 		return TRUE;
 
 	case GDK_KP_Enter:
-	case GDK_Return: {
-		SheetView *sv;
-		WBCEditResult result;
-
+	case GDK_Return:
 		if (gee->is_cell_renderer)
 			return FALSE;
 		/* Is this the right way to append a newline ?? */
@@ -621,44 +620,45 @@ cb_gee_key_press_event (GtkEntry	*entry,
 		if (!wbcg_is_editing (wbcg))
 			break;
 
-		/* Be careful to use the editing sheet */
-		sv = sheet_get_view (wbcg->editing_sheet,
-			wb_control_view (WORKBOOK_CONTROL (wbcg)));
-
-		if (state & GDK_CONTROL_MASK)
-			result = (state & GDK_SHIFT_MASK) ? WBC_EDIT_ACCEPT_ARRAY : WBC_EDIT_ACCEPT_RANGE;
-		else
-			result = WBC_EDIT_ACCEPT;
-		/* move the edit pos for normal entry */
-		if (wbcg_edit_finish (wbcg, result, NULL) && result == WBC_EDIT_ACCEPT) {
-			gboolean const direction = (event->state & GDK_SHIFT_MASK) ? FALSE : TRUE;
-			sv_selection_walk_step (sv, direction, FALSE);
-			sv_update (sv);
-		}
-		return TRUE;
-	}
+		is_enter = TRUE;
+		/* fall through */
 
-	case GDK_Tab: {
+	case GDK_Tab:
+	case GDK_ISO_Left_Tab:
+	case GDK_KP_Tab: {
 		SheetView *sv;
 		WBCEditResult result;
 
-		if (gee->is_cell_renderer)
-			return FALSE;
-
-		if (!wbcg_is_editing (wbcg))
-			break;
+		if (is_enter && (state & GDK_CONTROL_MASK))
+			result = (state & GDK_SHIFT_MASK) ? WBC_EDIT_ACCEPT_ARRAY : WBC_EDIT_ACCEPT_RANGE;
+		else
+			result = WBC_EDIT_ACCEPT;
 
-		/* Be careful to use the editing sheet */
+		/* Be careful to restore the editing sheet if we are editing */
 		sv = sheet_get_view (wbcg->editing_sheet,
 			wb_control_view (WORKBOOK_CONTROL (wbcg)));
 
-		result = WBC_EDIT_ACCEPT;
-		
-                /* move the edit pos for normal entry */
+		/* move the edit pos for normal entry */
 		if (wbcg_edit_finish (wbcg, result, NULL) && result == WBC_EDIT_ACCEPT) {
-			gboolean const direction = (event->state & GDK_SHIFT_MASK) ? FALSE : TRUE;
-			sv_selection_walk_step (sv, direction, TRUE);
-			sv_update (sv);
+			GODirection dir = gnm_conf_get_core_gui_editing_enter_moves_dir ();
+			if (!is_enter || dir != GO_DIRECTION_NONE) {
+				gboolean forward = TRUE;
+				gboolean horizontal = TRUE;
+				if (is_enter) {
+					horizontal = go_direction_is_horizontal (dir);
+					forward = go_direction_is_forward (dir);
+				}
+
+				if (event->state & GDK_SHIFT_MASK)
+					forward = !forward;
+
+				sv_selection_walk_step (sv, forward, horizontal);
+
+				/* invalidate, in case Enter direction changes */
+				if (is_enter)
+					sv->first_tab_col = -1;
+				sv_update (sv);
+			}
 		}
 		return TRUE;
 	}
diff --git a/tools/win32/Makefile.am b/tools/win32/Makefile.am
index 9bf677c..c6e7c05 100755
--- a/tools/win32/Makefile.am
+++ b/tools/win32/Makefile.am
@@ -1,11 +1,11 @@
 export start module target
 
-all: debug
+all: moduleset gnumeric.nsi
 
-debug:: moduleset gnumeric.nsi
+debug:: all
 	$(abs_srcdir)/build $(abs_builddir) $(abs_srcdir) debug
 
-release:: moduleset gnumeric.nsi
+release:: all
 	$(abs_srcdir)/build $(abs_builddir) $(abs_srcdir) release
 
 clean:



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