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"
32 #include "gdkproperty.h"
33 #include "gdkprivate.h"
34 #include "gdkprivate-x11.h"
35 #include "gdkdisplay-x11.h"
38 #include <X11/Xatom.h>
42 typedef struct _OwnerInfo OwnerInfo;
51 static GSList *owner_list;
53 /* When a window is destroyed we check if it is the owner
54 * of any selections. This is somewhat inefficient, but
55 * owner_list is typically short, and it is a low memory,
59 _gdk_selection_window_destroyed (GdkWindow *window)
61 GSList *tmp_list = owner_list;
64 OwnerInfo *info = tmp_list->data;
65 tmp_list = tmp_list->next;
67 if (info->owner == window)
69 owner_list = g_slist_remove (owner_list, info);
75 /* We only pass through those SelectionClear events that actually
76 * reflect changes to the selection owner that we didn't make ourself.
79 _gdk_selection_filter_clear_event (XSelectionClearEvent *event)
81 GSList *tmp_list = owner_list;
82 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->display);
86 OwnerInfo *info = tmp_list->data;
88 if (gdk_window_get_display (info->owner) == display &&
89 info->selection == gdk_x11_xatom_to_atom_for_display (display, event->selection))
91 if ((GDK_DRAWABLE_XID (info->owner) == event->window &&
92 event->serial >= info->serial))
94 owner_list = g_slist_remove (owner_list, info);
101 tmp_list = tmp_list->next;
107 * gdk_selection_owner_set_for_display:
108 * @display: the #GdkDisplay.
109 * @owner: a #GdkWindow or %NULL to indicate that the owner for
110 * the given should be unset.
111 * @selection: an atom identifying a selection.
112 * @time_: timestamp to use when setting the selection.
113 * If this is older than the timestamp given last time the owner was
114 * set for the given selection, the request will be ignored.
115 * @send_event: if %TRUE, and the new owner is different from the current
116 * owner, the current owner will be sent a SelectionClear event.
118 * Sets the #GdkWindow @owner as the current owner of the selection @selection.
120 * Returns: %TRUE if the selection owner was successfully changed to owner,
126 gdk_selection_owner_set_for_display (GdkDisplay *display,
138 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
139 g_return_val_if_fail (selection != GDK_NONE, FALSE);
146 if (GDK_WINDOW_DESTROYED (owner) || !GDK_WINDOW_IS_X11 (owner))
149 gdk_window_ensure_native (owner);
150 xdisplay = GDK_WINDOW_XDISPLAY (owner);
151 xwindow = GDK_WINDOW_XID (owner);
155 xdisplay = GDK_DISPLAY_XDISPLAY (display);
159 xselection = gdk_x11_atom_to_xatom_for_display (display, selection);
161 tmp_list = owner_list;
164 info = tmp_list->data;
165 if (info->selection == selection)
167 owner_list = g_slist_remove (owner_list, info);
171 tmp_list = tmp_list->next;
176 info = g_new (OwnerInfo, 1);
178 info->serial = NextRequest (GDK_WINDOW_XDISPLAY (owner));
179 info->selection = selection;
181 owner_list = g_slist_prepend (owner_list, info);
184 XSetSelectionOwner (xdisplay, xselection, xwindow, time);
186 return (XGetSelectionOwner (xdisplay, xselection) == xwindow);
190 * gdk_selection_owner_get_for_display:
191 * @display: a #GdkDisplay.
192 * @selection: an atom indentifying a selection.
194 * Determine the owner of the given selection.
196 * Note that the return value may be owned by a different
197 * process if a foreign window was previously created for that
198 * window, but a new foreign window will never be created by this call.
200 * Returns: (transfer none): if there is a selection owner for this window,
201 * and it is a window known to the current process, the #GdkWindow that
202 * owns the selection, otherwise %NULL.
207 gdk_selection_owner_get_for_display (GdkDisplay *display,
212 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
213 g_return_val_if_fail (selection != GDK_NONE, NULL);
218 xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
219 gdk_x11_atom_to_xatom_for_display (display,
224 return gdk_window_lookup_for_display (display, xwindow);
228 gdk_selection_convert (GdkWindow *requestor,
235 g_return_if_fail (selection != GDK_NONE);
237 if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
240 gdk_window_ensure_native (requestor);
241 display = GDK_WINDOW_DISPLAY (requestor);
243 XConvertSelection (GDK_WINDOW_XDISPLAY (requestor),
244 gdk_x11_atom_to_xatom_for_display (display, selection),
245 gdk_x11_atom_to_xatom_for_display (display, target),
246 gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property),
247 GDK_WINDOW_XID (requestor), time);
251 * gdk_selection_property_get:
252 * @requestor: the window on which the data is stored
253 * @data: location to store a pointer to the retrieved data.
254 If the retrieval failed, %NULL we be stored here, otherwise, it
255 will be non-%NULL and the returned data should be freed with g_free()
256 when you are finished using it. The length of the
257 allocated memory is one more than the length
258 of the returned data, and the final byte will always
259 be zero, to ensure nul-termination of strings.
260 * @prop_type: location to store the type of the property.
261 * @prop_format: location to store the format of the property.
263 * Retrieves selection data that was stored by the selection
264 * data in response to a call to gdk_selection_convert(). This function
265 * will not be used by applications, who should use the #GtkClipboard
268 * Return value: the length of the retrieved data.
271 gdk_selection_property_get (GdkWindow *requestor,
278 gulong length = 0; /* Quiet GCC */
284 g_return_val_if_fail (requestor != NULL, 0);
285 g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
286 g_return_val_if_fail (GDK_WINDOW_IS_X11 (requestor), 0);
288 display = GDK_WINDOW_DISPLAY (requestor);
290 if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
295 /* We can't delete the selection here, because it might be the INCR
296 protocol, in which case the client has to make sure they'll be
297 notified of PropertyChange events _before_ the property is deleted.
298 Otherwise there's no guarantee we'll win the race ... */
299 if (XGetWindowProperty (GDK_DRAWABLE_XDISPLAY (requestor),
300 GDK_DRAWABLE_XID (requestor),
301 gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property),
302 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False,
303 AnyPropertyType, &prop_type, &prop_format,
304 &nitems, &nbytes, &t) != Success)
307 if (prop_type != None)
310 *ret_type = gdk_x11_xatom_to_atom_for_display (display, prop_type);
312 *ret_format = prop_format;
314 if (prop_type == XA_ATOM ||
315 prop_type == gdk_x11_get_xatom_by_name_for_display (display, "ATOM_PAIR"))
317 Atom* atoms = (Atom*) t;
321 if (prop_format != 32)
325 length = sizeof (GdkAtom) * num_atom + 1;
329 *data = g_malloc (length);
330 (*data)[length - 1] = '\0';
331 atoms_dest = (GdkAtom *)(*data);
333 for (i=0; i < num_atom; i++)
334 atoms_dest[i] = gdk_x11_xatom_to_atom_for_display (display, atoms[i]);
345 length = sizeof(short) * nitems;
348 length = sizeof(long) * nitems;
351 g_assert_not_reached ();
355 /* Add on an extra byte to handle null termination. X guarantees
356 that t will be 1 longer than nitems and null terminated */
360 *data = g_memdup (t, length);
371 *ret_type = GDK_NONE;
381 * gdk_selection_send_notify_for_display:
382 * @display: the #GdkDisplay where @requestor is realized
383 * @requestor: window to which to deliver response.
384 * @selection: selection that was requested.
385 * @target: target that was selected.
386 * @property: property in which the selection owner stored the data,
387 * or %GDK_NONE to indicate that the request was rejected.
390 * Send a response to SelectionRequest event.
395 gdk_selection_send_notify_for_display (GdkDisplay *display,
396 GdkNativeWindow requestor,
402 XSelectionEvent xevent;
404 g_return_if_fail (GDK_IS_DISPLAY (display));
406 xevent.type = SelectionNotify;
408 xevent.send_event = True;
409 xevent.requestor = requestor;
410 xevent.selection = gdk_x11_atom_to_xatom_for_display (display, selection);
411 xevent.target = gdk_x11_atom_to_xatom_for_display (display, target);
412 if (property == GDK_NONE)
413 xevent.property = None;
415 xevent.property = gdk_x11_atom_to_xatom_for_display (display, property);
418 _gdk_send_xevent (display, requestor, False, NoEventMask, (XEvent*) & xevent);
422 * gdk_text_property_to_text_list_for_display:
423 * @display: The #GdkDisplay where the encoding is defined.
424 * @encoding: an atom representing the encoding. The most
425 * common values for this are STRING, or COMPOUND_TEXT.
426 * This is value used as the type for the property.
427 * @format: the format of the property.
428 * @text: The text data.
429 * @length: The number of items to transform.
430 * @list: location to store a terminated array of strings in
431 * the encoding of the current locale. This array should be
432 * freed using gdk_free_text_list().
434 * Convert a text string from the encoding as it is stored
435 * in a property into an array of strings in the encoding of
436 * the current locale. (The elements of the array represent the
437 * nul-separated elements of the original text string.)
439 * Returns: the number of strings stored in list, or 0,
440 * if the conversion failed.
445 gdk_text_property_to_text_list_for_display (GdkDisplay *display,
452 XTextProperty property;
456 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
464 property.value = (guchar *)text;
465 property.encoding = gdk_x11_atom_to_xatom_for_display (display, encoding);
466 property.format = format;
467 property.nitems = length;
468 res = XmbTextPropertyToTextList (GDK_DISPLAY_XDISPLAY (display), &property,
469 &local_list, &count);
470 if (res == XNoMemory || res == XLocaleNotSupported || res == XConverterNotFound)
477 XFreeStringList (local_list);
484 * gdk_free_text_list:
485 * @list: the value stored in the @list parameter by
486 * a call to gdk_text_property_to_text_list().
488 * Frees the array of strings created by
489 * gdk_text_property_to_text_list().
492 gdk_free_text_list (gchar **list)
494 g_return_if_fail (list != NULL);
496 XFreeStringList (list);
500 make_list (const gchar *text,
505 GSList *strings = NULL;
508 const gchar *p = text;
511 GError *error = NULL;
513 while (p < text + length)
518 while (*q && q < text + length)
523 str = g_convert (p, q - p,
524 "UTF-8", "ISO-8859-1",
529 g_warning ("Error converting selection from STRING: %s",
531 g_error_free (error);
536 str = g_strndup (p, q - p);
537 if (!g_utf8_validate (str, -1, NULL))
539 g_warning ("Error converting selection from UTF8_STRING");
547 strings = g_slist_prepend (strings, str);
556 *list = g_new (gchar *, n_strings + 1);
557 (*list)[n_strings] = NULL;
565 (*list)[--i] = tmp_list->data;
567 g_free (tmp_list->data);
569 tmp_list = tmp_list->next;
572 g_slist_free (strings);
578 * gdk_text_property_to_utf8_list_for_display:
579 * @display: a #GdkDisplay
580 * @encoding: an atom representing the encoding of the text
581 * @format: the format of the property
582 * @text: the text to convert
583 * @length: the length of @text, in bytes
584 * @list: location to store the list of strings or %NULL. The
585 * list should be freed with g_strfreev().
587 * Converts a text property in the given encoding to
588 * a list of UTF-8 strings.
590 * Return value: the number of strings in the resulting
596 gdk_text_property_to_utf8_list_for_display (GdkDisplay *display,
603 g_return_val_if_fail (text != NULL, 0);
604 g_return_val_if_fail (length >= 0, 0);
605 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
607 if (encoding == GDK_TARGET_STRING)
609 return make_list ((gchar *)text, length, TRUE, list);
611 else if (encoding == gdk_atom_intern_static_string ("UTF8_STRING"))
613 return make_list ((gchar *)text, length, FALSE, list);
620 const gchar *charset = NULL;
621 gboolean need_conversion = !g_get_charset (&charset);
623 GError *error = NULL;
625 /* Probably COMPOUND text, we fall back to Xlib routines
627 local_count = gdk_text_property_to_text_list_for_display (display,
634 *list = g_new (gchar *, local_count + 1);
636 for (i=0; i<local_count; i++)
638 /* list contains stuff in our default encoding
642 gchar *utf = g_convert (local_list[i], -1,
648 (*list)[count++] = utf;
654 g_warning ("Error converting to UTF-8 from '%s': %s",
655 charset, error->message);
656 g_error_free (error);
664 if (g_utf8_validate (local_list[i], -1, NULL))
665 (*list)[count++] = g_strdup (local_list[i]);
667 g_warning ("Error converting selection");
673 gdk_free_text_list (local_list);
676 (*list)[count] = NULL;
683 * gdk_string_to_compound_text_for_display:
684 * @display: the #GdkDisplay where the encoding is defined.
685 * @str: a nul-terminated string.
686 * @encoding: location to store the encoding atom
687 * (to be used as the type for the property).
688 * @format: location to store the format of the property
689 * @ctext: location to store newly allocated data for the property.
690 * @length: the length of @text, in bytes
692 * Convert a string from the encoding of the current
693 * locale into a form suitable for storing in a window property.
695 * Returns: 0 upon success, non-zero upon failure.
700 gdk_string_to_compound_text_for_display (GdkDisplay *display,
708 XTextProperty property;
710 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
713 res = XLocaleNotSupported;
715 res = XmbTextListToTextProperty (GDK_DISPLAY_XDISPLAY (display),
716 (char **)&str, 1, XCompoundTextStyle,
720 property.encoding = None;
721 property.format = None;
722 property.value = NULL;
727 *encoding = gdk_x11_xatom_to_atom_for_display (display, property.encoding);
729 *format = property.format;
731 *ctext = property.value;
733 *length = property.nitems;
738 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
739 * C1 are not allowed except for \n and \t, however the X conversions
740 * routines for COMPOUND_TEXT only enforce this in one direction,
741 * causing cut-and-paste of \r and \r\n separated text to fail.
742 * This routine strips out all non-allowed C0 and C1 characters
743 * from the input string and also canonicalizes \r, and \r\n to \n
746 sanitize_utf8 (const gchar *src,
747 gboolean return_latin1)
749 gint len = strlen (src);
750 GString *result = g_string_sized_new (len);
751 const gchar *p = src;
761 g_string_append_c (result, '\n');
765 gunichar ch = g_utf8_get_char (p);
767 if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
772 g_string_append_c (result, ch);
774 g_string_append_printf (result,
775 ch < 0x10000 ? "\\u%04x" : "\\U%08x",
783 buflen = g_unichar_to_utf8 (ch, buf);
784 g_string_append_len (result, buf, buflen);
788 p = g_utf8_next_char (p);
792 return g_string_free (result, FALSE);
796 * gdk_utf8_to_string_target:
797 * @str: a UTF-8 string
799 * Converts an UTF-8 string into the best possible representation
800 * as a STRING. The representation of characters not in STRING
801 * is not specified; it may be as pseudo-escape sequences
802 * \x{ABCD}, or it may be in some other form of approximation.
804 * Return value: the newly-allocated string, or %NULL if the
805 * conversion failed. (It should not fail for
806 * any properly formed UTF-8 string unless system
807 * limits like memory or file descriptors are exceeded.)
810 gdk_utf8_to_string_target (const gchar *str)
812 return sanitize_utf8 (str, TRUE);
816 * gdk_utf8_to_compound_text_for_display:
817 * @display: a #GdkDisplay
818 * @str: a UTF-8 string
819 * @encoding: location to store resulting encoding
820 * @format: location to store format of the result
821 * @ctext: location to store the data of the result
822 * @length: location to store the length of the data
825 * Converts from UTF-8 to compound text.
827 * Return value: %TRUE if the conversion succeeded, otherwise
833 gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
840 gboolean need_conversion;
841 const gchar *charset;
842 gchar *locale_str, *tmp_str;
843 GError *error = NULL;
846 g_return_val_if_fail (str != NULL, FALSE);
847 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
849 need_conversion = !g_get_charset (&charset);
851 tmp_str = sanitize_utf8 (str, FALSE);
855 locale_str = g_convert (tmp_str, -1,
862 if (!(error->domain = G_CONVERT_ERROR &&
863 error->code == G_CONVERT_ERROR_ILLEGAL_SEQUENCE))
865 g_warning ("Error converting from UTF-8 to '%s': %s",
866 charset, error->message);
868 g_error_free (error);
883 locale_str = tmp_str;
885 result = gdk_string_to_compound_text_for_display (display, locale_str,
888 result = (result == Success? TRUE : FALSE);
896 * gdk_free_compound_text:
897 * @ctext: The pointer stored in @ctext from a call to
898 * gdk_string_to_compound_text().
900 * Frees the data returned from gdk_string_to_compound_text().
902 void gdk_free_compound_text (guchar *ctext)