gimp-test-clipboard.c 11.5 KB
Newer Older
1
/*
2
 * gimp-test-clipboard.c -- do clipboard things
3 4 5 6 7 8
 *
 * Copyright (C) 2005  Michael Natterer <mitch@gimp.org>
 *
 * Use this code for whatever you like.
 */

9 10 11 12
#include "config.h"

#include <errno.h>
#include <fcntl.h>
13
#include <stdlib.h>
14
#include <string.h>
15 16 17 18 19
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
20 21 22

#include <gtk/gtk.h>

23
#include "libgimpbase/gimpbase.h"
24

25

26 27 28 29 30 31 32 33 34 35
typedef struct _CopyData CopyData;

struct _CopyData
{
  const gchar *filename;
  gboolean     file_copied;
  GError      *error;
};


36
static void     test_clipboard_show_version    (void) G_GNUC_NORETURN;
37 38 39 40
static gboolean test_clipboard_parse_selection (const gchar       *option_name,
                                                const gchar       *value,
                                                gpointer           data,
                                                GError           **error);
41 42
static gboolean test_clipboard_list_targets    (GtkClipboard      *clipboard);
static gboolean test_clipboard_copy            (GtkClipboard      *clipboard,
43 44
                                                const gchar       *target,
                                                const gchar       *filename);
45 46 47 48
static gboolean test_clipboard_store           (GtkClipboard      *clipboard,
                                                const gchar       *target,
                                                const gchar       *filename);
static gboolean test_clipboard_paste           (GtkClipboard      *clipboard,
49 50 51 52 53 54 55 56 57 58 59 60
                                                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;
61
static gchar    *option_store_filename = NULL;
62 63 64 65 66 67 68
static gchar    *option_paste_filename = NULL;

static const GOptionEntry main_entries[] =
{
  {
    "selection-type", 's', 0,
    G_OPTION_ARG_CALLBACK, test_clipboard_parse_selection,
69
    "Selection type (primary|secondary|clipboard)", "<type>"
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
  },
  {
    "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>"
  },
86 87 88 89 90
  {
    "store", 'S', 0,
    G_OPTION_ARG_STRING, &option_store_filename,
    "Store <file> in the clipboard manager", "<file>"
  },
91 92 93
  {
    "paste", 'p', 0,
    G_OPTION_ARG_STRING, &option_paste_filename,
94
    "Paste clipoard into <file> ('-' pastes to STDOUT)", "<file>"
95
  },
96
  {
97
    "version", 'v', G_OPTION_FLAG_NO_ARG,
98 99 100
    G_OPTION_ARG_CALLBACK, test_clipboard_show_version,
    "Show version information and exit", NULL
  },
101 102
  { NULL }
};
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137


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 (),
138
                                             option_selection_type);
139 140 141 142

  if (! clipboard)
    g_error ("gtk_clipboard_get_for_display");

143
  if (option_list_targets)
144
    {
145 146 147
      if (! test_clipboard_list_targets (clipboard))
        return EXIT_FAILURE;

148 149 150
      return EXIT_SUCCESS;
    }

151 152 153
  if ((option_copy_filename  && option_paste_filename) ||
      (option_copy_filename  && option_store_filename) ||
      (option_paste_filename && option_store_filename))
154
    {
155
      g_printerr ("Can't perform two operations at the same time\n");
156 157 158
      return EXIT_FAILURE;
    }

159
  if (option_copy_filename)
160
    {
161
      if (! option_target)
162 163 164 165
        {
          g_printerr ("Usage: %s -t <target> -c <file>\n", argv[0]);
          return EXIT_FAILURE;
        }
166

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
      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;
183 184
    }

185
  if (option_paste_filename)
