1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2019 gEDA Contributors (see ChangeLog for details)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "actions.decl.x"
32 #define MIME_TYPE_SCHEMATIC "application/x-geda-schematic"
33 #define CLIP_TYPE_SCHEMATIC 1
35 /* \brief Callback for handling system clipboard owner change.
36 * \par Function Description
40 clip_handle_owner_change (GtkClipboard
*cb
, GdkEvent
*event
,
43 GschemToplevel
*w_current
= (GschemToplevel
*) user_data
;
45 x_clipboard_update_menus (w_current
);
49 clip_get (GtkClipboard
*cb
, GtkSelectionData
*selection_data
,
50 guint info
, gpointer user_data_or_owner
)
52 GschemToplevel
*w_current
= (GschemToplevel
*) user_data_or_owner
;
53 GdkAtom type
= gdk_atom_intern (MIME_TYPE_SCHEMATIC
, FALSE
);
55 if (info
!= CLIP_TYPE_SCHEMATIC
) return;
56 /* Convert the objects in the clipboard buffer to gEDA schematic
58 buf
= o_save_buffer (w_current
->clipboard_buffer
);
59 /* Set the selection appropriately */
60 gtk_selection_data_set (selection_data
, type
,
61 8, /* 8-bit data (UTF-8) */
68 clip_clear (GtkClipboard
*cb
, gpointer user_data_or_owner
)
70 GschemToplevel
*w_current
= user_data_or_owner
;
71 TOPLEVEL
*toplevel
= gschem_toplevel_get_toplevel (w_current
);
73 /* Free the objects in the clipboard buffer */
74 s_delete_object_glist (toplevel
, w_current
->clipboard_buffer
);
75 w_current
->clipboard_buffer
= NULL
;
78 /* \brief Initialises system clipboard support
79 * \par Function Description
80 * Registers a signal handler to detect if the clipboard has changed
81 * and update the menu item sensitivity if necessary.
84 x_clipboard_init (GschemToplevel
*w_current
)
86 GtkClipboard
*cb
= gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
);
87 g_signal_connect (G_OBJECT (cb
),
89 G_CALLBACK (clip_handle_owner_change
),
93 /* \brief Initialises system clipboard support
94 * \par Function Description
95 * Registers a signal handler to detect if the clipboard has changed
96 * and update the menu item sensitivity if necessary.
99 x_clipboard_finish (GschemToplevel
*w_current
)
101 GtkClipboard
*cb
= gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
);
102 g_signal_handlers_disconnect_by_func (cb
, clip_handle_owner_change
, w_current
);
103 if (w_current
->clipboard_buffer
)
104 gtk_clipboard_store (cb
);
107 struct query_usable
{
108 void (*callback
) (int, void *);
113 /* \brief Callback for determining if any clipboard targets are pastable
114 * \par Function Description
116 * Checks if the clipboard targets match any format we recognise, then
117 * calls back into a supplied callback function which is interested in
118 * the TRUE / FALSE answer to whether we can paste from the clipboard.
121 query_usable_targets_cb (GtkClipboard
*clip
, GdkAtom
*targets
, gint ntargets
,
124 struct query_usable
*cbinfo
= data
;
126 int is_usable
= FALSE
;
128 for (i
= 0; i
< ntargets
; i
++) {
129 if (strcmp (gdk_atom_name (targets
[i
]), MIME_TYPE_SCHEMATIC
) == 0) {
135 cbinfo
->callback (is_usable
, cbinfo
->userdata
);
140 /* \brief Checks if the system clipboard contains schematic data.
141 * \par Function Description
142 * Checks whether the current owner of the system clipboard is
143 * advertising gEDA schematic data.
145 * The check is performed asynchronously. When a response is
146 * recieved, the provided callback is called with a TRUE / FALSE
149 * \param [in] w_current The current GschemToplevel.
150 * \param [in] callback The callback to recieve the response.
151 * \param [in] userdata Arbitrary data to pass the callback.
154 query_usable (GschemToplevel
*w_current
,
155 void (*callback
) (int, void *), void *userdata
)
157 GtkClipboard
*clip
= gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
);
158 struct query_usable
*cbinfo
;
160 cbinfo
= g_new (struct query_usable
, 1);
161 cbinfo
->callback
= callback
;
162 cbinfo
->userdata
= userdata
;
164 gtk_clipboard_request_targets (clip
, query_usable_targets_cb
, cbinfo
);
167 /*! \brief Asynchronous callback to update the sensitivity of the
168 * Edit/Paste menu item.
171 clipboard_usable_cb (int usable
, void *userdata
)
173 GschemToplevel
*w_current
= GSCHEM_TOPLEVEL (userdata
);
175 gschem_action_set_sensitive (action_clipboard_paste
, usable
, w_current
);
178 /*! \brief Update the sensitivity of the Edit/Paste menu item.
181 x_clipboard_update_menus(GschemToplevel
*w_current
)
183 query_usable (w_current
, clipboard_usable_cb
, w_current
);
186 /* \brief Set the contents of the system clipboard.
187 * \par Function Description
188 * Set the system clipboard to contain the gschem objects listed in \a
191 * \param [in,out] w_current The current GschemToplevel.
192 * \param [in] object_list The objects to put in the clipboard.
194 * \return TRUE if the clipboard is successfully set.
197 x_clipboard_set (GschemToplevel
*w_current
, const GList
*object_list
)
199 GtkClipboard
*cb
= gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
);
200 GtkTargetEntry target
= { MIME_TYPE_SCHEMATIC
, 0,
201 CLIP_TYPE_SCHEMATIC
};
202 TOPLEVEL
*toplevel
= gschem_toplevel_get_toplevel (w_current
);
205 /* Clear the clipboard buffer */
206 if (w_current
->clipboard_buffer
)
207 gtk_clipboard_clear (cb
);
209 /* Copy the objects to the clipboard buffer */
210 w_current
->clipboard_buffer
=
211 o_glist_copy_all (toplevel
, object_list
, w_current
->clipboard_buffer
);
213 /* Advertise that the data is available */
214 result
= gtk_clipboard_set_with_data (cb
, &target
, 1,
215 clip_get
, clip_clear
, w_current
);
217 /* Hint that the data can be stored to be accessed after the program
219 gtk_clipboard_set_can_store (cb
, NULL
, 0);
224 /* \brief Get the contents of the system clipboard.
225 * \par Function Description
226 * If the system clipboard contains schematic data, retrieve it.
228 * \param [in,out] w_current The current GschemToplevel.
230 * \returns Any OBJECTs retrieved from the system clipboard, or NULL
231 * if none were available.
234 x_clipboard_get (GschemToplevel
*w_current
)
236 GtkClipboard
*cb
= gtk_clipboard_get (GDK_SELECTION_CLIPBOARD
);
237 TOPLEVEL
*toplevel
= gschem_toplevel_get_toplevel (w_current
);
238 GdkAtom type
= gdk_atom_intern (MIME_TYPE_SCHEMATIC
, FALSE
);
239 GtkSelectionData
*selection_data
;
240 GList
*object_list
= NULL
;
244 /* Try to get the contents of the clipboard */
245 selection_data
= gtk_clipboard_wait_for_contents (cb
, type
);
246 if (selection_data
== NULL
) return FALSE
;
248 /* Convert the data buffer to OBJECTs */
249 #if GTK_CHECK_VERSION(2,14,0)
250 buf
= gtk_selection_data_get_data (selection_data
);
252 buf
= selection_data
->data
;
255 object_list
= o_read_buffer (toplevel
, object_list
,
256 (gchar
*) buf
, -1, "Clipboard", &err
);
259 GtkWidget
* dialog
= gtk_message_dialog_new_with_markup
260 (GTK_WINDOW (w_current
->main_window
),
261 GTK_DIALOG_DESTROY_WITH_PARENT
,
264 _("<b>Invalid schematic on clipboard.</b>\n\nAn error occurred while inserting clipboard data: %s."),
266 gtk_window_set_title (GTK_WINDOW (dialog
), _("Clipboard insertion failed"));
268 gtk_dialog_run (GTK_DIALOG (dialog
));
269 gtk_widget_destroy (dialog
);
272 gtk_selection_data_free (selection_data
);