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