summaryrefslogtreecommitdiffstats
authorPeter TB Brett <peter@peter-b.co.uk>2009-01-24 16:11:39 (GMT)
committer Peter TB Brett <peter@peter-b.co.uk>2009-01-24 16:11:39 (GMT)
commit6a07d737a32a816f43e1f061409a10e616d7aa2a (patch) (side-by-side diff)
treeeb303ca8a2df3c49d2f68a16fafdaaf96019522b
parent246acd46e591e542ac3f00f9064905ae0311b0ec (diff)
Enable basic clipboard support.
Enable clipboard support using the GTK Clipboard API. gschem advertises 'application/x-geda-schematic' data, and transfers it in the gEDA on-disc file format. This works between gschem instances, but data does not remain in the clipboard after the advertising instance of gschem exits.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--gschem/include/gschem_struct.h1
-rw-r--r--gschem/include/prototype.h11
-rw-r--r--gschem/lib/system-gschemrc.in6
-rw-r--r--gschem/src/Makefile.am1
-rw-r--r--gschem/src/g_keys.c5
-rw-r--r--gschem/src/g_register.c5
-rw-r--r--gschem/src/gschem_toplevel.c1
-rw-r--r--gschem/src/i_callbacks.c91
-rw-r--r--gschem/src/x_clipboard.c133
9 files changed, 251 insertions, 3 deletions
diff --git a/gschem/include/gschem_struct.h b/gschem/include/gschem_struct.h
index ebe58b8..4ae55b7 100644
--- a/gschem/include/gschem_struct.h
+++ b/gschem/include/gschem_struct.h
@@ -120,6 +120,7 @@ struct st_gschem_toplevel {
int doing_pan; /* mouse pan status flag */
int buffer_number; /* current paste buffer in use */
void (*last_callback)(); /* Last i_call* cmd executed */
+ GList *clipboard_buffer; /* buffer for system clipboard integration */
/* ------------------ */
/* rc/user parameters */
diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index 4bd7594..ce0c0c0 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -94,6 +94,10 @@ SCM g_keys_edit_find(SCM rest);
SCM g_keys_edit_show_text(SCM rest);
SCM g_keys_edit_hide_text(SCM rest);
SCM g_keys_edit_autonumber_text(SCM rest);
+SCM g_keys_clipboard_copy(SCM rest);
+SCM g_keys_clipboard_cut(SCM rest);
+SCM g_keys_clipboard_paste(SCM rest);
+SCM g_keys_clipboard_paste_hotkey(SCM rest);
SCM g_keys_buffer_copy1(SCM rest);
SCM g_keys_buffer_copy2(SCM rest);
SCM g_keys_buffer_copy3(SCM rest);
@@ -378,6 +382,10 @@ void i_callback_page_close(gpointer data, guint callback_action, GtkWidget *widg
void i_callback_page_revert(gpointer data, guint callback_action, GtkWidget *widget);
void i_callback_page_discard(gpointer data, guint callback_action, GtkWidget *widget);
void i_callback_page_print(gpointer data, guint callback_action, GtkWidget *widget);
+void i_callback_clipboard_copy(gpointer data, guint callback_action, GtkWidget *widget);
+void i_callback_clipboard_cut(gpointer data, guint callback_action, GtkWidget *widget);
+void i_callback_clipboard_paste(gpointer data, guint callback_action, GtkWidget *widget);
+void i_callback_clipboard_paste_hotkey(gpointer data, guint callback_action, GtkWidget *widget);
void i_callback_buffer_copy1(gpointer data, guint callback_action, GtkWidget *widget);
void i_callback_buffer_copy2(gpointer data, guint callback_action, GtkWidget *widget);
void i_callback_buffer_copy3(gpointer data, guint callback_action, GtkWidget *widget);
@@ -733,6 +741,9 @@ void x_vscrollbar_set_ranges(GSCHEM_TOPLEVEL *w_current);
void x_vscrollbar_update(GSCHEM_TOPLEVEL *w_current);
void x_scrollbars_update(GSCHEM_TOPLEVEL *w_current);
void x_basic_warp_cursor(GtkWidget *widget, gint x, gint y);
+/* x_clipboard.c */
+gboolean x_clipboard_set (GSCHEM_TOPLEVEL *w_current, const GList *object_list);
+GList *x_clipboard_get (GSCHEM_TOPLEVEL *w_current);
/* x_color.c */
void x_color_init (void);
void x_color_free (void);
diff --git a/gschem/lib/system-gschemrc.in b/gschem/lib/system-gschemrc.in
index 357bafb..09fd26a 100644
--- a/gschem/lib/system-gschemrc.in
+++ b/gschem/lib/system-gschemrc.in
@@ -1368,9 +1368,9 @@
("Shift U" . edit-undo)
("Shift R" . edit-redo)
("Shift Z" . view-zoom-out-hotkey)
- ("Control x" . buffer-cut1)
- ("Control c" . buffer-copy1)
- ("Control v" . buffer-paste1-hotkey)
+ ("Control x" . clipboard-cut)
+ ("Control c" . clipboard-copy)
+ ("Control v" . clipboard-paste-hotkey)
("Control z" . edit-undo)
("Control y" . edit-redo)))
diff --git a/gschem/src/Makefile.am b/gschem/src/Makefile.am
index 0403cd7..6374bba 100644
--- a/gschem/src/Makefile.am
+++ b/gschem/src/Makefile.am
@@ -52,6 +52,7 @@ gschem_SOURCES = \
x_attribedit.c \
x_autonumber.c \
x_basic.c \
+ x_clipboard.c \
x_color.c \
x_compselect.c \
x_dialog.c \
diff --git a/gschem/src/g_keys.c b/gschem/src/g_keys.c
index 0a9d1fe..665e7ef 100644
--- a/gschem/src/g_keys.c
+++ b/gschem/src/g_keys.c
@@ -255,6 +255,11 @@ DEFINE_G_KEYS(edit_show_text)
DEFINE_G_KEYS(edit_hide_text)
DEFINE_G_KEYS(edit_autonumber_text)
+DEFINE_G_KEYS(clipboard_copy)
+DEFINE_G_KEYS(clipboard_cut)
+DEFINE_G_KEYS(clipboard_paste)
+DEFINE_G_KEYS(clipboard_paste_hotkey)
+
DEFINE_G_KEYS(buffer_copy1)
DEFINE_G_KEYS(buffer_copy2)
DEFINE_G_KEYS(buffer_copy3)
diff --git a/gschem/src/g_register.c b/gschem/src/g_register.c
index fb710ed..5173d30 100644
--- a/gschem/src/g_register.c
+++ b/gschem/src/g_register.c
@@ -200,6 +200,11 @@ static struct gsubr_t gschem_funcs[] = {
{ "edit-hide-text", 0, 0, 0, g_keys_edit_hide_text },
{ "edit-autonumber", 0, 0, 0, g_keys_edit_autonumber_text },
+ { "clipboard-copy", 0, 0, 0, g_keys_clipboard_copy },
+ { "clipboard-cut", 0, 0, 0, g_keys_clipboard_cut },
+ { "clipboard-paste", 0, 0, 0, g_keys_clipboard_paste },
+ { "clipboard-paste-hotkey", 0, 0, 0, g_keys_clipboard_paste_hotkey },
+
{ "buffer-copy1", 0, 0, 0, g_keys_buffer_copy1 },
{ "buffer-copy2", 0, 0, 0, g_keys_buffer_copy2 },
{ "buffer-copy3", 0, 0, 0, g_keys_buffer_copy3 },
diff --git a/gschem/src/gschem_toplevel.c b/gschem/src/gschem_toplevel.c
index caafcd1..c2dd999 100644
--- a/gschem/src/gschem_toplevel.c
+++ b/gschem/src/gschem_toplevel.c
@@ -137,6 +137,7 @@ GSCHEM_TOPLEVEL *gschem_toplevel_new ()
w_current->doing_pan = 0;
w_current->buffer_number = 0;
w_current->last_callback = NULL;
+ w_current->clipboard_buffer = NULL;
/* ------------------ */
/* rc/user parameters */
diff --git a/gschem/src/i_callbacks.c b/gschem/src/i_callbacks.c
index b50f6fd..20a7da1 100644
--- a/gschem/src/i_callbacks.c
+++ b/gschem/src/i_callbacks.c
@@ -1800,6 +1800,97 @@ DEFINE_I_CALLBACK(page_print)
s_page_print_all(w_current->toplevel);
}
+/*! \section clipboard-menu Clipboard Menu Callback Functions */
+/*! \brief Copy selection to clipboard.
+ * \par Function Description
+ * Copies the current selection to the clipboard, via buffer 0.
+ */
+DEFINE_I_CALLBACK(clipboard_copy)
+{
+ GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL*) data;
+
+ exit_if_null (w_current);
+ if (!o_select_selected (w_current)) return;
+
+ i_update_middle_button (w_current, i_callback_clipboard_copy,
+ _("Copy to clipboard"));
+
+ o_buffer_copy (w_current, 0);
+ x_clipboard_set (w_current, object_buffer[0]);
+}
+
+/*! \brief Cut selection to clipboard.
+ * \par Function Description
+ * Cut the current selection to the clipboard, via buffer 0.
+ */
+DEFINE_I_CALLBACK(clipboard_cut)
+{
+ GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL*) data;
+
+ exit_if_null (w_current);
+ if (!o_select_selected (w_current)) return;
+
+ i_update_middle_button (w_current, i_callback_clipboard_cut,
+ _("Cut to clipboard"));
+
+ o_buffer_cut (w_current, 0);
+ x_clipboard_set (w_current, object_buffer[0]);
+}
+
+/*! \brief Start pasting clipboard contents.
+ * \par Function Description
+ * Cut the current selection to the clipboard, via buffer 0.
+ */
+DEFINE_I_CALLBACK(clipboard_paste)
+{
+ GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) data;
+ TOPLEVEL *toplevel = w_current->toplevel;
+ GList *object_list = NULL;
+
+ exit_if_null(w_current);
+
+ i_update_middle_button (w_current, i_callback_buffer_paste1, _("Paste from clipboard"));
+
+ object_list = x_clipboard_get (w_current);
+
+ if (object_list != NULL) {
+ s_delete_object_glist (toplevel, object_buffer[0]);
+ object_buffer[0] = object_list;
+ o_redraw_cleanstates (w_current);
+ w_current->buffer_number = 0;
+ w_current->inside_action = 1;
+ i_set_state (w_current, STARTPASTE);
+ } else {
+ i_set_state_msg (w_current, SELECT, _("Empty buffer"));
+ }
+}
+
+/*! \brief Start pasting clipboard contents (hotkey version)
+ * \par Function Description
+ * It's not entirely clear what the difference is between this and
+ * i_callback_clipboard_paste()...
+ */
+DEFINE_I_CALLBACK(clipboard_paste_hotkey)
+{
+ GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) data;
+ TOPLEVEL *toplevel = w_current->toplevel;
+ GList *object_list = NULL;
+ gint wx, wy;
+
+ exit_if_null (w_current);
+
+ if (!x_event_get_pointer_position (w_current, TRUE, &wx, &wy))
+ return;
+
+ object_list = x_clipboard_get (w_current);
+
+ if (object_list == NULL) return;
+ s_delete_object_glist (toplevel, object_buffer[0]);
+ object_buffer[0] = object_list;
+
+ o_buffer_paste_start (w_current, wx, wy, 0);
+}
+
/*! \section buffer-menu Buffer Menu Callback Functions */
/*! \todo Finish function documentation!!!
* \brief
diff --git a/gschem/src/x_clipboard.c b/gschem/src/x_clipboard.c
new file mode 100644
index 0000000..27fd436
--- a/dev/null
+++ b/gschem/src/x_clipboard.c
@@ -0,0 +1,133 @@
+/* gEDA - GPL Electronic Design Automation
+ * gschem - gEDA Schematic Capture
+ * Copyright (C) 1998-2009 gEDA Contributors (see ChangeLog for details)
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "gschem.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+#define MIME_TYPE_SCHEMATIC "application/x-geda-schematic"
+#define CLIP_TYPE_SCHEMATIC 1
+
+static void
+clip_get (GtkClipboard *cb, GtkSelectionData *selection_data,
+ guint info, gpointer user_data_or_owner)
+{
+ GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) user_data_or_owner;
+ TOPLEVEL *toplevel = w_current->toplevel;
+ GdkAtom type = gdk_atom_intern (MIME_TYPE_SCHEMATIC, FALSE);
+ gchar *buf;
+ if (info != CLIP_TYPE_SCHEMATIC) return;
+ /* Convert the objects in the clipboard buffer to gEDA schematic
+ * format */
+ buf = o_save_buffer (toplevel, w_current->clipboard_buffer);
+ /* Set the selection appropriately */
+ gtk_selection_data_set (selection_data, type,
+ 8, /* 8-bit data (UTF-8) */
+ (guchar *) buf,
+ (gint) strlen(buf));
+ g_free (buf);
+}
+
+static void
+clip_clear (GtkClipboard *cb, gpointer user_data_or_owner)
+{
+ /* Do nothing for now */
+}
+
+/* \brief Set the contents of the system clipboard.
+ * \par Function Description
+ * Set the system clipboard to contain the gschem objects listed in \a
+ * object_list.
+ *
+ * \param [in,out] w_current The current GSCHEM_TOPLEVEL.
+ * \param [in] object_list The objects to put in the clipboard.
+ *
+ * \return TRUE if the clipboard is successfully set.
+ */
+gboolean
+x_clipboard_set (GSCHEM_TOPLEVEL *w_current, const GList *object_list)
+{
+ GtkClipboard *cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+ GtkTargetEntry target = { MIME_TYPE_SCHEMATIC, 0,
+ CLIP_TYPE_SCHEMATIC };
+ TOPLEVEL *toplevel = w_current->toplevel;
+ gboolean result;
+
+ /* Clear the clipboard buffer */
+ s_delete_object_glist(toplevel, w_current->clipboard_buffer);
+ w_current->clipboard_buffer = NULL;
+
+ /* Copy the objects to the clipboard buffer */
+ w_current->clipboard_buffer =
+ o_glist_copy_all (toplevel, object_list, w_current->clipboard_buffer,
+ SELECTION_FLAG);
+
+ /* Advertise that the data is available */
+ result = gtk_clipboard_set_with_data (cb, &target, 1,
+ clip_get, clip_clear, w_current);
+
+ /* Hint that the data can be stored to be accessed after the program
+ * has quit. */
+ gtk_clipboard_set_can_store (cb, NULL, 0);
+
+ return result;
+}
+
+/* \brief Get the contents of the system clipboard.
+ * \par Function Description
+ * If the system clipboard contains schematic data, retrieve it.
+ *
+ * \param [in,out] w_current The current GSCHEM_TOPLEVEL.
+ *
+ * \returns Any OBJECTs retrieved from the system clipboard, or NULL
+ * if none were available.
+ */
+GList *
+x_clipboard_get (GSCHEM_TOPLEVEL *w_current)
+{
+ GtkClipboard *cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+ TOPLEVEL *toplevel = w_current->toplevel;
+ GdkAtom type = gdk_atom_intern (MIME_TYPE_SCHEMATIC, FALSE);
+ GtkSelectionData *selection_data;
+ GList *object_list = NULL;
+ const guchar *buf;
+
+ /* Try to get the contents of the clipboard */
+ selection_data = gtk_clipboard_wait_for_contents (cb, type);
+ if (selection_data == NULL) return FALSE;
+
+ /* Convert the data buffer to OBJECTs */
+ buf = gtk_selection_data_get_data (selection_data);
+ object_list = o_read_buffer (toplevel, object_list,
+ (gchar *) buf, -1, "Clipboard");
+
+ gtk_selection_data_free (selection_data);
+ return object_list;
+}