[glabels] Added undo/redo feature



commit 73b70cb6f49f732eb826f145cd1c229f707abc7f
Author: Jim Evins <evins snaught com>
Date:   Tue Dec 22 22:57:17 2009 -0500

    Added undo/redo feature
    
    Checkpoint the label state before each user initiated change.  These
    checkpoint states are kept on an undo stack.  As the user pops items
    from the undo stack, the current state is pushed onto a redo stack.

 src/file.c                    |    9 +-
 src/glabels-batch.c           |    3 +-
 src/label-barcode.c           |   64 ++++--
 src/label-barcode.h           |   11 +-
 src/label-box.c               |   66 +++++--
 src/label-box.h               |    3 +-
 src/label-ellipse.c           |   66 ++++--
 src/label-ellipse.h           |    3 +-
 src/label-image.c             |   65 ++++--
 src/label-image.h             |    9 +-
 src/label-line.c              |   49 +++-
 src/label-line.h              |    3 +-
 src/label-object.c            |  182 ++++++++++-----
 src/label-object.h            |   89 +++++---
 src/label-text.c              |  182 ++++++++++++---
 src/label-text.h              |   12 +-
 src/label.c                   |  503 +++++++++++++++++++++++++++++++++++++----
 src/label.h                   |   24 ++-
 src/merge-properties-dialog.c |    2 +-
 src/object-editor.c           |   64 +++---
 src/template-designer.c       |    2 +-
 src/ui-commands.c             |   92 ++++++---
 src/ui-commands.h             |    6 +
 src/ui-property-bar.c         |    4 +-
 src/ui.c                      |   37 +++
 src/view-barcode.c            |   11 +-
 src/view-box.c                |   19 +-
 src/view-ellipse.c            |   19 +-
 src/view-image.c              |   19 +-
 src/view-line.c               |   11 +-
 src/view-text.c               |   10 +-
 src/view.c                    |    9 +-
 src/window.c                  |   25 ++
 src/xml-label-04.c            |   70 +++---
 src/xml-label.c               |   97 ++++----
 35 files changed, 1380 insertions(+), 460 deletions(-)
---
diff --git a/src/file.c b/src/file.c
index 5264efb..5a1b78c 100644
--- a/src/file.c
+++ b/src/file.c
@@ -142,8 +142,8 @@ new_response (GtkDialog *dialog,
 		template = lgl_db_lookup_template_from_name (sheet_name);
 
 		label = GL_LABEL(gl_label_new ());
-		gl_label_set_template (label, template);
-		gl_label_set_rotate_flag (label, rotate_flag);
+		gl_label_set_template (label, template, FALSE);
+		gl_label_set_rotate_flag (label, rotate_flag, FALSE);
 
 		lgl_template_free (template);
 
@@ -249,8 +249,9 @@ properties_response (GtkDialog *dialog,
 		template = lgl_db_lookup_template_from_name (sheet_name);
 
                 label = GL_LABEL(g_object_get_data (G_OBJECT (dialog), "label"));
-                gl_label_set_template (label, template);
-                gl_label_set_rotate_flag (label, rotate_flag);
+
+                gl_label_set_template (label, template, TRUE);
+                gl_label_set_rotate_flag (label, rotate_flag, TRUE);
 
 		break;
 
diff --git a/src/glabels-batch.c b/src/glabels-batch.c
index 3168f52..bd95d51 100644
--- a/src/glabels-batch.c
+++ b/src/glabels-batch.c
@@ -26,6 +26,7 @@
 
 #include <libglabels/libglabels.h>
 #include "merge-init.h"
+#include "template-history.h"
 #include "xml-label.h"
 #include "print.h"
 #include "print-op.h"
@@ -142,7 +143,7 @@ main (int argc, char **argv)
                         if (input != NULL) {
                                 if (merge != NULL) {
                                         gl_merge_set_src(merge, input);
-                                        gl_label_set_merge(label, merge);
+                                        gl_label_set_merge(label, merge, FALSE);
                                 } else {
                                         fprintf ( stderr,
                                                   _("cannot perform document merge with glabels file %s\n"),
diff --git a/src/label-barcode.c b/src/label-barcode.c
index 992f982..efc5bc9 100644
--- a/src/label-barcode.c
+++ b/src/label-barcode.c
@@ -69,7 +69,8 @@ static void  get_size                       (glLabelObject       *object,
 					     gdouble             *h);
 
 static void  set_line_color                 (glLabelObject       *object,
-					     glColorNode         *line_color);
+					     glColorNode         *line_color,
+                                             gboolean             checkpoint);
 
 static glColorNode *get_line_color          (glLabelObject       *object);
 
@@ -138,7 +139,8 @@ gl_label_barcode_finalize (GObject *object)
 /* NEW label "barcode" object.                                               */
 /*****************************************************************************/
 GObject *
-gl_label_barcode_new (glLabel *label)
+gl_label_barcode_new (glLabel *label,
+                      gboolean checkpoint)
 {
 	glLabelBarcode      *lbc;
 	glColorNode         *line_color_node;
@@ -147,13 +149,19 @@ gl_label_barcode_new (glLabel *label)
 
         if (label != NULL)
         {
-                gl_label_object_set_parent (GL_LABEL_OBJECT(lbc), label);
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Create barcode object"));
+                }
 
                 line_color_node = gl_color_node_new_default ();
 
                 line_color_node->color = gl_label_get_default_line_color(label);
 
                 lbc->priv->color_node = line_color_node;
+
+                gl_label_add_object (label, GL_LABEL_OBJECT (lbc));
+                gl_label_object_set_parent (GL_LABEL_OBJECT (lbc), label);
         }
 
 	return G_OBJECT (lbc);
@@ -185,9 +193,9 @@ copy (glLabelObject *dst_object,
 	gl_label_barcode_get_props (lbc, &id, &text_flag, &checksum_flag, &format_digits);
 	color_node = get_line_color (src_object);
 
-	gl_label_barcode_set_data (new_lbc, text_node);
-	gl_label_barcode_set_props (new_lbc, id, text_flag, checksum_flag, format_digits);
-	set_line_color (dst_object, color_node);
+	gl_label_barcode_set_data (new_lbc, text_node, FALSE);
+	gl_label_barcode_set_props (new_lbc, id, text_flag, checksum_flag, format_digits, FALSE);
+	set_line_color (dst_object, color_node, FALSE);
 
 	gl_color_node_free (&color_node);
 	gl_text_node_free (&text_node);
@@ -202,19 +210,27 @@ copy (glLabelObject *dst_object,
 /*****************************************************************************/
 void
 gl_label_barcode_set_data (glLabelBarcode *lbc,
-			   glTextNode     *text_node)
+			   glTextNode     *text_node,
+                           gboolean        checkpoint)
 {
+        glLabel *label;
+
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
 
-	if (!gl_text_node_equal (lbc->priv->text_node, text_node)) {
-
+	if (!gl_text_node_equal (lbc->priv->text_node, text_node))
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
+                        gl_label_checkpoint (label, _("Barcode data"));
+                }
+                
 		gl_text_node_free (&lbc->priv->text_node);
 		lbc->priv->text_node = gl_text_node_dup (text_node);
 
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -226,8 +242,11 @@ gl_label_barcode_set_props (glLabelBarcode *lbc,
 			    gchar          *id,
 			    gboolean        text_flag,
 			    gboolean        checksum_flag,
-			    guint           format_digits)
+			    guint           format_digits,
+                            gboolean        checkpoint)
 {
+        glLabel *label;
+
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
@@ -236,7 +255,13 @@ gl_label_barcode_set_props (glLabelBarcode *lbc,
 	     || (g_ascii_strcasecmp (lbc->priv->id, id) != 0)
 	     || (lbc->priv->text_flag != text_flag)
 	     || (lbc->priv->checksum_flag != checksum_flag)
-	     || (lbc->priv->format_digits != format_digits)) {
+	     || (lbc->priv->format_digits != format_digits))
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
+                        gl_label_checkpoint (label, _("Barcode property"));
+                }
 
 		lbc->priv->id               = g_strdup (id);
 		lbc->priv->text_flag        = text_flag;
@@ -244,7 +269,6 @@ gl_label_barcode_set_props (glLabelBarcode *lbc,
 		lbc->priv->format_digits    = format_digits;
 
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -349,14 +373,22 @@ get_size (glLabelObject *object,
 /*---------------------------------------------------------------------------*/
 static void
 set_line_color (glLabelObject *object,
-		glColorNode   *line_color_node)
+		glColorNode   *line_color_node,
+                gboolean       checkpoint)
 {
 	glLabelBarcode *lbarcode = (glLabelBarcode *)object;
+        glLabel        *label;
 
 	g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
 
-	if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) ) {
-		
+	if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) )
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbarcode));
+                        gl_label_checkpoint (label, _("Barcode data"));
+                }
+
 		gl_color_node_free (&(lbarcode->priv->color_node));
 		lbarcode->priv->color_node = gl_color_node_dup (line_color_node);
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(lbarcode));
diff --git a/src/label-barcode.h b/src/label-barcode.h
index 61fde06..388ee5d 100644
--- a/src/label-barcode.h
+++ b/src/label-barcode.h
@@ -52,17 +52,22 @@ struct _glLabelBarcodeClass {
 
 GType           gl_label_barcode_get_type  (void) G_GNUC_CONST;
 
-GObject        *gl_label_barcode_new       (glLabel        *label);
+GObject        *gl_label_barcode_new       (glLabel        *label,
+                                            gboolean        checkpoint);
 
 void            gl_label_barcode_set_data  (glLabelBarcode *lbc,
-					    glTextNode     *text_node);
+					    glTextNode     *text_node,
+                                            gboolean        checkpoint);
+
 void            gl_label_barcode_set_props (glLabelBarcode *lbc,
 					    gchar          *id,
 					    gboolean        text_flag,
 					    gboolean        checksum_flag,
-					    guint           format_digits);
+					    guint           format_digits,
+                                            gboolean        checkpoint);
 
 glTextNode     *gl_label_barcode_get_data  (glLabelBarcode *lbc);
+
 void            gl_label_barcode_get_props (glLabelBarcode *lbc,
 					    gchar         **id,
 					    gboolean       *text_flag,
diff --git a/src/label-box.c b/src/label-box.c
index 6104e72..2d714f8 100644
--- a/src/label-box.c
+++ b/src/label-box.c
@@ -20,6 +20,7 @@
 
 #include "label-box.h"
 
+#include <glib/gi18n.h>
 #include <glib.h>
 
 #include "debug.h"
@@ -51,13 +52,16 @@ static void    copy                       (glLabelObject   *dst_object,
 					   glLabelObject   *src_object);
 
 static void    set_fill_color             (glLabelObject   *object,
-					   glColorNode     *fill_color_node);
+					   glColorNode     *fill_color_node,
+                                           gboolean         checkpoint);
 
 static void    set_line_color             (glLabelObject   *object,
-					   glColorNode     *line_color_node);
+					   glColorNode     *line_color_node,
+                                           gboolean         checkpoint);
 
 static void    set_line_width             (glLabelObject   *object,
-					   gdouble          line_width);
+					   gdouble          line_width,
+                                           gboolean         checkpoint);
 
 static glColorNode*   get_fill_color      (glLabelObject   *object);
 
@@ -136,7 +140,8 @@ gl_label_box_finalize (GObject *object)
 /* NEW label "box" object.                                                   */
 /*****************************************************************************/
 GObject *
-gl_label_box_new (glLabel *label)
+gl_label_box_new (glLabel *label,
+                  gboolean checkpoint)
 {
 	glLabelBox          *lbox;
 	glColorNode         *fill_color_node;
@@ -146,7 +151,10 @@ gl_label_box_new (glLabel *label)
 
         if (label != NULL)
         {
-                gl_label_object_set_parent (GL_LABEL_OBJECT(lbox), label);
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Create box object"));
+                }
 
                 fill_color_node = gl_color_node_new_default ();
                 line_color_node = gl_color_node_new_default ();
@@ -157,6 +165,9 @@ gl_label_box_new (glLabel *label)
                 lbox->priv->line_width      = gl_label_get_default_line_width(label);
                 lbox->priv->line_color_node = line_color_node;
                 lbox->priv->fill_color_node = fill_color_node;
+
+                gl_label_add_object (label, GL_LABEL_OBJECT (lbox));
+                gl_label_object_set_parent (GL_LABEL_OBJECT (lbox), label);
         }
 
 	return G_OBJECT (lbox);
@@ -185,9 +196,9 @@ copy (glLabelObject *dst_object,
 	line_color_node = get_line_color (src_object);
 	fill_color_node = get_fill_color (src_object);
 
-	set_line_width (dst_object, line_width);
-	set_line_color (dst_object, line_color_node);
-	set_fill_color (dst_object, fill_color_node);
+	set_line_width (dst_object, line_width, FALSE);
+	set_line_color (dst_object, line_color_node, FALSE);
+	set_fill_color (dst_object, fill_color_node, FALSE);
 	
 	gl_color_node_free (&line_color_node);
 	gl_color_node_free (&fill_color_node);
@@ -201,21 +212,30 @@ copy (glLabelObject *dst_object,
 /*---------------------------------------------------------------------------*/
 static void
 set_fill_color (glLabelObject *object,
-		glColorNode   *fill_color_node)
+		glColorNode   *fill_color_node,
+                gboolean       checkpoint)
 {
 	glLabelBox *lbox = (glLabelBox *)object;
+        glLabel    *label;
 	
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (lbox && GL_IS_LABEL_BOX (lbox));
 
-	if (!gl_color_node_equal (lbox->priv->fill_color_node, fill_color_node)) {
+	if (!gl_color_node_equal (lbox->priv->fill_color_node, fill_color_node))
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbox));
+                        gl_label_checkpoint (label, _("Fill color"));
+                }
 
 		gl_color_node_free (&(lbox->priv->fill_color_node));
 		lbox->priv->fill_color_node = gl_color_node_dup (fill_color_node);
 
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(lbox));
 	}
+
 	gl_debug (DEBUG_LABEL, "END");
 }
 
@@ -225,13 +245,22 @@ set_fill_color (glLabelObject *object,
 /*---------------------------------------------------------------------------*/
 static void
 set_line_color (glLabelObject *object,
-		glColorNode   *line_color_node)
+		glColorNode   *line_color_node,
+                gboolean       checkpoint)
 {
 	glLabelBox *lbox = (glLabelBox *)object;
+        glLabel    *label;
 
 	g_return_if_fail (lbox && GL_IS_LABEL_BOX (lbox));
 
-	if ( !gl_color_node_equal (lbox->priv->line_color_node, line_color_node )) {
+	if ( !gl_color_node_equal (lbox->priv->line_color_node, line_color_node ))
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbox));
+                        gl_label_checkpoint (label, _("Line color"));
+                }
+
 		gl_color_node_free (&(lbox->priv->line_color_node));
 		lbox->priv->line_color_node = gl_color_node_dup (line_color_node);
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(lbox));
@@ -244,13 +273,22 @@ set_line_color (glLabelObject *object,
 /*---------------------------------------------------------------------------*/
 static void
 set_line_width (glLabelObject *object,
-		gdouble        line_width)
+		gdouble        line_width,
+                gboolean       checkpoint)
 {
 	glLabelBox *lbox = (glLabelBox *)object;
+        glLabel    *label;
 
 	g_return_if_fail (lbox && GL_IS_LABEL_BOX (lbox));
 
-	if ( lbox->priv->line_width != line_width ) {
+	if ( lbox->priv->line_width != line_width )
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbox));
+                        gl_label_checkpoint (label, _("Line width"));
+                }
+
 		lbox->priv->line_width = line_width;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(lbox));
 	}
diff --git a/src/label-box.h b/src/label-box.h
index fdd623f..21bb741 100644
--- a/src/label-box.h
+++ b/src/label-box.h
@@ -50,7 +50,8 @@ struct _glLabelBoxClass {
 
 GType         gl_label_box_get_type       (void) G_GNUC_CONST;
 
-GObject      *gl_label_box_new            (glLabel    *label);
+GObject      *gl_label_box_new            (glLabel    *label,
+                                           gboolean    checkpoint);
 
 G_END_DECLS
 
diff --git a/src/label-ellipse.c b/src/label-ellipse.c
index 42439ff..6dbc789 100644
--- a/src/label-ellipse.c
+++ b/src/label-ellipse.c
@@ -20,6 +20,7 @@
 
 #include "label-ellipse.h"
 
+#include <glib/gi18n.h>
 #include <glib.h>
 #include <math.h>
 
@@ -55,13 +56,16 @@ static void    copy                       (glLabelObject     *dst_object,
                                            glLabelObject     *src_object);
 
 static void    set_fill_color             (glLabelObject     *object,
-                                           glColorNode       *fill_color_node);
+                                           glColorNode       *fill_color_node,
+                                           gboolean           checkpoint);
 
 static void    set_line_color             (glLabelObject     *object,
-                                           glColorNode       *line_color_node);
+                                           glColorNode       *line_color_node,
+                                           gboolean           checkpoint);
 
 static void    set_line_width             (glLabelObject     *object,
-                                           gdouble            line_width);
+                                           gdouble            line_width,
+                                           gboolean           checkpoint);
 
 static glColorNode*   get_fill_color      (glLabelObject     *object);
 
@@ -140,7 +144,8 @@ gl_label_ellipse_finalize (GObject *object)
 /* NEW label "ellipse" object.                                               */
 /*****************************************************************************/
 GObject *
-gl_label_ellipse_new (glLabel *label)
+gl_label_ellipse_new (glLabel *label,
+                      gboolean checkpoint)
 {
 	glLabelEllipse      *lellipse;
 	glColorNode         *fill_color_node;
@@ -150,7 +155,10 @@ gl_label_ellipse_new (glLabel *label)
 
         if (label != NULL)
         {
-                gl_label_object_set_parent (GL_LABEL_OBJECT(lellipse), label);
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Create ellipse object"));
+                }
 
                 fill_color_node = gl_color_node_new_default ();
                 line_color_node = gl_color_node_new_default ();
@@ -161,6 +169,9 @@ gl_label_ellipse_new (glLabel *label)
                 lellipse->priv->line_width      = gl_label_get_default_line_width(label);
                 lellipse->priv->line_color_node = line_color_node;
                 lellipse->priv->fill_color_node = fill_color_node;
+
+                gl_label_add_object (label, GL_LABEL_OBJECT (lellipse));
+                gl_label_object_set_parent (GL_LABEL_OBJECT (lellipse), label);
         }
 
 	return G_OBJECT (lellipse);
