]> git.decadent.org.uk Git - ion3.git/blob - ioncore/property.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[ion3.git] / ioncore / property.c
1 /*
2  * ion/ioncore/property.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <X11/Xmd.h>
10 #include <string.h>
11
12 #include "common.h"
13 #include "property.h"
14 #include "global.h"
15
16
17 /*{{{ Primitives */
18
19
20 static ulong xwindow_get_property_(Window win, Atom atom, Atom type, 
21                                    ulong n32expected, bool more, uchar **p,
22                                    int *format)
23 {
24     Atom real_type;
25     ulong n=-1, extra=0;
26     int status;
27     
28     do{
29         status=XGetWindowProperty(ioncore_g.dpy, win, atom, 0L, n32expected, 
30                                   False, type, &real_type, format, &n,
31                                   &extra, p);
32         
33         if(status!=Success || *p==NULL)
34             return -1;
35     
36         if(extra==0 || !more)
37             break;
38         
39         XFree((void*)*p);
40         n32expected+=(extra+4)/4;
41         more=FALSE;
42     }while(1);
43
44     if(n==0){
45         XFree((void*)*p);
46         *p=NULL;
47         return -1;
48     }
49     
50     return n;
51 }
52
53
54 ulong xwindow_get_property(Window win, Atom atom, Atom type, 
55                            ulong n32expected, bool more, uchar **p)
56 {
57     int format=0;
58     return xwindow_get_property_(win, atom, type, n32expected, more, p, 
59                                  &format);
60 }
61
62
63 /*}}}*/
64
65
66 /*{{{ String property stuff */
67
68
69 char *xwindow_get_string_property(Window win, Atom a, int *nret)
70 {
71     char *p;
72     int n;
73     
74     n=xwindow_get_property(win, a, XA_STRING, 64L, TRUE, (uchar**)&p);
75     
76     if(nret!=NULL)
77         *nret=n;
78     
79     return (n<=0 ? NULL : p);
80 }
81
82
83 void xwindow_set_string_property(Window win, Atom a, const char *value)
84 {
85     if(value==NULL){
86         XDeleteProperty(ioncore_g.dpy, win, a);
87     }else{
88         XChangeProperty(ioncore_g.dpy, win, a, XA_STRING,
89                         8, PropModeReplace, (uchar*)value, strlen(value));
90     }
91 }
92
93
94 /*}}}*/
95
96
97 /*{{{ Integer property stuff */
98
99
100 bool xwindow_get_integer_property(Window win, Atom a, int *vret)
101 {
102     long *p=NULL;
103     ulong n;
104     
105     n=xwindow_get_property(win, a, XA_INTEGER, 1L, FALSE, (uchar**)&p);
106     
107     if(n>0 && p!=NULL){
108         *vret=*p;
109         XFree((void*)p);
110         return TRUE;
111     }
112     
113     return FALSE;
114 }
115
116
117 void xwindow_set_integer_property(Window win, Atom a, int value)
118 {
119     CARD32 data[2];
120     
121     data[0]=value;
122     
123     XChangeProperty(ioncore_g.dpy, win, a, XA_INTEGER,
124                     32, PropModeReplace, (uchar*)data, 1);
125 }
126
127
128 /* WM_STATE
129  */
130
131 bool xwindow_get_state_property(Window win, int *state)
132 {
133     CARD32 *p=NULL;
134     
135     if(xwindow_get_property(win, ioncore_g.atom_wm_state, 
136                             ioncore_g.atom_wm_state, 
137                             2L, FALSE, (uchar**)&p)<=0)
138         return FALSE;
139     
140     *state=*p;
141     
142     XFree((void*)p);
143     
144     return TRUE;
145 }
146
147
148 void xwindow_set_state_property(Window win, int state)
149 {
150     CARD32 data[2];
151     
152     data[0]=state;
153     data[1]=None;
154     
155     XChangeProperty(ioncore_g.dpy, win,
156                     ioncore_g.atom_wm_state, ioncore_g.atom_wm_state,
157                     32, PropModeReplace, (uchar*)data, 2);
158 }
159
160
161 /*}}}*/
162
163
164 /*{{{ Text property stuff */
165
166
167 char **xwindow_get_text_property(Window win, Atom a, int *nret)
168 {
169     XTextProperty prop;
170     char **list=NULL;
171     int n=0;
172     Status st=0;
173     
174     st=XGetTextProperty(ioncore_g.dpy, win, &prop, a);
175
176     if(nret)
177         *nret=(!st ? 0 : -1);
178     
179     if(!st)
180         return NULL;
181
182 #ifdef CF_XFREE86_TEXTPROP_BUG_WORKAROUND
183     while(prop.nitems>0){
184         if(prop.value[prop.nitems-1]=='\0')
185             prop.nitems--;
186         else
187             break;
188     }
189 #endif
190
191     if(!ioncore_g.use_mb){
192         st=XTextPropertyToStringList(&prop, &list, &n);
193     }else{
194         st=XmbTextPropertyToTextList(ioncore_g.dpy, &prop, &list, &n);
195         st=!st;
196     }
197
198     XFree(prop.value);
199     
200     if(!st || n==0 || list==NULL)
201         return NULL;
202     
203     if(nret)
204         *nret=n;
205     
206     return list;
207 }
208
209
210 void xwindow_set_text_property(Window win, Atom a, const char **ptr, int n)
211 {
212     XTextProperty prop;
213     Status st;
214
215     if(!ioncore_g.use_mb){
216         st=XStringListToTextProperty((char **)&ptr, n, &prop);
217     }else{
218         st=XmbTextListToTextProperty(ioncore_g.dpy, (char **)ptr, n,
219                                      XTextStyle, &prop);
220         st=!st;
221     }
222     
223     if(!st)
224         return;
225     
226     XSetTextProperty(ioncore_g.dpy, win, &prop, a);
227     XFree(prop.value);
228 }
229
230
231 /*}}}*/
232
233
234 /*{{{ Exports */
235
236
237 /*EXTL_DOC
238  * Create a new atom. See \code{XInternAtom}(3) manual page for details.
239  */
240 EXTL_EXPORT
241 int ioncore_x_intern_atom(const char *name, bool only_if_exists)
242 {
243     return XInternAtom(ioncore_g.dpy, name, only_if_exists);
244 }
245
246
247 /*EXTL_DOC
248  * Get the name of an atom. See \code{XGetAtomName}(3) manual page for 
249  * details.
250  */
251 EXTL_EXPORT
252 char *ioncore_x_get_atom_name(int atom)
253 {
254     return XGetAtomName(ioncore_g.dpy, atom);
255 }
256
257
258 #define CP(TYPE)                                              \
259     {                                                         \
260         TYPE *d=(TYPE*)p;                                     \
261         for(i=0; i<n; i++) extl_table_seti_i(tab, i+1, d[i]); \
262     }
263
264
265 /*EXTL_DOC
266  * Get a property \var{atom} of type \var{atom_type} for window \var{win}. 
267  * The \var{n32expected} parameter indicates the expected number of 32bit
268  * words, and \var{more} indicates whether all or just this amount of data
269  * should be fetched. Each 8, 16 or 32bit element of the property, as
270  * deciphered from \var{atom_type} is a field in the returned table.
271  * See \code{XGetWindowProperty}(3) manual page for more information.
272  */
273 EXTL_SAFE
274 EXTL_EXPORT
275 ExtlTab ioncore_x_get_window_property(int win, int atom, int atom_type,
276                                       int n32expected, bool more)
277 {
278     uchar *p=NULL;
279     ExtlTab tab;
280     int format=0;
281     int i, n;
282     
283     n=xwindow_get_property_(win, atom, atom_type, n32expected, more, &p, 
284                             &format);
285     
286     if(p==NULL)
287         return extl_table_none();
288     
289     if(n<=0 || (format!=8 && format!=16 && format!=32)){
290         free(p);
291         return extl_table_none();
292     }
293     
294     tab=extl_create_table();
295     
296     switch(format){
297     case 8: CP(char); break;
298     case 16: CP(short); break;
299     case 32: CP(long); break;
300     }
301
302     return tab;
303 }
304
305
306 #define GET(TYPE)                                          \
307     {                                                      \
308         TYPE *d=ALLOC_N(TYPE, n);                          \
309         if(d==NULL) return;                                \
310         for(i=0; i<n; i++) {                               \
311             if(!extl_table_geti_i(tab, i+1, &tmp)) return; \
312             d[i]=tmp;                                      \
313         }                                                  \
314         p=(uchar*)d;                                       \
315     }
316
317         
318 static bool get_mode(const char *mode, int *m)
319 {
320     if(strcmp(mode, "replace")==0)
321         *m=PropModeReplace;
322     else if(strcmp(mode, "prepend")==0)
323         *m=PropModePrepend;
324     else if(strcmp(mode, "append")==0)
325         *m=PropModeAppend;
326     else
327         return FALSE;
328     
329     return TRUE;
330 }
331
332
333 /*EXTL_DOC
334  * Modify a window property. The \var{mode} is one of
335  * \codestr{replace}, \codestr{prepend} or \codestr{append}, and format
336  * is either 8, 16 or 32. Also see \fnref{ioncore.x_get_window_property}
337  * and the \code{XChangeProperty}(3) manual page.
338  */
339 EXTL_EXPORT
340 void ioncore_x_change_property(int win, int atom, int atom_type,
341                                int format, const char *mode, ExtlTab tab)
342 {
343     int tmp, m, i, n=extl_table_get_n(tab);
344     uchar *p;
345         
346     if(n<0 || !get_mode(mode, &m)){
347         warn(TR("Invalid arguments."));
348         return;
349     }
350
351     switch(format){
352     case 8: GET(char); break;
353     case 16: GET(short); break;
354     case 32: GET(long); break;
355     default:
356         warn(TR("Invalid arguments."));
357         return;
358     }
359     
360     XChangeProperty(ioncore_g.dpy, win, atom, atom_type, format, m, p, n);
361     
362     free(p);
363 }
364
365
366 /*EXTL_DOC
367  * Delete a window property.
368  */
369 EXTL_EXPORT
370 void ioncore_x_delete_property(int win, int atom)
371 {
372     XDeleteProperty(ioncore_g.dpy, win, atom);
373 }
374
375
376 /*EXTL_DOC
377  * Get a text property for a window. The fields in the returned
378  * table (starting from 1) are the null-separated parts of the property.
379  * See the \code{XGetTextProperty}(3) manual page for more information.
380  */
381 EXTL_SAFE
382 EXTL_EXPORT
383 ExtlTab ioncore_x_get_text_property(int win, int atom)
384 {
385     char **list;
386     int i, n;
387     ExtlTab tab=extl_table_none();
388     
389     list=xwindow_get_text_property(win, atom, &n);
390     
391     if(list!=NULL){
392         if(n!=0){
393             tab=extl_create_table();
394             for(i=0; i<n; i++)
395                 extl_table_seti_s(tab, i+1, list[i]);
396         }
397         XFreeStringList(list);
398     }
399     
400     return tab;
401 }
402
403
404 /*EXTL_DOC
405  * Set a text property for a window. The fields of \var{tab} starting from
406  * 1 should be the different null-separated parts of the property.
407  * See the \code{XSetTextProperty}(3) manual page for more information.
408  */
409 EXTL_EXPORT
410 void ioncore_x_set_text_property(int win, int atom, ExtlTab tab)
411 {
412     char **list;
413     int i, n=extl_table_get_n(tab);
414     
415     list=ALLOC_N(char*, n);
416
417     if(list==NULL)
418         return;
419     
420     for(i=0; i<n; i++){
421         list[i]=NULL;
422         extl_table_geti_s(tab, i+1, &(list[i]));
423     }
424     
425     xwindow_set_text_property(win, atom, (const char **)list, n);
426     
427     XFreeStringList(list);
428 }
429
430
431 /*}}}*/
432