Dirty flag now correct in all cases. Can be displayed in image window

Mon Aug 23 10:15:32 EDT 1999  Austin Donnelly  <austin@gimp.org>

	Dirty flag now correct in all cases.  Can be displayed in image
	window title too.  See NOTE near gimp_image_dirty() for details.

	* app/fileops.c: gimp_image_clean_all() after reverting an image.
	* app/gdisplay.c: register handlers for gimage dirty and clean
	    signals to update image title.  New image-title-format
	    expansion: %Dx expands to x if the image is dirty.
	* app/gdisplay_ops.c: gimage->dirty flags != 0 is the correct
	    condition to test to see if an image is dirty.
	* app/gimpdrawable.c: gimp_image_dirty() should never be called
	    except from an undo_push_* function.  Call
	    undo_push_cantundo() if you want to dirty the image but can't
	    be bothered writing an undo handler (be ashamed of yourself!).
	* app/gimpimage.c: new gimage signal: clean.  Emitted when an undo
	    operation takes place.  Gimage changes when either dirty or
	    clean is emitted, so if you need to update previews etc, look
	    for both!  Move group_count into gimage structure, since
	    leaving it as a static in undo.c is bad if two undo groups are
	    started on different images at the same time.  More changes
	    of gimp_image_dirty() to undo_push_cantundo()
	    (parasite-related, plus layer moves).  See the NOTE on dirty
	    counter near gimp_image_dirty() for the full story.
	    gimp_image_dirty() and gimp_image_clean() simplified - counter
	    can go negative.
	* app/gimpimageP.h: group_count moved from undo.c
	* app/layers_dialog.c: push undo for layer name change, rather
	    than dirtying the image.
	* app/undo.c: layer rename undo functions
	    added. undo_push_cantundo() convenience functions added.
	    group_count made per-gimage since everything else is.  When
	    blowing away redo stack, make image infinitely dirty if redo
	    info contained file save point.
	* app/undo.h: added undo_push_layer_rename() and
	    undo_push_cantundo().
	* TODO: added idea for undo history window.
This commit is contained in:
EDT 1999 Austin Donnelly 1999-08-23 14:34:58 +00:00 committed by Austin Donnelly
parent ef4cb06bb7
commit 0a7dca9110
25 changed files with 972 additions and 188 deletions

View File

@ -1,3 +1,41 @@
Mon Aug 23 10:15:32 EDT 1999 Austin Donnelly <austin@gimp.org>
Dirty flag now correct in all cases. Can be displayed in image
window title too. See NOTE near gimp_image_dirty() for details.
* app/fileops.c: gimp_image_clean_all() after reverting an image.
* app/gdisplay.c: register handlers for gimage dirty and clean
signals to update image title. New image-title-format
expansion: %Dx expands to x if the image is dirty.
* app/gdisplay_ops.c: gimage->dirty flags != 0 is the correct
condition to test to see if an image is dirty.
* app/gimpdrawable.c: gimp_image_dirty() should never be called
except from an undo_push_* function. Call
undo_push_cantundo() if you want to dirty the image but can't
be bothered writing an undo handler (be ashamed of yourself!).
* app/gimpimage.c: new gimage signal: clean. Emitted when an undo
operation takes place. Gimage changes when either dirty or
clean is emitted, so if you need to update previews etc, look
for both! Move group_count into gimage structure, since
leaving it as a static in undo.c is bad if two undo groups are
started on different images at the same time. More changes
of gimp_image_dirty() to undo_push_cantundo()
(parasite-related, plus layer moves). See the NOTE on dirty
counter near gimp_image_dirty() for the full story.
gimp_image_dirty() and gimp_image_clean() simplified - counter
can go negative.
* app/gimpimageP.h: group_count moved from undo.c
* app/layers_dialog.c: push undo for layer name change, rather
than dirtying the image.
* app/undo.c: layer rename undo functions
added. undo_push_cantundo() convenience functions added.
group_count made per-gimage since everything else is. When
blowing away redo stack, make image infinitely dirty if redo
info contained file save point.
* app/undo.h: added undo_push_layer_rename() and
undo_push_cantundo().
* TODO: added idea for undo history window.
1999-08-23 Michael Natterer <mitschel@cs.tu-berlin.de>
* app/bucket_fill.[ch]: export bucket_fill_region().

9
TODO
View File

@ -406,6 +406,13 @@ named undo
meaningful undo history display, so you can undo multiple
levels in one go.
undo history
The "type" argument to the undo_push_* functions isn't really
used for anything. We could use it to do the named undos
described above, and allow a "history" window to list the
undo-able actions. Clicking on the relevant line would
roll-back to that point. -- austin.
gradient map layer
map values from current gradient to value/intensity
@ -431,5 +438,3 @@ Grid
bitmap. limited utility for char's, but a couple of nice sets
of winding fonts could make it interestings. And you could
use words or strings.

View File

@ -490,7 +490,7 @@ gimp_drawable_attach_parasite (GimpDrawable *drawable,
!parasite_compare( parasite,
gimp_drawable_find_parasite
(drawable, parasite_name (parasite))))
gimp_image_dirty (drawable->gimage);
undo_push_cantundo (drawable->gimage, _("parasite attach to drawable"));
parasite_list_add (drawable->parasites, parasite);
if (parasite_has_flag (parasite, PARASITE_ATTACH_PARENT))
@ -523,7 +523,7 @@ gimp_drawable_detach_parasite (GimpDrawable *drawable,
undo_push_drawable_parasite_remove (drawable->gimage, drawable,
parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (drawable->gimage);
undo_push_cantundo (drawable->gimage, _("detach parasite from drawable"));
parasite_list_remove (drawable->parasites, parasite);
}

View File

@ -91,6 +91,7 @@ guint32 next_guide_id = 1; /* For generating guide_ID handles for PDB stuff */
*/
enum {
CLEAN,
DIRTY,
REPAINT,
RENAME,
@ -118,6 +119,9 @@ gimp_image_class_init (GimpImageClass *klass)
object_class->destroy = gimp_image_destroy;
gimp_image_signals[CLEAN] =
gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
gimp_image_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
@ -165,6 +169,7 @@ gimp_image_init (GimpImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
gimage->group_count = 0;
gimage->pushing_undo_group = 0;
gimage->comp_preview_valid[0] = FALSE;
gimage->comp_preview_valid[1] = FALSE;
@ -1069,7 +1074,7 @@ gimp_image_attach_parasite (GimpImage *gimage,
&& !parasite_compare (parasite,
gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("attach parasite to image"));
parasite_list_add (gimage->parasites, parasite);
@ -1092,7 +1097,7 @@ gimp_image_detach_parasite (GimpImage *gimage,
if (parasite_is_undoable (p))
undo_push_image_parasite_remove (gimage, parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("detach parasite from image"));
parasite_list_remove (gimage->parasites, parasite);
}
@ -2089,7 +2094,9 @@ gimp_image_raise_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
/* Dirty the image, but we're too lazy to provide a
* proper undo. */
undo_push_cantundo (gimage, _("raise layer"));
return prev_layer;
}
@ -2163,7 +2170,7 @@ gimp_image_lower_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer"));
return next_layer;
}
@ -2246,7 +2253,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("raise layer to top"));
return layer;
}
@ -2341,7 +2348,7 @@ gimp_image_lower_layer_to_bottom (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer to bottom"));
return layer_arg;
}
@ -2420,7 +2427,7 @@ gimp_image_position_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("re-position layer"));
return layer_arg;
}
@ -3340,12 +3347,40 @@ gimp_image_enable_undo (GimpImage *gimage)
return gimp_image_thaw_undo (gimage);
}
/* NOTE about the gimage->dirty counter:
* If 0, then the image is clean (ie, copy on disk is the same as the one
* in memory).
* If positive, then that's the number of dirtying operations done
* on the image since the last save.
* If negative, then user has hit undo and gone back in time prior
* to the saved copy. Hitting redo will eventually come back to
* the saved copy.
*
* The image is dirty (ie, needs saving) if counter is non-zero.
*
* If the counter is around 10000, this is due to undo-ing back
* before a saved version, then mutating the image (thus destroying
* the redo stack). Once this has happened, it's impossible to get
* the image back to the state on disk, since the redo info has been
* freed. See undo.c for the gorey details.
*/
/*
* NEVER CALL gimp_image_dirty() directly!
*
* If your code has just dirtied the image, push an undo instead.
* Failing that, push the trivial undo which tells the user the
* command is not undoable: undo_push_cantundo() (But really, it would
* be best to push a proper undo). If you just dirty the image
* without pushing an undo then the dirty count is increased, but
* popping that many undo actions won't lead to a clean image.
*/
gint
gimp_image_dirty (GimpImage *gimage)
{
/* if (gimage->dirty < 0)
gimage->dirty = 2;
else */
gimage->dirty++;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[DIRTY]);
@ -3355,10 +3390,9 @@ gimp_image_dirty (GimpImage *gimage)
gint
gimp_image_clean (GimpImage *gimage)
{
/* if (gimage->dirty <= 0)
gimage->dirty = 0;
else */
gimage->dirty--;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
return gimage->dirty;
}
@ -3366,6 +3400,8 @@ void
gimp_image_clean_all (GimpImage *gimage)
{
gimage->dirty = 0;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
}
Layer *

