From c12e485e47f5ac99f0ddd7f7e90b9ab28b077c3d Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 11 Nov 2009 23:52:08 -0500 Subject: Simplify clipboard handling in addressbook. --- e-util/e-selection.c | 536 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 536 insertions(+) create mode 100644 e-util/e-selection.c (limited to 'e-util/e-selection.c') diff --git a/e-util/e-selection.c b/e-util/e-selection.c new file mode 100644 index 0000000000..8d2efff764 --- /dev/null +++ b/e-util/e-selection.c @@ -0,0 +1,536 @@ +/* + * e-selection.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-selection.h" + +#include + +typedef struct _RequestTextInfo RequestTextInfo; +typedef struct _WaitForDataResults WaitForDataResults; + +struct _RequestTextInfo { + GtkClipboardTextReceivedFunc callback; + gpointer user_data; +}; + +struct _WaitForDataResults { + GMainLoop *loop; + gpointer data; +}; + +enum { + ATOM_CALENDAR, + ATOM_X_VCALENDAR, + NUM_CALENDAR_ATOMS +}; + +enum { + ATOM_DIRECTORY, + ATOM_X_VCARD, + NUM_DIRECTORY_ATOMS +}; + +static GdkAtom calendar_atoms[NUM_CALENDAR_ATOMS]; +static GdkAtom directory_atoms[NUM_DIRECTORY_ATOMS]; + +static void +init_atoms (void) +{ + static gboolean initialized = FALSE; + + if (initialized) + return; + + /* Calendar Atoms */ + + calendar_atoms[ATOM_CALENDAR] = + gdk_atom_intern_static_string ("text/calendar"); + + calendar_atoms[ATOM_X_VCALENDAR] = + gdk_atom_intern_static_string ("text/x-vcalendar"); + + /* Directory Atoms */ + + directory_atoms[ATOM_DIRECTORY] = + gdk_atom_intern_static_string ("text/directory"); + + directory_atoms[ATOM_X_VCARD] = + gdk_atom_intern_static_string ("text/x-vcard"); + + initialized = TRUE; +} + +static void +clipboard_wait_for_text_cb (GtkClipboard *clipboard, + const gchar *source, + WaitForDataResults *results) +{ + results->data = g_strdup (source); + g_main_loop_quit (results->loop); +} + +void +e_target_list_add_calendar_targets (GtkTargetList *list, + guint info) +{ + gint ii; + + g_return_if_fail (list != NULL); + + init_atoms (); + + for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) + gtk_target_list_add (list, calendar_atoms[ii], 0, info); +} + +void +e_target_list_add_directory_targets (GtkTargetList *list, + guint info) +{ + gint ii; + + g_return_if_fail (list != NULL); + + init_atoms (); + + for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++) + gtk_target_list_add (list, directory_atoms[ii], 0, info); +} + +gboolean +e_selection_data_set_calendar (GtkSelectionData *selection_data, + const gchar *source, + gint length) +{ + GdkAtom atom; + gint ii; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (length < 0) + length = strlen (source); + + init_atoms (); + + atom = gtk_selection_data_get_target (selection_data); + + /* All calendar atoms are treated the same. */ + for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) { + if (atom == calendar_atoms[ii]) { + gtk_selection_data_set ( + selection_data, atom, 8, + (guchar *) source, length); + return TRUE; + } + } + + return FALSE; +} + +gboolean +e_selection_data_set_directory (GtkSelectionData *selection_data, + const gchar *source, + gint length) +{ + GdkAtom atom; + gint ii; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (length < 0) + length = strlen (source); + + init_atoms (); + + atom = gtk_selection_data_get_target (selection_data); + + /* All directory atoms are treated the same. */ + for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++) { + if (atom == directory_atoms[ii]) { + gtk_selection_data_set ( + selection_data, atom, 8, + (guchar *) source, length); + return TRUE; + } + } + + return FALSE; +} + +gchar * +e_selection_data_get_calendar (GtkSelectionData *selection_data) +{ + GdkAtom data_type; + const guchar *data = NULL; + gint ii; + + /* XXX May need to do encoding and line ending conversions + * here. Not worrying about it for now. */ + + g_return_val_if_fail (selection_data != NULL, NULL); + + data = gtk_selection_data_get_data (selection_data); + data_type = gtk_selection_data_get_data_type (selection_data); + + /* All calendar atoms are treated the same. */ + for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) + if (data_type == calendar_atoms[ii]) + return g_strdup ((gchar *) data); + + return NULL; +} + +gchar * +e_selection_data_get_directory (GtkSelectionData *selection_data) +{ + GdkAtom data_type; + const guchar *data = NULL; + gint ii; + + /* XXX May need to do encoding and line ending conversions + * here. Not worrying about it for now. */ + + g_return_val_if_fail (selection_data != NULL, NULL); + + data = gtk_selection_data_get_data (selection_data); + data_type = gtk_selection_data_get_data_type (selection_data); + + /* All directory atoms are treated the same. */ + for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++) + if (data_type == directory_atoms[ii]) + return g_strdup ((gchar *) data); + + return NULL; +} + +gboolean +e_selection_data_targets_include_calendar (GtkSelectionData *selection_data) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) { + result = e_targets_include_calendar (targets, n_targets); + g_free (targets); + } + + return result; +} + +gboolean +e_selection_data_targets_include_directory (GtkSelectionData *selection_data) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + g_return_val_if_fail (selection_data != NULL, FALSE); + + if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) { + result = e_targets_include_directory (targets, n_targets); + g_free (targets); + } + + return result; +} + +gboolean +e_targets_include_calendar (GdkAtom *targets, + gint n_targets) +{ + gint ii, jj; + + g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); + + init_atoms (); + + for (ii = 0; ii < n_targets; ii++) + for (jj = 0; jj < NUM_CALENDAR_ATOMS; jj++) + if (targets[ii] == calendar_atoms[jj]) + return TRUE; + + return FALSE; +} + +gboolean +e_targets_include_directory (GdkAtom *targets, + gint n_targets) +{ + gint ii, jj; + + g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE); + + init_atoms (); + + for (ii = 0; ii < n_targets; ii++) + for (jj = 0; jj < NUM_DIRECTORY_ATOMS; jj++) + if (targets[ii] == directory_atoms[jj]) + return TRUE; + + return FALSE; +} + +static void +clipboard_get_calendar (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint info, + gchar *source) +{ + e_selection_data_set_calendar (selection_data, source, -1); +} + +static void +clipboard_clear_calendar (GtkClipboard *clipboard, + gchar *source) +{ + g_free (source); +} + +void +e_clipboard_set_calendar (GtkClipboard *clipboard, + const gchar *source, + gint length) +{ + GtkTargetList *list; + GtkTargetEntry *targets; + gint n_targets; + + g_return_if_fail (clipboard != NULL); + g_return_if_fail (source != NULL); + + list = gtk_target_list_new (NULL, 0); + e_target_list_add_calendar_targets (list, 0); + + targets = gtk_target_table_new_from_list (list, &n_targets); + + if (length < 0) + length = strlen (source); + + gtk_clipboard_set_with_data ( + clipboard, targets, n_targets, + (GtkClipboardGetFunc) clipboard_get_calendar, + (GtkClipboardClearFunc) clipboard_clear_calendar, + g_strndup (source, length)); + + gtk_clipboard_set_can_store (clipboard, NULL, 0); + + gtk_target_table_free (targets, n_targets); + gtk_target_list_unref (list); +} + +static void +clipboard_get_directory (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint info, + gchar *source) +{ + e_selection_data_set_directory (selection_data, source, -1); +} + +static void +clipboard_clear_directory (GtkClipboard *clipboard, + gchar *source) +{ + g_free (source); +} + +void +e_clipboard_set_directory (GtkClipboard *clipboard, + const gchar *source, + gint length) +{ + GtkTargetList *list; + GtkTargetEntry *targets; + gint n_targets; + + g_return_if_fail (clipboard != NULL); + g_return_if_fail (source != NULL); + + list = gtk_target_list_new (NULL, 0); + e_target_list_add_directory_targets (list, 0); + + targets = gtk_target_table_new_from_list (list, &n_targets); + + if (length < 0) + length = strlen (source); + + gtk_clipboard_set_with_data ( + clipboard, targets, n_targets, + (GtkClipboardGetFunc) clipboard_get_directory, + (GtkClipboardClearFunc) clipboard_clear_directory, + g_strndup (source, length)); + + gtk_clipboard_set_can_store (clipboard, NULL, 0); + + gtk_target_table_free (targets, n_targets); + gtk_target_list_unref (list); +} + +static void +clipboard_request_calendar_cb (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + RequestTextInfo *info) +{ + gchar *source; + + source = e_selection_data_get_calendar (selection_data); + info->callback (clipboard, source, info->user_data); + g_free (source); + + g_slice_free (RequestTextInfo, info); +} + +void +e_clipboard_request_calendar (GtkClipboard *clipboard, + GtkClipboardTextReceivedFunc callback, + gpointer user_data) +{ + RequestTextInfo *info; + + g_return_if_fail (clipboard != NULL); + g_return_if_fail (callback != NULL); + + info = g_slice_new (RequestTextInfo); + info->callback = callback; + info->user_data = user_data; + + gtk_clipboard_request_contents ( + clipboard, calendar_atoms[ATOM_CALENDAR], + (GtkClipboardReceivedFunc) + clipboard_request_calendar_cb, info); +} + +static void +clipboard_request_directory_cb (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + RequestTextInfo *info) +{ + gchar *source; + + source = e_selection_data_get_directory (selection_data); + info->callback (clipboard, source, info->user_data); + g_free (source); + + g_slice_free (RequestTextInfo, info); +} + +void +e_clipboard_request_directory (GtkClipboard *clipboard, + GtkClipboardTextReceivedFunc callback, + gpointer user_data) +{ + RequestTextInfo *info; + + g_return_if_fail (clipboard != NULL); + g_return_if_fail (callback != NULL); + + info = g_slice_new (RequestTextInfo); + info->callback = callback; + info->user_data = user_data; + + gtk_clipboard_request_contents ( + clipboard, directory_atoms[ATOM_DIRECTORY], + (GtkClipboardReceivedFunc) + clipboard_request_directory_cb, info); +} + +gchar * +e_clipboard_wait_for_calendar (GtkClipboard *clipboard) +{ + WaitForDataResults results; + + g_return_val_if_fail (clipboard != NULL, NULL); + + results.data = NULL; + results.loop = g_main_loop_new (NULL, TRUE); + + e_clipboard_request_calendar ( + clipboard, (GtkClipboardTextReceivedFunc) + clipboard_wait_for_text_cb, &results); + + if (g_main_loop_is_running (results.loop)) { + GDK_THREADS_LEAVE (); + g_main_loop_run (results.loop); + GDK_THREADS_ENTER (); + } + + g_main_loop_unref (results.loop); + + return results.data; +} + +gchar * +e_clipboard_wait_for_directory (GtkClipboard *clipboard) +{ + WaitForDataResults results; + + g_return_val_if_fail (clipboard != NULL, NULL); + + results.data = NULL; + results.loop = g_main_loop_new (NULL, TRUE); + + e_clipboard_request_directory ( + clipboard, (GtkClipboardTextReceivedFunc) + clipboard_wait_for_text_cb, &results); + + if (g_main_loop_is_running (results.loop)) { + GDK_THREADS_LEAVE (); + g_main_loop_run (results.loop); + GDK_THREADS_ENTER (); + } + + g_main_loop_unref (results.loop); + + return results.data; +} + +gboolean +e_clipboard_wait_is_calendar_available (GtkClipboard *clipboard) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + if (gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets)) { + result = e_targets_include_calendar (targets, n_targets); + g_free (targets); + } + + return result; +} + +gboolean +e_clipboard_wait_is_directory_available (GtkClipboard *clipboard) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + if (gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets)) { + result = e_targets_include_directory (targets, n_targets); + g_free (targets); + } + + return result; +} -- cgit v1.2.3