]> git.decadent.org.uk Git - ion3.git/blob - ioncore/property.c
[svn-upgrade] Integrating new upstream version, ion3 (20071220)
[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;
173     bool ok;
174     
175     st=XGetTextProperty(ioncore_g.dpy, win, &prop, a);
176
177     if(nret)
178         *nret=(!st ? 0 : -1);
179     
180     if(!st)
181         return NULL;
182
183 #ifdef CF_XFREE86_TEXTPROP_BUG_WORKAROUND
184     while(prop.nitems>0){
185         if(prop.value[prop.nitems-1]=='\0')
186             prop.nitems--;
187         else
188             break;
189     }
190 #endif
191
192     if(!ioncore_g.use_mb){
193         Status st=XTextPropertyToStringList(&prop, &list, &n);
194         ok=(st!=0);
195     }else{
196         int st=XmbTextPropertyToTextList(ioncore_g.dpy, &prop, &list, &n);
197         ok=(st>=0);
198     }
199
200     XFree(prop.value);
201     
202     if(!ok || n==0 || list==NULL)
203         return NULL;
204     
205     if(nret)
206         *nret=n;
207     
208     return list;
209 }
210
211
212 void xwindow_set_text_property(Window win, Atom a, const char **ptr, int n)
213 {
214     XTextProperty prop;
215     bool ok;
216     
217     if(!ioncore_g.use_mb){
218         Status st=XStringListToTextProperty((char **)ptr, n, &prop);
219         ok=(st!=0);
220     }else{
221         int st=XmbTextListToTextProperty(ioncore_g.dpy, (char **)ptr, n,
222                                          XTextStyle, &prop);
223         ok=(st>=0);
224     }
225     
226     if(!ok)
227         return;
228     
229     XSetTextProperty(ioncore_g.dpy, win, &prop, a);
230     XFree(prop.value);
231 }
232
233
234 /*}}}*/
235
236
237 /*{{{ Exports */
238
239
240 /*EXTL_DOC
241  * Create a new atom. See \code{XInternAtom}(3) manual page for details.
242  */
243 EXTL_EXPORT
244 int ioncore_x_intern_atom(const char *name, bool only_if_exists)
245 {
246     return XInternAtom(ioncore_g.dpy, name, only_if_exists);
247 }
248
249
250 /*EXTL_DOC
251  * Get the name of an atom. See \code{XGetAtomName}(3) manual page for 
252  * details.
253  */
254 EXTL_EXPORT
255 char *ioncore_x_get_atom_name(int atom)
256 {
257     return XGetAtomName(ioncore_g.dpy, atom);
258 }
259
260
261 #define CP(TYPE)                                              \
262     {                                                         \
263         TYPE *d=(TYPE*)p;                                     \
264         for(i=0; i<n; i++) extl_table_seti_i(tab, i+1, d[i]); \
265     }
266
267
268 /*EXTL_DOC
269  * Get a property \var{atom} of type \var{atom_type} for window \var{win}. 
270  * The \var{n32expected} parameter indicates the expected number of 32bit
271  * words, and \var{more} indicates whether all or just this amount of data
272  * should be fetched. Each 8, 16 or 32bit element of the property, as
273  * deciphered from \var{atom_type} is a field in the returned table.
274  * See \code{XGetWindowProperty}(3) manual page for more information.
275  */
276 EXTL_SAFE
277 EXTL_EXPORT
278 ExtlTab ioncore_x_get_window_property(int win, int atom, int atom_type,
279                                       int n32expected, bool more)
280 {
281     uchar *p=NULL;
282     ExtlTab tab;
283     int format=0;
284     int i, n;
285     
286     n=xwindow_get_property_(win, atom, atom_type, n32expected, more, &p, 
287                             &format);
288     
289     if(p==NULL)
290         return extl_table_none();
291     
292     if(n<=0 || (format!=8 && format!=16 && format!=32)){
293         free(p);
294         return extl_table_none();
295     }
296     
297     tab=extl_create_table();
298     
299     switch(format){
300     case 8: CP(char); break;
301     case 16: CP(short); break;
302     case 32: CP(long); break;
303     }
304
305     return tab;
306 }
307
308
309 #define GET(TYPE)                                          \
310     {                                                      \
311         TYPE *d=ALLOC_N(TYPE, n);                          \
312         if(d==NULL) return;                                \
313         for(i=0; i<n; i++) {                               \
314             if(!extl_table_geti_i(tab, i+1, &tmp)) return; \
315             d[i]=tmp;                                      \
316         }                                                  \
317         p=(uchar*)d;                                       \
318     }
319
320         
321 static bool get_mode(const char *mode, int *m)
322 {
323     if(strcmp(mode, "replace")==0)
324         *m=PropModeReplace;
325     else if(strcmp(mode, "prepend")==0)
326         *m=PropModePrepend;
327     else if(strcmp(mode, "append")==0)
328         *m=PropModeAppend;
329     else
330         return FALSE;
331     
332     return TRUE;
333 }
334
335
336 /*EXTL_DOC
337  * Modify a window property. The \var{mode} is one of
338  * \codestr{replace}, \codestr{prepend} or \codestr{append}, and format
339  * is either 8, 16 or 32. Also see \fnref{ioncore.x_get_window_property}
340  * and the \code{XChangeProperty}(3) manual page.
341  */
342 EXTL_EXPORT
343 void ioncore_x_change_property(int win, int atom, int atom_type,
344                                int format, const char *mode, ExtlTab tab)
345 {
346     int tmp, m, i, n=extl_table_get_n(tab);
347     uchar *p;
348         
349     if(n<0 || !get_mode(mode, &m)){
350         warn(TR("Invalid arguments."));
351         return;
352     }
353
354     switch(format){
355     case 8: GET(char); break;
356     case 16: GET(short); break;
357     case 32: GET(long); break;
358     default:
359         warn(TR("Invalid arguments."));
360         return;
361     }
362     
363     XChangeProperty(ioncore_g.dpy, win, atom, atom_type, format, m, p, n);
364     
365     free(p);
366 }
367
368
369 /*EXTL_DOC
370  * Delete a window property.
371  */
372 EXTL_EXPORT
373 void ioncore_x_delete_property(int win, int atom)
374 {
375     XDeleteProperty(ioncore_g.dpy, win, atom);
376 }
377
378
379 /*EXTL_DOC
380  * Get a text property for a window. The fields in the returned
381  * table (starting from 1) are the null-separated parts of the property.
382  * See the \code{XGetTextProperty}(3) manual page for more information.
383  */
384 EXTL_SAFE
385 EXTL_EXPORT
386 ExtlTab ioncore_x_get_text_property(int win, int atom)
387 {
388     char **list;
389     int i, n;
390     ExtlTab tab=extl_table_none();
391     
392     list=xwindow_get_text_property(win, atom, &n);
393     
394     if(list!=NULL){
395         if(n!=0){
396             tab=extl_create_table();
397             for(i=0; i<n; i++)
398                 extl_table_seti_s(tab, i+1, list[i]);
399         }
400         XFreeStringList(list);
401     }
402     
403     return tab;
404 }
405
406
407 /*EXTL_DOC
408  * Set a text property for a window. The fields of \var{tab} starting from
409  * 1 should be the different null-separated parts of the property.
410  * See the \code{XSetTextProperty}(3) manual page for more information.
411  */
412 EXTL_EXPORT
413 void ioncore_x_set_text_property(int win, int atom, ExtlTab tab)
414 {
415     char **list;
416     int i, n=extl_table_get_n(tab);
417     
418     list=ALLOC_N(char*, n);
419
420     if(list==NULL)
421         return;
422     
423     for(i=0; i<n; i++){
424         list[i]=NULL;
425         extl_table_geti_s(tab, i+1, &(list[i]));
426     }
427     
428     xwindow_set_text_property(win, atom, (const char **)list, n);
429     
430     XFreeStringList(list);
431 }
432
433
434 /*}}}*/
435