Index: app/text/gimptextlayout.c
===================================================================
--- app/text/gimptextlayout.c	(revision 25183)
+++ app/text/gimptextlayout.c	(working copy)
@@ -170,6 +170,7 @@
                                                            text->box_width,
                                                            text->box_unit,
                                                            xres));
+      layout->extents.width = PANGO_PIXELS (text->box_width);
       break;
     }
 
@@ -206,6 +207,11 @@
     case GIMP_TEXT_BOX_DYNAMIC:
       break;
     case GIMP_TEXT_BOX_FIXED:
+      layout->extents.width =
+        PANGO_PIXELS (gimp_text_layout_pixel_size (image->gimp,
+                                                   text->box_width,
+                                                   text->box_unit,
+                                                   xres));
       layout->extents.height =
         PANGO_PIXELS (gimp_text_layout_pixel_size (image->gimp,
                                                    text->box_height,
Index: app/tools/gimptexttool.c
===================================================================
--- app/tools/gimptexttool.c	(revision 25183)
+++ app/tools/gimptexttool.c	(working copy)
@@ -58,6 +58,8 @@
 #include "display/gimpdisplay.h"
 
 #include "gimpeditselectiontool.h"
+#include "gimprectangletool.h"
+#include "gimprectangleoptions.h"
 #include "gimptextoptions.h"
 #include "gimptexttool.h"
 #include "gimptoolcontrol.h"
@@ -70,6 +72,8 @@
 
 /*  local function prototypes  */
 
+static void gimp_text_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface);
+
 static GObject * gimp_text_tool_constructor    (GType              type,
                                                 guint              n_params,
                                                 GObjectConstructParam *params);
@@ -84,6 +88,12 @@
                                                 guint32            time,
                                                 GdkModifierType    state,
                                                 GimpDisplay       *display);
+static void      gimp_text_tool_button_release (GimpTool          *tool,
+                                                GimpCoords        *coords,
+                                                guint32            time,
+                                                GdkModifierType    state,
+                                                GimpButtonReleaseType release_type,
+                                                GimpDisplay       *display);
 static void      gimp_text_tool_cursor_update  (GimpTool          *tool,
                                                 GimpCoords        *coords,
                                                 GdkModifierType    state,
@@ -123,8 +133,14 @@
                                                 GimpDrawable      *drawable,
                                                 gboolean           confirm);
 
+static gboolean  gimp_text_tool_rectangle_changed (GimpRectangleTool *rect_tool);
+void             gimp_rectangle_tool_frame_item   (GimpRectangleTool *rect_tool,
+                                                   GimpItem          *item);
 
-G_DEFINE_TYPE (GimpTextTool, gimp_text_tool, GIMP_TYPE_TOOL)
+G_DEFINE_TYPE_WITH_CODE (GimpTextTool, gimp_text_tool,
+                         GIMP_TYPE_DRAW_TOOL,
+                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_RECTANGLE_TOOL,
+                                                gimp_text_tool_rectangle_tool_iface_init))
 
 #define parent_class gimp_text_tool_parent_class
 
@@ -149,20 +165,38 @@
 static void
 gimp_text_tool_class_init (GimpTextToolClass *klass)
 {
-  GObjectClass  *object_class = G_OBJECT_CLASS (klass);
-  GimpToolClass *tool_class   = GIMP_TOOL_CLASS (klass);
+  GObjectClass      *object_class    = G_OBJECT_CLASS (klass);
+  GimpToolClass     *tool_class      = GIMP_TOOL_CLASS (klass);
+  GimpDrawToolClass *draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);
 
-  object_class->constructor = gimp_text_tool_constructor;
-  object_class->dispose     = gimp_text_tool_dispose;
-  object_class->finalize    = gimp_text_tool_finalize;
+  object_class->constructor  = gimp_text_tool_constructor;
+  object_class->dispose      = gimp_text_tool_dispose;
+  object_class->finalize     = gimp_text_tool_finalize;
+  object_class->set_property = gimp_rectangle_tool_set_property;
+  object_class->get_property = gimp_rectangle_tool_get_property;
 