@@ -189,9 +200,9 @@ copy (glLabelObject *dst_object,
 	line_color_node = get_line_color (src_object);
 	fill_color_node = get_fill_color (src_object);
 
-	set_line_width (dst_object, line_width);
-	set_line_color (dst_object, line_color_node);
-	set_fill_color (dst_object, fill_color_node);
+	set_line_width (dst_object, line_width, FALSE);
+	set_line_color (dst_object, line_color_node, FALSE);
+	set_fill_color (dst_object, fill_color_node, FALSE);
 
 	gl_color_node_free (&line_color_node);
 	gl_color_node_free (&fill_color_node);
@@ -205,13 +216,21 @@ copy (glLabelObject *dst_object,
 /*---------------------------------------------------------------------------*/
 static void
 set_fill_color (glLabelObject *object,
-		glColorNode   *fill_color_node)
+		glColorNode   *fill_color_node,
+                gboolean       checkpoint)
 {
 	glLabelEllipse *lellipse = (glLabelEllipse *)object;
+        glLabel        *label;
 
 	g_return_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse));
 
-	if (!gl_color_node_equal (lellipse->priv->fill_color_node, fill_color_node)) {
+	if (!gl_color_node_equal (lellipse->priv->fill_color_node, fill_color_node))
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lellipse));
+                        gl_label_checkpoint (label, _("Fill color"));
+                }
 
 		gl_color_node_free (&(lellipse->priv->fill_color_node));
 		lellipse->priv->fill_color_node = gl_color_node_dup (fill_color_node);
@@ -226,14 +245,22 @@ set_fill_color (glLabelObject *object,
 /*---------------------------------------------------------------------------*/
 static void
 set_line_color (glLabelObject *object,
-		glColorNode   *line_color_node)
+		glColorNode   *line_color_node,
+                gboolean       checkpoint)
 {
 	glLabelEllipse *lellipse = (glLabelEllipse *)object;
+        glLabel        *label;
 
 	g_return_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse));
 
-	if ( !gl_color_node_equal (lellipse->priv->line_color_node, line_color_node) ) {
-		
+	if ( !gl_color_node_equal (lellipse->priv->line_color_node, line_color_node) )
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lellipse));
+                        gl_label_checkpoint (label, _("Line color"));
+                }
+
 		gl_color_node_free (&(lellipse->priv->line_color_node));
 		lellipse->priv->line_color_node = gl_color_node_dup (line_color_node);
 		
@@ -247,13 +274,22 @@ set_line_color (glLabelObject *object,
 /*---------------------------------------------------------------------------*/
 static void
 set_line_width (glLabelObject *object,
-		gdouble        line_width)
+		gdouble        line_width,
+                gboolean       checkpoint)
 {
 	glLabelEllipse *lellipse = (glLabelEllipse *)object;
+        glLabel        *label;
 
 	g_return_if_fail (lellipse && GL_IS_LABEL_ELLIPSE (lellipse));
 
-	if ( lellipse->priv->line_width != line_width ) {
+	if ( lellipse->priv->line_width != line_width )
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lellipse));
+                        gl_label_checkpoint (label, _("Line width"));
+                }
+
 		lellipse->priv->line_width = line_width;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(lellipse));
 	}
