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
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)
22 * SECTION: e-selection
23 * @short_description: selection and clipboard utilities
24 * @include: e-util/e-util.h
31 #include "e-selection.h"
35 typedef struct _RequestTextInfo RequestTextInfo
;
36 typedef struct _WaitForDataResults WaitForDataResults
;
38 struct _RequestTextInfo
{
39 GtkClipboardTextReceivedFunc callback
;
43 struct _WaitForDataResults
{
65 static GdkAtom calendar_atoms
[NUM_CALENDAR_ATOMS
];
66 static GdkAtom directory_atoms
[NUM_DIRECTORY_ATOMS
];
67 static GdkAtom html_atoms
[NUM_HTML_ATOMS
];
72 static gboolean initialized
= FALSE
;
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");
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");
95 html_atoms
[ATOM_HTML
] =
96 gdk_atom_intern_static_string ("text/html");
102 clipboard_wait_for_text_cb (GtkClipboard
*clipboard
,
104 WaitForDataResults
*results
)
106 results
->data
= g_strdup (source
);
107 g_main_loop_quit (results
->loop
);
111 e_target_list_add_calendar_targets (GtkTargetList
*list
,
116 g_return_if_fail (list
!= NULL
);
120 for (ii
= 0; ii
< NUM_CALENDAR_ATOMS
; ii
++)
121 gtk_target_list_add (list
, calendar_atoms
[ii
], 0, info
);
125 e_target_list_add_directory_targets (GtkTargetList
*list
,
130 g_return_if_fail (list
!= NULL
);
134 for (ii
= 0; ii
< NUM_DIRECTORY_ATOMS
; ii
++)
135 gtk_target_list_add (list
, directory_atoms
[ii
], 0, info
);
139 e_target_list_add_html_targets (GtkTargetList
*list
,
144 g_return_if_fail (list
!= NULL
);
148 for (ii
= 0; ii
< NUM_HTML_ATOMS
; ii
++)
149 gtk_target_list_add (list
, html_atoms
[ii
], 0, info
);
153 e_selection_data_set_calendar (GtkSelectionData
*selection_data
,
160 g_return_val_if_fail (selection_data
!= NULL
, FALSE
);
161 g_return_val_if_fail (source
!= NULL
, FALSE
);
164 length
= strlen (source
);
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
);
184 e_selection_data_set_directory (GtkSelectionData
*selection_data
,
191 g_return_val_if_fail (selection_data
!= NULL
, FALSE
);
192 g_return_val_if_fail (source
!= NULL
, FALSE
);
195 length
= strlen (source
);
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
);
215 e_selection_data_set_html (GtkSelectionData
*selection_data
,
222 g_return_val_if_fail (selection_data
!= NULL
, FALSE
);
223 g_return_val_if_fail (source
!= NULL
, FALSE
);
226 length
= strlen (source
);
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
);
246 e_selection_data_get_calendar (GtkSelectionData
*selection_data
)
249 const guchar
*data
= NULL
;
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
);
269 e_selection_data_get_directory (GtkSelectionData
*selection_data
)
272 const guchar
*data
= NULL
;
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
);
292 e_selection_data_get_html (GtkSelectionData
*selection_data
)
295 const guchar
*data
= NULL
;
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
);
316 utf8_text
= g_convert (
317 (const gchar
*) data
, length
,
318 "UTF-8", "UTF-16", NULL
, NULL
, &error
);
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
])
336 e_selection_data_targets_include_calendar (GtkSelectionData
*selection_data
)
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
);
353 e_selection_data_targets_include_directory (GtkSelectionData
*selection_data
)
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
);
370 e_selection_data_targets_include_html (GtkSelectionData
*selection_data
)
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
);
387 e_targets_include_calendar (GdkAtom
*targets
,
392 g_return_val_if_fail (targets
!= NULL
|| n_targets
== 0, FALSE
);
396 for (ii
= 0; ii
< n_targets
; ii
++)
397 for (jj
= 0; jj
< NUM_CALENDAR_ATOMS
; jj
++)
398 if (targets
[ii
] == calendar_atoms
[jj
])
405 e_targets_include_directory (GdkAtom
*targets
,
410 g_return_val_if_fail (targets
!= NULL
|| n_targets
== 0, FALSE
);
414 for (ii
= 0; ii
< n_targets
; ii
++)
415 for (jj
= 0; jj
< NUM_DIRECTORY_ATOMS
; jj
++)
416 if (targets
[ii
] == directory_atoms
[jj
])
423 e_targets_include_html (GdkAtom
*targets
,
428 g_return_val_if_fail (targets
!= NULL
|| n_targets
== 0, FALSE
);
432 for (ii
= 0; ii
< n_targets
; ii
++)
433 for (jj
= 0; jj
< NUM_HTML_ATOMS
; jj
++)
434 if (targets
[ii
] == html_atoms
[jj
])
441 clipboard_get_calendar (GtkClipboard
*clipboard
,
442 GtkSelectionData
*selection_data
,
446 e_selection_data_set_calendar (selection_data
, source
, -1);
450 clipboard_clear_calendar (GtkClipboard
*clipboard
,
457 e_clipboard_set_calendar (GtkClipboard
*clipboard
,
462 GtkTargetEntry
*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
);
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
);
489 clipboard_get_directory (GtkClipboard
*clipboard
,
490 GtkSelectionData
*selection_data
,
494 e_selection_data_set_directory (selection_data
, source
, -1);
498 clipboard_clear_directory (GtkClipboard
*clipboard
,
505 e_clipboard_set_directory (GtkClipboard
*clipboard
,
510 GtkTargetEntry
*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
);
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
);
537 clipboard_get_html (GtkClipboard
*clipboard
,
538 GtkSelectionData
*selection_data
,
542 e_selection_data_set_html (selection_data
, source
, -1);
546 clipboard_clear_html (GtkClipboard
*clipboard
,
553 e_clipboard_set_html (GtkClipboard
*clipboard
,
558 GtkTargetEntry
*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
);
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
);
585 clipboard_request_calendar_cb (GtkClipboard
*clipboard
,
586 GtkSelectionData
*selection_data
,
587 RequestTextInfo
*info
)
591 source
= e_selection_data_get_calendar (selection_data
);
592 info
->callback (clipboard
, source
, info
->user_data
);
595 g_slice_free (RequestTextInfo
, info
);
599 e_clipboard_request_calendar (GtkClipboard
*clipboard
,
600 GtkClipboardTextReceivedFunc callback
,
603 RequestTextInfo
*info
;
605 g_return_if_fail (clipboard
!= NULL
);
606 g_return_if_fail (callback
!= NULL
);
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
);
621 clipboard_request_directory_cb (GtkClipboard
*clipboard
,
622 GtkSelectionData
*selection_data
,
623 RequestTextInfo
*info
)
627 source
= e_selection_data_get_directory (selection_data
);
628 info
->callback (clipboard
, source
, info
->user_data
);
631 g_slice_free (RequestTextInfo
, info
);
635 e_clipboard_request_directory (GtkClipboard
*clipboard
,
636 GtkClipboardTextReceivedFunc callback
,
639 RequestTextInfo
*info
;
641 g_return_if_fail (clipboard
!= NULL
);
642 g_return_if_fail (callback
!= NULL
);
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
);
657 clipboard_request_html_cb (GtkClipboard
*clipboard
,
658 GtkSelectionData
*selection_data
,
659 RequestTextInfo
*info
)
663 source
= e_selection_data_get_html (selection_data
);
664 info
->callback (clipboard
, source
, info
->user_data
);
667 g_slice_free (RequestTextInfo
, info
);
671 e_clipboard_request_html (GtkClipboard
*clipboard
,
672 GtkClipboardTextReceivedFunc callback
,
675 RequestTextInfo
*info
;
677 g_return_if_fail (clipboard
!= NULL
);
678 g_return_if_fail (callback
!= NULL
);
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
);
693 e_clipboard_wait_for_calendar (GtkClipboard
*clipboard
)
695 WaitForDataResults results
;
697 g_return_val_if_fail (clipboard
!= NULL
, 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
);
715 e_clipboard_wait_for_directory (GtkClipboard
*clipboard
)
717 WaitForDataResults results
;
719 g_return_val_if_fail (clipboard
!= NULL
, 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
);
737 e_clipboard_wait_for_html (GtkClipboard
*clipboard
)
739 WaitForDataResults results
;
741 g_return_val_if_fail (clipboard
!= NULL
, 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
);
759 e_clipboard_wait_is_calendar_available (GtkClipboard
*clipboard
)
763 gboolean result
= FALSE
;
765 if (gtk_clipboard_wait_for_targets (clipboard
, &targets
, &n_targets
)) {
766 result
= e_targets_include_calendar (targets
, n_targets
);
774 e_clipboard_wait_is_directory_available (GtkClipboard
*clipboard
)
778 gboolean result
= FALSE
;
780 if (gtk_clipboard_wait_for_targets (clipboard
, &targets
, &n_targets
)) {
781 result
= e_targets_include_directory (targets
, n_targets
);
789 e_clipboard_wait_is_html_available (GtkClipboard
*clipboard
)
793 gboolean result
= FALSE
;
795 if (gtk_clipboard_wait_for_targets (clipboard
, &targets
, &n_targets
)) {
796 result
= e_targets_include_html (targets
, n_targets
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);