-  tool_class->control       = gimp_text_tool_control;
-  tool_class->button_press  = gimp_text_tool_button_press;
-  tool_class->key_press     = gimp_edit_selection_tool_key_press;
-  tool_class->cursor_update = gimp_text_tool_cursor_update;
+  gimp_rectangle_tool_install_properties (object_class);
+
+  tool_class->control        = gimp_text_tool_control;
+  tool_class->button_press   = gimp_text_tool_button_press;
+  tool_class->motion         = gimp_rectangle_tool_motion;
+  tool_class->button_release = gimp_text_tool_button_release;
+  tool_class->key_press      = gimp_edit_selection_tool_key_press;
+  tool_class->oper_update    = gimp_rectangle_tool_oper_update;
+  tool_class->cursor_update  = gimp_text_tool_cursor_update;
+
+  draw_tool_class->draw      = gimp_rectangle_tool_draw;
 }
 
 static void
+gimp_text_tool_rectangle_tool_iface_init (GimpRectangleToolInterface *iface)
+{
+  iface->execute           = NULL;
+  iface->cancel            = NULL;
+  iface->rectangle_changed = gimp_text_tool_rectangle_changed;
+}
+
+static void
 gimp_text_tool_init (GimpTextTool *text_tool)
 {
   GimpTool *tool = GIMP_TOOL (text_tool);
@@ -180,6 +214,8 @@
                                      GIMP_TOOL_CURSOR_TEXT);
   gimp_tool_control_set_action_object_1 (tool->control,
                                          "context/context-font-select-set");
+
+  text_tool->handle_rectangle_changed = TRUE;
 }
 
 static GObject *
@@ -193,6 +229,8 @@
 
   object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
 
+  gimp_rectangle_tool_constructor (object);
+
   text_tool = GIMP_TEXT_TOOL (object);
   options   = GIMP_TEXT_TOOL_GET_OPTIONS (text_tool);
 
@@ -238,6 +276,8 @@
 {
   GimpTextTool *text_tool = GIMP_TEXT_TOOL (tool);
 
+  gimp_rectangle_tool_control (tool, action, display);
+
   switch (action)
     {
     case GIMP_TOOL_ACTION_PAUSE:
@@ -259,16 +299,41 @@
                              GdkModifierType  state,
                              GimpDisplay     *display)
 {
-  GimpTextTool *text_tool = GIMP_TEXT_TOOL (tool);
-  GimpText     *text      = text_tool->text;
-  GimpDrawable *drawable;
+  GimpTextTool      *text_tool = GIMP_TEXT_TOOL (tool);
+  GimpText          *text      = text_tool->text;
+  GimpDrawable      *drawable;
+  GimpTextOptions   *options   = GIMP_TEXT_TOOL_GET_OPTIONS (text_tool);
+  GimpRectangleTool *rect_tool = GIMP_RECTANGLE_TOOL (tool);
 
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
+
   GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
                                                 display);
 
+  /* FIXME: this should certainly be done elsewhere */
+  g_object_set (options,
+                "highlight", FALSE,
+                NULL);
+
   text_tool->x1 = coords->x;
   text_tool->y1 = coords->y;
 
+  gimp_rectangle_tool_button_press (tool, coords, time, state, display);
+
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool));
+
+  /* bail out now if the rectangle is narrow and the button
+     press is outside the layer */
+  if (gimp_rectangle_tool_rectangle_is_narrow (rect_tool))
+    {
+      GimpItem *item = GIMP_ITEM (text_tool->layer);
+      gdouble   x    = coords->x - item->offset_x;
+      gdouble   y    = coords->y - item->offset_y;
+
+      if (x < 0 || x > item->width || y < 0 || y > item->height)
+        return;
+    }
+
   drawable = gimp_image_get_active_drawable (display->image);
 
   gimp_text_tool_set_drawable (text_tool, drawable, FALSE);
