]> Pileus Git - ~andy/gtk/blob - gdk/gdkselection.c
Started
[~andy/gtk] / gdk / gdkselection.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
31 #include "gdkproperty.h"
32 #include "gdkselection.h"
33 #include "gdkprivate.h"
34 #include "gdkx.h"
35
36
37 gint
38 gdk_selection_owner_set (GdkWindow *owner,
39                          GdkAtom    selection,
40                          guint32    time,
41                          gint       send_event)
42 {
43   Display *xdisplay;
44   Window xwindow;
45
46   if (owner)
47     {
48       GdkWindowPrivate *private;
49
50       private = (GdkWindowPrivate*) owner;
51       if (private->destroyed)
52         return FALSE;
53
54       xdisplay = private->xdisplay;
55       xwindow = private->xwindow;
56     }
57   else
58     {
59       xdisplay = gdk_display;
60       xwindow = None;
61     }
62
63   XSetSelectionOwner (xdisplay, selection, xwindow, time);
64
65   return (XGetSelectionOwner (xdisplay, selection) == xwindow);
66 }
67
68 GdkWindow*
69 gdk_selection_owner_get (GdkAtom selection)
70 {
71   Window xwindow;
72
73   xwindow = XGetSelectionOwner (gdk_display, selection);
74   if (xwindow == None)
75     return NULL;
76
77   return gdk_window_lookup (xwindow);
78 }
79
80 void
81 gdk_selection_convert (GdkWindow *requestor,
82                        GdkAtom    selection,
83                        GdkAtom    target,
84                        guint32    time)
85 {
86   GdkWindowPrivate *private;
87
88   g_return_if_fail (requestor != NULL);
89
90   private = (GdkWindowPrivate*) requestor;
91   if (private->destroyed)
92     return;
93
94   XConvertSelection (private->xdisplay, selection, target,
95                      gdk_selection_property, private->xwindow, time);
96 }
97
98 gint
99 gdk_selection_property_get (GdkWindow  *requestor,
100                             guchar    **data,
101                             GdkAtom    *ret_type,
102                             gint       *ret_format)
103 {
104   GdkWindowPrivate *private;
105   gulong nitems;
106   gulong nbytes;
107   gulong length;
108   GdkAtom prop_type;
109   gint prop_format;
110   guchar *t = NULL;
111
112   g_return_val_if_fail (requestor != NULL, 0);
113
114   /* If retrieved chunks are typically small, (and the ICCCM says the
115      should be) it would be a win to try first with a buffer of
116      moderate length, to avoid two round trips to the server */
117
118   private = (GdkWindowPrivate*) requestor;
119   if (private->destroyed)
120     return 0;
121
122   t = NULL;
123   XGetWindowProperty (private->xdisplay, private->xwindow,
124                       gdk_selection_property, 0, 0, False,
125                       AnyPropertyType, &prop_type, &prop_format,
126                       &nitems, &nbytes, &t);
127
128   if (ret_type)
129     *ret_type = prop_type;
130   if (ret_format)
131     *ret_format = prop_format;
132
133   if (prop_type == None)
134     {
135       *data = NULL;
136       return 0;
137     }
138   
139   if (t)
140     {
141       XFree (t);
142       t = NULL;
143     }
144
145   /* Add on an extra byte to handle null termination.  X guarantees
146      that t will be 1 longer than nbytes and null terminated */
147   length = nbytes + 1;
148
149   /* We can't delete the selection here, because it might be the INCR
150      protocol, in which case the client has to make sure they'll be
151      notified of PropertyChange events _before_ the property is deleted.
152      Otherwise there's no guarantee we'll win the race ... */
153   XGetWindowProperty (private->xdisplay, private->xwindow,
154                       gdk_selection_property, 0, (nbytes + 3) / 4, False,
155                       AnyPropertyType, &prop_type, &prop_format,
156                       &nitems, &nbytes, &t);
157
158   if (prop_type != None)
159     {
160       *data = g_new (guchar, length);
161       memcpy (*data, t, length);
162       if (t)
163         XFree (t);
164       return length-1;
165     }
166   else
167     {
168       *data = NULL;
169       return 0;
170     }
171 }
172
173
174 void
175 gdk_selection_send_notify (guint32  requestor,
176                            GdkAtom  selection,
177                            GdkAtom  target,
178                            GdkAtom  property,
179                            guint32  time)
180 {
181   XSelectionEvent xevent;
182
183   xevent.type = SelectionNotify;
184   xevent.serial = 0;
185   xevent.send_event = True;
186   xevent.display = gdk_display;
187   xevent.requestor = requestor;
188   xevent.selection = selection;
189   xevent.target = target;
190   xevent.property = property;
191   xevent.time = time;
192
193   gdk_send_xevent (requestor, False, NoEventMask, (XEvent*) &xevent);
194 }
195
196 gint
197 gdk_text_property_to_text_list (GdkAtom encoding, gint format, 
198                              guchar *text, gint length,
199                              gchar ***list)
200 {
201   XTextProperty property;
202   gint count = 0;
203   gint res;
204
205   if (!list) 
206     return 0;
207
208   property.value = text;
209   property.encoding = encoding;
210   property.format = format;
211   property.nitems = length;
212   res = XmbTextPropertyToTextList (GDK_DISPLAY(), &property, list, &count);
213
214   if (res == XNoMemory || res == XLocaleNotSupported || 
215       res == XConverterNotFound)
216     return 0;
217   else
218     return count;
219 }
220
221 void
222 gdk_free_text_list (gchar **list)
223 {
224   g_return_if_fail (list != NULL);
225
226   XFreeStringList (list);
227 }
228
229 gint
230 gdk_string_to_compound_text (gchar *str,
231                              GdkAtom *encoding, gint *format,
232                              guchar **ctext, gint *length)
233 {
234   gint res;
235   XTextProperty property;
236
237   res = XmbTextListToTextProperty (GDK_DISPLAY(), 
238                                    &str, 1, XCompoundTextStyle,
239                                    &property);
240   if (res != Success)
241     {
242       property.encoding = None;
243       property.format = None;
244       property.value = NULL;
245       property.nitems = 0;
246     }
247
248   if (encoding)
249     *encoding = property.encoding;
250   if (format)
251     *format = property.format;
252   if (ctext)
253     *ctext = property.value;
254   if (length)
255     *length = property.nitems;
256
257   return res;
258 }
259
260 void gdk_free_compound_text (guchar *ctext)
261 {
262   if (ctext)
263     XFree (ctext);
264 }