]> Pileus Git - ~andy/gtk/blob - gdk/gdkproperty.c
Added a modular client-message-filter mechanism, that is used for the DND
[~andy/gtk] / gdk / gdkproperty.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 #include <X11/Xlib.h>
20 #include <X11/Xatom.h>
21 #include <string.h>
22 #include "gdk.h"
23 #include "gdkprivate.h"
24
25 GdkAtom
26 gdk_atom_intern (const gchar *atom_name,
27                  gint         only_if_exists)
28 {
29   GdkAtom retval;
30   static GHashTable *atom_hash = NULL;
31   
32   if (!atom_hash)
33     atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
34
35   retval = GPOINTER_TO_UINT (g_hash_table_lookup (atom_hash, atom_name));
36   if (!retval)
37     retval = XInternAtom (gdk_display, atom_name, only_if_exists);
38
39   return retval;
40 }
41
42 gchar *
43 gdk_atom_name (GdkAtom atom)
44 {
45   gchar *t;
46   gchar *name;
47   gint old_error_warnings;
48
49   /* If this atom doesn't exist, we'll die with an X error unless
50      we take precautions */
51
52   old_error_warnings = gdk_error_warnings;
53   gdk_error_warnings = 0;
54   gdk_error_code = 0;
55   t = XGetAtomName (gdk_display, atom);
56   gdk_error_warnings = old_error_warnings;
57
58   if (gdk_error_code == -1)
59     {
60       if (t)
61         XFree (t);
62
63       return NULL;
64     }
65   else
66     {
67       name = g_strdup (t);
68       if (t)
69         XFree (t);
70       
71       return name;
72     }
73 }
74
75 gint
76 gdk_property_get (GdkWindow   *window,
77                   GdkAtom      property,
78                   GdkAtom      type,
79                   gulong       offset,
80                   gulong       length,
81                   gint         pdelete,
82                   GdkAtom     *actual_property_type,
83                   gint        *actual_format_type,
84                   gint        *actual_length,
85                   guchar     **data)
86 {
87   Display *xdisplay;
88   Window xwindow;
89   Atom ret_prop_type;
90   gint ret_format;
91   gulong ret_nitems;
92   gulong ret_bytes_after;
93   gulong ret_length;
94   guchar *ret_data;
95
96   if (window)
97     {
98       GdkWindowPrivate *private;
99
100       private = (GdkWindowPrivate*) window;
101       if (private->destroyed)
102         return FALSE;
103
104       xdisplay = private->xdisplay;
105       xwindow = private->xwindow;
106     }
107   else
108     {
109       xdisplay = gdk_display;
110       xwindow = gdk_root_window;
111     }
112
113   ret_data = NULL;
114   XGetWindowProperty (xdisplay, xwindow, property,
115                       offset, (length + 3) / 4, pdelete,
116                       type, &ret_prop_type, &ret_format,
117                       &ret_nitems, &ret_bytes_after,
118                       &ret_data);
119
120   if ((ret_prop_type == None) && (ret_format == 0)) {
121     return FALSE;
122   }
123
124   if (actual_property_type)
125     *actual_property_type = ret_prop_type;
126   if (actual_format_type)
127     *actual_format_type = ret_format;
128
129   if ((type != AnyPropertyType) && (ret_prop_type != type))
130     {
131       gchar *rn, *pn;
132
133       XFree (ret_data);
134       rn = gdk_atom_name(ret_prop_type);
135       pn = gdk_atom_name(type);
136       g_warning("Couldn't match property type %s to %s\n", rn, pn);
137       g_free(rn); g_free(pn);
138       return FALSE;
139     }
140
141   /* FIXME: ignoring bytes_after could have very bad effects */
142
143   if (data)
144     {
145       switch (ret_format)
146         {
147         case 8:
148           ret_length = ret_nitems;
149           break;
150         case 16:
151           ret_length = 2 * ret_nitems;
152           break;
153         case 32:
154           ret_length = 4 * ret_nitems;
155           break;
156         default:
157           g_warning ("unknown property return format: %d", ret_format);
158           XFree (ret_data);
159           return FALSE;
160         }
161
162       *data = g_new (guchar, ret_length);
163       memcpy (*data, ret_data, ret_length);
164       if (actual_length)
165         *actual_length = ret_length;
166     }
167
168   XFree (ret_data);
169
170   return TRUE;
171 }
172
173 void
174 gdk_property_change (GdkWindow   *window,
175                      GdkAtom      property,
176                      GdkAtom      type,
177                      gint         format,
178                      GdkPropMode  mode,
179                      guchar      *data,
180                      gint         nelements)
181 {
182   Display *xdisplay;
183   Window xwindow;
184
185   if (window)
186     {
187       GdkWindowPrivate *private;
188
189       private = (GdkWindowPrivate*) window;
190       if (private->destroyed)
191         return;
192
193       xdisplay = private->xdisplay;
194       xwindow = private->xwindow;
195     }
196   else
197     {
198       xdisplay = gdk_display;
199       xwindow = gdk_root_window;
200     }
201
202   XChangeProperty (xdisplay, xwindow, property, type,
203                    format, mode, data, nelements);
204 }
205
206 void
207 gdk_property_delete (GdkWindow *window,
208                      GdkAtom    property)
209 {
210   Display *xdisplay;
211   Window xwindow;
212
213   if (window)
214     {
215       GdkWindowPrivate *private;
216
217       private = (GdkWindowPrivate*) window;
218       if (private->destroyed)
219         return;
220
221       xdisplay = private->xdisplay;
222       xwindow = private->xwindow;
223     }
224   else
225     {
226       xdisplay = gdk_display;
227       xwindow = gdk_root_window;
228     }
229
230   XDeleteProperty (xdisplay, xwindow, property);
231 }