@@ -276,12 +341,14 @@
   if (GIMP_IS_LAYER (drawable))
     {
       GimpItem *item = GIMP_ITEM (drawable);
+      gdouble   x    = coords->x - item->offset_x;
+      gdouble   y    = coords->y - item->offset_y;
 
       coords->x -= item->offset_x;
       coords->y -= item->offset_y;
 
-      if (coords->x > 0 && coords->x < gimp_item_width  (item) &&
-          coords->y > 0 && coords->y < gimp_item_height (item))
+      if (x > 0 && x < gimp_item_width (item) &&
+          y > 0 && y < gimp_item_height (item))
         {
           /*  did the user click on a text layer?  */
           if (gimp_text_tool_set_drawable (text_tool, drawable, TRUE))
@@ -300,7 +367,76 @@
   gimp_text_tool_editor (text_tool);
 }
 
+#define MIN_LAYER_WIDTH 20
+
+/*
+ * Here is what we want to do:
+ * 1) If the user clicked on an existing text layer, and no rectangle
+ *    yet exists there, we want to create one with the right shape.
+ * 2) If the user has modified the rectangle for an existing text layer,
+ *    we want to change its shape accordingly.  We do this by falling
+ *    through to code that causes the "rectangle-changed" signal to
+ *    be emitted.
+ * 3) If the rectangle that has been swept out is too small, we want to
+ *    use dynamic text, so we halt the rectangle tool.
+ * 4) Otherwise, we want to use the new rectangle that the user has
+ *    created as our text box.  This again is done by causing
+ *    "rectangle-changed" to be emitted.
+ */
 static void
+gimp_text_tool_button_release (GimpTool              *tool,
+                               GimpCoords            *coords,
+                               guint32                time,
+                               GdkModifierType        state,
+                               GimpButtonReleaseType  release_type,
+                               GimpDisplay           *display)
+{
+  GimpRectangleTool *rect_tool      = GIMP_RECTANGLE_TOOL (tool);
+  GimpTextTool      *text_tool      = GIMP_TEXT_TOOL (tool);
+  GimpText          *text           = text_tool->text;
+  gint               x1, y1, x2, y2;
+
+  g_object_get (rect_tool,
+                "x1", &x1,
+                "y1", &y1,
+                "x2", &x2,
+                "y2", &y2,
+                NULL);
+
+  if (text && text_tool->text == text)
+    {
+      if (gimp_rectangle_tool_rectangle_is_new (rect_tool))
+        {
+          g_print ("user has clicked on an existing text layer\n");
+
+          gimp_tool_control_halt (tool->control);
+          text_tool->handle_rectangle_changed = FALSE;
+          gimp_rectangle_tool_frame_item (rect_tool,
+                                          GIMP_ITEM (text_tool->layer));
+          text_tool->handle_rectangle_changed = TRUE;
+          return;
+        }
+      else
+        g_print ("user has modified shape of an existing text layer\n");
+    }
+  else if (y2 - y1 < MIN_LAYER_WIDTH)
+    {
+      g_print ("user has clicked in dead space\n");
+      gimp_rectangle_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
+      if (GIMP_IS_TEXT (text_tool->proxy))
+        g_object_set (text_tool->proxy,
+                      "box-mode", GIMP_TEXT_BOX_DYNAMIC,
+                      NULL);
+      return;
+    }
+  else
+    g_print ("user has defined box for a new text layer\n");
+
+  gimp_rectangle_tool_button_release (tool, coords, time, state,
+                                      release_type, display);
+}
+
+static void
 gimp_text_tool_cursor_update (GimpTool        *tool,
                               GimpCoords      *coords,
                               GdkModifierType  state,
@@ -308,6 +444,8 @@
 {
   /* FIXME: should do something fancy here... */
 
+  gimp_rectangle_tool_cursor_update (tool, coords, state, display);
+
   GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
 }
 
@@ -474,6 +612,23 @@
 
   if (text_tool->editor && strcmp (pspec->name, "text") == 0)
     gimp_text_tool_editor_update (text_tool);
+
+  /* we need to redraw the rectangle if it is visible and the shape of
+     the layer has changed, because of an undo for example. */
+  if ((0 == strcmp (pspec->name, "box-width"))
+      || (0 == strcmp (pspec->name, "box-height")))
+    {
+      GimpRectangleTool *rect_tool = GIMP_RECTANGLE_TOOL (text_tool);
+      GimpDisplay       *display   = GIMP_TOOL (text_tool)->display;
+
+      if (gimp_rectangle_tool_rectangle_is_active (rect_tool, display))
+        {
+          text_tool->handle_rectangle_changed = FALSE;
+          gimp_rectangle_tool_frame_item (rect_tool,
+                                          GIMP_ITEM (text_tool->layer));
+          text_tool->handle_rectangle_changed = TRUE;
+        }
+    }
 }
 
 static gboolean
@@ -917,9 +1072,28 @@
 gimp_text_tool_layer_changed (GimpImage    *image,
                               GimpTextTool *text_tool)
 {
-  GimpLayer *layer = gimp_image_get_active_layer (image);
+  GimpLayer         *layer     = gimp_image_get_active_layer (image);
+  GimpRectangleTool *rect_tool = GIMP_RECTANGLE_TOOL (text_tool);
+  GimpDisplay       *display   = GIMP_TOOL (text_tool)->display;
 
   gimp_text_tool_set_drawable (text_tool, GIMP_DRAWABLE (layer), FALSE);
+
+  if (gimp_rectangle_tool_rectangle_is_active (rect_tool, display))
+    {
+      if (text_tool->layer)
+        {
+          if (! gimp_rectangle_tool_rectangle_is_new (rect_tool))
+            {
+              text_tool->handle_rectangle_changed = FALSE;
+              gimp_rectangle_tool_frame_item (rect_tool,
+                                              GIMP_ITEM (text_tool->layer));
+              text_tool->handle_rectangle_changed = TRUE;
+            }
+        }
+      else
+        gimp_rectangle_tool_control (GIMP_TOOL (rect_tool),
+                                     GIMP_TOOL_ACTION_HALT, display);
+    }
 }
 
 static void
@@ -1054,3 +1228,101 @@
         }
     }
 }
