1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gdkselection.h"
30 #include "gdkproperty.h"
31 #include "gdkprivate.h"
32 #include "gdkprivate-x11.h"
33 #include "gdkdisplay-x11.h"
36 #include <X11/Xatom.h>
40 typedef struct _OwnerInfo OwnerInfo;
49 static GSList *owner_list;
51 /* When a window is destroyed we check if it is the owner
52 * of any selections. This is somewhat inefficient, but
53 * owner_list is typically short, and it is a low memory,
57 _gdk_selection_window_destroyed (GdkWindow *window)
59 GSList *tmp_list = owner_list;
62 OwnerInfo *info = tmp_list->data;
63 tmp_list = tmp_list->next;
65 if (info->owner == window)
67 owner_list = g_slist_remove (owner_list, info);
73 /* We only pass through those SelectionClear events that actually
74 * reflect changes to the selection owner that we didn't make ourself.
77 _gdk_selection_filter_clear_event (XSelectionClearEvent *event)
79 GSList *tmp_list = owner_list;
80 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->display);
84 OwnerInfo *info = tmp_list->data;
86 if (gdk_window_get_display (info->owner) == display &&
87 info->selection == gdk_x11_xatom_to_atom_for_display (display, event->selection))
89 if ((GDK_WINDOW_XID (info->owner) == event->window &&
90 event->serial >= info->serial))
92 owner_list = g_slist_remove (owner_list, info);
99 tmp_list = tmp_list->next;
106 _gdk_x11_display_set_selection_owner (GdkDisplay *display,
118 if (gdk_display_is_closed (display))
123 if (GDK_WINDOW_DESTROYED (owner) || !GDK_WINDOW_IS_X11 (owner))
126 gdk_window_ensure_native (owner);
127 xdisplay = GDK_WINDOW_XDISPLAY (owner);
128 xwindow = GDK_WINDOW_XID (owner);
132 xdisplay = GDK_DISPLAY_XDISPLAY (display);
136 xselection = gdk_x11_atom_to_xatom_for_display (display, selection);
138 tmp_list = owner_list;
141 info = tmp_list->data;
142 if (info->selection == selection)
144 owner_list = g_slist_remove (owner_list, info);
148 tmp_list = tmp_list->next;
153 info = g_new (OwnerInfo, 1);
155 info->serial = NextRequest (GDK_WINDOW_XDISPLAY (owner));
156 info->selection = selection;
158 owner_list = g_slist_prepend (owner_list, info);
161 XSetSelectionOwner (xdisplay, xselection, xwindow, time);
163 return (XGetSelectionOwner (xdisplay, xselection) == xwindow);
167 _gdk_x11_display_get_selection_owner (GdkDisplay *display,
172 if (gdk_display_is_closed (display))
175 xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
176 gdk_x11_atom_to_xatom_for_display (display,
181 return gdk_x11_window_lookup_for_display (display, xwindow);
185 gdk_selection_convert (GdkWindow *requestor,
192 g_return_if_fail (selection != GDK_NONE);
194 if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
197 gdk_window_ensure_native (requestor);
198 display = GDK_WINDOW_DISPLAY (requestor);
200 XConvertSelection (GDK_WINDOW_XDISPLAY (requestor),
201 gdk_x11_atom_to_xatom_for_display (display, selection),
202 gdk_x11_atom_to_xatom_for_display (display, target),
203 gdk_x11_get_xatom_by_name_for_display (display, "GDK_SELECTION"),
204 GDK_WINDOW_XID (requestor), time);
208 * gdk_selection_property_get:
209 * @requestor: the window on which the data is stored
210 * @data: location to store a pointer to the retrieved data.
211 If the retrieval failed, %NULL we be stored here, otherwise, it
212 will be non-%NULL and the returned data should be freed with g_free()
213 when you are finished using it. The length of the
214 allocated memory is one more than the length
215 of the returned data, and the final byte will always
216 be zero, to ensure nul-termination of strings.
217 * @prop_type: location to store the type of the property.
218 * @prop_format: location to store the format of the property.
220 * Retrieves selection data that was stored by the selection
221 * data in response to a call to gdk_selection_convert(). This function
222 * will not be used by applications, who should use the #GtkClipboard
225 * Return value: the length of the retrieved data.
228 gdk_selection_property_get (GdkWindow *requestor,
235 gulong length = 0; /* Quiet GCC */
241 g_return_val_if_fail (requestor != NULL, 0);
242 g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
243 g_return_val_if_fail (GDK_WINDOW_IS_X11 (requestor), 0);
245 display = GDK_WINDOW_DISPLAY (requestor);
247 if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
252 /* We can't delete the selection here, because it might be the INCR
253 protocol, in which case the client has to make sure they'll be
254 notified of PropertyChange events _before_ the property is deleted.
255 Otherwise there's no guarantee we'll win the race ... */
256 if (XGetWindowProperty (GDK_WINDOW_XDISPLAY (requestor),
257 GDK_WINDOW_XID (requestor),
258 gdk_x11_get_xatom_by_name_for_display (display, "GDK_SELECTION"),
259 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False,
260 AnyPropertyType, &prop_type, &prop_format,
261 &nitems, &nbytes, &t) != Success)
264 if (prop_type != None)
267 *ret_type = gdk_x11_xatom_to_atom_for_display (display, prop_type);
269 *ret_format = prop_format;
271 if (prop_type == XA_ATOM ||
272 prop_type == gdk_x11_get_xatom_by_name_for_display (display, "ATOM_PAIR"))
274 Atom* atoms = (Atom*) t;
278 if (prop_format != 32)
282 length = sizeof (GdkAtom) * num_atom + 1;
286 *data = g_malloc (length);
287 (*data)[length - 1] = '\0';
288 atoms_dest = (GdkAtom *)(*data);
290 for (i=0; i < num_atom; i++)
291 atoms_dest[i] = gdk_x11_xatom_to_atom_for_display (display, atoms[i]);
302 length = sizeof(short) * nitems;
305 length = sizeof(long) * nitems;
308 g_assert_not_reached ();
312 /* Add on an extra byte to handle null termination. X guarantees
313 that t will be 1 longer than nitems and null terminated */
317 *data = g_memdup (t, length);
328 *ret_type = GDK_NONE;
338 * gdk_selection_send_notify_for_display:
339 * @display: the #GdkDisplay where @requestor is realized
340 * @requestor: window to which to deliver response.
341 * @selection: selection that was requested.
342 * @target: target that was selected.
343 * @property: property in which the selection owner stored the data,
344 * or %GDK_NONE to indicate that the request was rejected.
347 * Send a response to SelectionRequest event.
352 gdk_selection_send_notify_for_display (GdkDisplay *display,
353 GdkNativeWindow requestor,
359 XSelectionEvent xevent;
361 g_return_if_fail (GDK_IS_DISPLAY (display));
363 xevent.type = SelectionNotify;
365 xevent.send_event = True;
366 xevent.requestor = requestor;
367 xevent.selection = gdk_x11_atom_to_xatom_for_display (display, selection);
368 xevent.target = gdk_x11_atom_to_xatom_for_display (display, target);
369 if (property == GDK_NONE)
370 xevent.property = None;
372 xevent.property = gdk_x11_atom_to_xatom_for_display (display, property);
375 _gdk_x11_display_send_xevent (display, requestor, False, NoEventMask, (XEvent*) & xevent);
379 * gdk_text_property_to_text_list_for_display:
380 * @display: The #GdkDisplay where the encoding is defined.
381 * @encoding: an atom representing the encoding. The most
382 * common values for this are STRING, or COMPOUND_TEXT.
383 * This is value used as the type for the property.
384 * @format: the format of the property.
385 * @text: The text data.
386 * @length: The number of items to transform.
387 * @list: location to store a terminated array of strings in
388 * the encoding of the current locale. This array should be
389 * freed using gdk_free_text_list().
391 * Convert a text string from the encoding as it is stored
392 * in a property into an array of strings in the encoding of
393 * the current locale. (The elements of the array represent the
394 * nul-separated elements of the original text string.)
396 * Returns: the number of strings stored in list, or 0,
397 * if the conversion failed.
402 gdk_text_property_to_text_list_for_display (GdkDisplay *display,
409 XTextProperty property;
413 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
418 if (gdk_display_is_closed (display))
421 property.value = (guchar *)text;
422 property.encoding = gdk_x11_atom_to_xatom_for_display (display, encoding);
423 property.format = format;
424 property.nitems = length;
425 res = XmbTextPropertyToTextList (GDK_DISPLAY_XDISPLAY (display), &property,
426 &local_list, &count);
427 if (res == XNoMemory || res == XLocaleNotSupported || res == XConverterNotFound)
434 XFreeStringList (local_list);
441 * gdk_free_text_list:
442 * @list: the value stored in the @list parameter by
443 * a call to gdk_text_property_to_text_list().
445 * Frees the array of strings created by
446 * gdk_text_property_to_text_list().
449 gdk_free_text_list (gchar **list)
451 g_return_if_fail (list != NULL);
453 XFreeStringList (list);
457 make_list (const gchar *text,
462 GSList *strings = NULL;
465 const gchar *p = text;
468 GError *error = NULL;
470 while (p < text + length)
475 while (*q && q < text + length)
480 str = g_convert (p, q - p,
481 "UTF-8", "ISO-8859-1",
486 g_warning ("Error converting selection from STRING: %s",
488 g_error_free (error);
493 str = g_strndup (p, q - p);
494 if (!g_utf8_validate (str, -1, NULL))
496 g_warning ("Error converting selection from UTF8_STRING");
504 strings = g_slist_prepend (strings, str);
513 *list = g_new (gchar *, n_strings + 1);
514 (*list)[n_strings] = NULL;
522 (*list)[--i] = tmp_list->data;
524 g_free (tmp_list->data);
526 tmp_list = tmp_list->next;
529 g_slist_free (strings);
535 * gdk_text_property_to_utf8_list_for_display:
536 * @display: a #GdkDisplay
537 * @encoding: an atom representing the encoding of the text
538 * @format: the format of the property
539 * @text: the text to convert
540 * @length: the length of @text, in bytes
541 * @list: location to store the list of strings or %NULL. The
542 * list should be freed with g_strfreev().
544 * Converts a text property in the given encoding to
545 * a list of UTF-8 strings.
547 * Return value: the number of strings in the resulting
553 gdk_text_property_to_utf8_list_for_display (GdkDisplay *display,
560 g_return_val_if_fail (text != NULL, 0);
561 g_return_val_if_fail (length >= 0, 0);
562 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
564 if (encoding == GDK_TARGET_STRING)
566 return make_list ((gchar *)text, length, TRUE, list);
568 else if (encoding == gdk_atom_intern_static_string ("UTF8_STRING"))
570 return make_list ((gchar *)text, length, FALSE, list);
577 const gchar *charset = NULL;
578 gboolean need_conversion = !g_get_charset (&charset);
580 GError *error = NULL;
582 /* Probably COMPOUND text, we fall back to Xlib routines
584 local_count = gdk_text_property_to_text_list_for_display (display,
591 *list = g_new (gchar *, local_count + 1);
593 for (i=0; i<local_count; i++)
595 /* list contains stuff in our default encoding
599 gchar *utf = g_convert (local_list[i], -1,
605 (*list)[count++] = utf;
611 g_warning ("Error converting to UTF-8 from '%s': %s",
612 charset, error->message);
613 g_error_free (error);
621 if (g_utf8_validate (local_list[i], -1, NULL))
622 (*list)[count++] = g_strdup (local_list[i]);
624 g_warning ("Error converting selection");
630 gdk_free_text_list (local_list);
633 (*list)[count] = NULL;
640 * gdk_string_to_compound_text_for_display:
641 * @display: the #GdkDisplay where the encoding is defined.
642 * @str: a nul-terminated string.
643 * @encoding: location to store the encoding atom
644 * (to be used as the type for the property).
645 * @format: location to store the format of the property
646 * @ctext: location to store newly allocated data for the property.
647 * @length: the length of @text, in bytes
649 * Convert a string from the encoding of the current
650 * locale into a form suitable for storing in a window property.
652 * Returns: 0 upon success, non-zero upon failure.
657 gdk_string_to_compound_text_for_display (GdkDisplay *display,
665 XTextProperty property;
667 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
669 if (gdk_display_is_closed (display))
670 res = XLocaleNotSupported;
672 res = XmbTextListToTextProperty (GDK_DISPLAY_XDISPLAY (display),
673 (char **)&str, 1, XCompoundTextStyle,
677 property.encoding = None;
678 property.format = None;
679 property.value = NULL;
684 *encoding = gdk_x11_xatom_to_atom_for_display (display, property.encoding);
686 *format = property.format;
688 *ctext = property.value;
690 *length = property.nitems;
695 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
696 * C1 are not allowed except for \n and \t, however the X conversions
697 * routines for COMPOUND_TEXT only enforce this in one direction,
698 * causing cut-and-paste of \r and \r\n separated text to fail.
699 * This routine strips out all non-allowed C0 and C1 characters
700 * from the input string and also canonicalizes \r, and \r\n to \n
703 sanitize_utf8 (const gchar *src,
704 gboolean return_latin1)
706 gint len = strlen (src);
707 GString *result = g_string_sized_new (len);
708 const gchar *p = src;
718 g_string_append_c (result, '\n');
722 gunichar ch = g_utf8_get_char (p);
724 if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
729 g_string_append_c (result, ch);
731 g_string_append_printf (result,
732 ch < 0x10000 ? "\\u%04x" : "\\U%08x",
740 buflen = g_unichar_to_utf8 (ch, buf);
741 g_string_append_len (result, buf, buflen);
745 p = g_utf8_next_char (p);
749 return g_string_free (result, FALSE);
753 * gdk_utf8_to_string_target:
754 * @str: a UTF-8 string
756 * Converts an UTF-8 string into the best possible representation
757 * as a STRING. The representation of characters not in STRING
758 * is not specified; it may be as pseudo-escape sequences
759 * \x{ABCD}, or it may be in some other form of approximation.
761 * Return value: the newly-allocated string, or %NULL if the
762 * conversion failed. (It should not fail for
763 * any properly formed UTF-8 string unless system
764 * limits like memory or file descriptors are exceeded.)
767 gdk_utf8_to_string_target (const gchar *str)
769 return sanitize_utf8 (str, TRUE);
773 * gdk_utf8_to_compound_text_for_display:
774 * @display: a #GdkDisplay
775 * @str: a UTF-8 string
776 * @encoding: location to store resulting encoding
777 * @format: location to store format of the result
778 * @ctext: location to store the data of the result
779 * @length: location to store the length of the data
782 * Converts from UTF-8 to compound text.
784 * Return value: %TRUE if the conversion succeeded, otherwise
790 gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
797 gboolean need_conversion;
798 const gchar *charset;
799 gchar *locale_str, *tmp_str;
800 GError *error = NULL;
803 g_return_val_if_fail (str != NULL, FALSE);
804 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
806 need_conversion = !g_get_charset (&charset);
808 tmp_str = sanitize_utf8 (str, FALSE);
812 locale_str = g_convert (tmp_str, -1,
819 if (!(error->domain = G_CONVERT_ERROR &&
820 error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE))
822 g_warning ("Error converting from UTF-8 to '%s': %s",
823 charset, error->message);
825 g_error_free (error);
840 locale_str = tmp_str;
842 result = gdk_string_to_compound_text_for_display (display, locale_str,
845 result = (result == Success? TRUE : FALSE);
853 * gdk_free_compound_text:
854 * @ctext: The pointer stored in @ctext from a call to
855 * gdk_string_to_compound_text().
857 * Frees the data returned from gdk_string_to_compound_text().
859 void gdk_free_compound_text (guchar *ctext)