186
    {
187
      if (! option_target)
188 189 190 191
        {
          g_printerr ("Usage: %s -t <target> -p <file>\n", argv[0]);
          return EXIT_FAILURE;
        }
192

193 194 195
      if (! test_clipboard_paste (clipboard, option_target,
                                  option_paste_filename))
        return EXIT_FAILURE;
196 197 198 199 200
    }

  return EXIT_SUCCESS;
}

201 202 203
static void
test_clipboard_show_version (void)
{
204
  g_print ("gimp-test-clipboard (GIMP clipboard testbed) version %s\n",
205 206 207 208 209
           GIMP_VERSION);

  exit (EXIT_SUCCESS);
}

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
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;
}

228
static gboolean
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
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);
        }
    }
256 257

  return TRUE;
258 259
}

260
static gboolean
261
test_clipboard_copy (GtkClipboard *clipboard,
262
                     const gchar  *target,
263 264
                     const gchar  *filename)
{
265
  GtkTargetEntry entry;
266
  CopyData       data;
267

268 269 270
  entry.target = g_strdup (target);
  entry.flags  = 0;
  entry.info   = 1;
271

272 273 274 275
  data.filename    = filename;
  data.file_copied = FALSE;
  data.error       = NULL;

276
  if (! gtk_clipboard_set_with_data (clipboard, &entry, 1,
277 278
                                     test_clipboard_copy_callback,
                                     NULL,
279 280 281 282 283 284
                                     &data))
    {
      g_printerr ("%s: gtk_clipboard_set_with_data() failed\n",
                  g_get_prgname());
      return FALSE;
    }
285 286

  gtk_main ();
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305

  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;
306 307
}

308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
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
358
test_clipboard_paste (GtkClipboard *clipboard,
359 360
                      const gchar  *target,
                      const gchar  *filename)
361
{
362
  GtkSelectionData *sel_data;
363

364 365 366 367
  sel_data = gtk_clipboard_wait_for_contents (clipboard,
                                              gdk_atom_intern (target,
                                                               FALSE));
  if (sel_data)
368
    {
369 370 371
      const guchar *data;
      gint          length;
      gint          fd;
372

373 374 375
      if (! strcmp (filename, "-"))
        fd = 1;
      else
376
        fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
377 378

      if (fd < 0)
379 380 381 382 383
        {
          g_printerr ("%s: open() filed: %s",
                      g_get_prgname (), g_strerror (errno));
          return FALSE;
        }
384

385 386 387 388
      data   = gtk_selection_data_get_data (sel_data);
      length = gtk_selection_data_get_length (sel_data);

      if (write (fd, data, length) < length)
389 390 391 392 393 394
        {
          close (fd);
          g_printerr ("%s: write() failed: %s",
                      g_get_prgname (), g_strerror (errno));
          return FALSE;
        }
395 396

      if (close (fd) < 0)
397 398 399 400 401
        {
          g_printerr ("%s: close() failed: %s",
                      g_get_prgname (), g_strerror (errno));
          return FALSE;
        }
402

403
      gtk_selection_data_free (sel_data);
404
    }
405 406

  return TRUE;
407 408
}

409 410 411 412 413 414
static void
test_clipboard_copy_callback (GtkClipboard     *clipboard,
                              GtkSelectionData *selection,
                              guint             info,
                              gpointer          data)
{
415 416 417
  CopyData *copy_data = data;
  gchar    *buf;
  gsize     buf_size;
418

419 420
  if (! g_file_get_contents (copy_data->filename, &buf, &buf_size,
                             &copy_data->error))
421 422 423 424 425 426
    {
      if (! option_store_filename)
        gtk_main_quit ();

      return;
    }
427

428 429
  gtk_selection_data_set (selection,
                          gtk_selection_data_get_target (selection),
430 431 432 433
                          8, (guchar *) buf, buf_size);

  g_free (buf);

434
  copy_data->file_copied = TRUE;
435 436 437

  g_print ("%s: data transfer in progress, hit <ctrl>+c when pasted...",
           G_STRFUNC);
438
}