View File

@ -91,6 +91,7 @@ guint32 next_guide_id = 1; /* For generating guide_ID handles for PDB stuff */
*/
enum {
CLEAN,
DIRTY,
REPAINT,
RENAME,
@ -118,6 +119,9 @@ gimp_image_class_init (GimpImageClass *klass)
object_class->destroy = gimp_image_destroy;
gimp_image_signals[CLEAN] =
gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
gimp_image_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
@ -165,6 +169,7 @@ gimp_image_init (GimpImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
gimage->group_count = 0;
gimage->pushing_undo_group = 0;
gimage->comp_preview_valid[0] = FALSE;
gimage->comp_preview_valid[1] = FALSE;
@ -1069,7 +1074,7 @@ gimp_image_attach_parasite (GimpImage *gimage,
&& !parasite_compare (parasite,
gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("attach parasite to image"));
parasite_list_add (gimage->parasites, parasite);
@ -1092,7 +1097,7 @@ gimp_image_detach_parasite (GimpImage *gimage,
if (parasite_is_undoable (p))
undo_push_image_parasite_remove (gimage, parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("detach parasite from image"));
parasite_list_remove (gimage->parasites, parasite);
}
@ -2089,7 +2094,9 @@ gimp_image_raise_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
/* Dirty the image, but we're too lazy to provide a
* proper undo. */
undo_push_cantundo (gimage, _("raise layer"));
return prev_layer;
}
@ -2163,7 +2170,7 @@ gimp_image_lower_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer"));
return next_layer;
}
@ -2246,7 +2253,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("raise layer to top"));
return layer;
}
@ -2341,7 +2348,7 @@ gimp_image_lower_layer_to_bottom (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer to bottom"));
return layer_arg;
}
@ -2420,7 +2427,7 @@ gimp_image_position_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("re-position layer"));
return layer_arg;
}
@ -3340,12 +3347,40 @@ gimp_image_enable_undo (GimpImage *gimage)
return gimp_image_thaw_undo (gimage);
}
/* NOTE about the gimage->dirty counter:
* If 0, then the image is clean (ie, copy on disk is the same as the one
* in memory).
* If positive, then that's the number of dirtying operations done
* on the image since the last save.
* If negative, then user has hit undo and gone back in time prior
* to the saved copy. Hitting redo will eventually come back to
* the saved copy.
*
* The image is dirty (ie, needs saving) if counter is non-zero.
*
* If the counter is around 10000, this is due to undo-ing back
* before a saved version, then mutating the image (thus destroying
* the redo stack). Once this has happened, it's impossible to get
* the image back to the state on disk, since the redo info has been
* freed. See undo.c for the gorey details.
*/
/*
* NEVER CALL gimp_image_dirty() directly!
*
* If your code has just dirtied the image, push an undo instead.
* Failing that, push the trivial undo which tells the user the
* command is not undoable: undo_push_cantundo() (But really, it would
* be best to push a proper undo). If you just dirty the image
* without pushing an undo then the dirty count is increased, but
* popping that many undo actions won't lead to a clean image.
*/
gint
gimp_image_dirty (GimpImage *gimage)
{
/* if (gimage->dirty < 0)
gimage->dirty = 2;
else */
gimage->dirty++;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[DIRTY]);
@ -3355,10 +3390,9 @@ gimp_image_dirty (GimpImage *gimage)
gint
gimp_image_clean (GimpImage *gimage)
{
/* if (gimage->dirty <= 0)
gimage->dirty = 0;
else */
gimage->dirty--;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
return gimage->dirty;
}
@ -3366,6 +3400,8 @@ void
gimp_image_clean_all (GimpImage *gimage)
{
gimage->dirty = 0;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
}
Layer *

View File

@ -91,6 +91,7 @@ guint32 next_guide_id = 1; /* For generating guide_ID handles for PDB stuff */
*/
enum {
CLEAN,
DIRTY,
REPAINT,
RENAME,
@ -118,6 +119,9 @@ gimp_image_class_init (GimpImageClass *klass)
object_class->destroy = gimp_image_destroy;
gimp_image_signals[CLEAN] =
gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
gimp_image_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
@ -165,6 +169,7 @@ gimp_image_init (GimpImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
gimage->group_count = 0;
gimage->pushing_undo_group = 0;
gimage->comp_preview_valid[0] = FALSE;
gimage->comp_preview_valid[1] = FALSE;
@ -1069,7 +1074,7 @@ gimp_image_attach_parasite (GimpImage *gimage,
&& !parasite_compare (parasite,
gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("attach parasite to image"));
parasite_list_add (gimage->parasites, parasite);
@ -1092,7 +1097,7 @@ gimp_image_detach_parasite (GimpImage *gimage,
if (parasite_is_undoable (p))
undo_push_image_parasite_remove (gimage, parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("detach parasite from image"));
parasite_list_remove (gimage->parasites, parasite);
}
@ -2089,7 +2094,9 @@ gimp_image_raise_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
/* Dirty the image, but we're too lazy to provide a
* proper undo. */
undo_push_cantundo (gimage, _("raise layer"));
return prev_layer;
}
@ -2163,7 +2170,7 @@ gimp_image_lower_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer"));
return next_layer;
}
@ -2246,7 +2253,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("raise layer to top"));
return layer;
}
@ -2341,7 +2348,7 @@ gimp_image_lower_layer_to_bottom (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer to bottom"));
return layer_arg;
}
@ -2420,7 +2427,7 @@ gimp_image_position_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("re-position layer"));
return layer_arg;
}
@ -3340,12 +3347,40 @@ gimp_image_enable_undo (GimpImage *gimage)
return gimp_image_thaw_undo (gimage);
}
/* NOTE about the gimage->dirty counter:
* If 0, then the image is clean (ie, copy on disk is the same as the one
* in memory).
* If positive, then that's the number of dirtying operations done
* on the image since the last save.
* If negative, then user has hit undo and gone back in time prior
* to the saved copy. Hitting redo will eventually come back to
* the saved copy.
*
* The image is dirty (ie, needs saving) if counter is non-zero.
*
* If the counter is around 10000, this is due to undo-ing back
* before a saved version, then mutating the image (thus destroying
* the redo stack). Once this has happened, it's impossible to get
* the image back to the state on disk, since the redo info has been
* freed. See undo.c for the gorey details.
*/
/*
* NEVER CALL gimp_image_dirty() directly!
*
* If your code has just dirtied the image, push an undo instead.
* Failing that, push the trivial undo which tells the user the
* command is not undoable: undo_push_cantundo() (But really, it would
* be best to push a proper undo). If you just dirty the image
* without pushing an undo then the dirty count is increased, but
* popping that many undo actions won't lead to a clean image.
*/
gint
gimp_image_dirty (GimpImage *gimage)
{
/* if (gimage->dirty < 0)
gimage->dirty = 2;
else */
gimage->dirty++;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[DIRTY]);
@ -3355,10 +3390,9 @@ gimp_image_dirty (GimpImage *gimage)
gint
gimp_image_clean (GimpImage *gimage)
{
/* if (gimage->dirty <= 0)
gimage->dirty = 0;
else */
gimage->dirty--;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
return gimage->dirty;
}
@ -3366,6 +3400,8 @@ void
gimp_image_clean_all (GimpImage *gimage)
{
gimage->dirty = 0;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
}
Layer *

