/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include #include "libpikabase/pikabase.h" #include "libpikaconfig/pikaconfig.h" #include "libpikawidgets/pikawidgets.h" #include "actions-types.h" #include "config/pikadialogconfig.h" #include "core/pika.h" #include "core/pika-utils.h" #include "core/pikachannel.h" #include "core/pikacontext.h" #include "core/pikaimage.h" #include "core/pikaimage-merge.h" #include "core/pikaimage-undo.h" #include "core/pikaparamspecs.h" #include "core/pikaprogress.h" #include "core/pikatoolinfo.h" #include "pdb/pikapdb.h" #include "pdb/pikaprocedure.h" #include "vectors/pikavectors.h" #include "vectors/pikavectors-export.h" #include "vectors/pikavectors-import.h" #include "widgets/pikaaction.h" #include "widgets/pikaclipboard.h" #include "widgets/pikahelp-ids.h" #include "display/pikadisplay.h" #include "tools/pikavectortool.h" #include "tools/tool_manager.h" #include "dialogs/dialogs.h" #include "dialogs/vectors-export-dialog.h" #include "dialogs/vectors-import-dialog.h" #include "dialogs/vectors-options-dialog.h" #include "actions.h" #include "items-commands.h" #include "vectors-commands.h" #include "pika-intl.h" /* local function prototypes */ static void vectors_new_callback (GtkWidget *dialog, PikaImage *image, PikaVectors *vectors, PikaContext *context, const gchar *vectors_name, gboolean vectors_visible, PikaColorTag vectors_color_tag, gboolean vectors_lock_content, gboolean vectors_lock_position, gboolean vectors_lock_visibility, gpointer user_data); static void vectors_edit_attributes_callback (GtkWidget *dialog, PikaImage *image, PikaVectors *vectors, PikaContext *context, const gchar *vectors_name, gboolean vectors_visible, PikaColorTag vectors_color_tag, gboolean vectors_lock_content, gboolean vectors_lock_position, gboolean vectors_lock_visibility, gpointer user_data); static void vectors_import_callback (GtkWidget *dialog, PikaImage *image, GFile *file, GFile *import_folder, gboolean merge_vectors, gboolean scale_vectors, gpointer user_data); static void vectors_export_callback (GtkWidget *dialog, PikaImage *image, GFile *file, GFile *export_folder, gboolean active_only, gpointer user_data); /* public functions */ void vectors_edit_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; PikaTool *active_tool; return_if_no_vectors_list (image, vectors, data); if (g_list_length (vectors) != 1) return; active_tool = tool_manager_get_active (image->pika); if (! PIKA_IS_VECTOR_TOOL (active_tool)) { PikaToolInfo *tool_info = pika_get_tool_info (image->pika, "pika-vector-tool"); if (PIKA_IS_TOOL_INFO (tool_info)) { pika_context_set_tool (action_data_get_context (data), tool_info); active_tool = tool_manager_get_active (image->pika); } } if (PIKA_IS_VECTOR_TOOL (active_tool)) pika_vector_tool_set_vectors (PIKA_VECTOR_TOOL (active_tool), vectors->data); } void vectors_edit_attributes_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *paths; PikaVectors *vectors; GtkWidget *widget; GtkWidget *dialog; return_if_no_vectors_list (image, paths, data); return_if_no_widget (widget, data); if (g_list_length (paths) != 1) return; vectors = paths->data; #define EDIT_DIALOG_KEY "pika-vectors-edit-attributes-dialog" dialog = dialogs_get_dialog (G_OBJECT (vectors), EDIT_DIALOG_KEY); if (! dialog) { PikaItem *item = PIKA_ITEM (vectors); dialog = vectors_options_dialog_new (image, vectors, action_data_get_context (data), widget, _("Path Attributes"), "pika-vectors-edit", PIKA_ICON_EDIT, _("Edit Path Attributes"), PIKA_HELP_PATH_EDIT, pika_object_get_name (vectors), pika_item_get_visible (item), pika_item_get_color_tag (item), pika_item_get_lock_content (item), pika_item_get_lock_position (item), pika_item_get_lock_visibility (item), vectors_edit_attributes_callback, NULL); dialogs_attach_dialog (G_OBJECT (vectors), EDIT_DIALOG_KEY, dialog); } gtk_window_present (GTK_WINDOW (dialog)); } void vectors_new_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GtkWidget *widget; GtkWidget *dialog; return_if_no_image (image, data); return_if_no_widget (widget, data); #define NEW_DIALOG_KEY "pika-vectors-new-dialog" dialog = dialogs_get_dialog (G_OBJECT (image), NEW_DIALOG_KEY); if (! dialog) { PikaDialogConfig *config = PIKA_DIALOG_CONFIG (image->pika->config); dialog = vectors_options_dialog_new (image, NULL, action_data_get_context (data), widget, _("New Path"), "pika-vectors-new", PIKA_ICON_PATH, _("Create a New Path"), PIKA_HELP_PATH_NEW, config->vectors_new_name, FALSE, PIKA_COLOR_TAG_NONE, FALSE, FALSE, FALSE, vectors_new_callback, NULL); dialogs_attach_dialog (G_OBJECT (image), NEW_DIALOG_KEY, dialog); } gtk_window_present (GTK_WINDOW (dialog)); } void vectors_new_last_vals_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; PikaVectors *vectors; PikaDialogConfig *config; return_if_no_image (image, data); config = PIKA_DIALOG_CONFIG (image->pika->config); vectors = pika_vectors_new (image, config->vectors_new_name); pika_image_add_vectors (image, vectors, PIKA_IMAGE_ACTIVE_PARENT, -1, TRUE); pika_image_flush (image); } void vectors_raise_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *list; GList *iter; GList *moved_list = NULL; return_if_no_vectors_list (image, list, data); for (iter = list; iter; iter = iter->next) { gint index; index = pika_item_get_index (iter->data); if (index > 0) moved_list = g_list_prepend (moved_list, iter->data); } if (moved_list) { pika_image_undo_group_start (image, PIKA_UNDO_GROUP_ITEM_DISPLACE, ngettext ("Raise Path", "Raise Paths", g_list_length (moved_list))); for (iter = moved_list; iter; iter = iter->next) pika_image_raise_item (image, PIKA_ITEM (iter->data), NULL); pika_image_flush (image); pika_image_undo_group_end (image); g_list_free (moved_list); } } void vectors_raise_to_top_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *list; GList *iter; GList *moved_list = NULL; return_if_no_vectors_list (image, list, data); for (iter = list; iter; iter = iter->next) { gint index; index = pika_item_get_index (iter->data); if (index > 0) moved_list = g_list_prepend (moved_list, iter->data); } if (moved_list) { pika_image_undo_group_start (image, PIKA_UNDO_GROUP_ITEM_DISPLACE, ngettext ("Raise Path to Top", "Raise Paths to Top", g_list_length (moved_list))); for (iter = moved_list; iter; iter = iter->next) pika_image_raise_item_to_top (image, PIKA_ITEM (iter->data)); pika_image_flush (image); pika_image_undo_group_end (image); g_list_free (moved_list); } } void vectors_lower_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *list; GList *iter; GList *moved_list = NULL; return_if_no_vectors_list (image, list, data); for (iter = list; iter; iter = iter->next) { GList *vectors_list; gint index; vectors_list = pika_item_get_container_iter (PIKA_ITEM (iter->data)); index = pika_item_get_index (iter->data); if (index < g_list_length (vectors_list) - 1) moved_list = g_list_prepend (moved_list, iter->data); } if (moved_list) { moved_list = g_list_reverse (moved_list); pika_image_undo_group_start (image, PIKA_UNDO_GROUP_ITEM_DISPLACE, ngettext ("Lower Path", "Lower Paths", g_list_length (moved_list))); for (iter = moved_list; iter; iter = iter->next) pika_image_lower_item (image, PIKA_ITEM (iter->data), NULL); pika_image_flush (image); pika_image_undo_group_end (image); g_list_free (moved_list); } } void vectors_lower_to_bottom_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *list; GList *iter; GList *moved_list = NULL; return_if_no_vectors_list (image, list, data); for (iter = list; iter; iter = iter->next) { GList *vectors_list; gint index; vectors_list = pika_item_get_container_iter (PIKA_ITEM (iter->data)); index = pika_item_get_index (iter->data); if (index < g_list_length (vectors_list) - 1) moved_list = g_list_prepend (moved_list, iter->data); } if (moved_list) { moved_list = g_list_reverse (moved_list); pika_image_undo_group_start (image, PIKA_UNDO_GROUP_ITEM_DISPLACE, ngettext ("Lower Path to Bottom", "Lower Paths to Bottom", g_list_length (moved_list))); for (iter = moved_list; iter; iter = iter->next) pika_image_lower_item_to_bottom (image, PIKA_ITEM (iter->data)); pika_image_flush (image); pika_image_undo_group_end (image); g_list_free (moved_list); } } void vectors_duplicate_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *paths; GList *new_paths = NULL; GList *iter; return_if_no_vectors_list (image, paths, data); paths = g_list_copy (paths); paths = g_list_reverse (paths); /* TODO: proper undo group. */ pika_image_undo_group_start (image, PIKA_UNDO_GROUP_VECTORS_IMPORT, _("Duplicate Paths")); for (iter = paths; iter; iter = iter->next) { PikaVectors *new_vectors; new_vectors = PIKA_VECTORS (pika_item_duplicate (iter->data, G_TYPE_FROM_INSTANCE (iter->data))); /* use the actual parent here, not PIKA_IMAGE_ACTIVE_PARENT because * the latter would add a duplicated group inside itself instead of * above it */ pika_image_add_vectors (image, new_vectors, pika_vectors_get_parent (iter->data), -1, TRUE); new_paths = g_list_prepend (new_paths, new_vectors); } if (new_paths) { pika_image_set_selected_vectors (image, new_paths); pika_image_flush (image); } pika_image_undo_group_end (image); g_list_free (paths); } void vectors_delete_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *paths; return_if_no_vectors_list (image, paths, data); paths = g_list_copy (paths); /* TODO: proper undo group. */ pika_image_undo_group_start (image, PIKA_UNDO_GROUP_VECTORS_IMPORT, _("Remove Paths")); for (GList *iter = paths; iter; iter = iter->next) pika_image_remove_vectors (image, iter->data, TRUE, NULL); pika_image_undo_group_end (image); pika_image_flush (image); g_list_free (paths); } void vectors_merge_visible_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; GtkWidget *widget; GError *error = NULL; return_if_no_vectors_list (image, vectors, data); return_if_no_widget (widget, data); if (! pika_image_merge_visible_vectors (image, &error)) { pika_message_literal (image->pika, G_OBJECT (widget), PIKA_MESSAGE_WARNING, error->message); g_clear_error (&error); return; } pika_image_flush (image); } void vectors_to_selection_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; GList *iter; PikaChannelOps operation; return_if_no_vectors_list (image, vectors, data); pika_image_undo_group_start (image, PIKA_UNDO_GROUP_DRAWABLE_MOD, _("Paths to selection")); operation = (PikaChannelOps) g_variant_get_int32 (value); for (iter = vectors; iter; iter = iter->next) { pika_item_to_selection (iter->data, operation, TRUE, FALSE, 0, 0); if (operation == PIKA_CHANNEL_OP_REPLACE && iter == vectors) operation = PIKA_CHANNEL_OP_ADD; } pika_image_undo_group_end (image); pika_image_flush (image); } void vectors_selection_to_vectors_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GtkWidget *widget; PikaProcedure *procedure; PikaValueArray *args; PikaDisplay *display; gboolean advanced; GError *error = NULL; return_if_no_image (image, data); return_if_no_widget (widget, data); advanced = (gboolean) g_variant_get_int32 (value); procedure = pika_pdb_lookup_procedure (image->pika->pdb, "plug-in-sel2path"); if (! procedure) { pika_message_literal (image->pika, G_OBJECT (widget), PIKA_MESSAGE_ERROR, "Selection to path procedure lookup failed."); return; } display = pika_context_get_display (action_data_get_context (data)); args = pika_procedure_get_arguments (procedure); g_value_set_enum (pika_value_array_index (args, 0), advanced ? PIKA_RUN_INTERACTIVE : PIKA_RUN_NONINTERACTIVE); g_value_set_object (pika_value_array_index (args, 1), image); pika_procedure_execute_async (procedure, image->pika, action_data_get_context (data), PIKA_PROGRESS (display), args, display, &error); pika_value_array_unref (args); if (error) { pika_message_literal (image->pika, G_OBJECT (widget), PIKA_MESSAGE_ERROR, error->message); g_error_free (error); } } void vectors_fill_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; return_if_no_vectors_list (image, vectors, data); items_fill_cmd_callback (action, image, vectors, _("Fill Path"), PIKA_ICON_TOOL_BUCKET_FILL, PIKA_HELP_PATH_FILL, data); } void vectors_fill_last_vals_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; return_if_no_vectors_list (image, vectors, data); items_fill_last_vals_cmd_callback (action, image, vectors, data); } void vectors_stroke_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; return_if_no_vectors_list (image, vectors, data); items_stroke_cmd_callback (action, image, vectors, _("Stroke Path"), PIKA_ICON_PATH_STROKE, PIKA_HELP_PATH_STROKE, data); } void vectors_stroke_last_vals_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; return_if_no_vectors_list (image, vectors, data); items_stroke_last_vals_cmd_callback (action, image, vectors, data); } void vectors_copy_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; gchar *svg; return_if_no_vectors_list (image, vectors, data); svg = pika_vectors_export_string (image, vectors); if (svg) { pika_clipboard_set_svg (image->pika, svg); g_free (svg); } } void vectors_paste_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GtkWidget *widget; gchar *svg; gsize svg_size; return_if_no_image (image, data); return_if_no_widget (widget, data); svg = pika_clipboard_get_svg (image->pika, &svg_size); if (svg) { GError *error = NULL; if (! pika_vectors_import_buffer (image, svg, svg_size, TRUE, FALSE, PIKA_IMAGE_ACTIVE_PARENT, -1, NULL, &error)) { pika_message (image->pika, G_OBJECT (widget), PIKA_MESSAGE_ERROR, "%s", error->message); g_clear_error (&error); } else { pika_image_flush (image); } g_free (svg); } } void vectors_export_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; GtkWidget *widget; GtkWidget *dialog; return_if_no_vectors_list (image, vectors, data); return_if_no_widget (widget, data); #define EXPORT_DIALOG_KEY "pika-vectors-export-dialog" dialog = dialogs_get_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY); if (! dialog) { PikaDialogConfig *config = PIKA_DIALOG_CONFIG (image->pika->config); GFile *folder = NULL; if (config->vectors_export_path) folder = pika_file_new_for_config_path (config->vectors_export_path, NULL); dialog = vectors_export_dialog_new (image, widget, folder, config->vectors_export_active_only, vectors_export_callback, NULL); if (folder) g_object_unref (folder); dialogs_attach_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY, dialog); } gtk_window_present (GTK_WINDOW (dialog)); } void vectors_import_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GtkWidget *widget; GtkWidget *dialog; return_if_no_image (image, data); return_if_no_widget (widget, data); #define IMPORT_DIALOG_KEY "pika-vectors-import-dialog" dialog = dialogs_get_dialog (G_OBJECT (image), IMPORT_DIALOG_KEY); if (! dialog) { PikaDialogConfig *config = PIKA_DIALOG_CONFIG (image->pika->config); GFile *folder = NULL; if (config->vectors_import_path) folder = pika_file_new_for_config_path (config->vectors_import_path, NULL); dialog = vectors_import_dialog_new (image, widget, folder, config->vectors_import_merge, config->vectors_import_scale, vectors_import_callback, NULL); dialogs_attach_dialog (G_OBJECT (image), IMPORT_DIALOG_KEY, dialog); } gtk_window_present (GTK_WINDOW (dialog)); } void vectors_visible_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; return_if_no_vectors_list (image, vectors, data); items_visible_cmd_callback (action, value, image, vectors); } void vectors_lock_content_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; return_if_no_vectors_list (image, vectors, data); items_lock_content_cmd_callback (action, value, image, vectors); } void vectors_lock_position_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; return_if_no_vectors_list (image, vectors, data); items_lock_position_cmd_callback (action, value, image, vectors); } void vectors_color_tag_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *vectors; PikaColorTag color_tag; return_if_no_vectors_list (image, vectors, data); color_tag = (PikaColorTag) g_variant_get_int32 (value); items_color_tag_cmd_callback (action, image, vectors, color_tag); } /* private functions */ static void vectors_new_callback (GtkWidget *dialog, PikaImage *image, PikaVectors *vectors, PikaContext *context, const gchar *vectors_name, gboolean vectors_visible, PikaColorTag vectors_color_tag, gboolean vectors_lock_content, gboolean vectors_lock_position, gboolean vectors_lock_visibility, gpointer user_data) { PikaDialogConfig *config = PIKA_DIALOG_CONFIG (image->pika->config); g_object_set (config, "path-new-name", vectors_name, NULL); vectors = pika_vectors_new (image, config->vectors_new_name); pika_item_set_visible (PIKA_ITEM (vectors), vectors_visible, FALSE); pika_item_set_color_tag (PIKA_ITEM (vectors), vectors_color_tag, FALSE); pika_item_set_lock_content (PIKA_ITEM (vectors), vectors_lock_content, FALSE); pika_item_set_lock_position (PIKA_ITEM (vectors), vectors_lock_position, FALSE); pika_item_set_lock_visibility (PIKA_ITEM (vectors), vectors_lock_visibility, FALSE); pika_image_add_vectors (image, vectors, PIKA_IMAGE_ACTIVE_PARENT, -1, TRUE); pika_image_flush (image); gtk_widget_destroy (dialog); } static void vectors_edit_attributes_callback (GtkWidget *dialog, PikaImage *image, PikaVectors *vectors, PikaContext *context, const gchar *vectors_name, gboolean vectors_visible, PikaColorTag vectors_color_tag, gboolean vectors_lock_content, gboolean vectors_lock_position, gboolean vectors_lock_visibility, gpointer user_data) { PikaItem *item = PIKA_ITEM (vectors); if (strcmp (vectors_name, pika_object_get_name (vectors)) || vectors_visible != pika_item_get_visible (item) || vectors_color_tag != pika_item_get_color_tag (item) || vectors_lock_content != pika_item_get_lock_content (item) || vectors_lock_position != pika_item_get_lock_position (item) || vectors_lock_visibility != pika_item_get_lock_visibility (item)) { pika_image_undo_group_start (image, PIKA_UNDO_GROUP_ITEM_PROPERTIES, _("Path Attributes")); if (strcmp (vectors_name, pika_object_get_name (vectors))) pika_item_rename (PIKA_ITEM (vectors), vectors_name, NULL); if (vectors_visible != pika_item_get_visible (item)) pika_item_set_visible (item, vectors_visible, TRUE); if (vectors_color_tag != pika_item_get_color_tag (item)) pika_item_set_color_tag (item, vectors_color_tag, TRUE); if (vectors_lock_content != pika_item_get_lock_content (item)) pika_item_set_lock_content (item, vectors_lock_content, TRUE); if (vectors_lock_position != pika_item_get_lock_position (item)) pika_item_set_lock_position (item, vectors_lock_position, TRUE); if (vectors_lock_visibility != pika_item_get_lock_visibility (item)) pika_item_set_lock_visibility (item, vectors_lock_visibility, TRUE); pika_image_undo_group_end (image); pika_image_flush (image); } gtk_widget_destroy (dialog); } static void vectors_import_callback (GtkWidget *dialog, PikaImage *image, GFile *file, GFile *import_folder, gboolean merge_vectors, gboolean scale_vectors, gpointer user_data) { PikaDialogConfig *config = PIKA_DIALOG_CONFIG (image->pika->config); gchar *path = NULL; GError *error = NULL; if (import_folder) path = pika_file_get_config_path (import_folder, NULL); g_object_set (config, "path-import-path", path, "path-import-merge", merge_vectors, "path-import-scale", scale_vectors, NULL); if (path) g_free (path); if (pika_vectors_import_file (image, file, config->vectors_import_merge, config->vectors_import_scale, PIKA_IMAGE_ACTIVE_PARENT, -1, NULL, &error)) { pika_image_flush (image); } else { pika_message (image->pika, G_OBJECT (dialog), PIKA_MESSAGE_ERROR, "%s", error->message); g_error_free (error); return; } gtk_widget_destroy (dialog); } static void vectors_export_callback (GtkWidget *dialog, PikaImage *image, GFile *file, GFile *export_folder, gboolean active_only, gpointer user_data) { PikaDialogConfig *config = PIKA_DIALOG_CONFIG (image->pika->config); GList *vectors = NULL; gchar *path = NULL; GError *error = NULL; if (export_folder) path = pika_file_get_config_path (export_folder, NULL); g_object_set (config, "path-export-path", path, "path-export-active-only", active_only, NULL); if (path) g_free (path); if (config->vectors_export_active_only) vectors = pika_image_get_selected_vectors (image); if (! pika_vectors_export_file (image, vectors, file, &error)) { pika_message (image->pika, G_OBJECT (dialog), PIKA_MESSAGE_ERROR, "%s", error->message); g_clear_error (&error); return; } gtk_widget_destroy (dialog); } void vectors_select_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *new_vectors = NULL; GList *vectors; GList *iter; PikaActionSelectType select_type; gboolean run_once; return_if_no_image (image, data); select_type = (PikaActionSelectType) g_variant_get_int32 (value); vectors = pika_image_get_selected_vectors (image); run_once = (g_list_length (vectors) == 0); for (iter = vectors; iter || run_once; iter = iter ? iter->next : NULL) { PikaVectors *new_vec; PikaContainer *container; if (iter) { container = pika_item_get_container (PIKA_ITEM (iter->data)); } else /* run_once */ { container = pika_image_get_vectors (image); run_once = FALSE; } new_vec = (PikaVectors *) action_select_object (select_type, container, iter ? iter->data : NULL); if (new_vec) new_vectors = g_list_prepend (new_vectors, new_vec); } if (new_vectors) { pika_image_set_selected_vectors (image, new_vectors); pika_image_flush (image); } g_list_free (new_vectors); }