diff --git a/src/label-ellipse.h b/src/label-ellipse.h
index d1a0122..93ed3be 100644
--- a/src/label-ellipse.h
+++ b/src/label-ellipse.h
@@ -50,7 +50,8 @@ struct _glLabelEllipseClass {
 
 GType           gl_label_ellipse_get_type       (void) G_GNUC_CONST;
 
-GObject        *gl_label_ellipse_new            (glLabel        *label);
+GObject        *gl_label_ellipse_new            (glLabel        *label,
+                                                 gboolean        checkpoint);
 
 G_END_DECLS
 
diff --git a/src/label-image.c b/src/label-image.c
index fe463b3..b24d1a7 100644
--- a/src/label-image.c
+++ b/src/label-image.c
@@ -22,6 +22,7 @@
 
 #include "label-image.h"
 
+#include <glib/gi18n.h>
 #include <glib.h>
 #include <gdk/gdk.h>
 
@@ -61,7 +62,8 @@ static void copy                         (glLabelObject     *dst_object,
 
 static void set_size                     (glLabelObject     *object,
                                           gdouble            w,
-                                          gdouble            h);
+                                          gdouble            h,
+                                          gboolean           checkpoint);
 
 static void draw_object                  (glLabelObject     *object,
                                           cairo_t           *cr,
@@ -122,13 +124,15 @@ static void
 gl_label_image_finalize (GObject *object)
 {
 	glLabelObject *lobject = GL_LABEL_OBJECT (object);
-	glLabelImage  *limage  = GL_LABEL_IMAGE (object);;
+	glLabelImage  *limage  = GL_LABEL_IMAGE (object);
+        glLabel       *label;
 	GHashTable    *pixbuf_cache;
 
 	g_return_if_fail (object && GL_IS_LABEL_IMAGE (object));
 
 	if (!limage->priv->filename->field_flag) {
-		pixbuf_cache = gl_label_get_pixbuf_cache (lobject->parent);
+                label = gl_label_object_get_parent (lobject);
+		pixbuf_cache = gl_label_get_pixbuf_cache (label);
 		gl_pixbuf_cache_remove_pixbuf (pixbuf_cache,
 					       limage->priv->filename->data);
 	}
@@ -143,13 +147,23 @@ gl_label_image_finalize (GObject *object)
 /* NEW label "image" object.                                                 */
 /*****************************************************************************/
 GObject *
-gl_label_image_new (glLabel *label)
+gl_label_image_new (glLabel *label,
+                    gboolean checkpoint)
 {
 	glLabelImage *limage;
 
 	limage = g_object_new (gl_label_image_get_type(), NULL);
 
-	gl_label_object_set_parent (GL_LABEL_OBJECT(limage), label);
+        if (label != NULL)
+        {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Create image object"));
+                }
+
+                gl_label_add_object (label, GL_LABEL_OBJECT (limage));
+                gl_label_object_set_parent (GL_LABEL_OBJECT (limage), label);
+        }
 
 	return G_OBJECT (limage);
 }
@@ -166,6 +180,7 @@ copy (glLabelObject *dst_object,
 	glLabelImage     *new_limage = (glLabelImage *)dst_object;
 	glTextNode       *filename;
 	GdkPixbuf        *pixbuf;
+        glLabel          *label;
 	GHashTable       *pixbuf_cache;
 
 	gl_debug (DEBUG_LABEL, "START");
@@ -179,12 +194,13 @@ copy (glLabelObject *dst_object,
 	if ( !filename->field_flag && (filename->data != NULL) ) {
 		pixbuf = limage->priv->pixbuf;
 		if ( pixbuf != default_pixbuf ) {
-			pixbuf_cache = gl_label_get_pixbuf_cache (dst_object->parent);
+                        label = gl_label_object_get_parent (dst_object);
+			pixbuf_cache = gl_label_get_pixbuf_cache (label);
 			gl_pixbuf_cache_add_pixbuf (pixbuf_cache, filename->data, pixbuf);
 		}
 	}
 
-	gl_label_image_set_filename (new_limage, filename);
+	gl_label_image_set_filename (new_limage, filename, FALSE);
 	gl_text_node_free (&filename);
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -197,7 +213,8 @@ copy (glLabelObject *dst_object,
 static void
 set_size (glLabelObject *object,
 	  gdouble        w,
-	  gdouble        h)
+	  gdouble        h,
+          gboolean       checkpoint)
 {
 	g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
@@ -211,7 +228,7 @@ set_size (glLabelObject *object,
                 h = MIN_IMAGE_SIZE;
         }
 
-	GL_LABEL_OBJECT_CLASS (gl_label_image_parent_class)->set_size (object, w, h);
+	GL_LABEL_OBJECT_CLASS (gl_label_image_parent_class)->set_size (object, w, h, checkpoint);
 }
 
 
@@ -220,9 +237,11 @@ set_size (glLabelObject *object,
 /*****************************************************************************/
 void
 gl_label_image_set_filename (glLabelImage *limage,
-			     glTextNode   *filename)
+			     glTextNode   *filename,
+                             gboolean      checkpoint)
 {
 	glTextNode  *old_filename;
+        glLabel     *label;
 	GHashTable  *pixbuf_cache;
 	GdkPixbuf   *pixbuf;
 	gdouble      image_w, image_h, aspect_ratio, w, h;
@@ -239,7 +258,14 @@ gl_label_image_set_filename (glLabelImage *limage,
 		return;
 	}
 
-	pixbuf_cache = gl_label_get_pixbuf_cache (GL_LABEL_OBJECT(limage)->parent);
+        label = gl_label_object_get_parent (GL_LABEL_OBJECT (limage));
+
+        if ( checkpoint )
+        {
+                gl_label_checkpoint (label, _("Set image"));
+        }
+
+	pixbuf_cache = gl_label_get_pixbuf_cache (label);
 
 	/* Remove reference to previous pixbuf from cache, if needed. */
 	if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
@@ -277,7 +303,7 @@ gl_label_image_set_filename (glLabelImage *limage,
 	} else {
 		w = h / aspect_ratio;
 	}
-	gl_label_object_set_size (GL_LABEL_OBJECT(limage), w, h);
+	gl_label_object_set_size (GL_LABEL_OBJECT(limage), w, h, FALSE);
 
 	gl_label_object_emit_changed (GL_LABEL_OBJECT(limage));
 
@@ -287,9 +313,11 @@ gl_label_image_set_filename (glLabelImage *limage,
 
 void
 gl_label_image_set_pixbuf (glLabelImage  *limage,
-                           GdkPixbuf     *pixbuf)
+                           GdkPixbuf     *pixbuf,
+                           gboolean       checkpoint)
 {
 	glTextNode  *old_filename;
+        glLabel     *label;
 	GHashTable  *pixbuf_cache;
         gchar       *name;
 	gdouble      image_w, image_h;
@@ -301,7 +329,14 @@ gl_label_image_set_pixbuf (glLabelImage  *limage,
 
 	old_filename = limage->priv->filename;
 
-	pixbuf_cache = gl_label_get_pixbuf_cache (GL_LABEL_OBJECT(limage)->parent);
+        label = gl_label_object_get_parent (GL_LABEL_OBJECT (limage));
+
+        if ( checkpoint )
+        {
+                gl_label_checkpoint (label, _("Set image"));
+        }
+
+	pixbuf_cache = gl_label_get_pixbuf_cache (label);
 
 	/* Remove reference to previous pixbuf from cache, if needed. */
 	if ( !old_filename->field_flag && (old_filename->data != NULL) ) {
@@ -322,7 +357,7 @@ gl_label_image_set_pixbuf (glLabelImage  *limage,
 
 	image_w = gdk_pixbuf_get_width (limage->priv->pixbuf);
 	image_h = gdk_pixbuf_get_height (limage->priv->pixbuf);
-	gl_label_object_set_size (GL_LABEL_OBJECT(limage), image_w, image_h);
+	gl_label_object_set_size (GL_LABEL_OBJECT(limage), image_w, image_h, FALSE);
 
 	gl_label_object_emit_changed (GL_LABEL_OBJECT(limage));
 
diff --git a/src/label-image.h b/src/label-image.h
index 237badd..218a2e7 100644
--- a/src/label-image.h
+++ b/src/label-image.h
@@ -52,13 +52,16 @@ struct _glLabelImageClass {
 
 GType            gl_label_image_get_type     (void) G_GNUC_CONST;
 
-GObject         *gl_label_image_new          (glLabel       *label);
+GObject         *gl_label_image_new          (glLabel       *label,
+                                              gboolean       checkpoint);
 
 void             gl_label_image_set_filename (glLabelImage  *limage,
-					      glTextNode    *filename);
+					      glTextNode    *filename,
+                                              gboolean       checkpoint);
 
 void             gl_label_image_set_pixbuf   (glLabelImage  *limage,
-					      GdkPixbuf     *pixbuf);
+					      GdkPixbuf     *pixbuf,
+                                              gboolean       checkpoint);
 
 glTextNode      *gl_label_image_get_filename (glLabelImage  *limage);
 
diff --git a/src/label-line.c b/src/label-line.c
index 676b9af..30ee7cf 100644
--- a/src/label-line.c
+++ b/src/label-line.c
@@ -20,6 +20,7 @@
 
 #include "label-line.h"
 
+#include <glib/gi18n.h>
 #include <glib.h>
 
 #include "debug.h"
@@ -50,10 +51,12 @@ static void    copy                       (glLabelObject     *dst_object,
 					   glLabelObject     *src_object);
 
 static void    set_line_color             (glLabelObject     *object,
-					   glColorNode       *line_color_node);
+					   glColorNode       *line_color_node,
+                                           gboolean           checkpoint);
 
 static void    set_line_width             (glLabelObject     *object,
-					   gdouble            line_width);
+					   gdouble            line_width,
+                                           gboolean           checkpoint);
 
 static glColorNode   *get_line_color      (glLabelObject     *object);
 
@@ -129,7 +132,8 @@ gl_label_line_finalize (GObject *object)
 /* NEW label "line" object.                                               */
 /*****************************************************************************/
 GObject *
-gl_label_line_new (glLabel *label)
+gl_label_line_new (glLabel *label,
+                   gboolean checkpoint)
 {
 	glLabelLine         *lline;
 	glColorNode         *line_color_node;
@@ -138,7 +142,10 @@ gl_label_line_new (glLabel *label)
 
         if (label != NULL)
         {
-                gl_label_object_set_parent (GL_LABEL_OBJECT(lline), label);
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Create line object"));
+                }
 
                 line_color_node = gl_color_node_new_default ();
 
@@ -146,6 +153,9 @@ gl_label_line_new (glLabel *label)
 
                 lline->priv->line_width      = gl_label_get_default_line_width(label);
                 lline->priv->line_color_node = line_color_node;
+
+                gl_label_add_object (label, GL_LABEL_OBJECT (lline));
+                gl_label_object_set_parent (GL_LABEL_OBJECT (lline), label);
         }
 
 	return G_OBJECT (lline);
@@ -172,8 +182,8 @@ copy (glLabelObject *dst_object,
 	line_width = get_line_width (src_object);
 	line_color_node = get_line_color (src_object);
 
-	set_line_width (dst_object, line_width);
-	set_line_color (dst_object, line_color_node);
+	set_line_width (dst_object, line_width, FALSE);
+	set_line_color (dst_object, line_color_node, FALSE);
 
 	gl_color_node_free (&line_color_node);
 	
@@ -186,14 +196,22 @@ copy (glLabelObject *dst_object,
 /*---------------------------------------------------------------------------*/
 static void
 set_line_color (glLabelObject *object,
-		glColorNode   *line_color_node)
+		glColorNode   *line_color_node,
+                gboolean       checkpoint)
 {
 	glLabelLine *lline = (glLabelLine *)object;
+        glLabel     *label;
 
 	g_return_if_fail (lline && GL_IS_LABEL_LINE (lline));
 
-	if ( !gl_color_node_equal (lline->priv->line_color_node, line_color_node)) {
-		
+	if ( !gl_color_node_equal (lline->priv->line_color_node, line_color_node))
+        {
+                if ( checkpoint )
+                {
+                        gl_label_object_get_parent (GL_LABEL_OBJECT (lline));
+                        gl_label_checkpoint (label, _("Line color"));
+                }
+
 		gl_color_node_free (&(lline->priv->line_color_node ));
 		lline->priv->line_color_node = gl_color_node_dup (line_color_node);
 		
@@ -207,13 +225,22 @@ set_line_color (glLabelObject *object,
 /*---------------------------------------------------------------------------*/
 static void
 set_line_width (glLabelObject *object,
-		gdouble        line_width)
+		gdouble        line_width,
+                gboolean       checkpoint)
 {
 	glLabelLine *lline = (glLabelLine *)object;
+        glLabel     *label;
 
 	g_return_if_fail (lline && GL_IS_LABEL_LINE (lline));
 
-	if ( lline->priv->line_width != line_width ) {
+	if ( lline->priv->line_width != line_width )
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (lline));
+                        gl_label_checkpoint (label, _("Line width"));
+                }
+
 		lline->priv->line_width = line_width;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(lline));
 	}
diff --git a/src/label-line.h b/src/label-line.h
index da11a57..7dbb82a 100644
--- a/src/label-line.h
+++ b/src/label-line.h
@@ -50,7 +50,8 @@ struct _glLabelLineClass {
 
 GType        gl_label_line_get_type       (void) G_GNUC_CONST;
 
-GObject     *gl_label_line_new            (glLabel     *label);
+GObject     *gl_label_line_new            (glLabel     *label,
+                                           gboolean     checkpoint);
 
 
 G_END_DECLS
diff --git a/src/label-object.c b/src/label-object.c
index da63b28..d3ffe97 100644
--- a/src/label-object.c
+++ b/src/label-object.c
@@ -22,6 +22,7 @@
 
 #include "label-object.h"
 
+#include <glib/gi18n.h>
 #include <glib.h>
 #include <math.h>
 
@@ -36,6 +37,7 @@
 
 #define DEFAULT_SHADOW_X_OFFSET (3.6)
 #define DEFAULT_SHADOW_Y_OFFSET (3.6)
+#define DEFAULT_SHADOW_COLOR    GL_COLOR_BLACK
 #define DEFAULT_SHADOW_OPACITY  (0.5)
 
 #define HANDLE_FILL_RGBA_ARGS      0.0,   0.75,  0.0,   0.4
@@ -54,6 +56,7 @@ struct _glLabelObjectPrivate {
 	gchar             *name;
 
         gboolean           selected_flag;
+        glLabel           *parent;
 
 	gdouble            x, y;
 	gdouble            w, h;
@@ -91,7 +94,8 @@ static void     gl_label_object_finalize  (GObject            *object);
 
 static void     set_size                  (glLabelObject      *object,
 					   gdouble             w,
-					   gdouble             h);
+					   gdouble             h,
+                                           gboolean            checkpoint);
 
 
 /*****************************************************************************/
@@ -144,6 +148,7 @@ gl_label_object_init (glLabelObject *object)
 	object->priv->shadow_x = DEFAULT_SHADOW_X_OFFSET;
 	object->priv->shadow_y = DEFAULT_SHADOW_Y_OFFSET;
 	object->priv->shadow_color_node = gl_color_node_new_default ();
+        object->priv->shadow_color_node->color = DEFAULT_SHADOW_COLOR;
 	object->priv->shadow_opacity = DEFAULT_SHADOW_OPACITY;
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -180,7 +185,7 @@ gl_label_object_new (glLabel *label)
 
 	object = g_object_new (gl_label_object_get_type(), NULL);
 
-	gl_label_object_set_parent (object, label);
+        gl_label_object_set_parent (object, label);
 
 	gl_debug (DEBUG_LABEL, "END");
 
@@ -209,23 +214,24 @@ gl_label_object_dup (glLabelObject *src_object,
 
 	dst_object = g_object_new (G_OBJECT_TYPE(src_object), NULL);
 
-	gl_label_object_set_parent (dst_object, label);
+        gl_label_object_set_parent (dst_object, label);
+        dst_object->priv->selected_flag = src_object->priv->selected_flag;
 
 	gl_label_object_get_position      (src_object, &x, &y);
-	gl_label_object_get_size          (src_object, &w, &h);
+	gl_label_object_get_raw_size      (src_object, &w, &h);
 	gl_label_object_get_matrix        (src_object, &matrix);
 	gl_label_object_get_shadow_offset (src_object, &shadow_x, &shadow_y);
 	shadow_color_node = gl_label_object_get_shadow_color   (src_object);
 	shadow_opacity    = gl_label_object_get_shadow_opacity (src_object);
 	shadow_state      = gl_label_object_get_shadow_state   (src_object);
 
-	gl_label_object_set_position (dst_object, x, y);
-	gl_label_object_set_size     (dst_object, w, h);
+	gl_label_object_set_position (dst_object, x, y, FALSE);
+	gl_label_object_set_size     (dst_object, w, h, FALSE);
 	gl_label_object_set_matrix   (dst_object, &matrix);
-	gl_label_object_set_shadow_offset  (dst_object, shadow_x, shadow_y);
-	gl_label_object_set_shadow_color   (dst_object, shadow_color_node);
-	gl_label_object_set_shadow_opacity (dst_object, shadow_opacity);
-	gl_label_object_set_shadow_state   (dst_object, shadow_state);
+	gl_label_object_set_shadow_offset  (dst_object, shadow_x, shadow_y, FALSE);
+	gl_label_object_set_shadow_color   (dst_object, shadow_color_node, FALSE);
+	gl_label_object_set_shadow_opacity (dst_object, shadow_opacity, FALSE);
+	gl_label_object_set_shadow_state   (dst_object, shadow_state, FALSE);
 
 	gl_color_node_free (&shadow_color_node);
 
@@ -262,25 +268,14 @@ gl_label_object_emit_changed (glLabelObject *object)
 /*****************************************************************************/
 void
 gl_label_object_set_parent (glLabelObject *object,
-			    glLabel       *label)
+                            glLabel       *label)
 {
-	glLabel *old_parent;
-
-	gl_debug (DEBUG_LABEL, "START");
-
-	g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
-	g_return_if_fail (label && GL_IS_LABEL (label));
+        gl_debug (DEBUG_LABEL, "START");
 
-	old_parent = object->parent;
-	if ( old_parent != NULL )
-        {
-                g_object_ref (object);
-		gl_label_delete_object( old_parent, object );
-	}
-        object->parent = label;
-	gl_label_add_object (label, object);
+        g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
+        g_return_if_fail (label && GL_IS_LABEL (label));
 
-        gl_label_object_emit_changed (object);
+        object->priv->parent = label;
 }
 
 
@@ -290,13 +285,13 @@ gl_label_object_set_parent (glLabelObject *object,
 glLabel *
 gl_label_object_get_parent (glLabelObject *object)
 {
-	gl_debug (DEBUG_LABEL, "START");
+        gl_debug (DEBUG_LABEL, "START");
 
-	g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
+        g_return_val_if_fail (object && GL_IS_LABEL_OBJECT (object), NULL);
 
-	gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 
-	return object->parent;
+        return object->priv->parent;
 }
 
 
@@ -372,7 +367,8 @@ gl_label_object_get_name (glLabelObject *object)
 void    
 gl_label_object_set_position (glLabelObject *object,
 			      gdouble        x,
-			      gdouble        y)
+			      gdouble        y,
+                              gboolean       checkpoint)
 {
 	gdouble  dx, dy;
 
@@ -382,6 +378,11 @@ gl_label_object_set_position (glLabelObject *object,
 
 	if ( (x != object->priv->x) || (y != object->priv->y) )
         {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Move"));
+                }
+
 		dx = x - object->priv->x;
 		dy = y - object->priv->y;
 
@@ -401,7 +402,8 @@ gl_label_object_set_position (glLabelObject *object,
 void    
 gl_label_object_set_position_relative (glLabelObject *object,
 				       gdouble        dx,
-				       gdouble        dy)
+				       gdouble        dy,
+                                       gboolean       checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -409,6 +411,11 @@ gl_label_object_set_position_relative (glLabelObject *object,
 
 	if ( (dx != 0.0) || (dy != 0.0) )
         {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Move"));
+                }
+
 		object->priv->x += dx;
 		object->priv->y += dy;
 
@@ -448,12 +455,18 @@ gl_label_object_get_position (glLabelObject *object,
 static void
 set_size (glLabelObject *object,
 	  gdouble        w,
-	  gdouble        h)
+	  gdouble        h,
+          gboolean       checkpoint)
 {
 	g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
 	if ( (object->priv->w != w) || (object->priv->h != h) )
         {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Resize"));
+                }
+
 		object->priv->w = w;
 		object->priv->h = h;
 
@@ -468,7 +481,8 @@ set_size (glLabelObject *object,
 void    
 gl_label_object_set_size (glLabelObject *object,
 			  gdouble        w,
-			  gdouble        h)
+			  gdouble        h,
+                          gboolean       checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -477,7 +491,7 @@ gl_label_object_set_size (glLabelObject *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h, checkpoint);
 
 		object->priv->aspect_ratio = h / w;
 	}
@@ -492,7 +506,8 @@ gl_label_object_set_size (glLabelObject *object,
 void    
 gl_label_object_set_size_honor_aspect (glLabelObject *object,
 				       gdouble        w,
-				       gdouble        h)
+				       gdouble        h,
+                                       gboolean       checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -510,7 +525,7 @@ gl_label_object_set_size_honor_aspect (glLabelObject *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_size != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_size (object, w, h, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -630,7 +645,8 @@ gl_label_object_can_text (glLabelObject     *object)
 /*****************************************************************************/
 void    
 gl_label_object_set_font_family (glLabelObject     *object,
-				 const gchar       *font_family)
+				 const gchar       *font_family,
+                                 gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -638,9 +654,8 @@ gl_label_object_set_font_family (glLabelObject     *object,
 
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family != NULL )
         {
-
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_font_family (object, font_family, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -652,7 +667,8 @@ gl_label_object_set_font_family (glLabelObject     *object,
 /****************************************************************************/
 void    
 gl_label_object_set_font_size (glLabelObject     *object,
-			       gdouble            font_size)
+			       gdouble            font_size,
+                               gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -661,7 +677,7 @@ gl_label_object_set_font_size (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_font_size (object, font_size, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -673,7 +689,8 @@ gl_label_object_set_font_size (glLabelObject     *object,
 /****************************************************************************/
 void    
 gl_label_object_set_font_weight (glLabelObject     *object,
-				 PangoWeight        font_weight)
+				 PangoWeight        font_weight,
+                                 gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -682,7 +699,7 @@ gl_label_object_set_font_weight (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_font_weight (object, font_weight, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -694,7 +711,8 @@ gl_label_object_set_font_weight (glLabelObject     *object,
 /****************************************************************************/
 void    
 gl_label_object_set_font_italic_flag (glLabelObject     *object,
-				      gboolean           font_italic_flag)
+				      gboolean           font_italic_flag,
+                                      gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -703,7 +721,7 @@ gl_label_object_set_font_italic_flag (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object, font_italic_flag);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_font_italic_flag (object, font_italic_flag, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -715,7 +733,8 @@ gl_label_object_set_font_italic_flag (glLabelObject     *object,
 /****************************************************************************/
 void    
 gl_label_object_set_text_alignment (glLabelObject     *object,
-				    PangoAlignment     text_alignment)
+				    PangoAlignment     text_alignment,
+                                    gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -724,7 +743,7 @@ gl_label_object_set_text_alignment (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object, text_alignment);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_text_alignment (object, text_alignment, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -736,7 +755,8 @@ gl_label_object_set_text_alignment (glLabelObject     *object,
 /****************************************************************************/
 void    
 gl_label_object_set_text_line_spacing (glLabelObject     *object,
-			               gdouble            text_line_spacing)
+			               gdouble            text_line_spacing,
+                                       gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -745,7 +765,7 @@ gl_label_object_set_text_line_spacing (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_text_line_spacing (object, text_line_spacing, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -757,7 +777,8 @@ gl_label_object_set_text_line_spacing (glLabelObject     *object,
 /****************************************************************************/
 void    
 gl_label_object_set_text_color (glLabelObject     *object,
-				glColorNode       *text_color_node)
+				glColorNode       *text_color_node,
+                                gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -766,7 +787,7 @@ gl_label_object_set_text_color (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color_node);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_text_color (object, text_color_node, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -968,7 +989,8 @@ gl_label_object_can_fill (glLabelObject     *object)
 /****************************************************************************/
 void    
 gl_label_object_set_fill_color (glLabelObject     *object,
-				glColorNode       *fill_color_node)
+				glColorNode       *fill_color_node,
+                                gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -977,7 +999,7 @@ gl_label_object_set_fill_color (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color_node);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_fill_color (object, fill_color_node, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -1035,7 +1057,8 @@ gl_label_object_can_line_color (glLabelObject     *object)
 /****************************************************************************/
 void    
 gl_label_object_set_line_color (glLabelObject     *object,
-				glColorNode       *line_color_node)
+				glColorNode       *line_color_node,
+                                gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -1044,7 +1067,7 @@ gl_label_object_set_line_color (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color_node);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_line_color (object, line_color_node, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -1102,7 +1125,8 @@ gl_label_object_can_line_width (glLabelObject     *object)
 /****************************************************************************/
 void    
 gl_label_object_set_line_width (glLabelObject     *object,
-				gdouble            line_width)
+				gdouble            line_width,
+                                gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -1111,7 +1135,7 @@ gl_label_object_set_line_width (glLabelObject     *object,
 	if ( GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width != NULL )
         {
 		/* We have an object specific method, use it */
-		GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width);
+		GL_LABEL_OBJECT_GET_CLASS(object)->set_line_width (object, line_width, checkpoint);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -1147,7 +1171,8 @@ gl_label_object_get_line_width (glLabelObject     *object)
 /****************************************************************************/
 void    
 gl_label_object_set_shadow_state (glLabelObject     *object,
-				  gboolean           state)
+				  gboolean           state,
+                                  gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -1155,7 +1180,14 @@ gl_label_object_set_shadow_state (glLabelObject     *object,
 
 	if (object->priv->shadow_state != state)
 	{
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Shadow state"));
+                }
+
 		object->priv->shadow_state = state;
+
+		gl_label_object_emit_changed (object);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -1182,7 +1214,8 @@ gl_label_object_get_shadow_state (glLabelObject     *object)
 void    
 gl_label_object_set_shadow_offset (glLabelObject     *object,
 				   gdouble            x,
-				   gdouble            y)
+				   gdouble            y,
+                                   gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -1190,8 +1223,15 @@ gl_label_object_set_shadow_offset (glLabelObject     *object,
 
 	if ( (x != object->priv->shadow_x) || (y != object->priv->shadow_y) )
 	{
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Shadow offset"));
+                }
+
 		object->priv->shadow_x = x;
 		object->priv->shadow_y = y;
+
+		gl_label_object_emit_changed (object);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -1222,7 +1262,8 @@ gl_label_object_get_shadow_offset (glLabelObject     *object,
 /****************************************************************************/
 void    
 gl_label_object_set_shadow_color (glLabelObject     *object,
-				  glColorNode       *color_node)
+				  glColorNode       *color_node,
+                                  gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -1230,8 +1271,15 @@ gl_label_object_set_shadow_color (glLabelObject     *object,
 
 	if ( !gl_color_node_equal (object->priv->shadow_color_node, color_node ))
 	{
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Shadow color"));
+                }
+
 		gl_color_node_free (&(object->priv->shadow_color_node));
 		object->priv->shadow_color_node = gl_color_node_dup (color_node);
+
+		gl_label_object_emit_changed (object);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -1257,7 +1305,8 @@ gl_label_object_get_shadow_color (glLabelObject     *object)
 /****************************************************************************/
 void    
 gl_label_object_set_shadow_opacity (glLabelObject     *object,
-				    gdouble            alpha)
+				    gdouble            alpha,
+                                    gboolean           checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -1265,7 +1314,14 @@ gl_label_object_set_shadow_opacity (glLabelObject     *object,
 
 	if (object->priv->shadow_opacity != alpha)
 	{
-		object->priv->shadow_opacity = alpha;
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (object->priv->parent, _("Shadow opacity"));
+                }
+
+                object->priv->shadow_opacity = alpha;
+
+		gl_label_object_emit_changed (object);
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
diff --git a/src/label-object.h b/src/label-object.h
index 3be4462..5875f8e 100644
--- a/src/label-object.h
+++ b/src/label-object.h
@@ -74,8 +74,6 @@ typedef struct _glLabelObjectPrivate   glLabelObjectPrivate;
 struct _glLabelObject {
         GObject               object;
 
-        glLabel              *parent;
-
         glLabelObjectPrivate *priv;
 };
 
@@ -88,37 +86,48 @@ struct _glLabelObjectClass {
 
         void              (*set_size)             (glLabelObject     *object,
                                                    gdouble            w,
-                                                   gdouble            h);
+                                                   gdouble            h,
+                                                   gboolean           checkpoint);
 
         void              (*set_font_family)      (glLabelObject     *object,
-                                                   const gchar       *font_family);
+                                                   const gchar       *font_family,
+                                                   gboolean           checkpoint);
 
         void              (*set_font_size)        (glLabelObject     *object,
-                                                   gdouble            font_size);
+                                                   gdouble            font_size,
+                                                   gboolean           checkpoint);
 
         void              (*set_font_weight)      (glLabelObject     *object,
-                                                   PangoWeight        font_weight);
+                                                   PangoWeight        font_weight,
+                                                   gboolean           checkpoint);
 
         void              (*set_font_italic_flag) (glLabelObject     *object,
-                                                   gboolean           font_italic_flag);
+                                                   gboolean           font_italic_flag,
+                                                   gboolean           checkpoint);
 
         void              (*set_text_alignment)   (glLabelObject     *object,
-                                                   PangoAlignment     text_alignment);
+                                                   PangoAlignment     text_alignment,
+                                                   gboolean           checkpoint);
 
         void              (*set_text_line_spacing)(glLabelObject     *object,
-                                                   gdouble            text_line_spacing);
+                                                   gdouble            text_line_spacing,
+                                                   gboolean           checkpoint);
 
         void              (*set_text_color)       (glLabelObject     *object,
-                                                   glColorNode       *text_color_node);
+                                                   glColorNode       *text_color_node,
+                                                   gboolean           checkpoint);
 
         void              (*set_fill_color)       (glLabelObject     *object,
-                                                   glColorNode       *fill_color_node);
+                                                   glColorNode       *fill_color_node,
+                                                   gboolean           checkpoint);
 
         void              (*set_line_color)       (glLabelObject     *object,
-                                                   glColorNode       *line_color_node);
+                                                   glColorNode       *line_color_node,
+                                                   gboolean           checkpoint);
 
         void              (*set_line_width)       (glLabelObject     *object,
-                                                   gdouble            line_width);
+                                                   gdouble            line_width,
+                                                   gboolean           checkpoint);
 
         void              (*get_size)             (glLabelObject     *object,
                                                    gdouble           *w,
@@ -218,63 +227,81 @@ gchar         *gl_label_object_get_name              (glLabelObject     *object)
 
 void           gl_label_object_set_position          (glLabelObject     *object,
                                                       gdouble            x,
-                                                      gdouble            y);
+                                                      gdouble            y,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_position_relative (glLabelObject     *object,
                                                       gdouble            dx,
-                                                      gdouble            dy);
+                                                      gdouble            dy,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_size              (glLabelObject     *object,
                                                       gdouble            w,
-                                                      gdouble            h);
+                                                      gdouble            h,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_size_honor_aspect (glLabelObject     *object,
                                                       gdouble            w,
-                                                      gdouble            h);
+                                                      gdouble            h,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_font_family       (glLabelObject     *object,
-                                                      const gchar       *font_family);
+                                                      const gchar       *font_family,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_font_size         (glLabelObject     *object,
-                                                      gdouble            font_size);
+                                                      gdouble            font_size,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_font_weight       (glLabelObject     *object,
-                                                      PangoWeight        font_weight);
+                                                      PangoWeight        font_weight,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_font_italic_flag  (glLabelObject     *object,
-                                                      gboolean           font_italic_flag);
+                                                      gboolean           font_italic_flag,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_text_alignment    (glLabelObject     *object,
-                                                      PangoAlignment     text_alignment);
+                                                      PangoAlignment     text_alignment,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_text_color        (glLabelObject     *object,
-                                                      glColorNode       *text_color_node);
+                                                      glColorNode       *text_color_node,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_text_line_spacing (glLabelObject     *object,
-                                                      gdouble            text_line_spacing);
+                                                      gdouble            text_line_spacing,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_fill_color        (glLabelObject     *object,
-                                                      glColorNode       *fill_color_node);
+                                                      glColorNode       *fill_color_node,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_line_color        (glLabelObject     *object,
-                                                      glColorNode       *line_color_node);
+                                                      glColorNode       *line_color_node,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_line_width        (glLabelObject     *object,
-                                                      gdouble            line_width);
+                                                      gdouble            line_width,
+                                                      gboolean           checkpoint);
 
 
 void           gl_label_object_set_shadow_state      (glLabelObject     *object,
-                                                      gboolean           state);
+                                                      gboolean           state,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_shadow_offset     (glLabelObject     *object,
                                                       gdouble            x,
-                                                      gdouble            y);
+                                                      gdouble            y,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_shadow_color      (glLabelObject     *object,
-                                                      glColorNode       *color_node);
+                                                      glColorNode       *color_node,
+                                                      gboolean           checkpoint);
 
 void           gl_label_object_set_shadow_opacity    (glLabelObject     *object,
-                                                      gdouble            alpha);
+                                                      gdouble            alpha,
+                                                      gboolean           checkpoint);
 
 
 void           gl_label_object_flip_horiz            (glLabelObject     *object);
diff --git a/src/label-text.c b/src/label-text.c
index aef20b8..56270b4 100644
--- a/src/label-text.c
+++ b/src/label-text.c
@@ -22,6 +22,7 @@
 
 #include "label-text.h"
 
+#include <glib/gi18n.h>
 #include <glib.h>
 #include <pango/pango.h>
 #include <math.h>
@@ -60,6 +61,8 @@ struct _glLabelTextPrivate {
         gboolean         size_changed;
         gdouble          w;
         gdouble          h;
+
+        gboolean         checkpoint_flag;
 };
 
 
@@ -77,6 +80,9 @@ static void gl_label_text_finalize      (GObject          *object);
 static void copy                        (glLabelObject    *dst_object,
 					 glLabelObject    *src_object);
 
+static void buffer_begin_user_action_cb (GtkTextBuffer    *textbuffer,
+                                         glLabelText      *ltext);
+
 static void buffer_changed_cb           (GtkTextBuffer    *textbuffer,
 					 glLabelText      *ltext);
 
@@ -85,25 +91,32 @@ static void get_size                    (glLabelObject    *object,
 					 gdouble          *h);
 
 static void set_font_family             (glLabelObject    *object,
-					 const gchar      *font_family);
+					 const gchar      *font_family,
+                                         gboolean          checkpoint);
 
 static void set_font_size               (glLabelObject    *object,
-					 gdouble           font_size);
+					 gdouble           font_size,
+                                         gboolean          checkpoint);
 
 static void set_font_weight             (glLabelObject    *object,
-					 PangoWeight       font_weight);
+					 PangoWeight       font_weight,
+                                         gboolean          checkpoint);
 
 static void set_font_italic_flag        (glLabelObject    *object,
-					 gboolean          font_italic_flag);
+					 gboolean          font_italic_flag,
+                                         gboolean          checkpoint);
 
 static void set_text_alignment          (glLabelObject    *object,
-					 PangoAlignment    text_alignment);
+					 PangoAlignment    text_alignment,
+                                         gboolean          checkpoint);
 
 static void set_text_line_spacing       (glLabelObject    *object,
-					 gdouble           text_line_spacing);
+					 gdouble           text_line_spacing,
+                                         gboolean          checkpoint);
 
 static void set_text_color              (glLabelObject    *object,
-					 glColorNode      *text_color_node);
+					 glColorNode      *text_color_node,
+                                         gboolean          checkpoint);
 
 static gchar          *get_font_family             (glLabelObject    *object);
 
@@ -205,6 +218,10 @@ gl_label_text_init (glLabelText *ltext)
 
         ltext->priv->size_changed      = TRUE;
 
+        ltext->priv->checkpoint_flag   = TRUE;
+
+	g_signal_connect (G_OBJECT(ltext->priv->buffer), "begin-user-action",
+			  G_CALLBACK(buffer_begin_user_action_cb), ltext);
 	g_signal_connect (G_OBJECT(ltext->priv->buffer), "changed",
 			  G_CALLBACK(buffer_changed_cb), ltext);
 }
@@ -234,7 +251,8 @@ gl_label_text_finalize (GObject *object)
 /** New Object Generator.                                                    */
 /*****************************************************************************/
 GObject *
-gl_label_text_new (glLabel *label)
+gl_label_text_new (glLabel *label,
+                   gboolean checkpoint)
 {
 	glLabelText   *ltext;
         glColorNode   *color_node;
@@ -243,7 +261,10 @@ gl_label_text_new (glLabel *label)
 
         if (label != NULL)
         {
-                gl_label_object_set_parent (GL_LABEL_OBJECT(ltext), label);
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Create text object"));
+                }
 
                 color_node = gl_color_node_new_default ();
 
@@ -256,6 +277,9 @@ gl_label_text_new (glLabel *label)
                 ltext->priv->align            = gl_label_get_default_text_alignment (label);
 		ltext->priv->color_node       = color_node;	  
                 ltext->priv->line_spacing     = gl_label_get_default_text_line_spacing (label);
+
+                gl_label_add_object (label, GL_LABEL_OBJECT (ltext));
+                gl_label_object_set_parent (GL_LABEL_OBJECT (ltext), label);
         }
 
 	return G_OBJECT (ltext);
@@ -281,13 +305,13 @@ copy (glLabelObject *dst_object,
 
 	lines = gl_label_text_get_lines (ltext);
 	text_color_node = get_text_color (src_object);
-	gl_label_text_set_lines (new_ltext, lines);
+	gl_label_text_set_lines (new_ltext, lines, FALSE);
 
 	new_ltext->priv->font_family      = g_strdup (ltext->priv->font_family);
 	new_ltext->priv->font_size        = ltext->priv->font_size;
 	new_ltext->priv->font_weight      = ltext->priv->font_weight;
 	new_ltext->priv->font_italic_flag = ltext->priv->font_italic_flag;
-	set_text_color (dst_object, text_color_node);
+	set_text_color (dst_object, text_color_node, FALSE);
 	new_ltext->priv->align            = ltext->priv->align;
 	new_ltext->priv->line_spacing     = ltext->priv->line_spacing;
 	new_ltext->priv->auto_shrink      = ltext->priv->auto_shrink;
@@ -308,7 +332,8 @@ copy (glLabelObject *dst_object,
 /*****************************************************************************/
 void
 gl_label_text_set_lines (glLabelText *ltext,
-			 GList       *lines)
+			 GList       *lines,
+                         gboolean     checkpoint)
 {
 	gchar *text;
 
@@ -316,28 +341,37 @@ gl_label_text_set_lines (glLabelText *ltext,
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
+        ltext->priv->checkpoint_flag = checkpoint;
+
 	text = gl_text_node_lines_expand (lines, NULL);
 	gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
 	g_free (text);
 
         ltext->priv->size_changed = TRUE;
 
+        ltext->priv->checkpoint_flag = TRUE;
+
 	gl_debug (DEBUG_LABEL, "END");
 }
 
 
 void
 gl_label_text_set_text (glLabelText *ltext,
-                        const gchar *text)
+                        const gchar *text,
+                        gboolean     checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
+        ltext->priv->checkpoint_flag = checkpoint;
+
 	gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
 
         ltext->priv->size_changed = TRUE;
 
+        ltext->priv->checkpoint_flag = TRUE;
+
 	gl_debug (DEBUG_LABEL, "END");
 }
 
@@ -393,9 +427,28 @@ gl_label_text_get_text (glLabelText      *ltext)
 /* Text buffer "changed" callback.                                           */
 /*****************************************************************************/
 static void
+buffer_begin_user_action_cb (GtkTextBuffer *textbuffer,
+                             glLabelText   *ltext)
+{
+        glLabel *label;
+
+        if ( ltext->priv->checkpoint_flag )
+        {
+                label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                gl_label_checkpoint (label, _("Typing"));
+        }
+}
+
+
+/*****************************************************************************/
+/* Text buffer "changed" callback.                                           */
+/*****************************************************************************/
+static void
 buffer_changed_cb (GtkTextBuffer *textbuffer,
                    glLabelText   *ltext)
 {
+        glLabel *label;
+
         ltext->priv->size_changed = TRUE;
 
 	gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
@@ -491,10 +544,12 @@ get_size (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_font_family (glLabelObject *object,
-		 const gchar   *font_family)
+		 const gchar   *font_family,
+                 gboolean       checkpoint)
 {
 	glLabelText    *ltext = (glLabelText *)object;
 	gchar          *good_font_family;
+        glLabel        *label;
 
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -511,6 +566,13 @@ set_font_family (glLabelObject *object,
 		}
 		g_free (ltext->priv->font_family);
 	}
+
+        if ( checkpoint )
+        {
+                label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                gl_label_checkpoint (label, _("Font family"));
+        }
+
 	ltext->priv->font_family = g_strdup (good_font_family);
 	g_free (good_font_family);
 
@@ -531,21 +593,28 @@ set_font_family (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_font_size (glLabelObject *object,
-	       gdouble        font_size)
+	       gdouble        font_size,
+               gboolean       checkpoint)
 {
 	glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	if (ltext->priv->font_size != font_size) {
+	if (ltext->priv->font_size != font_size)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Font size"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
 		ltext->priv->font_size = font_size;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -557,21 +626,28 @@ set_font_size (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_font_weight (glLabelObject   *object,
-		 PangoWeight      font_weight)
+		 PangoWeight      font_weight,
+                 gboolean         checkpoint)
 {
 	glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	if (ltext->priv->font_weight != font_weight) {
+	if (ltext->priv->font_weight != font_weight)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Font weight"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
 		ltext->priv->font_weight = font_weight;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -583,21 +659,28 @@ set_font_weight (glLabelObject   *object,
 /*****************************************************************************/
 static void
 set_font_italic_flag (glLabelObject *object,
-		      gboolean       font_italic_flag)
+		      gboolean       font_italic_flag,
+                      gboolean       checkpoint)
 {
 	glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	if (ltext->priv->font_italic_flag != font_italic_flag) {
+	if (ltext->priv->font_italic_flag != font_italic_flag)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Italic"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
 		ltext->priv->font_italic_flag = font_italic_flag;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -609,21 +692,28 @@ set_font_italic_flag (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_text_alignment (glLabelObject    *object,
-		    PangoAlignment    text_alignment)
+		    PangoAlignment    text_alignment,
+                    gboolean          checkpoint)
 {
 	glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	if (ltext->priv->align != text_alignment) {
+	if (ltext->priv->align != text_alignment)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Align text"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
 		ltext->priv->align = text_alignment;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -635,21 +725,28 @@ set_text_alignment (glLabelObject    *object,
 /*****************************************************************************/
 static void
 set_text_line_spacing (glLabelObject *object,
-	               gdouble        line_spacing)
+	               gdouble        line_spacing,
+                       gboolean       checkpoint)
 {
 	glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	if (ltext->priv->line_spacing != line_spacing) {
+	if (ltext->priv->line_spacing != line_spacing)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Line spacing"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
 		ltext->priv->line_spacing = line_spacing;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -661,21 +758,28 @@ set_text_line_spacing (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_text_color (glLabelObject *object,
-		glColorNode   *text_color_node)
+		glColorNode   *text_color_node,
+                gboolean       checkpoint)
 {
 	glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	if (!gl_color_node_equal (ltext->priv->color_node, text_color_node)) {
+	if (!gl_color_node_equal (ltext->priv->color_node, text_color_node))
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Text color"));
+                }
 
 		gl_color_node_free (&(ltext->priv->color_node));
 		ltext->priv->color_node = gl_color_node_dup (text_color_node);
 		
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -799,17 +903,25 @@ get_text_color (glLabelObject *object)
 /*****************************************************************************/
 void
 gl_label_text_set_auto_shrink (glLabelText      *ltext,
-			       gboolean          auto_shrink)
+			       gboolean          auto_shrink,
+                               gboolean          checkpoint)
 {
+        glLabel *label;
+
 	gl_debug (DEBUG_LABEL, "BEGIN");
 
 	g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-	if (ltext->priv->auto_shrink != auto_shrink) {
+	if (ltext->priv->auto_shrink != auto_shrink)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Auto shrink"));
+                }
 
 		ltext->priv->auto_shrink = auto_shrink;
 		gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
 	}
 
 	gl_debug (DEBUG_LABEL, "END");
diff --git a/src/label-text.h b/src/label-text.h
index a7eb845..b99a046 100644
--- a/src/label-text.h
+++ b/src/label-text.h
@@ -56,13 +56,16 @@ struct _glLabelTextClass {
 
 GType          gl_label_text_get_type        (void) G_GNUC_CONST;
 
-GObject       *gl_label_text_new             (glLabel          *label);
+GObject       *gl_label_text_new             (glLabel          *label,
+                                              gboolean          checkpoint);
 
 void           gl_label_text_set_lines       (glLabelText      *ltext,
-                                              GList            *lines);
+                                              GList            *lines,
+                                              gboolean          checkpoint);
 
 void           gl_label_text_set_text        (glLabelText      *ltext,
-                                              const gchar      *text);
+                                              const gchar      *text,
+                                              gboolean          checkpoint);
 
 GtkTextBuffer *gl_label_text_get_buffer      (glLabelText      *ltext);
 
@@ -71,7 +74,8 @@ gchar         *gl_label_text_get_text        (glLabelText      *ltext);
 GList         *gl_label_text_get_lines       (glLabelText      *ltext);
 
 void           gl_label_text_set_auto_shrink (glLabelText      *ltext,
-					      gboolean          auto_shrink);
+					      gboolean          auto_shrink,
+                                              gboolean          checkpoint);
 
 gboolean       gl_label_text_get_auto_shrink (glLabelText      *ltext);
 
diff --git a/src/label.c b/src/label.c
index e482ac3..6d28f4c 100644
--- a/src/label.c
+++ b/src/label.c
@@ -49,9 +49,11 @@ struct _glLabelPrivate {
 
 	gchar       *filename;
 	gint         compression;
-	gboolean     modified_flag;
 	gint         untitled_instance;
 
+	gboolean     modified_flag;
+        GTimeVal     time_stamp;
+
         lglTemplate *template;
         gboolean     rotate_flag;
 
@@ -80,6 +82,12 @@ struct _glLabelPrivate {
 	
 	/* Default object fill properties */
 	guint              default_fill_color;
+
+        /* Undo/Redo state */
+        GQueue      *undo_stack;
+        GQueue      *redo_stack;
+        gboolean     cp_cleared_flag;
+        gchar       *cp_desc;
 };
 
 typedef struct {
@@ -98,6 +106,21 @@ enum {
 	LAST_SIGNAL
 };
 
+typedef struct {
+        gchar       *description;
+
+	gboolean     modified_flag;
+        GTimeVal     time_stamp;
+
+        lglTemplate *template;
+        gboolean     rotate_flag;
+
+        GList       *object_list;
+
+	glMerge     *merge;
+
+} State;
+
 
 /*========================================================*/
 /* Private globals.                                       */
@@ -147,6 +170,17 @@ static void paste_image_received_cb(GtkClipboard     *clipboard,
                                     GdkPixbuf        *pixbuf,
                                     glLabel          *label);
 
+static void   stack_clear          (GQueue           *stack);
+static void   stack_push_state     (GQueue           *stack,
+                                    State            *state);
+static State *stack_pop_state      (GQueue           *stack);
+
+static State *state_new            (glLabel          *this,
+                                    const gchar      *description);
+static void   state_free           (State            *state);
+static void   state_restore        (State            *state,
+                                    glLabel          *this);
+
 
 /*****************************************************************************/
 /* Boilerplate object stuff.                                                 */
@@ -231,16 +265,19 @@ gl_label_init (glLabel *label)
 
 	label->priv = g_new0 (glLabelPrivate, 1);
 
-	label->priv->template     = NULL;
-	label->priv->rotate_flag  = FALSE;
-        label->priv->object_list  = NULL;
+	label->priv->template      = NULL;
+	label->priv->rotate_flag   = FALSE;
+        label->priv->object_list   = NULL;
 
 	label->priv->filename      = NULL;
 	label->priv->modified_flag = FALSE;
 	label->priv->compression   = 9;
 
-	label->priv->merge        = NULL;
-	label->priv->pixbuf_cache = gl_pixbuf_cache_new ();
+	label->priv->merge         = NULL;
+	label->priv->pixbuf_cache  = gl_pixbuf_cache_new ();
+
+        label->priv->undo_stack    = g_queue_new ();
+        label->priv->redo_stack    = g_queue_new ();
 
         /*
          * Defaults from preferences
@@ -285,6 +322,12 @@ gl_label_finalize (GObject *object)
 	gl_pixbuf_cache_free (label->priv->pixbuf_cache);
         g_free (label->priv->default_font_family);
 
+        stack_clear (label->priv->undo_stack);
+        stack_clear (label->priv->redo_stack);
+
+        g_queue_free (label->priv->undo_stack);
+        g_queue_free (label->priv->redo_stack);
+
 	g_free (label->priv);
 
 	G_OBJECT_CLASS (gl_label_parent_class)->finalize (object);
@@ -439,6 +482,8 @@ gl_label_clear_modified (glLabel *label)
 
 	if ( label->priv->modified_flag )
         {
+
+                g_get_current_time (&label->priv->time_stamp);
 		label->priv->modified_flag = FALSE;
 
 		g_signal_emit (G_OBJECT(label), signals[MODIFIED_CHANGED], 0);
@@ -519,7 +564,8 @@ end_selection_op (glLabel  *label)
 /****************************************************************************/
 void
 gl_label_set_template (glLabel           *label,
-		       const lglTemplate *template)
+		       const lglTemplate *template,
+                       gboolean           checkpoint)
 {
         gchar *name;
 
@@ -532,6 +578,11 @@ gl_label_set_template (glLabel           *label,
             !lgl_template_do_templates_match (template, label->priv->template))
         {
 
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Label properties"));
+                }
+
 		lgl_template_free (label->priv->template);
 		label->priv->template = lgl_template_dup (template);
 
@@ -562,7 +613,8 @@ gl_label_get_template (glLabel            *label)
 /****************************************************************************/
 void
 gl_label_set_rotate_flag (glLabel *label,
-			  gboolean rotate_flag)
+			  gboolean rotate_flag,
+                          gboolean checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
@@ -570,6 +622,11 @@ gl_label_set_rotate_flag (glLabel *label,
 
 	if (rotate_flag != label->priv->rotate_flag)
         {
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Label properties"));
+                }
+
 		label->priv->rotate_flag = rotate_flag;
 
                 do_modify (label);
@@ -632,12 +689,18 @@ gl_label_get_size (glLabel *label,
 /****************************************************************************/
 void
 gl_label_set_merge (glLabel *label,
-		    glMerge *merge)
+		    glMerge *merge,
+                    gboolean checkpoint)
 {
 	gl_debug (DEBUG_LABEL, "START");
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
+        if ( checkpoint )
+        {
+                gl_label_checkpoint (label, _("Merge properties"));
+        }
+
 	if ( label->priv->merge != NULL )
         {
 		g_object_unref (G_OBJECT(label->priv->merge));
@@ -689,7 +752,7 @@ gl_label_add_object (glLabel       *label,
 	g_return_if_fail (label && GL_IS_LABEL (label));
 	g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
 
-	object->parent = label;
+	gl_label_object_set_parent (object, label);
 	label->priv->object_list = g_list_append (label->priv->object_list, object);
 
         g_signal_connect (G_OBJECT (object), "changed",
@@ -749,6 +812,7 @@ gl_label_select_object (glLabel       *label,
 
         gl_label_object_select (object);
 
+        label->priv->cp_cleared_flag = TRUE;
 	g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -769,6 +833,7 @@ gl_label_unselect_object (glLabel       *label,
 
         gl_label_object_unselect (object);
 
+        label->priv->cp_cleared_flag = TRUE;
 	g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -795,6 +860,7 @@ gl_label_select_all (glLabel       *label)
                 gl_label_object_select (object);
         }
 
+        label->priv->cp_cleared_flag = TRUE;
 	g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -821,6 +887,7 @@ gl_label_unselect_all (glLabel       *label)
                 gl_label_object_unselect (object);
         }
 
+        label->priv->cp_cleared_flag = TRUE;
 	g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -863,6 +930,7 @@ gl_label_select_region (glLabel       *label,
                 }
 	}
 
+        label->priv->cp_cleared_flag = TRUE;
 	g_signal_emit (G_OBJECT(label), signals[SELECTION_CHANGED], 0);
 
 	gl_debug (DEBUG_LABEL, "END");
@@ -1112,6 +1180,8 @@ gl_label_delete_selection (glLabel       *label)
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
+        gl_label_checkpoint (label, _("Delete"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1143,6 +1213,10 @@ gl_label_raise_selection_to_top (glLabel       *label)
 
 	gl_debug (DEBUG_LABEL, "START");
 
+        gl_label_checkpoint (label, _("Bring to front"));
+
+        begin_selection_op (label);
+
         selection_list = gl_label_get_selection_list (label);
 
         for ( p = selection_list; p != NULL; p = p->next )
@@ -1157,6 +1231,8 @@ gl_label_raise_selection_to_top (glLabel       *label)
 
         do_modify (label);
 
+        end_selection_op (label);
+
 	gl_debug (DEBUG_LABEL, "END");
 }
 
@@ -1173,6 +1249,10 @@ gl_label_lower_selection_to_bottom (glLabel       *label)
 
 	gl_debug (DEBUG_LABEL, "START");
 
+        gl_label_checkpoint (label, _("Send to back"));
+
+        begin_selection_op (label);
+
         selection_list = gl_label_get_selection_list (label);
 
         for ( p = selection_list; p != NULL; p = p->next )
@@ -1187,6 +1267,8 @@ gl_label_lower_selection_to_bottom (glLabel       *label)
 
         do_modify (label);
 
+        end_selection_op (label);
+
 	gl_debug (DEBUG_LABEL, "END");
 }
 
@@ -1208,6 +1290,8 @@ gl_label_rotate_selection (glLabel *label,
 
         begin_selection_op (label);
 
+        gl_label_checkpoint (label, _("Rotate"));
+
         selection_list = gl_label_get_selection_list (label);
 
         for ( p = selection_list; p != NULL; p = p->next )
@@ -1241,6 +1325,8 @@ gl_label_rotate_selection_left (glLabel *label)
 
         begin_selection_op (label);
 
+        gl_label_checkpoint (label, _("Rotate left"));
+
         selection_list = gl_label_get_selection_list (label);
 
         for ( p = selection_list; p != NULL; p = p->next )
@@ -1272,6 +1358,8 @@ gl_label_rotate_selection_right (glLabel *label)
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
+        gl_label_checkpoint (label, _("Rotate right"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1305,6 +1393,8 @@ gl_label_flip_selection_horiz (glLabel *label)
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
+        gl_label_checkpoint (label, _("Flip horizontally"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1338,6 +1428,8 @@ gl_label_flip_selection_vert (glLabel *label)
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
+        gl_label_checkpoint (label, _("Flip verically"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1376,6 +1468,8 @@ gl_label_align_selection_left (glLabel *label)
 	g_return_if_fail (!gl_label_is_selection_empty (label) &&
 			  !gl_label_is_selection_atomic (label));
 
+        gl_label_checkpoint (label, _("Align left"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1401,7 +1495,7 @@ gl_label_align_selection_left (glLabel *label)
 
 		gl_label_object_get_extent (object, &obj_extent);
 		dx = x1_min - obj_extent.x1;
-		gl_label_object_set_position_relative (object, dx, 0.0);
+		gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
 	}
 
         g_list_free (selection_list);
@@ -1431,6 +1525,8 @@ gl_label_align_selection_right (glLabel *label)
 	g_return_if_fail (!gl_label_is_selection_empty (label) &&
 			  !gl_label_is_selection_atomic (label));
 
+        gl_label_checkpoint (label, _("Align right"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1456,7 +1552,7 @@ gl_label_align_selection_right (glLabel *label)
 
 		gl_label_object_get_extent (object, &obj_extent);
 		dx = x2_max - obj_extent.x2;
-		gl_label_object_set_position_relative (object, dx, 0.0);
+		gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
 	}
 
         g_list_free (selection_list);
@@ -1490,6 +1586,8 @@ gl_label_align_selection_hcenter (glLabel *label)
 	g_return_if_fail (!gl_label_is_selection_empty (label) &&
 			  !gl_label_is_selection_atomic (label));
 
+        gl_label_checkpoint (label, _("Align horizontal center"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1534,7 +1632,7 @@ gl_label_align_selection_hcenter (glLabel *label)
 
 		gl_label_object_get_extent (object, &obj_extent);
 		dx = xcenter - (obj_extent.x1 + obj_extent.x2)/2.0;
-		gl_label_object_set_position_relative (object, dx, 0.0);
+		gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
 	}
 
         g_list_free (selection_list);
@@ -1564,6 +1662,8 @@ gl_label_align_selection_top (glLabel *label)
 	g_return_if_fail (!gl_label_is_selection_empty (label) &&
 			  !gl_label_is_selection_atomic (label));
 
+        gl_label_checkpoint (label, _("Align tops"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1589,7 +1689,7 @@ gl_label_align_selection_top (glLabel *label)
 
 		gl_label_object_get_extent (object, &obj_extent);
 		dy = y1_min - obj_extent.y1;
-		gl_label_object_set_position_relative (object, 0.0, dy);
+		gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
 	}
 
         g_list_free (selection_list);
@@ -1619,6 +1719,8 @@ gl_label_align_selection_bottom (glLabel *label)
 	g_return_if_fail (!gl_label_is_selection_empty (label) &&
 			  !gl_label_is_selection_atomic (label));
 
+        gl_label_checkpoint (label, _("Align bottoms"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1644,7 +1746,7 @@ gl_label_align_selection_bottom (glLabel *label)
 
 		gl_label_object_get_extent (object, &obj_extent);
 		dy = y2_max - obj_extent.y2;
-		gl_label_object_set_position_relative (object, 0.0, dy);
+		gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
 	}
 
         g_list_free (selection_list);
@@ -1678,6 +1780,8 @@ gl_label_align_selection_vcenter (glLabel *label)
 	g_return_if_fail (!gl_label_is_selection_empty (label) &&
 			  !gl_label_is_selection_atomic (label));
 
+        gl_label_checkpoint (label, _("Align vertical center"));
+
         begin_selection_op (label);
 
         selection_list = gl_label_get_selection_list (label);
@@ -1722,7 +1826,7 @@ gl_label_align_selection_vcenter (glLabel *label)
 
 		gl_label_object_get_extent (object, &obj_extent);
 		dy = ycenter - (obj_extent.y1 + obj_extent.y2)/2.0;
-		gl_label_object_set_position_relative (object, 0.0, dy);
+		gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
 	}
 
         g_list_free (selection_list);
@@ -1754,6 +1858,8 @@ gl_label_center_selection_horiz (glLabel *label)
 
 	g_return_if_fail (!gl_label_is_selection_empty (label));
 
+        gl_label_checkpoint (label, _("Center horizontally"));
+
         begin_selection_op (label);
 
 	gl_label_get_size (label, &w, &h);
@@ -1768,7 +1874,7 @@ gl_label_center_selection_horiz (glLabel *label)
 		gl_label_object_get_extent (object, &obj_extent);
 		x_obj_center = (obj_extent.x1 + obj_extent.x2) / 2.0;
 		dx = x_label_center - x_obj_center;
-		gl_label_object_set_position_relative (object, dx, 0.0);
+		gl_label_object_set_position_relative (object, dx, 0.0, FALSE);
 	}
         g_list_free (selection_list);
 
@@ -1799,6 +1905,8 @@ gl_label_center_selection_vert (glLabel *label)
 
 	g_return_if_fail (!gl_label_is_selection_empty (label));
 
+        gl_label_checkpoint (label, _("Center vertically"));
+
         begin_selection_op (label);
 
 	gl_label_get_size (label, &w, &h);
@@ -1813,7 +1921,7 @@ gl_label_center_selection_vert (glLabel *label)
 		gl_label_object_get_extent (object, &obj_extent);
 		y_obj_center = (obj_extent.y1 + obj_extent.y2) / 2.0;
 		dy = y_label_center - y_obj_center;
-		gl_label_object_set_position_relative (object, 0.0, dy);
+		gl_label_object_set_position_relative (object, 0.0, dy, FALSE);
 	}
         g_list_free (selection_list);
 
@@ -1847,7 +1955,7 @@ gl_label_move_selection (glLabel  *label,
         {
 		object = GL_LABEL_OBJECT (p->data);
 
-		gl_label_object_set_position_relative (object, dx, dy);
+		gl_label_object_set_position_relative (object, dx, dy, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -1880,7 +1988,7 @@ gl_label_set_selection_font_family (glLabel      *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_font_family (object, font_family);
+		gl_label_object_set_font_family (object, font_family, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -1913,7 +2021,7 @@ gl_label_set_selection_font_size (glLabel  *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_font_size (object, font_size);
+		gl_label_object_set_font_size (object, font_size, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -1939,16 +2047,19 @@ gl_label_set_selection_font_weight (glLabel      *label,
 
 	g_return_if_fail (label && GL_IS_LABEL (label));
 
+        begin_selection_op (label);
+
         selection_list = gl_label_get_selection_list (label);
 
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_font_weight (object, font_weight);
+		gl_label_object_set_font_weight (object, font_weight, TRUE);
 	}
 
         g_list_free (selection_list);
 
+        end_selection_op (label);
 
 	gl_debug (DEBUG_LABEL, "END");
 }
@@ -1976,7 +2087,7 @@ gl_label_set_selection_font_italic_flag (glLabel   *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_font_italic_flag (object, font_italic_flag);
+		gl_label_object_set_font_italic_flag (object, font_italic_flag, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -2009,7 +2120,7 @@ gl_label_set_selection_text_alignment (glLabel        *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_text_alignment (object, text_alignment);
+		gl_label_object_set_text_alignment (object, text_alignment, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -2042,7 +2153,7 @@ gl_label_set_selection_text_line_spacing (glLabel  *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_text_line_spacing (object, text_line_spacing);
+		gl_label_object_set_text_line_spacing (object, text_line_spacing, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -2075,7 +2186,7 @@ gl_label_set_selection_text_color (glLabel      *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_text_color (object, text_color_node);
+		gl_label_object_set_text_color (object, text_color_node, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -2108,7 +2219,7 @@ gl_label_set_selection_fill_color (glLabel      *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_fill_color (object, fill_color_node);
+		gl_label_object_set_fill_color (object, fill_color_node, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -2141,7 +2252,7 @@ gl_label_set_selection_line_color (glLabel      *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_line_color (object, line_color_node);
+		gl_label_object_set_line_color (object, line_color_node, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -2174,7 +2285,7 @@ gl_label_set_selection_line_width (glLabel  *label,
 	for (p = selection_list; p != NULL; p = p->next)
         {
 		object = GL_LABEL_OBJECT (p->data);
-		gl_label_object_set_line_width (object, line_width);
+		gl_label_object_set_line_width (object, line_width, TRUE);
 	}
 
         g_list_free (selection_list);
@@ -2245,14 +2356,14 @@ gl_label_copy_selection (glLabel       *label)
                  */
 		label_copy = GL_LABEL(gl_label_new ());
 
-		gl_label_set_template (label_copy, label->priv->template);
-		gl_label_set_rotate_flag (label_copy, label->priv->rotate_flag);
+		gl_label_set_template (label_copy, label->priv->template, FALSE);
+		gl_label_set_rotate_flag (label_copy, label->priv->rotate_flag, FALSE);
 
 		for (p = selection_list; p != NULL; p = p->next)
                 {
 			object = GL_LABEL_OBJECT (p->data);
 
-			gl_label_object_dup (object, label_copy);
+			gl_label_add_object (label_copy, gl_label_object_dup (object, label_copy));
 		}
 
                 data->xml_buffer = gl_xml_label_save_buffer (label_copy, &status);
@@ -2480,6 +2591,8 @@ paste_xml_received_cb (GtkClipboard     *clipboard,
 
 	gl_debug (DEBUG_LABEL, "START");
 
+        gl_label_checkpoint (label, _("Paste"));
+
         xml_buffer = (gchar *)gtk_selection_data_get_data (selection_data);
 
         /*
@@ -2494,6 +2607,7 @@ paste_xml_received_cb (GtkClipboard     *clipboard,
                 {
                         object = (glLabelObject *) p->data;
                         newobject = gl_label_object_dup (object, label);
+                        gl_label_add_object( label, newobject );
 
                         gl_label_select_object (label, newobject);
 
@@ -2519,11 +2633,13 @@ paste_text_received_cb (GtkClipboard     *clipboard,
 
 	gl_debug (DEBUG_LABEL, "START");
 
+        gl_label_checkpoint (label, _("Paste"));
+
         gl_label_unselect_all (label);
 
-        object = GL_LABEL_OBJECT (gl_label_text_new (label));
-        gl_label_text_set_text (GL_LABEL_TEXT (object), text);
-        gl_label_object_set_position (object, 18, 18);
+        object = GL_LABEL_OBJECT (gl_label_text_new (label, FALSE));
+        gl_label_text_set_text (GL_LABEL_TEXT (object), text, FALSE);
+        gl_label_object_set_position (object, 18, 18, FALSE);
 
         gl_label_select_object (label, object);
 
@@ -2543,11 +2659,13 @@ paste_image_received_cb (GtkClipboard     *clipboard,
 
 	gl_debug (DEBUG_LABEL, "START");
 
+        gl_label_checkpoint (label, _("Paste"));
+
         gl_label_unselect_all (label);
 
-        object = GL_LABEL_OBJECT (gl_label_image_new (label));
-        gl_label_image_set_pixbuf (GL_LABEL_IMAGE (object), pixbuf);
-        gl_label_object_set_position (object, 18, 18);
+        object = GL_LABEL_OBJECT (gl_label_image_new (label, FALSE));
+        gl_label_image_set_pixbuf (GL_LABEL_IMAGE (object), pixbuf, FALSE);
+        gl_label_object_set_position (object, 18, 18, FALSE);
 
         gl_label_select_object (label, object);
 
@@ -2975,12 +3093,101 @@ gl_label_get_handle_at (glLabel             *label,
 
 
 /****************************************************************************/
+/* Checkpoint state.                                                        */
+/****************************************************************************/
+void
+gl_label_checkpoint (glLabel       *this,
+                     const gchar   *description)
+{
+        State *state;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        /*
+         * Do not perform consecutive checkpoints that are identical.
+         * E.g. moving an object by dragging, would produce a large number
+         * of incremental checkpoints -- what we really want is a single
+         * checkpoint so that we can undo the entire dragging effort with
+         * one "undo"
+         */
+        if ( this->priv->cp_cleared_flag
+             || (this->priv->cp_desc == NULL)
+             || (strcmp (description, this->priv->cp_desc) != 0) )
+        {
+
+                /* Sever old redo "thread" */
+                stack_clear (this->priv->redo_stack);
+
+                /* Save state onto undo stack. */
+                state = state_new (this, description);
+                stack_push_state (this->priv->undo_stack, state);
+
+                /* Track consecutive checkpoints. */
+                this->priv->cp_cleared_flag = FALSE;
+                this->priv->cp_desc         = g_strdup (description);
+        }
+
+        gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
+/* Undo.                                                                    */
+/****************************************************************************/
+void
+gl_label_undo (glLabel       *this)
+{
+        State *state_old;
+        State *state_now;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        state_old = stack_pop_state (this->priv->undo_stack);
+        state_now = state_new (this, state_old->description);
+
+        stack_push_state (this->priv->redo_stack, state_now);
+
+        state_restore (state_old, this);
+        state_free (state_old);
+
+        this->priv->cp_cleared_flag = TRUE;
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
+/* Redo.                                                                    */
+/****************************************************************************/
+void
+gl_label_redo (glLabel       *this)
+{
+        State *state_old;
+        State *state_now;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        state_old = stack_pop_state (this->priv->redo_stack);
+        state_now = state_new (this, state_old->description);
+
+        stack_push_state (this->priv->undo_stack, state_now);
+
+        state_restore (state_old, this);
+        state_free (state_old);
+
+        this->priv->cp_cleared_flag = TRUE;
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
 /* Can undo?                                                                */
 /****************************************************************************/
 gboolean
-gl_label_can_undo (glLabel *label)
+gl_label_can_undo (glLabel *this)
 {
-	return FALSE;
+	return (!g_queue_is_empty (this->priv->undo_stack));
 }
 
 
@@ -2988,9 +3195,221 @@ gl_label_can_undo (glLabel *label)
 /* Can redo?                                                                */
 /****************************************************************************/
 gboolean
-gl_label_can_redo (glLabel *label)
+gl_label_can_redo (glLabel *this)
 {
-	return FALSE;
+	return (!g_queue_is_empty (this->priv->redo_stack));
+}
+
+
+/****************************************************************************/
+/* Get undo description string.                                             */
+/****************************************************************************/
+gchar *
+gl_label_get_undo_description (glLabel *this)
+{
+        State *state;
+        gchar *description;
+
+        state = g_queue_peek_head (this->priv->undo_stack);
+        if ( state )
+        {
+                description = g_strdup (state->description);
+        }
+        else
+        {
+                description = g_strdup ("");
+        }
+
+        return description;
+}
+
+
+/****************************************************************************/
+/* Get redo description string.                                             */
+/****************************************************************************/
+gchar *
+gl_label_get_redo_description (glLabel *this)
+{
+        State *state;
+        gchar *description;
+
+        state = g_queue_peek_head (this->priv->redo_stack);
+        if ( state )
+        {
+                description = g_strdup (state->description);
+        }
+        else
+        {
+                description = g_strdup ("");
+        }
+
+        return description;
+}
+
+
+/****************************************************************************/
+/* Clear undo or redo stack.                                                */
+/****************************************************************************/
+static void
+stack_clear (GQueue *stack)
+{
+        State *state;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        while ( (state = g_queue_pop_head (stack)) != NULL )
+        {
+                state_free (state);
+        }
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
+/* Push state onto stack.                                                   */
+/****************************************************************************/
+static void
+stack_push_state (GQueue *stack,
+                  State  *state)
+{
+	gl_debug (DEBUG_LABEL, "START");
+
+        g_queue_push_head( stack, state );
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
+/* Pop state from stack.                                                    */
+/****************************************************************************/
+static State *
+stack_pop_state (GQueue *stack)
+{
+        State *state;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        state = g_queue_pop_head (stack);
+
+	gl_debug (DEBUG_LABEL, "END");
+        return state;
+}
+
+
+/****************************************************************************/
+/* New state from label.                                                    */
+/****************************************************************************/
+static State *
+state_new (glLabel       *this,
+           const gchar   *description)
+{
+        State          *state;
+        GList          *p_obj;
+        glLabelObject  *object;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        state = g_new0 (State, 1);
+
+        state->description = g_strdup (description);
+
+        state->template    = lgl_template_dup (this->priv->template);
+        state->rotate_flag = this->priv->rotate_flag;
+
+        for ( p_obj = this->priv->object_list; p_obj != NULL; p_obj = p_obj->next )
+        {
+                object = GL_LABEL_OBJECT (p_obj->data);
+
+                state->object_list = g_list_append (state->object_list,
+                                                    gl_label_object_dup (object, this));
+        }
+
+        state->merge = gl_merge_dup (this->priv->merge);
+
+        state->modified_flag = this->priv->modified_flag;
+        state->time_stamp    = this->priv->time_stamp;
+
+
+	gl_debug (DEBUG_LABEL, "END");
+        return state;
+}
+
+
+/****************************************************************************/
+/* Restore label from saved state.                                          */
+/****************************************************************************/
+static void
+state_free (State   *state)
+{
+        GList          *p_obj;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        g_free (state->description);
+
+        lgl_template_free (state->template);
+        if ( state->merge )
+        {
+                g_object_unref (G_OBJECT (state->merge));
+        }
+
+        for ( p_obj = state->object_list; p_obj != NULL; p_obj = p_obj->next )
+        {
+                g_object_unref (G_OBJECT (p_obj->data));
+        }
+        g_list_free (state->object_list);
+
+        g_free (state);
+
+	gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/****************************************************************************/
+/* Restore label from saved state.                                          */
+/****************************************************************************/
+static void
+state_restore (State   *state,
+               glLabel *this)
+               
+{
+        GList          *p_obj, *p_next;
+        glLabelObject  *object;
+
+	gl_debug (DEBUG_LABEL, "START");
+
+        gl_label_set_rotate_flag (this, state->rotate_flag, FALSE);
+        gl_label_set_template (this, state->template, FALSE);
+
+        for ( p_obj = this->priv->object_list; p_obj != NULL; p_obj = p_next )
+        {
+                p_next = p_obj->next; /* Hold on to next; delete is destructive */
+                object = GL_LABEL_OBJECT (p_obj->data);
+
+                gl_label_delete_object (this, object);
+        }
+
+        for ( p_obj = state->object_list; p_obj != NULL; p_obj = p_obj->next )
+        {
+                object = GL_LABEL_OBJECT (p_obj->data);
+
+                gl_label_add_object (this, gl_label_object_dup (object, this));
+        }
+	g_signal_emit (G_OBJECT(this), signals[SELECTION_CHANGED], 0);
+
+        gl_label_set_merge (this, state->merge, FALSE);
+        
+
+        if ( !state->modified_flag &&
+             (state->time_stamp.tv_sec  == this->priv->time_stamp.tv_sec) &&
+             (state->time_stamp.tv_usec == this->priv->time_stamp.tv_usec) )
+        {
+                gl_label_clear_modified (this);
+        }
+
+	gl_debug (DEBUG_LABEL, "END");
 }
 
 
diff --git a/src/label.h b/src/label.h
index 5ff735b..aa18336 100644
--- a/src/label.h
+++ b/src/label.h
@@ -107,13 +107,15 @@ void          gl_label_clear_modified          (glLabel       *label);
 gboolean      gl_label_is_modified             (glLabel       *label);
 
 
-void               gl_label_set_template       (glLabel            *label,
-						const lglTemplate  *template);
+void          gl_label_set_template            (glLabel            *label,
+						const lglTemplate  *template,
+                                                gboolean            checkpoint);
 
 const lglTemplate *gl_label_get_template       (glLabel            *label);
 
 void          gl_label_set_rotate_flag         (glLabel       *label,
-						gboolean       rotate_flag);
+						gboolean       rotate_flag,
+                                                gboolean       checkpoint);
 
 gboolean      gl_label_get_rotate_flag         (glLabel       *label);
 
@@ -123,7 +125,8 @@ void          gl_label_get_size                (glLabel       *label,
 
 
 void          gl_label_set_merge               (glLabel       *label,
-						glMerge       *merge);
+						glMerge       *merge,
+                                                gboolean       checkpoint);
 
 glMerge      *gl_label_get_merge               (glLabel       *label);
 
@@ -335,16 +338,21 @@ glLabelObject *gl_label_get_handle_at          (glLabel             *label,
                                                 glLabelObjectHandle *handle);
 
 
-
-
-
 /*
  * Undo/Redo methods
  */
-gboolean      gl_label_can_undo                (glLabel       *label);
+void          gl_label_checkpoint              (glLabel       *label,
+                                                const gchar   *description);
 
+gboolean      gl_label_can_undo                (glLabel       *label);
 gboolean      gl_label_can_redo                (glLabel       *label);
 
+gchar        *gl_label_get_undo_description    (glLabel       *label);
+gchar        *gl_label_get_redo_description    (glLabel       *label);
+
+void          gl_label_undo                    (glLabel       *label);
+void          gl_label_redo                    (glLabel       *label);
+
 
 G_END_DECLS
 
diff --git a/src/merge-properties-dialog.c b/src/merge-properties-dialog.c
index 7141dc9..86e30f1 100644
--- a/src/merge-properties-dialog.c
+++ b/src/merge-properties-dialog.c
@@ -505,7 +505,7 @@ response_cb (glMergePropertiesDialog *dialog,
 	switch (response) {
 
 	case GTK_RESPONSE_OK:
-		gl_label_set_merge (dialog->priv->label, dialog->priv->merge);
+		gl_label_set_merge (dialog->priv->label, dialog->priv->merge, TRUE);
 		gtk_widget_hide (GTK_WIDGET (dialog));
 		break;
 	case GTK_RESPONSE_CANCEL:
diff --git a/src/object-editor.c b/src/object-editor.c
index ed5f676..1250d6c 100644
--- a/src/object-editor.c
+++ b/src/object-editor.c
@@ -753,6 +753,7 @@ object_changed_cb (glLabelObject  *object,
         gdouble          shadow_x, shadow_y;
         glColorNode     *shadow_color_node;
         gdouble          shadow_opacity;
+        glLabel         *label;
         glMerge         *merge;
 
         gl_debug (DEBUG_EDITOR, "BEGIN");
@@ -764,7 +765,8 @@ object_changed_cb (glLabelObject  *object,
         gl_label_object_get_position (object, &x, &y);
         gl_object_editor_set_position (editor, x, y);
 
-        merge = gl_label_get_merge (GL_LABEL(object->parent));
+        label = gl_label_object_get_parent (object);
+        merge = gl_label_get_merge (label);
 
 
         if ( GL_IS_LABEL_BOX (object) || GL_IS_LABEL_ELLIPSE (object) )
@@ -888,7 +890,6 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
 {
         glLabelObject     *object = editor->priv->object;
         gdouble            x, y;
-        gdouble            w, h;
         glColorNode       *line_color_node;
         gdouble            line_width;
         glColorNode       *fill_color_node;
@@ -902,6 +903,7 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
         gboolean           auto_shrink;
         glTextNode        *filename;
         const GdkPixbuf   *pixbuf;
+        gdouble            w, h;
         gdouble            image_w, image_h;
         gdouble            new_w, new_h;
         glTextNode        *bc_data;
@@ -920,21 +922,19 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
 
 
         gl_object_editor_get_position (editor, &x, &y);
-        gl_label_object_set_position (object, x, y);
+        gl_label_object_set_position (object, x, y, TRUE);
 
 
         if ( GL_IS_LABEL_BOX (object) || GL_IS_LABEL_ELLIPSE (object) )
         {
 
-                gl_object_editor_get_size (editor, &w, &h);
                 fill_color_node   = gl_object_editor_get_fill_color (editor);
                 line_color_node   = gl_object_editor_get_line_color (editor);
                 line_width        = gl_object_editor_get_line_width (editor);
 
-                gl_label_object_set_size (object, w, h);
-                gl_label_object_set_fill_color (object, fill_color_node);
-                gl_label_object_set_line_color (object, line_color_node);
-                gl_label_object_set_line_width (object, line_width);
+                gl_label_object_set_fill_color (object, fill_color_node, TRUE);
+                gl_label_object_set_line_color (object, line_color_node, TRUE);
+                gl_label_object_set_line_width (object, line_width, TRUE);
 
                 gl_color_node_free (&fill_color_node);
                 gl_color_node_free (&line_color_node);
@@ -943,13 +943,11 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
         else if (GL_IS_LABEL_LINE (object))
         {
 
-                gl_object_editor_get_lsize (editor, &w, &h);
                 line_color_node   = gl_object_editor_get_line_color (editor);
                 line_width        = gl_object_editor_get_line_width (editor);
 
-                gl_label_object_set_size (object, w, h);
-                gl_label_object_set_line_color (object, line_color_node);
-                gl_label_object_set_line_width (object, line_width);
+                gl_label_object_set_line_color (object, line_color_node, TRUE);
+                gl_label_object_set_line_width (object, line_width, TRUE);
 
                 gl_color_node_free (&line_color_node);
 
@@ -957,13 +955,12 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
         else if ( GL_IS_LABEL_IMAGE (object) )
         {
 
-                gl_object_editor_get_size (editor, &w, &h);
                 filename = gl_object_editor_get_image (editor);
 
-                gl_label_object_set_size (object, w, h);
-                gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
+                gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename, TRUE);
 
                 /* Setting filename may have modified the size. */
+                gl_object_editor_get_size (editor, &w, &h);
                 gl_label_object_get_size (object, &new_w, &new_h);
                 if ( (new_w != w) || (new_h != h) )
                 {
@@ -982,7 +979,6 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
         else if (GL_IS_LABEL_TEXT (object))
         {
 
-                gl_object_editor_get_size (editor, &w, &h);
                 font_family       = gl_object_editor_get_font_family (editor);
                 font_size         = gl_object_editor_get_font_size (editor);
                 font_weight       = gl_object_editor_get_font_weight (editor);
@@ -992,15 +988,14 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
                 text_line_spacing = gl_object_editor_get_text_line_spacing (editor);
                 auto_shrink       = gl_object_editor_get_text_auto_shrink (editor);
 
-                gl_label_object_set_size (object, w, h);
-                gl_label_object_set_font_family (object, font_family);
-                gl_label_object_set_font_size (object, font_size);
-                gl_label_object_set_font_weight (object, font_weight);
-                gl_label_object_set_font_italic_flag (object, font_italic_flag);
-                gl_label_object_set_text_color (object, text_color_node);
-                gl_label_object_set_text_alignment (object, align);
-                gl_label_object_set_text_line_spacing (object, text_line_spacing);
-                gl_label_text_set_auto_shrink (GL_LABEL_TEXT (object), auto_shrink);
+                gl_label_object_set_font_family (object, font_family, TRUE);
+                gl_label_object_set_font_size (object, font_size, TRUE);
+                gl_label_object_set_font_weight (object, font_weight, TRUE);
+                gl_label_object_set_font_italic_flag (object, font_italic_flag, TRUE);
+                gl_label_object_set_text_color (object, text_color_node, TRUE);
+                gl_label_object_set_text_alignment (object, align, TRUE);
+                gl_label_object_set_text_line_spacing (object, text_line_spacing, TRUE);
+                gl_label_text_set_auto_shrink (GL_LABEL_TEXT (object), auto_shrink, TRUE);
 
                 gl_color_node_free (&text_color_node);
                 g_free (font_family);
@@ -1009,17 +1004,15 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
         else if (GL_IS_LABEL_BARCODE (object))
         {
 
-                gl_object_editor_get_size (editor, &w, &h);
                 line_color_node = gl_object_editor_get_bc_color (editor);
                 bc_data = gl_object_editor_get_data (editor);
                 gl_object_editor_get_bc_style (editor,
                                                &id, &text_flag, &cs_flag, &format_digits);
 
-                gl_label_object_set_size (object, w, h);
-                gl_label_object_set_line_color (object, line_color_node);
-                gl_label_barcode_set_data (GL_LABEL_BARCODE(object), bc_data);
+                gl_label_object_set_line_color (object, line_color_node, TRUE);
+                gl_label_barcode_set_data (GL_LABEL_BARCODE(object), bc_data, TRUE);
                 gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
-                                            id, text_flag, cs_flag, format_digits);
+                                            id, text_flag, cs_flag, format_digits, TRUE);
 
                 gl_color_node_free (&line_color_node);
                 gl_text_node_free (&bc_data);
@@ -1033,11 +1026,10 @@ gl_object_editor_changed_cb (glObjectEditor *editor)
         shadow_color_node = gl_object_editor_get_shadow_color (editor);
         shadow_opacity    = gl_object_editor_get_shadow_opacity (editor);
 
-        gl_label_object_set_position (object, x, y);
-        gl_label_object_set_shadow_state (object, shadow_state);
-        gl_label_object_set_shadow_offset (object, shadow_x, shadow_y);
-        gl_label_object_set_shadow_color (object, shadow_color_node);
-        gl_label_object_set_shadow_opacity (object, shadow_opacity);
+        gl_label_object_set_shadow_state (object, shadow_state, TRUE);
+        gl_label_object_set_shadow_offset (object, shadow_x, shadow_y, TRUE);
+        gl_label_object_set_shadow_color (object, shadow_color_node, TRUE);
+        gl_label_object_set_shadow_opacity (object, shadow_opacity, TRUE);
 
         gl_color_node_free (&shadow_color_node);
 
@@ -1072,7 +1064,7 @@ gl_object_editor_size_changed_cb (glObjectEditor *editor)
                 gl_object_editor_get_size (editor, &w, &h);
         }
 
-        gl_label_object_set_size (object, w, h);
+        gl_label_object_set_size (object, w, h, TRUE);
 
 
         editor->priv->stop_signals = FALSE;
diff --git a/src/template-designer.c b/src/template-designer.c
index d668265..675ae98 100644
--- a/src/template-designer.c
+++ b/src/template-designer.c
@@ -1621,7 +1621,7 @@ print_test_cb (glTemplateDesigner      *dialog)
 	label = gl_label_new ();
 
 	template = build_template (dialog);
-	gl_label_set_template (GL_LABEL(label), template);
+	gl_label_set_template (GL_LABEL(label), template, FALSE);
 
 	print_op = gl_print_op_dialog_new (GL_LABEL(label));
 	gl_print_op_force_outline (GL_PRINT_OP (print_op));
diff --git a/src/ui-commands.c b/src/ui-commands.c
index e69679a..666b2e3 100644
--- a/src/ui-commands.c
+++ b/src/ui-commands.c
@@ -252,6 +252,42 @@ gl_ui_cmd_file_quit (GtkAction *action,
 
 
 /****************************************************************************/
+/** Edit/Undo command.                                                      */
+/****************************************************************************/
+void
+gl_ui_cmd_edit_undo (GtkAction *action,
+                     glWindow  *window)
+{
+        gl_debug (DEBUG_COMMANDS, "START");
+
+        g_return_if_fail (action && GTK_IS_ACTION(action));
+        g_return_if_fail (window && GL_IS_WINDOW(window));
+
+        gl_label_undo (GL_LABEL (GL_VIEW (window->view)->label));
+
+        gl_debug (DEBUG_COMMANDS, "END");
+}
+
+
+/****************************************************************************/
+/** Edit/Redo command.                                                      */
+/****************************************************************************/
+void
+gl_ui_cmd_edit_redo (GtkAction *action,
+                     glWindow  *window)
+{
+        gl_debug (DEBUG_COMMANDS, "START");
+
+        g_return_if_fail (action && GTK_IS_ACTION(action));
+        g_return_if_fail (window && GL_IS_WINDOW(window));
+
+        gl_label_redo (GL_LABEL (GL_VIEW (window->view)->label));
+
+        gl_debug (DEBUG_COMMANDS, "END");
+}
+
+
+/****************************************************************************/
 /** Edit/Cut command.                                                       */
 /****************************************************************************/
 void 
@@ -732,8 +768,8 @@ gl_ui_cmd_objects_raise (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_raise_selection_to_top (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_raise_selection_to_top (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -753,8 +789,8 @@ gl_ui_cmd_objects_lower (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_lower_selection_to_bottom (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_lower_selection_to_bottom (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -774,8 +810,8 @@ gl_ui_cmd_objects_rotate_left (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_rotate_selection_left (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_rotate_selection_left (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -795,8 +831,8 @@ gl_ui_cmd_objects_rotate_right (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_rotate_selection_right (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_rotate_selection_right (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -816,8 +852,8 @@ gl_ui_cmd_objects_flip_horiz (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_flip_selection_horiz (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_flip_selection_horiz (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -837,8 +873,8 @@ gl_ui_cmd_objects_flip_vert (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_flip_selection_vert (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_flip_selection_vert (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -858,8 +894,8 @@ gl_ui_cmd_objects_align_left (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_align_selection_left (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_align_selection_left (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -879,8 +915,8 @@ gl_ui_cmd_objects_align_right (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_align_selection_right (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_align_selection_right (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -900,8 +936,8 @@ gl_ui_cmd_objects_align_hcenter (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_align_selection_hcenter (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_align_selection_hcenter (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -921,8 +957,8 @@ gl_ui_cmd_objects_align_top (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_align_selection_top (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_align_selection_top (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -942,8 +978,8 @@ gl_ui_cmd_objects_align_bottom (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_align_selection_bottom (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_align_selection_bottom (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -963,8 +999,8 @@ gl_ui_cmd_objects_align_vcenter (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_align_selection_vcenter (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_align_selection_vcenter (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -984,8 +1020,8 @@ gl_ui_cmd_objects_center_horiz (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_center_selection_horiz (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_center_selection_horiz (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
@@ -1005,8 +1041,8 @@ gl_ui_cmd_objects_center_vert (GtkAction *action,
         g_return_if_fail (action && GTK_IS_ACTION(action));
         g_return_if_fail (window && GL_IS_WINDOW(window));
 
-        if (window->view != NULL) {
-                gl_label_center_selection_vert (GL_VIEW(window->view)->label);
+        if (window->label != NULL) {
+                gl_label_center_selection_vert (window->label);
         }
 
         gl_debug (DEBUG_COMMANDS, "END");
diff --git a/src/ui-commands.h b/src/ui-commands.h
index 42cfc89..aed362d 100644
--- a/src/ui-commands.h
+++ b/src/ui-commands.h
@@ -67,6 +67,12 @@ void gl_ui_cmd_edit_undo                (GtkAction   *action,
 void gl_ui_cmd_edit_redo                (GtkAction   *action,
 					 glWindow    *window);
 
+void gl_ui_cmd_edit_undo                (GtkAction   *action,
+					 glWindow    *window);
+
+void gl_ui_cmd_edit_redo                (GtkAction   *action,
+					 glWindow    *window);
+
 void gl_ui_cmd_edit_cut                 (GtkAction   *action,
 					 glWindow    *window);
 
diff --git a/src/ui-property-bar.c b/src/ui-property-bar.c
index bf2139d..345f21c 100644
--- a/src/ui-property-bar.c
+++ b/src/ui-property-bar.c
@@ -439,10 +439,10 @@ gl_ui_property_bar_set_label (glUIPropertyBar *this,
 
 	set_doc_items_sensitive (this, TRUE);
 
-	this->priv->label = GL_LABEL (g_object_ref (G_OBJECT (label)));
-
 	reset_to_default_properties (label, this);
 
+	this->priv->label = GL_LABEL (g_object_ref (G_OBJECT (label)));
+
 	g_signal_connect_swapped (G_OBJECT(label), "selection_changed",
 				  G_CALLBACK(selection_changed_cb), this);
 
diff --git a/src/ui.c b/src/ui.c
index a76b45c..b369f9d 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -175,6 +175,20 @@ static GtkActionEntry entries[] = {
 
 
 	/* Edit action entries. */
+	{ "EditUndo",
+	  GTK_STOCK_UNDO,
+	  N_("Undo"),
+	  "<control>Z",
+	  N_("Undo"),
+	  G_CALLBACK (gl_ui_cmd_edit_undo) },
+
+	{ "EditRedo",
+	  GTK_STOCK_REDO,
+	  N_("Redo"),
+	  "<shift><control>Z",
+	  N_("Redo"),
+	  G_CALLBACK (gl_ui_cmd_edit_redo) },
+
 	{ "EditCut",
 	  GTK_STOCK_CUT,
 	  N_("Cut"),
@@ -500,6 +514,9 @@ static const gchar *ui_info =
 "			<menuitem action='FileQuit' />"
 "		</menu>"
 "		<menu action='EditMenu'>"
+"			<menuitem action='EditUndo' />"
+"			<menuitem action='EditRedo' />"
+"			<separator />"
 "			<menuitem action='EditCut' />"
 "			<menuitem action='EditCopy' />"
 "			<menuitem action='EditPaste' />"
@@ -638,6 +655,8 @@ static gchar* doc_verbs [] = {
 	"/ui/MenuBar/FileMenu/FileSaveAs",
 	"/ui/MenuBar/FileMenu/FilePrint",
 	"/ui/MenuBar/FileMenu/FileClose",
+	"/ui/MenuBar/EditMenu/EditUndo",
+	"/ui/MenuBar/EditMenu/EditRedo",
 	"/ui/MenuBar/EditMenu/EditCut",
 	"/ui/MenuBar/EditMenu/EditCopy",
 	"/ui/MenuBar/EditMenu/EditDelete",
@@ -937,8 +956,26 @@ void
 gl_ui_update_undo_redo_verbs (GtkUIManager *ui,
 			      glLabel      *label)
 {
+        GtkWidget  *menu_item;
+        gchar      *description;
+        gchar      *menu_label;
+
 	gl_debug (DEBUG_UI, "START");
 
+        menu_item = gtk_ui_manager_get_widget (ui, "/MenuBar/EditMenu/EditUndo");
+        description = gl_label_get_undo_description (label);
+        menu_label = g_strdup_printf ("%s: %s", _("Undo"), description);
+        gtk_menu_item_set_label (GTK_MENU_ITEM (menu_item), menu_label);
+        g_free (menu_label);
+        g_free (description);
+
+        menu_item = gtk_ui_manager_get_widget (ui, "/MenuBar/EditMenu/EditRedo");
+        description = gl_label_get_redo_description (label);
+        menu_label = g_strdup_printf ("%s: %s", _("Redo"), description);
+        gtk_menu_item_set_label (GTK_MENU_ITEM (menu_item), menu_label);
+        g_free (menu_label);
+        g_free (description);
+
 	gl_ui_util_set_verb_sensitive (ui, "/ui/MenuBar/EditMenu/EditUndo",
 				       gl_label_can_undo (label));
 
diff --git a/src/view-barcode.c b/src/view-barcode.c
index 27a14f2..3f87b5b 100644
--- a/src/view-barcode.c
+++ b/src/view-barcode.c
@@ -94,10 +94,11 @@ gl_view_barcode_create_button_press_event   (glView *view,
 
         gl_label_unselect_all (view->label);
 
-        object = gl_label_barcode_new (view->label);
-        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+        object = gl_label_barcode_new (view->label, TRUE);
+
+        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
         text_node = gl_text_node_new_from_text ("123456789");
-        gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
+        gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node, FALSE);
 
         view->create_object = GL_LABEL_OBJECT (object);
         view->create_x0 = x;
@@ -113,7 +114,7 @@ gl_view_barcode_create_motion_event         (glView *view,
                                              gdouble x,
                                              gdouble y)
 {
-        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y);
+        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y, FALSE);
 }
 
 
@@ -125,7 +126,7 @@ gl_view_barcode_create_button_release_event (glView *view,
                                              gdouble x,
                                              gdouble y)
 {
-        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y);
+        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y, FALSE);
 }
 
 
diff --git a/src/view-box.c b/src/view-box.c
index 2dd259d..3c39219 100644
--- a/src/view-box.c
+++ b/src/view-box.c
@@ -93,9 +93,10 @@ gl_view_box_create_button_press_event   (glView *view,
 
         gl_label_unselect_all (view->label);
 
-        object = gl_label_box_new (view->label);
-        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
-        gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0);
+        object = gl_label_box_new (view->label, TRUE);
+
+        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
+        gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0, FALSE);
 			
         view->create_object = GL_LABEL_OBJECT (object);
         view->create_x0 = x;
@@ -114,10 +115,12 @@ gl_view_box_create_motion_event         (glView *view,
         gdouble w, h;
 
         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0));
+                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
+                                      FALSE);
+
         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
+        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
@@ -136,10 +139,12 @@ gl_view_box_create_button_release_event (glView *view,
                 y = view->create_y0 + 36.0;
         }
         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0));
+                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
+                                      FALSE);
+
         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
+        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
diff --git a/src/view-ellipse.c b/src/view-ellipse.c
index 7d286c2..1f0707c 100644
--- a/src/view-ellipse.c
+++ b/src/view-ellipse.c
@@ -93,9 +93,10 @@ gl_view_ellipse_create_button_press_event   (glView *view,
 
         gl_label_unselect_all (view->label);
 
-        object = gl_label_ellipse_new (view->label);
-        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
-        gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0);
+        object = gl_label_ellipse_new (view->label, TRUE);
+
+        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
+        gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0, FALSE);
 
         view->create_object = GL_LABEL_OBJECT (object);
         view->create_x0 = x;
@@ -114,10 +115,12 @@ gl_view_ellipse_create_motion_event     (glView *view,
         gdouble w, h;
 
         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0));
+                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
+                                      FALSE);
+
         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
+        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
@@ -136,10 +139,12 @@ gl_view_ellipse_create_button_release_event (glView *view,
                 y = view->create_y0 + 36.0;
         }
         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0));
+                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
+                                      FALSE);
+
         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
+        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
diff --git a/src/view-image.c b/src/view-image.c
index c0c5684..d335170 100644
--- a/src/view-image.c
+++ b/src/view-image.c
@@ -92,9 +92,10 @@ gl_view_image_create_button_press_event   (glView *view,
 
         gl_label_unselect_all (view->label);
 
-        object = gl_label_image_new (view->label);
-        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
-        gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0);
+        object = gl_label_image_new (view->label, TRUE);
+
+        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
+        gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0, FALSE);
 
         view->create_object = GL_LABEL_OBJECT (object);
         view->create_x0 = x;
@@ -113,10 +114,12 @@ gl_view_image_create_motion_event     (glView *view,
         gdouble w, h;
 
         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0));
+                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
+                                      FALSE);
+
         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
+        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
@@ -135,10 +138,12 @@ gl_view_image_create_button_release_event (glView *view,
                 y = view->create_y0 + 36.0;
         }
         gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0));
+                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
+                                      FALSE);
+
         w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
         h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
+        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
diff --git a/src/view-line.c b/src/view-line.c
index 2c7a0f2..5a91234 100644
--- a/src/view-line.c
+++ b/src/view-line.c
@@ -93,9 +93,10 @@ gl_view_line_create_button_press_event   (glView *view,
 
         gl_label_unselect_all (view->label);
 
-        object = gl_label_line_new (view->label);
-        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
-        gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0);
+        object = gl_label_line_new (view->label, TRUE);
+
+        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
+        gl_label_object_set_size (GL_LABEL_OBJECT(object), 0.0, 0.0, FALSE);
 
         view->create_object = GL_LABEL_OBJECT (object);
         view->create_x0 = x;
@@ -115,7 +116,7 @@ gl_view_line_create_motion_event     (glView *view,
 
         w = x - view->create_x0;
         h = y - view->create_y0;
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
+        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
@@ -135,7 +136,7 @@ gl_view_line_create_button_release_event (glView *view,
         }
         w = x - view->create_x0;
         h = y - view->create_y0;
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h);
+        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
diff --git a/src/view-text.c b/src/view-text.c
index 569a8c3..9668b79 100644
--- a/src/view-text.c
+++ b/src/view-text.c
@@ -96,11 +96,11 @@ gl_view_text_create_button_press_event   (glView *view,
 
         gl_label_unselect_all (view->label);
 
-        object = gl_label_text_new (view->label);
-        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+        object = gl_label_text_new (view->label, TRUE);
 
+        gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
         lines = gl_text_node_lines_new_from_text (_("Text"));
-        gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
+        gl_label_text_set_lines (GL_LABEL_TEXT(object), lines, FALSE);
 
         view->create_object = GL_LABEL_OBJECT (object);
         view->create_x0 = x;
@@ -116,7 +116,7 @@ gl_view_text_create_motion_event     (glView *view,
                                       gdouble x,
                                       gdouble y)
 {
-        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y);
+        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y, FALSE);
 }
 
 
@@ -128,7 +128,7 @@ gl_view_text_create_button_release_event (glView *view,
                                           gdouble x,
                                           gdouble y)
 {
-        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y);
+        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object), x, y, FALSE);
 }
 
 
diff --git a/src/view.c b/src/view.c
index f808e8f..6e742f6 100644
--- a/src/view.c
+++ b/src/view.c
@@ -1932,16 +1932,17 @@ resize_event (glView             *view,
                 g_print ("Invalid handle.\n");  /* Should not happen! */
 
         }
+
         if ( (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P1) &&
              (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P2) )
         {
                 if ( view->resize_honor_aspect )
                 {
-                        gl_label_object_set_size_honor_aspect (view->resize_object, w, h);
+                        gl_label_object_set_size_honor_aspect (view->resize_object, w, h, TRUE);
                 }
                 else
                 {
-                        gl_label_object_set_size (view->resize_object, w, h);
+                        gl_label_object_set_size (view->resize_object, w, h, TRUE);
                 }
 
                 /*
@@ -1984,7 +1985,7 @@ resize_event (glView             *view,
         }
         else
         {
-                gl_label_object_set_size (view->resize_object, dx, dy);
+                gl_label_object_set_size (view->resize_object, dx, dy, TRUE);
         }
 
         /*
@@ -1993,7 +1994,7 @@ resize_event (glView             *view,
         cairo_user_to_device (cr, &x0, &y0);
         cairo_restore (cr);
         cairo_device_to_user (cr, &x0, &y0);
-        gl_label_object_set_position (view->resize_object, x0, y0);
+        gl_label_object_set_position (view->resize_object, x0, y0, FALSE);
 }
 
 
diff --git a/src/window.c b/src/window.c
index 0d96806..2359a1b 100644
--- a/src/window.c
+++ b/src/window.c
@@ -105,6 +105,9 @@ static void     focus_widget_changed_cb(GtkWindow     *gtk_window,
 static void     set_copy_paste_sensitivity  (glWindow      *window,
                                              GtkWidget     *focus_widget);
 
+static void     label_changed_cb       (glLabel       *label,
+					glWindow      *window);
+
 
 /****************************************************************************/
 /* Boilerplate Object stuff.                                                */
@@ -442,6 +445,9 @@ gl_window_set_label (glWindow    *window,
         focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
         set_copy_paste_sensitivity (window, focus_widget);
 
+	g_signal_connect (G_OBJECT(label), "changed",
+			  G_CALLBACK(label_changed_cb), window);
+
 	gl_debug (DEBUG_WINDOW, "END");
 }
 
@@ -673,6 +679,25 @@ modified_changed_cb (glLabel  *label,
 
 
 /*---------------------------------------------------------------------------*/
+/** PRIVATE.  Label "changed" callback.                                      */
+/*---------------------------------------------------------------------------*/
+static void
+label_changed_cb (glLabel  *label,
+                  glWindow *window)
+{
+	gl_debug (DEBUG_WINDOW, "START");
+
+	g_return_if_fail (label && GL_IS_LABEL (label));
+	g_return_if_fail (window && GL_IS_WINDOW (window));
+
+	gl_ui_update_undo_redo_verbs (window->ui, label);
+
+	gl_debug (DEBUG_WINDOW, "END");
+}
+
+
+
+/*---------------------------------------------------------------------------*/
 /** PRIVATE.  Clipboard "owner change" callback.                             */
 /*---------------------------------------------------------------------------*/
 static void
diff --git a/src/xml-label-04.c b/src/xml-label-04.c
index 7fe639d..0e2b883 100644
--- a/src/xml-label-04.c
+++ b/src/xml-label-04.c
@@ -80,7 +80,7 @@ glLabel      *gl_xml_label_04_parse      (xmlNodePtr       root,
 	label = GL_LABEL (gl_label_new ());
 
 	rotate_flag = lgl_xml_get_prop_boolean (root, "rotate", FALSE);
-	gl_label_set_rotate_flag (label, rotate_flag);
+	gl_label_set_rotate_flag (label, rotate_flag, FALSE);
 
 	for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
 
@@ -92,28 +92,28 @@ glLabel      *gl_xml_label_04_parse      (xmlNodePtr       root,
 					*status = XML_LABEL_UNKNOWN_MEDIA;
 				}
 			} else if (xmlStrEqual (node->name, (xmlChar *)"Text")) {
-				object = gl_label_text_new (label);
+				object = gl_label_text_new (label, FALSE);
 				xml04_parse_object (node, GL_LABEL_OBJECT(object));
 				xml04_parse_text_props (node, GL_LABEL_TEXT(object));
 			} else if (xmlStrEqual (node->name, (xmlChar *)"Box")) {
-				object = gl_label_box_new (label);
+				object = gl_label_box_new (label, FALSE);
 				xml04_parse_object (node, GL_LABEL_OBJECT(object));
 				xml04_parse_box_props (node, GL_LABEL_BOX(object));
 			} else if (xmlStrEqual (node->name, (xmlChar *)"Line")) {
-				object = gl_label_line_new (label);
+				object = gl_label_line_new (label, FALSE);
 				xml04_parse_object (node, GL_LABEL_OBJECT(object));
 				xml04_parse_line_props (node, GL_LABEL_LINE(object));
 			} else if (xmlStrEqual (node->name, (xmlChar *)"Ellipse")) {
-				object = gl_label_ellipse_new (label);
+				object = gl_label_ellipse_new (label, FALSE);
 				xml04_parse_object (node, GL_LABEL_OBJECT(object));
 				xml04_parse_ellipse_props (node,
 							   GL_LABEL_ELLIPSE(object));
 			} else if (xmlStrEqual (node->name, (xmlChar *)"Image")) {
-				object = gl_label_image_new (label);
+				object = gl_label_image_new (label, FALSE);
 				xml04_parse_object (node, GL_LABEL_OBJECT(object));
 				xml04_parse_image_props (node, GL_LABEL_IMAGE(object));
 			} else if (xmlStrEqual (node->name, (xmlChar *)"Barcode")) {
-				object = gl_label_barcode_new (label);
+				object = gl_label_barcode_new (label, FALSE);
 				xml04_parse_object (node, GL_LABEL_OBJECT(object));
 				xml04_parse_barcode_props (node,
 							   GL_LABEL_BARCODE(object));
@@ -156,7 +156,7 @@ xml04_parse_media_description (xmlNodePtr node,
 		ret = TRUE;
 	}
 
-	gl_label_set_template (label, template);
+	gl_label_set_template (label, template, FALSE);
 
 	lgl_template_free (template);
 	xmlFree (template_name);
@@ -181,7 +181,7 @@ xml04_parse_object (xmlNodePtr    object_node,
 	x = lgl_xml_get_prop_double (object_node, "x", 0);
 	y = lgl_xml_get_prop_double (object_node, "y", 0);
 
-	gl_label_object_set_position (object, x, y);
+	gl_label_object_set_position (object, x, y, FALSE);
 
 	gl_debug (DEBUG_XML, "END");
 }
@@ -222,12 +222,12 @@ xml04_parse_text_props (xmlNodePtr    object_node,
 	color_node = gl_color_node_new_default ();
 	color_node->color = lgl_xml_get_prop_uint (object_node, "color", 0);
 
-	gl_label_object_set_font_family (GL_LABEL_OBJECT(object), (gchar *)font_family);
-	gl_label_object_set_font_size (GL_LABEL_OBJECT(object), font_size);
-	gl_label_object_set_font_weight (GL_LABEL_OBJECT(object), font_weight);
-	gl_label_object_set_font_italic_flag (GL_LABEL_OBJECT(object), font_italic_flag);
-	gl_label_object_set_text_color (GL_LABEL_OBJECT(object), color_node);
-	gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), align);
+	gl_label_object_set_font_family (GL_LABEL_OBJECT(object), (gchar *)font_family, FALSE);
+	gl_label_object_set_font_size (GL_LABEL_OBJECT(object), font_size, FALSE);
+	gl_label_object_set_font_weight (GL_LABEL_OBJECT(object), font_weight, FALSE);
+	gl_label_object_set_font_italic_flag (GL_LABEL_OBJECT(object), font_italic_flag, FALSE);
+	gl_label_object_set_text_color (GL_LABEL_OBJECT(object), color_node, FALSE);
+	gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), align, FALSE);
 	
 	gl_color_node_free (&color_node);
 
@@ -276,7 +276,7 @@ xml04_parse_text_props (xmlNodePtr    object_node,
 
 	}
 
-	gl_label_text_set_lines (object, lines);
+	gl_label_text_set_lines (object, lines, FALSE);
 
 	gl_text_node_lines_free (&lines);
 	xmlFree (font_family);
@@ -290,11 +290,11 @@ xml04_parse_text_props (xmlNodePtr    object_node,
 		break;
 	case PANGO_ALIGN_CENTER:
 		x -= w/2.0;
-		gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+		gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
 		break;
 	case PANGO_ALIGN_RIGHT:
 		x -= w;
-		gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+		gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
 		break;
 	default:
 		/* should not happen */
@@ -329,10 +329,10 @@ xml04_parse_box_props (xmlNodePtr    node,
 	fill_color_node = gl_color_node_new_default ();
 	fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
 
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
-	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
-	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
-	gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
+	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
+	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
+	gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node, FALSE);
 
 	gl_color_node_free (&line_color_node);
 	gl_color_node_free (&fill_color_node);
@@ -360,9 +360,9 @@ xml04_parse_line_props (xmlNodePtr    node,
 	line_color_node = gl_color_node_new_default ();
 	line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
 
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
-	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
-	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
+	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
+	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
 
 	gl_color_node_free (&line_color_node);
 	
@@ -394,10 +394,10 @@ xml04_parse_ellipse_props (xmlNodePtr     node,
 	fill_color_node = gl_color_node_new_default ();
 	fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
 
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
-	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
-	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
-	gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
+	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
+	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
+	gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node, FALSE);
 
 	gl_color_node_free (&line_color_node);
 	gl_color_node_free (&fill_color_node);
@@ -420,12 +420,12 @@ xml04_parse_image_props (xmlNodePtr    node,
 	filename = g_new0 (glTextNode, 1);
 	filename->field_flag = FALSE;
 	filename->data = (gchar *)xmlGetProp (node, (xmlChar *)"filename");
-	gl_label_image_set_filename (object, filename);
+	gl_label_image_set_filename (object, filename, FALSE);
 	gl_text_node_free (&filename);
 
 	w = lgl_xml_get_prop_double (node, "w", 0);
 	h = lgl_xml_get_prop_double (node, "h", 0);
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
 
 	gl_debug (DEBUG_XML, "END");
 }
@@ -457,8 +457,8 @@ xml04_parse_barcode_props (xmlNodePtr    node,
 	if (scale == 0.0) {
 		scale = 0.5; /* Set to a valid value */
 	}
-	gl_label_barcode_set_props (object, (gchar *)id, text_flag, TRUE, 0);
-	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color_node);
+	gl_label_barcode_set_props (object, (gchar *)id, text_flag, TRUE, 0, FALSE);
+	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color_node, FALSE);
 
 	child = node->xmlChildrenNode;
 	text_node = g_new0 (glTextNode, 1);
@@ -471,7 +471,7 @@ xml04_parse_barcode_props (xmlNodePtr    node,
 	} else {
 		g_message ("Unexpected Barcode child: \"%s\"", child->name);
 	}
-	gl_label_barcode_set_data (object, text_node);
+	gl_label_barcode_set_data (object, text_node, FALSE);
 
 	gl_color_node_free (&color_node);
 	gl_text_node_free (&text_node);
@@ -501,7 +501,7 @@ xml04_parse_merge_properties (xmlNodePtr node,
 	gl_merge_set_src (merge, (gchar *)string);
 	xmlFree (string);
 
-	gl_label_set_merge (label, merge);
+	gl_label_set_merge (label, merge, FALSE);
 
 	g_object_unref (G_OBJECT(merge));
 
diff --git a/src/xml-label.c b/src/xml-label.c
index 5d0fe9c..2fcf165 100644
--- a/src/xml-label.c
+++ b/src/xml-label.c
@@ -347,7 +347,7 @@ xml_parse_label (xmlNodePtr        root,
 				return NULL;
 			}
 			lgl_db_register_template (template);
-			gl_label_set_template (label, template);
+			gl_label_set_template (label, template, FALSE);
 			lgl_template_free (template);
 		} else if (lgl_xml_is_node (child_node, "Objects")) {
 			xml_parse_objects (child_node, label);
@@ -385,7 +385,7 @@ xml_parse_objects (xmlNodePtr  node,
 	gl_debug (DEBUG_XML, "START");
 
 	rotate_flag = lgl_xml_get_prop_boolean (node, "rotate", FALSE);
-	gl_label_set_rotate_flag (label, rotate_flag);
+	gl_label_set_rotate_flag (label, rotate_flag, FALSE);
 
 	for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
 
@@ -430,27 +430,27 @@ xml_parse_object_text (xmlNodePtr  node,
 
 	gl_debug (DEBUG_XML, "START");
 
-	object = gl_label_text_new (label);
+	object = gl_label_text_new (label, FALSE);
 
 	/* position attrs */
 	x = lgl_xml_get_prop_length (node, "x", 0.0);
 	y = lgl_xml_get_prop_length (node, "y", 0.0);
-	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
 
 	/* implied size attrs */
 	w = lgl_xml_get_prop_length (node, "w", 0);
 	h = lgl_xml_get_prop_length (node, "h", 0);
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
 
 	/* justify attr */
 	string = lgl_xml_get_prop_string (node, "justify", NULL);
 	align = gl_str_util_string_to_align (string);
 	g_free (string);
-	gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), align);
+	gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), align, FALSE);
 
 	/* auto_shrink attr */
 	auto_shrink = lgl_xml_get_prop_boolean (node, "auto_shrink", FALSE);
-	gl_label_text_set_auto_shrink (GL_LABEL_TEXT(object), auto_shrink);
+	gl_label_text_set_auto_shrink (GL_LABEL_TEXT(object), auto_shrink, FALSE);
 
 	/* affine attrs */
 	xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
@@ -492,21 +492,21 @@ xml_parse_object_box (xmlNodePtr  node,
 
 	gl_debug (DEBUG_XML, "START");
 
-	object = gl_label_box_new (label);
+	object = gl_label_box_new (label, FALSE);
 
 	/* position attrs */
 	x = lgl_xml_get_prop_length (node, "x", 0.0);
 	y = lgl_xml_get_prop_length (node, "y", 0.0);
-	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
 
 	/* size attrs */
 	w = lgl_xml_get_prop_length (node, "w", 0);
 	h = lgl_xml_get_prop_length (node, "h", 0);
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
 
 	/* line attrs */
 	line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
-	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
+	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
 	
 	line_color_node = gl_color_node_new_default ();
 	string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
@@ -516,7 +516,7 @@ xml_parse_object_box (xmlNodePtr  node,
 	} else {
 		line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
 	}
-	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
+	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
 	gl_color_node_free (&line_color_node);
 
 
@@ -529,7 +529,7 @@ xml_parse_object_box (xmlNodePtr  node,
 	} else {
 		fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
 	}
-	gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
+	gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node, FALSE);
 	gl_color_node_free (&fill_color_node);
 	
 	/* affine attrs */
@@ -559,21 +559,21 @@ xml_parse_object_ellipse (xmlNodePtr  node,
 
 	gl_debug (DEBUG_XML, "START");
 
-	object = gl_label_ellipse_new (label);
+	object = gl_label_ellipse_new (label, FALSE);
 
 	/* position attrs */
 	x = lgl_xml_get_prop_length (node, "x", 0.0);
 	y = lgl_xml_get_prop_length (node, "y", 0.0);
-	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
 
 	/* size attrs */
 	w = lgl_xml_get_prop_length (node, "w", 0);
 	h = lgl_xml_get_prop_length (node, "h", 0);
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
 
 	/* line attrs */
 	line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
-	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
+	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
 
 	line_color_node = gl_color_node_new_default ();
 	string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
@@ -583,7 +583,7 @@ xml_parse_object_ellipse (xmlNodePtr  node,
 	} else {
 		line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);		
 	}
-	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
+	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
 	gl_color_node_free (&line_color_node);
 
 
@@ -596,7 +596,7 @@ xml_parse_object_ellipse (xmlNodePtr  node,
 	} else {
 		fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
 	}
-	gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
+	gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node, FALSE);
 	gl_color_node_free (&fill_color_node);
 
 	/* affine attrs */
@@ -625,21 +625,21 @@ xml_parse_object_line (xmlNodePtr  node,
 
 	gl_debug (DEBUG_XML, "START");
 
-	object = gl_label_line_new (label);
+	object = gl_label_line_new (label, FALSE);
 
 	/* position attrs */
 	x = lgl_xml_get_prop_length (node, "x", 0.0);
 	y = lgl_xml_get_prop_length (node, "y", 0.0);
-	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
 
 	/* length attrs */
 	dx = lgl_xml_get_prop_length (node, "dx", 0);
 	dy = lgl_xml_get_prop_length (node, "dy", 0);
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy, FALSE);
 
 	/* line attrs */
 	line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
-	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
+	gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
 	
 	line_color_node = gl_color_node_new_default ();
 	string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
@@ -649,7 +649,7 @@ xml_parse_object_line (xmlNodePtr  node,
 	} else {
 		line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);		
 	}
-	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
+	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
 	gl_color_node_free (&line_color_node);
 
 	/* affine attrs */
@@ -677,12 +677,12 @@ xml_parse_object_image (xmlNodePtr  node,
 
 	gl_debug (DEBUG_XML, "START");
 
-	object = gl_label_image_new (label);
+	object = gl_label_image_new (label, FALSE);
 
 	/* position attrs */
 	x = lgl_xml_get_prop_length (node, "x", 0.0);
 	y = lgl_xml_get_prop_length (node, "y", 0.0);
-	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
 
 	/* src or field attr */
 	string = lgl_xml_get_prop_string (node, "src", NULL);
@@ -690,7 +690,7 @@ xml_parse_object_image (xmlNodePtr  node,
 		filename = g_new0 (glTextNode, 1);
 		filename->field_flag = FALSE;
 		filename->data = g_strdup ((gchar *)string);
-		gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
+		gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename, FALSE);
 		gl_text_node_free (&filename);
 		xmlFree (string);
 	} else {
@@ -699,7 +699,7 @@ xml_parse_object_image (xmlNodePtr  node,
 			filename = g_new0 (glTextNode, 1);
 			filename->field_flag = TRUE;
 			filename->data = g_strdup ((gchar *)string);
-			gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
+			gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename, FALSE);
 			gl_text_node_free (&filename);
 			xmlFree (string);
 		} else {
@@ -710,7 +710,7 @@ xml_parse_object_image (xmlNodePtr  node,
 	/* size attrs */
 	w = lgl_xml_get_prop_length (node, "w", 0);
 	h = lgl_xml_get_prop_length (node, "h", 0);
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
 
 	/* affine attrs */
 	xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
@@ -742,17 +742,17 @@ xml_parse_object_barcode (xmlNodePtr  node,
 
 	gl_debug (DEBUG_XML, "START");
 
-	object = gl_label_barcode_new (label);
+	object = gl_label_barcode_new (label, FALSE);
 
 	/* position attrs */
 	x = lgl_xml_get_prop_length (node, "x", 0.0);
 	y = lgl_xml_get_prop_length (node, "y", 0.0);
-	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
+	gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
 
 	/* size attrs */
 	w = lgl_xml_get_prop_length (node, "w", 0);
 	h = lgl_xml_get_prop_length (node, "h", 0);
-	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
+	gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
 
 	/* prop attrs */
 	id = lgl_xml_get_prop_string (node, "style", NULL);
@@ -760,7 +760,7 @@ xml_parse_object_barcode (xmlNodePtr  node,
 	checksum_flag = lgl_xml_get_prop_boolean (node, "checksum", TRUE);
 	format_digits = lgl_xml_get_prop_uint (node, "format", 10);
 	gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
-				    (gchar *)id, text_flag, checksum_flag, format_digits);
+				    (gchar *)id, text_flag, checksum_flag, format_digits, FALSE);
 	g_free (id);
 	
 	color_node = gl_color_node_new_default ();
@@ -771,7 +771,7 @@ xml_parse_object_barcode (xmlNodePtr  node,
 	} else {
 		color_node->color = lgl_xml_get_prop_uint (node, "color", 0);		
 	}
-	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color_node);
+	gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color_node, FALSE);
 	gl_color_node_free (&color_node);
 
 	/* data or field attr */
@@ -780,7 +780,7 @@ xml_parse_object_barcode (xmlNodePtr  node,
 		text_node = g_new0 (glTextNode, 1);
 		text_node->field_flag = FALSE;
 		text_node->data = string;
-		gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
+		gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node, FALSE);
 		gl_text_node_free (&text_node);
 	} else {
 		string = lgl_xml_get_prop_string (node, "field", NULL);
@@ -788,7 +788,7 @@ xml_parse_object_barcode (xmlNodePtr  node,
 			text_node = g_new0 (glTextNode, 1);
 			text_node->field_flag = TRUE;
 			text_node->data = string;
-			gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
+			gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node, FALSE);
 			gl_text_node_free (&text_node);
 		} else {
 			g_message ("Missing Object-barcode data or field attr");
@@ -827,7 +827,7 @@ xml_parse_merge_fields (xmlNodePtr  node,
                 gl_merge_set_src (merge, string);
                 g_free (string);
 
-                gl_label_set_merge (label, merge);
+                gl_label_set_merge (label, merge, FALSE);
 
                 g_object_unref (G_OBJECT(merge));
         }
@@ -926,22 +926,22 @@ xml_parse_toplevel_span  (xmlNodePtr        node,
 
 	/* Font family attr */
 	font_family = lgl_xml_get_prop_string (node, "font_family", "Sans");
-	gl_label_object_set_font_family (object, font_family);
+	gl_label_object_set_font_family (object, font_family, FALSE);
 	g_free (font_family);
 
 	/* Font size attr */
 	font_size = lgl_xml_get_prop_double (node, "font_size", 0.0);
-	gl_label_object_set_font_size (object, font_size);
+	gl_label_object_set_font_size (object, font_size, FALSE);
 
 	/* Font weight attr */
 	string = lgl_xml_get_prop_string (node, "font_weight", NULL);
 	font_weight = gl_str_util_string_to_weight (string);
 	g_free (string);
-	gl_label_object_set_font_weight (object, font_weight);
+	gl_label_object_set_font_weight (object, font_weight, FALSE);
 
 	/* Font italic flag attr */
 	font_italic_flag = lgl_xml_get_prop_boolean (node, "font_italic", FALSE);
-	gl_label_object_set_font_italic_flag (object, font_italic_flag);
+	gl_label_object_set_font_italic_flag (object, font_italic_flag, FALSE);
 
 	/* Text color attr */
 	color_node = gl_color_node_new_default ();
@@ -952,13 +952,12 @@ xml_parse_toplevel_span  (xmlNodePtr        node,
 	} else {
 		color_node->color = lgl_xml_get_prop_uint (node, "color", 0);		
 	}
-	gl_label_object_set_text_color (object, color_node);
+	gl_label_object_set_text_color (object, color_node, FALSE);
 	gl_color_node_free (&color_node);
 	
-
 	/* Text line spacing attr  */
 	text_line_spacing = lgl_xml_get_prop_double (node, "line_spacing", 1.0);
-	gl_label_object_set_text_line_spacing (object, text_line_spacing); 
+	gl_label_object_set_text_line_spacing (object, text_line_spacing, FALSE); 
 
 	/* Now descend children, and build lines of text nodes */
 	lines = NULL;
@@ -1007,7 +1006,7 @@ xml_parse_toplevel_span  (xmlNodePtr        node,
 		lines = g_list_append (lines, text_nodes);
 		text_nodes = NULL;
 	}
-	gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
+	gl_label_text_set_lines (GL_LABEL_TEXT(object), lines, FALSE);
 	gl_text_node_lines_free (&lines);
 
 	gl_debug (DEBUG_XML, "END");
@@ -1052,13 +1051,13 @@ xml_parse_shadow_attrs (xmlNodePtr        node,
 	gchar           *string;
 
 	shadow_state = lgl_xml_get_prop_boolean (node, "shadow", FALSE);
-	gl_label_object_set_shadow_state (object, shadow_state);
+	gl_label_object_set_shadow_state (object, shadow_state, FALSE);
 
 	if (shadow_state)
 	{
 		shadow_x = lgl_xml_get_prop_length (node, "shadow_x", 0.0);
 		shadow_y = lgl_xml_get_prop_length (node, "shadow_y", 0.0);
-		gl_label_object_set_shadow_offset (object, shadow_x, shadow_y);
+		gl_label_object_set_shadow_offset (object, shadow_x, shadow_y, FALSE);
 		
 		shadow_color_node = gl_color_node_new_default ();
 		string = lgl_xml_get_prop_string (node, "shadow_color_field", NULL);
@@ -1068,11 +1067,11 @@ xml_parse_shadow_attrs (xmlNodePtr        node,
 		} else {
 			shadow_color_node->color = lgl_xml_get_prop_uint (node, "shadow_color", 0);		
 		}
-		gl_label_object_set_shadow_color (object, shadow_color_node);
+		gl_label_object_set_shadow_color (object, shadow_color_node, FALSE);
 		gl_color_node_free (&shadow_color_node);
 
 		shadow_opacity = lgl_xml_get_prop_double (node, "shadow_opacity", 1.0);
-		gl_label_object_set_shadow_opacity (object, shadow_opacity);
+		gl_label_object_set_shadow_opacity (object, shadow_opacity, FALSE);
 	}
 }
 



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