View File

@ -91,6 +91,7 @@ guint32 next_guide_id = 1; /* For generating guide_ID handles for PDB stuff */
*/
enum {
CLEAN,
DIRTY,
REPAINT,
RENAME,
@ -118,6 +119,9 @@ gimp_image_class_init (GimpImageClass *klass)
object_class->destroy = gimp_image_destroy;
gimp_image_signals[CLEAN] =
gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
gimp_image_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
@ -165,6 +169,7 @@ gimp_image_init (GimpImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
gimage->group_count = 0;
gimage->pushing_undo_group = 0;
gimage->comp_preview_valid[0] = FALSE;
gimage->comp_preview_valid[1] = FALSE;
@ -1069,7 +1074,7 @@ gimp_image_attach_parasite (GimpImage *gimage,
&& !parasite_compare (parasite,
gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("attach parasite to image"));
parasite_list_add (gimage->parasites, parasite);
@ -1092,7 +1097,7 @@ gimp_image_detach_parasite (GimpImage *gimage,
if (parasite_is_undoable (p))
undo_push_image_parasite_remove (gimage, parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("detach parasite from image"));
parasite_list_remove (gimage->parasites, parasite);
}
@ -2089,7 +2094,9 @@ gimp_image_raise_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
/* Dirty the image, but we're too lazy to provide a
* proper undo. */
undo_push_cantundo (gimage, _("raise layer"));
return prev_layer;
}
@ -2163,7 +2170,7 @@ gimp_image_lower_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer"));
return next_layer;
}
@ -2246,7 +2253,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("raise layer to top"));
return layer;
}
@ -2341,7 +2348,7 @@ gimp_image_lower_layer_to_bottom (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer to bottom"));
return layer_arg;
}
@ -2420,7 +2427,7 @@ gimp_image_position_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("re-position layer"));
return layer_arg;
}
@ -3340,12 +3347,40 @@ gimp_image_enable_undo (GimpImage *gimage)
return gimp_image_thaw_undo (gimage);
}
/* NOTE about the gimage->dirty counter:
* If 0, then the image is clean (ie, copy on disk is the same as the one
* in memory).
* If positive, then that's the number of dirtying operations done
* on the image since the last save.
* If negative, then user has hit undo and gone back in time prior
* to the saved copy. Hitting redo will eventually come back to
* the saved copy.
*
* The image is dirty (ie, needs saving) if counter is non-zero.
*
* If the counter is around 10000, this is due to undo-ing back
* before a saved version, then mutating the image (thus destroying
* the redo stack). Once this has happened, it's impossible to get
* the image back to the state on disk, since the redo info has been
* freed. See undo.c for the gorey details.
*/
/*
* NEVER CALL gimp_image_dirty() directly!
*
* If your code has just dirtied the image, push an undo instead.
* Failing that, push the trivial undo which tells the user the
* command is not undoable: undo_push_cantundo() (But really, it would
* be best to push a proper undo). If you just dirty the image
* without pushing an undo then the dirty count is increased, but
* popping that many undo actions won't lead to a clean image.
*/
gint
gimp_image_dirty (GimpImage *gimage)
{
/* if (gimage->dirty < 0)
gimage->dirty = 2;
else */
gimage->dirty++;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[DIRTY]);
@ -3355,10 +3390,9 @@ gimp_image_dirty (GimpImage *gimage)
gint
gimp_image_clean (GimpImage *gimage)
{
/* if (gimage->dirty <= 0)
gimage->dirty = 0;
else */
gimage->dirty--;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
return gimage->dirty;
}
@ -3366,6 +3400,8 @@ void
gimp_image_clean_all (GimpImage *gimage)
{
gimage->dirty = 0;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
}
Layer *

View File

@ -91,6 +91,7 @@ guint32 next_guide_id = 1; /* For generating guide_ID handles for PDB stuff */
*/
enum {
CLEAN,
DIRTY,
REPAINT,
RENAME,
@ -118,6 +119,9 @@ gimp_image_class_init (GimpImageClass *klass)
object_class->destroy = gimp_image_destroy;
gimp_image_signals[CLEAN] =
gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
gimp_image_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
@ -165,6 +169,7 @@ gimp_image_init (GimpImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
gimage->group_count = 0;
gimage->pushing_undo_group = 0;
gimage->comp_preview_valid[0] = FALSE;
gimage->comp_preview_valid[1] = FALSE;
@ -1069,7 +1074,7 @@ gimp_image_attach_parasite (GimpImage *gimage,
&& !parasite_compare (parasite,
gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("attach parasite to image"));
parasite_list_add (gimage->parasites, parasite);
@ -1092,7 +1097,7 @@ gimp_image_detach_parasite (GimpImage *gimage,
if (parasite_is_undoable (p))
undo_push_image_parasite_remove (gimage, parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("detach parasite from image"));
parasite_list_remove (gimage->parasites, parasite);
}
@ -2089,7 +2094,9 @@ gimp_image_raise_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
/* Dirty the image, but we're too lazy to provide a
* proper undo. */
undo_push_cantundo (gimage, _("raise layer"));
return prev_layer;
}
@ -2163,7 +2170,7 @@ gimp_image_lower_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer"));
return next_layer;
}
@ -2246,7 +2253,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("raise layer to top"));
return layer;
}
@ -2341,7 +2348,7 @@ gimp_image_lower_layer_to_bottom (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer to bottom"));
return layer_arg;
}
@ -2420,7 +2427,7 @@ gimp_image_position_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("re-position layer"));
return layer_arg;
}
@ -3340,12 +3347,40 @@ gimp_image_enable_undo (GimpImage *gimage)
return gimp_image_thaw_undo (gimage);
}
/* NOTE about the gimage->dirty counter:
* If 0, then the image is clean (ie, copy on disk is the same as the one
* in memory).
* If positive, then that's the number of dirtying operations done
* on the image since the last save.
* If negative, then user has hit undo and gone back in time prior
* to the saved copy. Hitting redo will eventually come back to
* the saved copy.
*
* The image is dirty (ie, needs saving) if counter is non-zero.
*
* If the counter is around 10000, this is due to undo-ing back
* before a saved version, then mutating the image (thus destroying
* the redo stack). Once this has happened, it's impossible to get
* the image back to the state on disk, since the redo info has been
* freed. See undo.c for the gorey details.
*/
/*
* NEVER CALL gimp_image_dirty() directly!
*
* If your code has just dirtied the image, push an undo instead.
* Failing that, push the trivial undo which tells the user the
* command is not undoable: undo_push_cantundo() (But really, it would
* be best to push a proper undo). If you just dirty the image
* without pushing an undo then the dirty count is increased, but
* popping that many undo actions won't lead to a clean image.
*/
gint
gimp_image_dirty (GimpImage *gimage)
{
/* if (gimage->dirty < 0)
gimage->dirty = 2;
else */
gimage->dirty++;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[DIRTY]);
@ -3355,10 +3390,9 @@ gimp_image_dirty (GimpImage *gimage)
gint
gimp_image_clean (GimpImage *gimage)
{
/* if (gimage->dirty <= 0)
gimage->dirty = 0;
else */
gimage->dirty--;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
return gimage->dirty;
}
@ -3366,6 +3400,8 @@ void
gimp_image_clean_all (GimpImage *gimage)
{
gimage->dirty = 0;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
}
Layer *

