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 <X11/Xatom.h>
33 #include "gdkproperty.h"
34 #include "gdkselection.h"
35 #include "gdkprivate.h"
36 #include "gdkprivate-x11.h"
37 #include "gdkdisplay-x11.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_drawable_get_display (info->owner) == display &&
87 info->selection == gdk_x11_xatom_to_atom_for_display (display, event->selection))
89 if ((GDK_DRAWABLE_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);
144 if (GDK_WINDOW_DESTROYED (owner))
147 xdisplay = GDK_WINDOW_XDISPLAY (owner);
148 xwindow = GDK_WINDOW_XID (owner);
152 xdisplay = GDK_DISPLAY_XDISPLAY (display);
156 xselection = gdk_x11_atom_to_xatom_for_display (display, selection);
158 tmp_list = owner_list;
161 info = tmp_list->data;
162 if (info->selection == selection)
164 owner_list = g_slist_remove (owner_list, info);
168 tmp_list = tmp_list->next;
173 info = g_new (OwnerInfo, 1);
175 info->serial = NextRequest (GDK_WINDOW_XDISPLAY (owner));
176 info->selection = selection;
178 owner_list = g_slist_prepend (owner_list, info);
181 XSetSelectionOwner (xdisplay, xselection, xwindow, time);
183 return (XGetSelectionOwner (xdisplay, xselection) == xwindow);
187 * gdk_selection_owner_get_for_display:
188 * @display: a #GdkDisplay.
189 * @selection: an atom indentifying a selection.
191 * Determine the owner of the given selection.
193 * Note that the return value may be owned by a different
194 * process if a foreign window was previously created for that
195 * window, but a new foreign window will never be created by this call.
197 * Returns: if there is a selection owner for this window, and it is a
198 * window known to the current process, the #GdkWindow that owns the
199 * selection, otherwise %NULL.
204 gdk_selection_owner_get_for_display (GdkDisplay *display,
209 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
210 g_return_val_if_fail (selection != GDK_NONE, NULL);
215 xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
216 gdk_x11_atom_to_xatom_for_display (display,
221 return gdk_window_lookup_for_display (display, xwindow);
225 gdk_selection_convert (GdkWindow *requestor,
232 g_return_if_fail (selection != GDK_NONE);
234 if (GDK_WINDOW_DESTROYED (requestor))
237 display = GDK_WINDOW_DISPLAY (requestor);
239 XConvertSelection (GDK_WINDOW_XDISPLAY (requestor),
240 gdk_x11_atom_to_xatom_for_display (display, selection),
241 gdk_x11_atom_to_xatom_for_display (display, target),
242 gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property),
243 GDK_WINDOW_XID (requestor), time);
247 * gdk_selection_property_get:
248 * @requestor: the window on which the data is stored
249 * @data: location to store a pointer to the retrieved data.
250 If the retrieval failed, %NULL we be stored here, otherwise, it
251 will be non-%NULL and the returned data should be freed with g_free()
252 when you are finished using it. The length of the
253 allocated memory is one more than the length
254 of the returned data, and the final byte will always
255 be zero, to ensure nul-termination of strings.
256 * @prop_type: location to store the type of the property.
257 * @prop_format: location to store the format of the property.
259 * Retrieves selection data that was stored by the selection
260 * data in response to a call to gdk_selection_convert(). This function
261 * will not be used by applications, who should use the #GtkClipboard
264 * Return value: the length of the retrieved data.
267 gdk_selection_property_get (GdkWindow *requestor,
274 gulong length = 0; /* Quiet GCC */
280 g_return_val_if_fail (requestor != NULL, 0);
281 g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
283 display = GDK_WINDOW_DISPLAY (requestor);
285 if (GDK_WINDOW_DESTROYED (requestor))
290 /* We can't delete the selection here, because it might be the INCR
291 protocol, in which case the client has to make sure they'll be
292 notified of PropertyChange events _before_ the property is deleted.
293 Otherwise there's no guarantee we'll win the race ... */
294 if (XGetWindowProperty (GDK_DRAWABLE_XDISPLAY (requestor),
295 GDK_DRAWABLE_XID (requestor),
296 gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property),
297 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False,
298 AnyPropertyType, &prop_type, &prop_format,
299 &nitems, &nbytes, &t) != Success)
302 if (prop_type != None)
305 *ret_type = gdk_x11_xatom_to_atom_for_display (display, prop_type);
307 *ret_format = prop_format;
309 if (prop_type == XA_ATOM ||
310 prop_type == gdk_x11_get_xatom_by_name_for_display (display, "ATOM_PAIR"))
312 Atom* atoms = (Atom*) t;
316 if (prop_format != 32)
320 length = sizeof (GdkAtom) * num_atom + 1;
324 *data = g_malloc (length);
325 (*data)[length - 1] = '\0';
326 atoms_dest = (GdkAtom *)(*data);
328 for (i=0; i < num_atom; i++)
329 atoms_dest[i] = gdk_x11_xatom_to_atom_for_display (display, atoms[i]);
340 length = sizeof(short) * nitems;
343 length = sizeof(long) * nitems;
346 g_assert_not_reached ();
350 /* Add on an extra byte to handle null termination. X guarantees
351 that t will be 1 longer than nitems and null terminated */
355 *data = g_memdup (t, length);
366 *ret_type = GDK_NONE;
376 * gdk_selection_send_notify_for_display:
377 * @display: the #GdkDisplay where @requestor is realized
378 * @requestor: window to which to deliver response.
379 * @selection: selection that was requested.
380 * @target: target that was selected.
381 * @property: property in which the selection owner stored the data,
382 * or %GDK_NONE to indicate that the request was rejected.
385 * Send a response to SelectionRequest event.
390 gdk_selection_send_notify_for_display (GdkDisplay *display,
391 GdkNativeWindow requestor,
397 XSelectionEvent xevent;
399 g_return_if_fail (GDK_IS_DISPLAY (display));
401 xevent.type = SelectionNotify;
403 xevent.send_event = True;
404 xevent.requestor = requestor;
405 xevent.selection = gdk_x11_atom_to_xatom_for_display (display, selection);
406 xevent.target = gdk_x11_atom_to_xatom_for_display (display, target);
407 if (property == GDK_NONE)
408 xevent.property = None;
410 xevent.property = gdk_x11_atom_to_xatom_for_display (display, property);
413 _gdk_send_xevent (display, requestor, False, NoEventMask, (XEvent*) & xevent);
417 * gdk_text_property_to_text_list_for_display:
418 * @display: The #GdkDisplay where the encoding is defined.
419 * @encoding: an atom representing the encoding. The most
420 * common values for this are STRING, or COMPOUND_TEXT.
421 * This is value used as the type for the property.
422 * @format: the format of the property.
423 * @text: The text data.
424 * @length: The number of items to transform.
425 * @list: location to store a terminated array of strings in
426 * the encoding of the current locale. This array should be
427 * freed using gdk_free_text_list().
429 * Convert a text string from the encoding as it is stored
430 * in a property into an array of strings in the encoding of
431 * the current locale. (The elements of the array represent the
432 * nul-separated elements of the original text string.)
434 * Returns: the number of strings stored in list, or 0,
435 * if the conversion failed.
440 gdk_text_property_to_text_list_for_display (GdkDisplay *display,
447 XTextProperty property;
451 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
459 property.value = (guchar *)text;
460 property.encoding = gdk_x11_atom_to_xatom_for_display (display, encoding);
461 property.format = format;
462 property.nitems = length;
463 res = XmbTextPropertyToTextList (GDK_DISPLAY_XDISPLAY (display), &property,
464 &local_list, &count);
465 if (res == XNoMemory || res == XLocaleNotSupported || res == XConverterNotFound)
472 XFreeStringList (local_list);
479 gdk_free_text_list (gchar **list)
481 g_return_if_fail (list != NULL);
483 XFreeStringList (list);
487 make_list (const gchar *text,
492 GSList *strings = NULL;
495 const gchar *p = text;
498 GError *error = NULL;
500 while (p < text + length)
505 while (*q && q < text + length)
510 str = g_convert (p, q - p,
511 "UTF-8", "ISO-8859-1",
516 g_warning ("Error converting selection from STRING: %s",
518 g_error_free (error);
523 str = g_strndup (p, q - p);
524 if (!g_utf8_validate (str, -1, NULL))
526 g_warning ("Error converting selection from UTF8_STRING");
534 strings = g_slist_prepend (strings, str);
543 *list = g_new (gchar *, n_strings + 1);
544 (*list)[n_strings] = NULL;
552 (*list)[--i] = tmp_list->data;
554 g_free (tmp_list->data);
556 tmp_list = tmp_list->next;
559 g_slist_free (strings);
565 * gdk_text_property_to_utf8_list_for_display:
566 * @display: a #GdkDisplay
567 * @encoding: an atom representing the encoding of the text
568 * @format: the format of the property
569 * @text: the text to convert
570 * @length: the length of @text, in bytes
571 * @list: location to store the list of strings or %NULL. The
572 * list should be freed with g_strfreev().
574 * Converts a text property in the given encoding to
575 * a list of UTF-8 strings.
577 * Return value: the number of strings in the resulting
583 gdk_text_property_to_utf8_list_for_display (GdkDisplay *display,
590 g_return_val_if_fail (text != NULL, 0);
591 g_return_val_if_fail (length >= 0, 0);
592 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
594 if (encoding == GDK_TARGET_STRING)
596 return make_list ((gchar *)text, length, TRUE, list);
598 else if (encoding == gdk_atom_intern_static_string ("UTF8_STRING"))
600 return make_list ((gchar *)text, length, FALSE, list);
607 const gchar *charset = NULL;
608 gboolean need_conversion = !g_get_charset (&charset);
610 GError *error = NULL;
612 /* Probably COMPOUND text, we fall back to Xlib routines
614 local_count = gdk_text_property_to_text_list_for_display (display,
621 *list = g_new (gchar *, local_count + 1);
623 for (i=0; i<local_count; i++)
625 /* list contains stuff in our default encoding
629 gchar *utf = g_convert (local_list[i], -1,
635 (*list)[count++] = utf;
641 g_warning ("Error converting to UTF-8 from '%s': %s",
642 charset, error->message);
643 g_error_free (error);
651 if (g_utf8_validate (local_list[i], -1, NULL))
652 (*list)[count++] = g_strdup (local_list[i]);
654 g_warning ("Error converting selection");
660 gdk_free_text_list (local_list);
663 (*list)[count] = NULL;
670 * gdk_string_to_compound_text_for_display:
671 * @display: the #GdkDisplay where the encoding is defined.
672 * @str: a nul-terminated string.
673 * @encoding: location to store the encoding atom
674 * (to be used as the type for the property).
675 * @format: location to store the format of the property
676 * @ctext: location to store newly allocated data for the property.
677 * @length: the length of @text, in bytes
679 * Convert a string from the encoding of the current
680 * locale into a form suitable for storing in a window property.
682 * Returns: 0 upon success, non-zero upon failure.
687 gdk_string_to_compound_text_for_display (GdkDisplay *display,
695 XTextProperty property;
697 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
700 res = XLocaleNotSupported;
702 res = XmbTextListToTextProperty (GDK_DISPLAY_XDISPLAY (display),
703 (char **)&str, 1, XCompoundTextStyle,
707 property.encoding = None;
708 property.format = None;
709 property.value = NULL;
714 *encoding = gdk_x11_xatom_to_atom_for_display (display, property.encoding);
716 *format = property.format;
718 *ctext = property.value;
720 *length = property.nitems;
725 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
726 * C1 are not allowed except for \n and \t, however the X conversions
727 * routines for COMPOUND_TEXT only enforce this in one direction,
728 * causing cut-and-paste of \r and \r\n separated text to fail.
729 * This routine strips out all non-allowed C0 and C1 characters
730 * from the input string and also canonicalizes \r, and \r\n to \n
733 sanitize_utf8 (const gchar *src,
734 gboolean return_latin1)
736 gint len = strlen (src);
737 GString *result = g_string_sized_new (len);
738 const gchar *p = src;
748 g_string_append_c (result, '\n');
752 gunichar ch = g_utf8_get_char (p);
754 if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
759 g_string_append_c (result, ch);
761 g_string_append_printf (result,
762 ch < 0x10000 ? "\\u%04x" : "\\U%08x",
770 buflen = g_unichar_to_utf8 (ch, buf);
771 g_string_append_len (result, buf, buflen);
775 p = g_utf8_next_char (p);
779 return g_string_free (result, FALSE);
783 * gdk_utf8_to_string_target:
784 * @str: a UTF-8 string
786 * Converts an UTF-8 string into the best possible representation
787 * as a STRING. The representation of characters not in STRING
788 * is not specified; it may be as pseudo-escape sequences
789 * \x{ABCD}, or it may be in some other form of approximation.
791 * Return value: the newly-allocated string, or %NULL if the
792 * conversion failed. (It should not fail for
793 * any properly formed UTF-8 string unless system
794 * limits like memory or file descriptors are exceeded.)
797 gdk_utf8_to_string_target (const gchar *str)
799 return sanitize_utf8 (str, TRUE);
803 * gdk_utf8_to_compound_text_for_display:
804 * @display: a #GdkDisplay
805 * @str: a UTF-8 string
806 * @encoding: location to store resulting encoding
807 * @format: location to store format of the result
808 * @ctext: location to store the data of the result
809 * @length: location to store the length of the data
812 * Converts from UTF-8 to compound text.
814 * Return value: %TRUE if the conversion succeeded, otherwise
820 gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
827 gboolean need_conversion;
828 const gchar *charset;
829 gchar *locale_str, *tmp_str;
830 GError *error = NULL;
833 g_return_val_if_fail (str != NULL, FALSE);
834 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
836 need_conversion = !g_get_charset (&charset);
838 tmp_str = sanitize_utf8 (str, FALSE);
842 locale_str = g_convert (tmp_str, -1,
849 if (!(error->domain = G_CONVERT_ERROR &&
850 error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE))
852 g_warning ("Error converting from UTF-8 to '%s': %s",
853 charset, error->message);
855 g_error_free (error);
870 locale_str = tmp_str;
872 result = gdk_string_to_compound_text_for_display (display, locale_str,
875 result = (result == Success? TRUE : FALSE);
882 void gdk_free_compound_text (guchar *ctext)
888 #define __GDK_SELECTION_X11_C__
889 #include "gdkaliasdef.c"