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 Library 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
* Library General Public License for more details.
14
* You should have received a copy of the GNU Library 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-1999. 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>
31
#include "gdkprivate.h"
36
gdk_selection_owner_set (GdkWindow *owner,
46
GdkWindowPrivate *private;
48
private = (GdkWindowPrivate*) owner;
49
if (private->destroyed)
52
xdisplay = private->xdisplay;
53
xwindow = private->xwindow;
57
xdisplay = gdk_display;
61
XSetSelectionOwner (xdisplay, selection, xwindow, time);
63
return (XGetSelectionOwner (xdisplay, selection) == xwindow);
67
gdk_selection_owner_get (GdkAtom selection)
71
xwindow = XGetSelectionOwner (gdk_display, selection);
75
return gdk_window_lookup (xwindow);
79
gdk_selection_convert (GdkWindow *requestor,
84
GdkWindowPrivate *private;
86
g_return_if_fail (requestor != NULL);
88
private = (GdkWindowPrivate*) requestor;
89
if (private->destroyed)
92
XConvertSelection (private->xdisplay, selection, target,
93
gdk_selection_property, private->xwindow, time);
97
gdk_selection_property_get (GdkWindow *requestor,
102
GdkWindowPrivate *private;
110
g_return_val_if_fail (requestor != NULL, 0);
112
/* If retrieved chunks are typically small, (and the ICCCM says the
113
should be) it would be a win to try first with a buffer of
114
moderate length, to avoid two round trips to the server */
116
private = (GdkWindowPrivate*) requestor;
117
if (private->destroyed)
121
XGetWindowProperty (private->xdisplay, private->xwindow,
122
gdk_selection_property, 0, 0, False,
123
AnyPropertyType, &prop_type, &prop_format,
124
&nitems, &nbytes, &t);
127
*ret_type = prop_type;
129
*ret_format = prop_format;
131
if (prop_type == None)
143
/* Add on an extra byte to handle null termination. X guarantees
144
that t will be 1 longer than nbytes and null terminated */
147
/* We can't delete the selection here, because it might be the INCR
148
protocol, in which case the client has to make sure they'll be
149
notified of PropertyChange events _before_ the property is deleted.
150
Otherwise there's no guarantee we'll win the race ... */
151
XGetWindowProperty (private->xdisplay, private->xwindow,
152
gdk_selection_property, 0, (nbytes + 3) / 4, False,
153
AnyPropertyType, &prop_type, &prop_format,
154
&nitems, &nbytes, &t);
156
if (prop_type != None)
158
*data = g_new (guchar, length);
159
memcpy (*data, t, length);
173
gdk_selection_send_notify (guint32 requestor,
179
XSelectionEvent xevent;
181
xevent.type = SelectionNotify;
183
xevent.send_event = True;
184
xevent.display = gdk_display;
185
xevent.requestor = requestor;
186
xevent.selection = selection;
187
xevent.target = target;
188
xevent.property = property;
191
gdk_send_xevent (requestor, False, NoEventMask, (XEvent*) &xevent);
195
/* The output of XmbTextPropertyToTextList may include stuff not valid
196
* for COMPOUND_TEXT. This routine tries to correct this by:
198
* a) Canonicalizing CR LF and CR to LF
199
* b) Stripping out all other non-allowed control characters
201
* See the COMPOUND_TEXT spec distributed with X for explanations
205
sanitize_ctext (const char *str,
208
gchar *result = g_malloc (*length + 1);
211
const guchar *ustr = (const guchar *)str;
213
for (i=0; i < *length; i++)
219
result[out_length++] = '\n';
220
if (i + 1 < *length && ustr[i + 1] == '\n')
223
else if (c == 27 /* ESC */)
225
/* Check for "extended segments, which can contain arbitrary
226
* octets. See CTEXT spec, section 6.
229
if (i + 5 < *length &&
230
ustr[i + 1] == '%' &&
231
ustr[i + 2] == '/' &&
232
(ustr[i + 3] >= 48 && ustr[i + 3] <= 52) &&
233
ustr[i + 4] >= 128 &&
236
int extra_len = 6 + (ustr[i + 4] - 128) * 128 + ustr[i + 5] - 128;
237
extra_len = MAX (extra_len, *length - i);
239
memcpy (result + out_length, ustr + i, extra_len);
240
out_length += extra_len;
244
result[out_length++] = c;
246
else if (c == '\n' || c == '\t' || c == 27 /* ESC */ ||
247
(c >= 32 && c <= 127) || /* GL */
248
c == 155 /* CONTROL SEQUENCE INTRODUCER */ ||
249
(c >= 160 && c <= 255)) /* GR */
251
result[out_length++] = c;
255
result[out_length] = '\0';
256
*length = out_length;
262
gdk_text_property_to_text_list (GdkAtom encoding, gint format,
263
guchar *text, gint length,
266
XTextProperty property;
269
gchar *sanitized_text = NULL;
274
property.encoding = encoding;
275
property.format = format;
277
if (encoding == gdk_atom_intern ("COMPOUND_TEXT", FALSE) && format == 8)
279
gint sanitized_text_length = length;
281
property.value = sanitized_text = sanitize_ctext (text, &sanitized_text_length);
282
property.nitems = sanitized_text_length;
286
property.value = text;
287
property.nitems = length;
290
res = XmbTextPropertyToTextList (GDK_DISPLAY(), &property, list, &count);
293
g_free (sanitized_text);
295
if (res == XNoMemory || res == XLocaleNotSupported ||
296
res == XConverterNotFound)
303
gdk_free_text_list (gchar **list)
305
g_return_if_fail (list != NULL);
307
XFreeStringList (list);
311
gdk_string_to_compound_text (const gchar *str,
312
GdkAtom *encoding, gint *format,
313
guchar **ctext, gint *length)
316
XTextProperty property;
317
gint sanitized_text_length;
318
gchar *sanitized_text;
320
res = XmbTextListToTextProperty (GDK_DISPLAY(),
321
(char **)&str, 1, XCompoundTextStyle,
325
property.encoding = None;
326
property.format = None;
327
property.value = NULL;
331
g_assert (property.encoding == gdk_atom_intern ("COMPOUND_TEXT", FALSE) && property.format == 8);
334
*encoding = property.encoding;
336
*format = property.format;
338
sanitized_text_length = property.nitems;
339
sanitized_text = sanitize_ctext (property.value, &sanitized_text_length);
342
*ctext = sanitized_text;
344
g_free (sanitized_text);
347
*length = sanitized_text_length;
350
XFree (property.value);
355
void gdk_free_compound_text (guchar *ctext)