View File

@ -42,6 +42,7 @@
#include "tile.h" /* ick. */
#include "libgimp/parasite.h"
#include "libgimp/gimpintl.h"
#include "gimpparasite.h"
@ -80,6 +81,9 @@ int undo_pop_gimage_mod (GImage *, int, int, void *);
int undo_pop_guide (GImage *, int, int, void *);
int undo_pop_parasite (GImage *, int, int, void *);
int undo_pop_qmask (GImage *, int, int, void *);
static int undo_pop_layer_rename (GImage *, int, int, void *);
static int undo_pop_cantundo (GImage *, int, int, void *);
/* Free functions */
@ -100,13 +104,14 @@ void undo_free_gimage_mod (int, void *);
void undo_free_guide (int, void *);
void undo_free_parasite (int, void *);
void undo_free_qmask (int, void *);
static void undo_free_layer_rename (int, void *);
static void undo_free_cantundo (int, void *);
/* Sizing functions */
static int layer_size (Layer *);
static int channel_size (Channel *);
static int group_count = 0;
static int shrink_wrap = FALSE;
#define UNDO 0
@ -249,6 +254,14 @@ undo_push (GImage *gimage,
{
undo_free_list (gimage, REDO, gimage->redo_stack);
gimage->redo_stack = NULL;
/* If the image was dirty, but could become clean by redo-ing
* some actions, then it should now become 'infinitely' dirty.
* This is because we've just nuked the actions that would allow
* the image to become clean again. The only hope for salvation
* is to save the image now! -- austin */
if (gimage->dirty < 0)
gimage->dirty = 10000;
}
if (!gimage->pushing_undo_group)
@ -384,6 +397,18 @@ undo_free (GImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
/* If the image was dirty, but could become clean by redo-ing
* some actions, then it should now become 'infinitely' dirty.
* This is because we've just nuked the actions that would allow
* the image to become clean again. The only hope for salvation
* is to save the image now! -- austin */
if (gimage->dirty < 0)
gimage->dirty = 10000;
/* The same applies to the case where the image would become clean
* due to undo actions, but since user can't undo without an undo
* stack, that's not so much a problem. */
}
@ -397,16 +422,23 @@ undo_push_group_start (GImage *gimage,
if (! gimage->undo_on)
return FALSE;
group_count ++;
gimage->group_count ++;
/* If we're already in a group...ignore */
if (group_count > 1)
if (gimage->group_count > 1)
return TRUE;
if (gimage->redo_stack)
{
undo_free_list (gimage, REDO, gimage->redo_stack);
gimage->redo_stack = NULL;
/* If the image was dirty, but could become clean by redo-ing
* some actions, then it should now become 'infinitely' dirty.
* This is because we've just nuked the actions that would allow
* the image to become clean again. The only hope for salvation
* is to save the image now! -- austin */
if (gimage->dirty < 0)
gimage->dirty = 10000;
}
if (! undo_free_up_space (gimage))
@ -426,9 +458,9 @@ undo_push_group_end (GImage *gimage)
if (! gimage->undo_on)
return FALSE;
group_count --;
gimage->group_count --;
if (group_count == 0)
if (gimage->group_count == 0)
{
gimage->pushing_undo_group = 0;
gimage->undo_stack = g_slist_prepend (gimage->undo_stack, NULL);
@ -2423,3 +2455,134 @@ undo_free_parasite (int state,
g_free (data_ptr);
}
/*************/
/* Layer name change */
typedef struct {
Layer *layer;
gchar *old_name;
} LayerRenameUndo;
int
undo_push_layer_rename (GImage *gimage, Layer *layer)
{
Undo *new;
LayerRenameUndo *data;
long size;
/* increment the dirty flag for this gimage */
gimage_dirty (gimage);
size = sizeof (LayerRenameUndo);
if ((new = undo_push (gimage, size, LAYER_CHANGE)))
{
data = g_new (LayerRenameUndo, 1);
new->data = data;
new->pop_func = undo_pop_layer_rename;
new->free_func = undo_free_layer_rename;
data->layer = layer;
data->old_name = g_strdup (layer_get_name (layer));
return TRUE;
}
return FALSE;
}
static int
undo_pop_layer_rename (GImage *gimage,
int state,
int type,
void *data_ptr)
{
LayerRenameUndo *data = data_ptr;
gchar *tmp;
tmp = g_strdup (layer_get_name (data->layer));
layer_set_name (data->layer, data->old_name);
g_free (data->old_name);
data->old_name = tmp;
switch (state) {
case UNDO:
gimp_image_clean (gimage);
break;
case REDO:
gimp_image_dirty (gimage);
break;
}
return TRUE;
}
static void
undo_free_layer_rename (int state,
void *data_ptr)
{
LayerRenameUndo *data = data_ptr;
g_free (data->old_name);
g_free (data);
}
/*************/
/* Something for which programmer is too lazy to write an undo
* function for.
*/
int
undo_push_cantundo (GImage *gimage,
const char *action)
{
Undo *new;
/* This is the sole purpose of this type of undo: the ability to
* mark an image as having been mutated, without really providing
* any adequate undo facility. */
gimp_image_dirty (gimage);
new = undo_push (gimage, 0, GIMAGE_MOD);
if (!new)
return FALSE;
new->data = (void*)action;
new->pop_func = undo_pop_cantundo;
new->free_func = undo_free_cantundo;
return TRUE;
}
static int
undo_pop_cantundo (GImage *gimage,
int state,
int type,
void *data_ptr)
{
char *action = data_ptr;
switch (state) {
case UNDO:
g_message (_("Can't undo %s"), action);
gimp_image_clean (gimage);
break;
case REDO:
gimp_image_dirty (gimage);
break;
}
return TRUE;
}
static void
undo_free_cantundo (int state, void *data_ptr)
{
}

View File

@ -86,6 +86,8 @@ int undo_push_image_parasite_remove (GImage *, const char *);
int undo_push_drawable_parasite_remove (GImage *, GimpDrawable *,
const char *);
int undo_push_qmask (GImage *, int);
int undo_push_layer_rename (GImage *, Layer *);
int undo_push_cantundo (GImage *, const char *);
int undo_pop (GImage *);
int undo_redo (GImage *);

View File

@ -91,6 +91,7 @@ guint32 next_guide_id = 1; /* For generating guide_ID handles for PDB stuff */
*/
enum {
CLEAN,
DIRTY,
REPAINT,
RENAME,
@ -118,6 +119,9 @@ gimp_image_class_init (GimpImageClass *klass)
object_class->destroy = gimp_image_destroy;
gimp_image_signals[CLEAN] =
gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
gimp_image_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
@ -165,6 +169,7 @@ gimp_image_init (GimpImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
gimage->group_count = 0;
gimage->pushing_undo_group = 0;
gimage->comp_preview_valid[0] = FALSE;
gimage->comp_preview_valid[1] = FALSE;
@ -1069,7 +1074,7 @@ gimp_image_attach_parasite (GimpImage *gimage,
&& !parasite_compare (parasite,
gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("attach parasite to image"));
parasite_list_add (gimage->parasites, parasite);
@ -1092,7 +1097,7 @@ gimp_image_detach_parasite (GimpImage *gimage,
if (parasite_is_undoable (p))
undo_push_image_parasite_remove (gimage, parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("detach parasite from image"));
parasite_list_remove (gimage->parasites, parasite);
}
@ -2089,7 +2094,9 @@ gimp_image_raise_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
/* Dirty the image, but we're too lazy to provide a
* proper undo. */
undo_push_cantundo (gimage, _("raise layer"));
return prev_layer;
}
@ -2163,7 +2170,7 @@ gimp_image_lower_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer"));
return next_layer;
}
@ -2246,7 +2253,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("raise layer to top"));
return layer;
}
@ -2341,7 +2348,7 @@ gimp_image_lower_layer_to_bottom (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer to bottom"));
return layer_arg;
}
@ -2420,7 +2427,7 @@ gimp_image_position_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("re-position layer"));
return layer_arg;
}
@ -3340,12 +3347,40 @@ gimp_image_enable_undo (GimpImage *gimage)
return gimp_image_thaw_undo (gimage);
}
/* NOTE about the gimage->dirty counter:
* If 0, then the image is clean (ie, copy on disk is the same as the one
* in memory).
* If positive, then that's the number of dirtying operations done
* on the image since the last save.
* If negative, then user has hit undo and gone back in time prior
* to the saved copy. Hitting redo will eventually come back to
* the saved copy.
*
* The image is dirty (ie, needs saving) if counter is non-zero.
*
* If the counter is around 10000, this is due to undo-ing back
* before a saved version, then mutating the image (thus destroying
* the redo stack). Once this has happened, it's impossible to get
* the image back to the state on disk, since the redo info has been
* freed. See undo.c for the gorey details.
*/
/*
* NEVER CALL gimp_image_dirty() directly!
*
* If your code has just dirtied the image, push an undo instead.
* Failing that, push the trivial undo which tells the user the
* command is not undoable: undo_push_cantundo() (But really, it would
* be best to push a proper undo). If you just dirty the image
* without pushing an undo then the dirty count is increased, but
* popping that many undo actions won't lead to a clean image.
*/
gint
gimp_image_dirty (GimpImage *gimage)
{
/* if (gimage->dirty < 0)
gimage->dirty = 2;
else */
gimage->dirty++;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[DIRTY]);
@ -3355,10 +3390,9 @@ gimp_image_dirty (GimpImage *gimage)
gint
gimp_image_clean (GimpImage *gimage)
{
/* if (gimage->dirty <= 0)
gimage->dirty = 0;
else */
gimage->dirty--;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
return gimage->dirty;
}
@ -3366,6 +3400,8 @@ void
gimp_image_clean_all (GimpImage *gimage)
{
gimage->dirty = 0;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
}
Layer *

