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/.
28 #include <X11/Xatom.h>
32 #include "gdkproperty.h"
33 #include "gdkselection.h"
34 #include "gdkprivate.h"
35 #include "gdkprivate-x11.h"
36 #include "gdkdisplay-x11.h"
38 typedef struct _OwnerInfo OwnerInfo;
47 static GSList *owner_list;
49 /* When a window is destroyed we check if it is the owner
50 * of any selections. This is somewhat inefficient, but
51 * owner_list is typically short, and it is a low memory,
55 _gdk_selection_window_destroyed (GdkWindow *window)
57 GSList *tmp_list = owner_list;
60 OwnerInfo *info = tmp_list->data;
61 tmp_list = tmp_list->next;
63 if (info->owner == window)
65 owner_list = g_slist_remove (owner_list, info);
71 /* We only pass through those SelectionClear events that actually
72 * reflect changes to the selection owner that we didn't make ourself.
75 _gdk_selection_filter_clear_event (XSelectionClearEvent *event)
77 GSList *tmp_list = owner_list;
78 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->display);
82 OwnerInfo *info = tmp_list->data;
84 if (gdk_drawable_get_display (info->owner) == display &&
85 info->selection == gdk_x11_xatom_to_atom_for_display (display, event->selection))
87 if ((GDK_DRAWABLE_XID (info->owner) == event->window &&
88 event->serial >= info->serial))
90 owner_list = g_slist_remove (owner_list, info);
97 tmp_list = tmp_list->next;
103 * gdk_selection_owner_set_for_display:
104 * @display : the #GdkDisplay.
105 * @owner : a GdkWindow or NULL to indicate that the the owner for
106 * the given should be unset.
107 * @selection : an atom identifying a selection.
108 * @time_ : timestamp to use when setting the selection.
109 * If this is older than the timestamp given last time the owner was
110 * set for the given selection, the request will be ignored.
111 * @send_event : if TRUE, and the new owner is different from the current
112 * owner, the current owner will be sent a SelectionClear event.
114 * Sets the #GdkWindow @owner as the current owner of the selection @selection.
116 * Returns : TRUE if the selection owner was succesfully changed to owner,
120 gdk_selection_owner_set_for_display (GdkDisplay *display,
132 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
139 if (GDK_WINDOW_DESTROYED (owner))
142 xdisplay = GDK_WINDOW_XDISPLAY (owner);
143 xwindow = GDK_WINDOW_XID (owner);
147 xdisplay = GDK_DISPLAY_XDISPLAY (display);
151 xselection = gdk_x11_atom_to_xatom_for_display (display, selection);
153 tmp_list = owner_list;
156 info = tmp_list->data;
157 if (info->selection == selection)
159 owner_list = g_slist_remove (owner_list, info);
163 tmp_list = tmp_list->next;
168 info = g_new (OwnerInfo, 1);
170 info->serial = NextRequest (GDK_WINDOW_XDISPLAY (owner));
171 info->selection = selection;
173 owner_list = g_slist_prepend (owner_list, info);
176 XSetSelectionOwner (xdisplay, xselection, xwindow, time);
178 return (XGetSelectionOwner (xdisplay, xselection) == xwindow);
182 * gdk_selection_owner_get_for_display :
183 * @display : a #GdkDisplay.
184 * @selection : an atom indentifying a selection.
186 * Determine the owner of the given selection.
188 * Note that the return value may be owned by a different
189 * process if a foreign window was previously created for that
190 * window, but a new foreign window will never be created by this call.
192 * Returns :if there is a selection owner for this window,
193 * and it is a window known to the current process, the GdkWindow that owns
194 * the selection, otherwise NULL.
198 gdk_selection_owner_get_for_display (GdkDisplay *display,
202 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
207 xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
208 gdk_x11_atom_to_xatom_for_display (display,
213 return gdk_window_lookup_for_display (display, xwindow);
217 gdk_selection_convert (GdkWindow *requestor,
224 if (GDK_WINDOW_DESTROYED (requestor))
227 display = GDK_WINDOW_DISPLAY (requestor);
229 XConvertSelection (GDK_WINDOW_XDISPLAY (requestor),
230 gdk_x11_atom_to_xatom_for_display (display, selection),
231 gdk_x11_atom_to_xatom_for_display (display, target),
232 gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property),
233 GDK_WINDOW_XID (requestor), time);
237 * gdk_selection_property_get:
238 * @requestor: the window on which the data is stored
239 * @data: location to store a pointer to the retrieved data.
240 If the retrieval failed, %NULL we be stored here, otherwise, it
241 will be non-%NULL and the returned data should be freed with g_free()
242 when you are finished using it. The length of the
243 allocated memory is one more than the the length
244 of the returned data, and the final byte will always
245 be zero, to ensure nul-termination of strings.
246 * @prop_type: location to store the type of the property.
247 * @prop_format: location to store the format of the property.
249 * Retrieves selection data that was stored by the selection
250 * data in response to a call to gdk_selection_convert(). This function
251 * will not be used by applications, who should use the #GtkClipboard
254 * Return value: the length of the retrieved data.
257 gdk_selection_property_get (GdkWindow *requestor,
264 gulong length = 0; /* Quiet GCC */
270 g_return_val_if_fail (requestor != NULL, 0);
271 g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
273 display = GDK_WINDOW_DISPLAY (requestor);
275 if (GDK_WINDOW_DESTROYED (requestor))
280 /* We can't delete the selection here, because it might be the INCR
281 protocol, in which case the client has to make sure they'll be
282 notified of PropertyChange events _before_ the property is deleted.
283 Otherwise there's no guarantee we'll win the race ... */
284 if (XGetWindowProperty (GDK_DRAWABLE_XDISPLAY (requestor),
285 GDK_DRAWABLE_XID (requestor),
286 gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property),
287 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False,
288 AnyPropertyType, &prop_type, &prop_format,
289 &nitems, &nbytes, &t) != Success)
292 if (prop_type != None)
295 *ret_type = gdk_x11_xatom_to_atom_for_display (display, prop_type);
297 *ret_format = prop_format;
299 if (prop_type == XA_ATOM ||
300 prop_type == gdk_x11_get_xatom_by_name_for_display (display, "ATOM_PAIR"))
302 Atom* atoms = (Atom*) t;
306 if (prop_format != 32)
310 length = sizeof (GdkAtom) * num_atom + 1;
314 *data = g_malloc (length);
315 (*data)[length - 1] = '\0';
316 atoms_dest = (GdkAtom *)(*data);
318 for (i=0; i < num_atom; i++)
319 atoms_dest[i] = gdk_x11_xatom_to_atom_for_display (display, atoms[i]);
330 length = sizeof(short) * nitems;
333 length = sizeof(long) * nitems;
336 g_assert_not_reached ();
340 /* Add on an extra byte to handle null termination. X guarantees
341 that t will be 1 longer than nitems and null terminated */
345 *data = g_memdup (t, length);
356 *ret_type = GDK_NONE;
366 * gdk_selection_send_notify_for_display:
367 * @display : the #GdkDisplay where @requestor is realized
368 * @requestor : window to which to deliver response.
369 * @selection : selection that was requested.
370 * @target : target that was selected.
371 * @property : property in which the selection owner stored the data,
372 * or GDK_NONE to indicate that the request was rejected.
373 * @time_ : timestamp.
375 * Send a response to SelectionRequest event.
378 gdk_selection_send_notify_for_display (GdkDisplay *display,
385 XSelectionEvent xevent;
387 g_return_if_fail (GDK_IS_DISPLAY (display));
389 xevent.type = SelectionNotify;
391 xevent.send_event = True;
392 xevent.requestor = requestor;
393 xevent.selection = gdk_x11_atom_to_xatom_for_display (display, selection);
394 xevent.target = gdk_x11_atom_to_xatom_for_display (display, target);
395 xevent.property = gdk_x11_atom_to_xatom_for_display (display, property);
398 _gdk_send_xevent (display, requestor, False, NoEventMask, (XEvent*) & xevent);
402 * gdk_text_property_to_text_list_for_display:
403 * @display: The #GdkDisplay where the encoding is defined.
404 * @encoding: an atom representing the encoding. The most
405 * common values for this are STRING, or COMPOUND_TEXT.
406 * This is value used as the type for the property.
407 * @format: the format of the property.
408 * @text: The text data.
409 * @length: The number of items to transform.
410 * @list: location to store a terminated array of strings in
411 * the encoding of the current locale. This array should be
412 * freed using gdk_free_text_list().
414 * Convert a text string from the encoding as it is stored
415 * in a property into an array of strings in the encoding of
416 * the current local. (The elements of the array represent the
417 * null-separated elements of the original text string.)
419 * Returns : the number of strings stored in list, or 0,
420 * if the conversion failed.
423 gdk_text_property_to_text_list_for_display (GdkDisplay *display,
430 XTextProperty property;
434 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
442 property.value = (guchar *)text;
443 property.encoding = gdk_x11_atom_to_xatom_for_display (display, encoding);
444 property.format = format;
445 property.nitems = length;
446 res = XmbTextPropertyToTextList (GDK_DISPLAY_XDISPLAY (display), &property,
447 &local_list, &count);
448 if (res == XNoMemory || res == XLocaleNotSupported || res == XConverterNotFound)
455 XFreeStringList (local_list);
462 gdk_free_text_list (gchar **list)
464 g_return_if_fail (list != NULL);
466 XFreeStringList (list);
470 make_list (const gchar *text,
475 GSList *strings = NULL;
478 const gchar *p = text;
481 GError *error = NULL;
483 while (p < text + length)
488 while (*q && q < text + length)
493 str = g_convert (p, q - p,
494 "UTF-8", "ISO-8859-1",
499 g_warning ("Error converting selection from STRING: %s",
501 g_error_free (error);
505 str = g_strndup (p, q - p);
509 strings = g_slist_prepend (strings, str);
517 *list = g_new (gchar *, n_strings + 1);
519 (*list)[n_strings] = NULL;
526 (*list)[--i] = tmp_list->data;
528 g_free (tmp_list->data);
530 tmp_list = tmp_list->next;
533 g_slist_free (strings);
539 * gdk_text_property_to_utf8_list_for_display:
540 * @display: a #GdkDisplay
541 * @encoding: an atom representing the encoding of the text
542 * @format: the format of the property
543 * @text: the text to convert
544 * @length: the length of @text, in bytes
545 * @list: location to store the list of strings or %NULL. The
546 * list should be freed with g_strfreev().
548 * Converts a text property in the giving encoding to
549 * a list of UTF-8 strings.
551 * Return value: the number of strings in the resulting
555 gdk_text_property_to_utf8_list_for_display (GdkDisplay *display,
562 g_return_val_if_fail (text != NULL, 0);
563 g_return_val_if_fail (length >= 0, 0);
564 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
566 if (encoding == GDK_TARGET_STRING)
568 return make_list ((gchar *)text, length, TRUE, list);
570 else if (encoding == gdk_atom_intern ("UTF8_STRING", FALSE))
572 return make_list ((gchar *)text, length, FALSE, list);
579 const gchar *charset = NULL;
580 gboolean need_conversion = !g_get_charset (&charset);
582 GError *error = NULL;
584 /* Probably COMPOUND text, we fall back to Xlib routines
586 local_count = gdk_text_property_to_text_list_for_display (display,
593 *list = g_new (gchar *, local_count + 1);
595 for (i=0; i<local_count; i++)
597 /* list contains stuff in our default encoding
601 gchar *utf = g_convert (local_list[i], -1,
607 (*list)[count++] = utf;
613 g_warning ("Error converting to UTF-8 from '%s': %s",
614 charset, error->message);
615 g_error_free (error);
622 (*list)[count++] = g_strdup (local_list[i]);
627 gdk_free_text_list (local_list);
629 (*list)[count] = NULL;
636 * gdk_string_to_compound_text_for_display:
637 * @display : the #GdkDisplay where the encoding is defined.
638 * @str : a null-terminated string.
639 * @encoding: location to store the encoding atom
640 * (to be used as the type for the property).
641 * @format: location to store the format of the property
642 * @ctext: location to store newly allocated data for the property.
643 * @length: the length of @text, in bytes
645 * Convert a string from the encoding of the current
646 * locale into a form suitable for storing in a window property.
648 * Returns : 0 upon sucess, non-zero upon failure.
651 gdk_string_to_compound_text_for_display (GdkDisplay *display,
659 XTextProperty property;
661 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
664 res = XLocaleNotSupported;
666 res = XmbTextListToTextProperty (GDK_DISPLAY_XDISPLAY (display),
667 (char **)&str, 1, XCompoundTextStyle,
671 property.encoding = None;
672 property.format = None;
673 property.value = NULL;
678 *encoding = gdk_x11_xatom_to_atom_for_display (display, property.encoding);
680 *format = property.format;
682 *ctext = property.value;
684 *length = property.nitems;
689 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
690 * C1 are not allowed except for \n and \t, however the X conversions
691 * routines for COMPOUND_TEXT only enforce this in one direction,
692 * causing cut-and-paste of \r and \r\n separated text to fail.
693 * This routine strips out all non-allowed C0 and C1 characters
694 * from the input string and also canonicalizes \r, and \r\n to \n
697 sanitize_utf8 (const gchar *src)
699 gint len = strlen (src);
700 GString *result = g_string_sized_new (len);
701 const gchar *p = src;
711 g_string_append_c (result, '\n');
715 gunichar ch = g_utf8_get_char (p);
719 if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
721 buflen = g_unichar_to_utf8 (ch, buf);
722 g_string_append_len (result, buf, buflen);
725 p = g_utf8_next_char (p);
729 return g_string_free (result, FALSE);
733 * gdk_utf8_to_string_target:
734 * @str: a UTF-8 string
736 * Converts an UTF-8 string into the best possible representation
737 * as a STRING. The representation of characters not in STRING
738 * is not specified; it may be as pseudo-escape sequences
739 * \x{ABCD}, or it may be in some other form of approximation.
741 * Return value: the newly-allocated string, or %NULL if the
742 * conversion failed. (It should not fail for
743 * any properly formed UTF-8 string unless system
744 * limits like memory or file descriptors are exceeded.)
747 gdk_utf8_to_string_target (const gchar *str)
749 GError *error = NULL;
751 gchar *tmp_str = sanitize_utf8 (str);
752 gchar *result = g_convert_with_fallback (tmp_str, -1,
753 "ISO-8859-1", "UTF-8",
754 NULL, NULL, NULL, &error);
757 g_warning ("Error converting from UTF-8 to STRING: %s",
759 g_error_free (error);
767 * gdk_utf8_to_compound_text_for_display:
768 * @display: a #GdkDisplay
769 * @str: a UTF-8 string
770 * @encoding: location to store resulting encoding
771 * @format: location to store format of the result
772 * @ctext: location to store the data of the result
773 * @length: location to store the length of the data
776 * Converts from UTF-8 to compound text.
778 * Return value: %TRUE if the conversion succeeded, otherwise
782 gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
789 gboolean need_conversion;
790 const gchar *charset;
791 gchar *locale_str, *tmp_str;
792 GError *error = NULL;
795 g_return_val_if_fail (str != NULL, FALSE);
796 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
798 need_conversion = !g_get_charset (&charset);
800 tmp_str = sanitize_utf8 (str);
804 locale_str = g_convert_with_fallback (tmp_str, -1,
806 NULL, NULL, NULL, &error);
811 g_warning ("Error converting from UTF-8 to '%s': %s",
812 charset, error->message);
813 g_error_free (error);
828 locale_str = tmp_str;
830 result = gdk_string_to_compound_text_for_display (display, locale_str,
833 result = (result == Success? TRUE : FALSE);
840 void gdk_free_compound_text (guchar *ctext)