Commit 0b3e02be authored by Michael Natterer's avatar Michael Natterer 😴

libgimp: again, redo all APIs returning list of images, items, children

We now have both variants, one returning a GList, and another
returning an array. Turns out that while a list is often nicer,
sometimes a random-access array really keeps the code much simpler.

Adapt all plug-ins, and clean up a bit (like use g_list_reverse() once
instead of iterating the list reversed).
parent 6391b2bc
Pipeline #108759 passed with stages
in 31 minutes and 18 seconds
......@@ -299,6 +299,7 @@ EXPORTS
gimp_get_color_configuration
gimp_get_default_comment
gimp_get_default_unit
gimp_get_images
gimp_get_module_load_inhibit
gimp_get_monitor_resolution
gimp_get_parasite
......@@ -449,8 +450,10 @@ EXPORTS
gimp_image_insert_vectors
gimp_image_is_dirty
gimp_image_is_valid
gimp_image_list
gimp_image_list_channels
gimp_image_list_deprecated
gimp_image_list_layers
gimp_image_list_vectors
gimp_image_lower_item
gimp_image_lower_item_to_bottom
gimp_image_merge_down
......@@ -537,6 +540,7 @@ EXPORTS
gimp_item_is_text_layer
gimp_item_is_valid
gimp_item_is_vectors
gimp_item_list_children
gimp_item_set_color_tag
gimp_item_set_expanded
gimp_item_set_linked
......@@ -603,6 +607,7 @@ EXPORTS
gimp_layer_set_offsets
gimp_layer_set_opacity
gimp_layer_set_show_mask
gimp_list_images
gimp_load_procedure_get_handles_raw
gimp_load_procedure_get_thumbnail_loader
gimp_load_procedure_get_type
......
......@@ -76,8 +76,9 @@ export_merge (GimpImage *image,
GList *iter;
gint32 nvisible = 0;
layers = gimp_image_get_layers (image);
for (iter = layers; iter; iter = iter->next)
layers = gimp_image_list_layers (image);
for (iter = layers; iter; iter = g_list_next (iter))
{
if (gimp_item_get_visible (GIMP_ITEM (iter->data)))
nvisible++;
......@@ -119,11 +120,14 @@ export_merge (GimpImage *image,
}
g_list_free (layers);
layers = gimp_image_get_layers (image);
layers = gimp_image_list_layers (image);
/* make sure that the merged drawable matches the image size */
if (gimp_drawable_width (GIMP_DRAWABLE (merged)) != gimp_image_width (image) ||
gimp_drawable_height (GIMP_DRAWABLE (merged)) != gimp_image_height (image))
if (gimp_drawable_width (GIMP_DRAWABLE (merged)) !=
gimp_image_width (image) ||
gimp_drawable_height (GIMP_DRAWABLE (merged)) !=
gimp_image_height (image))
{
gint off_x, off_y;
......@@ -138,9 +142,10 @@ export_merge (GimpImage *image,
/* remove any remaining (invisible) layers */
for (iter = layers; iter; iter = iter->next)
{
if (gimp_item_get_id (iter->data) != gimp_item_get_id (GIMP_ITEM (*drawable)))
if (iter->data != *drawable)
gimp_image_remove_layer (image, iter->data);
}
g_list_free (layers);
}
......@@ -163,7 +168,7 @@ export_remove_alpha (GimpImage *image,
GList *layers;
GList *iter;
layers = gimp_image_get_layers (image);
layers = gimp_image_list_layers (image);
for (iter = layers; iter; iter = iter->next)
{
......@@ -181,7 +186,7 @@ export_apply_masks (GimpImage *image,
GList *layers;
GList *iter;
layers = gimp_image_get_layers (image);
layers = gimp_image_list_layers (image);
for (iter = layers; iter; iter = iter->next)
{
......@@ -216,7 +221,8 @@ export_convert_indexed (GimpImage *image,
GList *layers;
/* check alpha */
layers = gimp_image_get_layers (image);
layers = gimp_image_list_layers (image);
if (layers || gimp_drawable_has_alpha (*drawable))
gimp_image_convert_indexed (image,
GIMP_CONVERT_DITHER_NONE,
......@@ -250,12 +256,14 @@ export_add_alpha (GimpImage *image,
GList *layers;
GList *iter;
layers = gimp_image_get_layers (image);
layers = gimp_image_list_layers (image);
for (iter = layers; iter; iter = iter->next)
{
if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (iter->data)))
gimp_layer_add_alpha (GIMP_LAYER (iter->data));
}
g_list_free (layers);
}
......@@ -791,7 +799,7 @@ gimp_export_image (GimpImage **image,
/* check alpha and layer masks */
layers = gimp_image_get_layers (*image);
layers = gimp_image_list_layers (*image);
for (iter = layers; iter; iter = iter->next)
{
......@@ -844,7 +852,7 @@ gimp_export_image (GimpImage **image,
GimpLayer *layer = GIMP_LAYER (layers->data);
GList *children;
children = gimp_item_get_children (GIMP_ITEM (layer));
children = gimp_item_list_children (GIMP_ITEM (layer));
/* check if layer size != canvas size, opacity != 100%, or offsets != 0 */
if (g_list_length (layers) == 1 &&
......
......@@ -168,7 +168,41 @@ gimp_image_get_by_id (gint32 image_id)
}
/**
* gimp_image_list:
* gimp_get_images:
* @num_images: (out): The number of images in the returned array.
*
* Returns the list of images currently open.
*
* This procedure returns the list of images currently open in GIMP.
*
* Returns: (array length=num_images) (transfer container):
* The list of images currently open.
* The returned array must be freed with g_free(). Image
* elements belong to libgimp and must not be freed.
*
* Since: 3.0
**/
GimpImage **
gimp_get_images (gint *num_images)
{
GimpImage **images;
gint *ids;
gint i;
ids = _gimp_image_list (num_images);
images = g_new (GimpImage *, *num_images);
for (i = 0; i < *num_images; i++)
images[i] = gimp_image_get_by_id (ids[i]);
g_free (ids);
return images;
}
/**
* gimp_list_images:
*
* Returns the list of images currently open.
*
......@@ -176,11 +210,13 @@ gimp_image_get_by_id (gint32 image_id)
*
* Returns: (element-type GimpImage) (transfer container):
* The list of images currently open.
* The returned value must be freed with g_list_free(). Image
* The returned list must be freed with g_list_free(). Image
* elements belong to libgimp and must not be freed.
*
* Since: 3.0
**/
GList *
gimp_image_list (void)
gimp_list_images (void)
{
GList *images = NULL;
gint *ids;
......@@ -200,6 +236,114 @@ gimp_image_list (void)
/**
* gimp_image_get_layers:
* @image: The image.
* @num_layers: (out): The number of layers in the returned array.
*
* Returns the list of layers contained in the specified image.
*
* This procedure returns the list of layers contained in the specified
* image. The order of layers is from topmost to bottommost.
*
* Returns: (array length=num_layers) (transfer container):
* The list of layers contained in the image.
* The returned array must be freed with g_free(). Layer
* elements belong to libgimp and must not be freed.
**/
GimpLayer **
gimp_image_get_layers (GimpImage *image,
gint *num_layers)
{
GimpLayer **layers;
gint *ids;
gint i;
ids = _gimp_image_get_layers (image, num_layers);
layers = g_new (GimpLayer *, *num_layers);
for (i = 0; i < *num_layers; i++)
layers[i] = GIMP_LAYER (gimp_item_get_by_id (ids[i]));
g_free (ids);
return layers;
}
/**
* gimp_image_get_channels:
* @image: The image.
* @num_channels: (out): The number of channels in the returned array.
*
* Returns the list of channels contained in the specified image.
*
* This procedure returns the list of channels contained in the
* specified image. This does not include the selection mask, or layer
* masks. The order is from topmost to bottommost. Note that
* "channels" are custom channels and do not include the image's color
* components.
*
* Returns: (array length=num_channels) (transfer container):
* The list of channels contained in the image.
* The returned array must be freed with g_free(). Channel
* elements belong to libgimp and must not be freed.
**/
GimpChannel **
gimp_image_get_channels (GimpImage *image,
gint *num_channels)
{
GimpChannel **channels;
gint *ids;
gint i;
ids = _gimp_image_get_channels (image, num_channels);
channels = g_new (GimpChannel *, *num_channels);
for (i = 0; i < *num_channels; i++)
channels[i] = GIMP_CHANNEL (gimp_item_get_by_id (ids[i]));
g_free (ids);
return channels;
}
/**
* gimp_image_get_vectors:
* @image: The image.
* @num_vectors: (out): The number of vectors in the returned array.
*
* Returns the list of vectors contained in the specified image.
*
* This procedure returns the list of vectors contained in the
* specified image.
*
* Returns: (array length=num_vectors) (transfer container):
* The list of vectors contained in the image.
* The returned array must be freed with g_free(). Vectors
* elements belong to libgimp and must not be freed.
**/
GimpVectors **
gimp_image_get_vectors (GimpImage *image,
gint *num_vectors)
{
GimpVectors **vectors;
gint *ids;
gint i;
ids = _gimp_image_get_vectors (image, num_vectors);
vectors = g_new (GimpVectors *, *num_vectors);
for (i = 0; i < *num_vectors; i++)
vectors[i] = GIMP_VECTORS (gimp_item_get_by_id (ids[i]));
g_free (ids);
return vectors;
}
/**
* gimp_image_list_layers:
* @image: The image.
*
* Returns the list of layers contained in the specified image.
......@@ -209,13 +353,13 @@ gimp_image_list (void)
*
* Returns: (element-type GimpImage) (transfer container):
* The list of layers contained in the image.
* The returned value must be freed with g_list_free(). Layer
* The returned list must be freed with g_list_free(). Layer
* elements belong to libgimp and must not be freed.
*
* Since: 3.0
**/
GList *
gimp_image_get_layers (GimpImage *image)
gimp_image_list_layers (GimpImage *image)
{
GList *layers = NULL;
gint *ids;
......@@ -223,17 +367,18 @@ gimp_image_get_layers (GimpImage *image)
gint i;
ids = _gimp_image_get_layers (image, &num_layers);
for (i = 0; i < num_layers; i++)
layers = g_list_prepend (layers,
GIMP_LAYER (gimp_item_get_by_id (ids[i])));
layers = g_list_reverse (layers);
g_free (ids);
return layers;
return g_list_reverse (layers);
}
/**
* gimp_image_get_channels:
* gimp_image_list_channels:
* @image: The image.
*
* Returns the list of channels contained in the specified image.
......@@ -241,18 +386,18 @@ gimp_image_get_layers (GimpImage *image)
* This procedure returns the list of channels contained in the
* specified image. This does not include the selection mask, or layer
* masks. The order is from topmost to bottommost. Note that
* \"channels\" are custom channels and do not include the image's
* "channels" are custom channels and do not include the image's
* color components.
*
* Returns: (element-type GimpChannel) (transfer container):
* The list of channels contained in the image.
* The returned value must be freed with g_list_free(). Channel
* The returned list must be freed with g_list_free(). Channel
* elements belong to libgimp and must not be freed.
*
* Since: 3.0
**/
GList *
gimp_image_get_channels (GimpImage *image)
gimp_image_list_channels (GimpImage *image)
{
GList *channels = NULL;
gint *ids;
......@@ -260,17 +405,18 @@ gimp_image_get_channels (GimpImage *image)
gint i;
ids = _gimp_image_get_channels (image, &num_channels);
for (i = 0; i < num_channels; i++)
channels = g_list_prepend (channels,
GIMP_CHANNEL (gimp_item_get_by_id (ids[i])));
channels = g_list_reverse (channels);
g_free (ids);
return channels;
return g_list_reverse (channels);
}
/**
* gimp_image_get_vectors:
* gimp_image_list_vectors:
* @image: The image.
*
* Returns the list of vectors contained in the specified image.
......@@ -286,7 +432,7 @@ gimp_image_get_channels (GimpImage *image)
* Since: 3.0
**/
GList *
gimp_image_get_vectors (GimpImage *image)
gimp_image_list_vectors (GimpImage *image)
{
GList *vectors = NULL;
gint *ids;
......@@ -294,13 +440,14 @@ gimp_image_get_vectors (GimpImage *image)
gint i;
ids = _gimp_image_get_vectors (image, &num_vectors);
for (i = 0; i < num_vectors; i++)
vectors = g_list_prepend (vectors,
GIMP_VECTORS (gimp_item_get_by_id (ids[i])));
vectors = g_list_reverse (vectors);
g_free (ids);
return vectors;
return g_list_reverse (vectors);
}
/**
......@@ -340,9 +487,9 @@ gimp_image_get_colormap (GimpImage *image,
* Sets the entries in the image's colormap.
*
* This procedure sets the entries in the specified image's colormap.
* The number of colors is specified by the \"num_colors\" parameter
* The number of colors is specified by the "num_colors" parameter
* and corresponds to the number of INT8 triples that must be contained
* in the \"cmap\" array.
* in the "cmap" array.
*
* Returns: TRUE on success.
*/
......@@ -551,7 +698,7 @@ gimp_image_get_layers_deprecated (gint32 image_id,
* This procedure returns the list of channels contained in the
* specified image. This does not include the selection mask, or layer
* masks. The order is from topmost to bottommost. Note that
* \"channels\" are custom channels and do not include the image's
* "channels" are custom channels and do not include the image's
* color components.
*
* Returns: (array length=num_channels):
......@@ -620,9 +767,9 @@ gimp_image_get_colormap_deprecated (gint32 image_id,
* Sets the entries in the image's colormap.
*
* This procedure sets the entries in the specified image's colormap.
* The number of colors is specified by the \"num_colors\" parameter
* The number of colors is specified by the "num_colors" parameter
* and corresponds to the number of INT8 triples that must be contained
* in the \"cmap\" array.
* in the "cmap" array.
*
* Returns: TRUE on success.
*/
......
......@@ -68,13 +68,21 @@ GType gimp_image_get_type (void) G_GNUC_CONST;
gint32 gimp_image_get_id (GimpImage *image);
GimpImage * gimp_image_get_by_id (gint32 image_id);
GList * gimp_image_list (void);
GimpImage ** gimp_get_images (gint *num_images);
GList * gimp_list_images (void);
#ifndef GIMP_DEPRECATED_REPLACE_NEW_API
GList * gimp_image_get_layers (GimpImage *image);
GList * gimp_image_get_channels (GimpImage *image);
GList * gimp_image_get_vectors (GimpImage *image);
GimpLayer ** gimp_image_get_layers (GimpImage *image,
gint *num_layers);
GimpChannel ** gimp_image_get_channels (GimpImage *image,
gint *num_channels);
GimpVectors ** gimp_image_get_vectors (GimpImage *image,
gint *num_vectors);
GList * gimp_image_list_layers (GimpImage *image);
GList * gimp_image_list_channels (GimpImage *image);
GList * gimp_image_list_vectors (GimpImage *image);
guchar * gimp_image_get_colormap (GimpImage *image,
gint *num_colors);
......
......@@ -184,7 +184,7 @@ gimp_image_combo_box_populate (GimpImageComboBox *combo_box)
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
images = gimp_image_list ();
images = gimp_list_images ();
gimp_image_combo_box_model_add (GTK_LIST_STORE (model), images,
combo_box->constraint,
......@@ -208,7 +208,7 @@ gimp_image_combo_box_model_add (GtkListStore *store,
GtkTreeIter iter;
GList *list;
for (list = images; list; list = list->next)
for (list = images; list; list = g_list_next (list))
{
GimpImage *image = list->data;
gint32 image_id = gimp_image_get_id (image);
......
......@@ -174,6 +174,41 @@ gimp_item_get_by_id (gint32 item_id)
/**
* gimp_item_get_children:
* @item: The item.
* @num_children: (out): The number of items in the returned array.
*
* Returns the item's list of children.
*
* This procedure returns the list of items which are children of the
* specified item. The order is topmost to bottommost.
*
* Returns: (array length=num_children) (transfer container):
* The item's list of children.
* The returned array must be freed with g_free(). Item
* elements belong to libgimp and must not be unrefed.
**/
GimpItem **
gimp_item_get_children (GimpItem *item,
gint *num_children)
{
GimpItem **children;
gint *ids;
gint i;
ids = _gimp_item_get_children (item, num_children);
children = g_new (GimpItem *, *num_children);
for (i = 0; i < *num_children; i++)
children[i] = gimp_item_get_by_id (ids[i]);
g_free (ids);
return children;
}
/**
* gimp_item_list_children:
* @item: The item.
*
* Returns the item's list of children.
......@@ -183,13 +218,13 @@ gimp_item_get_by_id (gint32 item_id)
*
* Returns: (element-type GimpItem) (transfer container):
* The item's list of children.
* The returned value must be freed with g_list_free(). Item
* The returned ist must be freed with g_list_free(). Item
* elements belong to libgimp and must not be unrefed.
*
* Since: 3.0
**/
GList *
gimp_item_get_children (GimpItem *item)
gimp_item_list_children (GimpItem *item)
{
GList *children = NULL;
gint *ids;
......
......@@ -64,14 +64,16 @@ struct _GimpItemClass
void (*_gimp_reserved9) (void);
};
GType gimp_item_get_type (void) G_GNUC_CONST;
GType gimp_item_get_type (void) G_GNUC_CONST;
gint32 gimp_item_get_id (GimpItem *item);
GimpItem * gimp_item_get_by_id (gint32 item_id);
gint32 gimp_item_get_id (GimpItem *item);
GimpItem * gimp_item_get_by_id (gint32 item_id);
#ifndef GIMP_DEPRECATED_REPLACE_NEW_API
GList * gimp_item_get_children (GimpItem *item);
GimpItem ** gimp_item_get_children (GimpItem *item,
gint *num_children);
GList * gimp_item_list_children (GimpItem *item);
#else /* GIMP_DEPRECATED_REPLACE_NEW_API */
......
......@@ -393,9 +393,9 @@ gimp_item_combo_box_populate (GimpIntComboBox *combo_box)
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
images = gimp_image_list ();
images = gimp_list_images ();
for (list = images; list; list = list->next)
for (list = images; list; list = g_list_next (list))
{
GimpImage *image = list->data;
GList *items;
......@@ -403,7 +403,7 @@ gimp_item_combo_box_populate (GimpIntComboBox *combo_box)
if (GIMP_IS_DRAWABLE_COMBO_BOX (combo_box) ||
GIMP_IS_LAYER_COMBO_BOX (combo_box))
{
items = gimp_image_get_layers (image);
items = gimp_image_list_layers (image);
gimp_item_combo_box_model_add (combo_box, GTK_LIST_STORE (model),
image, items, 0);
g_list_free (items);
......@@ -412,7 +412,7 @@ gimp_item_combo_box_populate (GimpIntComboBox *combo_box)
if (GIMP_IS_DRAWABLE_COMBO_BOX (combo_box) ||
GIMP_IS_CHANNEL_COMBO_BOX (combo_box))
{
items = gimp_image_get_channels (image);
items = gimp_image_list_channels (image);
gimp_item_combo_box_model_add (combo_box, GTK_LIST_STORE (model),
image, items, 0);
g_list_free (items);
......@@ -420,7 +420,7 @@ gimp_item_combo_box_populate (GimpIntComboBox *combo_box)
if (GIMP_IS_VECTORS_COMBO_BOX (combo_box))
{
items = gimp_image_get_vectors (image);
items = gimp_image_list_vectors (image);
gimp_item_combo_box_model_add (combo_box, GTK_LIST_STORE (model),
image, items, 0);
g_list_free (items);
......@@ -457,7 +457,7 @@ gimp_item_combo_box_model_add (GimpIntComboBox *combo_box,
indent = g_strdup ("");
}
for (list = items; list; list = list->next)
for (list = items; list; list = g_list_next (list))
{
GimpItem *item = list->data;
gint32 item_id = gimp_item_get_id (item);
......@@ -503,7 +503,7 @@ gimp_item_combo_box_model_add (GimpIntComboBox *combo_box,
{
GList *children;
children = gimp_item_get_children (item);
children = gimp_item_list_children (item);
gimp_item_combo_box_model_add (combo_box, store,
image, children,
tree_level + 1);
......
......@@ -937,16 +937,21 @@ build_dialog (gchar *imagename)
/* Set up the frame disposal combo. */
frame_disposal_combo = gtk_combo_box_text_new ();
/* 2 styles of default frame disposals: cumulative layers and one frame per layer. */
/* 2 styles of default frame disposals: cumulative layers and one
* frame per layer.
*/
text = g_strdup (_("Cumulative layers (combine)"));
gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (frame_disposal_combo), DISPOSE_COMBINE, text);
gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (frame_disposal_combo),
DISPOSE_COMBINE, text);
g_free (text);
text = g_strdup (_("One frame per layer (replace)"));
gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (frame_disposal_combo), DISPOSE_REPLACE, text);
gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (frame_disposal_combo),
DISPOSE_REPLACE, text);
g_free (text);
gtk_combo_box_set_active (GTK_COMBO_BOX (frame_disposal_combo), settings.default_frame_disposal);
gtk_combo_box_set_active (GTK_COMBO_BOX (frame_disposal_combo),
settings.default_frame_disposal);
g_signal_connect (frame_disposal_combo, "changed",
G_CALLBACK (framecombo_changed),
......@@ -1040,14 +1045,19 @@ init_frames (void)
gimp_quit ();
return;
}
/* We only use RGB images for display because indexed images would somehow
render terrible colors. Layers from other types will be automatically
converted. */
/* We only use RGB images for display because indexed images would
* somehow render terrible colors. Layers from other types will be
* automatically converted.
*/
frames_image = gimp_image_new (width, height, GIMP_RGB);
/* Save processing time and memory by not saving history and merged frames. */
gimp_image_undo_disable (frames_image);
for (iter = g_list_last (layers), i = 0; iter; iter = iter->prev, i++)
for (iter = layers, i = 0;
iter;
iter = g_list_next (iter), i++)
{
layer_name = gimp_item_get_name (iter->data);
if (layer_name)
......@@ -1066,7 +1076,8 @@ init_frames (void)
new_layer = gimp_layer_new_from_drawable (iter->data, frames_image);
gimp_image_insert_layer (frames_image, new_layer, NULL, -1);
gimp_item_set_visible (GIMP_ITEM (new_layer), TRUE);
new_frame = gimp_image_merge_visible_layers (frames_image, GIMP_CLIP_TO_IMAGE);
new_frame = gimp_image_merge_visible_layers (frames_image,
GIMP_CLIP_TO_IMAGE);
frames[i] = new_frame;
gimp_item_set_visible (GIMP_ITEM (new_frame), FALSE);
......@@ -1112,9 +1123,11 @@ initialize (void)
return;
}
width = gimp_image_width (image);
height = gimp_image_height (image);
layers = gimp_image_get_layers (image);
width = gimp_image_width (image);
height = gimp_image_height (image);
layers = gimp_image_list_layers (image);
layers = g_list_reverse (layers);
if (!window)
build_dialog (gimp_image_get_name (image));
......
......@@ -370,7 +370,7 @@ remap (GimpImage *image,
/* There is no needs to process the layers recursively, because
* indexed images cannot have layer groups.
*/
layers = gimp_image_get_layers (image);
layers = gimp_image_list_layers (image);
for (list = layers; list; list = list->next)
pixels +=
......
......@@ -688,7 +688,7 @@ sanity_check (GFile *file,
/*** within the bounds of the image ***/
*image = gimp_image_duplicate (*image);
layers = gimp_image_get_layers (*image);
layers = gimp_image_list_layers (*image);
for (list = layers; list; list = g_list_next (list))
{
......@@ -802,8 +802,7 @@ save_image (GFile *file,
}
/* get a list of layers for this image */
layers = gimp_image_get_layers (image);
layers = gimp_image_list_layers (image);
nlayers = g_list_length (layers);
drawable_type = gimp_drawable_type (layers->data);
......@@ -963,9 +962,11 @@ save_image (GFile *file,
cur_progress = 0;
max_progress = nlayers * rows;
for (list = g_list_last (layers),i = nlayers - 1;
layers = g_list_reverse (layers);
for (list = layers, i = nlayers - 1;
list && i >= 0;
list = g_list_previous (list), i--, cur_progress = (nlayers - i) * rows)
list = g_list_next (list), i--, cur_progress = (nlayers - i) * rows)
{
GimpDrawable *drawable = list->data;
......@@ -1251,14 +1252,11 @@ save_dialog (GimpImage *image)
GtkWidget *toggle;
GtkWidget *frame;
GimpParasite *GIF2_CMNT;
GList *layers;
gint32 nlayers;