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;
105 * gdk_selection_owner_set_for_display:
106 * @display: the #GdkDisplay.
107 * @owner: a #GdkWindow or %NULL to indicate that the owner for
108 * the given should be unset.
109 * @selection: an atom identifying a selection.
110 * @time_: timestamp to use when setting the selection.
111 * If this is older than the timestamp given last time the owner was
112 * set for the given selection, the request will be ignored.
113 * @send_event: if %TRUE, and the new owner is different from the current
114 * owner, the current owner will be sent a SelectionClear event.
116 * Sets the #GdkWindow @owner as the current owner of the selection @selection.
118 * Returns: %TRUE if the selection owner was successfully changed to owner,
124 gdk_selection_owner_set_for_display (GdkDisplay *display,
136 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
137 g_return_val_if_fail (selection != GDK_NONE, FALSE);
139 if (gdk_display_is_closed (display))
144 if (GDK_WINDOW_DESTROYED (owner) || !GDK_WINDOW_IS_X11 (owner))
147 gdk_window_ensure_native (owner);
148 xdisplay = GDK_WINDOW_XDISPLAY (owner);
149 xwindow = GDK_WINDOW_XID (owner);
153 xdisplay = GDK_DISPLAY_XDISPLAY (display);
157 xselection = gdk_x11_atom_to_xatom_for_display (display, selection);
159 tmp_list = owner_list;
162 info = tmp_list->data;
163 if (info->selection == selection)
165 owner_list = g_slist_remove (owner_list, info);
169 tmp_list = tmp_list->next;
174 info = g_new (OwnerInfo, 1);
176 info->serial = NextRequest (GDK_WINDOW_XDISPLAY (owner));
177 info->selection = selection;
179 owner_list = g_slist_prepend (owner_list, info);
182 XSetSelectionOwner (xdisplay, xselection, xwindow, time);
184 return (XGetSelectionOwner (xdisplay, xselection) == xwindow);
188 * gdk_selection_owner_get_for_display:
189 * @display: a #GdkDisplay.
190 * @selection: an atom indentifying a selection.
192 * Determine the owner of the given selection.
194 * Note that the return value may be owned by a different
195 * process if a foreign window was previously created for that
196 * window, but a new foreign window will never be created by this call.
198 * Returns: (transfer none): if there is a selection owner for this window,
199 * and it is a window known to the current process, the #GdkWindow that
200 * owns the selection, otherwise %NULL.
205 gdk_selection_owner_get_for_display (GdkDisplay *display,
210 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
211 g_return_val_if_fail (selection != GDK_NONE, NULL);
213 if (gdk_display_is_closed (display))
216 xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
217 gdk_x11_atom_to_xatom_for_display (display,
222 return gdk_x11_window_lookup_for_display (display, xwindow);
226 gdk_selection_convert (GdkWindow *requestor,
233 g_return_if_fail (selection != GDK_NONE);
235 if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
238 gdk_window_ensure_native (requestor);
239 display = GDK_WINDOW_DISPLAY (requestor);
241 XConvertSelection (GDK_WINDOW_XDISPLAY (requestor),
242 gdk_x11_atom_to_xatom_for_display (display, selection),
243 gdk_x11_atom_to_xatom_for_display (display, target),
244 gdk_x11_get_xatom_by_name_for_display (display, "GDK_SELECTION"),
245 GDK_WINDOW_XID (requestor), time);
249 * gdk_selection_property_get:
250 * @requestor: the window on which the data is stored
251 * @data: location to store a pointer to the retrieved data.
252 If the retrieval failed, %NULL we be stored here, otherwise, it
253 will be non-%NULL and the returned data should be freed with g_free()
254 when you are finished using it. The length of the
255 allocated memory is one more than the length
256 of the returned data, and the final byte will always
257 be zero, to ensure nul-termination of strings.
258 * @prop_type: location to store the type of the property.
259 * @prop_format: location to store the format of the property.
261 * Retrieves selection data that was stored by the selection
262 * data in response to a call to gdk_selection_convert(). This function
263 * will not be used by applications, who should use the #GtkClipboard
266 * Return value: the length of the retrieved data.
269 gdk_selection_property_get (GdkWindow *requestor,
276 gulong length = 0; /* Quiet GCC */
282 g_return_val_if_fail (requestor != NULL, 0);
283 g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
284 g_return_val_if_fail (GDK_WINDOW_IS_X11 (requestor), 0);
286 display = GDK_WINDOW_DISPLAY (requestor);
288 if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
293 /* We can't delete the selection here, because it might be the INCR
294 protocol, in which case the client has to make sure they'll be
295 notified of PropertyChange events _before_ the property is deleted.
296 Otherwise there's no guarantee we'll win the race ... */
297 if (XGetWindowProperty (GDK_WINDOW_XDISPLAY (requestor),
298 GDK_WINDOW_XID (requestor),
299 gdk_x11_get_xatom_by_name_for_display (display, "GDK_SELECTION"),
300 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False,
301 AnyPropertyType, &prop_type, &prop_format,
302 &nitems, &nbytes, &t) != Success)
305 if (prop_type != None)
308 *ret_type = gdk_x11_xatom_to_atom_for_display (display, prop_type);
310 *ret_format = prop_format;
312 if (prop_type == XA_ATOM ||
313 prop_type == gdk_x11_get_xatom_by_name_for_display (display, "ATOM_PAIR"))
315 Atom* atoms = (Atom*) t;
319 if (prop_format != 32)
323 length = sizeof (GdkAtom) * num_atom + 1;
327 *data = g_malloc (length);
328 (*data)[length - 1] = '\0';
329 atoms_dest = (GdkAtom *)(*data);
331 for (i=0; i < num_atom; i++)
332 atoms_dest[i] = gdk_x11_xatom_to_atom_for_display (display, atoms[i]);
343 length = sizeof(short) * nitems;
346 length = sizeof(long) * nitems;
349 g_assert_not_reached ();
353 /* Add on an extra byte to handle null termination. X guarantees
354 that t will be 1 longer than nitems and null terminated */
358 *data = g_memdup (t, length);
369 *ret_type = GDK_NONE;
379 * gdk_selection_send_notify_for_display:
380 * @display: the #GdkDisplay where @requestor is realized
381 * @requestor: window to which to deliver response.
382 * @selection: selection that was requested.
383 * @target: target that was selected.
384 * @property: property in which the selection owner stored the data,
385 * or %GDK_NONE to indicate that the request was rejected.
388 * Send a response to SelectionRequest event.
393 gdk_selection_send_notify_for_display (GdkDisplay *display,
394 GdkNativeWindow requestor,
400 XSelectionEvent xevent;
402 g_return_if_fail (GDK_IS_DISPLAY (display));
404 xevent.type = SelectionNotify;
406 xevent.send_event = True;
407 xevent.requestor = requestor;
408 xevent.selection = gdk_x11_atom_to_xatom_for_display (display, selection);
409 xevent.target = gdk_x11_atom_to_xatom_for_display (display, target);
410 if (property == GDK_NONE)
411 xevent.property = None;
413 xevent.property = gdk_x11_atom_to_xatom_for_display (display, property);
416 _gdk_x11_display_send_xevent (display, requestor, False, NoEventMask, (XEvent*) & xevent);
420 * gdk_text_property_to_text_list_for_display:
421 * @display: The #GdkDisplay where the encoding is defined.
422 * @encoding: an atom representing the encoding. The most
423 * common values for this are STRING, or COMPOUND_TEXT.
424 * This is value used as the type for the property.
425 * @format: the format of the property.
426 * @text: The text data.
427 * @length: The number of items to transform.
428 * @list: location to store a terminated array of strings in
429 * the encoding of the current locale. This array should be
430 * freed using gdk_free_text_list().
432 * Convert a text string from the encoding as it is stored
433 * in a property into an array of strings in the encoding of
434 * the current locale. (The elements of the array represent the
435 * nul-separated elements of the original text string.)
437 * Returns: the number of strings stored in list, or 0,
438 * if the conversion failed.
443 gdk_text_property_to_text_list_for_display (GdkDisplay *display,
450 XTextProperty property;
454 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
459 if (gdk_display_is_closed (display))
462 property.value = (guchar *)text;
463 property.encoding = gdk_x11_atom_to_xatom_for_display (display, encoding);
464 property.format = format;
465 property.nitems = length;
466 res = XmbTextPropertyToTextList (GDK_DISPLAY_XDISPLAY (display), &property,
467 &local_list, &count);
468 if (res == XNoMemory || res == XLocaleNotSupported || res == XConverterNotFound)
475 XFreeStringList (local_list);
482 * gdk_free_text_list:
483 * @list: the value stored in the @list parameter by
484 * a call to gdk_text_property_to_text_list().
486 * Frees the array of strings created by
487 * gdk_text_property_to_text_list().
490 gdk_free_text_list (gchar **list)
492 g_return_if_fail (list != NULL);
494 XFreeStringList (list);
498 make_list (const gchar *text,
503 GSList *strings = NULL;
506 const gchar *p = text;
509 GError *error = NULL;
511 while (p < text + length)
516 while (*q && q < text + length)
521 str = g_convert (p, q - p,
522 "UTF-8", "ISO-8859-1",
527 g_warning ("Error converting selection from STRING: %s",
529 g_error_free (error);
534 str = g_strndup (p, q - p);
535 if (!g_utf8_validate (str, -1, NULL))
537 g_warning ("Error converting selection from UTF8_STRING");
545 strings = g_slist_prepend (strings, str);
554 *list = g_new (gchar *, n_strings + 1);
555 (*list)[n_strings] = NULL;
563 (*list)[--i] = tmp_list->data;
565 g_free (tmp_list->data);
567 tmp_list = tmp_list->next;
570 g_slist_free (strings);
576 * gdk_text_property_to_utf8_list_for_display:
577 * @display: a #GdkDisplay
578 * @encoding: an atom representing the encoding of the text
579 * @format: the format of the property
580 * @text: the text to convert
581 * @length: the length of @text, in bytes
582 * @list: location to store the list of strings or %NULL. The
583 * list should be freed with g_strfreev().
585 * Converts a text property in the given encoding to
586 * a list of UTF-8 strings.
588 * Return value: the number of strings in the resulting
594 gdk_text_property_to_utf8_list_for_display (GdkDisplay *display,
601 g_return_val_if_fail (text != NULL, 0);
602 g_return_val_if_fail (length >= 0, 0);
603 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
605 if (encoding == GDK_TARGET_STRING)
607 return make_list ((gchar *)text, length, TRUE, list);
609 else if (encoding == gdk_atom_intern_static_string ("UTF8_STRING"))
611 return make_list ((gchar *)text, length, FALSE, list);
618 const gchar *charset = NULL;
619 gboolean need_conversion = !g_get_charset (&charset);
621 GError *error = NULL;
623 /* Probably COMPOUND text, we fall back to Xlib routines
625 local_count = gdk_text_property_to_text_list_for_display (display,
632 *list = g_new (gchar *, local_count + 1);
634 for (i=0; i<local_count; i++)
636 /* list contains stuff in our default encoding
640 gchar *utf = g_convert (local_list[i], -1,
646 (*list)[count++] = utf;
652 g_warning ("Error converting to UTF-8 from '%s': %s",
653 charset, error->message);
654 g_error_free (error);
662 if (g_utf8_validate (local_list[i], -1, NULL))
663 (*list)[count++] = g_strdup (local_list[i]);
665 g_warning ("Error converting selection");
671 gdk_free_text_list (local_list);
674 (*list)[count] = NULL;
681 * gdk_string_to_compound_text_for_display:
682 * @display: the #GdkDisplay where the encoding is defined.
683 * @str: a nul-terminated string.
684 * @encoding: location to store the encoding atom
685 * (to be used as the type for the property).
686 * @format: location to store the format of the property
687 * @ctext: location to store newly allocated data for the property.
688 * @length: the length of @text, in bytes
690 * Convert a string from the encoding of the current
691 * locale into a form suitable for storing in a window property.
693 * Returns: 0 upon success, non-zero upon failure.
698 gdk_string_to_compound_text_for_display (GdkDisplay *display,
706 XTextProperty property;
708 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
710 if (gdk_display_is_closed (display))
711 res = XLocaleNotSupported;
713 res = XmbTextListToTextProperty (GDK_DISPLAY_XDISPLAY (display),
714 (char **)&str, 1, XCompoundTextStyle,
718 property.encoding = None;
719 property.format = None;
720 property.value = NULL;
725 *encoding = gdk_x11_xatom_to_atom_for_display (display, property.encoding);
727 *format = property.format;
729 *ctext = property.value;
731 *length = property.nitems;
736 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
737 * C1 are not allowed except for \n and \t, however the X conversions
738 * routines for COMPOUND_TEXT only enforce this in one direction,
739 * causing cut-and-paste of \r and \r\n separated text to fail.
740 * This routine strips out all non-allowed C0 and C1 characters
741 * from the input string and also canonicalizes \r, and \r\n to \n
744 sanitize_utf8 (const gchar *src,
745 gboolean return_latin1)
747 gint len = strlen (src);
748 GString *result = g_string_sized_new (len);
749 const gchar *p = src;
759 g_string_append_c (result, '\n');
763 gunichar ch = g_utf8_get_char (p);
765 if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
770 g_string_append_c (result, ch);
772 g_string_append_printf (result,
773 ch < 0x10000 ? "\\u%04x" : "\\U%08x",
781 buflen = g_unichar_to_utf8 (ch, buf);
782 g_string_append_len (result, buf, buflen);
786 p = g_utf8_next_char (p);
790 return g_string_free (result, FALSE);
794 * gdk_utf8_to_string_target:
795 * @str: a UTF-8 string
797 * Converts an UTF-8 string into the best possible representation
798 * as a STRING. The representation of characters not in STRING
799 * is not specified; it may be as pseudo-escape sequences
800 * \x{ABCD}, or it may be in some other form of approximation.
802 * Return value: the newly-allocated string, or %NULL if the
803 * conversion failed. (It should not fail for
804 * any properly formed UTF-8 string unless system
805 * limits like memory or file descriptors are exceeded.)
808 gdk_utf8_to_string_target (const gchar *str)
810 return sanitize_utf8 (str, TRUE);
814 * gdk_utf8_to_compound_text_for_display:
815 * @display: a #GdkDisplay
816 * @str: a UTF-8 string
817 * @encoding: location to store resulting encoding
818 * @format: location to store format of the result
819 * @ctext: location to store the data of the result
820 * @length: location to store the length of the data
823 * Converts from UTF-8 to compound text.
825 * Return value: %TRUE if the conversion succeeded, otherwise
831 gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
838 gboolean need_conversion;
839 const gchar *charset;
840 gchar *locale_str, *tmp_str;
841 GError *error = NULL;
844 g_return_val_if_fail (str != NULL, FALSE);
845 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
847 need_conversion = !g_get_charset (&charset);
849 tmp_str = sanitize_utf8 (str, FALSE);
853 locale_str = g_convert (tmp_str, -1,
860 if (!(error->domain = G_CONVERT_ERROR &&
861 error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE))
863 g_warning ("Error converting from UTF-8 to '%s': %s",
864 charset, error->message);
866 g_error_free (error);
881 locale_str = tmp_str;
883 result = gdk_string_to_compound_text_for_display (display, locale_str,
886 result = (result == Success? TRUE : FALSE);
894 * gdk_free_compound_text:
895 * @ctext: The pointer stored in @ctext from a call to
896 * gdk_string_to_compound_text().
898 * Frees the data returned from gdk_string_to_compound_text().
900 void gdk_free_compound_text (guchar *ctext)