+
+static gboolean
+gimp_text_tool_rectangle_changed (GimpRectangleTool *rect_tool)
+{
+  GimpTextTool   *text_tool     = GIMP_TEXT_TOOL (rect_tool);
+  GimpText       *text          = text_tool->text;
+  GimpTextEditor *editor        = GIMP_TEXT_EDITOR (text_tool->editor);
+  GimpImage      *image         = text_tool->image;
+  GimpItem       *item ;
+  gint            x1, y1, x2, y2;
+
+  if (text_tool->handle_rectangle_changed)
+    {
+      g_object_get (rect_tool,
+                    "x1", &x1,
+                    "y1", &y1,
+                    "x2", &x2,
+                    "y2", &y2,
+                    NULL);
+
+      /* FIXME!  hideous kludge to cause a layer to be created */
+      if (! text)
+        {
+          gimp_text_editor_set_text (editor, "X", -1);
+          gimp_text_editor_set_text (editor, "", -1);
+        }
+
+      g_object_set (text_tool->proxy,
+                    "box-mode", GIMP_TEXT_BOX_FIXED,
+                    "box-width", (gdouble) (x2 - x1),
+                    "box-height", (gdouble) (y2 - y1),
+                    NULL);
+
+      gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TEXT,
+                               _("Reshape Text Layer"));
+      item = GIMP_ITEM (text_tool->layer);
+      gimp_item_translate (item,
+                           x1 - item->offset_x,
+                           y1 - item->offset_y,
+                           TRUE);
+      gimp_text_tool_apply (text_tool);
+      gimp_image_undo_group_end (image);
+    }
+
+  return TRUE;
+}
+
+/* this doesn't belong here but this is the only place
+   it is used at the moment -- Bill
+*/
+
+/**
+ * gimp_rectangle_tool_frame_item:
+ * @rect_tool: a #GimpRectangleTool interface
+ * @item:      a #GimpItem attached to the image on which a
+ *             rectangle is being shown.
+ * @signal:    whether to execute the "rectangle-changed"
+ *             function after setting the rectangle.
+ *
+ * Convenience function to set the corners of the rectangle to
+ * match the bounds of the specified item.  The rectangle tool
+ * must be active (i.e., showing a rectangle), and the item must be
+ * attached to the image on which the rectangle tool is active.
+ */
+void
+gimp_rectangle_tool_frame_item (GimpRectangleTool *rect_tool,
+                                GimpItem          *item)
+{
+  GimpDisplay *display    = GIMP_TOOL (rect_tool)->display;
+  gint         offset_x;
+  gint         offset_y;
+  gint         width;
+  gint         height;
+
+  g_return_if_fail (GIMP_IS_ITEM (item));
+  g_return_if_fail (gimp_item_is_attached (item));
+  g_return_if_fail ( (display->image == item->image) );
+  g_return_if_fail (gimp_rectangle_tool_rectangle_is_active (rect_tool, display));
+
+  width     = gimp_item_width (item);
+  height    = gimp_item_height (item);
+  gimp_item_offsets (item, &offset_x, &offset_y);
+
+  gimp_draw_tool_pause (GIMP_DRAW_TOOL (rect_tool));
+
+  g_object_set (rect_tool,
+                "x1", offset_x,
+                "y1", offset_y,
+                "x2", offset_x + width,
+                "y2", offset_y + height,
+                NULL);
+
+  gimp_rectangle_tool_set_function (rect_tool,
+                                    GIMP_RECTANGLE_TOOL_MOVING);
+
+  gimp_draw_tool_resume (GIMP_DRAW_TOOL (rect_tool));
+}
+
Index: app/tools/gimptexttool.h
===================================================================
--- app/tools/gimptexttool.h	(revision 25183)
+++ app/tools/gimptexttool.h	(working copy)
@@ -20,7 +20,7 @@
 #define __GIMP_TEXT_TOOL_H__
 
 
