444 lines
12 KiB
C
444 lines
12 KiB
C
/*
|
|
* pika-test-clipboard.c -- do clipboard things
|
|
*
|
|
* Copyright (C) 2005 Michael Natterer <mitch@gimp.org>
|
|
*
|
|
* Use this code for whatever you like.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <glib/gstdio.h>
|
|
#ifndef _O_BINARY
|
|
#define _O_BINARY 0
|
|
#endif
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libpikabase/pikabase.h"
|
|
|
|
|
|
typedef struct _CopyData CopyData;
|
|
|
|
struct _CopyData
|
|
{
|
|
const gchar *filename;
|
|
gboolean file_copied;
|
|
GError *error;
|
|
};
|
|
|
|
|
|
static void test_clipboard_show_version (void) G_GNUC_NORETURN;
|
|
static gboolean test_clipboard_parse_selection (const gchar *option_name,
|
|
const gchar *value,
|
|
gpointer data,
|
|
GError **error);
|
|
static gboolean test_clipboard_list_targets (GtkClipboard *clipboard);
|
|
static gboolean test_clipboard_copy (GtkClipboard *clipboard,
|
|
const gchar *target,
|
|
const gchar *filename);
|
|
static gboolean test_clipboard_store (GtkClipboard *clipboard,
|
|
const gchar *target,
|
|
const gchar *filename);
|
|
static gboolean test_clipboard_paste (GtkClipboard *clipboard,
|
|
const gchar *target,
|
|
const gchar *filename);
|
|
static void test_clipboard_copy_callback (GtkClipboard *clipboard,
|
|
GtkSelectionData *selection,
|
|
guint info,
|
|
gpointer data);
|
|
|
|
|
|
static GdkAtom option_selection_type = GDK_SELECTION_CLIPBOARD;
|
|
static gboolean option_list_targets = FALSE;
|
|
static gchar *option_target = NULL;
|
|
static gchar *option_copy_filename = NULL;
|
|
static gchar *option_store_filename = NULL;
|
|
static gchar *option_paste_filename = NULL;
|
|
|
|
static const GOptionEntry main_entries[] =
|
|
{
|
|
{
|
|
"selection-type", 's', 0,
|
|
G_OPTION_ARG_CALLBACK, test_clipboard_parse_selection,
|
|
"Selection type (primary|secondary|clipboard)", "<type>"
|
|
},
|
|
{
|
|
"list-targets", 'l', 0,
|
|
G_OPTION_ARG_NONE, &option_list_targets,
|
|
"List the targets offered by the clipboard", NULL
|
|
},
|
|
{
|
|
"target", 't', 0,
|
|
G_OPTION_ARG_STRING, &option_target,
|
|
"The target format to copy or paste", "<target>"
|
|
},
|
|
{
|
|
"copy", 'c', 0,
|
|
G_OPTION_ARG_STRING, &option_copy_filename,
|
|
"Copy <file> to clipboard", "<file>"
|
|
},
|
|
{
|
|
"store", 'S', 0,
|
|
G_OPTION_ARG_STRING, &option_store_filename,
|
|
"Store <file> in the clipboard manager", "<file>"
|
|
},
|
|
{
|
|
"paste", 'p', 0,
|
|
G_OPTION_ARG_STRING, &option_paste_filename,
|
|
"Paste clipboard into <file> ('-' pastes to STDOUT)", "<file>"
|
|
},
|
|
{
|
|
"version", 'v', G_OPTION_FLAG_NO_ARG,
|
|
G_OPTION_ARG_CALLBACK, test_clipboard_show_version,
|
|
"Show version information and exit", NULL
|
|
},
|
|
{ NULL }
|
|
};
|
|
|
|
|
|
gint
|
|
main (gint argc,
|
|
gchar *argv[])
|
|
{
|
|
GOptionContext *context;
|
|
GtkClipboard *clipboard;
|
|
GError *error = NULL;
|
|
|
|
context = g_option_context_new (NULL);
|
|
g_option_context_add_main_entries (context, main_entries, NULL);
|
|
g_option_context_add_group (context, gtk_get_option_group (TRUE));
|
|
|
|
if (! g_option_context_parse (context, &argc, &argv, &error))
|
|
{
|
|
if (error)
|
|
{
|
|
g_printerr ("%s\n", error->message);
|
|
g_error_free (error);
|
|
}
|
|
else
|
|
{
|
|
g_print ("%s\n",
|
|
"Could not initialize the graphical user interface.\n"
|
|
"Make sure a proper setup for your display environment "
|
|
"exists.");
|
|
}
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
gtk_init (&argc, &argv);
|
|
|
|
clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
|
|
option_selection_type);
|
|
|
|
if (! clipboard)
|
|
g_error ("gtk_clipboard_get_for_display");
|
|
|
|
if (option_list_targets)
|
|
{
|
|
if (! test_clipboard_list_targets (clipboard))
|
|
return EXIT_FAILURE;
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
if ((option_copy_filename && option_paste_filename) ||
|
|
(option_copy_filename && option_store_filename) ||
|
|
(option_paste_filename && option_store_filename))
|
|
{
|
|
g_printerr ("Can't perform two operations at the same time\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (option_copy_filename)
|
|
{
|
|
if (! option_target)
|
|
{
|
|
g_printerr ("Usage: %s -t <target> -c <file>\n", argv[0]);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (! test_clipboard_copy (clipboard, option_target,
|
|
option_copy_filename))
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (option_store_filename)
|
|
{
|
|
if (! option_target)
|
|
{
|
|
g_printerr ("Usage: %s -t <target> -S <file>\n", argv[0]);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (! test_clipboard_store (clipboard, option_target,
|
|
option_store_filename))
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (option_paste_filename)
|
|
{
|
|
if (! option_target)
|
|
{
|
|
g_printerr ("Usage: %s -t <target> -p <file>\n", argv[0]);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (! test_clipboard_paste (clipboard, option_target,
|
|
option_paste_filename))
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
static void
|
|
test_clipboard_show_version (void)
|
|
{
|
|
g_print ("pika-test-clipboard (PIKA clipboard testbed) version %s\n",
|
|
PIKA_VERSION);
|
|
|
|
exit (EXIT_SUCCESS);
|
|
}
|
|
|
|
static gboolean
|
|
test_clipboard_parse_selection (const gchar *option_name,
|
|
const gchar *value,
|
|
gpointer data,
|
|
GError **error)
|
|
{
|
|
if (! strcmp (value, "primary"))
|
|
option_selection_type = GDK_SELECTION_PRIMARY;
|
|
else if (! strcmp (value, "secondary"))
|
|
option_selection_type = GDK_SELECTION_SECONDARY;
|
|
else if (! strcmp (value, "clipboard"))
|
|
option_selection_type = GDK_SELECTION_CLIPBOARD;
|
|
else
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
test_clipboard_list_targets (GtkClipboard *clipboard)
|
|
{
|
|
GtkSelectionData *data;
|
|
|
|
data = gtk_clipboard_wait_for_contents (clipboard,
|
|
gdk_atom_intern ("TARGETS",
|
|
FALSE));
|
|
if (data)
|
|
{
|
|
GdkAtom *targets;
|
|
gint n_targets;
|
|
gboolean success;
|
|
|
|
success = gtk_selection_data_get_targets (data, &targets, &n_targets);
|
|
|
|
gtk_selection_data_free (data);
|
|
|
|
if (success)
|
|
{
|
|
gint i;
|
|
|
|
for (i = 0; i < n_targets; i++)
|
|
g_print ("%s\n", gdk_atom_name (targets[i]));
|
|
|
|
g_free (targets);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
test_clipboard_copy (GtkClipboard *clipboard,
|
|
const gchar *target,
|
|
const gchar *filename)
|
|
{
|
|
GtkTargetEntry entry;
|
|
CopyData data;
|
|
|
|
entry.target = g_strdup (target);
|
|
entry.flags = 0;
|
|
entry.info = 1;
|
|
|
|
data.filename = filename;
|
|
data.file_copied = FALSE;
|
|
data.error = NULL;
|
|
|
|
if (! gtk_clipboard_set_with_data (clipboard, &entry, 1,
|
|
test_clipboard_copy_callback,
|
|
NULL,
|
|
&data))
|
|
{
|
|
g_printerr ("%s: gtk_clipboard_set_with_data() failed\n",
|
|
g_get_prgname());
|
|
return FALSE;
|
|
}
|
|
|
|
gtk_main ();
|
|
|
|
if (! data.file_copied)
|
|
{
|
|
if (data.error)
|
|
{
|
|
g_printerr ("%s: copying failed: %s\n",
|
|
g_get_prgname (), data.error->message);
|
|
g_error_free (data.error);
|
|
}
|
|
else
|
|
{
|
|
g_printerr ("%s: copying failed\n",
|
|
g_get_prgname ());
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
test_clipboard_store (GtkClipboard *clipboard,
|
|
const gchar *target,
|
|
const gchar *filename)
|
|
{
|
|
GtkTargetEntry entry;
|
|
CopyData data;
|
|
|
|
entry.target = g_strdup (target);
|
|
entry.flags = 0;
|
|
entry.info = 1;
|
|
|
|
data.filename = filename;
|
|
data.file_copied = FALSE;
|
|
data.error = NULL;
|
|
|
|
if (! gtk_clipboard_set_with_data (clipboard, &entry, 1,
|
|
test_clipboard_copy_callback,
|
|
NULL,
|
|
&data))
|
|
{
|
|
g_printerr ("%s: gtk_clipboard_set_with_data() failed\n",
|
|
g_get_prgname ());
|
|
return FALSE;
|
|
}
|
|
|
|
gtk_clipboard_set_can_store (clipboard, &entry, 1);
|
|
gtk_clipboard_store (clipboard);
|
|
|
|
if (! data.file_copied)
|
|
{
|
|
if (data.error)
|
|
{
|
|
g_printerr ("%s: storing failed: %s\n",
|
|
g_get_prgname (), data.error->message);
|
|
g_error_free (data.error);
|
|
}
|
|
else
|
|
{
|
|
g_printerr ("%s: could not contact clipboard manager\n",
|
|
g_get_prgname ());
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
test_clipboard_paste (GtkClipboard *clipboard,
|
|
const gchar *target,
|
|
const gchar *filename)
|
|
{
|
|
GtkSelectionData *sel_data;
|
|
|
|
sel_data = gtk_clipboard_wait_for_contents (clipboard,
|
|
gdk_atom_intern (target,
|
|
FALSE));
|
|
if (sel_data)
|
|
{
|
|
const guchar *data;
|
|
gint length;
|
|
gint fd;
|
|
|
|
if (! strcmp (filename, "-"))
|
|
fd = 1;
|
|
else
|
|
fd = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | _O_BINARY, 0666);
|
|
|
|
if (fd < 0)
|
|
{
|
|
g_printerr ("%s: open() filed: %s",
|
|
g_get_prgname (), g_strerror (errno));
|
|
return FALSE;
|
|
}
|
|
|
|
data = gtk_selection_data_get_data (sel_data);
|
|
length = gtk_selection_data_get_length (sel_data);
|
|
|
|
if (write (fd, data, length) < length)
|
|
{
|
|
close (fd);
|
|
g_printerr ("%s: write() failed: %s",
|
|
g_get_prgname (), g_strerror (errno));
|
|
return FALSE;
|
|
}
|
|
|
|
if (close (fd) < 0)
|
|
{
|
|
g_printerr ("%s: close() failed: %s",
|
|
g_get_prgname (), g_strerror (errno));
|
|
return FALSE;
|
|
}
|
|
|
|
gtk_selection_data_free (sel_data);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
test_clipboard_copy_callback (GtkClipboard *clipboard,
|
|
GtkSelectionData *selection,
|
|
guint info,
|
|
gpointer data)
|
|
{
|
|
CopyData *copy_data = data;
|
|
gchar *buf;
|
|
gsize buf_size;
|
|
|
|
if (! g_file_get_contents (copy_data->filename, &buf, &buf_size,
|
|
©_data->error))
|
|
{
|
|
if (! option_store_filename)
|
|
gtk_main_quit ();
|
|
|
|
return;
|
|
}
|
|
|
|
gtk_selection_data_set (selection,
|
|
gtk_selection_data_get_target (selection),
|
|
8, (guchar *) buf, buf_size);
|
|
|
|
g_free (buf);
|
|
|
|
copy_data->file_copied = TRUE;
|
|
|
|
g_print ("%s: data transfer in progress, hit <ctrl>+c when pasted...",
|
|
G_STRFUNC);
|
|
}
|