View File

@ -91,6 +91,7 @@ guint32 next_guide_id = 1; /* For generating guide_ID handles for PDB stuff */
*/
enum {
CLEAN,
DIRTY,
REPAINT,
RENAME,
@ -118,6 +119,9 @@ gimp_image_class_init (GimpImageClass *klass)
object_class->destroy = gimp_image_destroy;
gimp_image_signals[CLEAN] =
gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
gimp_image_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
@ -165,6 +169,7 @@ gimp_image_init (GimpImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
gimage->group_count = 0;
gimage->pushing_undo_group = 0;
gimage->comp_preview_valid[0] = FALSE;
gimage->comp_preview_valid[1] = FALSE;
@ -1069,7 +1074,7 @@ gimp_image_attach_parasite (GimpImage *gimage,
&& !parasite_compare (parasite,
gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("attach parasite to image"));
parasite_list_add (gimage->parasites, parasite);
@ -1092,7 +1097,7 @@ gimp_image_detach_parasite (GimpImage *gimage,
if (parasite_is_undoable (p))
undo_push_image_parasite_remove (gimage, parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("detach parasite from image"));
parasite_list_remove (gimage->parasites, parasite);
}
@ -2089,7 +2094,9 @@ gimp_image_raise_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
/* Dirty the image, but we're too lazy to provide a
* proper undo. */
undo_push_cantundo (gimage, _("raise layer"));
return prev_layer;
}
@ -2163,7 +2170,7 @@ gimp_image_lower_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer"));
return next_layer;
}
@ -2246,7 +2253,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("raise layer to top"));
return layer;
}
@ -2341,7 +2348,7 @@ gimp_image_lower_layer_to_bottom (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer to bottom"));
return layer_arg;
}
@ -2420,7 +2427,7 @@ gimp_image_position_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("re-position layer"));
return layer_arg;
}
@ -3340,12 +3347,40 @@ gimp_image_enable_undo (GimpImage *gimage)
return gimp_image_thaw_undo (gimage);
}
/* NOTE about the gimage->dirty counter:
* If 0, then the image is clean (ie, copy on disk is the same as the one
* in memory).
* If positive, then that's the number of dirtying operations done
* on the image since the last save.
* If negative, then user has hit undo and gone back in time prior
* to the saved copy. Hitting redo will eventually come back to
* the saved copy.
*
* The image is dirty (ie, needs saving) if counter is non-zero.
*
* If the counter is around 10000, this is due to undo-ing back
* before a saved version, then mutating the image (thus destroying
* the redo stack). Once this has happened, it's impossible to get
* the image back to the state on disk, since the redo info has been
* freed. See undo.c for the gorey details.
*/
/*
* NEVER CALL gimp_image_dirty() directly!
*
* If your code has just dirtied the image, push an undo instead.
* Failing that, push the trivial undo which tells the user the
* command is not undoable: undo_push_cantundo() (But really, it would
* be best to push a proper undo). If you just dirty the image
* without pushing an undo then the dirty count is increased, but
* popping that many undo actions won't lead to a clean image.
*/
gint
gimp_image_dirty (GimpImage *gimage)
{
/* if (gimage->dirty < 0)
gimage->dirty = 2;
else */
gimage->dirty++;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[DIRTY]);
@ -3355,10 +3390,9 @@ gimp_image_dirty (GimpImage *gimage)
gint
gimp_image_clean (GimpImage *gimage)
{
/* if (gimage->dirty <= 0)
gimage->dirty = 0;
else */
gimage->dirty--;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
return gimage->dirty;
}
@ -3366,6 +3400,8 @@ void
gimp_image_clean_all (GimpImage *gimage)
{
gimage->dirty = 0;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
}
Layer *

View File