-#include "gimptool.h"
+#include "gimpdrawtool.h"
 
 
 #define GIMP_TYPE_TEXT_TOOL            (gimp_text_tool_get_type ())
@@ -37,7 +37,7 @@
 
 struct _GimpTextTool
 {
-  GimpTool       parent_instance;
+  GimpDrawTool   parent_instance;
 
   GimpText      *proxy;
   GList         *pending;
@@ -52,11 +52,13 @@
 
   GtkWidget     *editor;
   GtkWidget     *confirm_dialog;
+
+  gboolean       handle_rectangle_changed;
 };
 
 struct _GimpTextToolClass
 {
-  GimpToolClass  parent_class;
+  GimpDrawToolClass parent_class;
 };
 
 
Index: app/tools/gimprectangletool.c
===================================================================
--- app/tools/gimprectangletool.c	(revision 25183)
+++ app/tools/gimprectangletool.c	(working copy)
@@ -102,6 +102,11 @@
    */
 
   /*
+   * Is a rectangle currently being drawn?
+   */
+  gboolean                active;
+
+  /*
    * Wether or not the rectangle currently being rubber-banded was
    * created from scatch.
    */
@@ -777,6 +782,8 @@
   g_signal_connect_object (options, "notify",
                            G_CALLBACK (gimp_rectangle_tool_options_notify),
                            rect_tool, 0);
+
+  private->active = FALSE;
 }
 
 void
@@ -837,8 +844,12 @@
 
   gimp_draw_tool_pause (draw_tool);
 
