Updated Spanish translation
[evolution.git] / e-util / e-selection.c
blobc789c732a0b91294c899a4840a69bab1418acb92
1 /*
2 * e-selection.c
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 /**
22 * SECTION: e-selection
23 * @short_description: selection and clipboard utilities
24 * @include: e-util/e-util.h
25 **/
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
31 #include "e-selection.h"
33 #include <string.h>
35 typedef struct _RequestTextInfo RequestTextInfo;
36 typedef struct _WaitForDataResults WaitForDataResults;
38 struct _RequestTextInfo {
39 GtkClipboardTextReceivedFunc callback;
40 gpointer user_data;
43 struct _WaitForDataResults {
44 GMainLoop *loop;
45 gpointer data;
48 enum {
49 ATOM_CALENDAR,
50 ATOM_X_VCALENDAR,
51 NUM_CALENDAR_ATOMS
54 enum {
55 ATOM_DIRECTORY,
56 ATOM_X_VCARD,
57 NUM_DIRECTORY_ATOMS
60 enum {
61 ATOM_HTML,
62 NUM_HTML_ATOMS
65 static GdkAtom calendar_atoms[NUM_CALENDAR_ATOMS];
66 static GdkAtom directory_atoms[NUM_DIRECTORY_ATOMS];
67 static GdkAtom html_atoms[NUM_HTML_ATOMS];
69 static void
70 init_atoms (void)
72 static gboolean initialized = FALSE;
74 if (initialized)
75 return;
77 /* Calendar Atoms */
79 calendar_atoms[ATOM_CALENDAR] =
80 gdk_atom_intern_static_string ("text/calendar");
82 calendar_atoms[ATOM_X_VCALENDAR] =
83 gdk_atom_intern_static_string ("text/x-vcalendar");
85 /* Directory Atoms */
87 directory_atoms[ATOM_DIRECTORY] =
88 gdk_atom_intern_static_string ("text/directory");
90 directory_atoms[ATOM_X_VCARD] =
91 gdk_atom_intern_static_string ("text/x-vcard");
93 /* HTML Atoms */
95 html_atoms[ATOM_HTML] =
96 gdk_atom_intern_static_string ("text/html");
98 initialized = TRUE;
101 static void
102 clipboard_wait_for_text_cb (GtkClipboard *clipboard,
103 const gchar *source,
104 WaitForDataResults *results)
106 results->data = g_strdup (source);
107 g_main_loop_quit (results->loop);
110 void
111 e_target_list_add_calendar_targets (GtkTargetList *list,
112 guint info)
114 gint ii;
116 g_return_if_fail (list != NULL);
118 init_atoms ();
120 for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++)
121 gtk_target_list_add (list, calendar_atoms[ii], 0, info);
124 void
125 e_target_list_add_directory_targets (GtkTargetList *list,
126 guint info)
128 gint ii;
130 g_return_if_fail (list != NULL);
132 init_atoms ();
134 for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++)
135 gtk_target_list_add (list, directory_atoms[ii], 0, info);
138 void
139 e_target_list_add_html_targets (GtkTargetList *list,
140 guint info)
142 gint ii;
144 g_return_if_fail (list != NULL);
146 init_atoms ();
148 for (ii = 0; ii < NUM_HTML_ATOMS; ii++)
149 gtk_target_list_add (list, html_atoms[ii], 0, info);
152 gboolean
153 e_selection_data_set_calendar (GtkSelectionData *selection_data,
154 const gchar *source,
155 gint length)
157 GdkAtom atom;
158 gint ii;
160 g_return_val_if_fail (selection_data != NULL, FALSE);
161 g_return_val_if_fail (source != NULL, FALSE);
163 if (length < 0)
164 length = strlen (source);
166 init_atoms ();
168 atom = gtk_selection_data_get_target (selection_data);
170 /* All calendar atoms are treated the same. */
171 for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++) {
172 if (atom == calendar_atoms[ii]) {
173 gtk_selection_data_set (
174 selection_data, atom, 8,
175 (guchar *) source, length);
176 return TRUE;
180 return FALSE;
183 gboolean
184 e_selection_data_set_directory (GtkSelectionData *selection_data,
185 const gchar *source,
186 gint length)
188 GdkAtom atom;
189 gint ii;
191 g_return_val_if_fail (selection_data != NULL, FALSE);
192 g_return_val_if_fail (source != NULL, FALSE);
194 if (length < 0)
195 length = strlen (source);
197 init_atoms ();
199 atom = gtk_selection_data_get_target (selection_data);
201 /* All directory atoms are treated the same. */
202 for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++) {
203 if (atom == directory_atoms[ii]) {
204 gtk_selection_data_set (
205 selection_data, atom, 8,
206 (guchar *) source, length);
207 return TRUE;
211 return FALSE;
214 gboolean
215 e_selection_data_set_html (GtkSelectionData *selection_data,
216 const gchar *source,
217 gint length)
219 GdkAtom atom;
220 gint ii;
222 g_return_val_if_fail (selection_data != NULL, FALSE);
223 g_return_val_if_fail (source != NULL, FALSE);
225 if (length < 0)
226 length = strlen (source);
228 init_atoms ();
230 atom = gtk_selection_data_get_target (selection_data);
232 /* All HTML atoms are treated the same. */
233 for (ii = 0; ii < NUM_HTML_ATOMS; ii++) {
234 if (atom == html_atoms[ii]) {
235 gtk_selection_data_set (
236 selection_data, atom, 8,
237 (guchar *) source, length);
238 return TRUE;
242 return FALSE;
245 gchar *
246 e_selection_data_get_calendar (GtkSelectionData *selection_data)
248 GdkAtom data_type;
249 const guchar *data = NULL;
250 gint ii;
252 /* XXX May need to do encoding and line ending conversions
253 * here. Not worrying about it for now. */
255 g_return_val_if_fail (selection_data != NULL, NULL);
257 data = gtk_selection_data_get_data (selection_data);
258 data_type = gtk_selection_data_get_data_type (selection_data);
260 /* All calendar atoms are treated the same. */
261 for (ii = 0; ii < NUM_CALENDAR_ATOMS; ii++)
262 if (data_type == calendar_atoms[ii])
263 return g_strdup ((gchar *) data);
265 return NULL;
268 gchar *
269 e_selection_data_get_directory (GtkSelectionData *selection_data)
271 GdkAtom data_type;
272 const guchar *data = NULL;
273 gint ii;
275 /* XXX May need to do encoding and line ending conversions
276 * here. Not worrying about it for now. */
278 g_return_val_if_fail (selection_data != NULL, NULL);
280 data = gtk_selection_data_get_data (selection_data);
281 data_type = gtk_selection_data_get_data_type (selection_data);
283 /* All directory atoms are treated the same. */
284 for (ii = 0; ii < NUM_DIRECTORY_ATOMS; ii++)
285 if (data_type == directory_atoms[ii])
286 return g_strdup ((gchar *) data);
288 return NULL;
291 gchar *
292 e_selection_data_get_html (GtkSelectionData *selection_data)
294 GdkAtom data_type;
295 const guchar *data = NULL;
296 gchar *utf8_text;
297 gint length;
298 gint ii;
299 GError *error = NULL;
301 /* XXX May need to do encoding conversions here.
302 * Not worrying about it for now. */
304 g_return_val_if_fail (selection_data != NULL, NULL);
306 data = gtk_selection_data_get_data (selection_data);
307 length = gtk_selection_data_get_length (selection_data);
308 data_type = gtk_selection_data_get_data_type (selection_data);
310 g_return_val_if_fail (data != NULL, NULL);
312 /* First validate the data. Assume it's UTF-8 or UTF-16. */
313 if (g_utf8_validate ((const gchar *) data, length - 1, NULL))
314 utf8_text = g_strdup ((const gchar *) data);
315 else
316 utf8_text = g_convert (
317 (const gchar *) data, length,
318 "UTF-8", "UTF-16", NULL, NULL, &error);
320 if (error != NULL) {
321 g_warning ("%s", error->message);
322 g_error_free (error);
325 /* All HTML atoms are treated the same. */
326 for (ii = 0; ii < NUM_HTML_ATOMS; ii++)
327 if (data_type == html_atoms[ii])
328 return utf8_text;
330 g_free (utf8_text);
332 return NULL;
335 gboolean
336 e_selection_data_targets_include_calendar (GtkSelectionData *selection_data)
338 GdkAtom *targets;
339 gint n_targets;
340 gboolean result = FALSE;
342 g_return_val_if_fail (selection_data != NULL, FALSE);
344 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) {
345 result = e_targets_include_calendar (targets, n_targets);
346 g_free (targets);
349 return result;
352 gboolean
353 e_selection_data_targets_include_directory (GtkSelectionData *selection_data)
355 GdkAtom *targets;
356 gint n_targets;
357 gboolean result = FALSE;
359 g_return_val_if_fail (selection_data != NULL, FALSE);
361 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) {
362 result = e_targets_include_directory (targets, n_targets);
363 g_free (targets);
366 return result;
369 gboolean
370 e_selection_data_targets_include_html (GtkSelectionData *selection_data)
372 GdkAtom *targets;
373 gint n_targets;
374 gboolean result = FALSE;
376 g_return_val_if_fail (selection_data != NULL, FALSE);
378 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) {
379 result = e_targets_include_html (targets, n_targets);
380 g_free (targets);
383 return result;
386 gboolean
387 e_targets_include_calendar (GdkAtom *targets,
388 gint n_targets)
390 gint ii, jj;
392 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
394 init_atoms ();
396 for (ii = 0; ii < n_targets; ii++)
397 for (jj = 0; jj < NUM_CALENDAR_ATOMS; jj++)
398 if (targets[ii] == calendar_atoms[jj])
399 return TRUE;
401 return FALSE;
404 gboolean
405 e_targets_include_directory (GdkAtom *targets,
406 gint n_targets)
408 gint ii, jj;
410 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
412 init_atoms ();
414 for (ii = 0; ii < n_targets; ii++)
415 for (jj = 0; jj < NUM_DIRECTORY_ATOMS; jj++)
416 if (targets[ii] == directory_atoms[jj])
417 return TRUE;
419 return FALSE;
422 gboolean
423 e_targets_include_html (GdkAtom *targets,
424 gint n_targets)
426 gint ii, jj;
428 g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
430 init_atoms ();
432 for (ii = 0; ii < n_targets; ii++)
433 for (jj = 0; jj < NUM_HTML_ATOMS; jj++)
434 if (targets[ii] == html_atoms[jj])
435 return TRUE;
437 return FALSE;
440 static void
441 clipboard_get_calendar (GtkClipboard *clipboard,
442 GtkSelectionData *selection_data,
443 guint info,
444 gchar *source)
446 e_selection_data_set_calendar (selection_data, source, -1);
449 static void
450 clipboard_clear_calendar (GtkClipboard *clipboard,
451 gchar *source)
453 g_free (source);
456 void
457 e_clipboard_set_calendar (GtkClipboard *clipboard,
458 const gchar *source,
459 gint length)
461 GtkTargetList *list;
462 GtkTargetEntry *targets;
463 gint n_targets;
465 g_return_if_fail (clipboard != NULL);
466 g_return_if_fail (source != NULL);
468 list = gtk_target_list_new (NULL, 0);
469 e_target_list_add_calendar_targets (list, 0);
471 targets = gtk_target_table_new_from_list (list, &n_targets);
473 if (length < 0)
474 length = strlen (source);
476 gtk_clipboard_set_with_data (
477 clipboard, targets, n_targets,
478 (GtkClipboardGetFunc) clipboard_get_calendar,
479 (GtkClipboardClearFunc) clipboard_clear_calendar,
480 g_strndup (source, length));
482 gtk_clipboard_set_can_store (clipboard, NULL, 0);
484 gtk_target_table_free (targets, n_targets);
485 gtk_target_list_unref (list);
488 static void
489 clipboard_get_directory (GtkClipboard *clipboard,
490 GtkSelectionData *selection_data,
491 guint info,
492 gchar *source)
494 e_selection_data_set_directory (selection_data, source, -1);
497 static void
498 clipboard_clear_directory (GtkClipboard *clipboard,
499 gchar *source)
501 g_free (source);
504 void
505 e_clipboard_set_directory (GtkClipboard *clipboard,
506 const gchar *source,
507 gint length)
509 GtkTargetList *list;
510 GtkTargetEntry *targets;
511 gint n_targets;
513 g_return_if_fail (clipboard != NULL);
514 g_return_if_fail (source != NULL);
516 list = gtk_target_list_new (NULL, 0);
517 e_target_list_add_directory_targets (list, 0);
519 targets = gtk_target_table_new_from_list (list, &n_targets);
521 if (length < 0)
522 length = strlen (source);
524 gtk_clipboard_set_with_data (
525 clipboard, targets, n_targets,
526 (GtkClipboardGetFunc) clipboard_get_directory,
527 (GtkClipboardClearFunc) clipboard_clear_directory,
528 g_strndup (source, length));
530 gtk_clipboard_set_can_store (clipboard, NULL, 0);
532 gtk_target_table_free (targets, n_targets);
533 gtk_target_list_unref (list);
536 static void
537 clipboard_get_html (GtkClipboard *clipboard,
538 GtkSelectionData *selection_data,
539 guint info,
540 gchar *source)
542 e_selection_data_set_html (selection_data, source, -1);
545 static void
546 clipboard_clear_html (GtkClipboard *clipboard,
547 gchar *source)
549 g_free (source);
552 void
553 e_clipboard_set_html (GtkClipboard *clipboard,
554 const gchar *source,
555 gint length)
557 GtkTargetList *list;
558 GtkTargetEntry *targets;
559 gint n_targets;
561 g_return_if_fail (clipboard != NULL);
562 g_return_if_fail (source != NULL);
564 list = gtk_target_list_new (NULL, 0);
565 e_target_list_add_html_targets (list, 0);
567 targets = gtk_target_table_new_from_list (list, &n_targets);
569 if (length < 0)
570 length = strlen (source);
572 gtk_clipboard_set_with_data (
573 clipboard, targets, n_targets,
574 (GtkClipboardGetFunc) clipboard_get_html,
575 (GtkClipboardClearFunc) clipboard_clear_html,
576 g_strndup (source, length));
578 gtk_clipboard_set_can_store (clipboard, NULL, 0);
580 gtk_target_table_free (targets, n_targets);
581 gtk_target_list_unref (list);
584 static void
585 clipboard_request_calendar_cb (GtkClipboard *clipboard,
586 GtkSelectionData *selection_data,
587 RequestTextInfo *info)
589 gchar *source;
591 source = e_selection_data_get_calendar (selection_data);
592 info->callback (clipboard, source, info->user_data);
593 g_free (source);
595 g_slice_free (RequestTextInfo, info);
598 void
599 e_clipboard_request_calendar (GtkClipboard *clipboard,
600 GtkClipboardTextReceivedFunc callback,
601 gpointer user_data)
603 RequestTextInfo *info;
605 g_return_if_fail (clipboard != NULL);
606 g_return_if_fail (callback != NULL);
608 init_atoms ();
610 info = g_slice_new (RequestTextInfo);
611 info->callback = callback;
612 info->user_data = user_data;
614 gtk_clipboard_request_contents (
615 clipboard, calendar_atoms[ATOM_CALENDAR],
616 (GtkClipboardReceivedFunc)
617 clipboard_request_calendar_cb, info);
620 static void
621 clipboard_request_directory_cb (GtkClipboard *clipboard,
622 GtkSelectionData *selection_data,
623 RequestTextInfo *info)
625 gchar *source;
627 source = e_selection_data_get_directory (selection_data);
628 info->callback (clipboard, source, info->user_data);
629 g_free (source);
631 g_slice_free (RequestTextInfo, info);
634 void
635 e_clipboard_request_directory (GtkClipboard *clipboard,
636 GtkClipboardTextReceivedFunc callback,
637 gpointer user_data)
639 RequestTextInfo *info;
641 g_return_if_fail (clipboard != NULL);
642 g_return_if_fail (callback != NULL);
644 init_atoms ();
646 info = g_slice_new (RequestTextInfo);
647 info->callback = callback;
648 info->user_data = user_data;
650 gtk_clipboard_request_contents (
651 clipboard, directory_atoms[ATOM_DIRECTORY],
652 (GtkClipboardReceivedFunc)
653 clipboard_request_directory_cb, info);
656 static void
657 clipboard_request_html_cb (GtkClipboard *clipboard,
658 GtkSelectionData *selection_data,
659 RequestTextInfo *info)
661 gchar *source;
663 source = e_selection_data_get_html (selection_data);
664 info->callback (clipboard, source, info->user_data);
665 g_free (source);
667 g_slice_free (RequestTextInfo, info);
670 void
671 e_clipboard_request_html (GtkClipboard *clipboard,
672 GtkClipboardTextReceivedFunc callback,
673 gpointer user_data)
675 RequestTextInfo *info;
677 g_return_if_fail (clipboard != NULL);
678 g_return_if_fail (callback != NULL);
680 init_atoms ();
682 info = g_slice_new (RequestTextInfo);
683 info->callback = callback;
684 info->user_data = user_data;
686 gtk_clipboard_request_contents (
687 clipboard, html_atoms[ATOM_HTML],
688 (GtkClipboardReceivedFunc)
689 clipboard_request_html_cb, info);
692 gchar *
693 e_clipboard_wait_for_calendar (GtkClipboard *clipboard)
695 WaitForDataResults results;
697 g_return_val_if_fail (clipboard != NULL, NULL);
699 results.data = NULL;
700 results.loop = g_main_loop_new (NULL, TRUE);
702 e_clipboard_request_calendar (
703 clipboard, (GtkClipboardTextReceivedFunc)
704 clipboard_wait_for_text_cb, &results);
706 if (g_main_loop_is_running (results.loop))
707 g_main_loop_run (results.loop);
709 g_main_loop_unref (results.loop);
711 return results.data;
714 gchar *
715 e_clipboard_wait_for_directory (GtkClipboard *clipboard)
717 WaitForDataResults results;
719 g_return_val_if_fail (clipboard != NULL, NULL);
721 results.data = NULL;
722 results.loop = g_main_loop_new (NULL, TRUE);
724 e_clipboard_request_directory (
725 clipboard, (GtkClipboardTextReceivedFunc)
726 clipboard_wait_for_text_cb, &results);
728 if (g_main_loop_is_running (results.loop))
729 g_main_loop_run (results.loop);
731 g_main_loop_unref (results.loop);
733 return results.data;
736 gchar *
737 e_clipboard_wait_for_html (GtkClipboard *clipboard)
739 WaitForDataResults results;
741 g_return_val_if_fail (clipboard != NULL, NULL);
743 results.data = NULL;
744 results.loop = g_main_loop_new (NULL, TRUE);
746 e_clipboard_request_html (
747 clipboard, (GtkClipboardTextReceivedFunc)
748 clipboard_wait_for_text_cb, &results);
750 if (g_main_loop_is_running (results.loop))
751 g_main_loop_run (results.loop);
753 g_main_loop_unref (results.loop);
755 return results.data;
758 gboolean
759 e_clipboard_wait_is_calendar_available (GtkClipboard *clipboard)
761 GdkAtom *targets;
762 gint n_targets;
763 gboolean result = FALSE;
765 if (gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets)) {
766 result = e_targets_include_calendar (targets, n_targets);
767 g_free (targets);
770 return result;
773 gboolean
774 e_clipboard_wait_is_directory_available (GtkClipboard *clipboard)
776 GdkAtom *targets;
777 gint n_targets;
778 gboolean result = FALSE;
780 if (gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets)) {
781 result = e_targets_include_directory (targets, n_targets);
782 g_free (targets);
785 return result;
788 gboolean
789 e_clipboard_wait_is_html_available (GtkClipboard *clipboard)
791 GdkAtom *targets;
792 gint n_targets;
793 gboolean result = FALSE;
795 if (gtk_clipboard_wait_for_targets (clipboard, &targets, &n_targets)) {
796 result = e_targets_include_html (targets, n_targets);
797 g_free (targets);
800 return result;
803 void
804 e_drag_dest_add_calendar_targets (GtkWidget *widget)
806 GtkTargetList *target_list;
808 g_return_if_fail (GTK_IS_WIDGET (widget));
810 target_list = gtk_drag_dest_get_target_list (widget);
811 if (target_list != NULL)
812 gtk_target_list_ref (target_list);
813 else
814 target_list = gtk_target_list_new (NULL, 0);
815 e_target_list_add_calendar_targets (target_list, 0);
816 gtk_drag_dest_set_target_list (widget, target_list);
817 gtk_target_list_unref (target_list);
820 void
821 e_drag_dest_add_directory_targets (GtkWidget *widget)
823 GtkTargetList *target_list;
825 g_return_if_fail (GTK_IS_WIDGET (widget));
827 target_list = gtk_drag_dest_get_target_list (widget);
828 if (target_list != NULL)
829 gtk_target_list_ref (target_list);
830 else
831 target_list = gtk_target_list_new (NULL, 0);
832 e_target_list_add_directory_targets (target_list, 0);
833 gtk_drag_dest_set_target_list (widget, target_list);
834 gtk_target_list_unref (target_list);
837 void
838 e_drag_dest_add_html_targets (GtkWidget *widget)
840 GtkTargetList *target_list;
842 g_return_if_fail (GTK_IS_WIDGET (widget));
844 target_list = gtk_drag_dest_get_target_list (widget);
845 if (target_list != NULL)
846 gtk_target_list_ref (target_list);
847 else
848 target_list = gtk_target_list_new (NULL, 0);
849 e_target_list_add_html_targets (target_list, 0);
850 gtk_drag_dest_set_target_list (widget, target_list);
851 gtk_target_list_unref (target_list);
854 void
855 e_drag_source_add_calendar_targets (GtkWidget *widget)
857 GtkTargetList *target_list;
859 g_return_if_fail (GTK_IS_WIDGET (widget));
861 target_list = gtk_drag_source_get_target_list (widget);
862 if (target_list != NULL)
863 gtk_target_list_ref (target_list);
864 else
865 target_list = gtk_target_list_new (NULL, 0);
866 e_target_list_add_calendar_targets (target_list, 0);
867 gtk_drag_source_set_target_list (widget, target_list);
868 gtk_target_list_unref (target_list);
871 void
872 e_drag_source_add_directory_targets (GtkWidget *widget)
874 GtkTargetList *target_list;
876 g_return_if_fail (GTK_IS_WIDGET (widget));
878 target_list = gtk_drag_source_get_target_list (widget);
879 if (target_list != NULL)
880 gtk_target_list_ref (target_list);
881 else
882 target_list = gtk_target_list_new (NULL, 0);
883 e_target_list_add_directory_targets (target_list, 0);
884 gtk_drag_source_set_target_list (widget, target_list);
885 gtk_target_list_unref (target_list);
888 void
889 e_drag_source_add_html_targets (GtkWidget *widget)
891 GtkTargetList *target_list;
893 g_return_if_fail (GTK_IS_WIDGET (widget));
895 target_list = gtk_drag_source_get_target_list (widget);
896 if (target_list != NULL)
897 gtk_target_list_ref (target_list);
898 else
899 target_list = gtk_target_list_new (NULL, 0);
900 e_target_list_add_html_targets (target_list, 0);
901 gtk_drag_source_set_target_list (widget, target_list);
902 gtk_target_list_unref (target_list);