@ -70,6 +70,7 @@ static void gdisplay_paint_area (GDisplay *, int, int, int, int);
static void gdisplay_draw_cursor (GDisplay *);
static void gdisplay_display_area (GDisplay *, int, int, int, int);
static guint gdisplay_hash (GDisplay *);
static void gdisplay_cleandirty_handler (GimpImage *, void *);
static GHashTable *display_ht = NULL;
@ -155,6 +156,13 @@ gdisplay_new (GimpImage *gimage,
lc_dialog_preview_update(gimage);
/* We're interested in clean and dirty signals so we can update the
* title if need be. */
gtk_signal_connect (GTK_OBJECT (gimage), "dirty",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gtk_signal_connect (GTK_OBJECT (gimage), "clean",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
return gdisp;
}
@ -259,7 +267,18 @@ gdisplay_format_title (GDisplay *gdisp,
"%d", 100 * SCALEDEST (gdisp) / SCALESRC (gdisp));
break;
/* other cool things to be added:
case 'D': /* dirty flag */
if (format[1] == 0)
{
g_warning("image-title-format string ended within %%D-sequence");
break;
}
if (gimage->dirty)
title[i++] = format[1];
format++;
break;
/* Other cool things to be added:
* %m = memory used by picture
* some kind of resolution / image size thing
* people seem to want to know the active layer name
@ -313,6 +332,9 @@ gdisplay_delete (GDisplay *gdisp)
gdisp->idle_render.active = FALSE;
}
/* get rid of signals handled by this display */
gtk_signal_disconnect_by_data (GTK_OBJECT (gdisp->gimage), gdisp);
if (gdisp->scroll_gc)
gdk_gc_destroy (gdisp->scroll_gc);
@ -2042,7 +2064,7 @@ gdisplays_dirty ()
/* traverse the linked list of displays */
while (list)
{
if (((GDisplay *) list->data)->gimage->dirty > 0)
if (((GDisplay *) list->data)->gimage->dirty != 0)
dirty = 1;
list = g_slist_next (list);
}
@ -2158,6 +2180,7 @@ gdisplay_reconnect (GDisplay *gdisp, GimpImage *gimage)
gdisp->idle_render.active = FALSE;
}
gtk_signal_disconnect_by_data (GTK_OBJECT (gdisp->gimage), gdisp);
gimage_delete (gdisp->gimage);
instance = gimage->instance_count;
@ -2167,8 +2190,24 @@ gdisplay_reconnect (GDisplay *gdisp, GimpImage *gimage)
gdisp->gimage = gimage;
gdisp->instance = instance;
/* reconnect our clean / dirty signals */
gtk_signal_connect (GTK_OBJECT (gimage), "dirty",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gtk_signal_connect (GTK_OBJECT (gimage), "clean",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gdisplays_update_title (gimage);
gdisplay_expose_full (gdisp);
gdisplay_flush (gdisp);
}
/* Called whenever the underlying gimage is dirtied or cleaned */
static void
gdisplay_cleandirty_handler (GimpImage *gimage, void *data)
{
GDisplay *gdisp = data;
gdisplay_update_title (gdisp);
}

View File

@ -120,7 +120,7 @@ gdisplay_close_window (GDisplay *gdisp,
* to an image canvas. (a gimage with ref_count = 1)
*/
if (!kill_it && (gdisp->gimage->ref_count == 1) &&
(gdisp->gimage->dirty > 0) && confirm_on_close)
gdisp->gimage->dirty && confirm_on_close)
{
gdisplay_close_warning_dialog
(g_basename (gimage_filename (gdisp->gimage)), gdisp);

View File

@ -70,6 +70,7 @@ static void gdisplay_paint_area (GDisplay *, int, int, int, int);
static void gdisplay_draw_cursor (GDisplay *);
static void gdisplay_display_area (GDisplay *, int, int, int, int);
static guint gdisplay_hash (GDisplay *);
static void gdisplay_cleandirty_handler (GimpImage *, void *);
static GHashTable *display_ht = NULL;
@ -155,6 +156,13 @@ gdisplay_new (GimpImage *gimage,
lc_dialog_preview_update(gimage);
/* We're interested in clean and dirty signals so we can update the
* title if need be. */
gtk_signal_connect (GTK_OBJECT (gimage), "dirty",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gtk_signal_connect (GTK_OBJECT (gimage), "clean",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
return gdisp;
}
@ -259,7 +267,18 @@ gdisplay_format_title (GDisplay *gdisp,
"%d", 100 * SCALEDEST (gdisp) / SCALESRC (gdisp));
break;
/* other cool things to be added:
case 'D': /* dirty flag */
if (format[1] == 0)
{
g_warning("image-title-format string ended within %%D-sequence");
break;
}
if (gimage->dirty)
title[i++] = format[1];
format++;
break;
/* Other cool things to be added:
* %m = memory used by picture
* some kind of resolution / image size thing
* people seem to want to know the active layer name
@ -313,6 +332,9 @@ gdisplay_delete (GDisplay *gdisp)
gdisp->idle_render.active = FALSE;
}
/* get rid of signals handled by this display */
gtk_signal_disconnect_by_data (GTK_OBJECT (gdisp->gimage), gdisp);
if (gdisp->scroll_gc)
gdk_gc_destroy (gdisp->scroll_gc);
@ -2042,7 +2064,7 @@ gdisplays_dirty ()
/* traverse the linked list of displays */
while (list)
{
if (((GDisplay *) list->data)->gimage->dirty > 0)
if (((GDisplay *) list->data)->gimage->dirty != 0)
dirty = 1;
list = g_slist_next (list);
}
@ -2158,6 +2180,7 @@ gdisplay_reconnect (GDisplay *gdisp, GimpImage *gimage)
gdisp->idle_render.active = FALSE;
}
gtk_signal_disconnect_by_data (GTK_OBJECT (gdisp->gimage), gdisp);
gimage_delete (gdisp->gimage);
instance = gimage->instance_count;
@ -2167,8 +2190,24 @@ gdisplay_reconnect (GDisplay *gdisp, GimpImage *gimage)
gdisp->gimage = gimage;
gdisp->instance = instance;
/* reconnect our clean / dirty signals */
gtk_signal_connect (GTK_OBJECT (gimage), "dirty",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gtk_signal_connect (GTK_OBJECT (gimage), "clean",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gdisplays_update_title (gimage);
gdisplay_expose_full (gdisp);
gdisplay_flush (gdisp);
}
/* Called whenever the underlying gimage is dirtied or cleaned */
static void
gdisplay_cleandirty_handler (GimpImage *gimage, void *data)
{
GDisplay *gdisp = data;
gdisplay_update_title (gdisp);
}

View File

@ -535,6 +535,7 @@ file_revert_callback (GtkWidget *w,
{
undo_free (gimage);
gdisplay_reconnect (gdisplay, gimage);
gimp_image_clean_all (gimage);
}
else
g_message (_("Revert failed."));

View File

@ -70,6 +70,7 @@ static void gdisplay_paint_area (GDisplay *, int, int, int, int);
static void gdisplay_draw_cursor (GDisplay *);
static void gdisplay_display_area (GDisplay *, int, int, int, int);
static guint gdisplay_hash (GDisplay *);
static void gdisplay_cleandirty_handler (GimpImage *, void *);
static GHashTable *display_ht = NULL;
@ -155,6 +156,13 @@ gdisplay_new (GimpImage *gimage,
lc_dialog_preview_update(gimage);
/* We're interested in clean and dirty signals so we can update the
* title if need be. */
gtk_signal_connect (GTK_OBJECT (gimage), "dirty",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gtk_signal_connect (GTK_OBJECT (gimage), "clean",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
return gdisp;
}
@ -259,7 +267,18 @@ gdisplay_format_title (GDisplay *gdisp,
"%d", 100 * SCALEDEST (gdisp) / SCALESRC (gdisp));
break;
/* other cool things to be added:
case 'D': /* dirty flag */
if (format[1] == 0)
{
g_warning("image-title-format string ended within %%D-sequence");
break;
}
if (gimage->dirty)
title[i++] = format[1];
format++;
break;
/* Other cool things to be added:
* %m = memory used by picture
* some kind of resolution / image size thing
* people seem to want to know the active layer name
@ -313,6 +332,9 @@ gdisplay_delete (GDisplay *gdisp)
gdisp->idle_render.active = FALSE;
}
/* get rid of signals handled by this display */
gtk_signal_disconnect_by_data (GTK_OBJECT (gdisp->gimage), gdisp);
if (gdisp->scroll_gc)
gdk_gc_destroy (gdisp->scroll_gc);
@ -2042,7 +2064,7 @@ gdisplays_dirty ()
/* traverse the linked list of displays */
while (list)
{
if (((GDisplay *) list->data)->gimage->dirty > 0)
if (((GDisplay *) list->data)->gimage->dirty != 0)
dirty = 1;
list = g_slist_next (list);
}
@ -2158,6 +2180,7 @@ gdisplay_reconnect (GDisplay *gdisp, GimpImage *gimage)
gdisp->idle_render.active = FALSE;
}
gtk_signal_disconnect_by_data (GTK_OBJECT (gdisp->gimage), gdisp);
gimage_delete (gdisp->gimage);
instance = gimage->instance_count;
@ -2167,8 +2190,24 @@ gdisplay_reconnect (GDisplay *gdisp, GimpImage *gimage)
gdisp->gimage = gimage;
gdisp->instance = instance;
/* reconnect our clean / dirty signals */
gtk_signal_connect (GTK_OBJECT (gimage), "dirty",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gtk_signal_connect (GTK_OBJECT (gimage), "clean",
GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
gdisplays_update_title (gimage);
gdisplay_expose_full (gdisp);
gdisplay_flush (gdisp);
}
/* Called whenever the underlying gimage is dirtied or cleaned */
static void
gdisplay_cleandirty_handler (GimpImage *gimage, void *data)
{
GDisplay *gdisp = data;
gdisplay_update_title (gdisp);
}

View File

@ -120,7 +120,7 @@ gdisplay_close_window (GDisplay *gdisp,
* to an image canvas. (a gimage with ref_count = 1)
*/
if (!kill_it && (gdisp->gimage->ref_count == 1) &&
(gdisp->gimage->dirty > 0) && confirm_on_close)
gdisp->gimage->dirty && confirm_on_close)
{
gdisplay_close_warning_dialog
(g_basename (gimage_filename (gdisp->gimage)), gdisp);

View File

@ -490,7 +490,7 @@ gimp_drawable_attach_parasite (GimpDrawable *drawable,
!parasite_compare( parasite,
gimp_drawable_find_parasite
(drawable, parasite_name (parasite))))
gimp_image_dirty (drawable->gimage);
undo_push_cantundo (drawable->gimage, _("parasite attach to drawable"));
parasite_list_add (drawable->parasites, parasite);
if (parasite_has_flag (parasite, PARASITE_ATTACH_PARENT))
@ -523,7 +523,7 @@ gimp_drawable_detach_parasite (GimpDrawable *drawable,
undo_push_drawable_parasite_remove (drawable->gimage, drawable,
parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (drawable->gimage);
undo_push_cantundo (drawable->gimage, _("detach parasite from drawable"));
parasite_list_remove (drawable->parasites, parasite);
}

View File

@ -91,6 +91,7 @@ guint32 next_guide_id = 1; /* For generating guide_ID handles for PDB stuff */
*/
enum {
CLEAN,
DIRTY,
REPAINT,
RENAME,
@ -118,6 +119,9 @@ gimp_image_class_init (GimpImageClass *klass)
object_class->destroy = gimp_image_destroy;
gimp_image_signals[CLEAN] =
gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
gimp_image_signals[DIRTY] =
gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
gimp_sigtype_void);
@ -165,6 +169,7 @@ gimp_image_init (GimpImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
gimage->group_count = 0;
gimage->pushing_undo_group = 0;
gimage->comp_preview_valid[0] = FALSE;
gimage->comp_preview_valid[1] = FALSE;
@ -1069,7 +1074,7 @@ gimp_image_attach_parasite (GimpImage *gimage,
&& !parasite_compare (parasite,
gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("attach parasite to image"));
parasite_list_add (gimage->parasites, parasite);
@ -1092,7 +1097,7 @@ gimp_image_detach_parasite (GimpImage *gimage,
if (parasite_is_undoable (p))
undo_push_image_parasite_remove (gimage, parasite_name (p));
else if (parasite_is_persistent (p))
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("detach parasite from image"));
parasite_list_remove (gimage->parasites, parasite);
}
@ -2089,7 +2094,9 @@ gimp_image_raise_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
/* Dirty the image, but we're too lazy to provide a
* proper undo. */
undo_push_cantundo (gimage, _("raise layer"));
return prev_layer;
}
@ -2163,7 +2170,7 @@ gimp_image_lower_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer"));
return next_layer;
}
@ -2246,7 +2253,7 @@ gimp_image_raise_layer_to_top (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("raise layer to top"));
return layer;
}
@ -2341,7 +2348,7 @@ gimp_image_lower_layer_to_bottom (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("lower layer to bottom"));
return layer_arg;
}
@ -2420,7 +2427,7 @@ gimp_image_position_layer (GimpImage *gimage,
/* invalidate the composite preview */
gimp_image_invalidate_preview (gimage);
gimp_image_dirty (gimage);
undo_push_cantundo (gimage, _("re-position layer"));
return layer_arg;
}
@ -3340,12 +3347,40 @@ gimp_image_enable_undo (GimpImage *gimage)
return gimp_image_thaw_undo (gimage);
}
/* NOTE about the gimage->dirty counter:
* If 0, then the image is clean (ie, copy on disk is the same as the one
* in memory).
* If positive, then that's the number of dirtying operations done
* on the image since the last save.
* If negative, then user has hit undo and gone back in time prior
* to the saved copy. Hitting redo will eventually come back to
* the saved copy.
*
* The image is dirty (ie, needs saving) if counter is non-zero.
*
* If the counter is around 10000, this is due to undo-ing back
* before a saved version, then mutating the image (thus destroying
* the redo stack). Once this has happened, it's impossible to get
* the image back to the state on disk, since the redo info has been
* freed. See undo.c for the gorey details.
*/
/*
* NEVER CALL gimp_image_dirty() directly!
*
* If your code has just dirtied the image, push an undo instead.
* Failing that, push the trivial undo which tells the user the
* command is not undoable: undo_push_cantundo() (But really, it would
* be best to push a proper undo). If you just dirty the image
* without pushing an undo then the dirty count is increased, but
* popping that many undo actions won't lead to a clean image.
*/
gint
gimp_image_dirty (GimpImage *gimage)
{
/* if (gimage->dirty < 0)
gimage->dirty = 2;
else */
gimage->dirty++;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[DIRTY]);
@ -3355,10 +3390,9 @@ gimp_image_dirty (GimpImage *gimage)
gint
gimp_image_clean (GimpImage *gimage)
{
/* if (gimage->dirty <= 0)
gimage->dirty = 0;
else */
gimage->dirty--;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
return gimage->dirty;
}
@ -3366,6 +3400,8 @@ void
gimp_image_clean_all (GimpImage *gimage)
{
gimage->dirty = 0;
gtk_signal_emit(GTK_OBJECT(gimage), gimp_image_signals[CLEAN]);
}
Layer *

View File

@ -97,6 +97,7 @@ struct _GimpImage
GSList *redo_stack; /* stack for redo operations */
gint undo_bytes; /* bytes in undo stack */
gint undo_levels; /* levels in undo stack */
gint group_count; /* nested undo groups */
gint pushing_undo_group; /* undo group status flag */
/* Composite preview */

View File

@ -3471,17 +3471,19 @@ edit_layer_query_ok_callback (GtkWidget *widget,
if ((layer = options->layer))
{
/* Set the new layer name */
if (GIMP_DRAWABLE (layer)->name)
if (GIMP_DRAWABLE (layer)->name && layer_is_floating_sel (layer))
{
/* If the layer is a floating selection, make it a layer */
if (layer_is_floating_sel (layer))
{
floating_sel_to_layer (layer);
}
else
{
/* We're doing a plain rename */
undo_push_layer_rename (options->gimage, layer);
}
layer_set_name (layer,
gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
gimage_dirty (options->gimage);
}
gdisplays_flush ();

View File

@ -3471,17 +3471,19 @@ edit_layer_query_ok_callback (GtkWidget *widget,
if ((layer = options->layer))
{
/* Set the new layer name */
if (GIMP_DRAWABLE (layer)->name)
if (GIMP_DRAWABLE (layer)->name && layer_is_floating_sel (layer))
{
/* If the layer is a floating selection, make it a layer */
if (layer_is_floating_sel (layer))
{
floating_sel_to_layer (layer);
}
else
{
/* We're doing a plain rename */
undo_push_layer_rename (options->gimage, layer);
}
layer_set_name (layer,
gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
gimage_dirty (options->gimage);
}
gdisplays_flush ();

View File

@ -42,6 +42,7 @@
#include "tile.h" /* ick. */
#include "libgimp/parasite.h"
#include "libgimp/gimpintl.h"
#include "gimpparasite.h"
@ -80,6 +81,9 @@ int undo_pop_gimage_mod (GImage *, int, int, void *);
int undo_pop_guide (GImage *, int, int, void *);
int undo_pop_parasite (GImage *, int, int, void *);
int undo_pop_qmask (GImage *, int, int, void *);
static int undo_pop_layer_rename (GImage *, int, int, void *);
static int undo_pop_cantundo (GImage *, int, int, void *);
/* Free functions */
@ -100,13 +104,14 @@ void undo_free_gimage_mod (int, void *);
void undo_free_guide (int, void *);
void undo_free_parasite (int, void *);
void undo_free_qmask (int, void *);
static void undo_free_layer_rename (int, void *);
static void undo_free_cantundo (int, void *);
/* Sizing functions */
static int layer_size (Layer *);
static int channel_size (Channel *);
static int group_count = 0;
static int shrink_wrap = FALSE;
#define UNDO 0
@ -249,6 +254,14 @@ undo_push (GImage *gimage,
{
undo_free_list (gimage, REDO, gimage->redo_stack);
gimage->redo_stack = NULL;
/* If the image was dirty, but could become clean by redo-ing
* some actions, then it should now become 'infinitely' dirty.
* This is because we've just nuked the actions that would allow
* the image to become clean again. The only hope for salvation
* is to save the image now! -- austin */
if (gimage->dirty < 0)
gimage->dirty = 10000;
}
if (!gimage->pushing_undo_group)
@ -384,6 +397,18 @@ undo_free (GImage *gimage)
gimage->redo_stack = NULL;
gimage->undo_bytes = 0;
gimage->undo_levels = 0;
/* If the image was dirty, but could become clean by redo-ing
* some actions, then it should now become 'infinitely' dirty.
* This is because we've just nuked the actions that would allow
* the image to become clean again. The only hope for salvation
* is to save the image now! -- austin */
if (gimage->dirty < 0)
gimage->dirty = 10000;
/* The same applies to the case where the image would become clean
* due to undo actions, but since user can't undo without an undo
* stack, that's not so much a problem. */
}
@ -397,16 +422,23 @@ undo_push_group_start (GImage *gimage,
if (! gimage->undo_on)
return FALSE;
group_count ++;
gimage->group_count ++;
/* If we're already in a group...ignore */
if (group_count > 1)
if (gimage->group_count > 1)
return TRUE;
if (gimage->redo_stack)
{
undo_free_list (gimage, REDO, gimage->redo_stack);
gimage->redo_stack = NULL;
/* If the image was dirty, but could become clean by redo-ing
* some actions, then it should now become 'infinitely' dirty.
* This is because we've just nuked the actions that would allow
* the image to become clean again. The only hope for salvation
* is to save the image now! -- austin */
if (gimage->dirty < 0)
gimage->dirty = 10000;
}
if (! undo_free_up_space (gimage))
@ -426,9 +458,9 @@ undo_push_group_end (GImage *gimage)
if (! gimage->undo_on)
return FALSE;
group_count --;
gimage->group_count --;
if (group_count == 0)
if (gimage->group_count == 0)
{
gimage->pushing_undo_group = 0;
gimage->undo_stack = g_slist_prepend (gimage->undo_stack, NULL);
@ -2423,3 +2455,134 @@ undo_free_parasite (int state,
g_free (data_ptr);
}
/*************/
/* Layer name change */
typedef struct {
Layer *layer;
gchar *old_name;
} LayerRenameUndo;
int
undo_push_layer_rename (GImage *gimage, Layer *layer)
{
Undo *new;
LayerRenameUndo *data;
long size;
/* increment the dirty flag for this gimage */
gimage_dirty (gimage);
size = sizeof (LayerRenameUndo);
if ((new = undo_push (gimage, size, LAYER_CHANGE)))
{
data = g_new (LayerRenameUndo, 1);
new->data = data;
new->pop_func = undo_pop_layer_rename;
new->free_func = undo_free_layer_rename;
data->layer = layer;
data->old_name = g_strdup (layer_get_name (layer));
return TRUE;
}
return FALSE;
}
static int
undo_pop_layer_rename (GImage *gimage,
int state,
int type,
void *data_ptr)
{
LayerRenameUndo *data = data_ptr;
gchar *tmp;
tmp = g_strdup (layer_get_name (data->layer));
layer_set_name (data->layer, data->old_name);
g_free (data->old_name);
data->old_name = tmp;
switch (state) {
case UNDO:
gimp_image_clean (gimage);
break;
case REDO:
gimp_image_dirty (gimage);
break;
}
return TRUE;
}
static void
undo_free_layer_rename (int state,
void *data_ptr)
{
LayerRenameUndo *data = data_ptr;
g_free (data->old_name);
g_free (data);
}
/*************/
/* Something for which programmer is too lazy to write an undo
* function for.
*/
int
undo_push_cantundo (GImage *gimage,
const char *action)
{
Undo *new;
/* This is the sole purpose of this type of undo: the ability to
* mark an image as having been mutated, without really providing
* any adequate undo facility. */
gimp_image_dirty (gimage);
new = undo_push (gimage, 0, GIMAGE_MOD);
if (!new)
return FALSE;
new->data = (void*)action;
new->pop_func = undo_pop_cantundo;
new->free_func = undo_free_cantundo;
return TRUE;
}
static int
undo_pop_cantundo (GImage *gimage,
int state,
int type,
void *data_ptr)
{
char *action = data_ptr;
switch (state) {
case UNDO:
g_message (_("Can't undo %s"), action);
gimp_image_clean (gimage);
break;
case REDO:
gimp_image_dirty (gimage);
break;
}
return TRUE;
}
static void
undo_free_cantundo (int state, void *data_ptr)
{
}

View File

@ -86,6 +86,8 @@ int undo_push_image_parasite_remove (GImage *, const char *);
int undo_push_drawable_parasite_remove (GImage *, GimpDrawable *,
const char *);
int undo_push_qmask (GImage *, int);
int undo_push_layer_rename (GImage *, Layer *);
int undo_push_cantundo (GImage *, const char *);
int undo_pop (GImage *);
int undo_redo (GImage *);