-  if (display != tool->display)
+  if (! gimp_rectangle_tool_rectangle_is_active (rect_tool, display) ||
+      private->function == GIMP_RECTANGLE_TOOL_CREATING)
     {
+      if (gimp_rectangle_tool_rectangle_is_active (rect_tool, display))
+        gimp_rectangle_tool_halt (rect_tool);
+
       if (gimp_draw_tool_is_active (draw_tool))
         {
           gimp_display_shell_set_highlight (GIMP_DISPLAY_SHELL (draw_tool->display->shell),
@@ -921,7 +932,8 @@
 
   gimp_rectangle_tool_update_highlight (rect_tool);
 
-  gimp_tool_control_activate (tool->control);
+  if (! gimp_tool_control_is_active (tool->control))
+    gimp_tool_control_activate (tool->control);
 
   gimp_draw_tool_resume (draw_tool);
 }
@@ -944,6 +956,9 @@
   private   = GIMP_RECTANGLE_TOOL_GET_PRIVATE (tool);
   options   = GIMP_RECTANGLE_TOOL_GET_OPTIONS (tool);
 
+  if (! gimp_rectangle_tool_rectangle_is_active (rect_tool, display))
+    return;
+
   gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
 
   gimp_tool_control_halt (tool->control);
@@ -975,9 +990,8 @@
 
       /* When a dead area is clicked, don't execute. */
       if (private->function == GIMP_RECTANGLE_TOOL_DEAD)
-        break;
-
-      if (gimp_rectangle_tool_execute (rect_tool))
+        private->active = FALSE;
+      else if (gimp_rectangle_tool_execute (rect_tool))
         gimp_rectangle_tool_halt (rect_tool);
       break;
 
@@ -1340,12 +1354,12 @@
 
   g_return_val_if_fail (GIMP_IS_RECTANGLE_TOOL (tool), FALSE);
 
-  if (display != tool->display)
-    return FALSE;
-
   rect_tool = GIMP_RECTANGLE_TOOL (tool);
   private   = GIMP_RECTANGLE_TOOL_GET_PRIVATE (tool);
 
+  if (! gimp_rectangle_tool_rectangle_is_active (rect_tool, display))
+    return FALSE;
+
   switch (kevent->keyval)
     {
     case GDK_Up:
@@ -1479,7 +1493,7 @@
   private        = GIMP_RECTANGLE_TOOL_GET_PRIVATE (tool);
   rect_tool = GIMP_RECTANGLE_TOOL (tool);
 
-  if (tool->display != display)
+  if (! gimp_rectangle_tool_rectangle_is_active (rect_tool, display))
     return;
 
   if (private->suppress_updates)
@@ -1572,7 +1586,7 @@
   rect_tool = GIMP_RECTANGLE_TOOL (tool);
   private   = GIMP_RECTANGLE_TOOL_GET_PRIVATE (tool);
 
-  if (tool->display == display)
+  if (gimp_rectangle_tool_rectangle_is_active (rect_tool, display))
     {
       switch (private->function)
         {
@@ -1905,7 +1919,7 @@
   GimpRectangleToolPrivate *private = GIMP_RECTANGLE_TOOL_GET_PRIVATE (tool);
   GimpDisplayShell         *shell;
 
-  if (! tool->display)
+  if (! gimp_rectangle_tool_rectangle_is_active (rect_tool, tool->display))
     return TRUE;
 
   shell = GIMP_DISPLAY_SHELL (tool->display->shell);
@@ -1930,6 +1944,7 @@
   private = GIMP_RECTANGLE_TOOL_GET_PRIVATE (rect_tool);
 
   tool->display = display;
+  private->active = TRUE;
 
   g_signal_connect_object (tool->display->shell, "scrolled",
                            G_CALLBACK (gimp_rectangle_tool_shell_scrolled),
@@ -2009,11 +2024,16 @@
 {
   GimpTool                    *tool = GIMP_TOOL (rect_tool);
   GimpRectangleOptionsPrivate *options_private;
+  GimpRectangleToolPrivate    *private;
 
   options_private =
     GIMP_RECTANGLE_OPTIONS_GET_PRIVATE (gimp_tool_get_options (tool));
 
-  if (tool->display)
+  private = GIMP_RECTANGLE_TOOL_GET_PRIVATE (rect_tool);
+  private->active = FALSE;
+  private->is_new = FALSE;
+
+  if (gimp_rectangle_tool_rectangle_is_active (rect_tool, tool->display))
     {
       gimp_display_shell_set_highlight (GIMP_DISPLAY_SHELL (tool->display->shell),
                                         NULL);
@@ -2029,9 +2049,6 @@
   if (gimp_tool_control_is_active (tool->control))
     gimp_tool_control_halt (tool->control);
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
-
   gimp_rectangle_tool_set_function (rect_tool, GIMP_RECTANGLE_TOOL_INACTIVE);
 
   if (options_private->auto_shrink_button)
@@ -2190,7 +2207,7 @@
       return;
     }
 
-  if (! tool->display)
+  if (! gimp_rectangle_tool_rectangle_is_active (rect_tool, tool->display))
     return;
 
   if (! strcmp (pspec->name, "x"))
@@ -2272,8 +2289,8 @@
        * immedieately switch width and height of the pending
        * rectangle.
        */
-      if (options_private->fixed_rule_active                   &&
-          tool->display                              != NULL   &&
+      if (gimp_rectangle_tool_rectangle_is_active (rect_tool, tool->display) &&
+          options_private->fixed_rule_active                   &&
           tool->button_press_state                   == 0      &&
           tool->active_modifier_state                == 0      &&
           options_private->desired_fixed_size_width  == height &&
@@ -2330,8 +2347,8 @@
        * immedieately switch width and height of the pending
        * rectangle.
        */
-      if (options_private->fixed_rule_active               &&
-          tool->display               != NULL              &&
+      if (gimp_rectangle_tool_rectangle_is_active (rect_tool, tool->display) &&
+          options_private->fixed_rule_active               &&
           tool->button_press_state    == 0                 &&
           tool->active_modifier_state == 0                 &&
           lower_ratio                 <  new_inverse_ratio &&
@@ -2699,7 +2716,7 @@
   private   = GIMP_RECTANGLE_TOOL_GET_PRIVATE (rect_tool);
   highlight = FALSE;
 
-  if (! tool->display)
+  if (! gimp_rectangle_tool_rectangle_is_active (rect_tool, tool->display))
     return;
 
   shell = GIMP_DISPLAY_SHELL (tool->display->shell);
@@ -3946,7 +3963,7 @@
   *max_x = 0;
   *max_y = 0;
 
-  if (! tool->display)
+  if (! gimp_rectangle_tool_rectangle_is_active (rect_tool, tool->display))
     return;
 
   switch (constraint)
@@ -4116,3 +4133,35 @@
         break;
     }
 }
+
+
+/**
+ * gimp_rectangle_tool_rectangle_is_active:
+ *
+ * Returns a Boolean telling the caller whether a rectangle
+ * is currently being drawn on the specified display.
+ */
+gboolean
+gimp_rectangle_tool_rectangle_is_active (GimpRectangleTool *rect_tool,
+                                         GimpDisplay       *display)
+{
+  GimpTool              *tool      = GIMP_TOOL (rect_tool);
+
+  if (display != tool->display)
+    return FALSE;
+
+  return GIMP_RECTANGLE_TOOL_GET_PRIVATE (rect_tool)->active;
+}
+
+/**
+ * gimp_rectangle_tool_rectangle_is_narrow:
+ *
+ * Returns TRUE if the handles are being shown outside the
+ * rectangle, FALSE if they are inside
+ */
+gboolean
+gimp_rectangle_tool_rectangle_is_narrow (GimpRectangleTool *rect_tool)
+{
+  return GIMP_RECTANGLE_TOOL_GET_PRIVATE (rect_tool)->narrow_mode;
+}
+
Index: app/tools/gimprectangletool.h
===================================================================
--- app/tools/gimprectangletool.h	(revision 25183)
+++ app/tools/gimprectangletool.h	(working copy)
@@ -139,9 +139,12 @@
                                                      const gchar             *width_property,
                                                      const gchar             *height_property);
 gboolean    gimp_rectangle_tool_rectangle_is_new    (GimpRectangleTool       *rect_tool);
+gboolean    gimp_rectangle_tool_rectangle_is_narrow (GimpRectangleTool       *rect_tool);
 gboolean    gimp_rectangle_tool_point_in_rectangle  (GimpRectangleTool       *rect_tool,
                                                      gdouble                  x,
                                                      gdouble                  y);
+gboolean    gimp_rectangle_tool_rectangle_is_active (GimpRectangleTool       *rect_tool,
+                                                     GimpDisplay             *display);
 
 
 /*  convenience functions  */
Index: app/tools/gimptextoptions.c
===================================================================
--- app/tools/gimptextoptions.c	(revision 25183)
+++ app/tools/gimptextoptions.c	(working copy)
@@ -43,13 +43,14 @@
 
 #include "gimptextoptions.h"
 #include "gimptooloptions-gui.h"
+#include "gimprectangleoptions.h"
 
 #include "gimp-intl.h"
 
 
 enum
 {
-  PROP_0,
+  PROP_0 = GIMP_RECTANGLE_OPTIONS_PROP_LAST + 1,
   PROP_FONT_SIZE,
   PROP_UNIT,
   PROP_HINTING,
@@ -90,7 +91,9 @@
                                                    GimpContext  *context);
 
 
-G_DEFINE_TYPE (GimpTextOptions, gimp_text_options, GIMP_TYPE_TOOL_OPTIONS)
+G_DEFINE_TYPE_WITH_CODE (GimpTextOptions, gimp_text_options, GIMP_TYPE_TOOL_OPTIONS,
+                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_RECTANGLE_OPTIONS,
+                                                NULL))
 
 
 static void
@@ -171,6 +174,8 @@
                                 GIMP_VIEWABLE_MAX_BUTTON_SIZE,
                                 GIMP_VIEW_SIZE_SMALL,
                                 GIMP_PARAM_STATIC_STRINGS);
+
+  gimp_rectangle_options_install_properties (object_class);
 }
 
 static void
@@ -233,7 +238,7 @@
       break;
 
     default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      gimp_rectangle_options_get_property (object, property_id, value, pspec);
       break;
     }
 }
@@ -291,7 +296,7 @@
       break;
 
     default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      gimp_rectangle_options_set_property (object, property_id, value, pspec);
       break;
     }
 }
