[gnumeric] Use GocCanvas instead of FooCanvas



commit 393e66d8a020d552380028a54b3b25a62e2d62db
Author: Jean Brefort <jean brefort normalesup org>
Date:   Tue Aug 25 19:42:46 2009 +0200

    Use GocCanvas instead of FooCanvas

 ChangeLog                                          |   42 +
 NEWS                                               |    3 +
 po/POTFILES.in                                     |    4 +-
 src/Makefile.am                                    |    4 -
 src/cell-draw.c                                    |   41 +-
 src/cell-draw.h                                    |    2 +-
 src/dialogs/dialog-autoformat.c                    |   51 +-
 src/dialogs/dialog-cell-format.c                   |  108 ++--
 src/dialogs/dialog-printer-setup.c                 |    5 -
 src/gnm-pane-impl.h                                |   18 +-
 src/gnm-pane.c                                     |  938 +++++++++-----------
 src/gnm-pane.h                                     |   48 +-
 src/gnm-sheet-slicer-combo.c                       |    6 +-
 src/gnm-so-filled.c                                |  158 ++--
 src/gnm-so-line.c                                  |   77 +-
 src/gnm-so-polygon.c                               |   88 +--
 src/gnumeric-simple-canvas.c                       |   31 +-
 src/gnumeric-simple-canvas.h                       |   12 +-
 src/gui-util.c                                     |   10 +-
 src/gui-util.h                                     |    4 +-
 src/item-acetate.c                                 |   44 -
 src/item-acetate.h                                 |   17 -
 src/item-bar.c                                     |  597 ++++++-------
 src/item-bar.h                                     |    1 +
 src/item-cursor.c                                  |  942 ++++++++------------
 src/item-cursor.h                                  |    1 +
 src/item-debug.c                                   |   13 -
 src/item-debug.h                                   |   29 -
 src/item-edit.c                                    |  440 +++++-----
 src/item-grid.c                                    |  427 +++++-----
 src/item-grid.h                                    |    1 +
 src/pattern.c                                      |  170 +---
 src/pattern.h                                      |    5 +-
 src/preview-grid-impl.h                            |    8 +-
 src/preview-grid.c                                 |  130 +--
 src/sheet-control-gui.c                            |  274 +++----
 src/sheet-control-gui.h                            |    4 +-
 src/sheet-filter.c                                 |   12 +-
 src/sheet-object-cell-comment.c                    |  174 ++--
 src/sheet-object-graph.c                           |   54 +-
 src/sheet-object-image.c                           |   46 +-
 src/sheet-object-impl.h                            |   13 +-
 src/sheet-object-widget.c                          |   73 +-
 src/sheet-object.c                                 |   92 ++-
 src/sheet-object.h                                 |    6 +
 src/style-border.c                                 |  220 +++--
 src/style-border.h                                 |    4 +-
 src/style-color.c                                  |    2 +-
 src/validation.c                                   |   12 +-
 src/wbc-gtk-edit.c                                 |    8 +-
 src/widgets/ChangeLog                              |   48 +
 src/widgets/Makefile.am                            |   18 +-
 src/widgets/gnm-cell-combo-foo-view-impl.h         |   26 -
 src/widgets/gnm-cell-combo-foo-view.h              |   11 -
 src/widgets/gnm-cell-combo-view-impl.h             |   28 +
 ...cell-combo-foo-view.c => gnm-cell-combo-view.c} |   71 +-
 src/widgets/gnm-cell-combo-view.h                  |   12 +
 src/widgets/gnm-filter-combo-foo-view.h            |    8 -
 ...er-combo-foo-view.c => gnm-filter-combo-view.c} |   52 +-
 src/widgets/gnm-filter-combo-view.h                |    9 +
 ...bo-foo-view.c => gnm-sheet-slicer-combo-view.c} |   47 +-
 ...bo-foo-view.h => gnm-sheet-slicer-combo-view.h} |    2 +-
 src/widgets/gnm-validation-combo-foo-view.h        |    8 -
 ...ombo-foo-view.c => gnm-validation-combo-view.c} |   56 +-
 src/widgets/gnm-validation-combo-view.h            |    9 +
 src/widgets/gnumeric-dashed-canvas-line.c          |   81 +-
 src/widgets/gnumeric-dashed-canvas-line.h          |   16 +-
 src/widgets/widget-font-selector.c                 |   26 +-
 src/widgets/widget-font-selector.h                 |    1 -
 69 files changed, 2714 insertions(+), 3284 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 534b136..c033c62 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2009-08-25  Jean Brefort  <jean brefort normalesup org>
+
+	* src/cell-draw.c: use GocCanvas ibstead of FooCanvas
+	* src/cell-draw.h: ditto.
+	* src/gnm-pane-impl.h: ditto.
+	* src/gnm-pane.c: ditto.
+	* src/gnm-pane.h: ditto.
+	* src/gnm-sheet-slicer-combo.c: ditto.
+	* src/gnm-so-filled.c: ditto.
+	* src/gnm-so-line.c: ditto.
+	* src/gnm-so-polygon.c: ditto.
+	* src/gnumeric-simple-canvas.c: ditto.
+	* src/gnumeric-simple-canvas.h: ditto.
+	* src/gui-util.c: ditto.
+	* src/gui-util.h: ditto.
+	* src/item-bar.c: ditto.
+	* src/item-bar.h: ditto.
+	* src/item-cursor.c: ditto.
+	* src/item-cursor.h: ditto.
+	* src/item-edit.c: ditto.
+	* src/item-grid.c: ditto.
+	* src/item-grid.h: ditto.
+	* src/pattern.c: ditto.
+	* src/pattern.h: ditto.
+	* src/preview-grid-impl.h: ditto.
+	* src/preview-grid.c: ditto.
+	* src/sheet-control-gui.c: ditto.
+	* src/sheet-control-gui.h: ditto.
+	* src/sheet-filter.c: ditto.
+	* src/sheet-object-cell-comment.c: ditto.
+	* src/sheet-object-graph.c: ditto.
+	* src/sheet-object-image.c: ditto.
+	* src/sheet-object-impl.h: ditto.
+	* src/sheet-object-widget.c: ditto.
+	* src/sheet-object.c: ditto.
+	* src/sheet-object.h: ditto.
+	* src/style-border.c: ditto.
+	* src/style-border.h: ditto.
+	* src/style-color.c: ditto.
+	* src/validation.c: ditto.
+	* src/wbc-gtk-edit.c: ditto.
+
 2009-08-21  Morten Welinder  <terra gnome org>
 
 	* src/wbc-gtk-actions.c (insert_date_time_common): Rewrite to work
diff --git a/NEWS b/NEWS
index fa75f05..d7b3fc2 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ Andreas:
 	* Add AVERAGEIF, MUNIT, RRI, SEARCHB, REPLACEB.
 	* Improve import of ODF functions
 
+Jean:
+	* Use GocCanvas instead of FooCanvas.
+
 Morten:
 	* Add GAMMA.
 	* Fix Insert-Date+Time.  [#592545]
diff --git a/po/POTFILES.in b/po/POTFILES.in
index eb9902b..61b316d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -330,9 +330,9 @@ src/value.c
 src/wbc-gtk-actions.c
 src/wbc-gtk-edit.c
 src/wbc-gtk.c
-src/widgets/gnm-cell-combo-foo-view.c
+src/widgets/gnm-cell-combo-view.c
 src/widgets/gnm-dao.c
-src/widgets/gnm-filter-combo-foo-view.c
+src/widgets/gnm-filter-combo-view.c
 src/widgets/gnm-format-sel.c
 src/widgets/gnm-validation-combo-foo-view.c
 src/widgets/gnumeric-cell-renderer-expr-entry.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 0fade90..a975434 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -124,10 +124,8 @@ libspreadsheet_la_SOURCES =			\
 	hlink.c					\
 	history.c				\
 	input-msg.c				\
-	item-acetate.c				\
 	item-bar.c				\
 	item-cursor.c				\
-	item-debug.c				\
 	item-edit.c				\
 	item-grid.c				\
 	libgnumeric.c				\
@@ -248,10 +246,8 @@ libspreadsheet_include_HEADERS = 	\
 	hlink-impl.h				\
 	history.h				\
 	input-msg.h				\
-	item-acetate.h				\
 	item-bar.h				\
 	item-cursor.h				\
-	item-debug.h				\
 	item-edit.h				\
 	item-grid.h				\
 	libgnumeric.h				\
diff --git a/src/cell-draw.c b/src/cell-draw.c
index 74bf552..003b1ad 100644
--- a/src/cell-draw.c
+++ b/src/cell-draw.c
@@ -276,8 +276,7 @@ cell_finish_layout (GnmCell *cell, GnmRenderedValue *rv,
 /**
  * cell_draw:
  * @cell : #GnmCell const
- * @gc   : #GdkGC
- * @drawable : #GdkDrawable
+ * @cr   : #cairo_t
  * @x1 :
  * @y1 :
  * @width : including margins and leading grid line
@@ -285,7 +284,7 @@ cell_finish_layout (GnmCell *cell, GnmRenderedValue *rv,
  * @h_center :
  **/
 void
-cell_draw (GnmCell const *cell, GdkGC *gc, GdkDrawable *drawable,
+cell_draw (GnmCell const *cell, cairo_t *cr,
 	   int x1, int y1, int width, int height, int h_center)
 {
 	GOColor fore_color;
@@ -309,15 +308,13 @@ cell_draw (GnmCell const *cell, GdkGC *gc, GdkDrawable *drawable,
 			      height * PANGO_SCALE,
 			      h_center == -1 ? -1 : (h_center * PANGO_SCALE),
 			      &fore_color, &x, &y)) {
-		GdkColor fore_gdk;
 
 		/* +1 to get past left grid-line.  */
-		GdkRectangle rect;
-		rect.x = x1 + 1 + GNM_COL_MARGIN;
-		rect.y = y1 + 1 + GNM_ROW_MARGIN;
-		rect.width = width;
-		rect.height = height;
+		cairo_rectangle (cr, x1 + 1 + GNM_COL_MARGIN,
+				 y1 + 1 + GNM_ROW_MARGIN,
+				 width, height);
 
+		cairo_save (cr);
 #if 0
 		gdk_gc_set_clip_rectangle (gc, &rect);
 		if (cell->pos.col == 3 && cell->pos.row == 10) {
@@ -334,12 +331,11 @@ cell_draw (GnmCell const *cell, GdkGC *gc, GdkDrawable *drawable,
 		 * approximation to the right effect.  (The right way
 		 * would be to create a proper cellspan type.)
 		 */
-		gdk_gc_set_clip_rectangle (gc,
-					   rv->rotation ? NULL : &rect);
+		if (!rv->rotation)
+			cairo_clip (cr);
 
 		/* See http://bugzilla.gnome.org/show_bug.cgi?id=105322 */
-		go_color_to_gdk (fore_color, &fore_gdk);
-		gdk_gc_set_rgb_fg_color (gc, &fore_gdk);
+		cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (fore_color));
 
 		if (rv->rotation) {
 			GnmRenderedRotatedValue *rrv = (GnmRenderedRotatedValue *)rv;
@@ -352,17 +348,18 @@ cell_draw (GnmCell const *cell, GdkGC *gc, GdkDrawable *drawable,
 			for (lines = pango_layout_get_lines (rv->layout);
 			     lines;
 			     lines = lines->next, li++) {
-				gdk_draw_layout_line (drawable, gc,
-					x1 + PANGO_PIXELS (x + li->dx),
-					y1 + PANGO_PIXELS (y + li->dy),
-					lines->data);
+				cairo_save (cr);
+				cairo_translate (cr, x1 + PANGO_PIXELS (x + li->dx), y1 + PANGO_PIXELS (y + li->dy));
+				cairo_rotate (cr, -rv->rotation * M_PI / 180);
+				pango_cairo_show_layout_line (cr, lines->data);
+				cairo_restore (cr);
 			}
 			pango_context_set_matrix (context, NULL);
 			pango_layout_context_changed (rv->layout);
-		} else
-			gdk_draw_layout (drawable, gc,
-				x1 + PANGO_PIXELS (x),
-				y1 + PANGO_PIXELS (y),
-				rv->layout);
+		} else {
+			cairo_translate (cr, x1 + PANGO_PIXELS (x), y1 + PANGO_PIXELS (y));
+			pango_cairo_show_layout (cr, rv->layout);
+		}
+		cairo_restore (cr);
 	}
 }
diff --git a/src/cell-draw.h b/src/cell-draw.h
index 03b87be..fbaa5c6 100644
--- a/src/cell-draw.h
+++ b/src/cell-draw.h
@@ -15,7 +15,7 @@ void cell_finish_layout (GnmCell *cell, GnmRenderedValue *rv,
 			 int col_width,
 			 gboolean inhibit_overflow);
 
-void cell_draw (GnmCell const *cell, GdkGC *gc, GdkDrawable *drawable,
+void cell_draw (GnmCell const *cell, cairo_t* cr,
 		int x, int y, int height, int width, int h_center);
 
 G_END_DECLS
diff --git a/src/dialogs/dialog-autoformat.c b/src/dialogs/dialog-autoformat.c
index 3829c98..810327b 100644
--- a/src/dialogs/dialog-autoformat.c
+++ b/src/dialogs/dialog-autoformat.c
@@ -45,7 +45,7 @@
 #include <selection.h>
 #include <ranges.h>
 
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-rect-ellipse.h>
+#include <goffice/goffice.h>
 #include <glade/glade.h>
 #include <gtk/gtk.h>
 #include <gsf/gsf-impl-utils.h>
@@ -80,10 +80,10 @@ typedef struct {
 	Workbook           *wb;                              /* Workbook we are working on */
 	WBCGtk *wbcg;
 	GladeXML	   *gui;
-	FooCanvasItem	   *grid[NUM_PREVIEWS];              /* Previewgrid's */
-	FooCanvasItem	   *selrect;                         /* Selection rectangle */
+	GocItem		   *grid[NUM_PREVIEWS];              /* Previewgrid's */
+	GocItem		   *selrect;                         /* Selection rectangle */
 	GSList             *templates;                       /* List of GnmFormatTemplate's */
-	GnmFormatTemplate     *selected_template;               /* The currently selected template */
+	GnmFormatTemplate  *selected_template;               /* The currently selected template */
 	GList              *category_groups;                 /* List of groups of categories */
 
 	FormatTemplateCategoryGroup *current_category_group; /* Currently selected category group */
@@ -100,7 +100,7 @@ typedef struct {
 
 	GtkComboBox    *category;
 
-	FooCanvas	 *canvas[NUM_PREVIEWS];
+	GocCanvas	 *canvas[NUM_PREVIEWS];
 	GtkFrame         *frame[NUM_PREVIEWS];
 	GtkVScrollbar    *scroll;
 	GtkCheckMenuItem *gridlines;
@@ -166,11 +166,11 @@ static GSF_CLASS (AutoFormatGrid, auto_format_grid,
 		  auto_format_grid_class_init, NULL,
 		  preview_grid_get_type())
 
-static FooCanvasItem *
+static GocItem *
 auto_format_grid_new (AutoFormatState *state, int i, GnmFormatTemplate *ft)
 {
-	FooCanvasItem *item = foo_canvas_item_new (
-		foo_canvas_root (state->canvas[i]),
+	GocItem *item = goc_item_new (
+		goc_canvas_get_root (state->canvas[i]),
 		auto_format_grid_get_type (),
 		"render-gridlines",	state->gridlines->active,
 		"default-col-width",	DEFAULT_COL_WIDTH,
@@ -326,27 +326,26 @@ previews_load (AutoFormatState *state, int topindex)
 
 			/* Are we selected? Then draw a selection rectangle */
 			if (topindex + i == state->preview_index) {
+				GOStyle *style;
 				g_return_if_fail (state->selrect == NULL);
 
-				state->selrect = foo_canvas_item_new (foo_canvas_root (state->canvas[i]),
-					FOO_TYPE_CANVAS_RECT,
-					"x1", (double)(-INNER_BORDER),
-					"y1", (double)(-INNER_BORDER),
-					"x2", (double)(TOTAL_WIDTH + INNER_BORDER),
-					"y2", (double)(TOTAL_HEIGHT + INNER_BORDER),
-					"width-pixels", (int) 3,
-					"outline-color", "red",
-					"fill-color", NULL,
+				state->selrect = goc_item_new (goc_canvas_get_root (state->canvas[i]),
+					GOC_TYPE_RECTANGLE,
+					"x", (double)(-INNER_BORDER),
+					"y", (double)(-INNER_BORDER),
+					"width", (double)(TOTAL_WIDTH + 2 * INNER_BORDER),
+					"height", (double)(TOTAL_HEIGHT + 2 * INNER_BORDER),
 					NULL);
+				style = go_styled_object_get_style (GO_STYLED_OBJECT (state->selrect));
+				style->outline.width = 3.;
+				style->outline.color = RGBA_RED;
+				style->fill.pattern.back = 0;
+				
 				gtk_frame_set_shadow_type (state->frame[i], GTK_SHADOW_IN);
 			} else
 				gtk_frame_set_shadow_type (state->frame[i], GTK_SHADOW_ETCHED_IN);
 
-			foo_canvas_set_scroll_region (state->canvas[i],
-				-BORDER, -BORDER,
-				TOTAL_WIDTH + BORDER,
-				TOTAL_HEIGHT + BORDER);
-			foo_canvas_scroll_to (state->canvas[i],
+			goc_canvas_scroll_to (state->canvas[i],
 				-BORDER, -BORDER);
 
 			go_widget_set_tooltip_text
@@ -394,7 +393,7 @@ cb_scroll_value_changed (GtkAdjustment *adjustment, AutoFormatState *state)
 }
 
 static gboolean
-cb_canvas_button_press (FooCanvas *canvas,
+cb_canvas_button_press (GocCanvas *canvas,
 			G_GNUC_UNUSED GdkEventButton *event,
 			AutoFormatState *state)
 {
@@ -455,7 +454,7 @@ cb_check_item_toggled (G_GNUC_UNUSED GtkCheckMenuItem *item,
 	}
 
 	for (i = 0; i < NUM_PREVIEWS; i++)
-		foo_canvas_request_redraw (state->canvas [i],
+		goc_canvas_invalidate (state->canvas [i],
 			-2, -2, INT_MAX/2, INT_MAX/2);
 }
 
@@ -512,7 +511,7 @@ cb_canvas_focus (GtkWidget *canvas, GtkDirectionType direction,
 {
 	if (!GTK_WIDGET_HAS_FOCUS (canvas)) {
 		gtk_widget_grab_focus (canvas);
-		cb_canvas_button_press (FOO_CANVAS (canvas), NULL, state);
+		cb_canvas_button_press (GOC_CANVAS (canvas), NULL, state);
 		return TRUE;
 	}
 	return FALSE;
@@ -586,7 +585,7 @@ dialog_autoformat (WBCGtk *wbcg)
 		state->frame[i] = GTK_FRAME (glade_xml_get_widget (gui, name));
 		g_free (name);
 
-		state->canvas[i] = FOO_CANVAS (foo_canvas_new ());
+		state->canvas[i] = GOC_CANVAS (g_object_new (GOC_TYPE_CANVAS, NULL));
 		gtk_widget_set_size_request (GTK_WIDGET (state->canvas[i]),
 			TOTAL_WIDTH + (2 * BORDER),
 			TOTAL_HEIGHT + (2 * BORDER));
diff --git a/src/dialogs/dialog-cell-format.c b/src/dialogs/dialog-cell-format.c
index fe8ebd7..2d1d9b3 100644
--- a/src/dialogs/dialog-cell-format.c
+++ b/src/dialogs/dialog-cell-format.c
@@ -56,8 +56,9 @@
 #include <style-conditions.h>
 
 #include <goffice/goffice.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-util.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-rect-ellipse.h>
+#include <goffice/canvas/goc-canvas.h>
+#include <goffice/canvas/goc-item.h>
+#include <goffice/canvas/goc-rectangle.h>
 #include <glade/glade.h>
 #include <gtk/gtk.h>
 
@@ -150,10 +151,10 @@ typedef struct _FormatState {
 		ColorPicker      color;
 	} font;
 	struct {
-		FooCanvas	*canvas;
+		GocCanvas	*canvas;
 		GtkButton	*preset[BORDER_PRESET_MAX];
-		FooCanvasItem	*back;
-		FooCanvasItem *lines[20];
+		GocItem		*back;
+		GocItem		*lines[20];
 
 		BorderPicker	 edge[GNM_STYLE_BORDER_EDGE_MAX];
 		ColorPicker      color;
@@ -162,7 +163,7 @@ typedef struct _FormatState {
 		PatternPicker	 pattern;
 	} border;
 	struct {
-		FooCanvas	*canvas;
+		GocCanvas	*canvas;
 		PreviewGrid     *grid;
 		GnmStyle        *style;
 
@@ -906,7 +907,7 @@ back_style_changed (FormatState *state)
 		gnm_style_merge_element (state->result, state->back.style, MSTYLE_PATTERN);
 		gnm_style_merge_element (state->result, state->back.style, MSTYLE_COLOR_BACK);
 		gnm_style_merge_element (state->result, state->back.style, MSTYLE_COLOR_PATTERN);
-		foo_canvas_item_set (FOO_CANVAS_ITEM (state->back.grid),
+		goc_item_set (GOC_ITEM (state->back.grid),
 			"default-style",	state->back.style,
 			NULL);
 	}
@@ -966,18 +967,17 @@ fmt_dialog_init_background_page (FormatState *state)
 	int w = 120;
 	int h = 60;
 
-	widget = foo_canvas_new ();
-	state->back.canvas = FOO_CANVAS (widget);
+	widget = g_object_new (GOC_TYPE_CANVAS, NULL);
+	state->back.canvas = GOC_CANVAS (widget);
 	gtk_widget_set_size_request (widget, w, h);
-	foo_canvas_set_scroll_region (state->back.canvas, -1, -1, w, h);
 
 	widget = glade_xml_get_widget (state->gui, "back_sample_frame");
 	gtk_container_add (GTK_CONTAINER (widget),
 		GTK_WIDGET (state->back.canvas));
 	gtk_widget_show_all (widget);
 
-	state->back.grid = PREVIEW_GRID (foo_canvas_item_new (
-		foo_canvas_root (state->back.canvas),
+	state->back.grid = PREVIEW_GRID (goc_item_new (
+		goc_canvas_get_root (state->back.canvas),
 		preview_grid_get_type (),
 		"render-gridlines",	FALSE,
 		"default-col-width",	w,
@@ -1104,10 +1104,8 @@ border_format_has_changed (FormatState *state, BorderPicker *edge)
 		for (i = 0; line_info[i].states != 0 ; ++i ) {
 			if (line_info[i].location == edge->index &&
 			    state->border.lines[i] != NULL)
-				foo_canvas_item_set (
-					FOO_CANVAS_ITEM (state->border.lines[i]),
-					"fill-color-rgba", edge->rgba,
-					NULL);
+				go_styled_object_get_style (
+					GO_STYLED_OBJECT (state->border.lines[i]))->line.color = edge->rgba;
 		}
 	}
 	if ((int)edge->pattern_index != state->border.pattern.cur_index) {
@@ -1246,35 +1244,36 @@ draw_border_preview (FormatState *state)
 	    { R+1., H-5., R+1., H, R+5., H },
 	    { R+1., H+5., R+1., H, R+5., H }
 	};
-	int i, j;
+	int i, j, k;
 
 	/* The first time through lets initialize */
 	if (state->border.canvas == NULL) {
-		FooCanvasGroup  *group;
-		FooCanvasPoints *points;
+		GocGroup  *group;
+		GocPoints *points;
+		GOStyle *style;
 
-		state->border.canvas = FOO_CANVAS (foo_canvas_new ());
+		state->border.canvas = GOC_CANVAS (g_object_new (GOC_TYPE_CANVAS, NULL));
 		gtk_widget_show (GTK_WIDGET (state->border.canvas));
 		gtk_widget_set_size_request (GTK_WIDGET (state->border.canvas),
 					     150, 100);
 		gtk_container_add (GTK_CONTAINER (glade_xml_get_widget (state->gui, "border_sample_container")),
 				   GTK_WIDGET (state->border.canvas));
-		group = FOO_CANVAS_GROUP (foo_canvas_root (state->border.canvas));
+		group = GOC_GROUP (goc_canvas_get_root (state->border.canvas));
 
 		g_signal_connect (G_OBJECT (state->border.canvas),
 			"button-press-event",
 			G_CALLBACK (border_event), state);
 
-		state->border.back = foo_canvas_item_new (group,
-			FOO_TYPE_CANVAS_RECT,
-			"x1", L-10.,	"y1", T-10.,
-			"x2", R+10.,	"y2", B+10.,
-			"width-pixels", (int) 0,
-			"fill-color",	"white",
+		state->border.back = goc_item_new (group,
+			GOC_TYPE_RECTANGLE,
+			"x", L-10.,		"y", T-10.,
+			"width", R-L+20.,	"height", B-T+20.,
 			NULL);
+		style = go_styled_object_get_style (GO_STYLED_OBJECT (state->border.back));
+		style->outline.dash_type = GO_LINE_NONE;
 
 		/* Draw the corners */
-		points = foo_canvas_points_new (3);
+		points = goc_points_new (3);
 
 		for (i = 0; i < 12 ; ++i) {
 			if (i >= 8) {
@@ -1285,45 +1284,48 @@ draw_border_preview (FormatState *state)
 					continue;
 			}
 
-			for (j = 6 ; --j >= 0 ;)
-				points->coords[j] = corners[i][j];
+			for (j = 3, k = 5 ; --j >= 0 ;) {
+				points->points[j].y = corners[i][k--] + .5;
+				points->points[j].x = corners[i][k--] + .5;
+			}
+				
 
-			foo_canvas_item_new (group,
-					       foo_canvas_line_get_type (),
-					       "width-pixels",	(int) 0,
-					       "fill-color",	"gray63",
+			style = go_styled_object_get_style (GO_STYLED_OBJECT (
+				goc_item_new (group,
+					       goc_polyline_get_type (),
 					       "points",	points,
-					       NULL);
+					       NULL)));
+			style->line.color = RGBA_TO_UINT (0xa1, 0xa1, 0xa1, 0xff); /* gray63 */
+			style->line.width = 0.;
 		}
-		foo_canvas_points_free (points);
+		goc_points_unref (points);
 
-		points = foo_canvas_points_new (2);
 		for (i = 0; line_info[i].states != 0 ; ++i ) {
-			for (j = 4; --j >= 0 ; )
-				points->coords[j] = line_info[i].points[j];
-
 			if (line_info[i].states & state->selection_mask) {
 				BorderPicker const *p =
 				    & state->border.edge[line_info[i].location];
 				state->border.lines[i] =
-					foo_canvas_item_new (group,
-							       gnumeric_dashed_canvas_line_get_type (),
-							       "fill-color-rgba", p->rgba,
-							       "points",	  points,
-							       NULL);
+					goc_item_new (group,
+						      gnumeric_dashed_canvas_line_get_type (),
+					              "x0", line_info[i].points[0],
+					              "y0", line_info[i].points[1],
+					              "x1", line_info[i].points[2],
+					              "y1", line_info[i].points[3],
+						       NULL);
+				style = go_styled_object_get_style (GO_STYLED_OBJECT (state->border.lines[i]));
+				style->line.color = p->rgba;
 				gnumeric_dashed_canvas_line_set_dash_index (
 					GNUMERIC_DASHED_CANVAS_LINE (state->border.lines[i]),
 					p->pattern_index);
 			} else
 				state->border.lines[i] = NULL;
 		}
-		foo_canvas_points_free (points);
 	}
 
 	for (i = 0; i < GNM_STYLE_BORDER_EDGE_MAX; ++i) {
 		BorderPicker *border = &state->border.edge[i];
-		void (*func)(FooCanvasItem *item) = border->is_selected
-			? &foo_canvas_item_show : &foo_canvas_item_hide;
+		void (*func)(GocItem *item) = border->is_selected
+			? &goc_item_show : &goc_item_hide;
 
 		for (j = 0; line_info[j].states != 0 ; ++j) {
 			if ((int)line_info[j].location == i &&
@@ -1331,7 +1333,7 @@ draw_border_preview (FormatState *state)
 				(*func) (state->border.lines[j]);
 		}
 	}
-
+	
 	fmt_dialog_changed (state);
 }
 
@@ -1440,10 +1442,10 @@ init_border_button (FormatState *state, GnmStyleBorderLocation const i,
 		state->border.edge[i].is_selected = TRUE;
 	} else {
 		GnmColor const *c = border->color;
-		state->border.edge[i].rgba = FOO_CANVAS_COLOR (
+		state->border.edge[i].rgba = RGBA_TO_UINT(
 			c->gdk_color.red >> 8,
 			c->gdk_color.green >> 8,
-			c->gdk_color.blue >> 8);
+			c->gdk_color.blue >> 8, 0xff);
 		state->border.edge[i].is_auto_color = c->is_auto;
 		state->border.edge[i].pattern_index = border->line_type;
 		state->border.edge[i].is_selected = (border->line_type != GNM_STYLE_BORDER_NONE);
@@ -2499,10 +2501,10 @@ fmt_dialog_impl (FormatState *state, FormatDialogPosition_t pageno)
 	state->border.pattern.draw_preview = NULL;
 	state->border.pattern.current_pattern = NULL;
 	state->border.pattern.state = state;
-	state->border.rgba = FOO_CANVAS_COLOR (
+	state->border.rgba = RGBA_TO_UINT (
 		default_border_color->red   >> 8,
 		default_border_color->green >> 8,
-		default_border_color->blue  >> 8);
+		default_border_color->blue  >> 8, 0xff);
 	for (i = 0; (name = line_pattern_buttons[i].name) != NULL; ++i)
 		setup_pattern_button (gtk_widget_get_screen (GTK_WIDGET (state->dialog)),
 				      state->gui, name, &state->border.pattern,
diff --git a/src/dialogs/dialog-printer-setup.c b/src/dialogs/dialog-printer-setup.c
index 22017bd..5c3c5e1 100644
--- a/src/dialogs/dialog-printer-setup.c
+++ b/src/dialogs/dialog-printer-setup.c
@@ -680,9 +680,6 @@ do_setup_margin (PrinterSetupState *state)
 	g_return_if_fail (state && state->pi);
 
 	state->preview.canvas = GTK_WIDGET (g_object_new (GOC_TYPE_CANVAS, NULL));
-	goc_canvas_set_scroll_region (  /* is this useful? */
-		GOC_CANVAS (state->preview.canvas),
-		PREVIEW_X, PREVIEW_Y);
 	gtk_widget_set_size_request (state->preview.canvas, PREVIEW_X, PREVIEW_Y);
 	gtk_widget_show (state->preview.canvas);
 
@@ -1871,8 +1868,6 @@ create_hf_preview_canvas (PrinterSetupState *state, gboolean header)
 
 	pi->canvas = GTK_WIDGET (g_object_new (GOC_TYPE_CANVAS, NULL));
 
-	goc_canvas_set_scroll_region (GOC_CANVAS (pi->canvas), width, width); /* ? */
-
  	gostyle = go_styled_object_get_style (
 		GO_STYLED_OBJECT (goc_item_new (goc_canvas_get_root (GOC_CANVAS (pi->canvas)),
 			GOC_TYPE_RECTANGLE,
diff --git a/src/gnm-pane-impl.h b/src/gnm-pane-impl.h
index 8723446..3ec5daf 100644
--- a/src/gnm-pane-impl.h
+++ b/src/gnm-pane-impl.h
@@ -4,6 +4,7 @@
 
 #include <src/gnm-pane.h>
 #include <src/gnumeric-simple-canvas.h>
+#include <goffice/canvas/goc-structs.h>
 #include <gtk/gtk.h>
 
 G_BEGIN_DECLS
@@ -14,12 +15,15 @@ G_BEGIN_DECLS
 struct _GnmPane {
 	GnmSimpleCanvas simple;
 
-	GnmCellPos first, last_full, last_visible, first_offset;
+	GnmCellPos first, last_full, last_visible;
+	struct {
+		gint64 x, y;
+	} first_offset;
 
 	/* In stacking order from lowest to highest */
-	FooCanvasGroup *grid_items;	/* grid & cursors */
-	FooCanvasGroup *object_views;	/* object views */
-	FooCanvasGroup *action_items;	/* drag cursors, and object ctrl pts */
+	GocGroup *grid_items;	/* grid & cursors */
+	GocGroup *object_views;	/* object views */
+	GocGroup *action_items;	/* drag cursors, and object ctrl pts */
 
 	/* Sliding scroll */
 	GnmPaneSlideHandler slide_handler;
@@ -41,15 +45,15 @@ struct _GnmPane {
 	int		 index;
 	struct {
 		GtkWidget *alignment;
-		FooCanvas *canvas;
+		GocCanvas *canvas;
 		ItemBar   *item;
 	} col, row;
 
 	/* Lines across the grid.  Used for col/row resize and the creation of
 	 * frozen panes */
 	struct {
-		FooCanvasItem   *guide, *start;
-		FooCanvasPoints *points;
+		GocItem   *guide, *start;
+		GocPoint  *points;
 	} size_guide;
 
 	ItemGrid      *grid;
diff --git a/src/gnm-pane.c b/src/gnm-pane.c
index 37ee3c1..93df29e 100644
--- a/src/gnm-pane.c
+++ b/src/gnm-pane.c
@@ -33,17 +33,13 @@
 #include "cmd-edit.h"
 #include "clipboard.h"
 #include "sheet-filter-combo.h"
-#include "widgets/gnm-cell-combo-foo-view.h"
-#include "item-acetate.h"
+#include "widgets/gnm-cell-combo-view.h"
 #include "item-bar.h"
 #include "item-cursor.h"
 #include "item-edit.h"
 #include "item-grid.h"
 #include "gnumeric-gconf.h"
 
-#include <goffice/goffice.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-line.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-rect-ellipse.h>
 #include <gsf/gsf-impl-utils.h>
 
 #include <gtk/gtk.h>
@@ -53,8 +49,8 @@
 
 #define SCROLL_LOCK_MASK GDK_MOD5_MASK
 
-typedef FooCanvasClass GnmPaneClass;
-static FooCanvasClass *parent_klass;
+typedef GocCanvasClass GnmPaneClass;
+static GocCanvasClass *parent_klass;
 
 static void cb_pane_popup_menu (GnmPane *pane);
 static void gnm_pane_clear_obj_size_tip (GnmPane *pane);
@@ -95,7 +91,7 @@ gnm_pane_object_key_press (GnmPane *pane, GdkEventKey *ev)
 	gboolean const control	= 0 != (ev->state & GDK_CONTROL_MASK);
 	gboolean const alt	= 0 != (ev->state & GDK_MOD1_MASK);
 	gboolean const symmetric = control && alt;
-	double   const delta = 1.0 / FOO_CANVAS (pane)->pixels_per_unit;
+	double   const delta = 1.0 / GOC_CANVAS (pane)->pixels_per_unit;
 
 	switch (ev->keyval) {
 	case GDK_Escape:
@@ -261,7 +257,7 @@ gnm_pane_key_mode_sheet (GnmPane *pane, GdkEventKey *event,
 			if (NULL != so) {
 				SheetObjectView	*sov = sheet_object_get_view (so,
 					(SheetObjectViewContainer *)pane);
-				gnm_cell_combo_foo_view_popdown (sov, event->time);
+				gnm_cell_combo_view_popdown (sov, event->time);
 				break;
 			}
 		}
@@ -363,7 +359,7 @@ gnm_pane_key_mode_sheet (GnmPane *pane, GdkEventKey *event,
 			wbcg_auto_complete_destroy (wbcg);
 			SCG_FOREACH_PANE (scg, pane, {
 				if (pane->editor)
-					foo_canvas_item_request_update (FOO_CANVAS_ITEM (pane->editor));
+					goc_item_invalidate (GOC_ITEM (pane->editor));
 			});
 			return TRUE;
 		}
@@ -824,7 +820,7 @@ cb_ctrl_pts_free (GtkObject **ctrl_pts)
 	int i = 10;
 	while (i-- > 0)
 		if (ctrl_pts [i] != NULL)
-			gtk_object_destroy (ctrl_pts [i]);
+			g_object_unref (ctrl_pts [i]);
 	g_free (ctrl_pts);
 }
 
@@ -888,20 +884,17 @@ gnm_pane_dispose (GObject *obj)
 static void
 gnm_pane_init (GnmPane *pane)
 {
-	FooCanvas	*canvas = FOO_CANVAS (pane);
-	FooCanvasGroup	*root_group = FOO_CANVAS_GROUP (canvas->root);
+	GocCanvas	*canvas = GOC_CANVAS (pane);
+	GocGroup	*root_group = goc_canvas_get_root (canvas);
 
-	pane->grid_items   = FOO_CANVAS_GROUP (
-		foo_canvas_item_new (root_group, FOO_TYPE_CANVAS_GROUP, NULL));
-	pane->object_views = FOO_CANVAS_GROUP (
-		foo_canvas_item_new (root_group, FOO_TYPE_CANVAS_GROUP, NULL));
-	pane->action_items = FOO_CANVAS_GROUP (
-		foo_canvas_item_new (root_group, FOO_TYPE_CANVAS_GROUP, NULL));
+	pane->grid_items   = goc_group_new (root_group);
+	pane->object_views = goc_group_new (root_group);
+	pane->action_items = goc_group_new (root_group);
 
 	pane->first.col = pane->last_full.col = pane->last_visible.col = 0;
 	pane->first.row = pane->last_full.row = pane->last_visible.row = 0;
-	pane->first_offset.col = 0;
-	pane->first_offset.row = 0;
+	pane->first_offset.x = 0;
+	pane->first_offset.y = 0;
 
 	pane->editor = NULL;
 	pane->mouse_cursor = NULL;
@@ -976,22 +969,21 @@ static void
 gnm_pane_header_init (GnmPane *pane, SheetControlGUI *scg,
 		      gboolean is_col_header)
 {
-	Sheet *sheet;
+	Sheet *sheet = scg_sheet (scg);
 	GtkWidget *alignment;
-	FooCanvas *canvas = gnm_simple_canvas_new (scg);
-	FooCanvasGroup *group = FOO_CANVAS_GROUP (canvas->root);
-	FooCanvasItem *item = foo_canvas_item_new (group,
+	GocCanvas *canvas = gnm_simple_canvas_new (scg);
+	GocGroup *group = goc_canvas_get_root (canvas);
+	GocItem *item = goc_item_new (group,
 		item_bar_get_type (),
 		"pane",	pane,
 		"IsColHeader", is_col_header,
 		NULL);
 
-	foo_canvas_set_center_scroll_region (canvas, FALSE);
 	/* give a non-constraining default in case something scrolls before we
 	 * are realized */
-	foo_canvas_set_scroll_region (canvas,
-		0, 0, GNM_PANE_MAX_X, GNM_PANE_MAX_Y);
 	if (is_col_header) {
+		if (sheet && sheet->text_is_rtl)
+			goc_canvas_set_direction (canvas, GOC_DIRECTION_RTL);
 		pane->col.canvas = canvas;
 		pane->col.item = ITEM_BAR (item);
 		alignment = pane->col.alignment = gtk_alignment_new (0, 1, 1, 0);
@@ -1007,9 +999,9 @@ gnm_pane_header_init (GnmPane *pane, SheetControlGUI *scg,
 	pane->size_guide.guide  = NULL;
 
 	if (NULL != scg &&
-	    NULL != (sheet = scg_sheet (scg)) &&
+	    NULL != sheet &&
 	    fabs (1. - sheet->last_zoom_factor_used) > 1e-6)
-		foo_canvas_set_pixels_per_unit (canvas, sheet->last_zoom_factor_used);
+		goc_canvas_set_pixels_per_unit (canvas, sheet->last_zoom_factor_used);
 
 	g_signal_connect (G_OBJECT (canvas), "realize",
 		G_CALLBACK (cb_gnm_pane_header_realized), NULL);
@@ -1030,7 +1022,7 @@ cb_pane_drag_data_received (GtkWidget *widget, GdkDragContext *context,
 	}
 #endif
 
-	gnm_pane_window_to_coord (pane, x, y, &wx, &wy);
+	goc_canvas_w2c (GOC_CANVAS (pane), x, y, &wx, &wy);
 	scg_drag_data_received (pane->simple.scg,
 		gtk_drag_get_source_widget (context),
 		wx, wy, selection_data);
@@ -1067,7 +1059,7 @@ cb_pane_drag_motion (GtkWidget *widget, GdkDragContext *context,
 
 		g_object_set_data (&context->parent_instance,
 			"wbcg", scg_wbcg (scg));
-		gnm_pane_window_to_coord (pane, x, y, &wx, &wy);
+		goc_canvas_w2c (GOC_CANVAS (pane), x, y, &wx, &wy);
 
 		gdk_window_get_pointer (gtk_widget_get_parent_window (source_widget),
 			NULL, NULL, &mask);
@@ -1084,12 +1076,17 @@ static void
 cb_pane_drag_end (GtkWidget *widget, GdkDragContext *context,
 		  GnmPane *source_pane)
 {
+	/* ungrab any grabbed item */
+	GocItem *item = goc_canvas_get_grabbed_item (GOC_CANVAS (source_pane));
+	if (item)
+		goc_item_ungrab (item);
 	/* sync the ctrl-pts with the object in case the drag was canceled. */
 	gnm_pane_objects_drag (source_pane, NULL,
 		source_pane->drag.origin_x,
 		source_pane->drag.origin_y,
 		8, FALSE, FALSE);
 	source_pane->drag.had_motion = FALSE;
+	source_pane->drag.button = 0;
 }
 
 /**
@@ -1146,9 +1143,9 @@ GnmPane *
 gnm_pane_new (SheetControlGUI *scg,
 	      gboolean col_headers, gboolean row_headers, int index)
 {
-	FooCanvasItem	*item;
-	GnmPane		*pane;
-	Sheet *sheet;
+	GocItem	*item;
+	GnmPane	*pane;
+	Sheet   *sheet;
 
 	g_return_val_if_fail (IS_SHEET_CONTROL_GUI (scg), NULL);
 
@@ -1158,18 +1155,18 @@ gnm_pane_new (SheetControlGUI *scg,
 
 	if (NULL != (sheet = scg_sheet (scg)) &&
 	    fabs (1. - sheet->last_zoom_factor_used) > 1e-6)
-		foo_canvas_set_pixels_per_unit (FOO_CANVAS (pane),
+		goc_canvas_set_pixels_per_unit (GOC_CANVAS (pane),
 			sheet->last_zoom_factor_used);
 
 	gnm_pane_drag_dest_init (pane, scg);
 
-	item = foo_canvas_item_new (pane->grid_items,
+	item = goc_item_new (pane->grid_items,
 		item_grid_get_type (),
 		"SheetControlGUI", scg,
 		NULL);
 	pane->grid = ITEM_GRID (item);
 
-	item = foo_canvas_item_new (pane->grid_items,
+	item = goc_item_new (pane->grid_items,
 		item_cursor_get_type (),
 		"SheetControlGUI", scg,
 		NULL);
@@ -1183,11 +1180,6 @@ gnm_pane_new (SheetControlGUI *scg,
 	else
 		pane->row.canvas = NULL;
 
-	/* FIXME: figure out some real size for the canvas scrolling region */
-	foo_canvas_set_center_scroll_region (FOO_CANVAS (pane), FALSE);
-	foo_canvas_set_scroll_region (FOO_CANVAS (pane), 0, 0,
-		GNM_PANE_MAX_X, GNM_PANE_MAX_Y);
-
 	g_signal_connect_swapped (pane, "popup-menu",
 		G_CALLBACK (cb_pane_popup_menu), pane);
 	g_signal_connect_swapped (G_OBJECT (pane), "realize",
@@ -1205,13 +1197,11 @@ gnm_pane_new (SheetControlGUI *scg,
  * Returns the column containing canvas coord @x
  **/
 int
-gnm_pane_find_col (GnmPane const *pane, int x, int *col_origin)
+gnm_pane_find_col (GnmPane const *pane, gint64 x, gint64 *col_origin)
 {
 	Sheet const *sheet = scg_sheet (pane->simple.scg);
 	int col   = pane->first.col;
-	int pixel = pane->first_offset.col;
-
-	x = gnm_pane_x_w2c (pane, x);
+	gint64 pixel = pane->first_offset.x;
 
 	if (x < pixel) {
 		while (col > 0) {
@@ -1220,14 +1210,13 @@ gnm_pane_find_col (GnmPane const *pane, int x, int *col_origin)
 				pixel -= ci->size_pixels;
 				if (x >= pixel) {
 					if (col_origin)
-						*col_origin = gnm_pane_x_w2c (pane,
-									      pixel);
+						*col_origin = pixel;
 					return col;
 				}
 			}
 		}
 		if (col_origin)
-			*col_origin = gnm_pane_x_w2c (pane, 0);
+			*col_origin = 0;
 		return 0;
 	}
 
@@ -1237,7 +1226,7 @@ gnm_pane_find_col (GnmPane const *pane, int x, int *col_origin)
 			int const tmp = ci->size_pixels;
 			if (x <= pixel + tmp) {
 				if (col_origin)
-					*col_origin = gnm_pane_x_w2c (pane, pixel);
+					*col_origin = pixel;
 				return col;
 			}
 			pixel += tmp;
@@ -1245,7 +1234,7 @@ gnm_pane_find_col (GnmPane const *pane, int x, int *col_origin)
 	} while (++col < gnm_sheet_get_last_col (sheet));
 
 	if (col_origin)
-		*col_origin = gnm_pane_x_w2c (pane, pixel);
+		*col_origin = pixel;
 	return gnm_sheet_get_last_col (sheet);
 }
 
@@ -1258,11 +1247,11 @@ gnm_pane_find_col (GnmPane const *pane, int x, int *col_origin)
  * Returns the column containing canvas coord @y
  **/
 int
-gnm_pane_find_row (GnmPane const *pane, int y, int *row_origin)
+gnm_pane_find_row (GnmPane const *pane, gint64 y, gint64 *row_origin)
 {
 	Sheet const *sheet = scg_sheet (pane->simple.scg);
 	int row   = pane->first.row;
-	int pixel = pane->first_offset.row;
+	gint64 pixel = pane->first_offset.y;
 
 	if (y < pixel) {
 		while (row > 0) {
@@ -1312,8 +1301,9 @@ gnm_pane_compute_visible_region (GnmPane *pane,
 {
 	SheetControlGUI const * const scg = pane->simple.scg;
 	Sheet const *sheet = scg_sheet (scg);
-	FooCanvas   *canvas = FOO_CANVAS (pane);
-	int pixels, col, row, width, height;
+	GocCanvas   *canvas = GOC_CANVAS (pane);
+	gint64 pixels;
+	int col, row, width, height;
 
 #if 0
 	g_warning ("compute_vis(W)[%d] = %d", pane->index,
@@ -1322,22 +1312,19 @@ gnm_pane_compute_visible_region (GnmPane *pane,
 
 	/* When col/row sizes change we need to do a full recompute */
 	if (full_recompute) {
-		int col_offset = pane->first_offset.col = scg_colrow_distance_get (scg,
+		gint64 col_offset = pane->first_offset.x = scg_colrow_distance_get (scg,
 										   TRUE, 0, pane->first.col);
-		if (sheet->text_is_rtl)
-			col_offset = gnm_pane_x_w2c (pane,
-						     pane->first_offset.col + GTK_WIDGET (pane)->allocation.width - 1);
 		if (NULL != pane->col.canvas)
-			foo_canvas_scroll_to (pane->col.canvas, col_offset, 0);
+			goc_canvas_scroll_to (pane->col.canvas, col_offset / canvas->pixels_per_unit, 0);
 
-		pane->first_offset.row = scg_colrow_distance_get (scg,
+		pane->first_offset.y = scg_colrow_distance_get (scg,
 								  FALSE, 0, pane->first.row);
 		if (NULL != pane->row.canvas)
-			foo_canvas_scroll_to (pane->row.canvas,
-					      0, pane->first_offset.row);
+			goc_canvas_scroll_to (pane->row.canvas,
+					      0, pane->first_offset.y / canvas->pixels_per_unit);
 
-		foo_canvas_scroll_to (FOO_CANVAS (pane),
-				      col_offset, pane->first_offset.row);
+		goc_canvas_scroll_to (GOC_CANVAS (pane),
+				      col_offset, pane->first_offset.y / canvas->pixels_per_unit);
 	}
 
 	/* Find out the last visible col and the last full visible column */
@@ -1417,9 +1404,10 @@ void
 gnm_pane_redraw_range (GnmPane *pane, GnmRange const *r)
 {
 	SheetControlGUI *scg;
-	int x1, y1, x2, y2;
+	gint64 x1, y1, x2, y2;
 	GnmRange tmp;
 	Sheet *sheet;
+	double scale = goc_canvas_get_pixels_per_unit (GOC_CANVAS (pane));
 
 	g_return_if_fail (IS_GNM_PANE (pane));
 
@@ -1442,29 +1430,24 @@ gnm_pane_redraw_range (GnmPane *pane, GnmRange const *r)
 	 * NOTE the 2nd coordinates are excluded so add 1 extra (+2border +1include)
 	 */
 	x1 = scg_colrow_distance_get (scg, TRUE, pane->first.col, tmp.start.col) +
-		pane->first_offset.col;
+		pane->first_offset.x;
 	y1 = scg_colrow_distance_get (scg, FALSE, pane->first.row, tmp.start.row) +
-		pane->first_offset.row;
+		pane->first_offset.y;
 	x2 = (tmp.end.col < gnm_sheet_get_last_col (sheet))
 		? 4 + 1 + x1 + scg_colrow_distance_get (scg, TRUE,
 							tmp.start.col, tmp.end.col+1)
-		: INT_MAX;
+		: G_MAXINT64;
 	y2 = (tmp.end.row < gnm_sheet_get_last_row (sheet))
 		? 4 + 1 + y1 + scg_colrow_distance_get (scg, FALSE,
 							tmp.start.row, tmp.end.row+1)
-		: INT_MAX;
+		: G_MAXINT64;
 
 #if 0
 	g_printerr ("%s%s:", col_name (min_col), row_name (first_row));
 	g_printerr ("%s%s\n", col_name (max_col), row_name (last_row));
 #endif
 
-	if (sheet->text_is_rtl)  {
-		int tmp = gnm_pane_x_w2c (pane, x1);
-		x1 = gnm_pane_x_w2c (pane, x2);
-		x2 = tmp;
-	}
-	foo_canvas_request_redraw (&pane->simple.canvas, x1-2, y1-2, x2, y2);
+	goc_canvas_invalidate (&pane->simple.canvas, (x1-2) / scale, (y1-2) / scale, x2 / scale, y2 / scale);
 }
 
 /*****************************************************************************/
@@ -1515,7 +1498,6 @@ cb_pane_sliding (GnmPane *pane)
 	gboolean slide_x = FALSE, slide_y = FALSE;
 	int col = -1, row = -1;
 	Sheet *sheet = scg_sheet (pane->simple.scg);
-	gboolean text_is_rtl = sheet->text_is_rtl;
 	GnmPaneSlideInfo info;
 
 #if 0
@@ -1528,11 +1510,10 @@ cb_pane_sliding (GnmPane *pane)
 		if (pane_index == 1 || pane_index == 2) {
 			if (!pane->sliding_adjacent_h) {
 				int width = GTK_WIDGET (pane)->allocation.width;
-				int x = pane->first_offset.col + width + pane->sliding_dx;
+				int x = pane->first_offset.x + width + pane->sliding_dx;
 
 				/* in case pane is narrow */
-				col = gnm_pane_find_col (pane, text_is_rtl
-							 ? -(x + pane->simple.canvas.scroll_x1 * pane->simple.canvas.pixels_per_unit) : x, NULL);
+				col = gnm_pane_find_col (pane, x, NULL);
 				if (col > pane0->last_full.col) {
 					pane->sliding_adjacent_h = TRUE;
 					pane->sliding_dx = 1; /* good enough */
@@ -1560,9 +1541,8 @@ cb_pane_sliding (GnmPane *pane)
 				int width = GTK_WIDGET (pane1)->allocation.width;
 				if (pane->sliding_dx > (-width) &&
 				    col <= pane1->last_visible.col) {
-					int x = pane1->first_offset.col + width + pane->sliding_dx;
-					col = gnm_pane_find_col (pane, text_is_rtl
-								 ? -(x + pane->simple.canvas.scroll_x1 * pane->simple.canvas.pixels_per_unit) : x, NULL);
+					int x = pane1->first_offset.x + width + pane->sliding_dx;
+					col = gnm_pane_find_col (pane, x, NULL);
 					slide_x = FALSE;
 				}
 			}
@@ -1584,7 +1564,7 @@ cb_pane_sliding (GnmPane *pane)
 		if (pane_index == 3 || pane_index == 2) {
 			if (!pane->sliding_adjacent_v) {
 				int height = GTK_WIDGET (pane)->allocation.height;
-				int y = pane->first_offset.row + height + pane->sliding_dy;
+				int y = pane->first_offset.y + height + pane->sliding_dy;
 
 				/* in case pane is short */
 				row = gnm_pane_find_row (pane, y, NULL);
@@ -1615,7 +1595,7 @@ cb_pane_sliding (GnmPane *pane)
 				int height = GTK_WIDGET (pane3)->allocation.height;
 				if (pane->sliding_dy > (-height) &&
 				    row <= pane3->last_visible.row) {
-					int y = pane3->first_offset.row + height + pane->sliding_dy;
+					int y = pane3->first_offset.y + height + pane->sliding_dy;
 					row = gnm_pane_find_row (pane3, y, NULL);
 					slide_y = FALSE;
 				}
@@ -1637,9 +1617,7 @@ cb_pane_sliding (GnmPane *pane)
 	}
 
 	if (col < 0) {
-		col = gnm_pane_find_col (pane, text_is_rtl
-					 ? -(pane->sliding_x + pane->simple.canvas.scroll_x1 * pane->simple.canvas.pixels_per_unit)
-					 : pane->sliding_x, NULL);
+		col = gnm_pane_find_col (pane, pane->sliding_x, NULL);
 	} else if (row < 0)
 		row = gnm_pane_find_row (pane, pane->sliding_y, NULL);
 
@@ -1663,7 +1641,6 @@ cb_pane_sliding (GnmPane *pane)
  * gnm_pane_handle_motion :
  * @pane	 : The GnmPane managing the scroll
  * @canvas	 : The Canvas the event comes from
- * @event	 : The motion event (in world coords, with rtl inversion)
  * @slide_flags	 :
  * @slide_handler: The handler when sliding
  * @user_data	 : closure data
@@ -1675,50 +1652,22 @@ cb_pane_sliding (GnmPane *pane)
  **/
 gboolean
 gnm_pane_handle_motion (GnmPane *pane,
-			FooCanvas *canvas, GdkEventMotion *event,
+			GocCanvas *canvas, gint64 x, gint64 y,
 			GnmPaneSlideFlags slide_flags,
 			GnmPaneSlideHandler slide_handler,
 			gpointer user_data)
 {
 	GnmPane *pane0, *pane1, *pane3;
-	int pindex, left, top, x, y, width, height;
-	int dx = 0, dy = 0;
-	gboolean text_is_rtl;
+	int pindex, width, height;
+	gint64 dx = 0, dy = 0, left, top;
 
 	g_return_val_if_fail (IS_GNM_PANE (pane), FALSE);
-	g_return_val_if_fail (FOO_IS_CANVAS (canvas), FALSE);
-	g_return_val_if_fail (event != NULL, FALSE);
+	g_return_val_if_fail (GOC_IS_CANVAS (canvas), FALSE);
 	g_return_val_if_fail (slide_handler != NULL, FALSE);
 
-	text_is_rtl = scg_sheet (pane->simple.scg)->text_is_rtl;
-
-	/* NOTE : work around a bug in gtk's use of X.
-	 * When dragging past the right edge of the sheet in rtl mode
-	 * we are operating at the edge of a 32k wide window and the event
-	 * coords get larger than can be held in a signed short.  As a result
-	 * we get world coords of -65535 or so.
-	 *
-	 * KLUDGE KLUDGE KLUDGE
-	 * with our current limit of 256 columns it is unlikely that we'll hit
-	 * -65535 (at appropriate zoom) as a valid coord (it would require all
-	 * cols to be 256 pixels wide.  it is not impossible, but at least
-	 * unlikely.  So we put in a kludge here to catch the screw up and
-	 * remap it.   This is not pretty,  at large zooms this is not far
-	 * fetched.*/
-	if (text_is_rtl &&
-	    event->x < (-64000 / pane->simple.canvas.pixels_per_unit)) {
-/*#if SHEET_MAX_COLS > 700*/ /* a guestimate */
-#warning WARNING We need a better solution to the rtl event kludge with gnm_sheet_get_max_cols (sheet) so large
-/*#endif*/
-		foo_canvas_w2c (canvas, event->x + 65536, event->y, &x, &y);
-	} else
-		foo_canvas_w2c (canvas, event->x, event->y, &x, &y);
-	if (text_is_rtl)
-		x = -(x + pane->simple.canvas.scroll_x1 * pane->simple.canvas.pixels_per_unit);
-
 	pindex = pane->index;
-	left = pane->first_offset.col;
-	top = pane->first_offset.row;
+	left = pane->first_offset.x;
+	top = pane->first_offset.y;
 	width = GTK_WIDGET (pane)->allocation.width;
 	height = GTK_WIDGET (pane)->allocation.height;
 
@@ -1743,7 +1692,7 @@ gnm_pane_handle_motion (GnmPane *pane,
 	if (pane->sliding_adjacent_h) {
 		if (pindex == 0 || pindex == 3) {
 			if (dx < 0) {
-				x = pane1->first_offset.col;
+				x = pane1->first_offset.x;
 				dx += GTK_WIDGET (pane1)->allocation.width;
 				if (dx > 0)
 					x += dx;
@@ -1752,7 +1701,7 @@ gnm_pane_handle_motion (GnmPane *pane,
 				pane->sliding_adjacent_h = FALSE;
 		} else {
 			if (dx > 0) {
-				x = pane0->first_offset.col + dx;
+				x = pane0->first_offset.x + dx;
 				dx -= GTK_WIDGET (pane0)->allocation.width;
 				if (dx < 0)
 					dx = 0;
@@ -1768,7 +1717,7 @@ gnm_pane_handle_motion (GnmPane *pane,
 	if (pane->sliding_adjacent_v) {
 		if (pindex == 0 || pindex == 1) {
 			if (dy < 0) {
-				y = pane3->first_offset.row;
+				y = pane3->first_offset.y;
 				dy += GTK_WIDGET (pane3)->allocation.height;
 				if (dy > 0)
 					y += dy;
@@ -1777,7 +1726,7 @@ gnm_pane_handle_motion (GnmPane *pane,
 				pane->sliding_adjacent_v = FALSE;
 		} else {
 			if (dy > 0) {
-				y = pane0->first_offset.row + dy;
+				y = pane0->first_offset.y + dy;
 				dy -= GTK_WIDGET (pane0)->allocation.height;
 				if (dy < 0)
 					dy = 0;
@@ -1795,9 +1744,7 @@ gnm_pane_handle_motion (GnmPane *pane,
 		if (!(slide_flags & GNM_PANE_SLIDE_EXTERIOR_ONLY)) {
 			GnmPaneSlideInfo info;
 			info.row = gnm_pane_find_row (pane, y, NULL);
-			info.col = gnm_pane_find_col (pane, text_is_rtl
-						      ? -(x + pane->simple.canvas.scroll_x1 * pane->simple.canvas.pixels_per_unit)
-						      : x, NULL);
+			info.col = gnm_pane_find_col (pane, x, NULL);
 			info.user_data = user_data;
 			(*slide_handler) (pane, &info);
 		}
@@ -1842,32 +1789,6 @@ gnm_pane_slide_init (GnmPane *pane)
 		: FALSE;
 }
 
-/*
- * gnm_pane_window_to_coord :
- * @pane : #GnmPane
- * @x :
- * @y :
- * @wx : result
- * @wy : result
- *
- * Map window coords into sheet object coords
- **/
-void
-gnm_pane_window_to_coord (GnmPane *pane,
-			  gint    x,	gint    y,
-			  double *wx, double *wy)
-{
-	double const scale = 1. / FOO_CANVAS (pane)->pixels_per_unit;
-	y += pane->first_offset.row;
-
-	if (scg_sheet (pane->simple.scg)->text_is_rtl)
-		x = x - GTK_WIDGET (pane)->allocation.width - 1 - pane->first_offset.col;
-	else
-		x += pane->first_offset.col;
-	*wx = x * scale;
-	*wy = y * scale;
-}
-
 static gboolean
 cb_obj_autoscroll (GnmPane *pane, GnmPaneSlideInfo const *info)
 {
@@ -1876,11 +1797,11 @@ cb_obj_autoscroll (GnmPane *pane, GnmPaneSlideInfo const *info)
 
 	/* Cheesy hack calculate distance we move the screen, this loses the
 	 * mouse position */
-	double dx = pane->first_offset.col;
-	double dy = pane->first_offset.row;
+	double dx = pane->first_offset.x;
+	double dy = pane->first_offset.y;
 	scg_make_cell_visible (scg, info->col, info->row, FALSE, TRUE);
-	dx = pane->first_offset.col - dx;
-	dy = pane->first_offset.row - dy;
+	dx = pane->first_offset.x - dx;
+	dy = pane->first_offset.y - dy;
 
 #if 0
 	g_warning ("dx = %g, dy = %g", dx, dy);
@@ -1946,7 +1867,7 @@ gnm_pane_object_autoscroll (GnmPane *pane, GdkDragContext *context,
 		cb_pane_sliding (pane);
 }
 
-FooCanvasGroup *
+GocGroup *
 gnm_pane_object_group (GnmPane *pane)
 {
 	return pane->object_views;
@@ -2012,7 +1933,7 @@ gnm_pane_bound_set (GnmPane *pane,
 	g_return_if_fail (pane != NULL);
 
 	range_init (&r, start_col, start_row, end_col, end_row);
-	foo_canvas_item_set (FOO_CANVAS_ITEM (pane->grid),
+	goc_item_set (GOC_ITEM (pane->grid),
 			     "bound", &r,
 			     NULL);
 }
@@ -2023,69 +1944,63 @@ void
 gnm_pane_size_guide_start (GnmPane *pane, gboolean vert, int colrow, int width)
 {
 	SheetControlGUI const *scg;
-	FooCanvasPoints *points;
+	double x0, y0, x1, y1;
 	double zoom;
-	gboolean text_is_rtl;
+	GOStyle *style;
 
 	g_return_if_fail (pane != NULL);
 	g_return_if_fail (pane->size_guide.guide  == NULL);
 	g_return_if_fail (pane->size_guide.start  == NULL);
 	g_return_if_fail (pane->size_guide.points == NULL);
 
+	zoom = GOC_CANVAS (pane)->pixels_per_unit;
 	scg = pane->simple.scg;
-	text_is_rtl = scg_sheet (scg)->text_is_rtl;
-	zoom = FOO_CANVAS (pane)->pixels_per_unit;
 
-	points = pane->size_guide.points = foo_canvas_points_new (2);
 	if (vert) {
-		double x = scg_colrow_distance_get (scg, TRUE,
-					0, colrow) / zoom;
-		if (text_is_rtl)
-			x = -x;
-		points->coords [0] = x;
-		points->coords [1] = scg_colrow_distance_get (scg, FALSE,
+		double x = (scg_colrow_distance_get (scg, TRUE,
+					0, colrow) - .5) / zoom;
+		x0 = x;
+		y0 = scg_colrow_distance_get (scg, FALSE,
 					0, pane->first.row) / zoom;
-		points->coords [2] = x;
-		points->coords [3] = scg_colrow_distance_get (scg, FALSE,
+		x1= x;
+		y1 = scg_colrow_distance_get (scg, FALSE,
 					0, pane->last_visible.row+1) / zoom;
 	} else {
-		double const y = scg_colrow_distance_get (scg, FALSE,
-					0, colrow) / zoom;
-		points->coords [0] = scg_colrow_distance_get (scg, TRUE,
+		double const y = (scg_colrow_distance_get (scg, FALSE,
+					0, colrow) - .5) / zoom;
+		x0 = scg_colrow_distance_get (scg, TRUE,
 					0, pane->first.col) / zoom;
-		points->coords [1] = y;
-		points->coords [2] = scg_colrow_distance_get (scg, TRUE,
+		y0 = y;
+		x1 = scg_colrow_distance_get (scg, TRUE,
 					0, pane->last_visible.col+1) / zoom;
-		points->coords [3] = y;
-
-		if (text_is_rtl) {
-			points->coords [0] *= -1.;
-			points->coords [2] *= -1.;
-		}
+		y1 = y;
 	}
 
 	/* Guideline positioning is done in gnm_pane_size_guide_motion */
-	pane->size_guide.guide = foo_canvas_item_new (pane->action_items,
-		FOO_TYPE_CANVAS_LINE,
-		"fill-color", "black",
-		"width-pixels", width,
+	pane->size_guide.guide = goc_item_new (pane->action_items,
+		GOC_TYPE_LINE,
+		"x0", x0, "y0", y0,
+		"x1", x1, "y1", y1,
 		NULL);
+	style = go_styled_object_get_style (GO_STYLED_OBJECT (pane->size_guide.guide));
+	style->line.width = width;
 
 	/* cheat for now and differentiate between col/row resize and frozen panes
 	 * using the width.  Frozen pane guides do not require a start line */
-	if (width == 1)
-		pane->size_guide.start = foo_canvas_item_new (pane->action_items,
-			FOO_TYPE_CANVAS_LINE,
-			"points", points,
-			"fill-color", "black",
-			"width-pixels", 1,
+	if (width == 1) {
+		style->line.color = RGBA_BLACK;
+		pane->size_guide.start = goc_item_new (pane->action_items,
+			GOC_TYPE_LINE,
+			"x0", x0, "y0", y0,
+			"x1", x1, "y1", y1,
 			NULL);
-	else {
-		static unsigned char const dat [] = { 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88 };
-		GdkBitmap *stipple = gdk_bitmap_create_from_data (
-			GTK_WIDGET (pane)->window, (const gchar *)dat, 8, 8);
-		foo_canvas_item_set (pane->size_guide.guide, "fill-stipple", stipple, NULL);
-		g_object_unref (stipple);
+		style = go_styled_object_get_style (GO_STYLED_OBJECT (pane->size_guide.start));
+		style->line.color = RGBA_BLACK;
+		style->line.width = width;
+	} else {
+		style->line.pattern = GO_PATTERN_GREY25;
+		style->line.color = RGBA_WHITE;
+		style->line.fore = RGBA_BLACK;
 	}
 }
 
@@ -2094,16 +2009,12 @@ gnm_pane_size_guide_stop (GnmPane *pane)
 {
 	g_return_if_fail (pane != NULL);
 
-	if (pane->size_guide.points != NULL) {
-		foo_canvas_points_free (pane->size_guide.points);
-		pane->size_guide.points = NULL;
-	}
 	if (pane->size_guide.start != NULL) {
-		gtk_object_destroy (GTK_OBJECT (pane->size_guide.start));
+		g_object_unref (G_OBJECT (pane->size_guide.start));
 		pane->size_guide.start = NULL;
 	}
 	if (pane->size_guide.guide != NULL) {
-		gtk_object_destroy (GTK_OBJECT (pane->size_guide.guide));
+		g_object_unref (G_OBJECT (pane->size_guide.guide));
 		pane->size_guide.guide = NULL;
 	}
 }
@@ -2119,26 +2030,23 @@ gnm_pane_size_guide_stop (GnmPane *pane)
  *	gnm_pane_size_guide_motion
  **/
 void
-gnm_pane_size_guide_motion (GnmPane *pane, gboolean vert, int guide_pos)
+gnm_pane_size_guide_motion (GnmPane *pane, gboolean vert, gint64 guide_pos)
 {
-	FooCanvasItem *resize_guide = FOO_CANVAS_ITEM (pane->size_guide.guide);
-	FooCanvasPoints *points     = pane->size_guide.points;
+	GocItem *resize_guide = GOC_ITEM (pane->size_guide.guide);
 	double const	 scale	    = 1. / resize_guide->canvas->pixels_per_unit;
+	double x;
 
-	if (vert) {
-		gboolean text_is_rtl = scg_sheet (pane->simple.scg)->text_is_rtl;
-		points->coords [0] = points->coords [2] = scale *
-			(text_is_rtl ? -guide_pos : guide_pos);
-	} else
-		points->coords [1] = points->coords [3] = scale * guide_pos;
-
-	foo_canvas_item_set (resize_guide, "points",  points, NULL);
+	x = scale * (guide_pos - .5);
+	if (vert)
+		goc_item_set (resize_guide, "x0", x, "x1", x, NULL);
+	else
+		goc_item_set (resize_guide, "y0", x, "y1", x, NULL);
 }
 
 /****************************************************************************/
 
 static void
-cb_update_ctrl_pts (SheetObject *so, FooCanvasItem **ctrl_pts, GnmPane *pane)
+cb_update_ctrl_pts (SheetObject *so, GocItem **ctrl_pts, GnmPane *pane)
 {
 	gnm_pane_object_update_bbox (pane, so);
 }
@@ -2181,7 +2089,7 @@ gnm_pane_rangesel_bound_set (GnmPane *pane, GnmRange const *r)
 void
 gnm_pane_rangesel_start (GnmPane *pane, GnmRange const *r)
 {
-	FooCanvasItem *item;
+	GocItem *item;
 	SheetControlGUI *scg = pane->simple.scg;
 	GnmExprEntry *gee = wbcg_get_entry_logical (pane->simple.scg->wbcg);
 
@@ -2193,7 +2101,7 @@ gnm_pane_rangesel_start (GnmPane *pane, GnmRange const *r)
 		item_cursor_set_visibility (pane->cursor.std, FALSE);
 	if (NULL != gee)
 		gnm_expr_entry_disable_highlight (gee);
-	item = foo_canvas_item_new (pane->grid_items,
+	item = goc_item_new (pane->grid_items,
 		item_cursor_get_type (),
 		"SheetControlGUI", scg,
 		"style",	ITEM_CURSOR_ANTED,
@@ -2210,7 +2118,7 @@ gnm_pane_rangesel_stop (GnmPane *pane)
 		gnm_expr_entry_enable_highlight (gee);
 
 	g_return_if_fail (pane->cursor.rangesel != NULL);
-	gtk_object_destroy (GTK_OBJECT (pane->cursor.rangesel));
+	g_object_unref (G_OBJECT (pane->cursor.rangesel));
 	pane->cursor.rangesel = NULL;
 
 	/* Make the primary cursor visible again */
@@ -2230,12 +2138,12 @@ gnm_pane_special_cursor_bound_set (GnmPane *pane, GnmRange const *r)
 void
 gnm_pane_special_cursor_start (GnmPane *pane, int style, int button)
 {
-	FooCanvasItem *item;
-	FooCanvas *canvas = FOO_CANVAS (pane);
+	GocItem *item;
+	GocCanvas *canvas = GOC_CANVAS (pane);
 
 	g_return_if_fail (pane->cursor.special == NULL);
-	item = foo_canvas_item_new (
-		FOO_CANVAS_GROUP (canvas->root),
+	item = goc_item_new (
+		GOC_GROUP (canvas->root),
 		item_cursor_get_type (),
 		"SheetControlGUI", pane->simple.scg,
 		"style",	   style,
@@ -2249,7 +2157,7 @@ gnm_pane_special_cursor_stop (GnmPane *pane)
 {
 	g_return_if_fail (pane->cursor.special != NULL);
 
-	gtk_object_destroy (GTK_OBJECT (pane->cursor.special));
+	g_object_unref (G_OBJECT (pane->cursor.special));
 	pane->cursor.special = NULL;
 }
 
@@ -2268,8 +2176,8 @@ void
 gnm_pane_expr_cursor_bound_set (GnmPane *pane, GnmRange const *r)
 {
 	if (NULL == pane->cursor.expr_range)
-		pane->cursor.expr_range = (ItemCursor *)foo_canvas_item_new (
-			FOO_CANVAS_GROUP (FOO_CANVAS (pane)->root),
+		pane->cursor.expr_range = (ItemCursor *) goc_item_new (
+			GOC_GROUP (GOC_CANVAS (pane)->root),
 			item_cursor_get_type (),
 			"SheetControlGUI",	pane->simple.scg,
 			"style",		ITEM_CURSOR_EXPR_RANGE,
@@ -2283,7 +2191,7 @@ void
 gnm_pane_expr_cursor_stop (GnmPane *pane)
 {
 	if (NULL != pane->cursor.expr_range) {
-		gtk_object_destroy (GTK_OBJECT (pane->cursor.expr_range));
+		g_object_unref (G_OBJECT (pane->cursor.expr_range));
 		pane->cursor.expr_range = NULL;
 	}
 }
@@ -2293,13 +2201,13 @@ gnm_pane_expr_cursor_stop (GnmPane *pane)
 void
 gnm_pane_edit_start (GnmPane *pane)
 {
-	FooCanvas *canvas = FOO_CANVAS (pane);
+	GocCanvas *canvas = GOC_CANVAS (pane);
 
 	g_return_if_fail (pane->editor == NULL);
 
 	/* edit item handles visibility checks */
-	pane->editor = (ItemEdit *)foo_canvas_item_new (
-		FOO_CANVAS_GROUP (canvas->root),
+	pane->editor = (ItemEdit *) goc_item_new (
+		GOC_GROUP (canvas->root),
 		item_edit_get_type (),
 		"SheetControlGUI",	pane->simple.scg,
 		NULL);
@@ -2309,7 +2217,7 @@ void
 gnm_pane_edit_stop (GnmPane *pane)
 {
 	if (pane->editor != NULL) {
-		gtk_object_destroy (GTK_OBJECT (pane->editor));
+		g_object_unref (G_OBJECT (pane->editor));
 		pane->editor = NULL;
 	}
 }
@@ -2323,7 +2231,6 @@ gnm_pane_objects_drag (GnmPane *pane, SheetObject *so,
 	dx = new_x - pane->drag.last_x;
 	dy = new_y - pane->drag.last_y;
 	pane->drag.had_motion = TRUE;
-
 	scg_objects_drag (pane->simple.scg, pane,
 		so, &dx, &dy, drag_type, symmetric, snap_to_grid, TRUE);
 
@@ -2355,17 +2262,14 @@ gnm_pane_object_move (GnmPane *pane, GObject *ctrl_pt,
 static gboolean
 cb_slide_handler (GnmPane *pane, GnmPaneSlideInfo const *info)
 {
-	int x, y;
+	guint64 x, y;
 	SheetControlGUI const *scg = pane->simple.scg;
-	double const scale = 1. / FOO_CANVAS (pane)->pixels_per_unit;
+	double const scale = 1. / GOC_CANVAS (pane)->pixels_per_unit;
 
 	x = scg_colrow_distance_get (scg, TRUE, pane->first.col, info->col);
-	x += pane->first_offset.col;
+	x += pane->first_offset.x;
 	y = scg_colrow_distance_get (scg, FALSE, pane->first.row, info->row);
-	y += pane->first_offset.row;
-
-	if (scg_sheet (scg)->text_is_rtl)
-		x *= -1;
+	y += pane->first_offset.y;
 
 	gnm_pane_object_move (pane, info->user_data,
 		x * scale, y * scale, FALSE, FALSE);
@@ -2374,7 +2278,7 @@ cb_slide_handler (GnmPane *pane, GnmPaneSlideInfo const *info)
 }
 
 static void
-cb_so_menu_activate (GObject *menu, FooCanvasItem *view)
+cb_so_menu_activate (GObject *menu, GocItem *view)
 {
 	SheetObjectAction const *a = g_object_get_data (menu, "action");
 	if (a->func)
@@ -2427,16 +2331,16 @@ cb_ptr_array_free (GPtrArray *actions)
 }
 
 /* event and so can be NULL */
-static void
-display_object_menu (GnmPane *pane, SheetObject *so, GdkEvent *event)
+void
+gnm_pane_display_object_menu (GnmPane *pane, SheetObject *so, GdkEvent *event)
 {
 	SheetControlGUI *scg = pane->simple.scg;
 	GPtrArray *actions = g_ptr_array_new ();
 	GtkWidget *menu;
 	unsigned i = 0;
 
-	if (NULL != so &&
-	    NULL == g_hash_table_lookup (scg->selected_objects, so))
+	if (NULL != so && (!scg->selected_objects ||
+	    NULL == g_hash_table_lookup (scg->selected_objects, so)))
 		scg_object_select (scg, so);
 
 	sheet_object_populate_menu (so, actions);
@@ -2473,7 +2377,7 @@ cb_pane_popup_menu (GnmPane *pane)
 		g_hash_table_foreach (scg->selected_objects,
 			(GHFunc) cb_collect_selected_objs, &accum);
 		if (NULL != accum && NULL == accum->next)
-			display_object_menu (pane, accum->data, NULL);
+			gnm_pane_display_object_menu (pane, accum->data, NULL);
 		g_slist_free (accum);
 	} else {
 		/* the popup-menu signal is a binding. the grid almost always
@@ -2503,7 +2407,7 @@ cb_pane_popup_menu (GnmPane *pane)
 }
 
 static void
-control_point_set_cursor (SheetControlGUI const *scg, FooCanvasItem *ctrl_pt)
+control_point_set_cursor (SheetControlGUI const *scg, GocItem *ctrl_pt)
 {
 	double const *coords = g_hash_table_lookup (scg->selected_objects,
 		g_object_get_data (G_OBJECT (ctrl_pt), "so"));
@@ -2569,7 +2473,7 @@ gnm_pane_drag_begin (GnmPane *pane, SheetObject *so, GdkEvent *event)
 {
 	GdkDragContext *context;
 	GtkTargetList *targets, *im_targets;
-	FooCanvas *canvas    = FOO_CANVAS (pane);
+	GocCanvas *canvas    = GOC_CANVAS (pane);
 	SheetControlGUI *scg = pane->simple.scg;
 	GSList *objects;
 	SheetObject *imageable = NULL, *exportable = NULL;
@@ -2625,15 +2529,17 @@ gnm_pane_drag_begin (GnmPane *pane, SheetObject *so, GdkEvent *event)
 }
 
 void
-gnm_pane_object_start_resize (GnmPane *pane, GdkEventButton *event,
+gnm_pane_object_start_resize (GnmPane *pane, int button, guint64 x, gint64 y,
 			      SheetObject *so, int drag_type, gboolean is_creation)
 {
-	FooCanvasItem **ctrl_pts;
+	GocItem **ctrl_pts;
+	GdkEventButton *event;
 
 	g_return_if_fail (IS_SHEET_OBJECT (so));
 	g_return_if_fail (0 <= drag_type);
 	g_return_if_fail (drag_type < 9);
 
+	event = (GdkEventButton *) goc_canvas_get_cur_event (GOC_CANVAS (pane));
 	ctrl_pts = g_hash_table_lookup (pane->drag.ctrl_pts, so);
 
 	g_return_if_fail (NULL != ctrl_pts);
@@ -2644,122 +2550,231 @@ gnm_pane_object_start_resize (GnmPane *pane, GdkEventButton *event,
 		GDK_BUTTON_RELEASE_MASK,
 		NULL, event->time);
 	pane->drag.created_objects = is_creation;
-	pane->drag.button = event->button;
-	pane->drag.last_x = pane->drag.origin_x = event->x;
-	pane->drag.last_y = pane->drag.origin_y = event->y;
+	pane->drag.button = button;
+	pane->drag.last_x = pane->drag.origin_x = x;
+	pane->drag.last_y = pane->drag.origin_y = y;
 	pane->drag.had_motion = FALSE;
 	gnm_pane_slide_init (pane);
 	gnm_widget_set_cursor_type (GTK_WIDGET (pane), GDK_HAND2);
 }
 
-static int
-cb_control_point_event (FooCanvasItem *ctrl_pt, GdkEvent *event, GnmPane *pane)
+/*
+ ControlCircleItem
+ */
+typedef GocCircle ControlCircle;
+typedef GocCircleClass ControlCircleClass;
+
+#define CONTROL_TYPE_CIRCLE	(control_circle_get_type ())
+#define CONTROL_CIRCLE(o)	(G_TYPE_CHECK_INSTANCE_CAST ((o), CONTROL_TYPE_CIRCLE, ControlCircle))
+#define CONTROL_IS_CIRCLE(o)	(G_TYPE_CHECK_INSTANCE_TYPE ((o), CONTROL_TYPE_CIRCLE))
+
+GType control_circle_get_type (void);
+
+static gboolean
+control_point_button_pressed (GocItem *item, int button, double x, double y)
 {
-	SheetControlGUI *scg = pane->simple.scg;
+	GnmPane *pane = GNM_PANE (item->canvas);
+	GdkEventButton *event = (GdkEventButton *) goc_canvas_get_cur_event (item->canvas);
 	SheetObject *so;
 	int idx;
 
-	if (wbc_gtk_get_guru (scg_wbcg (scg)) != NULL)
+	if (0 != pane->drag.button)
+		return TRUE;
+
+	x *= goc_canvas_get_pixels_per_unit (item->canvas);
+	y *= goc_canvas_get_pixels_per_unit (item->canvas);
+	so  = g_object_get_data (G_OBJECT (item), "so");
+	idx = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "index"));
+	switch (event->button) {
+	case 1:
+	case 2: gnm_pane_object_start_resize (pane, button, x, y, so,  idx, FALSE);
+		break;
+	case 3: gnm_pane_display_object_menu (pane, so, (GdkEvent *) event);
+		break;
+	default: /* Ignore mouse wheel events */
 		return FALSE;
+	}
+	return TRUE;
+}
 
-	so  = g_object_get_data (G_OBJECT (ctrl_pt), "so");
-	idx = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (ctrl_pt), "index"));
-	switch (event->type) {
-	case GDK_ENTER_NOTIFY:
-		control_point_set_cursor (scg, ctrl_pt);
+static gboolean
+control_point_button_released (GocItem *item, int button, G_GNUC_UNUSED double x, G_GNUC_UNUSED double y)
+{
+	GnmPane *pane = GNM_PANE (item->canvas);
+	GdkEventButton *event = (GdkEventButton *) goc_canvas_get_cur_event (item->canvas);
+	SheetControlGUI *scg = pane->simple.scg;
+	SheetObject *so;
+	int idx;
 
-		if (idx != 8) {
-			foo_canvas_item_set (ctrl_pt,
-				"fill-color",    "green",
-				NULL);
-			gnm_pane_display_obj_size_tip (pane, so);
-		}
-		break;
+	if (pane->drag.button != button)
+		return TRUE;
+	so  = g_object_get_data (G_OBJECT (item), "so");
+	idx = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "index"));
+	pane->drag.button = 0;
+	gnm_simple_canvas_ungrab (item, event->time);
+	gnm_pane_slide_stop (pane);
+	control_point_set_cursor (scg, item);
+	if (idx == 8)
+		; /* ignore fake event generated by the dnd code */
+	else if (pane->drag.had_motion)
+		scg_objects_drag_commit	(scg, idx,
+			pane->drag.created_objects);
+	else if (pane->drag.created_objects && idx == 7) {
+		double w, h;
+		sheet_object_default_size (so, &w, &h);
+		scg_objects_drag (scg, NULL, NULL, &w, &h, 7, FALSE, FALSE, FALSE);
+		scg_objects_drag_commit	(scg, 7, TRUE);
+	}
+	gnm_pane_clear_obj_size_tip (pane);
+	return TRUE;
+}
 
-	case GDK_LEAVE_NOTIFY:
-		scg_set_display_cursor (scg);
-		if (idx != 8) {
-			foo_canvas_item_set (ctrl_pt,
-				"fill-color",    "white",
-				NULL);
-			gnm_pane_clear_obj_size_tip (pane);
-		}
-		break;
+static gboolean
+control_point_motion (GocItem *item, double x, double y)
+{
+	GnmPane *pane = GNM_PANE (item->canvas);
+	GdkEventMotion *event = (GdkEventMotion *) goc_canvas_get_cur_event (item->canvas);
+	SheetObject *so;
+	int idx;
 
-	case GDK_2BUTTON_PRESS:
-		if (pane->drag.button == 1)
-			sheet_object_get_editor (so, SHEET_CONTROL (scg));
-		else
-			break;
+	if (0 == pane->drag.button)
+		return TRUE;
 
-	case GDK_BUTTON_RELEASE:
-		if (pane->drag.button != (int)event->button.button)
-			break;
-		pane->drag.button = 0;
-		gnm_simple_canvas_ungrab (ctrl_pt, event->button.time);
-		gnm_pane_slide_stop (pane);
-		control_point_set_cursor (scg, ctrl_pt);
-		if (idx == 8)
-			; /* ignore fake event generated by the dnd code */
-		else if (pane->drag.had_motion)
-			scg_objects_drag_commit	(scg, idx,
-				pane->drag.created_objects);
-		else if (pane->drag.created_objects && idx == 7) {
-			double w, h;
-			sheet_object_default_size (so, &w, &h);
-			scg_objects_drag (scg, NULL, NULL, &w, &h, 7, FALSE, FALSE, FALSE);
-			scg_objects_drag_commit	(scg, 7, TRUE);
-		}
-		gnm_pane_clear_obj_size_tip (pane);
-		break;
+	x *= goc_canvas_get_pixels_per_unit (item->canvas);
+	y *= goc_canvas_get_pixels_per_unit (item->canvas);
+	/* TODO : motion is still too granular along the internal axis
+	 * when the other axis is external.
+	 * eg  drag from middle of sheet down.  The x axis is still internal
+	 * onlt the y is external, however, since we are autoscrolling
+	 * we are limited to moving with col/row coords, not x,y.
+	 * Possible solution would be to change the EXTERIOR_ONLY flag
+	 * to something like USE_PIXELS_INSTEAD_OF_COLROW and change
+	 * the semantics of the col,row args in the callback.  However,
+	 * that is more work than I want to do right now.
+	 */
+	so  = g_object_get_data (G_OBJECT (item), "so");
+	idx = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "index"));
+	if (idx == 8)
+		gnm_pane_drag_begin (pane, so, (GdkEvent *) event);
+	else if (gnm_pane_handle_motion (pane,
+					   item->canvas, x, y,
+					   GNM_PANE_SLIDE_X | GNM_PANE_SLIDE_Y |
+					   GNM_PANE_SLIDE_EXTERIOR_ONLY,
+					   cb_slide_handler, item))
+		gnm_pane_object_move (pane, G_OBJECT (item),
+				      x, y,
+				      (event->state & GDK_CONTROL_MASK) != 0,
+				      (event->state & GDK_SHIFT_MASK) != 0);
+	return TRUE;
+}
 
-	case GDK_BUTTON_PRESS:
-		if (0 != pane->drag.button)
-			break;
-		switch (event->button.button) {
-		case 1:
-		case 2: gnm_pane_object_start_resize (pane, &event->button, so,  idx, FALSE);
-			break;
-		case 3: display_object_menu (pane, so, event);
-			break;
-		default: /* Ignore mouse wheel events */
-			return FALSE;
-		}
-		break;
+static gboolean
+control_point_button2_pressed (GocItem *item, int button, G_GNUC_UNUSED double x, G_GNUC_UNUSED double y)
+{
+	GnmPane *pane = GNM_PANE (item->canvas);
+	SheetControlGUI *scg = pane->simple.scg;
+	SheetObject *so;
 
-	case GDK_MOTION_NOTIFY :
-		if (0 == pane->drag.button)
-			break;
+	so  = g_object_get_data (G_OBJECT (item), "so");
+	if (pane->drag.button == 1)
+		sheet_object_get_editor (so, SHEET_CONTROL (scg));
+	return TRUE;
+}
 
-		/* TODO : motion is still too granular along the internal axis
-		 * when the other axis is external.
-		 * eg  drag from middle of sheet down.  The x axis is still internal
-		 * onlt the y is external, however, since we are autoscrolling
-		 * we are limited to moving with col/row coords, not x,y.
-		 * Possible solution would be to change the EXTERIOR_ONLY flag
-		 * to something like USE_PIXELS_INSTEAD_OF_COLROW and change
-		 * the semantics of the col,row args in the callback.  However,
-		 * that is more work than I want to do right now.
-		 */
-		if (idx == 8)
-			gnm_pane_drag_begin (pane, so, event);
-		else if (gnm_pane_handle_motion (GNM_PANE (ctrl_pt->canvas),
-						   ctrl_pt->canvas, &event->motion,
-						   GNM_PANE_SLIDE_X | GNM_PANE_SLIDE_Y |
-						   GNM_PANE_SLIDE_EXTERIOR_ONLY,
-						   cb_slide_handler, ctrl_pt))
-			gnm_pane_object_move (pane, G_OBJECT (ctrl_pt),
-					      event->motion.x, event->motion.y,
-					      (event->button.state & GDK_CONTROL_MASK) != 0,
-					      (event->button.state & GDK_SHIFT_MASK) != 0);
-		break;
+static gboolean
+control_point_enter_notify (GocItem *item, G_GNUC_UNUSED double x, G_GNUC_UNUSED double y)
+{
+	GnmPane *pane = GNM_PANE (item->canvas);
+	SheetControlGUI *scg = pane->simple.scg;
+	int idx;
+	SheetObject *so;
 
-	default:
-		return FALSE;
+	control_point_set_cursor (scg, item);
+
+	so  = g_object_get_data (G_OBJECT (item), "so");
+	idx = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "index"));
+	if (idx != 8) {
+		GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
+		style->fill.pattern.back = RGBA_GREEN;
+		goc_item_invalidate (item);
+		gnm_pane_display_obj_size_tip (pane, so);
 	}
 	return TRUE;
 }
 
+static gboolean
+control_point_leave_notify (GocItem *item, G_GNUC_UNUSED double x, G_GNUC_UNUSED double y)
+{
+	GnmPane *pane = GNM_PANE (item->canvas);
+	SheetControlGUI *scg = pane->simple.scg;
+	int idx;
+	SheetObject *so;
+
+	control_point_set_cursor (scg, item);
+
+	so  = g_object_get_data (G_OBJECT (item), "so");
+	idx = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "index"));
+	if (idx != 8) {
+		GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (item));
+		style->fill.pattern.back = RGBA_WHITE;
+		goc_item_invalidate (item);
+		gnm_pane_clear_obj_size_tip (pane);
+	}
+	return TRUE;
+}
+
+static void control_circle_class_init (GocItemClass *item_klass) {
+	item_klass->button_pressed = control_point_button_pressed;
+	item_klass->button_released = control_point_button_released;
+	item_klass->motion = control_point_motion;
+	item_klass->button2_pressed = control_point_button2_pressed;
+	item_klass->enter_notify = control_point_enter_notify;
+	item_klass->leave_notify = control_point_leave_notify;
+}
+
+GSF_CLASS (ControlCircle, control_circle,
+	   control_circle_class_init, NULL,
+	   GOC_TYPE_CIRCLE)
+
+#define ITEM_ACETATE(obj)          (G_TYPE_CHECK_INSTANCE_CAST((obj), item_acetate_get_type (), ItemAcetate))
+#define IS_ITEM_ACETATE(o)         (G_TYPE_CHECK_INSTANCE_TYPE((o), item_acetate_get_type ()))
+
+#define MARGIN	10
+
+GType item_acetate_get_type (void);
+
+typedef GocRectangle		ItemAcetate;
+typedef GocRectangleClass	ItemAcetateClass;
+
+static double
+item_acetate_distance (GocItem *item, double x, double y,
+		    GocItem **actual_item)
+{
+	if (x < (item->x0 - MARGIN) ||
+	    x > (item->x1 + MARGIN) ||
+	    y < (item->y0 - MARGIN) ||
+		y > (item->y1 + MARGIN))
+		return DBL_MAX;
+	*actual_item = item;
+	return 0.;
+}
+
+static void
+item_acetate_class_init (GocItemClass *item_class)
+{
+	item_class->distance = item_acetate_distance;
+	item_class->button_pressed = control_point_button_pressed;
+	item_class->button_released = control_point_button_released;
+	item_class->motion = control_point_motion;
+	item_class->button2_pressed = control_point_button2_pressed;
+	item_class->enter_notify = control_point_enter_notify;
+	item_class->leave_notify = control_point_leave_notify;
+}
+
+GSF_CLASS (ItemAcetate, item_acetate,
+	   item_acetate_class_init, NULL,
+	   GOC_TYPE_RECTANGLE)
+
 /**
  * new_control_point
  * @pane: #GnmPane
@@ -2781,21 +2796,23 @@ cb_control_point_event (FooCanvasItem *ctrl_pt, GdkEvent *event, GnmPane *pane)
  *     9 == an optional stippled rectangle for moving/resizing expensive
  *         objects
  **/
-static FooCanvasItem *
-new_control_point (GnmPane *pane, SheetObject *so, int idx, double x, double y)
+static GocItem *
+new_control_point (GnmPane *pane, SheetObject *so, int idx, double x, double y, double radius)
 {
-	FooCanvasItem *item = foo_canvas_item_new (
+	GOStyle *style = go_style_new ();
+	GocItem *item;
+
+	style->outline.width = CTRL_PT_OUTLINE;
+	item = goc_item_new (
 		pane->action_items,
-		FOO_TYPE_CANVAS_ELLIPSE,
-		"outline-color", "black",
-		"fill-color",    "white",
-		"width-pixels",  CTRL_PT_OUTLINE,
+		CONTROL_TYPE_CIRCLE,
+		"x", x,
+		"y", y,
+		"radius", radius,
+		"style", style,
 		NULL);
 
-	g_signal_connect (G_OBJECT (item),
-		"event",
-		G_CALLBACK (cb_control_point_event), pane);
-
+	g_object_unref (style);
 	g_object_set_data (G_OBJECT (item), "index",  GINT_TO_POINTER (idx));
 	g_object_set_data (G_OBJECT (item), "so",  so);
 
@@ -2808,49 +2825,53 @@ new_control_point (GnmPane *pane, SheetObject *so, int idx, double x, double y)
  * creating the control point if necessary.
  **/
 static void
-set_item_x_y (GnmPane *pane, SheetObject *so, FooCanvasItem **ctrl_pts,
+set_item_x_y (GnmPane *pane, SheetObject *so, GocItem **ctrl_pts,
 	      int idx, double x, double y, gboolean visible)
 {
-	double const scale = 1. / FOO_CANVAS (pane)->pixels_per_unit;
+	double scale = GOC_CANVAS (pane)->pixels_per_unit;
 	if (ctrl_pts [idx] == NULL)
-		ctrl_pts [idx] = new_control_point (pane, so, idx, x, y);
-	foo_canvas_item_set (ctrl_pts [idx],
-	       "x1", x - CTRL_PT_SIZE * scale,
-	       "y1", y - CTRL_PT_SIZE * scale,
-	       "x2", x + CTRL_PT_SIZE * scale,
-	       "y2", y + CTRL_PT_SIZE * scale,
-	       NULL);
+		ctrl_pts [idx] = new_control_point (pane, so, idx, x / scale, y / scale, CTRL_PT_SIZE / scale);
+	else
+		goc_item_set (ctrl_pts [idx], "x", x / scale, "y", y / scale, NULL);
 	if (visible)
-		foo_canvas_item_show (ctrl_pts [idx]);
+		goc_item_show (ctrl_pts [idx]);
 	else
-		foo_canvas_item_hide (ctrl_pts [idx]);
+		goc_item_hide (ctrl_pts [idx]);
 }
 
 #define normalize_high_low(d1,d2) if (d1<d2) { double tmp=d1; d1=d2; d2=tmp;}
 
 static void
-set_acetate_coords (GnmPane *pane, SheetObject *so, FooCanvasItem **ctrl_pts,
+set_acetate_coords (GnmPane *pane, SheetObject *so, GocItem **ctrl_pts,
 		    double l, double t, double r, double b)
 {
+	double scale = goc_canvas_get_pixels_per_unit (GOC_CANVAS (pane));
 	if (!sheet_object_rubber_band_directly (so)) {
 		if (NULL == ctrl_pts [9]) {
-			static char const dashed [] = { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 };
-			GdkBitmap *stipple = gdk_bitmap_create_from_data (
-				GTK_WIDGET (pane)->window, dashed, 8, 8);
-			ctrl_pts [9] = foo_canvas_item_new (pane->action_items,
-				FOO_TYPE_CANVAS_RECT,
-				"fill-color",		NULL,
-				"width-units",		1.,
-				"outline-color",	"black",
-				"outline-stipple",	stipple,
+			GOStyle *style = go_style_new ();
+			style->fill.auto_type = FALSE;
+			style->fill.type  = GO_STYLE_FILL_PATTERN;
+			style->fill.auto_back = FALSE;
+			style->fill.pattern.back = 0;
+			style->fill.auto_fore = FALSE;
+			style->fill.pattern.fore = 0;
+			style->line.pattern = GO_PATTERN_THIN_DIAG;
+			style->line.width = 1.;
+			style->line.auto_color = FALSE;
+			style->line.color = 0;
+			style->line.fore = RGBA_BLACK;
+			ctrl_pts [9] = goc_item_new (pane->action_items,
+				GOC_TYPE_RECTANGLE,
+				"style", style,
 				NULL);
-			g_object_unref (stipple);
-			foo_canvas_item_lower_to_bottom (ctrl_pts [9]);
+			g_object_unref (style);
+			goc_item_lower_to_bottom (ctrl_pts [9]);
 		}
 		normalize_high_low (r, l);
 		normalize_high_low (b, t);
-		foo_canvas_item_set (ctrl_pts [9],
-		       "x1", l, "y1", t, "x2", r, "y2", b,
+		goc_item_set (ctrl_pts [9],
+		       "x", l / scale, "y", t / scale,
+		       "width", (r - l) / scale, "height", (b - t) / scale,
 		       NULL);
 	} else {
 		double coords[4];
@@ -2871,44 +2892,36 @@ set_acetate_coords (GnmPane *pane, SheetObject *so, FooCanvasItem **ctrl_pts,
 	b += (CTRL_PT_SIZE + CTRL_PT_OUTLINE) / 2;
 
 	if (NULL == ctrl_pts [8]) {
-#undef WITH_STIPPLE_BORDER /* not so pretty */
-#ifdef WITH_STIPPLE_BORDER
-		static char const diagonal [] = { 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 };
-		GdkBitmap *stipple = gdk_bitmap_create_from_data (
-			GTK_WIDGET (pane)->window, diagonal, 8, 8);
-#endif
-		FooCanvasItem *item = foo_canvas_item_new (
+		GOStyle *style = go_style_new ();
+		GocItem *item;
+
+		style->fill.auto_type = FALSE;
+		style->fill.type  = GO_STYLE_FILL_PATTERN;
+		style->fill.auto_fore = FALSE;
+		go_pattern_set_solid (&style->fill.pattern, 0);
+		style->outline.auto_dash = FALSE;
+		style->outline.dash_type = GO_LINE_NONE;
+		/* work around the screwup in shapes that adds a large
+		 * border to anything that uses miter (is this required for
+		 * a rectangle in goc-canvas? */
+		style->outline.join = CAIRO_LINE_JOIN_ROUND;
+		item = goc_item_new (
 			pane->action_items,
 			item_acetate_get_type (),
-			"fill-color",		NULL,
-#ifdef WITH_STIPPLE_BORDER
-			"width-units",		(double)(CTRL_PT_SIZE + CTRL_PT_OUTLINE),
-			"outline-color",	"black",
-			"outline-stipple",	stipple,
-#endif
-#if 0
-			/* work around the screwup in canvas-item-shape that adds a large
-			 * border to anything that uses miter (required for gnome-canvas
-			 * not foocanvas */
-			"join-style",		GDK_JOIN_ROUND,
-#endif
-			NULL);
-#ifdef WITH_STIPPLE_BORDER
-		g_object_unref (stipple);
-#endif
-		g_signal_connect (G_OBJECT (item), "event",
-			G_CALLBACK (cb_control_point_event), pane);
+			"style", style,
+		        NULL);
+		g_object_unref (style);
 		g_object_set_data (G_OBJECT (item), "index",
 			GINT_TO_POINTER (8));
 		g_object_set_data (G_OBJECT (item), "so", so);
 
 		ctrl_pts [8] = item;
 	}
-	foo_canvas_item_set (ctrl_pts [8],
-	       "x1", l,
-	       "y1", t,
-	       "x2", r,
-	       "y2", b,
+	goc_item_set (ctrl_pts [8],
+	       "x", l / scale,
+	       "y", t / scale,
+	       "width", (r - l) / scale,
+	       "height", (b - t) / scale,
 	       NULL);
 }
 
@@ -2930,12 +2943,12 @@ gnm_pane_object_unselect (GnmPane *pane, SheetObject *so)
 void
 gnm_pane_object_update_bbox (GnmPane *pane, SheetObject *so)
 {
-	FooCanvasItem **ctrl_pts = g_hash_table_lookup (pane->drag.ctrl_pts, so);
+	GocItem **ctrl_pts = g_hash_table_lookup (pane->drag.ctrl_pts, so);
 	double const *pts = g_hash_table_lookup (
 		pane->simple.scg->selected_objects, so);
 
 	if (ctrl_pts == NULL) {
-		ctrl_pts = g_new0 (FooCanvasItem *, 10);
+		ctrl_pts = g_new0 (GocItem *, 10);
 		g_hash_table_insert (pane->drag.ctrl_pts, so, ctrl_pts);
 	}
 
@@ -2957,80 +2970,8 @@ gnm_pane_object_update_bbox (GnmPane *pane, SheetObject *so)
 	set_item_x_y (pane, so, ctrl_pts, 7, pts[2], pts[3], TRUE);
 }
 
-static int
-cb_sheet_object_canvas_event (FooCanvasItem *view, GdkEvent *event,
-			      SheetObject *so)
-{
-	GnmPane	*pane = GNM_PANE (view->canvas);
-
-	if (scg_wbcg(GNM_SIMPLE_CANVAS (view->canvas)->scg)->new_object) {
-		ItemGrid *grid = GNM_PANE (view->canvas)->grid;
-		return FOO_CANVAS_ITEM_GET_CLASS (grid)->event (FOO_CANVAS_ITEM (grid), event);
-	}
-
-	g_return_val_if_fail (IS_SHEET_OBJECT (so), FALSE);
-
-	switch (event->type) {
-	case GDK_ENTER_NOTIFY:
-		gnm_widget_set_cursor_type (GTK_WIDGET (view->canvas),
-			(so->flags & SHEET_OBJECT_CAN_PRESS) ? GDK_HAND2 : GDK_ARROW);
-		return FALSE;
-
-	case GDK_BUTTON_PRESS:
-		if (event->button.button > 3)
-			return FALSE;
-
-		/* cb_sheet_object_widget_canvas_event calls even if selected */
-		if (NULL == g_hash_table_lookup (pane->drag.ctrl_pts, so)) {
-			SheetObjectClass *soc =
-				G_TYPE_INSTANCE_GET_CLASS (so, SHEET_OBJECT_TYPE, SheetObjectClass);
-
-			if (soc->interactive && event->button.button != 3)
-				return FALSE;
-
-			if (!(event->button.state & GDK_SHIFT_MASK))
-				scg_object_unselect (pane->simple.scg, NULL);
-			scg_object_select (pane->simple.scg, so);
-			if (NULL == g_hash_table_lookup (pane->drag.ctrl_pts, so))
-				return FALSE;	/* protected ? */
-		}
-
-		if (event->button.button < 3)
-			gnm_pane_object_start_resize (pane, &event->button, so, 8, FALSE);
-		else
-			display_object_menu (pane, so, event);
-		break;
-
-	default:
-		return FALSE;
-	}
-	return TRUE;
-}
-
-static void
-cb_sheet_object_view_destroyed (FooCanvasItem *view, SheetObject *so)
-{
-	if (NULL != view->canvas) {
-		GnmPane *pane = GNM_PANE (view->canvas);
-		if (pane != NULL &&
-		    g_hash_table_lookup (pane->drag.ctrl_pts, so) != NULL)
-			scg_object_unselect (GNM_SIMPLE_CANVAS (view->canvas)->scg, so);
-	}
-}
-
-static int
-cb_sheet_object_widget_canvas_event (GtkWidget *widget, GdkEvent *event,
-				     FooCanvasItem *view)
-{
-	if (event->type == GDK_ENTER_NOTIFY ||
-	    (event->type == GDK_BUTTON_PRESS && event->button.button == 3))
-		return cb_sheet_object_canvas_event (view, event,
-			sheet_object_view_get_so (SHEET_OBJECT_VIEW (view)));
-	return FALSE;
-}
-
 static void
-cb_bounds_changed (SheetObject *so, FooCanvasItem *sov)
+cb_bounds_changed (SheetObject *so, GocItem *sov)
 {
 	double coords[4], *cur;
 	SheetControlGUI *scg = GNM_SIMPLE_CANVAS (sov->canvas)->scg;
@@ -3056,14 +2997,8 @@ cb_bounds_changed (SheetObject *so, FooCanvasItem *sov)
  * Setup some standard callbacks for manipulating a view of a sheet object.
  **/
 SheetObjectView *
-gnm_pane_object_register (SheetObject *so, FooCanvasItem *view, gboolean selectable)
+gnm_pane_object_register (SheetObject *so, GocItem *view, gboolean selectable)
 {
-	if (selectable) {
-		g_signal_connect (view, "event",
-			G_CALLBACK (cb_sheet_object_canvas_event), so);
-		g_signal_connect (view, "destroy",
-			G_CALLBACK (cb_sheet_object_view_destroyed), so);
-	}
 	g_signal_connect_object (so, "bounds-changed",
 		G_CALLBACK (cb_bounds_changed), view, 0);
 	return SHEET_OBJECT_VIEW (view);
@@ -3080,11 +3015,8 @@ gnm_pane_object_register (SheetObject *so, FooCanvasItem *view, gboolean selecta
  * objects.
  **/
 void
-gnm_pane_widget_register (SheetObject *so, GtkWidget *w, FooCanvasItem *view)
+gnm_pane_widget_register (SheetObject *so, GtkWidget *w, GocItem *view)
 {
-	g_signal_connect (G_OBJECT (w), "event",
-		G_CALLBACK (cb_sheet_object_widget_canvas_event), view);
-
 	if (GTK_IS_CONTAINER (w)) {
 		GList *ptr, *children = gtk_container_get_children (GTK_CONTAINER (w));
 		for (ptr = children ; ptr != NULL; ptr = ptr->next)
@@ -3092,3 +3024,11 @@ gnm_pane_widget_register (SheetObject *so, GtkWidget *w, FooCanvasItem *view)
 		g_list_free (children);
 	}
 }
+
+void
+gnm_pane_set_direction (GnmPane *pane, GocDirection direction)
+{
+	goc_canvas_set_direction (GOC_CANVAS (pane), direction);
+	if (pane->col.canvas != NULL)
+		goc_canvas_set_direction (pane->col.canvas, direction);
+}
diff --git a/src/gnm-pane.h b/src/gnm-pane.h
index b11c7dc..2112393 100644
--- a/src/gnm-pane.h
+++ b/src/gnm-pane.h
@@ -3,8 +3,7 @@
 # define _GNM_PANE_H_
 
 #include "gui-gnumeric.h"
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-util.h>
+#include <goffice/goffice.h>
 #include "gui-util.h"
 
 G_BEGIN_DECLS
@@ -17,8 +16,8 @@ GType	 gnm_pane_get_type (void);
 GnmPane *gnm_pane_new (SheetControlGUI *scg,
 		       gboolean col_headers, gboolean row_headers, int index);
 
-int   gnm_pane_find_col		(GnmPane const *pane, int x, int *col_origin);
-int   gnm_pane_find_row		(GnmPane const *pane, int y, int *row_origin);
+int   gnm_pane_find_col		(GnmPane const *pane, gint64 x, gint64 *col_origin);
+int   gnm_pane_find_row		(GnmPane const *pane, gint64 y, gint64 *row_origin);
 void  gnm_pane_redraw_range	(GnmPane *pane, GnmRange const *r);
 void  gnm_pane_compute_visible_region (GnmPane *pane, gboolean full_recompute);
 void  gnm_pane_bound_set	(GnmPane *pane,
@@ -31,7 +30,7 @@ void	gnm_pane_edit_start  (GnmPane *p);
 void	gnm_pane_edit_stop   (GnmPane *p);
 
 void	gnm_pane_size_guide_start  (GnmPane *p, gboolean vert, int colrow, int width);
-void	gnm_pane_size_guide_motion	(GnmPane *p, gboolean vert, int guide_pos);
+void	gnm_pane_size_guide_motion	(GnmPane *p, gboolean vert, gint64 guide_pos);
 void	gnm_pane_size_guide_stop	(GnmPane *p);
 
 void	 gnm_pane_reposition_cursors	   (GnmPane *pane);
@@ -53,19 +52,22 @@ void gnm_pane_objects_drag        (GnmPane *pane, SheetObject *so,
 				   gboolean symmetric,gboolean snap_to_grid);
 void gnm_pane_object_unselect	  (GnmPane *pane, SheetObject *so);
 void gnm_pane_object_update_bbox  (GnmPane *pane, SheetObject *so);
-void gnm_pane_object_start_resize (GnmPane *pane, GdkEventButton *event,
+void gnm_pane_object_start_resize (GnmPane *pane, int button,
+                                   guint64 x, gint64 y,
 				   SheetObject *so, int drag_type,
 				   gboolean is_creation);
 void gnm_pane_object_autoscroll	  (GnmPane *pane, GdkDragContext *context,
 				   gint x, gint y, guint time);
 
-FooCanvasGroup *gnm_pane_object_group (GnmPane *pane);
+GocGroup *gnm_pane_object_group (GnmPane *pane);
+void gnm_pane_display_object_menu (GnmPane *pane, SheetObject *so,
+					   GdkEvent *event);
 
 /* A convenience api */
-SheetObjectView *gnm_pane_object_register (SheetObject *so, FooCanvasItem *view,
+SheetObjectView *gnm_pane_object_register (SheetObject *so, GocItem *view,
 					   gboolean selectable);
 void		 gnm_pane_widget_register (SheetObject *so, GtkWidget *w,
-					   FooCanvasItem *view);
+					   GocItem *view);
 
 /************************************************************************/
 
@@ -84,37 +86,15 @@ typedef gboolean (*GnmPaneSlideHandler) (GnmPane *pane, GnmPaneSlideInfo const *
 void	 gnm_pane_slide_stop	  (GnmPane *pane);
 void	 gnm_pane_slide_init	  (GnmPane *pane);
 gboolean gnm_pane_handle_motion (GnmPane *pane,
-				 FooCanvas    *canvas,
-				 GdkEventMotion *event,
+				 GocCanvas    *canvas,
+				 gint64 x, gint64 y,
 				 GnmPaneSlideFlags   slide_flags,
 				 GnmPaneSlideHandler handler,
 				 gpointer user_data);
 
 /************************************************************************/
 
-void gnm_pane_window_to_coord   (GnmPane *pane,
-				 gint    x,	gint    y,
-				 double *wx, double *wy);
-
-/*
- * gnm_foo_canvas_x_w2c:
- * @canvas: a #FooCanvas
- * @x : a position in world coordinate
- *
- * Converts a x position from world coordinates to canvas coordinates.
- */
-#define gnm_foo_canvas_x_w2c(canvas,x) -(int)((x) + ((canvas)->scroll_x1 * (canvas)->pixels_per_unit) - 0.5)
-
-/*
- * gnm_pane_x_w2c:
- * @pane: a #GnmPane
- * @x: position in world coordinates
- *
- * Convert an x position from world coordinates to canvas coordinates,
- * taking into account sheet right to left text setting.
- */
-#define gnm_pane_x_w2c(pane,x) (scg_sheet ((pane)->simple.scg)->text_is_rtl) ? \
-	gnm_foo_canvas_x_w2c ((FooCanvas *) (pane), (x)) : (x)
+void gnm_pane_set_direction     (GnmPane *pane, GocDirection direction);
 
 G_END_DECLS
 
diff --git a/src/gnm-sheet-slicer-combo.c b/src/gnm-sheet-slicer-combo.c
index f8d3357..8c15d78 100644
--- a/src/gnm-sheet-slicer-combo.c
+++ b/src/gnm-sheet-slicer-combo.c
@@ -23,7 +23,7 @@
 #include "gnumeric.h"
 #include "gnm-sheet-slicer-combo.h"
 #include "go-data-slicer-field.h"
-#include "widgets/gnm-cell-combo-foo-view.h"
+#include "widgets/gnm-cell-combo-view.h"
 #include "widgets/gnm-sheet-slicer-combo-foo-view.h"
 
 #include <gsf/gsf-impl-utils.h>
@@ -53,8 +53,8 @@ gnm_sheet_slicer_combo_init (SheetObject *so)
 static SheetObjectView *
 gnm_sheet_slicer_combo_foo_view_new (SheetObject *so, SheetObjectViewContainer *container)
 {
-	return gnm_cell_combo_foo_view_new (so,
-		gnm_sheet_slicer_combo_foo_view_get_type (), container);
+	return gnm_cell_combo_view_new (so,
+		gnm_sheet_slicer_combo_view_get_type (), container);
 }
 
 static void
diff --git a/src/gnm-so-filled.c b/src/gnm-so-filled.c
index 3f9e8ce..4243209 100644
--- a/src/gnm-so-filled.c
+++ b/src/gnm-so-filled.c
@@ -58,69 +58,71 @@ typedef struct {
 typedef SheetObjectClass GnmSOFilledClass;
 
 #ifdef GNM_WITH_GTK
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
+#include <goffice/goffice.h>
+
+typedef struct {
+	SheetObjectView	base;
+	GocItem *bg, *text;
+} FilledItemView;
+
 static void
 so_filled_view_destroy (SheetObjectView *sov)
 {
-	gtk_object_destroy (GTK_OBJECT (sov));
+	g_object_unref (G_OBJECT (sov));
 }
 static void
 so_filled_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem  *view = FOO_CANVAS_ITEM (sov);
+	GocItem  *view = GOC_ITEM (sov);
+	FilledItemView *fiv = (FilledItemView *) sov;
+	double scale = goc_canvas_get_pixels_per_unit (view->canvas); 
 
 	if (visible) {
-		FooCanvasGroup	*group = FOO_CANVAS_GROUP (sov);
 		SheetObject	*so = sheet_object_view_get_so (sov);
 		GnmSOFilled	*sof  = GNM_SO_FILLED (so);
-		double w = fabs (coords [2] - coords [0]);
-		double h = fabs (coords [3] - coords [1]);
+		double w = fabs (coords [2] - coords [0]) / scale;
+		double h = fabs (coords [3] - coords [1]) / scale;
 
-		foo_canvas_item_set (FOO_CANVAS_ITEM (group),
-			"x", MIN (coords [0], coords [2]),
-			"y", MIN (coords [1], coords [3]),
+		goc_item_set (view,
+			"x", MIN (coords [0], coords [2]) / scale,
+			"y", MIN (coords [1], coords [3]) / scale,
 			NULL);
 
-		foo_canvas_item_set (FOO_CANVAS_ITEM (group->item_list->data),
-			"x2", w, "y2", h,
+		goc_item_set (GOC_ITEM (fiv->bg),
+			"width", w, "height", h,
 			NULL);
 
-		if (group->item_list->next) {
-			view = FOO_CANVAS_ITEM (group->item_list->next->data);
+
+		if (fiv->text != NULL && GOC_ITEM (fiv->text)) {
 			w -= (sof->margin_pts.left + sof->margin_pts.right)
-				* view->canvas->pixels_per_unit;
+				/ scale;
 			h -= (sof->margin_pts.top + sof->margin_pts.bottom)
-				* view->canvas->pixels_per_unit;
-
-			foo_canvas_item_set (view,
-				"clip_height", h,
-				"clip_width",  w,
-				"wrap_width",  w,
+				/ scale;
 
-				/* cheap hack to force the attributes to regenerate for
-				 * the rare case where the repositioning was caused by
-				 * a change in zoom */
-				"underline_set", FALSE,
+			goc_item_set (GOC_ITEM (fiv->text),
+				"clip-height", h,
+				"clip-width",  w,
+				"wrap-width",  w,
 				NULL);
 		}
 
-		foo_canvas_item_show (view);
+		goc_item_show (view);
 	} else
-		foo_canvas_item_hide (view);
+		goc_item_hide (view);
 }
 
 static void
-so_filled_foo_view_init (SheetObjectViewIface *sov_iface)
+so_filled_item_view_class_init (SheetObjectViewClass *sov_klass)
 {
-	sov_iface->destroy	= so_filled_view_destroy;
-	sov_iface->set_bounds	= so_filled_view_set_bounds;
+	sov_klass->destroy	= so_filled_view_destroy;
+	sov_klass->set_bounds	= so_filled_view_set_bounds;
 }
-typedef FooCanvasGroup		FilledFooView;
-typedef FooCanvasGroupClass	FilledFooViewClass;
-static GSF_CLASS_FULL (FilledFooView, so_filled_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, FOO_TYPE_CANVAS_GROUP, 0,
-	GSF_INTERFACE (so_filled_foo_view_init, SHEET_OBJECT_VIEW_TYPE))
+
+typedef SheetObjectViewClass	FilledItemViewClass;
+static GSF_CLASS (FilledItemView, so_filled_item_view,
+	so_filled_item_view_class_init, NULL,
+	SHEET_OBJECT_VIEW_TYPE)
+
 #endif /* GNM_WITH_GTK */
 
 /*****************************************************************************/
@@ -154,9 +156,9 @@ sof_default_style (void)
 #include <dialogs/dialogs.h>
 #include <gnumeric-simple-canvas.h>
 #include <gnm-pane.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-rect-ellipse.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-util.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-text.h>
+#include <goffice/canvas/goc-rectangle.h>
+#include <goffice/canvas/goc-ellipse.h>
+#include <goffice/canvas/goc-text.h>
 
 static void
 gnm_so_filled_user_config (SheetObject *so, SheetControl *sc)
@@ -169,74 +171,57 @@ gnm_so_filled_user_config (SheetObject *so, SheetControl *sc)
 }
 
 static void
-cb_gnm_so_filled_style_changed (FooCanvasItem *background, GnmSOFilled const *sof)
+cb_gnm_so_filled_style_changed (GocItem *background, GnmSOFilled const *sof)
 {
 	GOStyle const *style = sof->style;
-	GdkColor outline_buf, *outline_gdk = NULL;
-	GdkColor fill_buf, *fill_gdk = NULL;
-
-	if (style->outline.color != 0 &&
-	    style->outline.width >= 0 &&
-	    style->outline.dash_type != GO_LINE_NONE)
-		outline_gdk = go_color_to_gdk (style->outline.color, &outline_buf);
-
-	if (style->fill.type != GO_STYLE_FILL_NONE)
-		fill_gdk = go_color_to_gdk (style->fill.pattern.back, &fill_buf);
-
-	if (style->outline.width > 0.)	/* in pts */
-		foo_canvas_item_set (background,
-			"width-units",		style->outline.width,
-			"outline-color-gdk",	outline_gdk,
-			"fill-color-gdk",	fill_gdk,
-			NULL);
-	else /* hairline 1 pixel that ignores zoom */
-		foo_canvas_item_set (background,
-			"width-pixels",		1,
-			"outline-color-gdk",	outline_gdk,
-			"fill-color-gdk",	fill_gdk,
-			NULL);
+
+	goc_item_set (background, "style", style, NULL);
 
 }
 static void
 cb_gnm_so_filled_changed (GnmSOFilled const *sof,
 			  G_GNUC_UNUSED GParamSpec *pspec,
-			  FooCanvasGroup *group)
+			  FilledItemView *group)
 {
-	cb_gnm_so_filled_style_changed (group->item_list->data, sof);
-
-	if (group->item_list->next == NULL)
-		foo_canvas_item_new (group, FOO_TYPE_CANVAS_TEXT,
-				     "anchor",	GTK_ANCHOR_NW,
-				     "clip",		TRUE,
-				     "x",		sof->margin_pts.left,
-				     "y",		sof->margin_pts.top,
-				     "attributes",	sof->markup,
+	cb_gnm_so_filled_style_changed (GOC_ITEM (group->bg), sof);
+
+	if (!sof->is_oval && sof->text != NULL) {
+		if (group->text == NULL)
+			group->text = goc_item_new (GOC_GROUP (group), GOC_TYPE_TEXT,
+				"anchor",	GTK_ANCHOR_NW,
+				"clip",		TRUE,
+				"x",		sof->margin_pts.left,
+				"y",		sof->margin_pts.top,
+				"attributes",	sof->markup,
+				NULL);
+		goc_item_set (group->text,
 				     "text", sof->text,
+				     "attributes",	sof->markup,
 				     NULL);
-	foo_canvas_item_set (FOO_CANVAS_ITEM (group->item_list->next->data),
-			     "text", sof->text,
-			     "attributes",	sof->markup,
-			     NULL);
+	} else if (group->text != NULL) {
+		g_object_unref (group->text);
+		group->text = NULL;
+	}
 }
 
 static SheetObjectView *
 gnm_so_filled_new_view (SheetObject *so, SheetObjectViewContainer *container)
 {
 	GnmSOFilled *sof = GNM_SO_FILLED (so);
-	FooCanvasGroup *group = (FooCanvasGroup *) foo_canvas_item_new (
+	FilledItemView *group = (FilledItemView *) goc_item_new (
 		gnm_pane_object_group (GNM_PANE (container)),
-		so_filled_foo_view_get_type (),
+		so_filled_item_view_get_type (),
 		NULL);
 
-	foo_canvas_item_new (group,
-		sof->is_oval ?  FOO_TYPE_CANVAS_ELLIPSE : FOO_TYPE_CANVAS_RECT,
-		"x1", 0., "y1", 0.,
+	group->bg = goc_item_new (GOC_GROUP (group),
+		sof->is_oval ?  GOC_TYPE_ELLIPSE : GOC_TYPE_RECTANGLE,
+		"x", 0., "y", 0.,
 		NULL);
 	cb_gnm_so_filled_changed (sof, NULL, group);
 	g_signal_connect_object (sof,
 		"notify", G_CALLBACK (cb_gnm_so_filled_changed),
 		group, 0);
-	return gnm_pane_object_register (so, FOO_CANVAS_ITEM (group), TRUE);
+	return gnm_pane_object_register (so, GOC_ITEM (group), TRUE);
 }
 
 #endif /* GNM_WITH_GTK */
@@ -384,9 +369,10 @@ gnm_so_filled_prep_sax_parser (SheetObject *so, GsfXMLIn *xin,
 			g_object_set (G_OBJECT (sof), "text", attrs[1], NULL);
 		else if (attr_eq (attrs[0], "LabelFormat")) {
 			GOFormat * fmt = go_format_new_from_XL (attrs[1]);
-			g_object_set (G_OBJECT (sof),
-				      "markup", go_format_get_markup (fmt),
-				      NULL);
+			if (go_format_is_markup (fmt))
+				g_object_set (G_OBJECT (sof),
+					      "markup", go_format_get_markup (fmt),
+					      NULL);
 			go_format_unref (fmt);
 		} else if (gnm_xml_attr_int     (attrs, "Type", &type))
 			sof->is_oval = (type == 102);
@@ -539,8 +525,6 @@ gnm_so_filled_init (GObject *obj)
 {
 	GnmSOFilled *sof = GNM_SO_FILLED (obj);
 	sof->style = sof_default_style ();
-	sof->text = g_strdup (""); /* If we initialize with NULL, the canvas item */
-	                           /* does not react on changes */
 	sof->markup = NULL;
 	sof->margin_pts.top  = sof->margin_pts.bottom = 3;
 	sof->margin_pts.left = sof->margin_pts.right  = 5;
diff --git a/src/gnm-so-line.c b/src/gnm-so-line.c
index b31fb2a..d16f0e3 100644
--- a/src/gnm-so-line.c
+++ b/src/gnm-so-line.c
@@ -78,9 +78,6 @@ typedef SheetObjectClass GnmSOLineClass;
 static SheetObjectClass *gnm_so_line_parent_class;
 
 #ifdef GNM_WITH_GTK
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-line.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-util.h>
 static void
 so_line_view_destroy (SheetObjectView *sov)
 {
@@ -89,7 +86,7 @@ so_line_view_destroy (SheetObjectView *sov)
 static void
 so_line_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem	*view = FOO_CANVAS_ITEM (sov);
+	GocItem	*view = GOC_ITEM (sov), *item = GOC_ITEM (GOC_GROUP (view)->children->data);
 	SheetObject	*so = sheet_object_view_get_so (sov);
 	GOStyleLine const *style = &GNM_SO_LINE (so)->style->line;
 
@@ -97,30 +94,29 @@ so_line_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean vi
 
 	if (visible &&
 	    style->color != 0 && style->width >= 0 && style->dash_type != GO_LINE_NONE) {
-		FooCanvasPoints *points = foo_canvas_points_new (2);
-		points->coords[0] = coords[0];
-		points->coords[1] = coords[1];
-		points->coords[2] = coords[2];
-		points->coords[3] = coords[3];
-		foo_canvas_item_set (view, "points", points, NULL);
-		foo_canvas_points_free (points);
-		foo_canvas_item_show (view);
+		goc_item_set (item,
+		              "x0", coords[0],
+		              "y0", coords[1],
+		              "x1", coords[2],
+		              "y1", coords[3],
+		              NULL);
+		goc_item_show (view);
 	} else
-		foo_canvas_item_hide (view);
+		goc_item_hide (view);
 }
 
 static void
-so_line_foo_view_init (SheetObjectViewIface *sov_iface)
+so_line_goc_view_class_init (SheetObjectViewClass *sov_klass)
 {
-	sov_iface->destroy	= so_line_view_destroy;
-	sov_iface->set_bounds	= so_line_view_set_bounds;
+	sov_klass->destroy	= so_line_view_destroy;
+	sov_klass->set_bounds	= so_line_view_set_bounds;
 }
-typedef FooCanvasLine		LineFooView;
-typedef FooCanvasLineClass	LineFooViewClass;
-static GSF_CLASS_FULL (LineFooView, so_line_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, FOO_TYPE_CANVAS_LINE, 0,
-	GSF_INTERFACE (so_line_foo_view_init, SHEET_OBJECT_VIEW_TYPE))
+typedef SheetObjectView		LineGocView;
+typedef SheetObjectViewClass	LineGocViewClass;
+static GSF_CLASS (LineGocView, so_line_goc_view,
+	so_line_goc_view_class_init, NULL,
+	SHEET_OBJECT_VIEW_TYPE)
+
 #endif /* GNM_WITH_GTK */
 enum {
 	SOL_PROP_0,
@@ -158,28 +154,14 @@ gnm_so_line_user_config (SheetObject *so, SheetControl *sc)
 static void
 cb_gnm_so_line_changed (GnmSOLine const *sol,
 			G_GNUC_UNUSED GParamSpec *pspec,
-			FooCanvasItem *item)
+			GocItem *item)
 {
-	GOStyleLine const *style = &sol->style->line;
-	GdkColor buf, *gdk = NULL;
-
-	if (style->color != 0 && style->width >= 0 && style->dash_type != GO_LINE_NONE)
-		gdk = go_color_to_gdk (style->color, &buf);
-
-	if (style->width > 0.)	/* in pts */
-		foo_canvas_item_set (item,
-			"width_units",		style->width,
-			"fill_color_gdk",	gdk,
-			NULL);
-	else /* hairline 1 pixel that ignores zoom */
-		foo_canvas_item_set (item,
-			"width_pixels",		1,
-			"fill_color_gdk",	gdk,
-			NULL);
-	foo_canvas_item_set (item,
-		"arrow_shape_a",	sol->end_arrow.a,
-		"arrow_shape_b",	sol->end_arrow.b,
-		"arrow_shape_c",	sol->end_arrow.c,
+	item = GOC_ITEM (GOC_GROUP (item)->children->data);
+	goc_item_set (item,
+	        "style",		sol->style,
+		"arrow-shape-a",	sol->end_arrow.a,
+		"arrow-shape-b",	sol->end_arrow.b,
+		"arrow-shape-c",	sol->end_arrow.c,
 		NULL);
 }
 
@@ -187,10 +169,13 @@ static SheetObjectView *
 gnm_so_line_new_view (SheetObject *so, SheetObjectViewContainer *container)
 {
 	GnmSOLine const *sol = GNM_SO_LINE (so);
-	FooCanvasItem *item = foo_canvas_item_new (
+	GocItem *item = goc_item_new (
 		gnm_pane_object_group (GNM_PANE (container)),
-		so_line_foo_view_get_type (),
-		"last_arrowhead",	(sol->end_arrow.a != 0.),
+		so_line_goc_view_get_type (),
+		NULL);
+	goc_item_new (GOC_GROUP (item),
+		GOC_TYPE_LINE,
+		"arrowhead",	(sol->end_arrow.a != 0.),
 		NULL);
 	cb_gnm_so_line_changed (sol, NULL, item);
 	g_signal_connect_object (G_OBJECT (sol),
diff --git a/src/gnm-so-polygon.c b/src/gnm-so-polygon.c
index 14d06b9..2bf0fd4 100644
--- a/src/gnm-so-polygon.c
+++ b/src/gnm-so-polygon.c
@@ -53,8 +53,6 @@ typedef SheetObjectClass GnmSOPolygonClass;
 
 #ifdef GNM_WITH_GTK
 #include "gnm-pane.h"
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-polygon.h>
 static void
 so_polygon_view_destroy (SheetObjectView *sov)
 {
@@ -63,55 +61,55 @@ so_polygon_view_destroy (SheetObjectView *sov)
 static void
 so_polygon_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
+	GocItem *view = GOC_ITEM (sov->base.children->data);
 
 	if (visible) {
 		SheetObject		*so   = sheet_object_view_get_so (sov);
 		GnmSOPolygon const	*sop  = GNM_SO_POLYGON (so);
-		unsigned		 i;
-		FooCanvasPoints		*pts;
-		double *dst, x_scale, y_scale, x_translate, y_translate;
+		unsigned		 i, n;
+		GocPoints		*pts;
+		double x_scale, y_scale, x_translate, y_translate;
 		double const *src;
 
 		if (sop->points == NULL)
 			return;
 
-		i = sop->points->len / 2;
-		if (i == 0)
+		n = sop->points->len / 2;
+		if (n == 0)
 			return;
 
-		pts = foo_canvas_points_new (i);
+		pts = goc_points_new (n);
 		x_scale = fabs (coords[2] - coords[0]);
 		y_scale = fabs (coords[3] - coords[1]);
 		x_translate = MIN (coords[0], coords[2]),
 		y_translate = MIN (coords[1], coords[3]);
 
 		src = &g_array_index (sop->points, double, 0);
-		dst = pts->coords;
-		for ( ; i-- > 0; dst += 2, src += 2) {
-			dst[0] = x_translate + x_scale * src[0];
-			dst[1] = y_translate + y_scale * src[1];
+		for (i = 0 ; i < n; src += 2, i++) {
+			pts->points[i].x = x_translate + x_scale * src[0];
+			pts->points[i].y = y_translate + y_scale * src[1];
 		}
 
-		foo_canvas_item_set (view, "points", pts, NULL);
-		foo_canvas_points_free (pts);
-		foo_canvas_item_show (view);
+		goc_item_set (view, "points", pts, NULL);
+		goc_points_unref (pts);
+		goc_item_show (GOC_ITEM (view));
 	} else
-		foo_canvas_item_hide (view);
+		goc_item_hide (GOC_ITEM (view));
 }
 
 static void
-so_polygon_foo_view_init (SheetObjectViewIface *sov_iface)
+so_polygon_goc_view_class_init (SheetObjectViewClass *sov_klass)
 {
-	sov_iface->destroy	= so_polygon_view_destroy;
-	sov_iface->set_bounds	= so_polygon_view_set_bounds;
+	sov_klass->destroy	= so_polygon_view_destroy;
+	sov_klass->set_bounds	= so_polygon_view_set_bounds;
 }
-typedef FooCanvasPolygon	PolygonFooView;
-typedef FooCanvasPolygonClass	PolygonFooViewClass;
-static GSF_CLASS_FULL (PolygonFooView, so_polygon_foo_view,
-	NULL, NULL, NULL, NULL, NULL,
-	FOO_TYPE_CANVAS_POLYGON, 0,
-	GSF_INTERFACE (so_polygon_foo_view_init, SHEET_OBJECT_VIEW_TYPE))
+
+typedef SheetObjectView	PolygonGocView;
+typedef SheetObjectViewClass	PolygonGocViewClass;
+static GSF_CLASS (PolygonGocView, so_polygon_goc_view,
+	so_polygon_goc_view_class_init, NULL,
+	SHEET_OBJECT_VIEW_TYPE)
+
 #endif /* GNM_WITH_GTK */
 
 /*****************************************************************************/
@@ -131,6 +129,7 @@ sop_default_style (void)
 	res->outline.width = 0; /* hairline */
 	res->outline.color = RGBA_BLACK;
 	res->outline.dash_type = GO_LINE_SOLID; /* anything but 0 */
+	res->outline.join = CAIRO_LINE_JOIN_ROUND;
 	res->fill.type = GO_STYLE_FILL_PATTERN;
 	go_pattern_set_solid (&res->fill.pattern, RGBA_WHITE);
 	return res;
@@ -141,42 +140,23 @@ sop_default_style (void)
 #include <dialogs/dialogs.h>
 
 static void
-cb_gnm_so_polygon_style_changed (FooCanvasItem *view, GnmSOPolygon const *sop)
+cb_gnm_so_polygon_style_changed (GocItem *view, GnmSOPolygon const *sop)
 {
+	GocItem *item = GOC_ITEM (GOC_GROUP (view)->children->data);
 	GOStyle const *style = sop->style;
-	GdkColor outline_buf, *outline_gdk = NULL;
-	GdkColor fill_buf, *fill_gdk = NULL;
-
-	if (style->outline.color != 0 &&
-	    style->outline.width >= 0 &&
-	    style->outline.dash_type != GO_LINE_NONE)
-		outline_gdk = go_color_to_gdk (style->outline.color, &outline_buf);
-
-	if (style->fill.type != GO_STYLE_FILL_NONE)
-		fill_gdk = go_color_to_gdk (style->fill.pattern.back, &fill_buf);
-
-	if (style->outline.width > 0.)	/* in pts */
-		foo_canvas_item_set (view,
-			"width-units",		style->outline.width,
-			"outline-color-gdk",	outline_gdk,
-			"fill-color-gdk",	fill_gdk,
-			NULL);
-	else /* hairline 1 pixel that ignores zoom */
-		foo_canvas_item_set (view,
-			"width-pixels",		1,
-			"outline-color-gdk",	outline_gdk,
-			"fill-color-gdk",	fill_gdk,
-			NULL);
-
+	goc_item_set (item, "style", style, NULL);
 }
+
 static SheetObjectView *
 gnm_so_polygon_new_view (SheetObject *so, SheetObjectViewContainer *container)
 {
 	GnmSOPolygon *sop = GNM_SO_POLYGON (so);
-	FooCanvasItem *item = foo_canvas_item_new (
+	GocItem *item = goc_item_new (
 		gnm_pane_object_group (GNM_PANE (container)),
-		so_polygon_foo_view_get_type (),
-		/* "join_style",	GDK_JOIN_ROUND, */
+		so_polygon_goc_view_get_type (),
+		NULL);
+	goc_item_new (GOC_GROUP (item),
+		GOC_TYPE_POLYGON,
 		NULL);
 	cb_gnm_so_polygon_style_changed (item, sop);
 	g_signal_connect_object (sop,
diff --git a/src/gnumeric-simple-canvas.c b/src/gnumeric-simple-canvas.c
index 4cf5672..d52b88b 100644
--- a/src/gnumeric-simple-canvas.c
+++ b/src/gnumeric-simple-canvas.c
@@ -4,6 +4,7 @@
 #include "gnumeric-simple-canvas.h"
 
 #include "sheet-control-gui-priv.h"
+#include <goffice/goffice.h>
 #include <gsf/gsf-impl-utils.h>
 
 static GtkWidgetClass const *parent;
@@ -37,51 +38,41 @@ gnm_simple_canvas_class_init (GtkWidgetClass *klass)
 
 GSF_CLASS (GnmSimpleCanvas, gnm_simple_canvas,
 	   gnm_simple_canvas_class_init, NULL,
-	   FOO_TYPE_CANVAS)
+	   GOC_TYPE_CANVAS)
 
-FooCanvas *
+GocCanvas *
 gnm_simple_canvas_new (SheetControlGUI *scg)
 {
 	GnmSimpleCanvas *gcanvas = g_object_new (GNM_SIMPLE_CANVAS_TYPE, NULL);
 	gcanvas->scg  = scg;
 
-	/* YES! die die die */
-	foo_canvas_set_center_scroll_region (FOO_CANVAS (gcanvas), FALSE);
-
-	return FOO_CANVAS (gcanvas);
+	return GOC_CANVAS (gcanvas);
 }
 
 void
-gnm_simple_canvas_ungrab (FooCanvasItem *item, guint32 etime)
+gnm_simple_canvas_ungrab (GocItem *item, guint32 etime)
 {
 	GnmSimpleCanvas *gcanvas = GNM_SIMPLE_CANVAS(item->canvas);
 
 	g_return_if_fail (gcanvas != NULL);
 
 	gcanvas->scg->grab_stack--;
-	foo_canvas_item_ungrab (item, etime);
-
-	/* We flush after the ungrab, to have the ungrab take effect
-	 * immediately operations might take a while, and we
-	 * do not want the mouse to be grabbed the entire time.
-	 */
-	gdk_flush ();
+	goc_item_ungrab (item);
 }
 
+/* FIXME this funtion has been simplfied a lot, if it really works like that
+ we should remove unused args and not return anything except void */
 int
-gnm_simple_canvas_grab (FooCanvasItem *item, unsigned int event_mask,
+gnm_simple_canvas_grab (GocItem *item, unsigned int event_mask,
 			GdkCursor *cursor, guint32 etime)
 {
 	GnmSimpleCanvas *gcanvas = GNM_SIMPLE_CANVAS(item->canvas);
-	int res;
+	int res = 0;
 
 	g_return_val_if_fail (gcanvas != NULL, TRUE);
 
 	gcanvas->scg->grab_stack++;
-	res = foo_canvas_item_grab (item, event_mask, cursor, etime);
-
-	/* Be extra paranoid.  Ensure that the grab is registered */
-	gdk_flush ();
+	goc_item_grab (item);
 
 	return res;
 }
diff --git a/src/gnumeric-simple-canvas.h b/src/gnumeric-simple-canvas.h
index c07f5f5..5a1b37a 100644
--- a/src/gnumeric-simple-canvas.h
+++ b/src/gnumeric-simple-canvas.h
@@ -3,27 +3,27 @@
 # define _GNM_SIMPLE_CANVAS_H_
 
 #include "gui-gnumeric.h"
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
+#include <goffice/goffice.h>
 
 G_BEGIN_DECLS
 
 typedef struct {
-	FooCanvas   canvas;
+	GocCanvas   canvas;
 	SheetControlGUI *scg;
 } GnmSimpleCanvas;
 
 typedef struct {
-	FooCanvasClass   canvas;
+	GocCanvasClass   canvas;
 } GnmSimpleCanvasClass;
 
 #define GNM_SIMPLE_CANVAS_TYPE     (gnm_simple_canvas_get_type ())
 #define GNM_SIMPLE_CANVAS(obj)     (G_TYPE_CHECK_INSTANCE_CAST((obj), GNM_SIMPLE_CANVAS_TYPE, GnmSimpleCanvas))
 
 GType		 gnm_simple_canvas_get_type (void);
-FooCanvas	*gnm_simple_canvas_new      (SheetControlGUI *scg);
+GocCanvas	*gnm_simple_canvas_new      (SheetControlGUI *scg);
 
-void gnm_simple_canvas_ungrab (FooCanvasItem *item, guint32 etime);
-int  gnm_simple_canvas_grab   (FooCanvasItem *item, unsigned int event_mask,
+void gnm_simple_canvas_ungrab (GocItem *item, guint32 etime);
+int  gnm_simple_canvas_grab   (GocItem *item, unsigned int event_mask,
 			       GdkCursor *cursor, guint32 etime);
 
 G_END_DECLS
diff --git a/src/gui-util.c b/src/gui-util.c
index cafb53d..c999a4e 100644
--- a/src/gui-util.c
+++ b/src/gui-util.c
@@ -1350,12 +1350,11 @@ gnm_dialog_setup_destroy_handlers (GtkDialog *dialog,
 
 
 void
-gnm_canvas_get_position (FooCanvas *canvas, int *x, int *y, int px, int py)
+gnm_canvas_get_position (GocCanvas *canvas, int *x, int *y, gint64 px, gint64 py)
 {
 	GtkWidget *cw = GTK_WIDGET (canvas);
 	GdkWindow *cbw = GTK_LAYOUT (cw)->bin_window;
 	int wx, wy, ox, oy;
-	double pdx, pdy;
 
 	/*
 	 * Get offsets for the 16-bit X11 system within the 32-bit gdk system.
@@ -1365,10 +1364,11 @@ gnm_canvas_get_position (FooCanvas *canvas, int *x, int *y, int px, int py)
 
 	gdk_window_get_origin (cbw, &wx, &wy);
 
-	foo_canvas_world_to_window (canvas, px, py, &pdx, &pdy);
+	px = (px - canvas->scroll_x1) / canvas->pixels_per_unit;
+	py = (py - canvas->scroll_y1) / canvas->pixels_per_unit;
 
-	*x = (int)pdx + wx - ox;
-	*y = (int)pdy + wy - oy;
+	*x = px + wx - ox;
+	*y = py + wy - oy;
 }
 
 
diff --git a/src/gui-util.h b/src/gui-util.h
index 45e4863..bd566c5 100644
--- a/src/gui-util.h
+++ b/src/gui-util.h
@@ -124,8 +124,8 @@ void gnm_dialog_setup_destroy_handlers (GtkDialog *dialog,
 					WBCGtk *wbcg,
 					GnmDialogDestroyOptions what);
 
-void gnm_canvas_get_position (FooCanvas *canvas, int *x, int *y,
-			      int px, int py);
+void gnm_canvas_get_position (GocCanvas *canvas, int *x, int *y,
+			      gint64 px, gint64 py);
 
 gboolean gnm_check_for_plugins_missing (char const **ids, GtkWindow *parent);
 
diff --git a/src/item-bar.c b/src/item-bar.c
index 4d3b774..ac4ca9b 100644
--- a/src/item-bar.c
+++ b/src/item-bar.c
@@ -24,6 +24,7 @@
 #include "parse-util.h"
 #include "commands.h"
 
+#include <goffice/goffice.h>
 #include <gsf/gsf-impl-utils.h>
 #include <gtk/gtk.h>
 #define GNUMERIC_ITEM "BAR"
@@ -32,7 +33,7 @@
 #include <string.h>
 
 struct _ItemBar {
-	FooCanvasItem	 base;
+	GocItem	 base;
 
 	GnmPane		*pane;
 	GdkGC           *text_gc, *filter_gc, *lines, *shade;
@@ -56,8 +57,8 @@ struct _ItemBar {
 	} pango;
 };
 
-typedef FooCanvasItemClass ItemBarClass;
-static FooCanvasItemClass *parent_class;
+typedef GocItemClass ItemBarClass;
+static GocItemClass *parent_class;
 
 enum {
 	ITEM_BAR_PROP_0,
@@ -165,7 +166,6 @@ item_bar_calc_size (ItemBar *ib)
 					'A');
 
 	ib->indent = ib_compute_pixels_from_indent (sheet, ib->is_col_header);
-	foo_canvas_item_request_update (&ib->base);
 
 	return ib->indent +
 		(ib->is_col_header ? ib->cell_height : ib->cell_width);
@@ -184,51 +184,30 @@ item_bar_indent	(ItemBar const *ib)
 }
 
 static void
-item_bar_update (FooCanvasItem *item,  double i2w_dx, double i2w_dy, int flags)
+item_bar_update_bounds (GocItem *item)
 {
 	ItemBar *ib = ITEM_BAR (item);
-
-	item->x1 = 0;
-	item->y1 = 0;
+	item->x0 = 0;
+	item->y0 = 0;
 	if (ib->is_col_header) {
-		item->x2 = G_MAXINT/2;
-		item->y2 = (ib->cell_height + ib->indent);
+		item->x1 = G_MAXINT64/2;
+		item->y1 = (ib->cell_height + ib->indent);
 	} else {
-		item->x2 = (ib->cell_width  + ib->indent);
-		item->y2 = G_MAXINT/2;
+		item->x1 = (ib->cell_width  + ib->indent);
+		item->y1 = G_MAXINT64/2;
 	}
-
-	if (parent_class->update)
-		(*parent_class->update)(item, i2w_dx, i2w_dy, flags);
 }
 
 static void
-item_bar_realize (FooCanvasItem *item)
+item_bar_realize (GocItem *item)
 {
 	ItemBar *ib;
-	GdkWindow *window;
-	GtkStyle *style;
 	GdkDisplay *display;
 
 	if (parent_class->realize)
 		(*parent_class->realize)(item);
 
 	ib = ITEM_BAR (item);
-	window = GTK_WIDGET (item->canvas)->window;
-
-	/* Configure our gc */
-	style = gtk_widget_get_style (GTK_WIDGET (item->canvas));
-
-	ib->text_gc = gdk_gc_new (window);
-	gdk_gc_set_rgb_fg_color (ib->text_gc, &style->text[GTK_STATE_NORMAL]);
-	ib->filter_gc = gdk_gc_new (window);
-	gdk_gc_set_rgb_fg_color (ib->filter_gc, &gs_yellow);
-	ib->shade = gdk_gc_new (window);
-	gdk_gc_set_rgb_fg_color (ib->shade, &style->dark[GTK_STATE_NORMAL]);
-	ib->lines = gdk_gc_new (window);
-	gdk_gc_copy (ib->lines, ib->text_gc);
-	gdk_gc_set_line_attributes (ib->lines, 2, GDK_LINE_SOLID,
-				    GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
 
 	display = gtk_widget_get_display (GTK_WIDGET (item->canvas));
 	ib->normal_cursor = gdk_cursor_new_for_display (display, GDK_LEFT_PTR);
@@ -240,69 +219,67 @@ item_bar_realize (FooCanvasItem *item)
 }
 
 static void
-item_bar_unrealize (FooCanvasItem *item)
+item_bar_unrealize (GocItem *item)
 {
 	ItemBar *ib = ITEM_BAR (item);
 
-	g_object_unref (G_OBJECT (ib->text_gc));
-	g_object_unref (G_OBJECT (ib->filter_gc));
-	g_object_unref (G_OBJECT (ib->lines));
-	g_object_unref (G_OBJECT (ib->shade));
 	gdk_cursor_unref (ib->change_cursor);
 	gdk_cursor_unref (ib->normal_cursor);
-
-	if (parent_class->unrealize)
-		(*parent_class->unrealize)(item);
 }
 
 static void
-ib_draw_cell (ItemBar const * const ib, GdkDrawable *drawable,
-	      GdkGC *text_gc, ColRowSelectionType const type,
-	      char const * const str, GdkRectangle *rect)
+ib_draw_cell (ItemBar const * const ib, cairo_t *cr,
+	      ColRowSelectionType const type,
+	      char const * const str, GocRect *rect)
 {
-	GtkWidget	*canvas = GTK_WIDGET (ib->base.canvas);
-	GdkGC		*gc;
+	GtkLayout	*canvas = GTK_LAYOUT (ib->base.canvas);
+	GtkWidget   *widget = GTK_WIDGET (canvas);
 	PangoFont	*font;
 	PangoRectangle   size;
+	GOColor color;
 	int shadow, ascent;
 
 	switch (type) {
 	default:
 	case COL_ROW_NO_SELECTION:
 		shadow = GTK_SHADOW_OUT;
-		gc     = canvas->style->bg_gc [GTK_STATE_ACTIVE];
 		font   = ib->normal_font;
+		color = GDK_TO_UINT (widget->style->bg[GTK_STATE_ACTIVE]);
 		ascent = ib->normal_font_ascent;
 		break;
 
 	case COL_ROW_PARTIAL_SELECTION:
 		shadow = GTK_SHADOW_OUT;
-		gc     = canvas->style->dark_gc [GTK_STATE_PRELIGHT];
 		font   = ib->bold_font;
+		color = GDK_TO_UINT (widget->style->dark[GTK_STATE_PRELIGHT]);
 		ascent = ib->bold_font_ascent;
 		break;
 
 	case COL_ROW_FULL_SELECTION:
 		shadow = GTK_SHADOW_IN;
-		gc     = canvas->style->dark_gc [GTK_STATE_NORMAL];
 		font   = ib->bold_font;
+		color = GDK_TO_UINT (widget->style->dark[GTK_STATE_NORMAL]);
 		ascent = ib->bold_font_ascent;
 		break;
 	}
 	/* When we are really small leave out the shadow and the text */
+	cairo_save (cr);
+	cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (color));
 	if (rect->width <= 2 || rect->height <= 2) {
-		gdk_draw_rectangle (drawable, gc, TRUE,
-			rect->x, rect->y, rect->width, rect->height);
+		cairo_rectangle (cr, rect->x, rect->y, rect->width, rect->height);
+		cairo_fill (cr);
+		cairo_restore (cr);
 		return;
 	}
 
-	gdk_draw_rectangle (drawable, gc, TRUE,
-		rect->x + 1, rect->y + 1, rect->width - 1, rect->height - 1);
+	cairo_rectangle (cr, rect->x + 1, rect->y + 1, rect->width - 1, rect->height - 1);
+	cairo_fill (cr);
+	cairo_restore (cr);
 
 	/* The widget parameters could be NULL, but if so some themes would emit a warning.
 	 * (Murrine is known to do this: http://bugzilla.gnome.org/show_bug.cgi?id=564410). */
-	gtk_paint_shadow (canvas->style, drawable, GTK_STATE_NORMAL, shadow,
-			  NULL, canvas, "GnmItemBarCell",
+	gtk_paint_shadow (widget->style, canvas->bin_window, GTK_STATE_NORMAL, shadow,
+			  NULL, widget, "GnmItemBarCell",
 			  rect->x, rect->y, rect->width + 1, rect->height + 1);
 
 	g_return_if_fail (font != NULL);
@@ -311,11 +288,13 @@ ib_draw_cell (ItemBar const * const ib, GdkDrawable *drawable,
 	pango_shape (str, strlen (str), &(ib->pango.item->analysis), ib->pango.glyphs);
 	pango_glyph_string_extents (ib->pango.glyphs, font, NULL, &size);
 
-	gdk_gc_set_clip_rectangle (text_gc, rect);
-	gdk_draw_glyphs (drawable, text_gc, font,
-		rect->x + (rect->width - PANGO_PIXELS (size.width)) / 2,
-		rect->y + (rect->height - PANGO_PIXELS (size.height)) / 2 + ascent,
-		ib->pango.glyphs);
+	cairo_save (cr);
+	cairo_set_source_rgb (cr, 0., 0., 0.);
+	cairo_translate (cr,
+					 rect->x + (rect->width - PANGO_PIXELS (size.width)) / 2,
+					 rect->y  + (rect->height - PANGO_PIXELS (size.height)) / 2 + ascent);
+	pango_cairo_show_glyph_string (cr, font, ib->pango.glyphs);
+	cairo_restore (cr);
 }
 
 int
@@ -324,9 +303,11 @@ item_bar_group_size (ItemBar const *ib, int max_outline)
 	return (max_outline > 0) ? (ib->indent - 2) / (max_outline + 1) : 0;
 }
 
-static void
-item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expose)
+static gboolean
+item_bar_draw_region (GocItem const *item, cairo_t *cr, double x_0, double y_0, double x_1, double y_1)
 {
+	double scale = item->canvas->pixels_per_unit;
+	int x0, x1, y0, y1;
 	ItemBar const         *ib = ITEM_BAR (item);
 	GnmPane	 const	      *pane = ib->pane;
 	SheetControlGUI const *scg    = pane->simple.scg;
@@ -339,34 +320,32 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 	gboolean const draw_below = sheet->outline_symbols_below != FALSE;
 	gboolean const draw_right = sheet->outline_symbols_right != FALSE;
 	int prev_level;
-	GdkRectangle rect;
-	GdkPoint points[3];
+	GocRect rect;
+	GocPoint points[3];
 	gboolean const has_object = scg->wbcg->new_object != NULL || scg->selected_objects != NULL;
 	gboolean const rtl = sheet->text_is_rtl != FALSE;
 	int shadow;
 	int first_line_offset = 1;
+	GtkStyle *style = gtk_widget_get_style (canvas);
+	GOColor color = GDK_TO_UINT (style->text[GTK_STATE_NORMAL]);
+	goc_canvas_c2w (item->canvas, x_0, y_0, &x0, &y0);
+	goc_canvas_c2w (item->canvas, x_1, y_1, &x1, &y1);
 
 	if (ib->is_col_header) {
 		int const inc = item_bar_group_size (ib, sheet->cols.max_outline_level);
 		int const base_pos = .2 * inc;
 		int const len = (inc > 4) ? 4 : inc;
-		int end = expose->area.x;
-		int total, col = pane->first.col;
+		int end, total, col = pane->first.col;// = 0;
 		gboolean const char_label = !sheet->convs->r1c1_addresses;
 
 		/* shadow type selection must be keep in sync with code in ib_draw_cell */
+		goc_canvas_c2w (item->canvas, pane->first_offset.x / scale, 0, &total, NULL);
+		end = x1;
 		rect.y = ib->indent;
 		rect.height = ib->cell_height;
 		shadow = (col > 0 && !has_object && sv_selection_col_type (sv, col-1) == COL_ROW_FULL_SELECTION)
 			? GTK_SHADOW_IN : GTK_SHADOW_OUT;
 
-		if (rtl)
-			total = gnm_foo_canvas_x_w2c (item->canvas, pane->first_offset.col);
-		else {
-			total = pane->first_offset.col;
-			end += expose->area.width;
-		}
-
 		if (col > 0) {
 			cri = sheet_col_get_info (sheet, col-1);
 			prev_visible = cri->visible;
@@ -378,7 +357,7 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 
 		do {
 			if (col >= gnm_sheet_get_max_cols (sheet))
-				return;
+				return TRUE;
 
 			/* DO NOT enable resizing all until we get rid of
 			 * resize_start_pos.  It will be wrong if things ahead
@@ -403,7 +382,7 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 				}
 
 				rect.width = pixels;
-				ib_draw_cell (ib, drawable, ib->text_gc,
+				ib_draw_cell (ib, cr,
 					       has_object
 						       ? COL_ROW_NO_SELECTION
 						       : sv_selection_col_type (sv, col),
@@ -413,6 +392,11 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 					       &rect);
 
 				if (len > 0) {
+					cairo_save (cr);
+					cairo_set_line_width (cr, 2.0);
+					cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+					cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+					cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (color));
 					if (!draw_right) {
 						next = sheet_col_get_info (sheet, col + 1);
 						prev_level = next->outline_level;
@@ -426,16 +410,17 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 					for (level = cri->outline_level; i++ < level ; pos += inc) {
 						points[0].y = points[1].y = pos;
 						points[2].y		  = pos + len;
-						if (i > prev_level)
-							gdk_draw_lines (drawable, ib->lines, points, 3);
-						else if (rtl)
-							gdk_draw_line (drawable, ib->lines,
-								       left - first_line_offset, pos,
-								       total + pixels,		 pos);
-						else
-							gdk_draw_line (drawable, ib->lines,
-								       left - first_line_offset, pos,
-								       total,			 pos);
+						if (i > prev_level) {
+							cairo_move_to (cr, points[0].x, points[0].y);
+							cairo_line_to (cr, points[1].x, points[1].y);
+							cairo_line_to (cr, points[2].x, points[2].y);
+						} else if (rtl) {
+							cairo_move_to (cr, left - first_line_offset, pos);
+							cairo_line_to (cr, total + pixels, pos);
+						} else {
+							cairo_move_to (cr, left - first_line_offset, pos);
+							cairo_line_to (cr, total, pos);
+						}
 					}
 					first_line_offset = 0;
 
@@ -450,7 +435,7 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 							else if (size < 6)
 								safety = 6 - size;
 
-							gtk_paint_shadow (canvas->style, drawable,
+							gtk_paint_shadow (canvas->style, GTK_LAYOUT (canvas)->bin_window,
 								 GTK_STATE_NORMAL,
 								 prev_visible ? GTK_SHADOW_OUT : GTK_SHADOW_IN,
 								 NULL, NULL, "GnmItemBarCell",
@@ -459,18 +444,16 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 								if (!prev_visible) {
 									top++;
 									left++;
-									gdk_draw_line (drawable, ib->lines,
-										       left+size/2, top+3,
-										       left+size/2, top+size-4);
+									cairo_move_to (cr, left+size/2, top+3);
+									cairo_line_to (cr, left+size/2, top+size-4);
 								}
-								gdk_draw_line (drawable, ib->lines,
-									       left+3,	    top+size/2,
-									       left+size-4, top+size/2);
+								cairo_move_to (cr, left+3,	    top+size/2);
+								cairo_line_to (cr, left+size-4, top+size/2);
 							}
-						} else if (level > 0)
-							gdk_draw_line (drawable, ib->lines,
-								       left+pixels/2, pos,
-								       left+pixels/2, pos+len);
+						} else if (level > 0) {
+							cairo_move_to (cr, left+pixels/2, pos);
+							cairo_line_to (cr, left+pixels/2, pos+len);
+						}
 					} else {
 						if (prev_level > level) {
 							int safety = 0;
@@ -484,7 +467,7 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 								safety = 6 - size;
 
 							right = (rtl ? (total + pixels) : total) - size;
-							gtk_paint_shadow (canvas->style, drawable,
+							gtk_paint_shadow (canvas->style, GTK_LAYOUT (canvas)->bin_window,
 								 GTK_STATE_NORMAL,
 								 prev_visible ? GTK_SHADOW_OUT : GTK_SHADOW_IN,
 								 NULL, NULL, "GnmItemBarCell",
@@ -493,19 +476,19 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 								if (!prev_visible) {
 									top++;
 									right++;
-									gdk_draw_line (drawable, ib->lines,
-										       right+size/2, top+3,
-										       right+size/2, top+size-4);
+									cairo_move_to (cr, right+size/2, top+3);
+									cairo_line_to (cr, right+size/2, top+size-4);
 								}
-								gdk_draw_line (drawable, ib->lines,
-									       right+3,	    top+size/2,
-									       right+size-4, top+size/2);
+								cairo_move_to (cr, right+3,	    top+size/2);
+								cairo_line_to (cr, right+size-4, top+size/2);
 							}
-						} else if (level > 0)
-							gdk_draw_line (drawable, ib->lines,
-								       left+pixels/2, pos,
-								       left+pixels/2, pos+len);
+						} else if (level > 0) {
+								cairo_move_to (cr, left+pixels/2, pos);
+								cairo_line_to (cr, left+pixels/2, pos+len);
+						}
 					}
+					cairo_stroke (cr);
+					cairo_restore (cr);
 				}
 			}
 			prev_visible = cri->visible;
@@ -516,10 +499,10 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 		int const inc = item_bar_group_size (ib, sheet->rows.max_outline_level);
 		int base_pos = .2 * inc;
 		int const len = (inc > 4) ? 4 : inc;
-		int const end = expose->area.y + expose->area.height;
+		int const end = y1;
 		int const dir = rtl ? -1 : 1;
 
-		int total = pane->first_offset.row;
+		int total = pane->first_offset.y - item->canvas->scroll_y1 * scale;
 		int row = pane->first.row;
 
 		if (rtl) {
@@ -541,7 +524,7 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 
 		do {
 			if (row >= gnm_sheet_get_max_rows (sheet))
-				return;
+				return TRUE;
 
 			/* DO NOT enable resizing all until we get rid of
 			 * resize_start_pos.  It will be wrong if things ahead
@@ -561,15 +544,18 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 				total += pixels;
 				rect.y = top;
 				rect.height = pixels;
-				ib_draw_cell (ib, drawable,
-					      cri->in_filter
-						      ? ib->filter_gc : ib->text_gc,
+				ib_draw_cell (ib, cr,
 					      has_object
 						      ? COL_ROW_NO_SELECTION
 						      : sv_selection_row_type (sv, row),
 					      row_name (row), &rect);
 
 				if (len > 0) {
+					cairo_save (cr);
+					cairo_set_line_width (cr, 2.0);
+					cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+					cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+					cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (color));
 					if (!draw_below) {
 						next = sheet_row_get_info (sheet, row + 1);
 						points[0].y = top;
@@ -581,14 +567,18 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 					for (level = cri->outline_level; i++ < level ; pos += inc * dir) {
 						points[0].x = points[1].x = pos;
 						points[2].x		  = pos + len * dir;
-						if (draw_below && i > prev_level)
-							gdk_draw_lines (drawable, ib->lines, points, 3);
-						else if (!draw_below && i > next->outline_level)
-							gdk_draw_lines (drawable, ib->lines, points, 3);
-						else
-							gdk_draw_line (drawable, ib->lines,
-								       pos, top - first_line_offset,
-								       pos, total);
+						if (draw_below && i > prev_level) {
+							cairo_move_to (cr, points[0].x, points[0].y);
+							cairo_line_to (cr, points[1].x, points[1].y);
+							cairo_line_to (cr, points[2].x, points[2].y);
+						} else if (!draw_below && i > next->outline_level) {
+							cairo_move_to (cr, points[0].x, points[0].y);
+							cairo_line_to (cr, points[1].x, points[1].y);
+							cairo_line_to (cr, points[2].x, points[2].y);
+						} else {
+							cairo_move_to (cr, pos, top - first_line_offset);
+							cairo_line_to (cr, pos, total);
+						}
 					}
 					first_line_offset = 0;
 
@@ -606,7 +596,7 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 							left = pos - dir * (.2 * inc - 2);
 							if (rtl)
 								left -= size;
-							gtk_paint_shadow (canvas->style, drawable,
+							gtk_paint_shadow (canvas->style, GTK_LAYOUT (canvas)->bin_window,
 								 GTK_STATE_NORMAL,
 								 prev_visible ? GTK_SHADOW_OUT : GTK_SHADOW_IN,
 								 NULL, NULL, "GnmItemBarCell",
@@ -615,18 +605,15 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 								if (!prev_visible) {
 									left += dir;
 									top++;
-									gdk_draw_line (drawable, ib->lines,
-										       left+size/2, top+3,
-										       left+size/2, top+size-4);
+									cairo_move_to (cr, left+size/2, top+3);
+									cairo_line_to (cr, left+size/2, top+size-4);
 								}
-								gdk_draw_line (drawable, ib->lines,
-									       left+3,	    top+size/2,
-									       left+size-4, top+size/2);
+								cairo_move_to (cr, left+3,	    top+size/2);
+								cairo_line_to (cr, left+size-4, top+size/2);
 							}
 						} else if (level > 0)
-							gdk_draw_line (drawable, ib->lines,
-								       pos,      top+pixels/2,
-								       pos+len,  top+pixels/2);
+							cairo_move_to (cr, pos,      top+pixels/2);
+							cairo_line_to (cr, pos+len,  top+pixels/2);
 					} else {
 						if (next->outline_level > level) {
 							int left, safety = 0;
@@ -643,7 +630,7 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 							if (rtl)
 								left -= size;
 							bottom = total - size;
-							gtk_paint_shadow (canvas->style, drawable,
+							gtk_paint_shadow (canvas->style, GTK_LAYOUT (canvas)->bin_window,
 								 GTK_STATE_NORMAL,
 								 next->visible ? GTK_SHADOW_OUT : GTK_SHADOW_IN,
 								 NULL, NULL, "GnmItemBarCell",
@@ -652,19 +639,18 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 								if (!next->visible) {
 									left += dir;
 									top++;
-									gdk_draw_line (drawable, ib->lines,
-										       left+size/2, bottom+3,
-										       left+size/2, bottom+size-4);
+									cairo_move_to (cr, left+size/2, bottom+3);
+									cairo_line_to (cr, left+size/2, bottom+size-4);
 								}
-								gdk_draw_line (drawable, ib->lines,
-									       left+3,	    bottom+size/2,
-									       left+size-4, bottom+size/2);
+								cairo_move_to (cr, left+3,	    bottom+size/2);
+								cairo_line_to (cr, left+size-4, bottom+size/2);
 							}
 						} else if (level > 0)
-							gdk_draw_line (drawable, ib->lines,
-								       pos,      top+pixels/2,
-								       pos+len,  top+pixels/2);
+							cairo_move_to (cr, pos,      top+pixels/2);
+							cairo_line_to (cr, pos+len,  top+pixels/2);
 					}
+					cairo_stroke (cr);
+					cairo_restore (cr);
 				}
 			}
 			prev_visible = cri->visible;
@@ -672,11 +658,12 @@ item_bar_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expos
 			++row;
 		} while (total <= end);
 	}
+	return TRUE;
 }
 
 static double
-item_bar_point (FooCanvasItem *item, double x, double y, int cx, int cy,
-		FooCanvasItem **actual_item)
+item_bar_distance (GocItem *item, double x, double y,
+		GocItem **actual_item)
 {
 	*actual_item = item;
 	return 0.0;
@@ -697,30 +684,30 @@ item_bar_point (FooCanvasItem *item, double x, double y, int cx, int cy,
  * Returns non-NULL if point (@x,@y) is on a division
  **/
 static ColRowInfo const *
-is_pointer_on_division (ItemBar const *ib, double x, double y,
-			int *the_total, int *the_element, int *minor_pos)
+is_pointer_on_division (ItemBar const *ib, gint64 x, gint64 y,
+			gint64 *the_total, int *the_element, gint64 *minor_pos)
 {
 	Sheet *sheet = scg_sheet (ib->pane->simple.scg);
 	ColRowInfo const *cri;
-	double const scale = ib->base.canvas->pixels_per_unit;
-	int major, minor, i, total = 0;
+	gint64 major, minor, total = 0;
+	int i;
 
-	x *= scale;
-	y *= scale;
 	if (ib->is_col_header) {
 		major = x;
 		minor = y;
+		i = ib->pane->first.col;
+		total = ib->pane->first_offset.x;
 	} else {
 		major = y;
-		minor = sheet->text_is_rtl ? (ib->cell_width + ib->indent - x) : x;
+		minor = x;
+		i = ib->pane->first.row;
+		total = ib->pane->first_offset.y;
 	}
 	if (NULL != minor_pos)
 		*minor_pos = minor;
-	if (ib->is_col_header && sheet->text_is_rtl)
-		major = -major;
 	if (NULL != the_element)
 		*the_element = -1;
-	for (i = 0; total < major; i++) {
+	for (; total < major; i++) {
 		if (ib->is_col_header) {
 			if (i >= gnm_sheet_get_max_cols (sheet))
 				return NULL;
@@ -757,7 +744,7 @@ is_pointer_on_division (ItemBar const *ib, double x, double y,
 
 /* x & y in world coords */
 static void
-ib_set_cursor (ItemBar *ib, double x, double y)
+ib_set_cursor (ItemBar *ib, gint64 x, gint64 y)
 {
 	GdkWindow *window = GTK_WIDGET (ib->base.canvas)->window;
 	GdkCursor *cursor = ib->normal_cursor;
@@ -838,11 +825,11 @@ outline_button_press (ItemBar const *ib, int element, int pixel)
 	return TRUE;
 }
 
-static gint
-item_bar_event (FooCanvasItem *item, GdkEvent *e)
+static gboolean
+item_bar_button_pressed (GocItem *item, int button, double x_, double y_)
 {
 	ColRowInfo const *cri;
-	FooCanvas	* const canvas = item->canvas;
+	GocCanvas	* const canvas = item->canvas;
 	ItemBar		* const ib = ITEM_BAR (item);
 	GnmPane		* const pane = ib->pane;
 	SheetControlGUI	* const scg = pane->simple.scg;
@@ -850,106 +837,35 @@ item_bar_event (FooCanvasItem *item, GdkEvent *e)
 	Sheet		* const sheet = sc_sheet (sc);
 	WBCGtk * const wbcg = scg_wbcg (scg);
 	gboolean const is_cols = ib->is_col_header;
-	int pos, minor_pos, start, element, x, y;
-
-	/* NOTE :
-	 * No need to map coordinates since we do the zooming of the item bars manually
-	 * there is no transform needed.
-	 */
-	switch (e->type){
-	case GDK_ENTER_NOTIFY:
-		ib_set_cursor (ib, e->crossing.x, e->crossing.y);
-		break;
+	gint64 minor_pos, start;
+	int element;
+	GdkEventButton *event = (GdkEventButton *) goc_canvas_get_cur_event (item->canvas);
+	gint64 x = x_ * item->canvas->pixels_per_unit, y = y_ * item->canvas->pixels_per_unit;
 
-	case GDK_MOTION_NOTIFY:
-		foo_canvas_w2c (canvas, e->motion.x, e->motion.y, &x, &y);
-
-		/* Do col/row resizing or incremental marking */
-		if (ib->colrow_being_resized != -1) {
-			int new_size;
-			if (!ib->has_resize_guides) {
-				ib->has_resize_guides = TRUE;
-				scg_size_guide_start (ib->pane->simple.scg,
-					ib->is_col_header, ib->colrow_being_resized, 1);
-
-				gnm_simple_canvas_grab (item,
-					GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
-					ib->change_cursor, e->motion.time);
-			}
-
-			cri = sheet_colrow_get_info (sheet,
-				ib->colrow_being_resized, is_cols);
-			pos = is_cols ? (sheet->text_is_rtl ? -e->motion.x : e->motion.x) : e->motion.y;
-			pos *= ib->base.canvas->pixels_per_unit;
-			new_size = pos - ib->resize_start_pos;
-			if (is_cols && sheet->text_is_rtl)
-				new_size += cri->size_pixels;
-
-			/* Ensure we always have enough room for the margins */
-			if (is_cols) {
-				if (new_size <= (GNM_COL_MARGIN + GNM_COL_MARGIN)) {
-					new_size = GNM_COL_MARGIN + GNM_COL_MARGIN + 1;
-					pos = pane->first_offset.col +
-						scg_colrow_distance_get (scg, TRUE,
-							pane->first.col,
-							ib->colrow_being_resized);
-					pos += new_size;
-				}
-			} else {
-				if (new_size <= (GNM_ROW_MARGIN + GNM_ROW_MARGIN)) {
-					new_size = GNM_ROW_MARGIN + GNM_ROW_MARGIN + 1;
-					pos = pane->first_offset.row +
-						scg_colrow_distance_get (scg, FALSE,
-							pane->first.row,
-							ib->colrow_being_resized);
-					pos += new_size;
-				}
-			}
-
-			ib->colrow_resize_size = new_size;
-			colrow_tip_setlabel (ib, is_cols, new_size);
-			scg_size_guide_motion (scg, is_cols, pos);
-
-			/* Redraw the ItemBar to show nice incremental progress */
-			foo_canvas_request_redraw (canvas, 0, 0, G_MAXINT/2,  G_MAXINT/2);
-
-		} else if (ib->start_selection != -1) {
-
-			gnm_pane_handle_motion (ib->pane,
-				canvas, &e->motion,
-				GNM_PANE_SLIDE_AT_COLROW_BOUND |
-					(is_cols ? GNM_PANE_SLIDE_X : GNM_PANE_SLIDE_Y),
-				cb_extend_selection, ib);
-		} else
-			ib_set_cursor (ib, e->motion.x, e->motion.y);
-		break;
-
-	case GDK_BUTTON_PRESS:
-		/* Ignore scroll wheel events */
-		if (e->button.button > 3)
-			return FALSE;
+	if (button > 3)
+		return FALSE;
 
-		if (wbc_gtk_get_guru (wbcg) == NULL)
-			scg_mode_edit (scg);
+	if (wbc_gtk_get_guru (wbcg) == NULL)
+		scg_mode_edit (scg);
 
-		cri = is_pointer_on_division (ib, e->button.x, e->button.y,
-			&start, &element, &minor_pos);
-		if (element < 0)
-			return FALSE;
-		if (minor_pos < ib->indent)
-			return outline_button_press (ib, element, minor_pos);
+	cri = is_pointer_on_division (ib, x, y,
+		&start, &element, &minor_pos);
+	if (element < 0)
+		return FALSE;
+	if (minor_pos < ib->indent)
+		return outline_button_press (ib, element, minor_pos);
 
-		if (e->button.button == 3) {
-			if (wbc_gtk_get_guru (wbcg) != NULL)
-				return TRUE;
+	if (button == 3) {
+		if (wbc_gtk_get_guru (wbcg) != NULL)
+			return TRUE;
 			/* If the selection does not contain the current row/col
 			 * then clear the selection and add it.
 			 */
 			if (!sv_is_colrow_selected (sc_view (sc), element, is_cols))
 				scg_colrow_select (scg, is_cols,
-						   element, e->button.state);
+						   element, event->state);
 
-			scg_context_menu (scg, &e->button, is_cols, !is_cols);
+			scg_context_menu (scg, event, is_cols, !is_cols);
 		} else if (cri != NULL) {
 			/*
 			 * Record the important bits.
@@ -966,10 +882,6 @@ item_bar_event (FooCanvasItem *item, GdkEvent *e)
 			if (ib->tip == NULL) {
 				GtkWidget *cw = GTK_WIDGET (canvas);
 				int wx, wy;
-
-				gnm_canvas_get_position (canvas, &wx, &wy,
-							 e->button.x,
-							 e->button.y);
 				ib->tip = gnumeric_create_tooltip (cw);
 				colrow_tip_setlabel (ib, is_cols, ib->colrow_resize_size);
 				/* Position above the current point for both
@@ -978,73 +890,140 @@ item_bar_event (FooCanvasItem *item, GdkEvent *e)
 				 * the tip under the cursor which can have odd
 				 * effects on the event stream.  win32 was
 				 * different from X. */
-				gnumeric_position_tooltip (ib->tip, wx, wy,
-							   TRUE);
+
+				gnm_canvas_get_position (canvas, &wx, &wy,x, y);
+				gnumeric_position_tooltip (ib->tip,
+							   wx, wy, TRUE);
 				gtk_widget_show_all (gtk_widget_get_toplevel (ib->tip));
 			}
 		} else {
 			if (wbc_gtk_get_guru (wbcg) != NULL &&
 			    !wbcg_entry_has_logical (wbcg))
-				break;
+				return TRUE;
 
 			/* If we're editing it is possible for this to fail */
-			if (!scg_colrow_select (scg, is_cols, element, e->button.state))
-				break;
+			if (!scg_colrow_select (scg, is_cols, element, event->state))
+				return TRUE;
 
 			ib->start_selection = element;
 			gnm_pane_slide_init (pane);
-			gnm_simple_canvas_grab (item,
-				GDK_POINTER_MOTION_MASK |
-				GDK_BUTTON_RELEASE_MASK,
-				ib->normal_cursor,
-				e->button.time);
-
-		}
-		break;
+	}
+	gnm_simple_canvas_grab (item,
+		GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
+		ib->change_cursor, event->time);
+	return TRUE;
+}
 
-	case GDK_2BUTTON_PRESS:
-		/* Ignore scroll wheel events */
-		if (e->button.button > 3)
-			return FALSE;
+static gboolean
+item_bar_2button_pressed (GocItem *item, int button, double x, double y)
+{
+	ItemBar		* const ib = ITEM_BAR (item);
+	if (button > 3)
+		return FALSE;
 
-		if (e->button.button != 3)
-			item_bar_resize_stop (ib, -1);
-		break;
+	if (button != 3)
+		item_bar_resize_stop (ib, -1);
+	return TRUE;
+}
 
-	case GDK_BUTTON_RELEASE: {
-		gboolean needs_ungrab = FALSE;
+static gboolean
+item_bar_enter_notify (GocItem *item, double x_, double y_)
+{
+	ItemBar		* const ib = ITEM_BAR (item);
+	gint64 x = x_ * item->canvas->pixels_per_unit, y = y_ * item->canvas->pixels_per_unit;
+	ib_set_cursor (ib, x, y);
+	return TRUE;
+}
 
-		/* Ignore scroll wheel events */
-		if (e->button.button > 3)
-			return FALSE;
+static gboolean
+item_bar_motion (GocItem *item, double x_, double y_)
+{
+	ColRowInfo const *cri;
+	GocCanvas	* const canvas = item->canvas;
+	ItemBar		* const ib = ITEM_BAR (item);
+	GnmPane		* const pane = ib->pane;
+	SheetControlGUI	* const scg = pane->simple.scg;
+	SheetControl	* const sc = (SheetControl *) pane->simple.scg;
+	Sheet		* const sheet = sc_sheet (sc);
+	gboolean const is_cols = ib->is_col_header;
+	gint64 pos;
+	gint64 x = x_ * item->canvas->pixels_per_unit, y = y_ * item->canvas->pixels_per_unit;
 
-		gnm_pane_slide_stop (ib->pane);
+	if (ib->colrow_being_resized != -1) {
+		int new_size;
+		if (!ib->has_resize_guides) {
+			ib->has_resize_guides = TRUE;
+			scg_size_guide_start (ib->pane->simple.scg,
+				ib->is_col_header, ib->colrow_being_resized, 1);
 
-		if (ib->start_selection >= 0) {
-			needs_ungrab = TRUE;
-			ib->start_selection = -1;
-			gnm_expr_entry_signal_update (
-				wbcg_get_entry_logical (wbcg), TRUE);
+			gnm_simple_canvas_grab (item,
+				GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
+				ib->change_cursor,
+			    ((GdkEventMotion *) goc_canvas_get_cur_event (canvas))->time);
 		}
-		if (ib->colrow_being_resized >= 0) {
-			if (ib->has_resize_guides) {
-				needs_ungrab = TRUE;
-				item_bar_resize_stop (ib, ib->colrow_resize_size);
-			} else
-				/*
-				 * No need to resize, nothing changed.
-				 * This will handle the case of a double click.
-				 */
-				item_bar_resize_stop (ib, 0);
+
+		cri = sheet_colrow_get_info (sheet,
+			ib->colrow_being_resized, is_cols);
+		pos = is_cols ? x: y;
+		new_size = pos - ib->resize_start_pos;
+		if (is_cols && sheet->text_is_rtl)
+			new_size += cri->size_pixels;
+
+		/* Ensure we always have enough room for the margins */
+		if (is_cols) {
+			if (new_size <= (GNM_COL_MARGIN + GNM_COL_MARGIN)) {
+				new_size = GNM_COL_MARGIN + GNM_COL_MARGIN + 1;
+				pos = pane->first_offset.x +
+					scg_colrow_distance_get (scg, TRUE,
+						pane->first.col,
+						ib->colrow_being_resized);
+				pos += new_size;
+			}
+		} else {
+			if (new_size <= (GNM_ROW_MARGIN + GNM_ROW_MARGIN)) {
+				new_size = GNM_ROW_MARGIN + GNM_ROW_MARGIN + 1;
+				pos = pane->first_offset.y +
+					scg_colrow_distance_get (scg, FALSE,
+						pane->first.row,
+						ib->colrow_being_resized);
+				pos += new_size;
+			}
 		}
-		if (needs_ungrab)
-			gnm_simple_canvas_ungrab (item, e->button.time);
-		break;
-	}
 
-	default:
-		return FALSE;
+		ib->colrow_resize_size = new_size;
+		colrow_tip_setlabel (ib, is_cols, new_size);
+		scg_size_guide_motion (scg, is_cols, pos);
+
+		/* Redraw the ItemBar to show nice incremental progress */
+		goc_canvas_invalidate (canvas, 0, 0, G_MAXINT/2,  G_MAXINT/2);
+
+	} else if (ib->start_selection != -1) {
+		gnm_pane_handle_motion (ib->pane,
+			canvas, x, y,
+			GNM_PANE_SLIDE_AT_COLROW_BOUND |
+				(is_cols ? GNM_PANE_SLIDE_X : GNM_PANE_SLIDE_Y),
+			cb_extend_selection, ib);
+	} else
+		ib_set_cursor (ib, x, y);
+	return TRUE;
+}
+
+static gboolean
+item_bar_button_released (GocItem *item, int button, double x, double y)
+{
+	ItemBar	*ib = ITEM_BAR (item);
+	gnm_simple_canvas_ungrab (item, 0);
+	if (ib->colrow_being_resized >= 0) {
+		if (ib->has_resize_guides)
+			item_bar_resize_stop (ib, ib->colrow_resize_size);
+		else
+			/*
+			 * No need to resize, nothing changed.
+			 * This will handle the case of a double click.
+			 */
+			item_bar_resize_stop (ib, 0);
 	}
+	ib->start_selection = -1;
 	return TRUE;
 }
 
@@ -1060,9 +1039,9 @@ item_bar_set_property (GObject *obj, guint param_id,
 		break;
 	case ITEM_BAR_PROP_IS_COL_HEADER:
 		ib->is_col_header = g_value_get_boolean (value);
+		goc_item_bounds_changed (GOC_ITEM (obj));
 		break;
 	}
-	foo_canvas_item_request_update (&ib->base);
 }
 
 static void
@@ -1092,10 +1071,10 @@ item_bar_dispose (GObject *obj)
 static void
 item_bar_init (ItemBar *ib)
 {
+	ib->base.x0 = 0;
+	ib->base.y0 = 0;
 	ib->base.x1 = 0;
 	ib->base.y1 = 0;
-	ib->base.x2 = 0;
-	ib->base.y2 = 0;
 
 	ib->dragging = FALSE;
 	ib->is_col_header = FALSE;
@@ -1116,7 +1095,7 @@ item_bar_init (ItemBar *ib)
 static void
 item_bar_class_init (GObjectClass  *gobject_klass)
 {
-	FooCanvasItemClass *item_klass = (FooCanvasItemClass *) gobject_klass;
+	GocItemClass *item_klass = (GocItemClass *) gobject_klass;
 
 	parent_class = g_type_class_peek_parent (gobject_klass);
 
@@ -1133,14 +1112,18 @@ item_bar_class_init (GObjectClass  *gobject_klass)
 			FALSE,
 			GSF_PARAM_STATIC | G_PARAM_WRITABLE));
 
-	item_klass->update      = item_bar_update;
 	item_klass->realize     = item_bar_realize;
 	item_klass->unrealize   = item_bar_unrealize;
-	item_klass->draw        = item_bar_draw;
-	item_klass->point       = item_bar_point;
-	item_klass->event       = item_bar_event;
+	item_klass->draw_region = item_bar_draw_region;
+	item_klass->update_bounds  = item_bar_update_bounds;
+	item_klass->distance	= item_bar_distance;
+	item_klass->button_pressed = item_bar_button_pressed;
+	item_klass->button_released = item_bar_button_released;
+	item_klass->button2_pressed = item_bar_2button_pressed;
+	item_klass->enter_notify = item_bar_enter_notify;
+	item_klass->motion = item_bar_motion;
 }
 
 GSF_CLASS (ItemBar, item_bar,
 	   item_bar_class_init, item_bar_init,
-	   FOO_TYPE_CANVAS_ITEM)
+	   GOC_TYPE_ITEM)
diff --git a/src/item-bar.h b/src/item-bar.h
index e3f9d72..0c5d9a7 100644
--- a/src/item-bar.h
+++ b/src/item-bar.h
@@ -5,6 +5,7 @@
 #include "gui-gnumeric.h"
 #include <glib-object.h>
 #include <pango/pango-font.h>
+#include <goffice/canvas/goffice-canvas.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/item-cursor.c b/src/item-cursor.c
index 4e6a7db..63c3e93 100644
--- a/src/item-cursor.c
+++ b/src/item-cursor.c
@@ -45,7 +45,7 @@
 #define CLIP_SAFETY_MARGIN      (AUTO_HANDLE_SPACE + 5)
 
 struct _ItemCursor {
-	FooCanvasItem canvas_item;
+	GocItem canvas_item;
 
 	SheetControlGUI *scg;
 	gboolean	 pos_initialized;
@@ -72,12 +72,12 @@ struct _ItemCursor {
 	int   base_x, base_y;
 	GnmRange autofill_src;
 	int   autofill_hsize, autofill_vsize;
-	gint last_x, last_y;
+	gint64 last_x, last_y;
 
 	/* cursor outline in canvas coords, the bounding box (Item::[xy][01])
 	 * is slightly larger ) */
 	struct {
-		int x1, x2, y1, y2;
+		gint64 x1, x2, y1, y2;
 	} outline;
 	int drag_button;
 	guint drag_button_state;
@@ -87,12 +87,12 @@ struct _ItemCursor {
 	gboolean auto_fill_handle_at_top;
 	gboolean auto_fill_handle_at_left;
 
-	GdkPixmap *stipple;
-	GdkColor  color;
+	cairo_pattern_t *stipple;
+	GOColor  color;
 };
-typedef FooCanvasItemClass ItemCursorClass;
+typedef GocItemClass ItemCursorClass;
 
-static FooCanvasItemClass *parent_class;
+static GocItemClass *parent_class;
 
 enum {
 	ITEM_CURSOR_PROP_0,
@@ -105,10 +105,10 @@ enum {
 static int
 cb_item_cursor_animation (ItemCursor *ic)
 {
-	FooCanvasItem *item = FOO_CANVAS_ITEM (ic);
+	GocItem *item = GOC_ITEM (ic);
 
 	ic->state = !ic->state;
-	foo_canvas_item_request_update (item);
+	goc_item_invalidate (item);
 	return TRUE;
 }
 
@@ -126,42 +126,38 @@ item_cursor_dispose (GObject *obj)
 }
 
 static void
-item_cursor_realize (FooCanvasItem *item)
+item_cursor_realize (GocItem *item)
 {
-	ItemCursor *ic;
-	GdkWindow  *window;
+	ItemCursor *ic = ITEM_CURSOR (item);
 
 	if (parent_class->realize)
 		(*parent_class->realize) (item);
 
-	ic = ITEM_CURSOR (item);
-	window = GTK_WIDGET (item->canvas)->window;
-
-	ic->gc = gdk_gc_new (window);
-
 	if (ic->style == ITEM_CURSOR_ANTED) {
 		g_return_if_fail (ic->animation_timer == -1);
 		ic->animation_timer = g_timeout_add (
-			150, (GSourceFunc)cb_item_cursor_animation,
+			150, (GSourceFunc) cb_item_cursor_animation,
 			ic);
 	}
 
 	if (ic->style == ITEM_CURSOR_DRAG || ic->style == ITEM_CURSOR_AUTOFILL) {
-		static unsigned char const stipple_data [] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
-		ic->stipple = gdk_bitmap_create_from_data (window, (const gchar *)stipple_data, 8, 8);
+		GOPattern pat;
+		cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (GTK_WIDGET (item->canvas)));
+		pat.fore = RGBA_BLACK;
+		pat.back = RGBA_WHITE;
+		pat.pattern = GO_PATTERN_GREY50;
+		ic->stipple = go_pattern_create_cairo_pattern (&pat, cr);
+		cairo_destroy (cr);
 	}
 }
 
 static void
-item_cursor_unrealize (FooCanvasItem *item)
+item_cursor_unrealize (GocItem *item)
 {
 	ItemCursor *ic = ITEM_CURSOR (item);
 
-	g_object_unref (G_OBJECT (ic->gc));
-	ic->gc = NULL;
-
 	if (ic->stipple) {
-		g_object_unref (ic->stipple);
+		cairo_pattern_destroy (ic->stipple);
 		ic->stipple = NULL;
 	}
 
@@ -175,63 +171,50 @@ item_cursor_unrealize (FooCanvasItem *item)
 }
 
 static void
-item_cursor_update (FooCanvasItem *item, double i2w_dx, double i2w_dy, int flags)
+item_cursor_update_bounds (GocItem *item)
 {
 	ItemCursor	*ic = ITEM_CURSOR (item);
 	GnmPane		*pane = GNM_PANE (item->canvas);
 	SheetControlGUI const * const scg = ic->scg;
 	int tmp;
+	double scale = item->canvas->pixels_per_unit;
 
 	int const left	 = ic->pos.start.col;
 	int const right	 = ic->pos.end.col;
 	int const top	 = ic->pos.start.row;
 	int const bottom = ic->pos.end.row;
-
-	foo_canvas_item_request_redraw (item); /* Erase the old cursor */
-
-	ic->outline.x1 = pane->first_offset.col +
+	ic->outline.x1 = pane->first_offset.x +
 		scg_colrow_distance_get (scg, TRUE, pane->first.col, left);
 	ic->outline.x2 = ic->outline.x1 +
 		scg_colrow_distance_get (scg, TRUE, left, right+1);
-	ic->outline.y1 = pane->first_offset.row +
+	ic->outline.y1 = pane->first_offset.y +
 		scg_colrow_distance_get (scg, FALSE, pane->first.row, top);
 	ic->outline.y2 = ic->outline.y1 +
 		scg_colrow_distance_get (scg, FALSE,top, bottom+1);
 
-	if (scg_sheet (scg)->text_is_rtl) {
-		tmp = ic->outline.x1;
-		ic->outline.x1 = gnm_foo_canvas_x_w2c (item->canvas, ic->outline.x2);
-		ic->outline.x2 = gnm_foo_canvas_x_w2c (item->canvas, tmp);
-	}
 	/* NOTE : sometimes y1 > y2 || x1 > x2 when we create a cursor in an
 	 * invisible region such as above a frozen pane */
 
-	item->x1 = ic->outline.x1 - 1;
-	item->y1 = ic->outline.y1 - 1;
+	/* jean: I don't know why we now need 2 instead of one in the next two lines */
+	item->x0 = (ic->outline.x1 - 2) / scale;
+	item->y0 = (ic->outline.y1 - 2) / scale;
 
 	/* for the autohandle */
 	tmp = (ic->style == ITEM_CURSOR_SELECTION) ? AUTO_HANDLE_WIDTH : 0;
-	item->x2 = ic->outline.x2 + 3 + tmp;
-	item->y2 = ic->outline.y2 + 3 + tmp;
-
-	foo_canvas_item_request_redraw (item); /* draw the new cursor */
-
-	if (parent_class->update)
-		(*parent_class->update) (item, i2w_dx, i2w_dy, flags);
+	item->x1 = (ic->outline.x2 + 3 + tmp) / scale;
+	item->y1 = (ic->outline.y2 + 3 + tmp) / scale;
 }
 
 static void
-item_cursor_draw (FooCanvasItem *item, GdkDrawable *drawable,
-		  GdkEventExpose *expose)
+item_cursor_draw (GocItem const *item, cairo_t *cr)
 {
-	GdkGCValues values;
 	ItemCursor *ic = ITEM_CURSOR (item);
-	int x0, y0, x1, y1; /* in canvas coordinates */
-	GdkPoint points [5];
-	int draw_thick, draw_handle;
+	int x0, y0, x1, y1; /* in widget coordinates */
+	GocPoint points [5];
+	int draw_thick, draw_handle, i;
 	int premove = 0;
-	GdkColor *fore = NULL, *back = NULL;
-	gboolean draw_stippled, draw_center, draw_external, draw_internal, draw_xor;
+	gboolean draw_stippled, draw_center, draw_external, draw_internal;
+	double scale = item->canvas->pixels_per_unit;
 
 #if 0
 	g_print ("draw[%d] %d,%d %d,%d\n",
@@ -244,10 +227,16 @@ item_cursor_draw (FooCanvasItem *item, GdkDrawable *drawable,
 	if (!ic->visible || !ic->pos_initialized)
 		return;
 
-	x0 = ic->outline.x1;
-	y0 = ic->outline.y1;
-	x1 = ic->outline.x2;
-	y1 = ic->outline.y2;
+	/* we need to use canvas coordinates in goc_canvas_c2w, hence the divisions by scale. */
+	if (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL) {
+		goc_canvas_c2w (item->canvas, ic->outline.x2 / scale, ic->outline.y2 / scale, &x0, &y1);
+		goc_canvas_c2w (item->canvas, ic->outline.x1 / scale, ic->outline.y1 / scale, &x1, &y0);
+		x0--; /* because of the +.5, things are not symetric */
+		x1--;
+	} else {
+		goc_canvas_c2w (item->canvas, ic->outline.x1 / scale, ic->outline.y1 / scale, &x0, &y0);
+		goc_canvas_c2w (item->canvas, ic->outline.x2 / scale, ic->outline.y2 / scale, &x1, &y1);
+	}
 
 	/* only mostly in invisible areas (eg on creation of frozen panes) */
 	if (x0 > x1 || y0 > y1)
@@ -259,7 +248,6 @@ item_cursor_draw (FooCanvasItem *item, GdkDrawable *drawable,
 	draw_thick    = 1;
 	draw_center   = FALSE;
 	draw_stippled = FALSE;
-	draw_xor      = TRUE;
 
 	switch (ic->style) {
 	case ITEM_CURSOR_AUTOFILL:
@@ -267,14 +255,11 @@ item_cursor_draw (FooCanvasItem *item, GdkDrawable *drawable,
 		draw_center   = TRUE;
 		draw_thick    = 3;
 		draw_stippled = TRUE;
-		fore          = &gs_white;
-		back          = &gs_white;
 		break;
 
 	case ITEM_CURSOR_EXPR_RANGE:
 		draw_center   = TRUE;
-		draw_thick    = (item->canvas->current_item == item) ? 3 : 2;
-		draw_xor      = FALSE;
+		draw_thick    = (item->canvas->last_item == item) ? 3 : 2;
 		break;
 
 	case ITEM_CURSOR_SELECTION:
@@ -305,44 +290,23 @@ item_cursor_draw (FooCanvasItem *item, GdkDrawable *drawable,
 	case ITEM_CURSOR_ANTED:
 		draw_center   = TRUE;
 		draw_thick    = 2;
-		if (ic->state) {
-			fore = &gs_light_gray;
-			back = &gs_dark_gray;
-		} else {
-			fore = &gs_dark_gray;
-			back = &gs_light_gray;
-		}
-	}
-
-	if (ic->use_color) {
-		fore = &ic->color;
-		back = &ic->color;
+		break;
+	default:
+		break;
 	}
 
 	ic->auto_fill_handle_at_top = (draw_handle >= 2);
 
-	gdk_gc_set_clip_rectangle (ic->gc, &expose->area);
-
-	/* Avoid guint16 overflow during line drawing.  We can change
-	 * the shape we draw, so long as no lines or parts of
-	 * rectangles are moved from outside to inside the clipping
-	 * region */
-	x0 = MAX (x0, expose->area.x - CLIP_SAFETY_MARGIN);
-	y0 = MAX (y0, expose->area.y - CLIP_SAFETY_MARGIN);
-	x1 = MIN (x1, expose->area.x + expose->area.width + CLIP_SAFETY_MARGIN);
-	y1 = MIN (y1, expose->area.y + expose->area.height + CLIP_SAFETY_MARGIN);
+	/* Do we need to clip? */
 
 	if (x0 >= x1 || y0 >= y1)
 		draw_handle = 0;
-
-	gdk_gc_set_line_attributes (ic->gc, 1,
-		GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
-	gdk_gc_set_rgb_fg_color (ic->gc, &gs_white);
-	gdk_gc_set_rgb_bg_color (ic->gc, &gs_white);
-	if (draw_xor) {
-		values.function = GDK_XOR;
-		gdk_gc_set_values (ic->gc, &values, GDK_GC_FUNCTION);
-	}
+	cairo_save (cr);
+	cairo_set_dash (cr, NULL, 0, 0.);
+	cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+	cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+	cairo_set_source_rgba (cr, 0., 0., 0., 1.);
+	cairo_set_line_width (cr, draw_thick);
 
 	if (draw_external) {
 		switch (draw_handle) {
@@ -353,15 +317,15 @@ item_cursor_draw (FooCanvasItem *item, GdkDrawable *drawable,
 
 		/* No auto handle */
 		case 0 :
-			points [0].x = x1 + 1;
-			points [0].y = y1 + 1 - premove;
+			points [0].x = x1 + 1.5;
+			points [0].y = y1 + 1.5 - premove;
 			points [1].x = points [0].x;
-			points [1].y = y0 - 1;
-			points [2].x = x0 - 1;
-			points [2].y = y0 - 1;
-			points [3].x = x0 - 1;
-			points [3].y = y1 + 1;
-			points [4].x = x1 + 1 - premove;
+			points [1].y = y0 - .5;
+			points [2].x = x0 - .5;
+			points [2].y = y0 - .5;
+			points [3].x = x0 - .5;
+			points [3].y = y1 + 1.5;
+			points [4].x = x1 + 1.5 - premove;
 			points [4].y = points [3].y;
 			break;
 
@@ -371,22 +335,25 @@ item_cursor_draw (FooCanvasItem *item, GdkDrawable *drawable,
 
 		/* Auto handle at top of sheet */
 		case 3 :
-			points [0].x = x1 + 1;
-			points [0].y = y0 - 1 + AUTO_HANDLE_SPACE;
+			points [0].x = x1 + 1.5;
+			points [0].y = y0 - .5 + AUTO_HANDLE_SPACE;
 			points [1].x = points [0].x;
-			points [1].y = y1 + 1;
-			points [2].x = x0 - 1;
+			points [1].y = y1 + 1.5;
+			points [2].x = x0 - .5;
 			points [2].y = points [1].y;
 			points [3].x = points [2].x;
-			points [3].y = y0 - 1;
-			points [4].x = x1 + 1 - premove;
+			points [3].y = y0 - .5;
+			points [4].x = x1 + 1.5 - premove;
 			points [4].y = points [3].y;
 			break;
 
 		default :
 			g_assert_not_reached ();
 		}
-		gdk_draw_lines (drawable, ic->gc, points, 5);
+		cairo_move_to (cr, points[0].x, points[0].y);
+		for (i = 1; i < 5; i++)
+			cairo_line_to (cr, points[i].x, points[i].y);
+		cairo_stroke (cr);
 	}
 
 	if (draw_external && draw_internal) {
@@ -409,75 +376,84 @@ item_cursor_draw (FooCanvasItem *item, GdkDrawable *drawable,
 			points [3].y += 2;
 			points [4].y += 2;
 		}
-		gdk_draw_lines (drawable, ic->gc, points, 5);
+		cairo_move_to (cr, points[0].x, points[0].y);
+		for (i = 1; i < 5; i++)
+			cairo_line_to (cr, points[i].x, points[i].y);
+		cairo_stroke (cr);
 	}
 
 	if (draw_handle == 1 || draw_handle == 2) {
 		int const y_off = (draw_handle == 1) ? y1 - y0 : 0;
-		gdk_draw_rectangle (drawable, ic->gc, TRUE,
+		cairo_rectangle (cr,
 				    x1 - 2,
 				    y0 + y_off - 2,
 				    2, 2);
-		gdk_draw_rectangle (drawable, ic->gc, TRUE,
+		cairo_rectangle (cr,
 				    x1 + 1,
 				    y0 + y_off - 2,
 				    2, 2);
-		gdk_draw_rectangle (drawable, ic->gc, TRUE,
+		cairo_rectangle (cr,
 				    x1 - 2,
 				    y0 + y_off + 1,
 				    2, 2);
-		gdk_draw_rectangle (drawable, ic->gc, TRUE,
+		cairo_rectangle (cr,
 				    x1 + 1,
 				    y0 + y_off + 1,
 				    2, 2);
 	} else if (draw_handle == 3) {
-		gdk_draw_rectangle (drawable, ic->gc, TRUE,
+		cairo_rectangle (cr,
 				    x1 - 2,
 				    y0 + 1,
 				    2, 4);
-		gdk_draw_rectangle (drawable, ic->gc, TRUE,
+		cairo_rectangle (cr,
 				    x1 + 1,
 				    y0 + 1,
 				    2, 4);
 	}
+	cairo_fill (cr);
 
 	if (draw_center) {
-		gdk_gc_set_rgb_fg_color (ic->gc, fore);
-		gdk_gc_set_rgb_bg_color (ic->gc, back);
-
 		if (draw_stippled) {
-			gdk_gc_set_fill (ic->gc, GDK_STIPPLED);
-			gdk_gc_set_stipple (ic->gc, ic->stipple);
-			gdk_gc_set_line_attributes (ic->gc, draw_thick,
-				GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
-		} else
-			gdk_gc_set_line_attributes (ic->gc, draw_thick,
-				GDK_LINE_DOUBLE_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER);
-
-		/* Stay in the boundary */
+			cairo_set_source (cr, ic->stipple);
+			cairo_set_line_width (cr, draw_thick);
+		} else {
+			double dash_length = 4.;
+			cairo_set_dash (cr, &dash_length, 1, (ic->state? dash_length: 0.));
+		}
 		if ((draw_thick % 2) == 0) {
+		/* Stay in the boundary */
 			x0++;
 			y0++;
+		} else {
+			x0 += 0.5;
+			x1 += 0.5;
+			y0 += 0.5;
+			y1 += 0.5;
 		}
-		gdk_draw_rectangle (drawable, ic->gc, FALSE,
-				    x0, y0,
-				    abs (x1 - x0), abs (y1 - y0));
+		cairo_rectangle (cr, x0, y0, x1 - x0, y1 - y0);
+		cairo_stroke (cr);
 	}
+	cairo_restore (cr);
+	return;
 }
 
 gboolean
 item_cursor_bound_set (ItemCursor *ic, GnmRange const *new_bound)
 {
+	GocItem *item;
 	g_return_val_if_fail (IS_ITEM_CURSOR (ic), FALSE);
 	g_return_val_if_fail (range_is_sane (new_bound), FALSE);
 
 	if (ic->pos_initialized && range_equal (&ic->pos, new_bound))
 		return FALSE;
 
+	item = GOC_ITEM (ic);
+	goc_item_invalidate (item);
 	ic->pos = *new_bound;
 	ic->pos_initialized = TRUE;
 
-	foo_canvas_item_request_update (FOO_CANVAS_ITEM (ic));
+	goc_item_bounds_changed (item);
+	goc_item_invalidate (item);
 
 	return TRUE;
 }
@@ -491,13 +467,13 @@ item_cursor_bound_set (ItemCursor *ic, GnmRange const *new_bound)
 void
 item_cursor_reposition (ItemCursor *ic)
 {
-	g_return_if_fail (ic != NULL);
-	foo_canvas_item_request_update (&ic->canvas_item);
+	g_return_if_fail (GOC_IS_ITEM (ic));
+	goc_item_bounds_changed (GOC_ITEM (ic));
 }
 
 static double
-item_cursor_point (FooCanvasItem *item, double x, double y, int cx, int cy,
-		   FooCanvasItem **actual_item)
+item_cursor_distance (GocItem *item, double x, double y,
+		   GocItem **actual_item)
 {
 	ItemCursor const *ic = ITEM_CURSOR (item);
 
@@ -512,18 +488,17 @@ item_cursor_point (FooCanvasItem *item, double x, double y, int cx, int cy,
 
 	*actual_item = NULL;
 
-	if (cx < item->x1-3)
+	if (x < item->x0-3)
 		return DBL_MAX;
-	if (cx > item->x2+3)
+	if (x > item->x1+3)
 		return DBL_MAX;
-	if (cy < item->y1-3)
+	if (y < item->y0-3)
 		return DBL_MAX;
-	if (cy > item->y2+3)
+	if (y > item->y1+3)
 		return DBL_MAX;
 
-	/* FIXME: the drag handle for ITEM_CURSOR_SELECTION needs work */
-	if ((cx < (item->x1 + 4)) || (cx > (item->x2 - 8)) ||
-	    (cy < (item->y1 + 4)) || (cy > (item->y2 - 8))) {
+	if ((x < (item->x0 + 4)) || (x > (item->x1 - 8)) ||
+	    (y < (item->y0 + 4)) || (y > (item->y1 - 8))) {
 		*actual_item = item;
 		return 0.0;
 	}
@@ -560,17 +535,18 @@ item_cursor_setup_auto_fill (ItemCursor *ic, ItemCursor const *parent, int x, in
 }
 
 static inline gboolean
-item_cursor_in_drag_handle (ItemCursor *ic, int x, int y)
+item_cursor_in_drag_handle (ItemCursor *ic, gint64 x, gint64 y)
 {
-	int const y_test = ic->auto_fill_handle_at_top
-		? ic->canvas_item.y1 + AUTO_HANDLE_WIDTH
-		: ic->canvas_item.y2 - AUTO_HANDLE_WIDTH;
+	double scale = ic->canvas_item.canvas->pixels_per_unit;
+	gint64 const y_test = ic->auto_fill_handle_at_top
+		? ic->canvas_item.y0 * scale + AUTO_HANDLE_WIDTH
+		: ic->canvas_item.y1 * scale - AUTO_HANDLE_WIDTH;
 
 	if ((y_test-AUTO_HANDLE_SPACE) <= y &&
 	    y <= (y_test+AUTO_HANDLE_SPACE)) {
-		int const x_test = ic->auto_fill_handle_at_left
-			? ic->canvas_item.x1 + AUTO_HANDLE_WIDTH
-			: ic->canvas_item.x2 - AUTO_HANDLE_WIDTH;
+		gint64 const x_test = ic->auto_fill_handle_at_left
+			? ic->canvas_item.x0 * scale + AUTO_HANDLE_WIDTH
+			: ic->canvas_item.x1 *scale - AUTO_HANDLE_WIDTH;
 		return (x_test-AUTO_HANDLE_SPACE) <= x &&
 			x <= (x_test+AUTO_HANDLE_SPACE);
 	 }
@@ -578,7 +554,7 @@ item_cursor_in_drag_handle (ItemCursor *ic, int x, int y)
 }
 
 static void
-item_cursor_set_cursor (FooCanvas *canvas, ItemCursor *ic, int x, int y)
+item_cursor_set_cursor (GocCanvas *canvas, ItemCursor *ic, gint64 x, gint64 y)
 {
 	GdkCursorType cursor;
 
@@ -590,312 +566,93 @@ item_cursor_set_cursor (FooCanvas *canvas, ItemCursor *ic, int x, int y)
 	gnm_widget_set_cursor_type (GTK_WIDGET (canvas), cursor);
 }
 
-static gint
-item_cursor_selection_event (FooCanvasItem *item, GdkEvent *event)
+static gboolean
+item_cursor_selection_motion (GocItem *item, double x_, double y_)
 {
-	FooCanvas  *canvas = item->canvas;
+	GocCanvas  *canvas = item->canvas;
 	GnmPane  *pane = GNM_PANE (canvas);
 	ItemCursor *ic = ITEM_CURSOR (item);
-	int x, y;
+	int style, button;
+	gint64 x = x_ * canvas->pixels_per_unit, y = y_ * canvas->pixels_per_unit;
+	ItemCursor *special_cursor;
+	GdkEventMotion *event = (GdkEventMotion *) goc_canvas_get_cur_event (item->canvas);
 
-	switch (event->type) {
-	case GDK_ENTER_NOTIFY:
-		foo_canvas_w2c (canvas,
-			event->crossing.x, event->crossing.y, &x, &y);
+	if (ic->drag_button < 0) {
 		item_cursor_set_cursor (canvas, ic, x, y);
 		return TRUE;
-
-	case GDK_MOTION_NOTIFY: {
-		int style, button;
-		ItemCursor *special_cursor;
-
-		foo_canvas_w2c (canvas,
-			event->motion.x, event->motion.y, &x, &y);
-
-		if (ic->drag_button < 0) {
-			item_cursor_set_cursor (canvas, ic, x, y);
-			return TRUE;
-		}
-
-		/*
-		 * determine which part of the cursor was clicked:
-		 * the border or the handlebox
-		 */
-		if (item_cursor_in_drag_handle (ic, x, y))
-			style = ITEM_CURSOR_AUTOFILL;
-		else
-			style = ITEM_CURSOR_DRAG;
-
-		button = ic->drag_button;
-		ic->drag_button = -1;
-		gnm_simple_canvas_ungrab (item, event->button.time);
-
-		scg_special_cursor_start (ic->scg, style, button);
-		special_cursor = pane->cursor.special;
-		special_cursor->drag_button_state = ic->drag_button_state;
-		if (style == ITEM_CURSOR_AUTOFILL)
-			item_cursor_setup_auto_fill (
-				special_cursor, ic, x, y);
-
-		if (x < 0)
-			x = 0;
-		if (y < 0)
-			y = 0;
-		/*
-		 * Capture the offset of the current cell relative to
-		 * the upper left corner.  Be careful handling the position
-		 * of the cursor.  it is possible to select the exterior or
-		 * interior of the cursor edge which behaves as if the cursor
-		 * selection was offset by one.
-		 */
-		{
-			int d_col = gnm_pane_find_col (pane, x, NULL) -
-				ic->pos.start.col;
-			int d_row = gnm_pane_find_row (pane, y, NULL) -
-				ic->pos.start.row;
-
-			if (d_col >= 0) {
-				int tmp = ic->pos.end.col - ic->pos.start.col;
-				if (d_col > tmp)
-					d_col = tmp;
-			} else
-				d_col = 0;
-			special_cursor->col_delta = d_col;
-
-			if (d_row >= 0) {
-				int tmp = ic->pos.end.row - ic->pos.start.row;
-				if (d_row > tmp)
-					d_row = tmp;
-			} else
-				d_row = 0;
-			special_cursor->row_delta = d_row;
-		}
-
-		if (scg_special_cursor_bound_set (ic->scg, &ic->pos))
-			foo_canvas_update_now (canvas);
-
-		gnm_simple_canvas_grab (FOO_CANVAS_ITEM (special_cursor),
-			GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK,
-			NULL, event->button.time);
-		gnm_pane_slide_init (pane);
-
-		/*
-		 * We flush after the grab to ensure that the new item-cursor
-		 * gets created.  If it is not ready in time double click
-		 * events will be disrupted and it will appear as if we are
-		 * doing an button_press with a missing release.
-		 */
-		gdk_flush ();
-		return TRUE;
 	}
 
-	case GDK_2BUTTON_PRESS: {
-		Sheet *sheet = scg_sheet (ic->scg);
-		int final_col = ic->pos.end.col;
-		int final_row = ic->pos.end.row;
-
-		if (ic->drag_button != (int)event->button.button)
-			return TRUE;
-
-		ic->drag_button = -1;
-		gnm_simple_canvas_ungrab (item, event->button.time);
-
-		if (sheet_is_region_empty (sheet, &ic->pos))
-			return TRUE;
-
-		/* If the cell(s) immediately below the ones in the
-		 * auto-fill template are not blank then over-write
-		 * them.
-		 *
-		 * Otherwise, only go as far as the next non-blank
-		 * cells.
-		 *
-		 * The code below uses find_boundary twice.  a. to
-		 * find the boundary of the column/row that acts as a
-		 * template to define the region to file and b. to
-		 * find the boundary of the region being filled.
-		 */
-
-		if (event->button.state & GDK_MOD1_MASK) {
-			int template_col = ic->pos.end.col + 1;
-			int template_row = ic->pos.start.row - 1;
-			int boundary_col_for_target;
-			int target_row;
-
-			if (template_row < 0 || template_col >= gnm_sheet_get_max_cols (sheet) ||
-			    sheet_is_cell_empty (sheet, template_col,
-						 template_row)) {
-
-				template_row = ic->pos.end.row + 1;
-				if (template_row >= gnm_sheet_get_max_rows (sheet) ||
-				    template_col >= gnm_sheet_get_max_cols (sheet) ||
-				    sheet_is_cell_empty (sheet, template_col,
-							 template_row))
-					return TRUE;
-			}
-
-			if (template_col >= gnm_sheet_get_max_cols (sheet) ||
-			    sheet_is_cell_empty (sheet, template_col,
-						 template_row))
-				return TRUE;
-			final_col = sheet_find_boundary_horizontal (sheet,
-				ic->pos.end.col, template_row,
-				template_row, 1, TRUE);
-			if (final_col <= ic->pos.end.col)
-				return TRUE;
-
-			/*
-			   Find the boundary of the target region.
-			   We don't want to go beyond this boundary.
-			*/
-			for (target_row = ic->pos.start.row; target_row <= ic->pos.end.row; target_row++) {
-				/* find_boundary is designed for Ctrl-arrow movement.  (Ab)using it for
-				 * finding autofill regions works fairly well.  One little gotcha is
-				 * that if the current col is the last row of a block of data Ctrl-arrow
-				 * will take you to then next block.  The workaround for this is to
-				 * start the search at the last col of the selection, rather than
-				 * the first col of the region being filled.
-				 */
-				boundary_col_for_target = sheet_find_boundary_horizontal
-					(sheet,
-					 ic->pos.end.col, target_row,
-					 target_row, 1, TRUE);
-
-				if (sheet_is_cell_empty (sheet, boundary_col_for_target-1, target_row) &&
-				    ! sheet_is_cell_empty (sheet, boundary_col_for_target, target_row)) {
-					/* target region was empty, we are now one col
-					   beyond where it is safe to autofill. */
-					boundary_col_for_target--;
-				}
-				if (boundary_col_for_target < final_col) {
-					final_col = boundary_col_for_target;
-				}
-			}
-		} else {
-			int template_row = ic->pos.end.row + 1;
-			int template_col = ic->pos.start.col - 1;
-			int boundary_row_for_target;
-			int target_col;
-
-			if (template_col < 0 || template_row >= gnm_sheet_get_max_rows (sheet) ||
-			    sheet_is_cell_empty (sheet, template_col,
-						 template_row)) {
-
-				template_col = ic->pos.end.col + 1;
-				if (template_col >= gnm_sheet_get_max_cols (sheet) ||
-				    template_row >= gnm_sheet_get_max_rows (sheet) ||
-				    sheet_is_cell_empty (sheet, template_col,
-							 template_row))
-					return TRUE;
-			}
-
-			if (template_row >= gnm_sheet_get_max_rows (sheet) ||
-			    sheet_is_cell_empty (sheet, template_col,
-						 template_row))
-				return TRUE;
-			final_row = sheet_find_boundary_vertical (sheet,
-				template_col, ic->pos.end.row,
-				template_col, 1, TRUE);
-			if (final_row <= ic->pos.end.row)
-				return TRUE;
-
-			/*
-			   Find the boundary of the target region.
-			   We don't want to go beyond this boundary.
-			*/
-			for (target_col = ic->pos.start.col; target_col <= ic->pos.end.col; target_col++) {
-				/* find_boundary is designed for Ctrl-arrow movement.  (Ab)using it for
-				 * finding autofill regions works fairly well.  One little gotcha is
-				 * that if the current row is the last row of a block of data Ctrl-arrow
-				 * will take you to then next block.  The workaround for this is to
-				 * start the search at the last row of the selection, rather than
-				 * the first row of the region being filled.
-				 */
-				boundary_row_for_target = sheet_find_boundary_vertical
-					(sheet,
-					 target_col, ic->pos.end.row,
-					 target_col, 1, TRUE);
-				if (sheet_is_cell_empty (sheet, target_col, boundary_row_for_target-1) &&
-				    ! sheet_is_cell_empty (sheet, target_col, boundary_row_for_target)) {
-					/* target region was empty, we are now one row
-					   beyond where it is safe to autofill. */
-					boundary_row_for_target--;
-				}
-
-				if (boundary_row_for_target < final_row) {
-					final_row = boundary_row_for_target;
-				}
-			}
-		}
+	/*
+	 * determine which part of the cursor was clicked:
+	 * the border or the handlebox
+	 */
+	if (item_cursor_in_drag_handle (ic, x, y))
+		style = ITEM_CURSOR_AUTOFILL;
+	else
+		style = ITEM_CURSOR_DRAG;
 
-		/* fill the row/column */
-		cmd_autofill (scg_wbc (ic->scg), sheet, FALSE,
-			      ic->pos.start.col, ic->pos.start.row,
-			      ic->pos.end.col - ic->pos.start.col + 1,
-			      ic->pos.end.row - ic->pos.start.row + 1,
-			      final_col, final_row,
-			      FALSE);
+	button = ic->drag_button;
+	ic->drag_button = -1;
+	gnm_simple_canvas_ungrab (item, event->time);
+
+	scg_special_cursor_start (ic->scg, style, button);
+	special_cursor = pane->cursor.special;
+	special_cursor->drag_button_state = ic->drag_button_state;
+	if (style == ITEM_CURSOR_AUTOFILL)
+		item_cursor_setup_auto_fill (
+			special_cursor, ic, x, y);
+
+	if (x < 0)
+		x = 0;
+	if (y < 0)
+		y = 0;
+	/*
+	 * Capture the offset of the current cell relative to
+	 * the upper left corner.  Be careful handling the position
+	 * of the cursor.  it is possible to select the exterior or
+	 * interior of the cursor edge which behaves as if the cursor
+	 * selection was offset by one.
+	 */
+	{
+		int d_col = gnm_pane_find_col (pane, x, NULL) -
+			ic->pos.start.col;
+		int d_row = gnm_pane_find_row (pane, y, NULL) -
+			ic->pos.start.row;
+
+		if (d_col >= 0) {
+			int tmp = ic->pos.end.col - ic->pos.start.col;
+			if (d_col > tmp)
+				d_col = tmp;
+		} else
+			d_col = 0;
+		special_cursor->col_delta = d_col;
 
-		return TRUE;
+		if (d_row >= 0) {
+			int tmp = ic->pos.end.row - ic->pos.start.row;
+			if (d_row > tmp)
+				d_row = tmp;
+		} else
+			d_row = 0;
+		special_cursor->row_delta = d_row;
 	}
 
-	case GDK_BUTTON_PRESS:
-		/* NOTE : this cannot be called while we are editing.  because
-		 * the point routine excludes events.  so we do not need to
-		 * call wbcg_edit_finish.
-		 */
-
-		/* scroll wheel events dont have corresponding release events */
-		if (event->button.button > 3)
-			return FALSE;
-
-		/* If another button is already down ignore this one */
-		if (ic->drag_button >= 0)
-			return TRUE;
-
-		if (event->button.button != 3) {
-			int x, y;
-
-			/* prepare to create fill or drag cursors, but dont until we
-			 * move.  If we did create them here there would be problems
-			 * with race conditions when the new cursors pop into existence
-			 * during a double-click
-			 */
-
-			foo_canvas_w2c (canvas,
-					event->button.x, event->button.y, &x, &y);
-			if (item_cursor_in_drag_handle (ic, x, y))
-				go_cmd_context_progress_message_set (GO_CMD_CONTEXT (scg_wbcg (ic->scg)),
-								     _("Drag to autofill"));
-			else
-				go_cmd_context_progress_message_set (GO_CMD_CONTEXT (scg_wbcg (ic->scg)),
-								     _("Drag to move"));
-
-			ic->drag_button = event->button.button;
-			ic->drag_button_state = event->button.state;
-			gnm_simple_canvas_grab (item,
-				GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK,
-				NULL, event->button.time);
-		} else
-			scg_context_menu (ic->scg, &event->button, FALSE, FALSE);
-		return TRUE;
+	scg_special_cursor_bound_set (ic->scg, &ic->pos);
 
-	case GDK_BUTTON_RELEASE:
-		if (ic->drag_button != (int)event->button.button)
-			return TRUE;
+	gnm_simple_canvas_grab (GOC_ITEM (special_cursor),
+		GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK,
+		NULL, event->time);
+	gnm_pane_slide_init (pane);
 
-		/* Double clicks may have already released the drag prep */
-		if (ic->drag_button >= 0) {
-			gnm_simple_canvas_ungrab (item, event->button.time);
-			ic->drag_button = -1;
-		}
-		go_cmd_context_progress_message_set (GO_CMD_CONTEXT (scg_wbcg (ic->scg)),
-						     " ");
-		return TRUE;
+	goc_item_bounds_changed (GOC_ITEM (ic));
 
-	default:
-		return FALSE;
-	}
+	/*
+	 * We flush after the grab to ensure that the new item-cursor
+	 * gets created.  If it is not ready in time double click
+	 * events will be disrupted and it will appear as if we are
+	 * doing an button_press with a missing release.
+	 */
+	gdk_flush ();
+	return TRUE;
 }
 
 typedef enum {
@@ -1055,22 +812,22 @@ item_cursor_set_visibility (ItemCursor *ic, gboolean visible)
 		return;
 
 	ic->visible = visible;
-	foo_canvas_item_request_update (FOO_CANVAS_ITEM (ic));
+	if (visible)
+		goc_item_show (GOC_ITEM (ic));
+	else
+		goc_item_hide (GOC_ITEM (ic));
 }
 
 static void
 item_cursor_tip_setlabel (ItemCursor *ic, char const *text)
 {
 	if (ic->tip == NULL) {
-		FooCanvas *canvas = FOO_CANVAS_ITEM (ic)->canvas;
-		GtkWidget *cw = GTK_WIDGET (canvas);
-		int wx, wy;
-
-		gnm_canvas_get_position (canvas, &wx, &wy,
-					 ic->last_x, ic->last_y);
+		GtkWidget *cw = GTK_WIDGET (GOC_ITEM (ic)->canvas);
+		int x, y;
 		ic->tip = gnumeric_create_tooltip (cw);
 
-		gnumeric_position_tooltip (ic->tip, wx, wy, TRUE);
+		gnm_canvas_get_position (GOC_CANVAS (cw), &x, &y, ic->last_x, ic->last_y);
+		gnumeric_position_tooltip (ic->tip, x, y, TRUE);
 		gtk_widget_show_all (gtk_widget_get_toplevel (ic->tip));
 	}
 
@@ -1109,47 +866,23 @@ cb_move_cursor (GnmPane *pane, GnmPaneSlideInfo const *info)
 }
 
 static void
-item_cursor_handle_motion (ItemCursor *ic, GdkEvent *event,
+item_cursor_handle_motion (ItemCursor *ic, double x, double y,
 			   GnmPaneSlideHandler slide_handler)
 {
-	FooCanvas *canvas = FOO_CANVAS_ITEM (ic)->canvas;
+	GocCanvas *canvas = GOC_ITEM (ic)->canvas;
 
 	gnm_pane_handle_motion (GNM_PANE (canvas),
-		canvas, &event->motion,
+		canvas, x, y,
 		GNM_PANE_SLIDE_X | GNM_PANE_SLIDE_Y | GNM_PANE_SLIDE_AT_COLROW_BOUND,
 		slide_handler, ic);
+	goc_item_bounds_changed (GOC_ITEM (ic));
 }
 
-static gint
-item_cursor_drag_event (FooCanvasItem *item, GdkEvent *event)
+static gboolean
+item_cursor_drag_motion (ItemCursor *ic, double x, double y)
 {
-	ItemCursor *ic = ITEM_CURSOR (item);
-
-	switch (event->type) {
-	case GDK_BUTTON_RELEASE:
-		/* Note : see comment below, and bug 30507 */
-		if ((int)event->button.button == ic->drag_button) {
-			gnm_pane_slide_stop (GNM_PANE (item->canvas));
-			gnm_simple_canvas_ungrab (item, event->button.time);
-			item_cursor_do_drop (ic, (GdkEventButton *) event);
-		}
-		return TRUE;
-
-	case GDK_BUTTON_PRESS:
-		/* This kind of cursor is created and grabbed.  Then destroyed
-		 * when the button is released.  If we are seeing a press it
-		 * means that someone has pressed another button WHILE THE
-		 * FIRST IS STILL DOWN.  Ignore this event.
-		 */
-		return TRUE;
-
-	case GDK_MOTION_NOTIFY:
-		item_cursor_handle_motion (ic, event, &cb_move_cursor);
-		return TRUE;
-
-	default:
-		return FALSE;
-	}
+	item_cursor_handle_motion (ic, x, y, &cb_move_cursor);
+	return TRUE;
 }
 
 static gboolean
@@ -1234,117 +967,208 @@ cb_autofill_scroll (GnmPane *pane, GnmPaneSlideInfo const *info)
 	return FALSE;
 }
 
-static gint
-item_cursor_autofill_event (FooCanvasItem *item, GdkEvent *event)
+static gboolean
+item_cursor_button_pressed (GocItem *item, int button, double x_, double y_)
 {
 	ItemCursor *ic = ITEM_CURSOR (item);
-	SheetControlGUI *scg = ic->scg;
+	gint64 x = x_ * item->canvas->pixels_per_unit, y = y_ * item->canvas->pixels_per_unit;
+	GdkEventButton *event = (GdkEventButton *) goc_canvas_get_cur_event (item->canvas);
+	if (ic->style == ITEM_CURSOR_EXPR_RANGE)
+		return FALSE;
 
-	switch (event->type) {
-	case GDK_BUTTON_RELEASE: {
-		gboolean inverse_autofill =
-			(ic->pos.start.col < ic->autofill_src.start.col ||
-			 ic->pos.start.row < ic->autofill_src.start.row);
-		gboolean default_increment =
-			ic->drag_button_state & GDK_CONTROL_MASK;
+	/* While editing nothing should be draggable */
+	if (wbcg_is_editing (scg_wbcg (ic->scg)))
+		return TRUE;
 
-		gnm_pane_slide_stop (GNM_PANE (item->canvas));
-		gnm_simple_canvas_ungrab (item, event->button.time);
+	switch (ic->style) {
 
-		cmd_autofill (scg_wbc (scg), scg_sheet (scg), default_increment,
-			      ic->pos.start.col, ic->pos.start.row,
-			      range_width (&ic->autofill_src),
-			      range_height (&ic->autofill_src),
-			      ic->pos.end.col, ic->pos.end.row,
-			      inverse_autofill);
+	case ITEM_CURSOR_ANTED:
+		g_warning ("Animated cursors should not receive events, "
+			   "the point method should preclude that");
+		return FALSE;
 
-		scg_special_cursor_stop	(scg);
+	case ITEM_CURSOR_SELECTION:
+		/* NOTE : this cannot be called while we are editing.  because
+		 * the point routine excludes events.  so we do not need to
+		 * call wbcg_edit_finish.
+		 */
+
+		/* scroll wheel events dont have corresponding release events */
+		if (button > 3)
+			return FALSE;
+
+		/* If another button is already down ignore this one */
+		if (ic->drag_button >= 0)
+			return TRUE;
+
+		if (button != 3) {
+			/* prepare to create fill or drag cursors, but dont until we
+			 * move.  If we did create them here there would be problems
+			 * with race conditions when the new cursors pop into existence
+			 * during a double-click
+			 */
+
+			if (item_cursor_in_drag_handle (ic, x, y))
+				go_cmd_context_progress_message_set (GO_CMD_CONTEXT (scg_wbcg (ic->scg)),
+								     _("Drag to autofill"));
+			else
+				go_cmd_context_progress_message_set (GO_CMD_CONTEXT (scg_wbcg (ic->scg)),
+								     _("Drag to move"));
+
+			ic->drag_button = button;
+			ic->drag_button_state = event->state;
+			gnm_simple_canvas_grab (item,
+				GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK,
+				NULL, event->time);
+		} else
+			scg_context_menu (ic->scg, event, FALSE, FALSE);
 		return TRUE;
-	}
 
-	case GDK_MOTION_NOTIFY:
-		item_cursor_handle_motion (ic, event, &cb_autofill_scroll);
+	case ITEM_CURSOR_DRAG:
+		/* This kind of cursor is created and grabbed.  Then destroyed
+		 * when the button is released.  If we are seeing a press it
+		 * means that someone has pressed another button WHILE THE
+		 * FIRST IS STILL DOWN.  Ignore this event.
+		 */
 		return TRUE;
 
 	default:
 		return FALSE;
 	}
+	return TRUE;
 }
 
-static gint
-item_cursor_expr_range_event (FooCanvasItem *item, GdkEvent *event)
+static gboolean
+item_cursor_motion (GocItem *item, double x_, double y_)
 {
-	switch (event->type) {
-	case GDK_ENTER_NOTIFY:
-		gnm_widget_set_cursor_type (GTK_WIDGET (item->canvas), GDK_ARROW);
-		/* fall through */
-	case GDK_LEAVE_NOTIFY:
-		foo_canvas_item_request_redraw (item); /* Erase the old cursor */
-		break;
-	default :
-		break;
+	ItemCursor *ic = ITEM_CURSOR (item);
+	gint64 x = x_ * item->canvas->pixels_per_unit, y = y_ * item->canvas->pixels_per_unit;
+	ic->last_x = x;
+	ic->last_y = y;
+	if (ic->drag_button < 0) {
+		item_cursor_set_cursor (item->canvas, ic, x, y);
+		return TRUE;
 	}
-	return FALSE;
-}
+	if (ic->style == ITEM_CURSOR_EXPR_RANGE)
+		return FALSE;
 
-static gint
-item_cursor_event (FooCanvasItem *item, GdkEvent *event)
-{
-	ItemCursor *ic = ITEM_CURSOR (item);
+	/* While editing nothing should be draggable */
+	if (wbcg_is_editing (scg_wbcg (ic->scg)))
+		return TRUE;
+	switch (ic->style) {
+
+	case ITEM_CURSOR_ANTED:
+		g_warning ("Animated cursors should not receive events, "
+			   "the point method should preclude that");
+		return FALSE;
+
+	case ITEM_CURSOR_SELECTION:
+		return item_cursor_selection_motion (item, x, y);
+
+	case ITEM_CURSOR_DRAG:
+		return item_cursor_drag_motion (ic, x, y);
+
+	case ITEM_CURSOR_AUTOFILL:
+		item_cursor_handle_motion (ITEM_CURSOR (item), x, y, &cb_autofill_scroll);
+		return TRUE;
 
-#if 0
-	switch (event->type)
-	{
-	case GDK_BUTTON_RELEASE: printf ("release %d\n", ic->style); break;
-	case GDK_BUTTON_PRESS: printf ("press %d\n", ic->style); break;
-	case GDK_2BUTTON_PRESS: printf ("2press %d\n", ic->style); break;
-	default :
-	    break;
-	}
-#endif
-	switch (event->type) {
-	case GDK_MOTION_NOTIFY:
-		ic->last_x = event->motion.x;
-		ic->last_y = event->motion.y;
-		break;
 	default:
-		;
+		return FALSE;
 	}
+}
 
+static gboolean
+item_cursor_button_released (GocItem *item, int button, G_GNUC_UNUSED double x, G_GNUC_UNUSED double y)
+{
+	ItemCursor *ic = ITEM_CURSOR (item);
+	GdkEventButton *event = (GdkEventButton *) goc_canvas_get_cur_event (item->canvas);
 	if (ic->style == ITEM_CURSOR_EXPR_RANGE)
-		return item_cursor_expr_range_event (item, event);
+		return FALSE;
 
 	/* While editing nothing should be draggable */
 	if (wbcg_is_editing (scg_wbcg (ic->scg)))
 		return TRUE;
-
 	switch (ic->style) {
+
 	case ITEM_CURSOR_ANTED:
 		g_warning ("Animated cursors should not receive events, "
 			   "the point method should preclude that");
 		return FALSE;
 
 	case ITEM_CURSOR_SELECTION:
-		return item_cursor_selection_event (item, event);
+		if (ic->drag_button != button)
+			return TRUE;
+
+		/* Double clicks may have already released the drag prep */
+		if (ic->drag_button >= 0) {
+			gnm_simple_canvas_ungrab (item, event->time);
+			ic->drag_button = -1;
+		}
+		go_cmd_context_progress_message_set (GO_CMD_CONTEXT (scg_wbcg (ic->scg)),
+						     " ");
+		return TRUE;
 
 	case ITEM_CURSOR_DRAG:
-		return item_cursor_drag_event (item, event);
+		/* Note : see comment initem_cursor_button_pressed, and bug 30507 */
+		if (button == ic->drag_button) {
+			gnm_pane_slide_stop (GNM_PANE (item->canvas));
+			gnm_simple_canvas_ungrab (item, event->time);
+			item_cursor_do_drop (ic, event);
+		}
+		return TRUE;
 
-	case ITEM_CURSOR_AUTOFILL:
-		return item_cursor_autofill_event (item, event);
+	case ITEM_CURSOR_AUTOFILL: {
+		gboolean inverse_autofill =
+			(ic->pos.start.col < ic->autofill_src.start.col ||
+			 ic->pos.start.row < ic->autofill_src.start.row);
+		gboolean default_increment =
+			ic->drag_button_state & GDK_CONTROL_MASK;
+		SheetControlGUI *scg = ic->scg;
+
+		gnm_pane_slide_stop (GNM_PANE (item->canvas));
+		gnm_simple_canvas_ungrab (item, event->time);
+
+		cmd_autofill (scg_wbc (scg), scg_sheet (scg), default_increment,
+			      ic->pos.start.col, ic->pos.start.row,
+			      range_width (&ic->autofill_src),
+			      range_height (&ic->autofill_src),
+			      ic->pos.end.col, ic->pos.end.row,
+			      inverse_autofill);
 
+		scg_special_cursor_stop	(scg);
+		return TRUE;
+	}
 	default:
 		return FALSE;
 	}
 }
 
+static gboolean
+item_cursor_enter_notify (GocItem *item, double x_, double y_)
+{
+	ItemCursor *ic = ITEM_CURSOR (item);
+	gint64 x = x_ * item->canvas->pixels_per_unit, y = y_ * item->canvas->pixels_per_unit;
+	if (ic->style == ITEM_CURSOR_EXPR_RANGE)
+		gnm_widget_set_cursor_type (GTK_WIDGET (item->canvas), GDK_ARROW);
+	else if (ic->style == ITEM_CURSOR_SELECTION)
+		item_cursor_set_cursor (item->canvas, ic, x, y);
+	return FALSE;
+}
+
+static gboolean
+item_cursor_leave_notify (GocItem *item, G_GNUC_UNUSED double x, G_GNUC_UNUSED double y)
+{
+	ItemCursor *ic = ITEM_CURSOR (item);
+	if (ic->style == ITEM_CURSOR_EXPR_RANGE)
+		goc_item_invalidate (item);
+	return FALSE;
+}
+
 static void
 item_cursor_set_property (GObject *obj, guint param_id,
 			  GValue const *value, GParamSpec *pspec)
 {
-	FooCanvasItem *item = FOO_CANVAS_ITEM (obj);
 	ItemCursor *ic = ITEM_CURSOR (obj);
-	GdkColor color;
 	char const *color_name;
 
 	switch (param_id) {
@@ -1359,10 +1183,8 @@ item_cursor_set_property (GObject *obj, guint param_id,
 		break;
 	case ITEM_CURSOR_PROP_COLOR:
 		color_name = g_value_get_string (value);
-		if (foo_canvas_get_color (item->canvas, color_name, &color)) {
-			ic->color = color;
+		if (go_color_from_str (color_name, &ic->color))
 			ic->use_color = 1;
-		}
 	}
 }
 
@@ -1372,7 +1194,8 @@ item_cursor_set_property (GObject *obj, guint param_id,
 static void
 item_cursor_class_init (GObjectClass *gobject_klass)
 {
-	FooCanvasItemClass *item_klass = (FooCanvasItemClass *) gobject_klass;
+
+	GocItemClass *item_klass = (GocItemClass *) gobject_klass;
 
 	parent_class = g_type_class_peek_parent (gobject_klass);
 
@@ -1399,24 +1222,21 @@ item_cursor_class_init (GObjectClass *gobject_klass)
 			"black",
                         GSF_PARAM_STATIC |  G_PARAM_WRITABLE));
 
-	item_klass->update      = item_cursor_update;
 	item_klass->realize     = item_cursor_realize;
 	item_klass->unrealize   = item_cursor_unrealize;
-	item_klass->draw        = item_cursor_draw;
-	item_klass->point       = item_cursor_point;
-	item_klass->event       = item_cursor_event;
+	item_klass->draw		= item_cursor_draw;
+	item_klass->update_bounds = item_cursor_update_bounds;
+	item_klass->distance	= item_cursor_distance;
+	item_klass->button_pressed = item_cursor_button_pressed;
+	item_klass->button_released = item_cursor_button_released;
+	item_klass->motion      = item_cursor_motion;
+	item_klass->enter_notify = item_cursor_enter_notify;
+	item_klass->enter_notify = item_cursor_leave_notify;
 }
 
 static void
 item_cursor_init (ItemCursor *ic)
 {
-	FooCanvasItem *item = FOO_CANVAS_ITEM (ic);
-
-	item->x1 = 0;
-	item->y1 = 0;
-	item->x2 = 1;
-	item->y2 = 1;
-
 	ic->pos_initialized = FALSE;
 	ic->pos.start.col = 0;
 	ic->pos.end.col   = 0;
@@ -1434,7 +1254,6 @@ item_cursor_init (ItemCursor *ic)
 	ic->last_y = 0;
 
 	ic->style = ITEM_CURSOR_SELECTION;
-	ic->gc = NULL;
 	ic->state = 0;
 	ic->animation_timer = -1;
 
@@ -1442,8 +1261,9 @@ item_cursor_init (ItemCursor *ic)
 	ic->auto_fill_handle_at_top = FALSE;
 	ic->auto_fill_handle_at_left = FALSE;
 	ic->drag_button = -1;
+	ic->color = RGBA_BLACK;
 }
 
 GSF_CLASS (ItemCursor, item_cursor,
 	   item_cursor_class_init, item_cursor_init,
-	   FOO_TYPE_CANVAS_ITEM)
+	   GOC_TYPE_ITEM)
diff --git a/src/item-cursor.h b/src/item-cursor.h
index 38b2d07..cad315b 100644
--- a/src/item-cursor.h
+++ b/src/item-cursor.h
@@ -4,6 +4,7 @@
 
 #include "gui-gnumeric.h"
 #include <glib-object.h>
+#include <goffice/canvas/goffice-canvas.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/item-edit.c b/src/item-edit.c
index 274c545..c225935 100644
--- a/src/item-edit.c
+++ b/src/item-edit.c
@@ -38,15 +38,14 @@
 #define GNUMERIC_ITEM "EDIT"
 
 #include <gtk/gtk.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
 #include <gsf/gsf-impl-utils.h>
 #include <string.h>
 #include <goffice/goffice.h>
 
-static FooCanvasItemClass *parent_class;
+static GocItemClass *parent_class;
 
 struct _ItemEdit {
-	FooCanvasItem item;
+	GocItem item;
 
 	SheetControlGUI *scg;
 	GtkEntry	*entry;		/* Utility pointer to the workbook entry */
@@ -60,10 +59,9 @@ struct _ItemEdit {
 
 	GnmFont   *gfont;
 	GnmStyle  *style;
-	GdkGC     *fill_gc;	/* Default background fill gc */
 };
 
-typedef FooCanvasItemClass ItemEditClass;
+typedef GocItemClass ItemEditClass;
 
 /* The arguments we take */
 enum {
@@ -75,13 +73,15 @@ static void
 get_top_left (ItemEdit const *ie, int *top, int *left)
 {
 	GnmVAlign const align = gnm_style_get_align_v (ie->style);
+	GocItem *item = GOC_ITEM (ie);
+	GocCanvas *canvas = item->canvas;
+	double l = (goc_canvas_get_direction (canvas) == GOC_DIRECTION_RTL)? item->x1 - 1: item->x0;
 
-	*left = ((int)ie->item.x1) + GNM_COL_MARGIN;
-	*top  = (int)ie->item.y1;
+	goc_canvas_c2w (canvas, l, item->y0, left, top);
 
 	if (align == VALIGN_CENTER || align == VALIGN_DISTRIBUTED ||
 	    align == VALIGN_BOTTOM) {
-		int text_height, height = (int)(ie->item.y2 - ie->item.y1);
+		int text_height, height = (int)(ie->item.y1 - ie->item.y0) * canvas->pixels_per_unit;
 		pango_layout_get_pixel_size (ie->layout, NULL, &text_height);
 		*top += (align != VALIGN_BOTTOM)
 			? (height - text_height)/2
@@ -90,194 +90,196 @@ get_top_left (ItemEdit const *ie, int *top, int *left)
 }
 
 static void
-item_edit_draw (FooCanvasItem *item, GdkDrawable *drawable,
-		GdkEventExpose *expose)
+item_edit_draw (GocItem const *item, cairo_t *cr)
 {
 	ItemEdit  const *ie	= ITEM_EDIT (item);
-	GdkGC *black_gc		= GTK_WIDGET (item->canvas)->style->black_gc;
 	int top, left;
-
-	if (ie->style == NULL)
-		return;
-
-	/* Draw the background (recall that gdk_draw_rectangle excludes far coords) */
-	gdk_draw_rectangle (drawable, ie->fill_gc, TRUE,
-		(int)item->x1,			(int)item->y1,
-		(int)(item->x2 - item->x1),	(int)(item->y2 - item->y1));
+	PangoLayout *layout;
+	GOColor color;
+	int x0, y0, x1, y1; /* in widget coordinates */
 
 	get_top_left (ie, &top, &left);
-	gdk_draw_layout (drawable, black_gc, left, top, ie->layout);
+	if (goc_canvas_get_direction (item->canvas) == GOC_DIRECTION_RTL) {
+		goc_canvas_c2w (item->canvas, item->x1, item->y0, &x0, &y0);
+		goc_canvas_c2w (item->canvas, item->x0, item->y1, &x1, &y1);
+	} else {
+		goc_canvas_c2w (item->canvas, item->x0, item->y0, &x0, &y0);
+		goc_canvas_c2w (item->canvas, item->x1, item->y1, &x1, &y1);
+	}
+
+	cairo_rectangle (cr, x0, y0, x1 - x0, y1 - y0);
+	cairo_set_source_rgba (cr, 1., 1., 0.878431373, 1.);
+	cairo_fill (cr);
+
+	color = GDK_TO_UINT (gtk_widget_get_style (GTK_WIDGET (item->canvas))->black);
+	cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (color));
+	cairo_move_to (cr, left, top);
+	layout = pango_cairo_create_layout (cr);
+	pango_layout_set_text (layout, pango_layout_get_text (ie->layout), -1);
+	pango_layout_set_attributes (layout, pango_layout_get_attributes (ie->layout));
+	pango_cairo_show_layout (cr, layout);
+	g_object_unref (layout);
 	if (ie->cursor_visible) {
 		PangoRectangle pos;
 		char const *text = gtk_entry_get_text (ie->entry);
 		int cursor_pos = gtk_editable_get_position (GTK_EDITABLE (ie->entry));
 		pango_layout_index_to_pos (ie->layout,
 			g_utf8_offset_to_pointer (text, cursor_pos) - text, &pos);
-		gdk_draw_line (drawable, black_gc,
-			left + PANGO_PIXELS (pos.x), top + PANGO_PIXELS (pos.y),
-			left + PANGO_PIXELS (pos.x), top + PANGO_PIXELS (pos.y + pos.height) - 1);
+		cairo_set_line_width (cr, 1.);
+		cairo_set_dash (cr, NULL, 0, 0.);
+		cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+		cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+		cairo_set_source_rgba (cr, 0., 0., 0., 1.);
+		cairo_move_to (cr, left + PANGO_PIXELS (pos.x) + .5, top + PANGO_PIXELS (pos.y));
+		cairo_line_to (cr, left + PANGO_PIXELS (pos.x) + .5, top + PANGO_PIXELS (pos.y + pos.height) - 1);
+		cairo_stroke (cr);
 	}
 }
 
 static double
-item_edit_point (FooCanvasItem *item, double c_x, double c_y, int cx, int cy,
-		 FooCanvasItem **actual_item)
+item_edit_distance (GocItem *item, double cx, double cy,
+		 GocItem **actual_item)
 {
 	*actual_item = NULL;
-	if ((cx < item->x1) || (cy < item->y1) || (cx >= item->x2) || (cy >= item->y2))
+	if ((cx < item->x0) || (cy < item->y0) || (cx >= item->x1) || (cy >= item->y1))
 		return 10000.0;
 
 	*actual_item = item;
 	return 0.0;
 }
 
+static gboolean
+item_edit_enter_notify (GocItem *item, double x, double y)
+{
+	gnm_widget_set_cursor_type (GTK_WIDGET (item->canvas), GDK_XTERM);
+	return TRUE;
+}
+
 static int
-item_edit_event (FooCanvasItem *item, GdkEvent *event)
+item_edit_button_pressed (GocItem *item, int button, double x, double y)
 {
-	switch (event->type){
-	case GDK_ENTER_NOTIFY:
-		gnm_widget_set_cursor_type (GTK_WIDGET (item->canvas), GDK_XTERM);
-		return TRUE;
-
-	case GDK_BUTTON_PRESS:
-		if (event->button.button == 1) {
-			ItemEdit *ie = ITEM_EDIT (item);
-			GtkEditable *ed = GTK_EDITABLE (ie->entry);
-			int x, y, target_index, trailing, top, left;
-
-			foo_canvas_w2c (item->canvas,
-				event->button.x, event->button.y, &x, &y);
-
-			get_top_left (ie, &top, &left);
-			y -= top;
-			x -= left;
-
-			if (pango_layout_xy_to_index (ie->layout,
-						      x * PANGO_SCALE, y * PANGO_SCALE,
-						      &target_index, &trailing)) {
-				int preedit = GNM_PANE (item->canvas)->preedit_length;
-				char const *text = pango_layout_get_text (ie->layout);
-				gint cur_index = gtk_editable_get_position (ed);
-				cur_index = g_utf8_offset_to_pointer (text, cur_index) - text;
-
-				if (target_index >= cur_index && preedit > 0) {
-					if (target_index < (cur_index + preedit)) {
-						target_index = cur_index;
-						trailing = 0;
-					} else
-						target_index -= preedit;
-				}
-				gtk_editable_set_position (GTK_EDITABLE (ie->entry),
-					g_utf8_pointer_to_offset (text, text + target_index)
-					+ trailing);
-
-				return TRUE;
+	if (button == 1) {
+		ItemEdit *ie = ITEM_EDIT (item);
+		GtkEditable *ed = GTK_EDITABLE (ie->entry);
+		int target_index, trailing;
+		int top, left;
+
+		get_top_left (ie, &top, &left);
+		y -= top;
+		x -= left;
+
+		if (pango_layout_xy_to_index (ie->layout,
+					      x * PANGO_SCALE, y * PANGO_SCALE,
+					      &target_index, &trailing)) {
+			int preedit = GNM_PANE (item->canvas)->preedit_length;
+			char const *text = pango_layout_get_text (ie->layout);
+			gint cur_index = gtk_editable_get_position (ed);
+			cur_index = g_utf8_offset_to_pointer (text, cur_index) - text;
+
+			if (target_index >= cur_index && preedit > 0) {
+				if (target_index < (cur_index + preedit)) {
+					target_index = cur_index;
+					trailing = 0;
+				} else
+					target_index -= preedit;
 			}
-		}
-		break;
+			gtk_editable_set_position (GTK_EDITABLE (ie->entry),
+				g_utf8_pointer_to_offset (text, text + target_index)
+				+ trailing);
 
-	default :
-		break;
+			return TRUE;
+		}
 	}
 	return FALSE;
 }
 
 static void
-ie_layout (FooCanvasItem *item)
+item_edit_update_bounds (GocItem *item)
 {
 	ItemEdit *ie = ITEM_EDIT (item);
-	GtkWidget const  *canvas = GTK_WIDGET (item->canvas);
-	GnmPane	 const  *pane = GNM_PANE (item->canvas);
-	ColRowInfo const *ci;
-	Sheet const	 *sheet  = scg_sheet (ie->scg);
-	GnmFont  const   *gfont = ie->gfont;
-	GnmRange const   *merged;
-	int col, tmp, width, height, col_size;
-	char const *text, *entered_text;
-	PangoAttrList	*attrs;
-	PangoAttribute  *attr;
-	int cursor_pos = gtk_editable_get_position (GTK_EDITABLE (ie->entry));
-
-	entered_text = gtk_entry_get_text (ie->entry);
-	text = wbcg_edit_get_display_text (scg_wbcg (ie->scg));
-	pango_layout_set_text (ie->layout, text, -1);
-
-	pango_layout_set_font_description (ie->layout, gfont->go.font->desc);
-	pango_layout_set_wrap (ie->layout, PANGO_WRAP_WORD_CHAR);
-	pango_layout_set_width (ie->layout, (int)(item->x2 - item->x1)*PANGO_SCALE);
-
-	attrs = wbcg_edit_get_markup (scg_wbcg (ie->scg), TRUE);
-	if (attrs != NULL)
-		attrs = pango_attr_list_copy (attrs);
-	else
-		attrs = gnm_style_generate_attrs_full (ie->style);
-
-	/* reverse video the auto completion text  */
-	if (entered_text != NULL && entered_text != text) {
-		int const start = strlen (entered_text);
-		GnmColor const *color = gnm_style_get_font_color (ie->style);
-		attr = pango_attr_background_new (
-			color->gdk_color.red, color->gdk_color.green, color->gdk_color.blue);
-		attr->start_index = start;
-		attr->end_index = G_MAXINT;
-		pango_attr_list_insert (attrs, attr);
+	double scale = item->canvas->pixels_per_unit;
 
-		color = gnm_style_get_back_color (ie->style);
-		attr = pango_attr_foreground_new (
-			color->gdk_color.red, color->gdk_color.green, color->gdk_color.blue);
-		attr->start_index = start;
+	if (ie->gfont != NULL) {
+		GtkWidget const  *canvas = GTK_WIDGET (item->canvas);
+		GnmPane	 const  *pane = GNM_PANE (item->canvas);
+		ColRowInfo const *ci;
+		Sheet const	 *sheet  = scg_sheet (ie->scg);
+		GnmFont  const   *gfont = ie->gfont;
+		GnmRange const   *merged;
+		int col, tmp, width, height, col_size;
+		char const *text, *entered_text;
+		PangoAttrList	*attrs;
+		PangoAttribute  *attr;
+		int cursor_pos = gtk_editable_get_position (GTK_EDITABLE (ie->entry));
+
+		entered_text = gtk_entry_get_text (ie->entry);
+		text = wbcg_edit_get_display_text (scg_wbcg (ie->scg));
+		pango_layout_set_text (ie->layout, text, -1);
+
+		pango_layout_set_font_description (ie->layout, gfont->go.font->desc);
+		pango_layout_set_wrap (ie->layout, PANGO_WRAP_WORD_CHAR);
+		pango_layout_set_width (ie->layout, (int)(item->x1 - item->x0)*PANGO_SCALE);
+
+		attrs = wbcg_edit_get_markup (scg_wbcg (ie->scg), TRUE);
+		if (attrs != NULL)
+			attrs = pango_attr_list_copy (attrs);
+		else
+			attrs = gnm_style_generate_attrs_full (ie->style);
+
+		/* reverse video the auto completion text  */
+		if (entered_text != NULL && entered_text != text) {
+			int const start = strlen (entered_text);
+			GnmColor const *color = gnm_style_get_font_color (ie->style);
+			attr = pango_attr_background_new (
+				color->gdk_color.red, color->gdk_color.green, color->gdk_color.blue);
+			attr->start_index = start;
+			attr->end_index = G_MAXINT;
+			pango_attr_list_insert (attrs, attr);
+
+			color = gnm_style_get_back_color (ie->style);
+			attr = pango_attr_foreground_new (
+				color->gdk_color.red, color->gdk_color.green, color->gdk_color.blue);
+			attr->start_index = start;
+			attr->end_index = G_MAXINT;
+			pango_attr_list_insert (attrs, attr);
+		}
+		attr = pango_attr_scale_new (item->canvas->pixels_per_unit);
+		attr->start_index = 0;
 		attr->end_index = G_MAXINT;
-		pango_attr_list_insert (attrs, attr);
-	}
-	attr = pango_attr_scale_new (item->canvas->pixels_per_unit);
-	attr->start_index = 0;
-	attr->end_index = G_MAXINT;
-	pango_attr_list_insert_before (attrs, attr);
-
-	pango_layout_set_attributes (ie->layout, attrs);
-	pango_attr_list_unref (attrs);
-
-	text = wbcg_edit_get_display_text (scg_wbcg (ie->scg));
-
-	if (pane->preedit_length) {
-		PangoAttrList *tmp_attrs = pango_attr_list_new ();
-		pango_attr_list_splice (tmp_attrs, pane->preedit_attrs,
-			g_utf8_offset_to_pointer (text, cursor_pos) - text,
-			g_utf8_offset_to_pointer (text, cursor_pos + pane->preedit_length) - text);
-		pango_layout_set_attributes (ie->layout, tmp_attrs);
-		pango_attr_list_unref (tmp_attrs);
-	}
+		pango_attr_list_insert_before (attrs, attr);
 
-	pango_layout_set_width (ie->layout, -1);
-	pango_layout_get_pixel_size (ie->layout, &width, &height);
+		pango_layout_set_attributes (ie->layout, attrs);
+		pango_attr_list_unref (attrs);
 
-	col = ie->pos.col;
-	if (NULL == (merged = gnm_sheet_merge_is_corner (sheet, &ie->pos))) {
-		ci = sheet_col_get_info (sheet, col);
-		g_return_if_fail (ci != NULL);
-		col_size = ci->size_pixels;
-	} else
-		col_size = scg_colrow_distance_get (ie->scg, TRUE,
-			merged->start.col, merged->end.col+1);
+		text = wbcg_edit_get_display_text (scg_wbcg (ie->scg));
 
-	/* both margins and the gridline */
-	col_size -= GNM_COL_MARGIN + GNM_COL_MARGIN + 1;
+		if (pane->preedit_length) {
+			PangoAttrList *tmp_attrs = pango_attr_list_new ();
+			pango_attr_list_splice (tmp_attrs, pane->preedit_attrs,
+				g_utf8_offset_to_pointer (text, cursor_pos) - text,
+				g_utf8_offset_to_pointer (text, cursor_pos + pane->preedit_length) - text);
+			pango_layout_set_attributes (ie->layout, tmp_attrs);
+			pango_attr_list_unref (tmp_attrs);
+		}
 
-	/* far corner based on the span size
-	 *	- margin on each end
-	 *	- the bound excludes the far point => +1 */
-	if (sheet->text_is_rtl) {
-		while (col_size < width && col >= pane->first.col) {
-			ci = sheet_col_get_info (sheet, col--);
+		pango_layout_set_width (ie->layout, -1);
+		pango_layout_get_pixel_size (ie->layout, &width, &height);
 
+		col = ie->pos.col;
+		if (NULL == (merged = gnm_sheet_merge_is_corner (sheet, &ie->pos))) {
+			ci = sheet_col_get_info (sheet, col);
 			g_return_if_fail (ci != NULL);
+			col_size = ci->size_pixels;
+		} else
+			col_size = scg_colrow_distance_get (ie->scg, TRUE,
+				merged->start.col, merged->end.col+1);
 
-			if (ci->visible)
-				col_size += ci->size_pixels;
-		}
+		/* both margins and the gridline */
+		col_size -= GNM_COL_MARGIN + GNM_COL_MARGIN + 1;
 
-		tmp = gnm_foo_canvas_x_w2c (item->canvas, pane->first_offset.col);
-	} else {
+		/* far corner based on the span size
+		 *	- margin on each end
+		 *	- the bound excludes the far point => +1 */
 		if (merged != NULL)
 			col = merged->end.col;
 
@@ -291,62 +293,39 @@ ie_layout (FooCanvasItem *item)
 			if (ci->visible)
 				col_size += ci->size_pixels;
 		}
-		tmp = pane->first_offset.col + canvas->allocation.width;
-	}
-	item->x2 = item->x1 + col_size + GNM_COL_MARGIN + GNM_COL_MARGIN + 1;
-
-	if (item->x2 >= tmp) {
-		item->x2 = tmp;
-		pango_layout_set_width (ie->layout, (item->x2 - item->x1 + 1)*PANGO_SCALE);
-		pango_layout_get_pixel_size (ie->layout, &width, &height);
-	}
-
-	tmp = scg_colrow_distance_get (ie->scg, FALSE, ie->pos.row,
-		(merged ? merged->end.row : ie->pos.row) + 1) - 2 + 1;
-	item->y2 = item->y1 + MAX (height, tmp);
-}
-
-static void
-item_edit_update (FooCanvasItem *item,  double i2w_dx, double i2w_dy, int flags)
-{
-	ItemEdit *ie = ITEM_EDIT (item);
+		tmp = pane->first_offset.x + canvas->allocation.width;
+		item->x1 = item->x0 + (col_size + GNM_COL_MARGIN + GNM_COL_MARGIN + 1) / scale;
 
-	if (parent_class->update)
-		(parent_class->update)(item, i2w_dx, i2w_dy, flags);
+		if (item->x1 >= tmp) {
+			item->x1 = tmp;
+			pango_layout_set_width (ie->layout, (item->x1 - item->x0 + 1)*PANGO_SCALE);
+			pango_layout_get_pixel_size (ie->layout, &width, &height);
+		}
 
-	/* do not calculate spans until after row/col has been set */
-	if (ie->gfont != NULL) {
-		/* Redraw before and after in case the span changes */
-		foo_canvas_item_request_redraw (item);
-		ie_layout (item);
-		foo_canvas_item_request_redraw (item);
+		tmp = scg_colrow_distance_get (ie->scg, FALSE, ie->pos.row,
+			(merged ? merged->end.row : ie->pos.row) + 1) - 1;
+		item->y1 = item->y0 + (MAX (height, tmp)) / scale;
 	}
 }
 
 static void
-item_edit_realize (FooCanvasItem *item)
+item_edit_realize (GocItem *item)
 {
 	ItemEdit *ie = ITEM_EDIT (item);
 	if (parent_class->realize)
 		(parent_class->realize) (item);
 
-	ie->fill_gc = gdk_gc_new (GTK_WIDGET (item->canvas)->window);
-	if (!gnumeric_background_set_gc (ie->style, ie->fill_gc, item->canvas, FALSE))
-		gdk_gc_set_rgb_fg_color (ie->fill_gc, &gs_yellow);
-
 	ie->layout = gtk_widget_create_pango_layout (GTK_WIDGET (item->canvas), NULL);
-	pango_layout_set_alignment (ie->layout,
-		scg_sheet (ie->scg)->text_is_rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT);
+	if (ie->scg)
+		pango_layout_set_alignment (ie->layout,
+			scg_sheet (ie->scg)->text_is_rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT);
 }
 
 static void
-item_edit_unrealize (FooCanvasItem *item)
+item_edit_unrealize (GocItem *item)
 {
 	ItemEdit *ie = ITEM_EDIT (item);
 
-	g_object_unref (G_OBJECT (ie->fill_gc));
-	ie->fill_gc = NULL;
-
 	g_object_unref (G_OBJECT (ie->layout));
 	ie->layout = NULL;
 
@@ -357,11 +336,11 @@ item_edit_unrealize (FooCanvasItem *item)
 static int
 cb_item_edit_cursor_blink (ItemEdit *ie)
 {
-	FooCanvasItem *item = FOO_CANVAS_ITEM (ie);
+	GocItem *item = GOC_ITEM (ie);
 
 	ie->cursor_visible = !ie->cursor_visible;
-
-	foo_canvas_item_request_redraw (item);
+	
+	goc_item_invalidate (item);
 	return TRUE;
 }
 
@@ -393,21 +372,12 @@ item_edit_cursor_blink_start (ItemEdit *ie)
 static void
 item_edit_init (ItemEdit *ie)
 {
-	FooCanvasItem *item = FOO_CANVAS_ITEM (ie);
-
-	/* Apply an arbitrary size/pos for now.  Init when we get the scg */
-	item->x1 = 0;
-	item->y1 = 0;
-	item->x2 = 1;
-	item->y2 = 1;
-
 	ie->scg = NULL;
 	ie->pos.col = -1;
 	ie->pos.row = -1;
 	ie->gfont = NULL;
 	ie->style      = NULL;
 	ie->cursor_visible = TRUE;
-	ie->fill_gc = NULL;
 }
 
 static void
@@ -434,19 +404,20 @@ item_edit_dispose (GObject *gobject)
 }
 
 static int
-cb_entry_key_press (FooCanvasItem *item)
+cb_entry_key_press (GocItem *item)
 {
-	foo_canvas_item_request_update (item);
+	goc_item_bounds_changed (item);
 	return TRUE;
 }
 
 static int
-cb_entry_cursor_event (FooCanvasItem *item)
+cb_entry_cursor_event (GocItem *item)
 {
 	/* ensure we draw a cursor when moving quickly no matter what the
 	 * current state is */
 	ITEM_EDIT (item)->cursor_visible = TRUE;
-	foo_canvas_item_request_update (item);
+	goc_item_invalidate (item);
+
 	return TRUE;
 }
 
@@ -454,10 +425,11 @@ static void
 item_edit_set_property (GObject *gobject, guint param_id,
 			GValue const *value, GParamSpec *pspec)
 {
-	FooCanvasItem *item      = FOO_CANVAS_ITEM (gobject);
+	GocItem *item      = GOC_ITEM (gobject);
 	ItemEdit        *ie = ITEM_EDIT (gobject);
 	GnmPane		*pane = GNM_PANE (item->canvas);
 	SheetView const	*sv;
+	double scale = item->canvas->pixels_per_unit;
 
 	/* We can only set the sheet-control-gui once */
 	g_return_if_fail (param_id == ARG_SHEET_CONTROL_GUI);
@@ -470,10 +442,10 @@ item_edit_set_property (GObject *gobject, guint param_id,
 	ie->entry = wbcg_get_entry (scg_wbcg (ie->scg));
 	g_signal_connect_object (G_OBJECT (scg_wbcg (ie->scg)),
 		"markup-changed",
-		G_CALLBACK (foo_canvas_item_request_update), G_OBJECT (ie), G_CONNECT_SWAPPED);
+		G_CALLBACK (goc_item_invalidate), G_OBJECT (ie), G_CONNECT_SWAPPED);
 	g_signal_connect_object (G_OBJECT (gtk_widget_get_parent (GTK_WIDGET (ie->entry))),
 		"changed",
-		G_CALLBACK (foo_canvas_item_request_update), G_OBJECT (ie), G_CONNECT_SWAPPED);
+		G_CALLBACK (goc_item_bounds_changed), G_OBJECT (ie), G_CONNECT_SWAPPED);
 	g_signal_connect_object (G_OBJECT (ie->entry),
 		"key-press-event",
 		G_CALLBACK (cb_entry_key_press), G_OBJECT (ie), G_CONNECT_AFTER|G_CONNECT_SWAPPED);
@@ -494,37 +466,28 @@ item_edit_set_property (GObject *gobject, guint param_id,
 			gnm_style_set_align_h (ie->style, HALIGN_LEFT);
 
 		/* move inwards 1 pixel from the grid line */
-		item->y1 = 1 + pane->first_offset.row +
+		item->y0 = (1 + pane->first_offset.y +
 			scg_colrow_distance_get (ie->scg, FALSE,
-				pane->first.row, ie->pos.row);
-		item->x1 = 1 + pane->first_offset.col +
+				pane->first.row, ie->pos.row)) / scale;
+		item->x0 = (1 + pane->first_offset.x +
 			scg_colrow_distance_get (ie->scg, TRUE,
-				pane->first.col, ie->pos.col);
-		if (sv_sheet (sv)->text_is_rtl) {
-			GnmRange const *merged = gnm_sheet_merge_is_corner (sheet, &ie->pos);
-			int end_col = ie->pos.col;
-			if (merged != NULL)
-				end_col = merged->end.col;
-
-			/* -1 to remove the above, then 2 more to move from next cell back */
-			item->x1 = 1 + gnm_foo_canvas_x_w2c (item->canvas, item->x1 +
-				scg_colrow_distance_get (ie->scg, TRUE,
-					ie->pos.col, end_col + 1) - 1);
-		}
+				pane->first.col, ie->pos.col)) / scale;
 
-		item->x2 = item->x1 + 1;
-		item->y2 = item->y2 + 1;
+		item->x1 = item->x0 + 1 / scale;
+		item->y1 = item->y0 + 1 / scale;
 	}
 
-	item_edit_cursor_blink_start (ie);
+	if (ie->layout)
+		pango_layout_set_alignment (ie->layout,
+			scg_sheet (ie->scg)->text_is_rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT);
 
-	foo_canvas_item_request_update (item);
+	item_edit_cursor_blink_start (ie);
 }
 
 static void
 item_edit_class_init (GObjectClass *gobject_class)
 {
-	FooCanvasItemClass *item_class = (FooCanvasItemClass *) gobject_class;
+	GocItemClass *item_class = (GocItemClass *) gobject_class;
 
 	parent_class = g_type_class_peek_parent (gobject_class);
 
@@ -536,20 +499,21 @@ item_edit_class_init (GObjectClass *gobject_class)
 			"the sheet control gui controlling the item",
 			SHEET_CONTROL_GUI_TYPE,
 			/* resist the urge to use G_PARAM_CONSTRUCT_ONLY
-			 * We are going through foo_canvas_item_new, which
+			 * We are going through goc_item_new, which
 			 * calls g_object_new assigns the parent pointer before
 			 * setting the construction parameters */
 			 GSF_PARAM_STATIC | G_PARAM_WRITABLE));
 
-	/* FooCanvasItem method overrides */
-	item_class->update      = item_edit_update;
-	item_class->realize     = item_edit_realize;
-	item_class->unrealize   = item_edit_unrealize;
-	item_class->draw        = item_edit_draw;
-	item_class->point       = item_edit_point;
-	item_class->event       = item_edit_event;
+	/* GocItem method overrides */
+	item_class->realize        = item_edit_realize;
+	item_class->unrealize      = item_edit_unrealize;
+	item_class->draw           = item_edit_draw;
+	item_class->distance       = item_edit_distance;
+	item_class->update_bounds  = item_edit_update_bounds;
+	item_class->button_pressed = item_edit_button_pressed;
+	item_class->enter_notify   = item_edit_enter_notify;
 }
 
 GSF_CLASS (ItemEdit, item_edit,
 	   item_edit_class_init, item_edit_init,
-	   FOO_TYPE_CANVAS_ITEM)
+	   GOC_TYPE_ITEM)
diff --git a/src/item-grid.c b/src/item-grid.c
index 8705d1c..2111d7c 100644
--- a/src/item-grid.c
+++ b/src/item-grid.c
@@ -40,7 +40,7 @@
 #include "hlink.h"
 #include "gui-util.h"
 
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-rect-ellipse.h>
+#include <goffice/goffice.h>
 #include <gtk/gtk.h>
 #include <gsf/gsf-impl-utils.h>
 #include <math.h>
@@ -61,7 +61,7 @@ typedef enum {
 } ItemGridSelectionType;
 
 struct _ItemGrid {
-	FooCanvasItem canvas_item;
+	GocItem canvas_item;
 
 	SheetControlGUI *scg;
 
@@ -78,7 +78,7 @@ struct _ItemGrid {
 
 	/* information for the cursor motion handler */
 	guint cursor_timer;
-	gint last_x, last_y;
+	gint64 last_x, last_y;
 	GnmHLink *cur_link; /* do not derference, just a pointer */
 	GtkWidget *tip;
 	guint tip_timer;
@@ -87,8 +87,8 @@ struct _ItemGrid {
 
 	guint32 last_click_time;
 };
-typedef FooCanvasItemClass ItemGridClass;
-static FooCanvasItemClass *parent_class;
+typedef GocItemClass ItemGridClass;
+static GocItemClass *parent_class;
 
 enum {
 	ITEM_GRID_PROP_0,
@@ -129,16 +129,14 @@ static gint
 cb_cursor_motion (ItemGrid *ig)
 {
 	Sheet const *sheet = scg_sheet (ig->scg);
-	FooCanvas *canvas = ig->canvas_item.canvas;
+	GocCanvas *canvas = ig->canvas_item.canvas;
 	GnmPane *pane = GNM_PANE (canvas);
-	int x, y;
 	GdkCursor *cursor;
 	GnmCellPos pos;
 	GnmHLink *old_link;
 
-	foo_canvas_w2c (canvas, ig->last_x, ig->last_y, &x, &y);
-	pos.col = gnm_pane_find_col (pane, x, NULL);
-	pos.row = gnm_pane_find_row (pane, y, NULL);
+	pos.col = gnm_pane_find_col (pane, ig->last_x, NULL);
+	pos.row = gnm_pane_find_row (pane, ig->last_y, NULL);
 
 	old_link = ig->cur_link;
 	ig->cur_link = sheet_hlink_find (sheet, &pos);
@@ -161,9 +159,8 @@ cb_cursor_motion (ItemGrid *ig)
 }
 
 static void
-item_grid_realize (FooCanvasItem *item)
+item_grid_realize (GocItem *item)
 {
-	GdkWindow  *window;
 	GdkDisplay *display;
 	ItemGrid   *ig;
 
@@ -171,22 +168,6 @@ item_grid_realize (FooCanvasItem *item)
 		(*parent_class->realize) (item);
 
 	ig = ITEM_GRID (item);
-	window = GTK_WIDGET (item->canvas)->window;
-
-	/* Configure the default grid gc */
-	ig->gc.cell = gdk_gc_new (window);
-	gdk_gc_set_fill (ig->gc.cell, GDK_SOLID);
-
-	ig->gc.empty = gdk_gc_new (window);
-
-	ig->gc.fill = gdk_gc_new (window);
-	gdk_gc_set_rgb_fg_color (ig->gc.fill,  &gs_white);
-	gdk_gc_set_rgb_bg_color (ig->gc.fill,  &gs_light_gray);
-
-	ig->gc.bound = gdk_gc_new (window);
-	gdk_gc_set_rgb_fg_color (ig->gc.bound, &gs_dark_gray);
-	gdk_gc_set_line_attributes (ig->gc.bound, 3, GDK_LINE_SOLID,
-				    GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
 
 	display = gtk_widget_get_display (GTK_WIDGET (item->canvas));
 	ig->cursor_link  = gdk_cursor_new_for_display (display, GDK_HAND2);
@@ -197,42 +178,21 @@ item_grid_realize (FooCanvasItem *item)
 }
 
 static void
-item_grid_unrealize (FooCanvasItem *item)
+item_grid_update_bounds (GocItem *item)
 {
-	ItemGrid *ig = ITEM_GRID (item);
-
-	gdk_cursor_unref (ig->cursor_link);
-	gdk_cursor_unref (ig->cursor_cross);
-
-	g_object_unref (G_OBJECT (ig->gc.fill));	ig->gc.fill = NULL;
-	g_object_unref (G_OBJECT (ig->gc.cell));	ig->gc.cell = NULL;
-	g_object_unref (G_OBJECT (ig->gc.empty));	ig->gc.empty = NULL;
-	g_object_unref (G_OBJECT (ig->gc.bound));	ig->gc.bound = NULL;
-
-	if (parent_class->unrealize)
-		(*parent_class->unrealize) (item);
+	item->x0 = 0;
+	item->y0 = 0;
+	item->x1 = G_MAXINT64/2;
+	item->y1 = G_MAXINT64/2;
 }
 
 static void
-item_grid_update (FooCanvasItem *item, double i2w_dx, double i2w_dy, int flags)
-{
-	if (parent_class->update)
-		(*parent_class->update) (item, i2w_dx, i2w_dy, flags);
-
-	item->x1 = 0;
-	item->y1 = 0;
-	item->x2 = INT_MAX/2;
-	item->y2 = INT_MAX/2;
-}
-
-static void
-item_grid_draw_merged_range (GdkDrawable *drawable, ItemGrid *ig,
+item_grid_draw_merged_range (cairo_t *cr, ItemGrid *ig,
 			     int start_x, int start_y,
 			     GnmRange const *view, GnmRange const *range,
 			     gboolean draw_selection)
 {
 	int l, r, t, b, last;
-	GdkGC *gc = ig->gc.empty;
 	SheetView const *sv = scg_view (ig->scg);
 	Sheet const *sheet  = sv->sheet;
 	GnmCell  const *cell   = sheet_cell_get (sheet, range->start.col, range->start.row);
@@ -274,14 +234,14 @@ item_grid_draw_merged_range (GdkDrawable *drawable, ItemGrid *ig,
 	}
 
 	/* Check for background THEN selection */
-	if (gnumeric_background_set_gc (style, gc,
-		ig->canvas_item.canvas, is_selected) ||
-	    is_selected) {
+	if (gnumeric_background_set (style, cr,
+		is_selected) || is_selected) {
 		/* Remember X excludes the far pixels */
 		if (dir > 0)
-			gdk_draw_rectangle (drawable, gc, TRUE, l, t, r-l+1, b-t+1);
+			cairo_rectangle (cr, l, t, r-l+1, b-t+1);
 		else
-			gdk_draw_rectangle (drawable, gc, TRUE, r, t, l-r+1, b-t+1);
+			cairo_rectangle (cr, r, t, l-r+1, b-t+1);
+		cairo_fill (cr);
 	}
 
 	/* Expand the coords to include non-visible areas too.  The clipped
@@ -306,32 +266,30 @@ item_grid_draw_merged_range (GdkDrawable *drawable, ItemGrid *ig,
 			row_calc_spans ((ColRowInfo *)ri, cell->pos.row, sheet);
 
 		if (dir > 0)
-			cell_draw (cell, ig->gc.cell, drawable,
+			cell_draw (cell, cr,
 				l, t, r - l, b - t, -1);
 		else
-			cell_draw (cell, ig->gc.cell, drawable,
+			cell_draw (cell, cr,
 				r, t, l - r, b - t, -1);
 	}
 	if (dir > 0)
-		gnm_style_border_draw_diag (style, drawable, l, t, r, b);
+		gnm_style_border_draw_diag (style, cr, l, t, r, b);
 	else
-		gnm_style_border_draw_diag (style, drawable, r, t, l, b);
+		gnm_style_border_draw_diag (style, cr, r, t, l, b);
 }
 
 static void
-item_grid_draw_background (GdkDrawable *drawable, ItemGrid *ig,
+item_grid_draw_background (cairo_t *cr, ItemGrid *ig,
 			   GnmStyle const *style,
 			   int col, int row, int x, int y, int w, int h,
 			   gboolean draw_selection)
 {
-	GdkGC           *gc = ig->gc.empty;
 	SheetView const *sv = scg_view (ig->scg);
 	gboolean const is_selected = draw_selection &&
 		(sv->edit_pos.col != col || sv->edit_pos.row != row) &&
 		sv_is_pos_selected (sv, col, row);
 	gboolean const has_back =
-		gnumeric_background_set_gc (style, gc,
-					    ig->canvas_item.canvas,
+		gnumeric_background_set (style, cr,
 					    is_selected);
 
 #if DEBUG_SELECTION_PAINT
@@ -339,11 +297,13 @@ item_grid_draw_background (GdkDrawable *drawable, ItemGrid *ig,
 		g_printerr ("x = %d, w = %d\n", x, w+1);
 	}
 #endif
-	if (has_back || is_selected)
+	if (has_back || is_selected) {
 		/* Fill the entire cell (API excludes far pixel) */
-		gdk_draw_rectangle (drawable, gc, TRUE, x, y, w+1, h+1);
+		cairo_rectangle (cr, x, y, w+1, h+1);
+		cairo_fill (cr);
+	}
 
-	gnm_style_border_draw_diag (style, drawable, x, y, x+w, y+h);
+	gnm_style_border_draw_diag (style, cr, x, y, x+w, y+h);
 }
 
 static gint
@@ -353,11 +313,26 @@ merged_col_cmp (GnmRange const *a, GnmRange const *b)
 }
 
 static void
-item_grid_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expose)
+ig_cairo_draw_bound (cairo_t* cr, int x0, int y0, int x1, int y1)
+{
+	cairo_set_line_width (cr, 1.);
+	cairo_set_dash (cr, NULL, 0, 0.);
+	cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+	cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+	cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1.);
+	cairo_move_to (cr, x0 - .5, y0 - .5);
+	cairo_line_to (cr, x1 - .5, y1 - .5);
+	cairo_stroke (cr);
+}
+
+static gboolean
+item_grid_draw_region (GocItem const *item, cairo_t *cr, double x_0, double y_0, double x_1, double y_1)
 {
-	gint width  = expose->area.width;
-	gint height = expose->area.height;
-	FooCanvas *canvas = item->canvas;
+	GocCanvas *canvas = item->canvas;
+	double scale = canvas->pixels_per_unit;
+	gint64 x0 = x_0 * scale, y0 = y_0 * scale, x1 = x_1 * scale, y1 = y_1 * scale;
+	gint width  = x1 - x0;
+	gint height = y1 - y0;
 	GnmPane *pane = GNM_PANE (canvas);
 	Sheet const *sheet = scg_sheet (pane->simple.scg);
 	WBCGtk *wbcg = scg_wbcg (pane->simple.scg);
@@ -373,10 +348,12 @@ item_grid_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expo
 	 * painting the borders of the edges and not the content.
 	 * However, that feels like more hassle that it is worth.  Look into this someday.
 	 */
-	int x, y, col, row, n, start_col, end_col, start_x, offset;
-	int start_row = gnm_pane_find_row (pane, expose->area.y-2, &y);
-	int end_row = gnm_pane_find_row (pane, expose->area.y+height+2, NULL);
-	int const start_y = y;
+	int x;
+	gint64 y, start_x, offset;
+	int col, row, n, start_col, end_col;
+	int start_row = gnm_pane_find_row (pane, y0-2, &y);
+	int end_row = gnm_pane_find_row (pane, y1+2, NULL);
+	gint64 const start_y = y - canvas->scroll_y1 * scale;
 
 	GnmStyleRow sr, next_sr;
 	GnmStyle const **styles;
@@ -394,15 +371,10 @@ item_grid_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expo
 		ig->scg->selected_objects == NULL &&
 		wbcg->new_object == NULL;
 
-	if (dir < 0) {
-		start_col = gnm_pane_find_col (pane, expose->area.x+width+2, &start_x);
-		end_col   = gnm_pane_find_col (pane, expose->area.x-2, NULL);
-	} else {
-		start_col = gnm_pane_find_col (pane, expose->area.x-2, &start_x);
-		end_col   = gnm_pane_find_col (pane, expose->area.x+width+2, NULL);
-	}
+	start_col = gnm_pane_find_col (pane, x0-2, &start_x);
+	end_col   = gnm_pane_find_col (pane, x1+2, NULL);
 
-	g_return_if_fail (start_col <= end_col);
+	g_return_val_if_fail (start_col <= end_col, TRUE);
 
 #if 0
 	g_printerr ("%s:", cell_coord_name (start_col, start_row));
@@ -432,7 +404,7 @@ item_grid_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expo
 	/* if everything is hidden no need to draw */
 	if (end_col < ig->bound.start.col || start_col > ig->bound.end.col ||
 	    end_row < ig->bound.start.row || start_row > ig->bound.end.row)
-		return;
+		return TRUE;
 
 	/* Respan all rows that need it.  */
 	for (row = start_row; row <= end_row; row++) {
@@ -444,8 +416,12 @@ item_grid_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expo
 	sheet_style_update_grid_color (sheet);
 
 	/* Fill entire region with default background (even past far edge) */
-	gdk_draw_rectangle (drawable, ig->gc.fill, TRUE,
-		expose->area.x, expose->area.y, width, height);
+	cairo_save (cr);
+	/* FIXME: we previously used gs_white */
+	cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (RGBA_WHITE));
+	cairo_rectangle (cr, x0, y0, width, height);
+	cairo_fill (cr);
+	cairo_restore (cr);
 
 	/* Get ordered list of merged regions */
 	merged_active = merged_active_seen = merged_used = NULL;
@@ -477,11 +453,12 @@ item_grid_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expo
 		colwidths[col] = ci->visible ? ci->size_pixels : -1;
 	}
 
-	x = start_x; /* make gcc happy in case there are no visible rows */
+	goc_canvas_c2w (canvas, start_x / scale, 0, &x, NULL);
+	start_x = x;
 	for (y = start_y; row <= end_row; row = sr.row = next_sr.row, ri = next_ri) {
 		/* Restore the set of ranges seen, but still active.
 		 * Reinverting list to maintain the original order */
-		g_return_if_fail (merged_active == NULL);
+		g_return_val_if_fail (merged_active == NULL, TRUE);
 
 #if DEBUG_SELECTION_PAINT
 		g_printerr ("row = %d (startcol = %d)\n", row, start_col);
@@ -534,7 +511,7 @@ item_grid_draw (FooCanvasItem *item, GdkDrawable *drawable, GdkEventExpose *expo
 					MERGE_DEBUG (r, " : unused -> active\n");
 
 					if (ci->visible)
-						item_grid_draw_merged_range (drawable, ig,
+						item_grid_draw_merged_range (cr, ig,
 							start_x, y, &view, r, draw_selection);
 				}
 			} else {
@@ -628,7 +605,7 @@ plain_draw : /* a quick hack to deal with 142267 */
 			if (dir < 0)
 				x -= ci->size_pixels;
 			style = sr.styles [col];
-			item_grid_draw_background (drawable, ig,
+			item_grid_draw_background (cr, ig,
 				style, col, row, x, y,
 				ci->size_pixels, ri->size_pixels,
 				draw_selection);
@@ -648,7 +625,7 @@ plain_draw : /* a quick hack to deal with 142267 */
 				 */
 				GnmCell const *cell = sheet_cell_get (sheet, col, row);
 				if (!gnm_cell_is_empty (cell) && cell != edit_cell)
-					cell_draw (cell, ig->gc.cell, drawable,
+					cell_draw (cell, cr,
 						   x, y, ci->size_pixels,
 						   ri->size_pixels, -1);
 
@@ -696,7 +673,7 @@ plain_draw : /* a quick hack to deal with 142267 */
 						real_x -= offset;
 				}
 
-				cell_draw (cell, ig->gc.cell, drawable,
+				cell_draw (cell, cr,
 					   real_x, y, tmp_width,
 					   ri->size_pixels, center_offset);
 			} else if (col != span->left)
@@ -706,7 +683,7 @@ plain_draw : /* a quick hack to deal with 142267 */
 				x += ci->size_pixels;
 		}
 		gnm_style_borders_row_draw (prev_vert, &sr,
-					drawable, start_x, y, y+ri->size_pixels,
+					cr, start_x, y, y+ri->size_pixels,
 					colwidths, TRUE, dir);
 
 		/* In case there were hidden merges that trailed off the end */
@@ -737,24 +714,28 @@ plain_draw : /* a quick hack to deal with 142267 */
 
 	if (row >= ig->bound.end.row) {
 		gnm_style_borders_row_draw (prev_vert, &sr,
-			drawable, start_x, y, y, colwidths, FALSE, dir);
+			cr, start_x, y, y, colwidths, FALSE, dir);
 		if (pane->index >= 2)
-			gdk_draw_line (drawable, ig->gc.bound, start_x, y, x, y);
+			ig_cairo_draw_bound (cr, start_x, y, x, y);
 	}
 	if (col >= ig->bound.end.col &&
 	    /* TODO : Add pane flags to avoid hard coding pane numbers */
-	    (pane->index == 1 || pane->index == 2))
-		gdk_draw_line (drawable, ig->gc.bound, x, start_y, x, y);
+	    (pane->index == 1 || pane->index == 2)) {
+		if (canvas->direction == GOC_DIRECTION_RTL)
+			x += 1; /* fix a border effect */
+		ig_cairo_draw_bound (cr, x, start_y, x, y);
+	    }
 
 	g_slist_free (merged_used);	   /* merges with bottom in view */
 	g_slist_free (merged_active_seen); /* merges with bottom the view */
 	g_slist_free (merged_unused);	   /* merges in hidden rows */
-	g_return_if_fail (merged_active == NULL);
+	g_return_val_if_fail (merged_active == NULL, TRUE);
+	return TRUE;
 }
 
 static double
-item_grid_point (FooCanvasItem *item, double x, double y, int cx, int cy,
-		 FooCanvasItem **actual_item)
+item_grid_distance (GocItem *item, double x, double y,
+		 GocItem **actual_item)
 {
 	*actual_item = item;
 	return 0.0;
@@ -763,9 +744,9 @@ item_grid_point (FooCanvasItem *item, double x, double y, int cx, int cy,
 /***********************************************************************/
 
 static gboolean
-ig_obj_create_begin (ItemGrid *ig, GdkEventButton *event)
+ig_obj_create_begin (ItemGrid *ig, int button, gint64 x, gint64 y)
 {
-	GnmPane *pane = GNM_PANE (FOO_CANVAS_ITEM (ig)->canvas);
+	GnmPane *pane = GNM_PANE (GOC_ITEM (ig)->canvas);
 	SheetObject *so = ig->scg->wbcg->new_object;
 	SheetObjectAnchor anchor;
 	double coords[4];
@@ -773,14 +754,14 @@ ig_obj_create_begin (ItemGrid *ig, GdkEventButton *event)
 	g_return_val_if_fail (ig->scg->selected_objects == NULL, TRUE);
 	g_return_val_if_fail (so != NULL, TRUE);
 
-	coords[0] = coords[2] = event->x;
-	coords[1] = coords[3] = event->y;
+	coords[0] = coords[2] = x;
+	coords[1] = coords[3] = y;
 	sheet_object_anchor_init (&anchor, NULL, NULL, GOD_ANCHOR_DIR_DOWN_RIGHT);
 	scg_object_coords_to_anchor (ig->scg, coords, &anchor);
 	sheet_object_set_anchor (so, &anchor);
 	sheet_object_set_sheet (so, scg_sheet (ig->scg));
 	scg_object_select (ig->scg, so);
-	gnm_pane_object_start_resize (pane, event, so, 7, TRUE);
+	gnm_pane_object_start_resize (pane, button, x, y, so, 7, TRUE);
 
 	return TRUE;
 }
@@ -788,10 +769,10 @@ ig_obj_create_begin (ItemGrid *ig, GdkEventButton *event)
 /***************************************************************************/
 
 static int
-item_grid_button_press (ItemGrid *ig, GdkEventButton *event)
+item_grid_button_pressed (GocItem *item, int button, double x_, double y_)
 {
-	FooCanvasItem *item = FOO_CANVAS_ITEM (ig);
-	FooCanvas    *canvas = item->canvas;
+	ItemGrid *ig = ITEM_GRID (item);
+	GocCanvas    *canvas = item->canvas;
 	GnmPane *pane = GNM_PANE (canvas);
 	SheetControlGUI *scg = ig->scg;
 	WBCGtk *wbcg = scg_wbcg (scg);
@@ -799,13 +780,13 @@ item_grid_button_press (ItemGrid *ig, GdkEventButton *event)
 	SheetView	*sv = sc_view (sc);
 	Sheet		*sheet = sv_sheet (sv);
 	GnmCellPos	pos;
-	int x, y;
 	gboolean edit_showed_dialog;
 	gboolean already_selected;
+	GdkEventButton *event = (GdkEventButton *) goc_canvas_get_cur_event (item->canvas);
+	gint64 x = x_ * canvas->pixels_per_unit, y = y_ * canvas->pixels_per_unit;
 
 	gnm_pane_slide_stop (pane);
 
-	foo_canvas_w2c (canvas, event->x, event->y, &x, &y);
 	pos.col = gnm_pane_find_col (pane, x, NULL);
 	pos.row = gnm_pane_find_row (pane, y, NULL);
 
@@ -817,7 +798,7 @@ item_grid_button_press (ItemGrid *ig, GdkEventButton *event)
 
 	/* A new object is ready to be realized and inserted */
 	if (wbcg->new_object != NULL)
-		return ig_obj_create_begin (ig, event);
+		return ig_obj_create_begin (ig, button, x, y);
 
 	/* If we are not configuring an object then clicking on the sheet
 	 * ends the edit.  */
@@ -829,7 +810,7 @@ item_grid_button_press (ItemGrid *ig, GdkEventButton *event)
 	/* If we were already selecting a range of cells for a formula,
 	 * reset the location to a new place, or extend the selection.
 	 */
-	if (event->button == 1 && scg->rangesel.active) {
+	if (button == 1 && scg->rangesel.active) {
 		ig->selecting = ITEM_GRID_SELECTING_FORMULA_RANGE;
 		if (event->state & GDK_SHIFT_MASK)
 			scg_rangesel_extend_to (scg, pos.col, pos.row);
@@ -845,7 +826,7 @@ item_grid_button_press (ItemGrid *ig, GdkEventButton *event)
 	/* If the user is editing a formula (wbcg_rangesel_possible) then we
 	 * enable the dynamic cell selection mode.
 	 */
-	if (event->button == 1 && wbcg_rangesel_possible (wbcg)) {
+	if (button == 1 && wbcg_rangesel_possible (wbcg)) {
 		scg_rangesel_start (scg, pos.col, pos.row, pos.col, pos.row);
 		ig->selecting = ITEM_GRID_SELECTING_FORMULA_RANGE;
 		gnm_pane_slide_init (pane);
@@ -864,13 +845,13 @@ item_grid_button_press (ItemGrid *ig, GdkEventButton *event)
 	if (!wbcg_edit_finish (wbcg, WBC_EDIT_ACCEPT, &edit_showed_dialog))
 		return TRUE;
 
-	if (event->button == 1 && !sheet_selection_is_allowed (sheet, &pos))
+	if (button == 1 && !sheet_selection_is_allowed (sheet, &pos))
 		return TRUE;
 
 	/* button 1 will always change the selection,  the other buttons will
 	 * only effect things if the target is not already selected.  */
 	already_selected = sv_is_pos_selected (sv, pos.col, pos.row);
-	if (event->button == 1 || !already_selected) {
+	if (button == 1 || !already_selected) {
 		if (!(event->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)))
 			sv_selection_reset (sv);
 
@@ -886,7 +867,7 @@ item_grid_button_press (ItemGrid *ig, GdkEventButton *event)
 	if (edit_showed_dialog)
 		return TRUE;  /* we already ignored the button release */
 
-	switch (event->button) {
+	switch (button) {
 	case 1: {
 		guint32 double_click_time;
 
@@ -948,16 +929,17 @@ static gint
 cb_cursor_come_to_rest (ItemGrid *ig)
 {
 	Sheet const *sheet = scg_sheet (ig->scg);
-	FooCanvas *canvas = ig->canvas_item.canvas;
+	GocCanvas *canvas = ig->canvas_item.canvas;
 	GnmPane *pane = GNM_PANE (canvas);
 	GnmHLink *link;
-	int x, y;
+	gint64 x, y;
 	GnmCellPos pos;
 	char const *tiptext;
 
 	/* Be anal and look it up in case something has destroyed the link
 	 * since the last motion */
-	foo_canvas_w2c (canvas, ig->last_x, ig->last_y, &x, &y);
+	x = ig->last_x;
+	y = ig->last_y;
 	pos.col = gnm_pane_find_col (pane, x, NULL);
 	pos.row = gnm_pane_find_row (pane, y, NULL);
 
@@ -981,124 +963,126 @@ cb_cursor_come_to_rest (ItemGrid *ig)
 	return FALSE;
 }
 
-static gint
-item_grid_event (FooCanvasItem *item, GdkEvent *event)
+static gboolean
+item_grid_motion (GocItem *item, double x_, double y_)
 {
-	FooCanvas *canvas = item->canvas;
+	ItemGrid *ig = ITEM_GRID (item);
+	GocCanvas *canvas = item->canvas;
 	GnmPane   *pane = GNM_PANE (canvas);
-	ItemGrid  *ig = ITEM_GRID (item);
-	SheetControlGUI *scg = ig->scg;
-	Sheet *sheet = scg_sheet (scg);
-
-	switch (event->type){
-	case GDK_ENTER_NOTIFY:
-		scg_set_display_cursor (scg);
-		return TRUE;
-	case GDK_LEAVE_NOTIFY:
-		ig_clear_hlink_tip (ig);
-		if (ig->cursor_timer != 0) {
-			g_source_remove (ig->cursor_timer);
-			ig->cursor_timer = 0;
-		}
+	GnmPaneSlideHandler slide_handler = NULL;
+	gint64 x = x_ * canvas->pixels_per_unit, y = y_ * canvas->pixels_per_unit;
+	switch (ig->selecting) {
+	case ITEM_GRID_NO_SELECTION:
+		if (ig->cursor_timer == 0)
+			ig->cursor_timer = g_timeout_add (100,
+				(GSourceFunc)cb_cursor_motion, ig);
+		if (ig->tip_timer != 0)
+			g_source_remove (ig->tip_timer);
+		ig->tip_timer = g_timeout_add (500,
+				(GSourceFunc)cb_cursor_come_to_rest, ig);
+		ig->last_x = x;
+		ig->last_y = y;
 		return TRUE;
+	case ITEM_GRID_SELECTING_CELL_RANGE :
+		slide_handler = &cb_extend_cell_range;
+		break;
+	case ITEM_GRID_SELECTING_FORMULA_RANGE :
+		slide_handler = &cb_extend_expr_range;
+		break;
+	default:
+		g_assert_not_reached ();
+	}
 
-	case GDK_BUTTON_RELEASE: {
-		ItemGridSelectionType selecting = ig->selecting;
+		gnm_pane_handle_motion (pane, canvas, x, y,
+		GNM_PANE_SLIDE_X | GNM_PANE_SLIDE_Y |
+		GNM_PANE_SLIDE_AT_COLROW_BOUND,
+		slide_handler, NULL);
+	return TRUE;
+}
 
-		if (event->button.button != 1)
-			return FALSE;
+static gboolean
+item_grid_button_released (GocItem *item, int button, G_GNUC_UNUSED double x_, G_GNUC_UNUSED double y_)
+{
+	ItemGrid *ig = ITEM_GRID (item);
+	GnmPane  *pane = GNM_PANE (item->canvas);
+	SheetControlGUI *scg = ig->scg;
+	Sheet *sheet = scg_sheet (scg);
+	ItemGridSelectionType selecting = ig->selecting;
+	GdkEventButton *event = (GdkEventButton *) goc_canvas_get_cur_event (item->canvas);
 
-		gnm_pane_slide_stop (pane);
+	if (button != 1)
+		return FALSE;
 
-		switch (selecting) {
-		case ITEM_GRID_NO_SELECTION:
-			return TRUE;
+	gnm_pane_slide_stop (pane);
+
+	switch (selecting) {
+	case ITEM_GRID_NO_SELECTION:
+		return TRUE;
 
-		case ITEM_GRID_SELECTING_FORMULA_RANGE :
+	case ITEM_GRID_SELECTING_FORMULA_RANGE :
 /*  Removal of this code (2 lines)                                                */
 /*  should fix http://bugzilla.gnome.org/show_bug.cgi?id=63485                    */
 /*			sheet_make_cell_visible (sheet,                           */
 /*				sheet->edit_pos.col, sheet->edit_pos.row, FALSE); */
-			/* Fall through */
-		case ITEM_GRID_SELECTING_CELL_RANGE :
-			wb_view_selection_desc (
-				wb_control_view (scg_wbc (scg)), TRUE, NULL);
-			break;
-
-		default:
-			g_assert_not_reached ();
-		}
+		/* Fall through */
+	case ITEM_GRID_SELECTING_CELL_RANGE :
+		wb_view_selection_desc (
+			wb_control_view (scg_wbc (scg)), TRUE, NULL);
+		break;
 
-		ig->selecting = ITEM_GRID_NO_SELECTION;
-		gnm_simple_canvas_ungrab (item, event->button.time);
-
-		if (selecting == ITEM_GRID_SELECTING_FORMULA_RANGE)
-			gnm_expr_entry_signal_update (
-				wbcg_get_entry_logical (scg_wbcg (scg)), TRUE);
-
-		if (selecting == ITEM_GRID_SELECTING_CELL_RANGE) {
-			GnmCellPos const *pos = sv_is_singleton_selected (scg_view (scg));
-			if (pos != NULL) {
-				GnmHLink *link;
-				/* check for hyper links */
-				link = sheet_hlink_find (sheet, pos);
-				if (link != NULL)
-					gnm_hlink_activate (link, scg_wbc (scg));
-			}
-		}
-		return TRUE;
+	default:
+		g_assert_not_reached ();
 	}
 
-	case GDK_MOTION_NOTIFY: {
-		GnmPaneSlideHandler slide_handler = NULL;
-		switch (ig->selecting) {
-		case ITEM_GRID_NO_SELECTION:
-			if (ig->cursor_timer == 0)
-				ig->cursor_timer = g_timeout_add (100,
-					(GSourceFunc)cb_cursor_motion, ig);
-			if (ig->tip_timer != 0)
-				g_source_remove (ig->tip_timer);
-			ig->tip_timer = g_timeout_add (500,
-					(GSourceFunc)cb_cursor_come_to_rest, ig);
-			ig->last_x = event->motion.x;
-			ig->last_y = event->motion.y;
-			return TRUE;
-		case ITEM_GRID_SELECTING_CELL_RANGE :
-			slide_handler = &cb_extend_cell_range;
-			break;
-		case ITEM_GRID_SELECTING_FORMULA_RANGE :
-			slide_handler = &cb_extend_expr_range;
-			break;
-		default:
-			g_assert_not_reached ();
+	ig->selecting = ITEM_GRID_NO_SELECTION;
+	gnm_simple_canvas_ungrab (item, event->time);
+
+	if (selecting == ITEM_GRID_SELECTING_FORMULA_RANGE)
+		gnm_expr_entry_signal_update (
+			wbcg_get_entry_logical (scg_wbcg (scg)), TRUE);
+
+	if (selecting == ITEM_GRID_SELECTING_CELL_RANGE) {
+		GnmCellPos const *pos = sv_is_singleton_selected (scg_view (scg));
+		if (pos != NULL) {
+			GnmHLink *link;
+			/* check for hyper links */
+			link = sheet_hlink_find (sheet, pos);
+			if (link != NULL)
+				gnm_hlink_activate (link, scg_wbc (scg));
 		}
-
-		gnm_pane_handle_motion (pane, canvas, &event->motion,
-			GNM_PANE_SLIDE_X | GNM_PANE_SLIDE_Y |
-			GNM_PANE_SLIDE_AT_COLROW_BOUND,
-			slide_handler, NULL);
-		return TRUE;
 	}
+	return TRUE;
+}
 
-	case GDK_BUTTON_PRESS:
-		return item_grid_button_press (ig, &event->button);
+static gboolean
+item_grid_enter_notify (GocItem *item, G_GNUC_UNUSED double x, G_GNUC_UNUSED double y)
+{
+	ItemGrid  *ig = ITEM_GRID (item);
+	scg_set_display_cursor (ig->scg);
+	return TRUE;
+}
 
-	default:
-		return FALSE;
+static gboolean
+item_grid_leave_notify (GocItem *item, G_GNUC_UNUSED double x, G_GNUC_UNUSED double y)
+{
+	ItemGrid  *ig = ITEM_GRID (item);
+	ig_clear_hlink_tip (ig);
+	if (ig->cursor_timer != 0) {
+		g_source_remove (ig->cursor_timer);
+		ig->cursor_timer = 0;
 	}
-
-	return FALSE;
+	return TRUE;
 }
 
 static void
 item_grid_init (ItemGrid *ig)
 {
-	FooCanvasItem *item = FOO_CANVAS_ITEM (ig);
+	GocItem *item = GOC_ITEM (ig);
 
+	item->x0 = 0;
+	item->y0 = 0;
 	item->x1 = 0;
 	item->y1 = 0;
-	item->x2 = 0;
-	item->y2 = 0;
 
 	ig->selecting = ITEM_GRID_NO_SELECTION;
 	ig->gc.fill = ig->gc.cell = ig->gc.empty = ig->gc.bound = NULL;
@@ -1135,7 +1119,7 @@ item_grid_set_property (GObject *obj, guint param_id,
 static void
 item_grid_class_init (GObjectClass *gobject_klass)
 {
-	FooCanvasItemClass *item_klass = (FooCanvasItemClass *) gobject_klass;
+	GocItemClass *item_klass = (GocItemClass *) gobject_klass;
 
 	parent_class = g_type_class_peek_parent (gobject_klass);
 
@@ -1151,14 +1135,17 @@ item_grid_class_init (GObjectClass *gobject_klass)
 			"The display bounds",
 			GSF_PARAM_STATIC | G_PARAM_WRITABLE));
 
-	item_klass->update      = item_grid_update;
 	item_klass->realize     = item_grid_realize;
-	item_klass->unrealize   = item_grid_unrealize;
-	item_klass->draw        = item_grid_draw;
-	item_klass->point       = item_grid_point;
-	item_klass->event       = item_grid_event;
+	item_klass->draw_region     = item_grid_draw_region;
+	item_klass->update_bounds   = item_grid_update_bounds;
+	item_klass->button_pressed  = item_grid_button_pressed;
+	item_klass->button_released = item_grid_button_released;
+	item_klass->motion          = item_grid_motion;
+	item_klass->enter_notify    = item_grid_enter_notify;
+	item_klass->leave_notify    = item_grid_leave_notify;
+	item_klass->distance        = item_grid_distance;
 }
 
 GSF_CLASS (ItemGrid, item_grid,
 	   item_grid_class_init, item_grid_init,
-	   FOO_TYPE_CANVAS_ITEM)
+	   GOC_TYPE_ITEM)
diff --git a/src/item-grid.h b/src/item-grid.h
index 1e86653..043839f 100644
--- a/src/item-grid.h
+++ b/src/item-grid.h
@@ -4,6 +4,7 @@
 
 #include "gui-gnumeric.h"
 #include <glib-object.h>
+#include <goffice/canvas/goffice-canvas.h>
 
 G_BEGIN_DECLS
 
diff --git a/src/pattern.c b/src/pattern.c
index cc1005a..c558bb9 100644
--- a/src/pattern.c
+++ b/src/pattern.c
@@ -13,106 +13,44 @@
 
 #include "style-color.h"
 
-typedef struct {
-	int const x, y;
-	char const pattern[8];
-} gnumeric_sheet_pattern_t;
-
-static gnumeric_sheet_pattern_t const
-gnumeric_sheet_patterns[] = {
-/* 0 */	{ 8, 8, /* DUMMY PLACEHOLDER */
-	  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
-/* 1 */	{ 8, 8, /* Solid */
-	  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
-/* 2 */	{ 8, 8, /* 75% */
-	  { 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee } },
-/* 3 */	{ 8, 8, /* 50% */
-	  { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 } },
-/* 4 */	{ 8, 8, /* 25% */
-	  { 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88 } },
-/* 5 */	{ 8, 8, /* 12.5% */
-	  { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 } },
-/* 6 */	{ 8, 8, /* 6.25% */
-	  { 0x20, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00 } },
-/* 7 */	{ 8, 8, /* Horizontal Stripe */
-	  { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff } },
-/* 8 */	{ 8, 8, /* Vertical Stripe */
-	  { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33 } },
-/* 9 */	{ 8, 8, /* Reverse Diagonal Stripe */
-	  { 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 } },
-/* 10*/	{ 8, 8, /* Diagonal Stripe */
-	  { 0x33, 0x66, 0xcc, 0x99, 0x33, 0x66, 0xcc, 0x99 } },
-/* 11*/	{ 8, 8, /* Diagonal Crosshatch */
-	  { 0x99, 0x66, 0x66, 0x99, 0x99, 0x66, 0x66, 0x99 } },
-/* 12*/	{ 8, 8, /* Thick Diagonal Crosshatch */
-	  { 0xff, 0x66, 0xff, 0x99, 0xff, 0x66, 0xff, 0x99 } },
-/* 13*/	{ 8, 8, /* Thin Horizontal Stripe */
-	  { 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00 } },
-/* 14*/	{ 8, 8, /* Thin Vertical Stripe */
-	  { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 } },
-/* 15*/	{ 8, 8, /* Thin Reverse Diagonal Stripe */
-	  { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 } },
-/* 16*/	{ 8, 8, /* Thin Diagonal Stripe */
-	  { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 } },
-/* 17*/	{ 8, 8, /* Thin Crosshatch */
-	  { 0x22, 0x22, 0xff, 0x22, 0x22, 0x22, 0xff, 0x22 } },
-/* 18*/	{ 8, 8, /* Thin Diagonal Crosshatch */
-	  { 0x88, 0x55, 0x22, 0x55, 0x88, 0x55, 0x22, 0x55 } },
-/* 19*/	{ 8, 8, /* Applix small circle */
-	  { 0x99, 0x55, 0x33, 0xff, 0x99, 0x55, 0x33, 0xff } },
-/* 20*/	{ 8, 8, /* Applix semicircle */
-	  { 0x10, 0x10, 0x28, 0xc7, 0x01, 0x01, 0x82, 0x7c } },
-/* 21*/	{ 8, 8, /* Applix small thatch */
-	  { 0x22, 0x74, 0xf8, 0x71, 0x22, 0x17, 0x8f, 0x47 } },
-/* 22*/	{ 8, 8, /* Applix round thatch */
-	  { 0xc1, 0x80, 0x1c, 0x3e, 0x3e, 0x3e, 0x1c, 0x80 } },
-/* 23*/	{ 8, 8, /* Applix Brick */
-	  { 0x20, 0x20, 0x20, 0xff, 0x02, 0x02, 0x02, 0xff } },
-/* 24*/	{ 8, 8, /* 100% */
-	  { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } },
-/* 25*/	{ 6, 6, /* 87.5% */
-	  { 0xfe, 0xef, 0xfb, 0xdf, 0xfd, 0xf7, 0x00, 0x00 } }
+#include <goffice/utils/go-pattern.h>
+
+GOPatternType patterns[] = {
+	GO_PATTERN_SOLID,
+	GO_PATTERN_GREY75,
+	GO_PATTERN_GREY50,
+	GO_PATTERN_GREY25,
+	GO_PATTERN_GREY125,
+	GO_PATTERN_GREY625,
+	GO_PATTERN_HORIZ,
+	GO_PATTERN_VERT,
+	GO_PATTERN_DIAG,
+	GO_PATTERN_REV_DIAG,
+	GO_PATTERN_DIAG_CROSS,
+	GO_PATTERN_THICK_DIAG_CROSS,
+	GO_PATTERN_THIN_HORIZ,
+	GO_PATTERN_THIN_VERT,
+	GO_PATTERN_THIN_REV_DIAG,
+	GO_PATTERN_THIN_DIAG,
+	GO_PATTERN_THIN_HORIZ_CROSS,
+	GO_PATTERN_THIN_DIAG_CROSS,
+	GO_PATTERN_SMALL_CIRCLES,
+	GO_PATTERN_SEMI_CIRCLES,
+	GO_PATTERN_THATCH,
+	GO_PATTERN_LARGE_CIRCLES,
+	GO_PATTERN_BRICKS,
+	GO_PATTERN_FOREGROUND_SOLID
 };
 
-static GdkPixmap *
-gnumeric_pattern_get_stipple (GdkDrawable *drawable, gint index)
-{
-	static GdkPixmap *patterns[GNUMERIC_SHEET_PATTERNS + 1];
-	static GdkDrawable *last_drawable[GNUMERIC_SHEET_PATTERNS + 1];
-
-	g_return_val_if_fail (index >= 0, NULL);
-	g_return_val_if_fail (index <= GNUMERIC_SHEET_PATTERNS, NULL);
-	g_return_val_if_fail (drawable != NULL, NULL);
-
-	if (index == 0)
-		return NULL;
-
-	if (drawable != last_drawable[index] && patterns[index]) {
-		g_object_unref (patterns[index]);
-		patterns[index] = NULL;
-	}
-
-	if (patterns[index] == NULL) {
-		gnumeric_sheet_pattern_t const * pat = gnumeric_sheet_patterns + index;
-		patterns[index] = gdk_bitmap_create_from_data (
-			drawable, pat->pattern, pat->x, pat->y);
-		last_drawable[index] = drawable;
-	}
-
-	return patterns[index];
-}
-
 /*
- * gnumeric_background_set_gc : Set up a GdkGC to paint the background
+ * gnumeric_background_set : Set up a cairo context to paint the background
  *                              of a cell.
  * return : TRUE if there is a background to paint.
  */
 gboolean
-gnumeric_background_set_gc (GnmStyle const *mstyle, GdkGC *gc,
-			    FooCanvas *canvas,
+gnumeric_background_set (GnmStyle const *mstyle, cairo_t *cr,
 			    gboolean const is_selected)
 {
-	GdkColormap *cmap = gdk_gc_get_colormap (gc);
 	int pattern;
 
 	/*
@@ -121,47 +59,17 @@ gnumeric_background_set_gc (GnmStyle const *mstyle, GdkGC *gc,
 	 */
 	pattern = gnm_style_get_pattern (mstyle);
 	if (pattern > 0) {
-		const GdkColor *back;
-		GnmColor const *back_col = gnm_style_get_back_color (mstyle);
-		g_return_val_if_fail (back_col != NULL, FALSE);
-
-		back = is_selected ? &back_col->gdk_selected_color : &back_col->gdk_color;
-
-		if (pattern > 1) {
-			GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (canvas));
-			GdkDrawable *drawable = gdk_screen_get_root_window (screen);
-			GdkGCValues values;
-			GnmColor const *pat_col = gnm_style_get_pattern_color (mstyle);
-			g_return_val_if_fail (pat_col != NULL, FALSE);
-
-			values.fill = GDK_OPAQUE_STIPPLED;
-			values.foreground = pat_col->gdk_color;
-			gdk_rgb_find_color (cmap, &values.foreground);
-			values.background = *back;
-			gdk_rgb_find_color (cmap, &values.background);
-			values.stipple =
-				gnumeric_pattern_get_stipple (drawable, pattern);
-			gdk_gc_set_values (gc, &values,
-					   GDK_GC_FILL | GDK_GC_FOREGROUND |
-					   GDK_GC_BACKGROUND | GDK_GC_STIPPLE);
-			foo_canvas_set_stipple_origin (canvas, gc);
-		} else {
-			GdkGCValues values;
-
-			values.fill = GDK_SOLID;
-			values.foreground = *back;
-			gdk_rgb_find_color (cmap, &values.foreground);
-			gdk_gc_set_values (gc, &values, GDK_GC_FILL | GDK_GC_FOREGROUND);
-		}
+		GOPattern gopat;
+		cairo_pattern_t *crpat;
+		gopat.pattern = patterns[pattern - 1];
+		gopat.fore = gnm_style_get_pattern_color (mstyle)->go_color;
+		gopat.back = gnm_style_get_back_color (mstyle)->go_color;
+		crpat = go_pattern_create_cairo_pattern (&gopat, cr);
+		cairo_set_source (cr, crpat);
+		cairo_pattern_destroy (crpat);
 		return TRUE;
-	} else if (is_selected) {
-		GdkGCValues values;
-
-		values.foreground = gs_lavender;
-		gdk_rgb_find_color (cmap, &values.foreground);
-		values.fill = GDK_SOLID;
-		gdk_gc_set_values (gc, &values, GDK_GC_FILL | GDK_GC_FOREGROUND);
-	}
+	} else if (is_selected)
+		cairo_set_source_rgb (cr, .901960784, .901960784, .980392157);
 	return FALSE;
 }
 
diff --git a/src/pattern.h b/src/pattern.h
index b82ce8a..ced929a 100644
--- a/src/pattern.h
+++ b/src/pattern.h
@@ -3,14 +3,13 @@
 # define _GNM_PATTERN_H_
 
 #include "style.h"
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
 
 G_BEGIN_DECLS
 
 #define GNUMERIC_SHEET_PATTERNS 25
 
-gboolean    gnumeric_background_set_gc	(GnmStyle const *style,
-					 GdkGC *gc, FooCanvas *canvas,
+gboolean    gnumeric_background_set	(GnmStyle const *style,
+					 cairo_t *cr,
 					 gboolean const is_selected);
 gboolean    gnumeric_background_set_gtk	(GnmStyle const *style,
 					 cairo_t *context);
diff --git a/src/preview-grid-impl.h b/src/preview-grid-impl.h
index cddc0fd..4f58c7d 100644
--- a/src/preview-grid-impl.h
+++ b/src/preview-grid-impl.h
@@ -3,20 +3,22 @@
 # define _GNM_PREVIEW_GRID_IMPL_H_
 
 #include "preview-grid.h"
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
+#include <goffice/goffice.h>
 
 G_BEGIN_DECLS
 
 struct _PreviewGrid {
-	FooCanvasGroup base;
+	GocGroup base;
 
 	Sheet *sheet;
 
+#if 0
 	struct { /* Gc's */
 		GdkGC *fill;	/* Default background fill gc */
 		GdkGC *cell;	/* Color used for the cell */
 		GdkGC *empty;	/* GC used for drawing empty cells */
 	} gc;
+#endif
 
 	struct {
 		int     col_width;
@@ -29,7 +31,7 @@ struct _PreviewGrid {
 };
 
 typedef struct {
-	FooCanvasGroupClass parent_class;
+	GocGroupClass parent_class;
 
 	/* Virtuals */
 	GnmStyle * (* get_cell_style) (PreviewGrid *pg, int col, int row);
diff --git a/src/preview-grid.c b/src/preview-grid.c
index e47a077..ac8b616 100644
--- a/src/preview-grid.c
+++ b/src/preview-grid.c
@@ -41,7 +41,7 @@
 
 #include <gsf/gsf-impl-utils.h>
 
-static FooCanvasItemClass *parent_klass;
+static GocItemClass *parent_klass;
 enum {
 	PREVIEW_GRID_PROP_0,
 	PREVIEW_GRID_PROP_RENDER_GRIDLINES,
@@ -163,77 +163,29 @@ pg_get_col_offset (PreviewGrid *pg, int const x, int *col_origin)
 }
 
 static void
-preview_grid_realize (FooCanvasItem *item)
+preview_grid_update_bounds (GocItem *item)
 {
-	GtkStyle    *style;
-	GdkWindow   *window = GTK_WIDGET (item->canvas)->window;
-	PreviewGrid *pg = PREVIEW_GRID (item);
-
-
-	if (parent_klass->realize)
-		(*parent_klass->realize) (item);
-
-	/* Set the default background color of the canvas itself to white.
-	 * This makes the redraws when the canvas scrolls flicker less.
-	 */
-	style = gtk_style_copy (GTK_WIDGET (item->canvas)->style);
-	style->bg[GTK_STATE_NORMAL] = style->white;
-	gtk_widget_set_style (GTK_WIDGET (item->canvas), style);
-	g_object_unref (style);
-
-	/* Configure the default grid gc */
-	pg->gc.fill  = gdk_gc_new (window);
-	pg->gc.cell  = gdk_gc_new (window);
-	pg->gc.empty = gdk_gc_new (window);
-
-	gdk_gc_set_rgb_fg_color (pg->gc.fill, &gs_white);
-	gdk_gc_set_rgb_bg_color (pg->gc.fill, &gs_light_gray);
-	gdk_gc_set_fill (pg->gc.cell, GDK_SOLID);
-}
-
-static void
-preview_grid_unrealize (FooCanvasItem *item)
-{
-	PreviewGrid *pg = PREVIEW_GRID (item);
-	g_object_unref (pg->gc.fill);  pg->gc.fill  = NULL;
-	g_object_unref (pg->gc.cell);  pg->gc.cell  = NULL;
-	g_object_unref (pg->gc.empty); pg->gc.empty = NULL;
-	if (parent_klass->unrealize)
-		(*parent_klass->unrealize) (item);
+	item->x0 = -2;
+	item->y0 = -2;
+	item->x1 = INT_MAX/2;	/* FIXME add some num cols/rows abilities */
+	item->y1 = INT_MAX/2;	/* FIXME and some flags to decide how to adapt */
 }
 
 static void
-preview_grid_update (FooCanvasItem *item,  double i2w_dx, double i2w_dy, int flags)
-{
-	FooCanvasGroup *group = FOO_CANVAS_GROUP (item);
-	if (parent_klass->update)
-		(*parent_klass->update) (item, i2w_dx, i2w_dy, flags);
-
-	item->x1 = group->xpos - 2;
-	item->y1 = group->ypos - 2;
-	item->x2 = INT_MAX/2;	/* FIXME add some num cols/rows abilities */
-	item->y2 = INT_MAX/2;	/* FIXME and some flags to decide how to adapt */
-
-	foo_canvas_item_request_redraw (item);
-}
-
-static void
-preview_grid_draw_background (GdkDrawable *drawable, PreviewGrid const *pg, GnmStyle const *mstyle,
+preview_grid_draw_background (cairo_t *cr, PreviewGrid const *pg, GnmStyle const *mstyle,
 			      int col, int row, int x, int y, int w, int h)
 {
-	GdkGC *gc = pg->gc.empty;
-
-	if (gnumeric_background_set_gc (mstyle, gc, pg->base.item.canvas, FALSE))
-		/* Fill the entire cell (API excludes far pixel) */
-		gdk_draw_rectangle (drawable, gc, TRUE, x, y, w+1, h+1);
-
-	gnm_style_border_draw_diag (mstyle, drawable, x, y, x+w, y+h);
+	if (gnumeric_background_set (mstyle, cr, FALSE)) {
+		cairo_rectangle (cr, x, y, w+1, h+1);
+		cairo_fill (cr);
+	}
+	gnm_style_border_draw_diag (mstyle, cr, x, y, x+w, y+h);
 }
 
 #define border_null(b)	((b) == none || (b) == NULL)
 static void
 pg_style_get_row (PreviewGrid *pg, GnmStyleRow *sr)
-{
+{	
 	GnmBorder const *top, *bottom, *none = gnm_style_border_none ();
 	GnmBorder const *left, *right;
 	int const end = sr->end_col, row = sr->row;
@@ -272,14 +224,16 @@ pg_style_get_row (PreviewGrid *pg, GnmStyleRow *sr)
 }
 
 /* no spans or merges */
-static void
-preview_grid_draw (FooCanvasItem *item, GdkDrawable *drawable,
-		   GdkEventExpose *expose)
+static gboolean
+preview_grid_draw_region (GocItem const *item, cairo_t *cr,
+			  double x0, double y0, double x1, double y1)
 {
+#if 0
 	gint draw_x = expose->area.x;
 	gint draw_y = expose->area.y;
 	gint width  = expose->area.width;
 	gint height = expose->area.height;
+#endif
 	PreviewGrid *pg = PREVIEW_GRID (item);
 	PangoContext *context = gtk_widget_get_pango_context
 		(gtk_widget_get_toplevel (GTK_WIDGET (item->canvas)));
@@ -292,11 +246,11 @@ preview_grid_draw (FooCanvasItem *item, GdkDrawable *drawable,
 	 * However, that feels like more hassle that it is worth.  Look into this someday.
 	 */
 	int x, y, col, row, n;
-	int const start_col = pg_get_col_offset (pg, draw_x - 2, &x);
-	int end_col         = pg_get_col_offset (pg, draw_x + width + 2, NULL);
+	int const start_col = pg_get_col_offset (pg, x0 - 2, &x);
+	int end_col         = pg_get_col_offset (pg, x1+ 2, NULL);
 	int diff_x    = x;
-	int start_row       = pg_get_row_offset (pg, draw_y - 2, &y);
-	int end_row         = pg_get_row_offset (pg, draw_y + height + 2, NULL);
+	int start_row       = pg_get_row_offset (pg, y0 - 2, &y);
+	int end_row         = pg_get_row_offset (pg, y1 + 2, NULL);
 	int diff_y    = y;
 	int row_height = pg->defaults.row_height;
 
@@ -328,10 +282,10 @@ preview_grid_draw (FooCanvasItem *item, GdkDrawable *drawable,
 	for (col = start_col; col <= end_col; col++)
 		colwidths[col] = pg->defaults.col_width;
 
-	foo_canvas_w2c (item->canvas, diff_x, diff_y, &diff_x, &diff_y);
 	/* Fill entire region with default background (even past far edge) */
-	gdk_draw_rectangle (drawable, pg->gc.fill, TRUE,
-			    diff_x, diff_y, width, height);
+	cairo_set_source_rgb (cr, 1., 1., 1.);
+	cairo_rectangle (cr, diff_x, diff_y, x1 - x0, y1 - y0);
+	cairo_fill (cr);
 
 	for (y = diff_y; row <= end_row; row = sr.row = next_sr.row) {
 		if (++next_sr.row > end_row) {
@@ -346,19 +300,19 @@ preview_grid_draw (FooCanvasItem *item, GdkDrawable *drawable,
 			GnmCell const  *cell  = pg_fetch_cell (pg,
 				col, row, context, style);
 
-			preview_grid_draw_background (drawable, pg,
+			preview_grid_draw_background (cr, pg,
 						      style, col, row, x, y,
 						      colwidths [col], row_height);
 
 			if (!gnm_cell_is_empty (cell))
-				cell_draw (cell, pg->gc.cell, drawable,
+				cell_draw (cell, cr,
 					   x, y, colwidths [col], row_height, -1);
 
 			x += colwidths [col];
 		}
 
-		gnm_style_borders_row_draw (prev_vert, &sr,
-					drawable, diff_x, y, y+row_height,
+		gnm_style_borders_row_draw (prev_vert, &sr, cr,
+					diff_x, y, y+row_height,
 					colwidths, TRUE, 1 /* cheat dir == 1 for now */);
 
 		/* roll the pointers */
@@ -370,11 +324,12 @@ preview_grid_draw (FooCanvasItem *item, GdkDrawable *drawable,
 
 		y += row_height;
 	}
+	return TRUE;
 }
 
 static double
-preview_grid_point (FooCanvasItem *item, double x, double y, int cx, int cy,
-		    FooCanvasItem **actual_item)
+preview_grid_distance (GocItem *item, double cx, double cy,
+		    GocItem **actual_item)
 {
 	*actual_item = item;
 	return 0.0;
@@ -417,7 +372,7 @@ preview_grid_set_property (GObject *obj, guint param_id,
 		return; /* NOTE : RETURN */
 	}
 
-	foo_canvas_item_request_update (FOO_CANVAS_ITEM (obj));
+	goc_item_invalidate (GOC_ITEM (obj));
 }
 
 static void
@@ -445,13 +400,6 @@ preview_grid_dispose (GObject *obj)
 static void
 preview_grid_init (PreviewGrid *pg)
 {
-	FooCanvasItem *item = FOO_CANVAS_ITEM (pg);
-
-	item->x1 = 0;
-	item->y1 = 0;
-	item->x2 = 0;
-	item->y2 = 0;
-
 	pg->sheet = g_object_new (GNM_SHEET_TYPE,
 				  "rows", 256,
 				  "columns", 256,
@@ -466,7 +414,7 @@ preview_grid_init (PreviewGrid *pg)
 static void
 preview_grid_class_init (GObjectClass *gobject_klass)
 {
-	FooCanvasItemClass *item_klass = (FooCanvasItemClass *)gobject_klass;
+	GocItemClass *item_klass = (GocItemClass *)gobject_klass;
 
 	parent_klass = g_type_class_peek_parent (gobject_klass);
 
@@ -491,13 +439,11 @@ preview_grid_class_init (GObjectClass *gobject_klass)
                  g_param_spec_pointer ("default-value", NULL, NULL,
 			GSF_PARAM_STATIC | G_PARAM_WRITABLE));
 
-	item_klass->update      = preview_grid_update;
-	item_klass->realize     = preview_grid_realize;
-	item_klass->unrealize   = preview_grid_unrealize;
-	item_klass->draw        = preview_grid_draw;
-	item_klass->point       = preview_grid_point;
+	item_klass->update_bounds = preview_grid_update_bounds;
+	item_klass->draw_region = preview_grid_draw_region;
+	item_klass->distance    = preview_grid_distance;
 }
 
 GSF_CLASS (PreviewGrid, preview_grid,
 	   preview_grid_class_init, preview_grid_init,
-	   FOO_TYPE_CANVAS_GROUP)
+	   GOC_TYPE_GROUP)
diff --git a/src/sheet-control-gui.c b/src/sheet-control-gui.c
index ebfddd9..9090529 100644
--- a/src/sheet-control-gui.c
+++ b/src/sheet-control-gui.c
@@ -130,15 +130,15 @@ scg_redraw_all (SheetControl *sc, gboolean headers)
 	g_return_if_fail (IS_SHEET_CONTROL_GUI (scg));
 
 	SCG_FOREACH_PANE (scg, pane, {
-		foo_canvas_request_redraw (FOO_CANVAS (pane),
-			0, 0, G_MAXINT, G_MAXINT);
+		goc_canvas_invalidate (GOC_CANVAS (pane),
+			G_MININT64, 0, G_MAXINT64, G_MAXINT64);
 		if (headers) {
 			if (NULL != pane->col.canvas)
-				foo_canvas_request_redraw (pane->col.canvas,
-					0, 0, G_MAXINT, G_MAXINT);
+				goc_canvas_invalidate (pane->col.canvas,
+					0, 0, G_MAXINT64, G_MAXINT64);
 			if (NULL != pane->row.canvas)
-				foo_canvas_request_redraw (pane->row.canvas,
-					0, 0, G_MAXINT, G_MAXINT);
+				goc_canvas_invalidate (pane->row.canvas,
+					0, 0, G_MAXINT64, G_MAXINT64);
 		}
 	});
 }
@@ -175,6 +175,7 @@ scg_redraw_headers (SheetControl *sc,
 	SheetControlGUI *scg = (SheetControlGUI *)sc;
 	GnmPane *pane;
 	int i;
+	double scale;
 
 	for (i = scg->active_panes; i-- > 0 ; ) {
 		if (NULL == (pane = scg->pane[i]))
@@ -182,12 +183,13 @@ scg_redraw_headers (SheetControl *sc,
 
 		if (col && pane->col.canvas != NULL) {
 			int left = 0, right = G_MAXINT - 1;
-			FooCanvas * const col_canvas = FOO_CANVAS (pane->col.canvas);
+			GocCanvas * const col_canvas = GOC_CANVAS (pane->col.canvas);
+			scale = goc_canvas_get_pixels_per_unit (col_canvas);
 
 			if (r != NULL) {
 				int const size = r->end.col - r->start.col;
 				if (-COL_HEURISTIC < size && size < COL_HEURISTIC) {
-					left = pane->first_offset.col +
+					left = pane->first_offset.x +
 						scg_colrow_distance_get (scg, TRUE,
 									 pane->first.col, r->start.col);
 					right = left +
@@ -195,22 +197,22 @@ scg_redraw_headers (SheetControl *sc,
 									 r->start.col, r->end.col+1);
 				}
 			}
-			/* Request excludes the far coordinate.  Add 1 to include them */
 			if (col_canvas->scroll_x1) {
-				foo_canvas_request_redraw (col_canvas,
-					gnm_foo_canvas_x_w2c (pane->col.canvas, right + 1), 0,
-					gnm_foo_canvas_x_w2c (pane->col.canvas, left), G_MAXINT);
+				goc_canvas_invalidate (col_canvas,
+					right / scale, 0,
+					left / scale, G_MAXINT64);
 			} else
-				foo_canvas_request_redraw (col_canvas,
-					left, 0, right+1, G_MAXINT);
+				goc_canvas_invalidate (col_canvas,
+					left / scale, 0, right / scale, G_MAXINT64);
 		}
 
 		if (row && pane->row.canvas != NULL) {
-			int top = 0, bottom = G_MAXINT - 1;
+			gint64 top = 0, bottom = G_MAXINT64 - 1;
+			scale = goc_canvas_get_pixels_per_unit (pane->row.canvas);
 			if (r != NULL) {
 				int const size = r->end.row - r->start.row;
 				if (-ROW_HEURISTIC < size && size < ROW_HEURISTIC) {
-					top = pane->first_offset.row +
+					top = pane->first_offset.y +
 						scg_colrow_distance_get (scg, FALSE,
 									 pane->first.row, r->start.row);
 					bottom = top +
@@ -218,9 +220,8 @@ scg_redraw_headers (SheetControl *sc,
 									 r->start.row, r->end.row+1);
 				}
 			}
-			/* Request excludes the far coordinate.  Add 1 to include them */
-			foo_canvas_request_redraw (FOO_CANVAS (pane->row.canvas),
-				0, top, G_MAXINT, bottom+1);
+			goc_canvas_invalidate (GOC_CANVAS (pane->row.canvas),
+				0, top / scale, G_MAXINT64, bottom / scale);
 		}
 	}
 }
@@ -315,9 +316,9 @@ scg_resize (SheetControlGUI *scg, gboolean force_scroll)
 	int h, w, btn_h, btn_w, tmp;
 
 	/* Recalibrate the starting offsets */
-	pane->first_offset.col = scg_colrow_distance_get (scg,
+	pane->first_offset.x = scg_colrow_distance_get (scg,
 		TRUE, 0, pane->first.col);
-	pane->first_offset.row = scg_colrow_distance_get (scg,
+	pane->first_offset.y = scg_colrow_distance_get (scg,
 		FALSE, 0, pane->first.row);
 
 	/* resize Pane[0] headers */
@@ -338,21 +339,7 @@ scg_resize (SheetControlGUI *scg, gboolean force_scroll)
 		scg->pane[0]->row.item, FALSE,
 		-1, btn_h, scg->row_group.buttons, scg->row_group.button_box);
 
-	/* When setting a canvas scroll region to [x0 .. x1[ , pixel x1 is not displayed.
-	 * That's why we set scroll region to [-FACTOR + 1 .. +1[ in rtl mode, because
-	 * we want x(ltr) = - x(rtl). */
-
-	/* no need to resize panes that are about to go away while unfreezing */
-	if (scg->active_panes == 1 || !sv_is_frozen (scg_view (scg))) {
-		if (sheet->text_is_rtl)
-			foo_canvas_set_scroll_region (scg->pane[0]->col.canvas,
-				-GNM_PANE_MAX_X * scale + 1.0, 0, 1.0, h * scale);
-		else
-			foo_canvas_set_scroll_region (scg->pane[0]->col.canvas,
-				0, 0, GNM_PANE_MAX_X * scale, h * scale);
-		foo_canvas_set_scroll_region (scg->pane[0]->row.canvas,
-			0, 0, w * scale, GNM_PANE_MAX_Y * scale);
-	} else {
+	if (scg->active_panes != 1 && sv_is_frozen (scg_view (scg))) {
 		GnmCellPos const *tl = &scg_view (scg)->frozen_top_left;
 		GnmCellPos const *br = &scg_view (scg)->unfrozen_top_left;
 		int const l = scg_colrow_distance_get (scg, TRUE,
@@ -369,9 +356,9 @@ scg_resize (SheetControlGUI *scg, gboolean force_scroll)
 		for (i = scg->active_panes; i-- > 1 ; ) {
 			GnmPane *pane = scg->pane[i];
 			if (NULL != pane) {
-				pane->first_offset.col = scg_colrow_distance_get (
+				pane->first_offset.x = scg_colrow_distance_get (
 					scg, TRUE, 0, pane->first.col);
-				pane->first_offset.row = scg_colrow_distance_get (
+				pane->first_offset.y = scg_colrow_distance_get (
 					scg, FALSE, 0, pane->first.row);
 			}
 		}
@@ -386,12 +373,6 @@ scg_resize (SheetControlGUI *scg, gboolean force_scroll)
 			 */
 			h = item_bar_calc_size (scg->pane[1]->col.item);
 			gtk_widget_set_size_request (GTK_WIDGET (scg->pane[1]->col.canvas), r - l, h);
-			if (sheet->text_is_rtl)
-				foo_canvas_set_scroll_region (scg->pane[1]->col.canvas,
-					-GNM_PANE_MAX_X * scale + 1.0, 0, 1.0, h * scale);
-			else
-				foo_canvas_set_scroll_region (scg->pane[1]->col.canvas,
-					0, 0, GNM_PANE_MAX_X * scale, h * scale);
 		}
 
 		if (scg->pane[3]) {
@@ -399,30 +380,13 @@ scg_resize (SheetControlGUI *scg, gboolean force_scroll)
 			/* The item_bar_calcs should be equal */
 			w = item_bar_calc_size (scg->pane[3]->row.item);
 			gtk_widget_set_size_request (GTK_WIDGET (scg->pane[3]->row.canvas), w, b - t);
-			foo_canvas_set_scroll_region (scg->pane[3]->row.canvas,
-				0, 0, w * scale, GNM_PANE_MAX_Y * scale);
 		}
 
 		if (scg->pane[2])
 			gtk_widget_set_size_request (GTK_WIDGET (scg->pane[2]), r - l, b - t);
-
-		if (sheet->text_is_rtl)
-			foo_canvas_set_scroll_region (scg->pane[0]->col.canvas,
-				-GNM_PANE_MAX_X * scale + 1.0, 0, 1.0, h * scale);
-		else
-			foo_canvas_set_scroll_region (scg->pane[0]->col.canvas,
-				0, 0, GNM_PANE_MAX_X * scale, h * scale);
-		foo_canvas_set_scroll_region (scg->pane[0]->row.canvas,
-			0, 0, w * scale, GNM_PANE_MAX_Y * scale);
 	}
 
 	SCG_FOREACH_PANE (scg, pane, {
-		if (sheet->text_is_rtl)
-			foo_canvas_set_scroll_region (FOO_CANVAS (pane),
-				-(GNM_PANE_MAX_X * scale) + 1.0, 0., 1.0, GNM_PANE_MAX_Y * scale);
-		else
-			foo_canvas_set_scroll_region (FOO_CANVAS (pane),
-				0., 0., GNM_PANE_MAX_X * scale,  GNM_PANE_MAX_Y * scale);
 		gnm_pane_reposition_cursors (pane);
 	});
 }
@@ -704,17 +668,6 @@ scg_init (SheetControlGUI *scg)
 
 /*************************************************************************/
 
-/*
- * calc_left_position:
- * @pane: a #GnmPane
- * @x: first row x position.
- *
- * Calculate x position of left row in canvas coordinates.
- */
-#define calc_left_row_position(pane,x)	(scg_sheet ((pane)->simple.scg)->text_is_rtl) ? \
-						gnm_foo_canvas_x_w2c ((FooCanvas *) (pane), \
-						(x) + GTK_WIDGET (pane)->allocation.width - 1) : (x)
-
 /**
  * gnm_pane_update_inital_top_left :
  * A convenience routine to store the new topleft back in the view.
@@ -728,22 +681,20 @@ gnm_pane_update_inital_top_left (GnmPane const *pane)
 	}
 }
 
-static int
+static gint64
 bar_set_left_col (GnmPane *pane, int new_first_col)
 {
-	FooCanvas *colc;
-	int col_offset;
+	GocCanvas *colc;
+	gint64 col_offset;
 
 
-	col_offset = pane->first_offset.col +=
+	col_offset = pane->first_offset.x +=
 		scg_colrow_distance_get (pane->simple.scg, TRUE, pane->first.col, new_first_col);
 	pane->first.col = new_first_col;
-	col_offset  = calc_left_row_position (pane, col_offset);
 
 	/* Scroll the column headers */
 	if (NULL != (colc = pane->col.canvas))
-		foo_canvas_scroll_to (colc, col_offset,
-			pane->first_offset.row);
+		goc_canvas_scroll_to (colc, col_offset / colc->pixels_per_unit, 0);
 
 	return col_offset;
 }
@@ -757,11 +708,11 @@ gnm_pane_set_left_col (GnmPane *pane, int new_first_col)
 	g_return_if_fail (0 <= new_first_col && new_first_col < gnm_sheet_get_max_cols (sheet));
 
 	if (pane->first.col != new_first_col) {
-		FooCanvas * const canvas = FOO_CANVAS (pane);
-		int const col_offset = bar_set_left_col (pane, new_first_col);
+		GocCanvas * const canvas = GOC_CANVAS (pane);
+		gint64 const col_offset = bar_set_left_col (pane, new_first_col);
 
 		gnm_pane_compute_visible_region (pane, FALSE);
-		foo_canvas_scroll_to (canvas, col_offset, pane->first_offset.row);
+		goc_canvas_scroll_to (canvas, col_offset / canvas->pixels_per_unit, pane->first_offset.y / canvas->pixels_per_unit);
 		gnm_pane_update_inital_top_left (pane);
 	}
 }
@@ -793,19 +744,19 @@ scg_set_left_col (SheetControlGUI *scg, int col)
 	gnm_pane_set_left_col (scg_pane (scg, 0), col);
 }
 
-static int
+static gint64
 bar_set_top_row (GnmPane *pane, int new_first_row)
 {
-	FooCanvas *rowc;
-	int row_offset;
+	GocCanvas *rowc;
+	gint64 row_offset;
 
-	row_offset = pane->first_offset.row +=
+	row_offset = pane->first_offset.y +=
 		scg_colrow_distance_get (pane->simple.scg, FALSE, pane->first.row, new_first_row);
 	pane->first.row = new_first_row;
 
 	/* Scroll the row headers */
 	if (NULL != (rowc = pane->row.canvas))
-		foo_canvas_scroll_to (rowc, 0, row_offset);
+		goc_canvas_scroll_to (rowc, 0, row_offset / rowc->pixels_per_unit);
 
 	return row_offset;
 }
@@ -819,13 +770,12 @@ gnm_pane_set_top_row (GnmPane *pane, int new_first_row)
 	g_return_if_fail (0 <= new_first_row && new_first_row < gnm_sheet_get_max_rows (sheet));
 
 	if (pane->first.row != new_first_row) {
-		FooCanvas * const canvas = FOO_CANVAS(pane);
-		int const row_offset = bar_set_top_row (pane, new_first_row);
-		int col_offset = pane->first_offset.col;
+		GocCanvas * const canvas = GOC_CANVAS(pane);
+		gint64 const row_offset = bar_set_top_row (pane, new_first_row);
+		gint64 col_offset = pane->first_offset.x;
 
 		gnm_pane_compute_visible_region (pane, FALSE);
-		col_offset = calc_left_row_position (pane, col_offset);
-		foo_canvas_scroll_to (canvas, col_offset, row_offset);
+		goc_canvas_scroll_to (canvas, col_offset / canvas->pixels_per_unit, row_offset / canvas->pixels_per_unit);
 		gnm_pane_update_inital_top_left (pane);
 	}
 }
@@ -862,7 +812,8 @@ gnm_pane_set_top_left (GnmPane *pane,
 			 int col, int row, gboolean force_scroll)
 {
 	gboolean changed = FALSE;
-	int col_offset, row_offset;
+	gint64 col_offset, row_offset;
+	GocCanvas *canvas;
 
 	g_return_if_fail (0 <= col &&
 			  col < gnm_sheet_get_max_cols (scg_sheet (pane->simple.scg)));
@@ -872,32 +823,33 @@ gnm_pane_set_top_left (GnmPane *pane,
 	if (pane->first.col != col || force_scroll) {
 		if (force_scroll) {
 			/* Clear the offsets in case col/row size changed */
-			pane->first_offset.col = 0;
+			pane->first_offset.x = 0;
 			pane->first.col = 0;
 		}
 
 		col_offset = bar_set_left_col (pane, col);
 		changed = TRUE;
 	} else {
-		col_offset = calc_left_row_position (pane, pane->first_offset.col);
+		col_offset = pane->first_offset.x;
 	}
 
 	if (pane->first.row != row || force_scroll) {
 		if (force_scroll) {
 			/* Clear the offsets in case col/row size changed */
-			pane->first_offset.row = 0;
+			pane->first_offset.y = 0;
 			pane->first.row = 0;
 		}
 		row_offset = bar_set_top_row (pane, row);
 		changed = TRUE;
 	} else
-		row_offset = pane->first_offset.row;
+		row_offset = pane->first_offset.y;
 
 	if (!changed)
 		return;
 
 	gnm_pane_compute_visible_region (pane, force_scroll);
-	foo_canvas_scroll_to (FOO_CANVAS (pane), col_offset, row_offset);
+	canvas = GOC_CANVAS (pane);
+	goc_canvas_scroll_to (canvas, col_offset / canvas->pixels_per_unit, row_offset / canvas->pixels_per_unit);
 	gnm_pane_update_inital_top_left (pane);
 }
 
@@ -917,7 +869,7 @@ static void
 gnm_pane_make_cell_visible (GnmPane *pane, int col, int row,
 			      gboolean const force_scroll)
 {
-	FooCanvas *canvas;
+	GocCanvas *canvas;
 	Sheet *sheet;
 	int   new_first_col, new_first_row;
 
@@ -936,7 +888,7 @@ gnm_pane_make_cell_visible (GnmPane *pane, int col, int row,
 	g_return_if_fail (col < gnm_sheet_get_max_cols (sheet));
 	g_return_if_fail (row < gnm_sheet_get_max_rows (sheet));
 
-	canvas = FOO_CANVAS (pane);
+	canvas = GOC_CANVAS (pane);
 
 	/* Find the new pane->first.col */
 	if (col < pane->first.col) {
@@ -1084,6 +1036,9 @@ scg_set_panes (SheetControl *sc)
 	SheetControlGUI *scg = (SheetControlGUI *) sc;
 	SheetView	*sv = sc->view;
 	gboolean const being_frozen = sv_is_frozen (sv);
+	GocDirection direction = (sv_sheet (sv)->text_is_rtl)? GOC_DIRECTION_RTL: GOC_DIRECTION_LTR;
+
+	g_return_if_fail (IS_SHEET_VIEW (sv));
 
 	if (being_frozen) {
 		GnmCellPos const *tl = &sv->frozen_top_left;
@@ -1099,6 +1054,7 @@ scg_set_panes (SheetControl *sc)
 			scg->active_panes = 2;
 			if (!scg->pane[1]) {
 				scg->pane[1] = gnm_pane_new (scg, TRUE, FALSE, 1);
+				gnm_pane_set_direction (scg->pane[1], direction);
 				gtk_table_attach (scg->inner_table,
 					GTK_WIDGET (scg->pane[1]),
 					1, 2, 2, 3,
@@ -1119,6 +1075,7 @@ scg_set_panes (SheetControl *sc)
 			scg->active_panes = 4;
 			if (!scg->pane[2]) {
 				scg->pane[2] = gnm_pane_new (scg, FALSE, FALSE,  2);
+				gnm_pane_set_direction (scg->pane[2], direction);
 				gtk_table_attach (scg->inner_table,
 					GTK_WIDGET (scg->pane[2]),
 					1, 2, 1, 2,
@@ -1133,6 +1090,7 @@ scg_set_panes (SheetControl *sc)
 			scg->active_panes = 4;
 			if (!scg->pane[3]) {
 				scg->pane[3] = gnm_pane_new (scg, FALSE, TRUE, 3);
+				gnm_pane_set_direction (scg->pane[3], direction);
 				gtk_table_attach (scg->inner_table,
 					GTK_WIDGET (scg->pane[3]),
 					2, 3, 1, 2,
@@ -1227,17 +1185,26 @@ cb_scg_sheet_resized (Sheet *sheet,
 static void
 cb_scg_direction_changed (SheetControlGUI *scg)
 {
+	/* set direction in the canvas */
+	int i = scg->active_panes;
+	while (i-- > 0) {
+		GnmPane *pane = scg->pane[i];
+		if (NULL != pane)
+			gnm_pane_set_direction (scg->pane[i],
+			                        scg_sheet (scg)->text_is_rtl? GOC_DIRECTION_RTL: GOC_DIRECTION_LTR);
+	}
 	scg_resize (scg, TRUE);
 }
 
 static GnmPane const *
 resize_pane_pos (SheetControlGUI *scg, GtkPaned *p,
-		 int *colrow_result, int *guide_pos)
+		 int *colrow_result, gint64 *guide_pos)
 {
 	ColRowInfo const *cri;
 	GnmPane const  *pane = scg_pane (scg, 0);
 	gboolean const    vert = (p == scg->hpane);
-	int colrow, handle, pos = gtk_paned_get_position (p);
+	int colrow, handle;
+	gint64 pos = gtk_paned_get_position (p);
 
 	gtk_widget_style_get (GTK_WIDGET (p), "handle-size", &handle, NULL);
 	pos += handle / 2;
@@ -1250,11 +1217,8 @@ resize_pane_pos (SheetControlGUI *scg, GtkPaned *p,
 			else
 				pos -= w;
 		}
-		pos += pane->first_offset.col;
-		colrow = gnm_pane_find_col (pane,
-					      gnm_pane_x_w2c (pane, pos),
-					      guide_pos);
-		*guide_pos = gnm_pane_x_w2c (pane, *guide_pos);
+		pos += pane->first_offset.x;
+		colrow = gnm_pane_find_col (pane, pos, guide_pos);
 	} else {
 		pos -= GTK_WIDGET (scg->pane[0]->col.canvas)->allocation.height;
 		if (scg->pane[3]) {
@@ -1264,7 +1228,7 @@ resize_pane_pos (SheetControlGUI *scg, GtkPaned *p,
 			else
 				pos -= h;
 		}
-		pos += pane->first_offset.row;
+		pos += pane->first_offset.y;
 		colrow = gnm_pane_find_row (pane, pos, guide_pos);
 	}
 	cri = sheet_colrow_get_info (scg_sheet (scg), colrow, vert);
@@ -1316,7 +1280,8 @@ resize_pane_finish (SheetControlGUI *scg, GtkPaned *p)
 	SheetView *sv =	scg_view (scg);
 	GnmCellPos frozen_tl, unfrozen_tl;
 	GnmPane const *pane;
-	int	   colrow, guide_pos;
+	int colrow;
+	gint64 guide_pos;
 
 	if (p->in_drag)
 		return TRUE;
@@ -1361,7 +1326,8 @@ cb_resize_pane_motion (GtkPaned *p,
 		       SheetControlGUI *scg)
 {
 	gboolean const vert = (p == scg->hpane);
-	int colrow, guide_pos;
+	int colrow;
+	gint64 guide_pos;
 
 	resize_pane_pos (scg, p, &colrow, &guide_pos);
 	if (scg->pane_drag_handler == 0 && p->in_drag) {
@@ -1381,10 +1347,12 @@ sheet_control_gui_new (SheetView *sv, WBCGtk *wbcg)
 	SheetControlGUI *scg;
 	GtkUpdateType scroll_update_policy;
 	Sheet *sheet;
+	GocDirection direction;
 
 	g_return_val_if_fail (IS_SHEET_VIEW (sv), NULL);
 
 	sheet = sv_sheet (sv);
+	direction = (sheet->text_is_rtl)? GOC_DIRECTION_RTL: GOC_DIRECTION_LTR;
 
 	scg = g_object_new (SHEET_CONTROL_GUI_TYPE, NULL);
 	scg->wbcg = wbcg;
@@ -1431,6 +1399,7 @@ sheet_control_gui_new (SheetView *sv, WBCGtk *wbcg)
 
 	scg->pane[1] = scg->pane[2] = scg->pane[3] = NULL;
 	scg->pane[0] = gnm_pane_new (scg, TRUE, TRUE, 0);
+	gnm_pane_set_direction (scg->pane[0], direction);
 	scg->inner_table = GTK_TABLE (gtk_table_new (3, 3, FALSE));
 	gtk_table_attach (scg->inner_table, GTK_WIDGET (scg->corner),
 		0, 1, 0, 1,
@@ -1626,7 +1595,7 @@ scg_unant (SheetControl *sc)
 		GSList *l;
 
 		for (l = pane->cursor.animated; l; l = l->next)
-			gtk_object_destroy (GTK_OBJECT (l->data));
+			g_object_unref (G_OBJECT (l->data));
 
 		g_slist_free (pane->cursor.animated);
 		pane->cursor.animated = NULL;
@@ -1649,7 +1618,7 @@ scg_ant (SheetControl *sc)
 		GnmRange const *r = l->data;
 
 		SCG_FOREACH_PANE (scg, pane, {
-			ItemCursor *ic = ITEM_CURSOR (foo_canvas_item_new (
+			ItemCursor *ic = ITEM_CURSOR (goc_item_new (
 				pane->grid_items,
 				item_cursor_get_type (),
 				"SheetControlGUI", scg,
@@ -2056,21 +2025,17 @@ scg_mode_edit_virt (SheetControl *sc)
 }
 
 static int
-calc_obj_place (GnmPane *pane, int canvas_coord, gboolean is_col,
+calc_obj_place (GnmPane *pane, gint64 canvas_coord, gboolean is_col,
 		float *offset)
 {
-	int origin, colrow;
+	gint64 origin;
+	int colrow;
 	ColRowInfo const *cri;
 	Sheet const *sheet = scg_sheet (pane->simple.scg);
 
 	if (is_col) {
 		colrow = gnm_pane_find_col (pane, canvas_coord, &origin);
 		cri = sheet_col_get_info (sheet, colrow);
-		if (sheet->text_is_rtl) {
-			int tmp = canvas_coord;
-			canvas_coord = origin;
-			origin = tmp;
-		}
 	} else {
 		colrow = gnm_pane_find_row (pane, canvas_coord, &origin);
 		cri = sheet_row_get_info (sheet, colrow);
@@ -2200,13 +2165,13 @@ snap_pos_to_grid (ObjDragInfo const *info, gboolean is_col, double w_pos,
 	GnmPane const *pane = info->pane;
 	Sheet const *sheet = scg_sheet (info->scg);
 	int cell  = is_col ? pane->first.col        : pane->first.row;
-	int pixel = is_col ? pane->first_offset.col : pane->first_offset.row;
+	gint64 pixel = is_col ? pane->first_offset.x : pane->first_offset.y;
 	gboolean snap = FALSE;
 	int length = 0;
 	ColRowInfo const *cr_info;
 	int sheet_max = colrow_max (is_col, sheet);
-	int const sign = (is_col && sheet->text_is_rtl) ? -1 : 1;
-	int pos = sign * (w_pos * FOO_CANVAS (pane)->pixels_per_unit + .5);
+
+	double pos = w_pos + .5;
 
 	if (pos < pixel) {
 		while (cell > 0 && pos < pixel) {
@@ -2236,7 +2201,7 @@ snap_pos_to_grid (ObjDragInfo const *info, gboolean is_col, double w_pos,
 				pos = (pixel == pos) ? pixel : (to_min ? pixel : pixel + length);
 		}
 	}
-	return sign * pos / FOO_CANVAS (pane)->pixels_per_unit;
+	return/* sign */ pos;
 }
 
 static void
@@ -2254,9 +2219,7 @@ apply_move (SheetObject *so, int x_idx, int y_idx, double *coords,
 		g_return_if_fail (info->pane != NULL);
 
 		if (move_x)
-			x = snap_pos_to_grid (info, TRUE,  x,
-			      scg_sheet (info->scg)->text_is_rtl
-				      ? info->dx > 0. : info->dx < 0.);
+			x = snap_pos_to_grid (info, TRUE,  x, info->dx < 0.);
 		if (move_y)
 			y = snap_pos_to_grid (info, FALSE, y, info->dy < 0.);
 		if (info->primary_object == so || NULL == info->primary_object) {
@@ -2287,9 +2250,8 @@ drag_object (SheetObject *so, double *coords, ObjDragInfo *info)
 	g_return_if_fail (info->drag_type <= 8);
 
 	if (info->drag_type == 8) {
-		gboolean const rtl = scg_sheet (info->scg)->text_is_rtl;
-		apply_move (so, rtl ? 2 : 0, 1, coords, info, info->snap_to_grid);
-		apply_move (so, rtl ? 0 : 2, 3, coords, info, FALSE);
+		apply_move (so, 0, 1, coords, info, info->snap_to_grid);
+		apply_move (so, 2, 3, coords, info, FALSE);
 	} else
 		apply_move (so,
 			    idx_info[info->drag_type].x_idx,
@@ -2367,18 +2329,18 @@ cb_collect_objects_to_commit (SheetObject *so, double *coords, CollectObjectsDat
 
 	if (!sheet_object_rubber_band_directly (so)) {
 		SCG_FOREACH_PANE (data->scg, pane, {
-			FooCanvasItem **ctrl_pts = g_hash_table_lookup (pane->drag.ctrl_pts, so);
+			GocItem **ctrl_pts = g_hash_table_lookup (pane->drag.ctrl_pts, so);
 			if (NULL != ctrl_pts[9]) {
 				double const *pts = g_hash_table_lookup (
 					pane->simple.scg->selected_objects, so);
 				SheetObjectView *sov = sheet_object_get_view (so,
 					(SheetObjectViewContainer *)pane);
 
-				gtk_object_destroy (GTK_OBJECT (ctrl_pts[9]));
+				g_object_unref (G_OBJECT (ctrl_pts[9]));
 				ctrl_pts[9] = NULL;
 
 				if (NULL == sov)
-					sov = sheet_object_new_view (so, (SheetObjectViewContainer *)pane);
+					sov = sheet_object_new_view (so, (SheetObjectViewContainer *) pane);
 				if (NULL != sov)
 					sheet_object_view_set_bounds (sov, pts, TRUE);
 			}
@@ -2420,13 +2382,11 @@ scg_object_coords_to_anchor (SheetControlGUI const *scg,
 	/* pane 0 always exists and the others are always use the same basis */
 	GnmPane *pane = scg_pane ((SheetControlGUI *)scg, 0);
 	double	tmp[4];
-	int pixels[4];
-
 	g_return_if_fail (IS_SHEET_CONTROL_GUI (scg));
 	g_return_if_fail (coords != NULL);
 
 	in_out->base.direction = GOD_ANCHOR_DIR_NONE_MASK;
-	if ((coords[0] > coords[2]) == (!scg_sheet (scg)->text_is_rtl)) {
+	if (coords[0] > coords[2]) {
 		tmp[0] = coords[2];
 		tmp[2] = coords[0];
 	} else {
@@ -2443,18 +2403,13 @@ scg_object_coords_to_anchor (SheetControlGUI const *scg,
 		in_out->base.direction |= GOD_ANCHOR_DIR_DOWN;
 	}
 
-	foo_canvas_w2c (FOO_CANVAS (pane), tmp[0], tmp[1],
-		pixels + 0, pixels + 1);
-	foo_canvas_w2c (FOO_CANVAS (pane),
-		tmp[2], tmp[3],
-		pixels + 2, pixels + 3);
-	in_out->cell_bound.start.col = calc_obj_place (pane, pixels[0], TRUE,
+	in_out->cell_bound.start.col = calc_obj_place (pane, tmp[0], TRUE,
 		in_out->offset + 0);
-	in_out->cell_bound.start.row = calc_obj_place (pane, pixels[1], FALSE,
+	in_out->cell_bound.start.row = calc_obj_place (pane, tmp[1], FALSE,
 		in_out->offset + 1);
-	in_out->cell_bound.end.col = calc_obj_place (pane, pixels[2], TRUE,
+	in_out->cell_bound.end.col = calc_obj_place (pane, tmp[2], TRUE,
 		in_out->offset + 2);
-	in_out->cell_bound.end.row = calc_obj_place (pane, pixels[3], FALSE,
+	in_out->cell_bound.end.row = calc_obj_place (pane, tmp[3], FALSE,
 		in_out->offset + 3);
 }
 
@@ -2469,11 +2424,9 @@ void
 scg_object_anchor_to_coords (SheetControlGUI const *scg,
 			     SheetObjectAnchor const *anchor, double *coords)
 {
-	/* pane 0 always exists and the others are always use the same basis */
-	GnmPane *pane = scg_pane ((SheetControlGUI *)scg, 0);
 	Sheet *sheet = scg_sheet (scg);
 	GODrawingAnchorDir direction;
-	double pixels[4], scale;
+	gint64 pixels[4];
 	GnmRange const *r;
 
 	g_return_if_fail (IS_SHEET_CONTROL_GUI (scg));
@@ -2500,16 +2453,10 @@ scg_object_anchor_to_coords (SheetControlGUI const *scg,
 	if (direction == GOD_ANCHOR_DIR_UNKNOWN)
 		direction = GOD_ANCHOR_DIR_DOWN_RIGHT;
 
-	scale = 1. / FOO_CANVAS (pane)->pixels_per_unit;
-	coords[0] = pixels[direction & GOD_ANCHOR_DIR_H_MASK  ? 0 : 2] * scale;
-	coords[1] = pixels[direction & GOD_ANCHOR_DIR_V_MASK  ? 1 : 3] * scale;
-	coords[2] = pixels[direction & GOD_ANCHOR_DIR_H_MASK  ? 2 : 0] * scale;
-	coords[3] = pixels[direction & GOD_ANCHOR_DIR_V_MASK  ? 3 : 1] * scale;
-	if (sheet->text_is_rtl) {
-		double tmp = -coords[0];
-		coords[0] = -coords[2];
-		coords[2] = tmp;
-	}
+	coords[0] = pixels[direction & GOD_ANCHOR_DIR_H_MASK  ? 0 : 2];
+	coords[1] = pixels[direction & GOD_ANCHOR_DIR_V_MASK  ? 1 : 3];
+	coords[2] = pixels[direction & GOD_ANCHOR_DIR_H_MASK  ? 2 : 0];
+	coords[3] = pixels[direction & GOD_ANCHOR_DIR_V_MASK  ? 3 : 1];
 }
 
 /***************************************************************************/
@@ -2649,14 +2596,15 @@ scg_comment_unselect (SheetControlGUI *scg, GnmComment *cc)
 /************************************************************************/
 /* Col/Row size support routines.  */
 
-int
+gint64
 scg_colrow_distance_get (SheetControlGUI const *scg, gboolean is_cols,
 			 int from, int to)
 {
 	Sheet *sheet = scg_sheet (scg);
 	ColRowCollection const *collection;
 	int default_size;
-	int i, pixels = 0;
+	int i;
+	gint64 pixels = 0;
 	int sign = 1;
 
 	g_return_val_if_fail (IS_SHEET_CONTROL_GUI (scg), 1);
@@ -3056,7 +3004,7 @@ scg_size_guide_start (SheetControlGUI *scg, gboolean vert, int colrow, int width
 		gnm_pane_size_guide_start (pane, vert, colrow, width););
 }
 void
-scg_size_guide_motion (SheetControlGUI *scg, gboolean vert, int guide_pos)
+scg_size_guide_motion (SheetControlGUI *scg, gboolean vert, gint64 guide_pos)
 {
 	g_return_if_fail (IS_SHEET_CONTROL_GUI (scg));
 	SCG_FOREACH_PANE (scg, pane,
@@ -3121,10 +3069,10 @@ scg_scale_changed (SheetControl *sc)
 
 	SCG_FOREACH_PANE (scg, pane, {
 		if (pane->col.canvas != NULL)
-			foo_canvas_set_pixels_per_unit (pane->col.canvas, z);
+			goc_canvas_set_pixels_per_unit (pane->col.canvas, z);
 		if (pane->row.canvas != NULL)
-			foo_canvas_set_pixels_per_unit (pane->row.canvas, z);
-		foo_canvas_set_pixels_per_unit (FOO_CANVAS (pane), z);
+			goc_canvas_set_pixels_per_unit (pane->row.canvas, z);
+		goc_canvas_set_pixels_per_unit (GOC_CANVAS (pane), z);
 	});
 
 	scg_resize (scg, TRUE);
diff --git a/src/sheet-control-gui.h b/src/sheet-control-gui.h
index 413f97f..7afff49 100644
--- a/src/sheet-control-gui.h
+++ b/src/sheet-control-gui.h
@@ -50,7 +50,7 @@ gboolean scg_colrow_select	(SheetControlGUI *scg,
 				 gboolean is_cols, int index, int modifiers);
 void scg_colrow_size_set	(SheetControlGUI *scg,
 				 gboolean is_cols, int index, int new_size_pixels);
-int  scg_colrow_distance_get	(SheetControlGUI const *scg,
+gint64  scg_colrow_distance_get	(SheetControlGUI const *scg,
 				 gboolean is_cols, int from, int to);
 
 void scg_edit_start		(SheetControlGUI *scg);
@@ -88,7 +88,7 @@ void scg_set_top_row		(SheetControlGUI *scg, int new_first_row);
 void scg_size_guide_start	(SheetControlGUI *scg, gboolean vert,
 				 int colrow, int width);
 void scg_size_guide_motion	(SheetControlGUI *scg, gboolean vert,
-				 int guide_pos);
+				 gint64 guide_pos);
 void scg_size_guide_stop	(SheetControlGUI *scg);
 
 typedef void (*SCGUIMoveFunc)	(SheetControlGUI *, int n,
diff --git a/src/sheet-filter.c b/src/sheet-filter.c
index 4a409ea..f506cec 100644
--- a/src/sheet-filter.c
+++ b/src/sheet-filter.c
@@ -35,8 +35,8 @@
 #include "number-match.h"
 #include "gutils.h"
 #include "sheet-object.h"
-#include "gnm-filter-combo-foo-view.h"
-#include "gnm-cell-combo-foo-view.h"
+#include "gnm-filter-combo-view.h"
+#include "gnm-cell-combo-view.h"
 #include <gsf/gsf-impl-utils.h>
 
 #include <glib/gi18n-lib.h>
@@ -510,10 +510,10 @@ gnm_filter_combo_init (SheetObject *so)
 	so->flags &= ~SHEET_OBJECT_MOVE_WITH_CELLS;
 }
 static SheetObjectView *
-gnm_filter_combo_foo_view_new (SheetObject *so, SheetObjectViewContainer *container)
+gnm_filter_combo_view_new (SheetObject *so, SheetObjectViewContainer *container)
 {
-	return gnm_cell_combo_foo_view_new (so,
-		gnm_filter_combo_foo_view_get_type (), container);
+	return gnm_cell_combo_view_new (so,
+		gnm_filter_combo_view_get_type (), container);
 }
 static void
 gnm_filter_combo_class_init (GObjectClass *gobject_class)
@@ -524,7 +524,7 @@ gnm_filter_combo_class_init (GObjectClass *gobject_class)
 	gobject_class->finalize = gnm_filter_combo_finalize;
 
 	/* SheetObject class method overrides */
-	so_class->new_view	= gnm_filter_combo_foo_view_new;
+	so_class->new_view	= gnm_filter_combo_view_new;
 	so_class->read_xml_dom  = NULL;
 	so_class->write_xml_sax = NULL;
 	so_class->prep_sax_parser = NULL;
diff --git a/src/sheet-object-cell-comment.c b/src/sheet-object-cell-comment.c
index 2ab6c8f..95fb636 100644
--- a/src/sheet-object-cell-comment.c
+++ b/src/sheet-object-cell-comment.c
@@ -37,7 +37,6 @@
 #include <string.h>
 #include <libxml/globals.h>
 #include <gsf/gsf-impl-utils.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-polygon.h>
 
 struct _GnmComment {
 	SheetObject	base;
@@ -65,17 +64,18 @@ comment_view_destroy (SheetObjectView *sov)
 static void
 comment_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
+	GocPoints *points = goc_points_new (3);
+	GocItem *item = GOC_ITEM (GOC_GROUP (sov)->children->data);
 	if (visible) {
 		SheetObject *so = sheet_object_view_get_so (sov);
-		SheetControlGUI const *scg = GNM_SIMPLE_CANVAS (view->canvas)->scg;
+		SheetControlGUI const *scg = GNM_SIMPLE_CANVAS (item->canvas)->scg;
 		double scale;
-		int x, y, dx, far_col;
-		FooCanvasPoints *points = foo_canvas_points_new (3);
+		gint64 x, y, dx;
+		int far_col;
 		GnmRange const *r = gnm_sheet_merge_is_corner (so->sheet,
 			&so->anchor.cell_bound.start);
 
-		scale = 1. / view->canvas->pixels_per_unit;
+		scale = 1. / item->canvas->pixels_per_unit;
 
 		if (r != NULL)
 			far_col = 1 + r->end.col;
@@ -86,9 +86,9 @@ comment_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean vi
 		/* Add 1 to y because we measure from start, x is measured from end, so
 		 * it does not need it */
 		y = scg_colrow_distance_get (scg, FALSE, 0, so->anchor.cell_bound.start.row)+ 1;
-		points->coords[1] = scale * y;
-		points->coords[3] = scale * y;
-		points->coords[5] = scale * y + TRIANGLE_WIDTH;
+		points->points[0].y = scale * y;
+		points->points[1].y = scale * y;
+		points->points[2].y = scale * y + TRIANGLE_WIDTH;
 
 		dx = TRIANGLE_WIDTH;
 		if (so->sheet->text_is_rtl) {
@@ -96,29 +96,87 @@ comment_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean vi
 			scale = -scale;
 		}
 		x = scg_colrow_distance_get (scg, TRUE, 0, far_col);
-		points->coords[0] = scale * x - dx;
-		points->coords[2] = scale * x;
-		points->coords[4] = scale * x;
+		points->points[0].x = scale * x - dx;
+		points->points[1].x = scale * x;
+		points->points[2].x = scale * x;
 
-		foo_canvas_item_set (view, "points", points, NULL);
-		foo_canvas_points_free (points);
-		foo_canvas_item_show (view);
+		goc_item_set (item, "points", points, NULL);
+		goc_points_unref (points);
+		goc_item_show (GOC_ITEM (sov));
 	} else
-		foo_canvas_item_hide (view);
+		goc_item_hide (GOC_ITEM (sov));
+}
+
+static gboolean
+comment_view_button_released (GocItem *item, int button, double x, double y)
+{
+	if (button !=1)
+		return FALSE;
+
+	scg_comment_display (GNM_PANE (item->canvas)->simple.scg,
+	                     CELL_COMMENT (sheet_object_view_get_so (SHEET_OBJECT_VIEW (item))));
+	return TRUE;
+}
+
+static gboolean
+comment_view_button_pressed (GocItem *item, int button, double x, double y)
+{
+	return TRUE;
+}
+
+static gboolean
+comment_view_button2_pressed (GocItem *item, int button, double x, double y)
+{
+	SheetObject *so;
+	GnmRange const *r;
+	SheetControlGUI *scg;
+	if (button !=1)
+		return FALSE;
+
+	scg = GNM_PANE (item->canvas)->simple.scg;
+	so = sheet_object_view_get_so (SHEET_OBJECT_VIEW (item));
+	r = sheet_object_get_range (so);
+	dialog_cell_comment (scg->wbcg, so->sheet, &r->start);
+	return TRUE;
+}
+
+static gboolean
+comment_view_enter_notify (GocItem *item, double x, double y)
+{
+	gnm_widget_set_cursor_type (GTK_WIDGET (item->canvas), GDK_ARROW);
+	scg_comment_select (GNM_PANE (item->canvas)->simple.scg,
+	                     CELL_COMMENT (sheet_object_view_get_so (SHEET_OBJECT_VIEW (item))));
+	return TRUE;
+}
+
+static gboolean
+comment_view_leave_notify (GocItem *item, double x, double y)
+{
+	scg_comment_unselect (GNM_PANE (item->canvas)->simple.scg,
+	                     CELL_COMMENT (sheet_object_view_get_so (SHEET_OBJECT_VIEW (item))));
+	return TRUE;
 }
 
 static void
-comment_foo_view_init (SheetObjectViewIface *sov_iface)
+comment_view_class_init (SheetObjectViewClass *sov_klass)
 {
-	sov_iface->destroy	= comment_view_destroy;
-	sov_iface->set_bounds	= comment_view_set_bounds;
+	GocItemClass *item_klass = (GocItemClass *) sov_klass;
+
+	sov_klass->destroy	= comment_view_destroy;
+	sov_klass->set_bounds	= comment_view_set_bounds;
+
+	item_klass->button_pressed = comment_view_button_pressed;
+	item_klass->button_released = comment_view_button_released;
+	item_klass->button2_pressed = comment_view_button2_pressed;
+	item_klass->enter_notify = comment_view_enter_notify;
+	item_klass->leave_notify = comment_view_leave_notify;
 }
-typedef FooCanvasPolygon	CommentFooView;
-typedef FooCanvasPolygonClass	CommentFooViewClass;
-static GSF_CLASS_FULL (CommentFooView, comment_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, FOO_TYPE_CANVAS_POLYGON, 0,
-	GSF_INTERFACE (comment_foo_view_init, SHEET_OBJECT_VIEW_TYPE))
+
+typedef SheetObjectView		CommentView;
+typedef SheetObjectViewClass	CommentViewClass;
+static GSF_CLASS (CommentView, comment_view,
+	comment_view_class_init, NULL,
+	SHEET_OBJECT_VIEW_TYPE)
 
 static void
 cell_comment_finalize (GObject *object)
@@ -196,70 +254,18 @@ cell_comment_get_property (GObject *obj, guint param_id,
 	}
 }
 
-static int
-cell_comment_event (FooCanvasItem *view, GdkEvent *event, GnmPane *pane)
-{
-	GnmComment *cc;
-	SheetObject *so;
-	GnmRange const *r;
-	SheetControlGUI *scg;
-
-	switch (event->type) {
-	default:
-		return FALSE;
-
-	case GDK_BUTTON_RELEASE:
-		if (event->button.button != 1)
-			return FALSE;
-	case GDK_ENTER_NOTIFY:
-	case GDK_LEAVE_NOTIFY:
-	case GDK_2BUTTON_PRESS:
-		break;
-	}
-
-	scg = pane->simple.scg;
-	so = sheet_object_view_get_so (SHEET_OBJECT_VIEW (view));
-	cc = CELL_COMMENT (so);
-
-	g_return_val_if_fail (cc != NULL, FALSE);
-
-	switch (event->type) {
-	case GDK_BUTTON_RELEASE:
-		scg_comment_display (scg, cc);
-		break;
-
-	case GDK_ENTER_NOTIFY:
-		gnm_widget_set_cursor_type (GTK_WIDGET (view->canvas), GDK_ARROW);
-		scg_comment_select (scg, cc);
-		break;
-
-	case GDK_LEAVE_NOTIFY:
-		scg_comment_unselect (scg, cc);
-		break;
-
-	case GDK_2BUTTON_PRESS:
-		r = sheet_object_get_range (so);
-		dialog_cell_comment (scg->wbcg, so->sheet, &r->start);
-		break;
-
-	default:
-		return FALSE;
-	}
-	return TRUE;
-}
-
 static SheetObjectView *
 cell_comment_new_view (SheetObject *so, SheetObjectViewContainer *container)
 {
 	GnmPane	*pane = GNM_PANE (container);
-	FooCanvasItem	*view = foo_canvas_item_new (pane->grid_items,
-		comment_foo_view_get_type (),
-		"fill-color",	"red",
+	GocItem	*view = goc_item_new (pane->grid_items,
+		comment_view_get_type (),
 		NULL);
-	/* Do not use the standard handler, comments are not movable */
-	g_signal_connect (view,
-		"event",
-		G_CALLBACK (cell_comment_event), container);
+	GOStyle *style = go_styled_object_get_style (
+		GO_STYLED_OBJECT (goc_item_new (GOC_GROUP (view),
+			GOC_TYPE_POLYGON, NULL)));
+	style->outline.dash_type = GO_LINE_NONE;
+	style->fill.pattern.back = RGBA_RED;
 	return gnm_pane_object_register (so, view, FALSE);
 }
 
diff --git a/src/sheet-object-graph.c b/src/sheet-object-graph.c
index 78b04de..f434a45 100644
--- a/src/sheet-object-graph.c
+++ b/src/sheet-object-graph.c
@@ -39,6 +39,7 @@
 #include <graph.h>
 
 #include <goffice/goffice.h>
+#include <goffice/canvas/goc-graph.h>
 
 #include <gsf/gsf-impl-utils.h>
 #include <gsf/gsf-utils.h>
@@ -46,48 +47,48 @@
 #include <gsf/gsf-libxml.h>
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-line.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-rect-ellipse.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-polygon.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-text.h>
 #include <math.h>
 #include <string.h>
 
 static void
 so_graph_view_destroy (SheetObjectView *sov)
 {
-	gtk_object_destroy (GTK_OBJECT (sov));
+	g_object_unref (G_OBJECT (sov));
 }
 static void
 so_graph_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
+	GocItem *view = GOC_ITEM (GOC_GROUP (sov)->children->data);
+	double scale = goc_canvas_get_pixels_per_unit (view->canvas); 
 
 	if (visible) {
-		foo_canvas_item_set (view,
-			"x", MIN (coords [0], coords[2]),
-			"y", MIN (coords [3], coords[1]),
-			"w", fabs (coords [2] - coords [0]) + 1.,
-			"h", fabs (coords [3] - coords [1]) + 1.,
+		goc_item_set (GOC_ITEM (sov),
+			"x", MIN (coords [0], coords[2]) / scale,
+			"y", MIN (coords [3], coords[1]) / scale,
+			NULL);
+		goc_item_set (view,
+			"width", (fabs (coords [2] - coords [0]) + 1.) / scale,
+			"height", (fabs (coords [3] - coords [1]) + 1.) / scale,
 			NULL);
 
-		foo_canvas_item_show (view);
+		goc_item_show (view);
 	} else
-		foo_canvas_item_hide (view);
+		goc_item_hide (view);
 }
 
 static void
-so_graph_foo_view_init (SheetObjectViewIface *sov_iface)
+so_graph_goc_view_class_init (SheetObjectViewClass *sov_klass)
 {
-	sov_iface->destroy	= so_graph_view_destroy;
-	sov_iface->set_bounds	= so_graph_view_set_bounds;
+	sov_klass->destroy	= so_graph_view_destroy;
+	sov_klass->set_bounds	= so_graph_view_set_bounds;
 }
-typedef GogControlFooCanvas		SOGraphFooView;
-typedef GogControlFooCanvasClass	SOGraphFooViewClass;
-static GSF_CLASS_FULL (SOGraphFooView, so_graph_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, GOG_TYPE_CONTROL_FOOCANVAS, 0,
-	GSF_INTERFACE (so_graph_foo_view_init, SHEET_OBJECT_VIEW_TYPE))
+
+typedef SheetObjectView		SOGraphGocView;
+typedef SheetObjectViewClass	SOGraphGocViewClass;
+
+static GSF_CLASS (SOGraphGocView, so_graph_goc_view,
+	so_graph_goc_view_class_init, NULL,
+	SHEET_OBJECT_VIEW_TYPE)
 
 /****************************************************************************/
 #define SHEET_OBJECT_CONFIG_KEY "sheet-object-graph-key"
@@ -162,10 +163,13 @@ gnm_sog_new_view (SheetObject *so, SheetObjectViewContainer *container)
 {
 	GnmPane *pane = GNM_PANE (container);
 	SheetObjectGraph *sog = SHEET_OBJECT_GRAPH (so);
-	FooCanvasItem *view = foo_canvas_item_new (pane->object_views,
-		so_graph_foo_view_get_type (),
-		"renderer",	sog->renderer,
+	GocItem *view = goc_item_new (pane->object_views,
+		so_graph_goc_view_get_type (),
 		NULL);
+	goc_item_new (GOC_GROUP (view),
+		      GOC_TYPE_GRAPH,
+		      "renderer", sog->renderer,
+		      NULL);
 	return gnm_pane_object_register (so, view, TRUE);
 }
 
diff --git a/src/sheet-object-image.c b/src/sheet-object-image.c
index 428fc82..14f724e 100644
--- a/src/sheet-object-image.c
+++ b/src/sheet-object-image.c
@@ -20,8 +20,6 @@
 #include "xml-io.h"
 
 #include <goffice/goffice.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-pixbuf.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-rect-ellipse.h>
 #include <gsf/gsf-impl-utils.h>
 #include <gsf/gsf-output-stdio.h>
 #include <gsf/gsf-utils.h>
@@ -53,7 +51,7 @@ so_image_view_destroy (SheetObjectView *sov)
 static void
 so_image_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
+	GocItem *view = GOC_ITEM (GOC_GROUP (sov)->children->data);
 	if (visible) {
 		double x, y, width, height;
 		double old_x1, old_y1, old_x2, old_y2, old_width, old_height;
@@ -64,11 +62,10 @@ so_image_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean v
 		width  = fabs (coords [2] - coords [0]);
 		height = fabs (coords [3] - coords [1]);
 
-		foo_canvas_item_get_bounds (view, &old_x1, &old_y1, &old_x2, &old_y2);
-		foo_canvas_item_set (view,
+		goc_item_get_bounds (view, &old_x1, &old_y1, &old_x2, &old_y2);
+		goc_item_set (view,
 			"x", x,			"y", y,
-			"width",  width,	"width_set",  (width > 0.),
-			"height", height,	"height_set", (height > 0.),
+			"width",  width,	"height", height,
 			NULL);
 
 		/* regenerate the image if necessary */
@@ -78,27 +75,26 @@ so_image_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean v
 		    (fabs (width - old_width) > 0.5 || fabs (height - old_height) > 0.5)) {
 			GdkPixbuf *newimage = go_pixbuf_tile (placeholder,
 				(guint)width, (guint)height);
-			foo_canvas_item_set (view, "pixbuf", newimage, NULL);
+			goc_item_set (view, "pixbuf", newimage, NULL);
 			g_object_unref (newimage);
 		}
 
-		foo_canvas_item_show (view);
+		goc_item_show (view);
 	} else
-		foo_canvas_item_hide (view);
+		goc_item_hide (view);
 }
 
 static void
-so_image_foo_view_init (SheetObjectViewIface *sov_iface)
+so_image_goc_view_class_init (SheetObjectViewClass *sov_klass)
 {
-	sov_iface->destroy	= so_image_view_destroy;
-	sov_iface->set_bounds	= so_image_view_set_bounds;
+	sov_klass->destroy	= so_image_view_destroy;
+	sov_klass->set_bounds	= so_image_view_set_bounds;
 }
-typedef FooCanvasPixbuf		SOImageFooView;
-typedef FooCanvasPixbufClass	SOImageFooViewClass;
-static GSF_CLASS_FULL (SOImageFooView, so_image_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, FOO_TYPE_CANVAS_PIXBUF, 0,
-	GSF_INTERFACE (so_image_foo_view_init, SHEET_OBJECT_VIEW_TYPE))
+typedef SheetObjectView	SOImageGocView;
+typedef SheetObjectViewClass	SOImageGocViewClass;
+static GSF_CLASS (SOImageGocView, so_image_goc_view,
+	so_image_goc_view_class_init, NULL,
+	SHEET_OBJECT_VIEW_TYPE)
 
 /****************************************************************************/
 struct _SheetObjectImage {
@@ -306,7 +302,7 @@ static SheetObjectView *
 gnm_soi_new_view (SheetObject *so, SheetObjectViewContainer *container)
 {
 	SheetObjectImage *soi = SHEET_OBJECT_IMAGE (so);
-	FooCanvasItem *item = NULL;
+	GocItem *item = NULL;
 	GdkPixbuf *pixbuf, *placeholder = NULL;
 
 	pixbuf = soi_get_pixbuf (soi, 1.);
@@ -318,12 +314,14 @@ gnm_soi_new_view (SheetObject *so, SheetObjectViewContainer *container)
 		pixbuf = gdk_pixbuf_copy (placeholder);
 	}
 
-	item = foo_canvas_item_new (
+	item = goc_item_new (
 		gnm_pane_object_group (GNM_PANE (container)),
-		so_image_foo_view_get_type (),
-		"pixbuf", pixbuf,
-		"visible", FALSE,
+		so_image_goc_view_get_type (),
 		NULL);
+	goc_item_hide (goc_item_new (GOC_GROUP (item),
+		GOC_TYPE_PIXBUF,
+		"pixbuf", pixbuf,
+		NULL));
 	g_object_unref (G_OBJECT (pixbuf));
 
 	if (placeholder)
diff --git a/src/sheet-object-impl.h b/src/sheet-object-impl.h
index c87812c..22f0710 100644
--- a/src/sheet-object-impl.h
+++ b/src/sheet-object-impl.h
@@ -5,6 +5,7 @@
 G_BEGIN_DECLS
 
 #include "sheet-object.h"
+#include <goffice/goffice.h>
 #include <gsf/gsf-libxml.h>
 #include <libxml/tree.h>
 #include <glib-object.h>
@@ -105,21 +106,27 @@ typedef struct {
 
 /***************************************************************************/
 
+struct _SheetObjectView {
+	GocGroup base;
+
+	GnmSOResizeMode resize_mode;
+};
+
 typedef struct {
-	GTypeInterface base;
+	GocGroupClass base;
 
 	void (*destroy)    (SheetObjectView *sov);
 	void (*active)	   (SheetObjectView *sov, gboolean is_active);
 	void (*set_bounds) (SheetObjectView *sov,
 			    double const *coords, gboolean visible);
-} SheetObjectViewIface;
+} SheetObjectViewClass;
 
 #define SHEET_OBJECT_VIEW_TYPE		(sheet_object_view_get_type ())
 #define SHEET_OBJECT_VIEW(o)		(G_TYPE_CHECK_INSTANCE_CAST((o), SHEET_OBJECT_VIEW_TYPE, SheetObjectView))
 #define IS_SHEET_OBJECT_VIEW(o)		(G_TYPE_CHECK_INSTANCE_TYPE((o), SHEET_OBJECT_VIEW_TYPE))
 #define SHEET_OBJECT_VIEW_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), SHEET_OBJECT_VIEW_TYPE, SheetObjectViewIface))
 #define IS_SHEET_OBJECT_VIEW_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE((k), SHEET_OBJECT_VIEW_TYPE))
-#define SHEET_OBJECT_VIEW_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_INTERFACE ((o), SHEET_OBJECT_VIEW_TYPE, SheetObjectViewIface))
+#define SHEET_OBJECT_VIEW_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), SHEET_OBJECT_VIEW_TYPE, SheetObjectViewClass))
 
 GType	     sheet_object_view_get_type	  (void);
 SheetObject *sheet_object_view_get_so	  (SheetObjectView *sov);
diff --git a/src/sheet-object-widget.c b/src/sheet-object-widget.c
index c004152..5ee7487 100644
--- a/src/sheet-object-widget.c
+++ b/src/sheet-object-widget.c
@@ -23,7 +23,7 @@
 #include <gnumeric-config.h>
 #include <glib/gi18n-lib.h>
 #include "gnumeric.h"
-#include "sheet-object-widget.h"
+#include "sheet-object-widget-impl.h"
 
 #include "gnm-pane.h"
 #include "gnumeric-simple-canvas.h"
@@ -52,7 +52,6 @@
 
 #include <gsf/gsf-impl-utils.h>
 #include <libxml/globals.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-widget.h>
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
 #include <math.h>
@@ -123,16 +122,18 @@ so_clear_sheet (SheetObject *so)
 static void
 so_widget_view_destroy (SheetObjectView *sov)
 {
-	gtk_object_destroy (GTK_OBJECT (sov));
+	g_object_unref (G_OBJECT (sov));
 }
+
 static void
 so_widget_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
-	double left = MIN (coords [0], coords [2]);
-	double top = MIN (coords [1], coords [3]);
-	double width = fabs (coords [2] - coords [0]) + 1.;
-	double height = fabs (coords [3] - coords [1]) + 1.;
+	GocItem *view = GOC_ITEM (sov);
+	double scale = goc_canvas_get_pixels_per_unit (view->canvas); 
+	double left = MIN (coords [0], coords [2]) / scale;
+	double top = MIN (coords [1], coords [3]) / scale;
+	double width = (fabs (coords [2] - coords [0]) + 1.) / scale;
+	double height = (fabs (coords [3] - coords [1]) + 1.) / scale;
 
 	/* We only need the next check for frames, but it doesn't hurt otherwise. */
 	if (width < 8.)
@@ -140,29 +141,23 @@ so_widget_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean
 
 	if (visible) {
 		/* NOTE : far point is EXCLUDED so we add 1 */
-		foo_canvas_item_set (view,
-			"x",	  left,
-			"y",	  top,
-			"width",  width,
-			"height", height,
-			NULL);
-		foo_canvas_item_show (view);
+		goc_widget_set_bounds (GOC_WIDGET (GOC_GROUP (view)->children->data),
+			left, top, width, height);
+		goc_item_show (view);
 	} else
-		foo_canvas_item_hide (view);
+		goc_item_hide (view);
 }
 
 static void
-so_widget_foo_view_init (SheetObjectViewIface *sov_iface)
+so_widget_view_class_init (SheetObjectViewClass *sov_klass)
 {
-	sov_iface->destroy	= so_widget_view_destroy;
-	sov_iface->set_bounds	= so_widget_view_set_bounds;
+	sov_klass->destroy	= so_widget_view_destroy;
+	sov_klass->set_bounds	= so_widget_view_set_bounds;
 }
-typedef FooCanvasWidget		SOWidgetFooView;
-typedef FooCanvasWidgetClass	SOWidgetFooViewClass;
-static GSF_CLASS_FULL (SOWidgetFooView, so_widget_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, FOO_TYPE_CANVAS_WIDGET, 0,
-	GSF_INTERFACE (so_widget_foo_view_init, SHEET_OBJECT_VIEW_TYPE))
+
+static GSF_CLASS (SOWidgetView, so_widget_view,
+	so_widget_view_class_init, NULL,
+	SHEET_OBJECT_VIEW_TYPE)
 
 /****************************************************************************/
 
@@ -278,15 +273,17 @@ sheet_object_widget_new_view (SheetObject *so, SheetObjectViewContainer *contain
 {
 	GtkWidget *view_widget =
 		SOW_CLASS(so)->create_widget (SHEET_OBJECT_WIDGET (so));
-	FooCanvasItem *view_item = foo_canvas_item_new (
+	GocItem *view_item = goc_item_new (
 		gnm_pane_object_group (GNM_PANE (container)),
-		so_widget_foo_view_get_type (),
-		"widget", view_widget,
-		"size_pixels", FALSE,
+		so_widget_view_get_type (),
 		NULL);
+	goc_item_new (GOC_GROUP (view_item),
+		      GOC_TYPE_WIDGET,
+		      "widget", view_widget,
+		      NULL);
 	/* g_warning ("%p is widget for so %p", (void *)view_widget, (void *)so);*/
 	gtk_widget_show_all (view_widget);
-	foo_canvas_item_hide (view_item);
+	goc_item_hide (view_item);
 	gnm_pane_widget_register (so, view_widget, view_item);
 	return gnm_pane_object_register (so, view_item, TRUE);
 }
@@ -467,7 +464,7 @@ sheet_widget_frame_set_label (SheetObject *so, char const* str)
 	swf->label = g_strdup (str);
 
 	for (ptr = swf->sow.realized_list; ptr != NULL; ptr = ptr->next) {
-		FooCanvasWidget *item = FOO_CANVAS_WIDGET (ptr->data);
+		GocWidget *item = GOC_WIDGET (ptr->data);
 		gtk_frame_set_label (GTK_FRAME (item->widget), str);
 	}
 }
@@ -677,7 +674,7 @@ sheet_widget_button_set_label (SheetObject *so, char const *str)
 	swb->label = new_label;
 
 	for (ptr = swb->sow.realized_list; ptr != NULL; ptr = ptr->next) {
-		FooCanvasWidget *item = FOO_CANVAS_WIDGET (ptr->data);
+		GocWidget *item = GOC_WIDGET (ptr->data);
 		gtk_button_set_label (GTK_BUTTON (item->widget), swb->label);
 	}
 }
@@ -696,7 +693,7 @@ sheet_widget_button_set_markup (SheetObject *so, PangoAttrList *markup)
 	if (markup) pango_attr_list_ref (markup);
 
 	for (ptr = swb->sow.realized_list; ptr != NULL; ptr = ptr->next) {
-		FooCanvasWidget *item = FOO_CANVAS_WIDGET (ptr->data);
+		GocWidget *item = GOC_WIDGET (ptr->data);
 		gtk_label_set_attributes (GTK_LABEL (GTK_BIN (item->widget)->child),
 					  swb->markup);
 	}
@@ -901,11 +898,11 @@ sheet_widget_adjustment_set_horizontal (SheetWidgetAdjustment *swa,
 
 	/* Change direction for all realized widgets.  */
 	for (ptr = swa->sow.realized_list; ptr != NULL; ptr = ptr->next) {
-		FooCanvasItem *item = FOO_CANVAS_ITEM (ptr->data);
+		GocItem *item = GOC_ITEM (ptr->data);
 		GtkWidget *neww =
 			SOW_CLASS (swa)->create_widget (SHEET_OBJECT (swa));
 		gtk_widget_show (neww);
-		foo_canvas_item_set (item, "widget", neww, NULL);
+		goc_item_set (item, "widget", neww, NULL);
 	}
 }
 
@@ -1583,7 +1580,7 @@ sheet_widget_checkbox_set_active (SheetWidgetCheckbox *swc)
 
 	ptr = swc->sow.realized_list;
 	for (; ptr != NULL ; ptr = ptr->next) {
-		FooCanvasWidget *item = FOO_CANVAS_WIDGET (ptr->data);
+		GocWidget *item = GOC_WIDGET (GOC_GROUP (ptr->data)->children->data);
 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item->widget),
 					      swc->value);
 	}
@@ -1975,7 +1972,7 @@ sheet_widget_checkbox_set_label	(SheetObject *so, char const *str)
 
 	list = swc->sow.realized_list;
 	for (; list != NULL; list = list->next) {
-		FooCanvasWidget *item = FOO_CANVAS_WIDGET (list->data);
+		GocWidget *item = GOC_WIDGET (list->data);
 		gtk_button_set_label (GTK_BUTTON (item->widget), swc->label);
 	}
 }
@@ -2154,7 +2151,7 @@ sheet_widget_radio_button_set_label (SheetObject *so, char const *str)
 
 	list = swrb->sow.realized_list;
 	for (; list != NULL; list = list->next) {
-		FooCanvasWidget *item = FOO_CANVAS_WIDGET (list->data);
+		GocWidget *item = GOC_WIDGET (list->data);
 		gtk_button_set_label (GTK_BUTTON (item->widget), swrb->label);
 	}
 }
diff --git a/src/sheet-object.c b/src/sheet-object.c
index ad5d23b..17a42a5 100644
--- a/src/sheet-object.c
+++ b/src/sheet-object.c
@@ -17,13 +17,16 @@
 #include "dependent.h"
 #include "sheet-view.h"
 #include "sheet-control.h"
+#include "sheet-control-gui.h"
 #include "sheet-private.h"
 #include "dialogs.h"
 #include "sheet-object-impl.h"
 #include "expr.h"
 #include "ranges.h"
 #include "commands.h"
+#include "gui-util.h"
 
+#include "gnm-pane-impl.h"
 #include "gnm-so-line.h"
 #include "gnm-so-filled.h"
 #include "sheet-object-cell-comment.h"
@@ -36,7 +39,6 @@
 #include "gutils.h"
 
 #include <libxml/globals.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
 #include <gsf/gsf-impl-utils.h>
 
 #include <string.h>
@@ -1077,11 +1079,11 @@ sheet_object_adjust_stacking (SheetObject *so, gint offset)
 
 	/* TODO : Move this to the container */
 	for (l = so->realized_list; l; l = l->next) {
-		FooCanvasItem *item = FOO_CANVAS_ITEM (l->data);
+		GocItem *item = GOC_ITEM (l->data);
 		if (offset > 0)
-			foo_canvas_item_raise (item, offset);
+			goc_item_raise (item, offset);
 		else
-			foo_canvas_item_lower (item, - offset);
+			goc_item_lower (item, - offset);
 	}
 	return cur - i;
 }
@@ -1092,12 +1094,12 @@ void
 sheet_object_view_set_bounds (SheetObjectView *sov,
 			      double const *coords, gboolean visible)
 {
-	SheetObjectViewIface *iface;
+	SheetObjectViewClass *klass;
 
 	g_return_if_fail (IS_SHEET_OBJECT_VIEW (sov));
-	iface = SHEET_OBJECT_VIEW_GET_CLASS (sov);
-	if (NULL != iface->set_bounds)
-		(iface->set_bounds) (sov, coords, visible);
+	klass = SHEET_OBJECT_VIEW_GET_CLASS (sov);
+	if (NULL != klass->set_bounds)
+		(klass->set_bounds) (sov, coords, visible);
 }
 
 SheetObject *
@@ -1106,34 +1108,72 @@ sheet_object_view_get_so (SheetObjectView *view)
 	return g_object_get_qdata (G_OBJECT (view), sov_so_quark);
 }
 
-void
-sheet_object_view_destroy (SheetObjectView *sov)
+static gboolean
+sheet_object_view_enter_notify (GocItem *item, double x, double y)
 {
-	SheetObjectViewIface *iface = SHEET_OBJECT_VIEW_GET_CLASS (sov);
-	g_return_if_fail (iface != NULL);
-	if (iface->destroy)
-		iface->destroy (sov);
+	SheetObject *so = (SheetObject *) g_object_get_qdata (G_OBJECT (item), sov_so_quark);
+	gnm_widget_set_cursor_type (GTK_WIDGET (item->canvas),
+		(so->flags & SHEET_OBJECT_CAN_PRESS) ? GDK_HAND2 : GDK_ARROW);
+	return FALSE;
 }
 
-GType
-sheet_object_view_get_type (void)
+static gboolean
+sheet_object_view_button_pressed (GocItem *item, int button, double x, double y)
 {
-	static GType type = 0;
+	GnmPane *pane;
+	SheetObject *so;
 
-	if (!type) {
-		static GTypeInfo const type_info = {
-			sizeof (SheetObjectViewIface),	/* class_size */
-			NULL,				/* base_init */
-			NULL,				/* base_finalize */
-		};
+	if (button > 3)
+		return FALSE;
 
-		type = g_type_register_static (G_TYPE_INTERFACE,
-			"SheetObjectView", &type_info, 0);
+	pane = GNM_PANE (item->canvas);
+	so = (SheetObject *) g_object_get_qdata (G_OBJECT (item), sov_so_quark);
+
+	x *= goc_canvas_get_pixels_per_unit (item->canvas);
+	y *= goc_canvas_get_pixels_per_unit (item->canvas);
+	/* cb_sheet_object_widget_canvas_event calls even if selected */
+	if (NULL == g_hash_table_lookup (pane->drag.ctrl_pts, so)) {
+		SheetObjectClass *soc =
+			G_TYPE_INSTANCE_GET_CLASS (so, SHEET_OBJECT_TYPE, SheetObjectClass);
+		GdkEventButton *event = (GdkEventButton *) goc_canvas_get_cur_event (item->canvas);
+
+		if (soc->interactive && button != 3)
+			return FALSE;
+
+		if (!(event->state & GDK_SHIFT_MASK))
+			scg_object_unselect (pane->simple.scg, NULL);
+		scg_object_select (pane->simple.scg, so);
+		if (NULL == g_hash_table_lookup (pane->drag.ctrl_pts, so))
+			return FALSE;	/* protected ? */
 	}
 
-	return type;
+	if (button < 3)
+		gnm_pane_object_start_resize (pane, button, x, y, so, 8, FALSE);
+	else
+		gnm_pane_display_object_menu (pane, so, goc_canvas_get_cur_event (item->canvas));
+	return TRUE;
 }
 
+void
+sheet_object_view_destroy (SheetObjectView *sov)
+{
+	SheetObjectViewClass *klass = SHEET_OBJECT_VIEW_GET_CLASS (sov);
+	g_return_if_fail (klass != NULL);
+	if (klass->destroy)
+		klass->destroy (sov);
+}
+
+static void
+sheet_object_view_class_init (GocItemClass *item_klass)
+{
+	item_klass->enter_notify = sheet_object_view_enter_notify;
+	item_klass->button_pressed = sheet_object_view_button_pressed;
+}
+
+GSF_CLASS (SheetObjectView, sheet_object_view,
+	   sheet_object_view_class_init, NULL,
+	   GOC_TYPE_GROUP)
+
 /*****************************************************************************/
 
 GType
diff --git a/src/sheet-object.h b/src/sheet-object.h
index c166ada..02c35ba 100644
--- a/src/sheet-object.h
+++ b/src/sheet-object.h
@@ -31,6 +31,12 @@ typedef struct _GODrawingAnchor {
 } GODrawingAnchor;
 /***********************************************************/
 
+typedef enum {
+	GNM_SO_RESIZE_MANUAL,   /* can be manually resized */
+	GNM_SO_RESIZE_AUTO, /* automatically resized like cell bounded widgets */
+	GNM_SO_RESIZE_NONE /* can't be resized like some sheen components */
+} GnmSOResizeMode;
+
 struct _SheetObjectAnchor {
 	GODrawingAnchor	base;
 
diff --git a/src/style-border.c b/src/style-border.c
index f8bfa39..0d3e66d 100644
--- a/src/style-border.c
+++ b/src/style-border.c
@@ -579,105 +579,6 @@ style_border_vmargins (GnmBorder const * const * prev_vert,
 	return FALSE;
 }
 
-/**
- * gnm_style_borders_row_draw :
- *
- * TODO : This is not the final resting place for this.
- * It will move into the gui layer eventually.
- */
-void
-gnm_style_borders_row_draw (GnmBorder const * const * prev_vert,
-			    GnmStyleRow const *sr,
-			    GdkDrawable * const drawable,
-			    int x, int y1, int y2,
-			    int *colwidths,
-			    gboolean draw_vertical, int dir)
-{
-	int o[2][2];
-	int col, next_x = x;
-	GdkGC *gc;
-
-	for (col = sr->start_col; col <= sr->end_col ; col++, x = next_x) {
-
-		if (colwidths[col] == -1)
-			continue;
-		next_x = x + dir * colwidths[col];
-
-		gc = style_border_get_gc (sr->top [col], drawable);
-		if (gc != NULL) {
-			int y = y1;
-			if (style_border_hmargins (prev_vert, sr, col, o, dir)) {
-				gdk_draw_line (drawable, gc, x + o[1][0], y1-1,
-					       next_x + o[1][1] + dir, y1-1);
-				++y;
-			}
-
-			/* See note in gnm_style_border_set_gc_dash about +1 */
-			gdk_draw_line (drawable, gc, x + o[0][0], y,
-				       next_x + o[0][1] + dir, y);
-		}
-
-		if (!draw_vertical)
-			continue;
-
-		gc = style_border_get_gc (sr->vertical [col], drawable);
-		if (gc != NULL) {
-			int x1 = x;
-			if (style_border_vmargins (prev_vert, sr, col, o)) {
-				gdk_draw_line (drawable, gc, x-dir, y1 + o[1][0],
-					       x-dir, y2 + o[1][1] + 1);
-				x1 += dir;
-			}
-			/* See note in gnm_style_border_set_gc_dash about +1 */
-			gdk_draw_line (drawable, gc, x1, y1 + o[0][0],
-				       x1, y2 + o[0][1] + 1);
-		}
-	}
-	if (draw_vertical) {
-		gc = style_border_get_gc (sr->vertical [col], drawable);
-		if (gc != NULL) {
-			int x1 = x;
-			if (style_border_vmargins (prev_vert, sr, col, o)) {
-				gdk_draw_line (drawable, gc, x-dir, y1 + o[1][0],
-					       x-dir, y2 + o[1][1] + 1);
-				x1 += dir;
-			}
-			/* See note in gnm_style_border_set_gc_dash about +1 */
-			gdk_draw_line (drawable, gc, x1, y1 + o[0][0],
-				       x1, y2 + o[0][1] + 1);
-		}
-	}
-}
-
-void
-gnm_style_border_draw_diag (GnmStyle const *style,
-			    GdkDrawable *drawable,
-			    int x1, int y1, int x2, int y2)
-{
-	GnmBorder const *diag;
-	GdkGC *gc;
-
-	diag = gnm_style_get_border (style, MSTYLE_BORDER_REV_DIAGONAL);
-	if (diag != NULL && diag->line_type != GNM_STYLE_BORDER_NONE) {
-		gc = style_border_get_gc (diag, drawable);
-		if (diag->line_type == GNM_STYLE_BORDER_DOUBLE) {
-			gdk_draw_line (drawable, gc, x1+1, y1+3, x2-3, y2-1);
-			gdk_draw_line (drawable, gc, x1+3, y1+1, x2-1, y2-3);
-		} else
-			gdk_draw_line (drawable, gc, x1, y1, x2, y2);
-	}
-
-	diag = gnm_style_get_border (style, MSTYLE_BORDER_DIAGONAL);
-	if (diag != NULL && diag->line_type != GNM_STYLE_BORDER_NONE) {
-		gc = style_border_get_gc (diag, drawable);
-		if (diag->line_type == GNM_STYLE_BORDER_DOUBLE) {
-			gdk_draw_line (drawable, gc, x1+1, y2-3, x2-3, y1+1);
-			gdk_draw_line (drawable, gc, x1+3, y2-1, x2-1, y1+3);
-		} else
-			gdk_draw_line (drawable, gc, x1, y2, x2, y1);
-	}
-}
-
 static void
 style_border_set_gtk_dash (GnmStyleBorderType const i,
 			   cairo_t *context)
@@ -747,6 +648,127 @@ print_vline_gtk (cairo_t *context,
 	cairo_stroke (context);
 }
 
+/**
+ * gnm_style_borders_row_draw :
+ *
+ * TODO : This is not the final resting place for this.
+ * It will move into the gui layer eventually.
+ */
+void
+gnm_style_borders_row_draw (GnmBorder const * const * prev_vert,
+			    GnmStyleRow const *sr,
+			    cairo_t *cr,
+			    int x, int y1, int y2,
+			    int *colwidths,
+			    gboolean draw_vertical, int dir)
+{
+	int o[2][2];
+	int col, next_x = x;
+	GnmBorder const *border;
+
+	cairo_save (cr);
+
+	for (col = sr->start_col; col <= sr->end_col ; col++, x = next_x) {
+
+		if (colwidths[col] == -1)
+			continue;
+		next_x = x + dir * colwidths[col];
+
+		border = sr->top [col];
+
+		if (style_border_set_gtk (border, cr)) {
+			float y = y1;
+			if (style_border_hmargins (prev_vert, sr, col, o, dir)) {
+				print_hline_gtk (cr, x + o[1][0],
+						 next_x + o[1][1] + dir, y1-1.,
+						 border->width);
+				++y;
+			}
+
+			/* See note in gnm_style_border_set_gc_dash about +1 */
+			print_hline_gtk (cr, x + o[0][0],
+					 next_x + o[0][1] + dir, y, border->width);
+		}
+
+		if (!draw_vertical)
+			continue;
+
+
+		border = sr->vertical [col];
+		if (style_border_set_gtk (border, cr)) {
+			float x1 = x;
+			if (style_border_vmargins (prev_vert, sr, col, o)) {
+				print_vline_gtk (cr, x-dir, y1 + o[1][0],
+						 y2 + o[1][1] + 1., border->width, dir);
+				x1 += dir;
+			}
+			/* See note in gnm_style_border_set_gc_dash about +1 */
+			print_vline_gtk (cr, x1, y1 + o[0][0],
+					 y2 + o[0][1] + 1., border->width, dir);
+		}
+	}
+	if (draw_vertical) {
+		border = sr->vertical [col];
+		if (style_border_set_gtk (border, cr)) {
+			float x1 = x;
+			if (style_border_vmargins (prev_vert, sr, col, o)) {
+				print_vline_gtk (cr, x-dir, y1 + o[1][0] + 1.,
+						 y2 + o[1][1], border->width, dir);
+				x1 += dir;
+			}
+			/* See note in gnm_style_border_set_gc_dash about +1 */
+			print_vline_gtk (cr, x1, y1 + o[0][0],
+					 y2 + o[0][1] + 1, border->width, dir);
+		}
+	}
+
+	cairo_restore (cr);
+}
+
+void
+gnm_style_border_draw_diag (GnmStyle const *style,
+			    cairo_t *cr,
+			    int x1, int y1, int x2, int y2)
+{
+	GnmBorder const *diag;
+
+	cairo_save (cr);
+
+	diag = gnm_style_get_border (style, MSTYLE_BORDER_REV_DIAGONAL);
+	if (diag != NULL && diag->line_type != GNM_STYLE_BORDER_NONE) {
+		style_border_set_gtk (diag, cr);
+		if (diag->line_type == GNM_STYLE_BORDER_DOUBLE) {
+			cairo_move_to (cr, x1+1.5,  y1+3.);
+			cairo_line_to (cr, x2-2.,   y2- .5);
+			cairo_stroke (cr);
+			cairo_move_to (cr, x1+ 3.,  y1+1.5);
+			cairo_line_to (cr, x2-  .5, y2-2.);
+		} else {
+			cairo_move_to (cr, x1+.5, y1+.5);
+			cairo_line_to (cr, x2+.5, y2+.5);
+		}
+		cairo_stroke (cr);
+	}
+
+	diag = gnm_style_get_border (style, MSTYLE_BORDER_DIAGONAL);
+	if (diag != NULL && diag->line_type != GNM_STYLE_BORDER_NONE) {
+		style_border_set_gtk (diag, cr);
+		if (diag->line_type == GNM_STYLE_BORDER_DOUBLE) {
+			cairo_move_to (cr, x1+1.5, y2-2.);
+			cairo_line_to (cr, x2-2.,  y1+1.5);
+			cairo_stroke (cr);
+			cairo_move_to (cr, x1+3.,  y2- .5);
+			cairo_line_to (cr, x2- .5, y1+3.);
+		} else {
+			cairo_move_to (cr, x1+.5, y2+.5);
+			cairo_line_to (cr, x2+.5, y1+.5);
+		}
+		cairo_stroke (cr);
+	}
+
+	cairo_restore (cr);
+}
+
 void
 gnm_style_borders_row_print_gtk (GnmBorder const * const * prev_vert,
 				 GnmStyleRow const *sr,
diff --git a/src/style-border.h b/src/style-border.h
index c94c8fc..c579cbb 100644
--- a/src/style-border.h
+++ b/src/style-border.h
@@ -86,12 +86,12 @@ void   gnm_style_border_set_gc_dash (GdkGC *gc,
 
 void gnm_style_borders_row_draw (GnmBorder const * const * prev_vert,
 				 GnmStyleRow const *sr,
-				 GdkDrawable *drawable,
+				 cairo_t *cr,
 				 int x, int y1, int y2,
 				 int *colwidths,
 				 gboolean draw_vertical, int dir);
 void gnm_style_border_draw_diag  (GnmStyle const *style,
-				  GdkDrawable *drawable,
+				  cairo_t *cr,
 				  int x1, int y1, int x2, int y2);
 
 void gnm_style_borders_row_print_gtk (GnmBorder const * const * prev_vert,
diff --git a/src/style-color.c b/src/style-color.c
index f81f9f7..9cef5d6 100644
--- a/src/style-color.c
+++ b/src/style-color.c
@@ -44,7 +44,7 @@ style_color_new_uninterned (gushort red, gushort green, gushort blue,
 	sc->gdk_color.green = green;
 	sc->gdk_color.blue = blue;
 	sc->gdk_color.pixel = gs_white.pixel;
-	sc->go_color = RGBA_TO_UINT (red>>8,green>>8,blue>>8,0);
+	sc->go_color = RGBA_TO_UINT (red>>8,green>>8,blue>>8,0xff);
 	sc->name = NULL;
 	sc->is_auto = is_auto;
 
diff --git a/src/validation.c b/src/validation.c
index 0e7bcf2..64367af 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -38,8 +38,8 @@
 
 #include "sheet-view.h"
 #include "sheet-object.h"
-#include "gnm-validation-combo-foo-view.h"
-#include "gnm-cell-combo-foo-view.h"
+#include "gnm-validation-combo-view.h"
+#include "gnm-cell-combo-view.h"
 #include <gsf/gsf-impl-utils.h>
 
 #include <glib/gi18n-lib.h>
@@ -103,10 +103,10 @@ gnm_validation_combo_init (SheetObject *so)
 }
 
 static SheetObjectView *
-gnm_validation_combo_foo_view_new (SheetObject *so, SheetObjectViewContainer *container)
+gnm_validation_combo_view_new (SheetObject *so, SheetObjectViewContainer *container)
 {
-	return gnm_cell_combo_foo_view_new (so,
-		gnm_validation_combo_foo_view_get_type (), container);
+	return gnm_cell_combo_view_new (so,
+		gnm_validation_combo_view_get_type (), container);
 }
 
 static void
@@ -114,7 +114,7 @@ gnm_validation_combo_class_init (GObjectClass *gobject_class)
 {
 	SheetObjectClass *so_class = SHEET_OBJECT_CLASS (gobject_class);
 	gobject_class->finalize	= gnm_validation_combo_finalize;
-	so_class->new_view	  = gnm_validation_combo_foo_view_new;
+	so_class->new_view = gnm_validation_combo_view_new;
 
 	gvc_parent_klass = g_type_class_peek_parent (gobject_class);
 }
diff --git a/src/wbc-gtk-edit.c b/src/wbc-gtk-edit.c
index 42c9370..328071d 100644
--- a/src/wbc-gtk-edit.c
+++ b/src/wbc-gtk-edit.c
@@ -331,9 +331,9 @@ workbook_edit_complete_notify (char const *text, void *closure)
 	g_free (wbcg->auto_complete_text);
 	wbcg->auto_complete_text = g_strdup (text);
 
-	SCG_FOREACH_PANE (scg, pane,
+/*	SCG_FOREACH_PANE (scg, pane,
 		if (pane->editor != NULL)
-			foo_canvas_item_request_update (FOO_CANVAS_ITEM (pane->editor)););
+			foo_canvas_item_request_update (FOO_CANVAS_ITEM (pane->editor)););*/
 }
 
 static void
@@ -493,10 +493,10 @@ cb_entry_delete_text (GtkEditable    *editable,
 	if (wbcg->auto_completing) {
 		SheetControlGUI *scg = wbcg_cur_scg (wbcg);
 		wbcg_auto_complete_destroy (wbcg);
-		if (scg)
+/*		if (scg)
 			SCG_FOREACH_PANE (scg, pane,
 					  if (pane->editor != NULL)
-					  foo_canvas_item_request_update (FOO_CANVAS_ITEM (pane->editor)););
+					  foo_canvas_item_request_update (FOO_CANVAS_ITEM (pane->editor)););*/
 	}
 
 	if (wbcg->edit_line.full_content) {
diff --git a/src/widgets/ChangeLog b/src/widgets/ChangeLog
index ed43618..4645151 100644
--- a/src/widgets/ChangeLog
+++ b/src/widgets/ChangeLog
@@ -1,3 +1,51 @@
+2009-08-25  Jean Brefort  <jean brefort normalesup org>
+
+	reviewed by: <delete if not using a buddy>
+
+	* Makefile.am:
+	* gnm-cell-combo-foo-view-impl.h:
+	* gnm-cell-combo-foo-view.c:
+	* gnm-cell-combo-foo-view.h:
+	* gnm-cell-combo-view-impl.h:
+	* gnm-cell-combo-view.c (ccombo_create_arrow), (ccombo_activate),
+	(ccombo_create_list), (ccombo_focus_change),
+	(cb_ccombo_autoscroll), (ccombo_autoscroll_set),
+	(ccombo_popup_destroy), (cb_ccombo_key_press),
+	(cb_ccombo_popup_motion), (cb_ccombo_list_motion),
+	(cb_ccombo_list_button_press), (cb_ccombo_button_press),
+	(cb_ccombo_button_release), (cb_ccombo_button_pressed),
+	(gnm_cell_combo_view_popdown), (gnm_cell_combo_view_new),
+	(gnm_cell_combo_view_init):
+	* gnm-cell-combo-view.h:
+	* gnm-filter-combo-foo-view.c:
+	* gnm-filter-combo-foo-view.h:
+	* gnm-filter-combo-view.c (fcombo_activate), (cb_collect_content),
+	(cb_hash_domain), (formatted_value_equal), (fcombo_create_list),
+	(fcombo_arrow_format), (fcombo_create_arrow),
+	(filter_view_set_bounds), (gnm_filter_view_class_init):
+	* gnm-filter-combo-view.h:
+	* gnm-sheet-slicer-combo-foo-view.c:
+	* gnm-sheet-slicer-combo-foo-view.h:
+	* gnm-sheet-slicer-combo-view.c (sscombo_activate),
+	(cb_filter_toggle), (sscombo_create_list), (sscombo_create_arrow),
+	(sscombo_set_bounds), (sscombo_class_init):
+	* gnm-sheet-slicer-combo-view.h:
+	* gnm-validation-combo-foo-view.c:
+	* gnm-validation-combo-foo-view.h:
+	* gnm-validation-combo-view.c (vcombo_activate),
+	(cb_collect_unique), (cb_hash_domain), (vcombo_create_list),
+	(vcombo_create_arrow), (vcombo_set_bounds),
+	(gnm_validation_view_class_init):
+	* gnm-validation-combo-view.h:
+	* gnumeric-dashed-canvas-line.c (double_line_draw),
+	(gnumeric_dashed_canvas_line_draw),
+	(gnumeric_dashed_canvas_line_class_init),
+	(gnumeric_dashed_canvas_line_set_dash_index):
+	* gnumeric-dashed-canvas-line.h:
+	* widget-font-selector.c (fs_modify_style), (canvas_size_changed),
+	(fs_init), (font_selector_set_value):
+	* widget-font-selector.h:
+
 2009-08-15  Morten Welinder <terra gnome org>
 
 	* Release 1.9.10
diff --git a/src/widgets/Makefile.am b/src/widgets/Makefile.am
index e18700a..0343bb1 100644
--- a/src/widgets/Makefile.am
+++ b/src/widgets/Makefile.am
@@ -19,15 +19,15 @@ libwidgets_la_SOURCES =				\
 	widget-editable-label.h			\
 	widget-font-selector.c			\
 	widget-font-selector.h			\
-	gnm-cell-combo-foo-view.c		\
-	gnm-cell-combo-foo-view.h		\
-	gnm-cell-combo-foo-view-impl.h		\
-	gnm-filter-combo-foo-view.c		\
-	gnm-filter-combo-foo-view.h		\
-	gnm-validation-combo-foo-view.c		\
-	gnm-validation-combo-foo-view.h		\
-	gnm-sheet-slicer-combo-foo-view.c	\
-	gnm-sheet-slicer-combo-foo-view.h	\
+	gnm-cell-combo-view.c		\
+	gnm-cell-combo-view.h		\
+	gnm-cell-combo-view-impl.h		\
+	gnm-filter-combo-view.c		\
+	gnm-filter-combo-view.h		\
+	gnm-validation-combo-view.c		\
+	gnm-validation-combo-view.h		\
+	gnm-sheet-slicer-combo-view.c	\
+	gnm-sheet-slicer-combo-view.h	\
 	gnumeric-cell-renderer-text.c		\
 	gnumeric-cell-renderer-text.h		\
 	gnumeric-cell-renderer-expr-entry.c	\
diff --git a/src/widgets/gnm-cell-combo-view-impl.h b/src/widgets/gnm-cell-combo-view-impl.h
new file mode 100644
index 0000000..2e34b92
--- /dev/null
+++ b/src/widgets/gnm-cell-combo-view-impl.h
@@ -0,0 +1,28 @@
+#ifndef GNM_CELL_COMBO_VIEW_IMPL_H
+#define GNM_CELL_COMBO_VIEW_IMPL_H
+
+#include "gui-gnumeric.h"
+#include "sheet-object-impl.h"
+#include <gtk/gtk.h>
+
+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);
+	GtkWidget *	(*create_arrow) (SheetObject *so);
+} GnmCComboViewClass;
+
+#define GNM_CCOMBO_VIEW_TYPE	 (gnm_ccombo_view_get_type ())
+#define GNM_CCOMBO_VIEW(o)		 (G_TYPE_CHECK_INSTANCE_CAST((o), GNM_CCOMBO_VIEW_TYPE, GnmCComboView))
+#define IS_GNM_CCOMBO_VIEW(o)	 (G_TYPE_CHECK_INSTANCE_TYPE((o), GNM_CCOMBO_VIEW_TYPE))
+#define GNM_CCOMBO_VIEW_CLASS(k)	 (G_TYPE_CHECK_CLASS_CAST((k), GNM_CCOMBO_CComboViewClass))
+#define IS_GNM_CCOMBO_VIEW_CLASS(k)	 (G_TYPE_CHECK_CLASS_TYPE((k), GNM_CCOMBO_VIEW_TYPE))
+#define GNM_CCOMBO_VIEW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GNM_CCOMBO_VIEW_TYPE, GnmCComboViewClass))
+
+GType gnm_ccombo_view_get_type (void);
+
+#endif /* GNM_CELL_COMBO_VIEW_IMPL_H */
+
diff --git a/src/widgets/gnm-cell-combo-foo-view.c b/src/widgets/gnm-cell-combo-view.c
similarity index 86%
rename from src/widgets/gnm-cell-combo-foo-view.c
rename to src/widgets/gnm-cell-combo-view.c
index 6eb08ad..3dc38e4 100644
--- a/src/widgets/gnm-cell-combo-foo-view.c
+++ b/src/widgets/gnm-cell-combo-view.c
@@ -1,7 +1,7 @@
 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
 /*
- * gnm-cell-combo-foo-view.c: A foocanvas object for an in-cell combo-box
+ * gnm-cell-combo-view.c: A canvas object for an in-cell combo-box
  *
  * Copyright (C) 2006-2007 Jody Goldberg (jody gnome org)
  *
@@ -21,19 +21,19 @@
  */
 
 #include <gnumeric-config.h>
-#include "gnm-cell-combo-foo-view.h"
-#include "gnm-cell-combo-foo-view-impl.h"
+#include "gnm-cell-combo-view.h"
+#include "gnm-cell-combo-view-impl.h"
 
 #include "wbc-gtk.h"
 #include "sheet.h"
 #include "sheet-control-gui.h"
 #include "gnm-pane-impl.h"
-#include "sheet-object-impl.h"
 
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-widget.h>
+#include <goffice/goffice.h>
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
+#include <gsf/gsf-impl-utils.h>
 
 #define	SOV_ID		"sov"
 #define	AUTOSCROLL_ID	"autoscroll-id"
@@ -42,21 +42,21 @@
 static void ccombo_popup_destroy (GtkWidget *popup, GtkWidget *list);
 
 static GtkWidget *
-ccombo_create_arrow (GnmCComboFooView *ccombo, SheetObject *so)
+ccombo_create_arrow (GnmCComboView *ccombo, SheetObject *so)
 {
-	GnmCComboFooViewIface *iface = GNM_CCOMBO_FOO_VIEW_GET_CLASS (ccombo);
-	return (iface->create_arrow) (so);
+	GnmCComboViewClass *klass = GNM_CCOMBO_VIEW_GET_CLASS (ccombo);
+	return (klass->create_arrow) (so);
 }
 
 static gboolean
 ccombo_activate (GtkWidget *popup, GtkTreeView *list)
 {
 	SheetObjectView		*sov    = g_object_get_data (G_OBJECT (list), SOV_ID);
-	FooCanvasItem		*view   = FOO_CANVAS_ITEM (sov);
+	GocItem			*view   = GOC_ITEM (sov);
 	GnmPane			*pane   = GNM_PANE (view->canvas);
-	GnmCComboFooViewIface	*iface  = GNM_CCOMBO_FOO_VIEW_GET_CLASS (sov);
+	GnmCComboViewClass	*klass  = GNM_CCOMBO_VIEW_GET_CLASS (sov);
 
-	if ((iface->activate) (sheet_object_view_get_so (sov), popup, list,
+	if ((klass->activate) (sheet_object_view_get_so (sov), popup, list,
 			      scg_wbcg (pane->simple.scg)))
 	{
 		ccombo_popup_destroy (popup, GTK_WIDGET (list));
@@ -66,11 +66,11 @@ ccombo_activate (GtkWidget *popup, GtkTreeView *list)
 }
 
 static GtkWidget *
-ccombo_create_list (GnmCComboFooView *ccombo,
+ccombo_create_list (GnmCComboView *ccombo,
 		    SheetObject *so, GtkTreePath **clip, GtkTreePath **select)
 {
-	GnmCComboFooViewIface *iface = GNM_CCOMBO_FOO_VIEW_GET_CLASS (ccombo);
-	return (iface->create_list) (so, clip, select);
+	GnmCComboViewClass *klass = GNM_CCOMBO_VIEW_GET_CLASS (ccombo);
+	return (klass->create_list) (so, clip, select);
 }
 
 /****************************************************************************/
@@ -253,20 +253,20 @@ static void
 cb_ccombo_button_pressed (G_GNUC_UNUSED GtkButton *button,
 			  SheetObjectView *sov)
 {
-	gnm_cell_combo_foo_view_popdown (sov, GDK_CURRENT_TIME);
+	gnm_cell_combo_view_popdown (sov, GDK_CURRENT_TIME);
 }
 
 /**
- * gnm_cell_combo_foo_view_popdown:
+ * gnm_cell_combo_view_popdown:
  * @sov : #SheetObjectView
  * @activate_time : event time
  *
  * Open the popup window associated with @sov
  **/
 void
-gnm_cell_combo_foo_view_popdown (SheetObjectView *sov, guint32 activate_time)
+gnm_cell_combo_view_popdown (SheetObjectView *sov, guint32 activate_time)
 {
-	FooCanvasItem	   *view   = FOO_CANVAS_ITEM (sov);
+	GocItem		   *view   = GOC_ITEM (sov);
 	GnmPane		   *pane   = GNM_PANE (view->canvas);
 	SheetControlGUI	   *scg    = pane->simple.scg;
 	SheetObject	   *so     = sheet_object_view_get_so (sov);
@@ -286,7 +286,7 @@ gnm_cell_combo_foo_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_FOO_VIEW (sov), so, &clip, &select);
+	list = ccombo_create_list (GNM_CCOMBO_VIEW (sov), so, &clip, &select);
 
 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE);
 	gtk_widget_size_request (GTK_WIDGET (list), &req);
@@ -381,7 +381,7 @@ gnm_cell_combo_foo_view_popdown (SheetObjectView *sov, guint32 activate_time)
 }
 
 /**
- * gnm_cell_combo_foo_view_new:
+ * gnm_cell_combo_view_new:
  * @so : #SheetObject
  * @type : #GType
  * @container : SheetObjectViewContainer (a GnmPane)
@@ -389,19 +389,19 @@ gnm_cell_combo_foo_view_popdown (SheetObjectView *sov, guint32 activate_time)
  * Create and register an in cell combo to pick from an autofilter list.
  **/
 SheetObjectView *
-gnm_cell_combo_foo_view_new (SheetObject *so, GType type,
+gnm_cell_combo_view_new (SheetObject *so, GType type,
 			     SheetObjectViewContainer *container)
 {
 	GnmPane *pane = GNM_PANE (container);
 	GtkWidget *view_widget = gtk_button_new ();
-	FooCanvasItem *ccombo = foo_canvas_item_new (pane->object_views, type,
+	GocItem *ccombo = goc_item_new (pane->object_views, type, NULL);
+	goc_item_new (GOC_GROUP (ccombo), GOC_TYPE_WIDGET,
 		"widget",	view_widget,
-		"size_pixels",	FALSE,
 		NULL);
 	GTK_WIDGET_UNSET_FLAGS (view_widget, GTK_CAN_FOCUS);
 
 	gtk_container_add (GTK_CONTAINER (view_widget),
-		ccombo_create_arrow (GNM_CCOMBO_FOO_VIEW (ccombo), so));
+		ccombo_create_arrow (GNM_CCOMBO_VIEW (ccombo), so));
 	g_signal_connect (view_widget, "pressed",
 		G_CALLBACK (cb_ccombo_button_pressed), ccombo);
 	gtk_widget_show_all (view_widget);
@@ -409,21 +409,12 @@ gnm_cell_combo_foo_view_new (SheetObject *so, GType type,
 	return gnm_pane_object_register (so, ccombo, FALSE);
 }
 
-GType
-gnm_ccombo_foo_view_get_type (void)
+static void
+gnm_cell_combo_view_init (SheetObjectView *view)
 {
-	static GType type = 0;
-
-	if (!type) {
-		static GTypeInfo const type_info = {
-			sizeof (GnmCComboFooViewIface),	/* class_size */
-			NULL,				/* base_init */
-			NULL,				/* base_finalize */
-		};
-
-		type = g_type_register_static (G_TYPE_INTERFACE,
-			"GnmCComboFooView", &type_info, 0);
-	}
-
-	return type;
+	view->resize_mode = GNM_SO_RESIZE_AUTO;
 }
+
+GSF_CLASS (GnmCComboView, gnm_ccombo_view,
+	   NULL, gnm_cell_combo_view_init,
+	   SHEET_OBJECT_VIEW_TYPE)
diff --git a/src/widgets/gnm-cell-combo-view.h b/src/widgets/gnm-cell-combo-view.h
new file mode 100644
index 0000000..123c16f
--- /dev/null
+++ b/src/widgets/gnm-cell-combo-view.h
@@ -0,0 +1,12 @@
+#ifndef GNM_CELL_COMBO_VIEW_H
+#define GNM_CELL_COMBO_VIEW_H
+
+#include "gnumeric.h"
+#include <glib-object.h>
+
+SheetObjectView *gnm_cell_combo_view_new	 (SheetObject *so, GType t,
+						  SheetObjectViewContainer *container);
+void		 gnm_cell_combo_view_popdown (SheetObjectView *sov, guint32 activate_time);
+
+#endif /* GNM_CELL_COMBO_VIEW_H */
+
diff --git a/src/widgets/gnm-filter-combo-foo-view.c b/src/widgets/gnm-filter-combo-view.c
similarity index 89%
rename from src/widgets/gnm-filter-combo-foo-view.c
rename to src/widgets/gnm-filter-combo-view.c
index e5ac1de..6f34e98 100644
--- a/src/widgets/gnm-filter-combo-foo-view.c
+++ b/src/widgets/gnm-filter-combo-view.c
@@ -1,7 +1,7 @@
 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
 /*
- * gnm-filter-combo.c: the autofilter combo box for FooCanvas
+ * gnm-filter-combo.c: the autofilter combo box for the goffice canvas
  *
  * Copyright (C) 2006 Jody Goldberg (jody gnome org)
  *
@@ -21,8 +21,8 @@
  */
 
 #include <gnumeric-config.h>
-#include "gnm-filter-combo-foo-view.h"
-#include "gnm-cell-combo-foo-view-impl.h"
+#include "gnm-filter-combo-view.h"
+#include "gnm-cell-combo-view-impl.h"
 
 #include "gui-gnumeric.h"
 #include "sheet-filter.h"
@@ -31,13 +31,13 @@
 #include "value.h"
 #include "cell.h"
 #include "sheet.h"
+#include "sheet-object-impl.h"
 #include "workbook.h"
 #include "style-color.h"
 #include "sheet-control-gui.h"
 #include "../dialogs/dialogs.h"
 
 #include <goffice/goffice.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-widget.h>
 #include <gsf/gsf-impl-utils.h>
 #include <gtk/gtk.h>
 #include <glib/gi18n-lib.h>
@@ -313,14 +313,6 @@ fcombo_create_arrow (SheetObject *so)
 	return arrow;
 }
 
-static void
-fcombo_ccombo_init (GnmCComboFooViewIface *ccombo_iface)
-{
-	ccombo_iface->create_list	= fcombo_create_list;
-	ccombo_iface->create_arrow	= fcombo_create_arrow;
-	ccombo_iface->activate		= fcombo_activate;
-}
-
 /*******************************************************************************/
 
 /* Somewhat magic.
@@ -328,13 +320,13 @@ fcombo_ccombo_init (GnmCComboFooViewIface *ccombo_iface)
 static void
 filter_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
+	GocGroup *view = GOC_GROUP (sov);
 
 	if (visible) {
 		double h = (coords[3] - coords[1]) + 1.;
 		if (h > 20.)	/* clip vertically */
 			h = 20.;
-		foo_canvas_item_set (view,
+		goc_item_set (GOC_ITEM (view->children->data),
 			/* put it inside the cell */
 			"x",	  ((coords[2] >= 0.) ? (coords[2]-h+1) : coords[0]),
 			"y",	  coords [3] - h + 1.,
@@ -342,28 +334,26 @@ filter_view_set_bounds (SheetObjectView *sov, double const *coords, gboolean vis
 			"height", h,
 			NULL);
 
-		foo_canvas_item_show (view);
+		goc_item_show (GOC_ITEM (view));
 	} else
-		foo_canvas_item_hide (view);
-}
-static void filter_view_destroy (SheetObjectView *sov)
-{
-	gtk_object_destroy (GTK_OBJECT (sov));
+		goc_item_hide (GOC_ITEM (view));
 }
+
 static void
-fcombo_sov_init (SheetObjectViewIface *sov_iface)
+gnm_filter_view_class_init (GnmCComboViewClass *ccombo_class)
 {
-	sov_iface->destroy	= filter_view_destroy;
-	sov_iface->set_bounds	= filter_view_set_bounds;
+	SheetObjectViewClass *sov_class = (SheetObjectViewClass *) ccombo_class;
+	ccombo_class->create_list	= fcombo_create_list;
+	ccombo_class->create_arrow	= fcombo_create_arrow;
+	ccombo_class->activate		= fcombo_activate;
+	sov_class->set_bounds		= filter_view_set_bounds;
 }
 
 /****************************************************************************/
 
-typedef FooCanvasWidget		GnmFilterComboFooView;
-typedef FooCanvasWidgetClass	GnmFilterComboFooViewClass;
-GSF_CLASS_FULL (GnmFilterComboFooView, gnm_filter_combo_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, FOO_TYPE_CANVAS_WIDGET, 0,
-	GSF_INTERFACE (fcombo_sov_init, SHEET_OBJECT_VIEW_TYPE)
-	GSF_INTERFACE (fcombo_ccombo_init, GNM_CCOMBO_FOO_VIEW_TYPE)
-)
+typedef GnmCComboView		GnmFilterComboView;
+typedef GnmCComboViewClass	GnmFilterComboViewClass;
+GSF_CLASS (GnmFilterComboView, gnm_filter_combo_view,
+	gnm_filter_view_class_init, NULL,
+	GNM_CCOMBO_VIEW_TYPE)
+
diff --git a/src/widgets/gnm-filter-combo-view.h b/src/widgets/gnm-filter-combo-view.h
new file mode 100644
index 0000000..6ddac62
--- /dev/null
+++ b/src/widgets/gnm-filter-combo-view.h
@@ -0,0 +1,9 @@
+#ifndef GNM_FILTER_COMBO_VIEW_H
+#define GNM_FILTER_COMBO_VIEW_H
+
+#include <glib-object.h>
+
+GType gnm_filter_combo_view_get_type (void);
+
+#endif /* GNM_FILTER_COMBO_VIEW_H */
+
diff --git a/src/widgets/gnm-sheet-slicer-combo-foo-view.c b/src/widgets/gnm-sheet-slicer-combo-view.c
similarity index 84%
rename from src/widgets/gnm-sheet-slicer-combo-foo-view.c
rename to src/widgets/gnm-sheet-slicer-combo-view.c
index 0fd2b95..f0a25b8 100644
--- a/src/widgets/gnm-sheet-slicer-combo-foo-view.c
+++ b/src/widgets/gnm-sheet-slicer-combo-view.c
@@ -22,7 +22,7 @@
 
 #include <gnumeric-config.h>
 #include "gnm-sheet-slicer-combo-foo-view.h"
-#include "gnm-cell-combo-foo-view-impl.h"
+#include "gnm-cell-combo-view-impl.h"
 
 #include "gnm-sheet-slicer-combo.h"
 #include "workbook.h"
@@ -34,7 +34,6 @@
 #include "go-data-slicer-field.h"
 #include "go-data-cache-field.h"
 #include <goffice/goffice.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-widget.h>
 #include <gsf/gsf-impl-utils.h>
 #include <gtk/gtk.h>
 #include <glib/gi18n-lib.h>
@@ -111,7 +110,7 @@ sscombo_create_list (SheetObject *so, GtkTreePath **clip, GtkTreePath **select)
 			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); 
+			g_string_truncate (str, 0);
 		}
 	}
 	list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
@@ -137,13 +136,13 @@ sscombo_create_arrow (G_GNUC_UNUSED SheetObject *so)
 	return gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
 }
 
-static void
-sscombo_ccombo_init (GnmCComboFooViewIface *ccombo_iface)
+/*static void
+sscombo_ccombo_init (GnmCComboViewIface void *ccombo_iface)
 {
 	ccombo_iface->create_list	= sscombo_create_list;
 	ccombo_iface->create_arrow	= sscombo_create_arrow;
 	ccombo_iface->activate		= sscombo_activate;
-}
+}*/
 
 /*******************************************************************************/
 
@@ -152,42 +151,38 @@ sscombo_ccombo_init (GnmCComboFooViewIface *ccombo_iface)
 static void
 sscombo_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
+	GocItem *view = GOC_ITEM (sov);
 
 	if (visible) {
 		double h = (coords[3] - coords[1]) + 1.;
 		if (h > 20.)	/* clip vertically */
 			h = 20.;
-		foo_canvas_item_set (view,
+		goc_item_set (view,
 			/* 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);
-		foo_canvas_item_show (view);
+		goc_item_show (view);
 	} else
-		foo_canvas_item_hide (view);
-}
-static void
-sscombo_destroy (SheetObjectView *sov)
-{
-	gtk_object_destroy (GTK_OBJECT (sov));
+		goc_item_hide (view);
 }
+
 static void
-sscombo_sov_init (SheetObjectViewIface *sov_iface)
+sscombo_class_init (GnmCComboViewClass *ccombo_class)
 {
-	sov_iface->destroy	= sscombo_destroy;
-	sov_iface->set_bounds	= sscombo_set_bounds;
+	SheetObjectViewClass *sov_class = (SheetObjectViewClass *) ccombo_class;
+	ccombo_class->create_list	= sscombo_create_list;
+	ccombo_class->create_arrow	= sscombo_create_arrow;
+	ccombo_class->activate		= sscombo_activate;
+	sov_class->set_bounds		= sscombo_set_bounds;
 }
 
 /****************************************************************************/
 
-typedef FooCanvasWidget		GnmSheetSlicerComboFooView;
-typedef FooCanvasWidgetClass	GnmSheetSlicerComboFooViewClass;
-GSF_CLASS_FULL (GnmSheetSlicerComboFooView, gnm_sheet_slicer_combo_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, FOO_TYPE_CANVAS_WIDGET, 0,
-	GSF_INTERFACE (sscombo_sov_init, SHEET_OBJECT_VIEW_TYPE)
-	GSF_INTERFACE (sscombo_ccombo_init, GNM_CCOMBO_FOO_VIEW_TYPE)
-)
+typedef GnmCComboView		GnmSheetSlicerComboView;
+typedef GnmCComboViewClass	GnmSheetSlicerComboViewClass;
+GSF_CLASS (GnmSheetSlicerComboView, gnm_sheet_slicer_combo_view,
+	sscombo_class_init, NULL,
+	GNM_CCOMBO_VIEW_TYPE)
diff --git a/src/widgets/gnm-sheet-slicer-combo-foo-view.h b/src/widgets/gnm-sheet-slicer-combo-view.h
similarity index 74%
rename from src/widgets/gnm-sheet-slicer-combo-foo-view.h
rename to src/widgets/gnm-sheet-slicer-combo-view.h
index 0e4d0b9..c4f5203 100644
--- a/src/widgets/gnm-sheet-slicer-combo-foo-view.h
+++ b/src/widgets/gnm-sheet-slicer-combo-view.h
@@ -3,6 +3,6 @@
 
 #include <glib-object.h>
 
-GType gnm_sheet_slicer_combo_foo_view_get_type (void);
+GType gnm_sheet_slicer_combo_view_get_type (void);
 
 #endif /* GNM_SHEET_SLICER_COMBO_FOO_VIEW_H */
diff --git a/src/widgets/gnm-validation-combo-foo-view.c b/src/widgets/gnm-validation-combo-view.c
similarity index 83%
rename from src/widgets/gnm-validation-combo-foo-view.c
rename to src/widgets/gnm-validation-combo-view.c
index 8b0e3ad..b0c77e9 100644
--- a/src/widgets/gnm-validation-combo-foo-view.c
+++ b/src/widgets/gnm-validation-combo-view.c
@@ -1,8 +1,8 @@
 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
 /*
- * gnm-validation-combo-foo-view.c: A foocanvas object for Validate from list
- *				in cell combos
+ * gnm-validation-combo-view.c: A canvas object for Validate from list
+ * 				in cell combos
  *
  * Copyright (C) 2006 Jody Goldberg (jody gnome org)
  *
@@ -22,8 +22,8 @@
  */
 
 #include <gnumeric-config.h>
-#include "gnm-validation-combo-foo-view.h"
-#include "gnm-cell-combo-foo-view-impl.h"
+#include "gnm-validation-combo-view.h"
+#include "gnm-cell-combo-view-impl.h"
 
 #include "validation-combo.h"
 #include "commands.h"
@@ -40,7 +40,6 @@
 
 #include "gui-gnumeric.h"
 #include <goffice/goffice.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-widget.h>
 #include <gsf/gsf-impl-utils.h>
 #include <gtk/gtk.h>
 #include <glib/gi18n-lib.h>
@@ -179,14 +178,6 @@ vcombo_create_arrow (G_GNUC_UNUSED SheetObject *so)
 	return gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
 }
 
-static void
-vcombo_ccombo_init (GnmCComboFooViewIface *ccombo_iface)
-{
-	ccombo_iface->create_list	= vcombo_create_list;
-	ccombo_iface->create_arrow	= vcombo_create_arrow;
-	ccombo_iface->activate		= vcombo_activate;
-}
-
 /*******************************************************************************/
 
 /* Somewhat magic.
@@ -194,42 +185,39 @@ vcombo_ccombo_init (GnmCComboFooViewIface *ccombo_iface)
 static void
 vcombo_set_bounds (SheetObjectView *sov, double const *coords, gboolean visible)
 {
-	FooCanvasItem *view = FOO_CANVAS_ITEM (sov);
+	GocItem *view = GOC_ITEM (sov);
 
 	if (visible) {
 		double h = (coords[3] - coords[1]) + 1.;
 		if (h > 20.)	/* clip vertically */
 			h = 20.;
-		foo_canvas_item_set (view,
+		goc_item_set (view,
 			/* 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);
-		foo_canvas_item_show (view);
+		goc_item_show (view);
 	} else
-		foo_canvas_item_hide (view);
-}
-static void
-vcombo_destroy (SheetObjectView *sov)
-{
-	gtk_object_destroy (GTK_OBJECT (sov));
+		goc_item_hide (view);
 }
+
+/****************************************************************************/
+
 static void
-vcombo_sov_init (SheetObjectViewIface *sov_iface)
+gnm_validation_view_class_init (GnmCComboViewClass *ccombo_class)
 {
-	sov_iface->destroy	= vcombo_destroy;
-	sov_iface->set_bounds	= vcombo_set_bounds;
+	SheetObjectViewClass *sov_class = (SheetObjectViewClass *) ccombo_class;
+	ccombo_class->create_list	= vcombo_create_list;
+	ccombo_class->create_arrow	= vcombo_create_arrow;
+	ccombo_class->activate		= vcombo_activate;
+	sov_class->set_bounds		= vcombo_set_bounds;
 }
 
-/****************************************************************************/
+typedef GnmCComboView		GnmValidationComboView;
+typedef GnmCComboViewClass	GnmValidationComboViewClass;
+GSF_CLASS (GnmValidationComboView, gnm_validation_combo_view,
+	gnm_validation_view_class_init, NULL,
+	GNM_CCOMBO_VIEW_TYPE)
 
-typedef FooCanvasWidget		GnmValidationComboFooView;
-typedef FooCanvasWidgetClass	GnmValidationComboFooViewClass;
-GSF_CLASS_FULL (GnmValidationComboFooView, gnm_validation_combo_foo_view,
-	NULL, NULL, NULL, NULL,
-	NULL, FOO_TYPE_CANVAS_WIDGET, 0,
-	GSF_INTERFACE (vcombo_sov_init, SHEET_OBJECT_VIEW_TYPE)
-	GSF_INTERFACE (vcombo_ccombo_init, GNM_CCOMBO_FOO_VIEW_TYPE)
-)
diff --git a/src/widgets/gnm-validation-combo-view.h b/src/widgets/gnm-validation-combo-view.h
new file mode 100644
index 0000000..a822861
--- /dev/null
+++ b/src/widgets/gnm-validation-combo-view.h
@@ -0,0 +1,9 @@
+#ifndef GNM_VALIDATION_COMBO_VIEW_H
+#define GNM_VALIDATION_COMBO_VIEW_H
+
+#include <glib-object.h>
+
+GType gnm_validation_combo_view_get_type (void);
+
+#endif /* GNM_VALIDATION_COMBO_VIEW_H */
+
diff --git a/src/widgets/gnumeric-dashed-canvas-line.c b/src/widgets/gnumeric-dashed-canvas-line.c
index b5b6139..2f76c07 100644
--- a/src/widgets/gnumeric-dashed-canvas-line.c
+++ b/src/widgets/gnumeric-dashed-canvas-line.c
@@ -13,9 +13,8 @@
 #include <gsf/gsf-impl-utils.h>
 #include <math.h>
 
-static void gnumeric_dashed_canvas_line_draw (FooCanvasItem *item,
-					      GdkDrawable *drawable,
-					      GdkEventExpose *event);
+static void gnumeric_dashed_canvas_line_draw (GocItem const *item,
+					      cairo_t *cr);
 
 static GnumericDashedCanvasLineClass *gnumeric_dashed_canvas_line_class;
 
@@ -73,27 +72,17 @@ hypothenuse (double xlength, double ylength)
  * (x0,y0) - B is the y offset from y0 of the start of this line.
  */
 static void
-double_line_draw (FooCanvasItem *item, GdkDrawable *drawable,
-		  GdkEventExpose *event)
+double_line_draw (GocItem const *item, cairo_t *cr)
 {
-	double *coords;
+	double coords[4];
 	double length, xdiff, ydiff, xoffs, yoffs;
-	double offsetcoords[4];
 
-	GnumericDashedCanvasLine *line = GNUMERIC_DASHED_CANVAS_LINE (item);
-
-	if (FOO_CANVAS_LINE (line)->num_points != 2) {
-		g_warning ("file %s: line %d: \n%s", __FILE__, __LINE__,
-			   "GnumericDashedCanvasLine only supports a "
-			   "single line segment.");
-
-		line->dash_style_index = GNM_STYLE_BORDER_MEDIUM;
-		gnumeric_dashed_canvas_line_draw
-			(FOO_CANVAS_ITEM (line), drawable, event);
-		return;
-	}
+	GocLine *line = GOC_LINE (item);
 
-	coords = FOO_CANVAS_LINE (line)->coords;
+	coords[0] = line->startx;
+	coords[1] = line->starty;
+	coords[2] = line->endx;
+	coords[3] = line->endy;
 	xdiff = coords[2] - coords[0];
 	ydiff = coords[3] - coords[1];
 
@@ -101,51 +90,47 @@ double_line_draw (FooCanvasItem *item, GdkDrawable *drawable,
 	yoffs = xdiff/length;
 	xoffs = -ydiff/length;
 
-	gnm_style_border_set_gc_dash (FOO_CANVAS_LINE (item)->gc,
-				  GNM_STYLE_BORDER_THIN);
-	offsetcoords[0] = coords[0] + xoffs;
-	offsetcoords[1] = coords[1] + yoffs;
-	offsetcoords[2] = coords[2] + xoffs;
-	offsetcoords[3] = coords[3] + yoffs;
-	FOO_CANVAS_LINE (line)->coords = offsetcoords;
+	line->startx = coords[0] + xoffs;
+	line->starty = coords[1] + yoffs;
+	line->endx = coords[2] + xoffs;
+	line->endy = coords[3] + yoffs;
 	gnumeric_dashed_canvas_line_class->
-		real_draw (item, drawable, event);
+		real_draw (item, cr);
 
-	offsetcoords[0] = coords[0] - xoffs;
-	offsetcoords[1] = coords[1] - yoffs;
-	offsetcoords[2] = coords[2] - xoffs;
-	offsetcoords[3] = coords[3] - yoffs;
+	line->startx = coords[0] - xoffs;
+	line->starty = coords[1] - yoffs;
+	line->endx = coords[2] - xoffs;
+	line->endy = coords[3] - yoffs;
 	gnumeric_dashed_canvas_line_class->
-		real_draw (item, drawable, event);
+		real_draw (item, cr);
 
-	FOO_CANVAS_LINE (line)->coords = coords;
+	line->startx = coords[0];
+	line->starty = coords[1];
+	line->endx = coords[2];
+	line->endy = coords[3];
 }
 
 static void
-gnumeric_dashed_canvas_line_draw (FooCanvasItem *item,
-				  GdkDrawable *drawable,
-				  GdkEventExpose *event)
+gnumeric_dashed_canvas_line_draw (GocItem const *item, cairo_t *cr)
 {
 	GnumericDashedCanvasLine *line = GNUMERIC_DASHED_CANVAS_LINE (item);
 
 	if (line->dash_style_index == GNM_STYLE_BORDER_DOUBLE)
-		double_line_draw (item, drawable, event);
+		double_line_draw (item, cr);
 	else {
-		gnm_style_border_set_gc_dash (FOO_CANVAS_LINE (item)->gc,
-					  line->dash_style_index);
 		gnumeric_dashed_canvas_line_class->
-			real_draw (item, drawable, event);
+			real_draw (item, cr);
 	}
 }
 
 static void
 gnumeric_dashed_canvas_line_class_init (GnumericDashedCanvasLineClass *klass)
 {
-	FooCanvasItemClass *item_class;
+	GocItemClass *item_class;
 
 	gnumeric_dashed_canvas_line_class = klass;
 
-	item_class = (FooCanvasItemClass *) klass;
+	item_class = (GocItemClass *) klass;
 
 	klass->real_draw = item_class->draw;
 	item_class->draw = &gnumeric_dashed_canvas_line_draw;
@@ -159,17 +144,17 @@ gnumeric_dashed_canvas_line_init (GnumericDashedCanvasLine *line)
 
 GSF_CLASS (GnumericDashedCanvasLine, gnumeric_dashed_canvas_line,
 	   gnumeric_dashed_canvas_line_class_init,
-	   gnumeric_dashed_canvas_line_init, FOO_TYPE_CANVAS_LINE)
+	   gnumeric_dashed_canvas_line_init, GOC_TYPE_LINE)
 
 void
 gnumeric_dashed_canvas_line_set_dash_index (GnumericDashedCanvasLine *line,
 					    GnmStyleBorderType const indx)
 {
 	gint const width = gnm_style_border_get_width (indx);
+	GOStyle *style = go_styled_object_get_style (GO_STYLED_OBJECT (line));
 	line->dash_style_index = indx;
-	foo_canvas_item_set (FOO_CANVAS_ITEM (line),
-			       "width-pixels", width,
-			       NULL);
+	style->line.width = width;
+	style->line.dash_type = (indx == GNM_STYLE_BORDER_DOUBLE)? GNM_STYLE_BORDER_THIN: indx;
 
-	foo_canvas_item_request_update (FOO_CANVAS_ITEM (line));
+	goc_item_invalidate (GOC_ITEM (line));
 }
diff --git a/src/widgets/gnumeric-dashed-canvas-line.h b/src/widgets/gnumeric-dashed-canvas-line.h
index 5b5e307..652461e 100644
--- a/src/widgets/gnumeric-dashed-canvas-line.h
+++ b/src/widgets/gnumeric-dashed-canvas-line.h
@@ -2,7 +2,7 @@
 #define GNUMERIC_DASHED_CANVAS_LINE_H
 
 /* dashed Line item for the canvas */
-#include <goffice/cut-n-paste/foocanvas/foo-canvas-line.h>
+#include <goffice/goffice.h>
 #include "style-border.h"
 
 #define GNUMERIC_TYPE_DASHED_CANVAS_LINE\
@@ -18,22 +18,18 @@
 
 
 typedef struct _GnumericDashedCanvasLine GnumericDashedCanvasLine;
-typedef struct _GnumericDashedCanvasLineClass GnumericDashedCanvasLineClass;
+typedef struct {
+	GocLineClass base;
+	void (*real_draw) (GocItem const *item, cairo_t *cr);
+} GnumericDashedCanvasLineClass;
 
 struct _GnumericDashedCanvasLine {
-	FooCanvasLine line;
+	GocLine line;
 
 	/* Public : */
 	GnmStyleBorderType dash_style_index;
 };
 
-struct _GnumericDashedCanvasLineClass {
-	FooCanvasLineClass parent_class;
-	void (*real_draw)(FooCanvasItem *item,
-			  GdkDrawable *drawable,
-			  GdkEventExpose *event);
-};
-
 void    gnumeric_dashed_canvas_line_set_dash_index (GnumericDashedCanvasLine *line,
 						    GnmStyleBorderType const indx);
 
diff --git a/src/widgets/widget-font-selector.c b/src/widgets/widget-font-selector.c
index 541232e..f7fdd00 100644
--- a/src/widgets/widget-font-selector.c
+++ b/src/widgets/widget-font-selector.c
@@ -21,6 +21,8 @@
 #include <preview-grid.h>
 
 #include <goffice/goffice.h>
+#include <goffice/canvas/goc-canvas.h>
+#include <goffice/canvas/goc-item.h>
 #include <gsf/gsf-impl-utils.h>
 #include <gtk/gtk.h>
 #include <glade/glade.h>
@@ -39,8 +41,8 @@ struct _FontSelector {
 	GtkTreeView *font_style_list;
 	GtkTreeView *font_size_list;
 
-	FooCanvas *font_preview_canvas;
-	FooCanvasItem *font_preview_grid;
+	GocCanvas *font_preview_canvas;
+	GocItem	  *font_preview_grid;
 
 	GnmStyle     *mstyle;
 
@@ -90,7 +92,7 @@ fs_modify_style (FontSelector *fs, GnmStyle *modification)
 		fs->mstyle = new_style;
 		g_signal_emit (G_OBJECT (fs),
 			       fs_signals[FONT_CHANGED], 0, modification);
-		foo_canvas_item_set (fs->font_preview_grid,
+		goc_item_set (fs->font_preview_grid,
 				     "default-style",  fs->mstyle,
 				     NULL);
 		gnm_style_unref (original);
@@ -354,13 +356,10 @@ canvas_size_changed (G_GNUC_UNUSED GtkWidget *widget,
 	int width  = allocation->width - 1;
 	int height = allocation->height - 1;
 
-	foo_canvas_item_set (fs->font_preview_grid,
+	goc_item_set (fs->font_preview_grid,
                  "default-col-width",  width,
                  "default-row-height", height,
 		 NULL);
-
-	foo_canvas_set_scroll_region (fs->font_preview_canvas, 0, 0,
-				      width, height);
 }
 
 static void
@@ -387,15 +386,14 @@ fs_init (FontSelector *fs)
 	fs->font_style_list = GTK_TREE_VIEW (glade_xml_get_widget (fs->gui, "font-style-list"));
 	fs->font_size_list  = GTK_TREE_VIEW (glade_xml_get_widget (fs->gui, "font-size-list"));
 
-	w = foo_canvas_new ();
-	fs->font_preview_canvas = FOO_CANVAS (w);
-	foo_canvas_set_scroll_region (fs->font_preview_canvas, -1, -1, INT_MAX/2, INT_MAX/2);
-	foo_canvas_scroll_to (fs->font_preview_canvas, 0, 0);
+	w = g_object_new (GOC_TYPE_CANVAS, NULL);
+	fs->font_preview_canvas = GOC_CANVAS (w);
+	goc_canvas_scroll_to (fs->font_preview_canvas, 0, 0);
 	gtk_widget_show_all (w);
 	w = glade_xml_get_widget (fs->gui, "font-preview-frame");
 	gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (fs->font_preview_canvas));
-	fs->font_preview_grid = FOO_CANVAS_ITEM (foo_canvas_item_new (
-		foo_canvas_root (fs->font_preview_canvas),
+	fs->font_preview_grid = GOC_ITEM (goc_item_new (
+		goc_canvas_get_root (fs->font_preview_canvas),
 		preview_grid_get_type (),
 		"render-gridlines",	FALSE,
 		"default-value",	value_new_string ("AaBbCcDdEe12345"),
@@ -477,7 +475,7 @@ font_selector_set_value (FontSelector *fs, GnmValue const *v)
 	val = (v != NULL)
 		? value_dup (v)
 		: value_new_string ("AaBbCcDdEe12345");
-	foo_canvas_item_set (fs->font_preview_grid,
+	goc_item_set (fs->font_preview_grid,
 		"default-value",  val,
 		NULL);
 }
diff --git a/src/widgets/widget-font-selector.h b/src/widgets/widget-font-selector.h
index 87f357c..74c5043 100644
--- a/src/widgets/widget-font-selector.h
+++ b/src/widgets/widget-font-selector.h
@@ -3,7 +3,6 @@
 
 #include <gui-gnumeric.h>
 #include <style.h>
-#include <goffice/cut-n-paste/foocanvas/foo-canvas.h>
 #include <gtk/gtk.h>
 
 #define FONT_SELECTOR_TYPE        (font_selector_get_type ())



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