]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkselection-x11.c
[ Merges from gtk-1-2 ]
[~andy/gtk] / gdk / x11 / gdkselection-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /*
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/. 
25  */
26
27 #include <X11/Xlib.h>
28 #include <X11/Xatom.h>
29 #include <string.h>
30 #include "gdk.h"
31 #include "gdkprivate.h"
32 #include "gdkx.h"
33
34
35 gint
36 gdk_selection_owner_set (GdkWindow *owner,
37                          GdkAtom    selection,
38                          guint32    time,
39                          gint       send_event)
40 {
41   Display *xdisplay;
42   Window xwindow;
43
44   if (owner)
45     {
46       GdkWindowPrivate *private;
47
48       private = (GdkWindowPrivate*) owner;
49       if (private->destroyed)
50         return FALSE;
51
52       xdisplay = private->xdisplay;
53       xwindow = private->xwindow;
54     }
55   else
56     {
57       xdisplay = gdk_display;
58       xwindow = None;
59     }
60
61   XSetSelectionOwner (xdisplay, selection, xwindow, time);
62
63   return (XGetSelectionOwner (xdisplay, selection) == xwindow);
64 }
65
66 GdkWindow*
67 gdk_selection_owner_get (GdkAtom selection)
68 {
69   Window xwindow;
70
71   xwindow = XGetSelectionOwner (gdk_display, selection);
72   if (xwindow == None)
73     return NULL;
74
75   return gdk_window_lookup (xwindow);
76 }
77
78 void
79 gdk_selection_convert (GdkWindow *requestor,
80                        GdkAtom    selection,
81                        GdkAtom    target,
82                        guint32    time)
83 {
84   GdkWindowPrivate *private;
85
86   g_return_if_fail (requestor != NULL);
87
88   private = (GdkWindowPrivate*) requestor;
89   if (private->destroyed)
90     return;
91
92   XConvertSelection (private->xdisplay, selection, target,
93                      gdk_selection_property, private->xwindow, time);
94 }
95
96 gint
97 gdk_selection_property_get (GdkWindow  *requestor,
98                             guchar    **data,
99                             GdkAtom    *ret_type,
100                             gint       *ret_format)
101 {
102   GdkWindowPrivate *private;
103   gulong nitems;
104   gulong nbytes;
105   gulong length;
106   GdkAtom prop_type;
107   gint prop_format;
108   guchar *t = NULL;
109
110   g_return_val_if_fail (requestor != NULL, 0);
111
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 */
115
116   private = (GdkWindowPrivate*) requestor;
117   if (private->destroyed)
118     return 0;
119
120   t = NULL;
121   XGetWindowProperty (private->xdisplay, private->xwindow,
122                       gdk_selection_property, 0, 0, False,
123                       AnyPropertyType, &prop_type, &prop_format,
124                       &nitems, &nbytes, &t);
125
126   if (ret_type)
127     *ret_type = prop_type;
128   if (ret_format)
129     *ret_format = prop_format;
130
131   if (prop_type == None)
132     {
133       *data = NULL;
134       return 0;
135     }
136   
137   if (t)
138     {
139       XFree (t);
140       t = NULL;
141     }
142
143   /* Add on an extra byte to handle null termination.  X guarantees
144      that t will be 1 longer than nbytes and null terminated */
145   length = nbytes + 1;
146
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);
155
156   if (prop_type != None)
157     {
158       *data = g_new (guchar, length);
159       memcpy (*data, t, length);
160       if (t)
161         XFree (t);
162       return length-1;
163     }
164   else
165     {
166       *data = NULL;
167       return 0;
168     }
169 }
170
171
172 void
173 gdk_selection_send_notify (guint32  requestor,
174                            GdkAtom  selection,
175                            GdkAtom  target,
176                            GdkAtom  property,
177                            guint32  time)
178 {
179   XSelectionEvent xevent;
180
181   xevent.type = SelectionNotify;
182   xevent.serial = 0;
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;
189   xevent.time = time;
190
191   gdk_send_xevent (requestor, False, NoEventMask, (XEvent*) &xevent);
192 }
193
194 gint
195 gdk_text_property_to_text_list (GdkAtom encoding, gint format, 
196                              guchar *text, gint length,
197                              gchar ***list)
198 {
199   XTextProperty property;
200   gint count = 0;
201   gint res;
202
203   if (!list) 
204     return 0;
205
206   property.value = text;
207   property.encoding = encoding;
208   property.format = format;
209   property.nitems = length;
210   res = XmbTextPropertyToTextList (GDK_DISPLAY(), &property, list, &count);
211
212   if (res == XNoMemory || res == XLocaleNotSupported || 
213       res == XConverterNotFound)
214     return 0;
215   else
216     return count;
217 }
218
219 void
220 gdk_free_text_list (gchar **list)
221 {
222   g_return_if_fail (list != NULL);
223
224   XFreeStringList (list);
225 }
226
227 gint
228 gdk_string_to_compound_text (gchar *str,
229                              GdkAtom *encoding, gint *format,
230                              guchar **ctext, gint *length)
231 {
232   gint res;
233   XTextProperty property;
234
235   res = XmbTextListToTextProperty (GDK_DISPLAY(), 
236                                    &str, 1, XCompoundTextStyle,
237                                    &property);
238   if (res != Success)
239     {
240       property.encoding = None;
241       property.format = None;
242       property.value = NULL;
243       property.nitems = 0;
244     }
245
246   if (encoding)
247     *encoding = property.encoding;
248   if (format)
249     *format = property.format;
250   if (ctext)
251     *ctext = property.value;
252   if (length)
253     *length = property.nitems;
254
255   return res;
256 }
257
258 void gdk_free_compound_text (guchar *ctext)
259 {
260   if (ctext)
261     XFree (ctext);
262 }