Update contrib
[notion/jeffpc.git] / ioncore / property.c
blob64d789ea799b8ee51e3a96fd20874d8b49394989
1 /*
2 * notion/ioncore/property.c
4 * Copyright (c) The Notion Team 2011.
5 * Copyright (c) Tuomo Valkonen 1999-2009.
7 * See the included file LICENSE for details.
8 */
10 #include <X11/Xmd.h>
11 #include <string.h>
13 #include "common.h"
14 #include "property.h"
15 #include "global.h"
18 /*{{{ Primitives */
21 static ulong xwindow_get_property_(Window win, Atom atom, Atom type,
22 ulong n32expected, bool more, uchar **p,
23 int *format)
25 Atom real_type;
26 ulong n=-1, extra=0;
27 int status;
29 do{
30 status=XGetWindowProperty(ioncore_g.dpy, win, atom, 0L, n32expected,
31 False, type, &real_type, format, &n,
32 &extra, p);
34 if(status!=Success || *p==NULL)
35 return -1;
37 if(extra==0 || !more)
38 break;
40 XFree((void*)*p);
41 n32expected+=(extra+4)/4;
42 more=FALSE;
43 }while(1);
45 if(n==0){
46 XFree((void*)*p);
47 *p=NULL;
48 return -1;
51 return n;
55 ulong xwindow_get_property(Window win, Atom atom, Atom type,
56 ulong n32expected, bool more, uchar **p)
58 int format=0;
59 return xwindow_get_property_(win, atom, type, n32expected, more, p,
60 &format);
64 /*}}}*/
67 /*{{{ String property stuff */
70 char *xwindow_get_string_property(Window win, Atom a, int *nret)
72 char *p;
73 int n;
75 n=xwindow_get_property(win, a, XA_STRING, 64L, TRUE, (uchar**)&p);
77 if(nret!=NULL)
78 *nret=n;
80 return (n<=0 ? NULL : p);
84 void xwindow_set_string_property(Window win, Atom a, const char *value)
86 if(value==NULL){
87 XDeleteProperty(ioncore_g.dpy, win, a);
88 }else{
89 XChangeProperty(ioncore_g.dpy, win, a, XA_STRING,
90 8, PropModeReplace, (uchar*)value, strlen(value));
95 /*}}}*/
98 /*{{{ Integer property stuff */
101 bool xwindow_get_integer_property(Window win, Atom a, int *vret)
103 long *p=NULL;
104 ulong n;
106 n=xwindow_get_property(win, a, XA_INTEGER, 1L, FALSE, (uchar**)&p);
108 if(n>0 && p!=NULL){
109 *vret=*p;
110 XFree((void*)p);
111 return TRUE;
114 return FALSE;
118 void xwindow_set_integer_property(Window win, Atom a, int value)
120 CARD32 data[2];
122 data[0]=value;
124 XChangeProperty(ioncore_g.dpy, win, a, XA_INTEGER,
125 32, PropModeReplace, (uchar*)data, 1);
129 /* WM_STATE
132 bool xwindow_get_state_property(Window win, int *state)
134 CARD32 *p=NULL;
136 if(xwindow_get_property(win, ioncore_g.atom_wm_state,
137 ioncore_g.atom_wm_state,
138 2L, FALSE, (uchar**)&p)<=0)
139 return FALSE;
141 *state=*p;
143 XFree((void*)p);
145 return TRUE;
149 void xwindow_set_state_property(Window win, int state)
151 CARD32 data[2];
153 data[0]=state;
154 data[1]=None;
156 XChangeProperty(ioncore_g.dpy, win,
157 ioncore_g.atom_wm_state, ioncore_g.atom_wm_state,
158 32, PropModeReplace, (uchar*)data, 2);
162 /*}}}*/
165 /*{{{ Text property stuff */
168 char **xwindow_get_text_property(Window win, Atom a, int *nret)
170 XTextProperty prop;
171 char **list=NULL;
172 int n=0;
173 Status st;
174 bool ok;
176 st=XGetTextProperty(ioncore_g.dpy, win, &prop, a);
178 if(nret)
179 *nret=(!st ? 0 : -1);
181 if(!st)
182 return NULL;
184 #ifdef CF_XFREE86_TEXTPROP_BUG_WORKAROUND
185 while(prop.nitems>0){
186 if(prop.value[prop.nitems-1]=='\0')
187 prop.nitems--;
188 else
189 break;
191 #endif
193 if(!ioncore_g.use_mb){
194 Status st=XTextPropertyToStringList(&prop, &list, &n);
195 ok=(st!=0);
196 }else{
197 int st=XmbTextPropertyToTextList(ioncore_g.dpy, &prop, &list, &n);
198 ok=(st>=0);
201 XFree(prop.value);
203 if(!ok || n==0 || list==NULL)
204 return NULL;
206 if(nret)
207 *nret=n;
209 return list;
213 void xwindow_set_text_property(Window win, Atom a, const char **ptr, int n)
215 XTextProperty prop;
216 bool ok;
218 if(ioncore_g.use_mb){
219 int st;
220 #ifdef X_HAVE_UTF8_STRING
221 if (ioncore_g.enc_utf8)
222 st=Xutf8TextListToTextProperty(ioncore_g.dpy, (char **)ptr, n,
223 XUTF8StringStyle, &prop);
224 else
225 #endif
226 st=XmbTextListToTextProperty(ioncore_g.dpy, (char **)ptr, n,
227 XTextStyle, &prop);
228 ok=(st>=0);
229 }else{
230 Status st=XStringListToTextProperty((char **)ptr, n, &prop);
231 ok=(st!=0);
234 if(!ok)
235 return;
237 XSetTextProperty(ioncore_g.dpy, win, &prop, a);
238 XFree(prop.value);
241 void xwindow_set_utf8_property(Window win, Atom a, const char **ptr, int n)
243 #ifndef X_HAVE_UTF8_STRING
244 xwindow_set_text_property(win, a, ptr, n);
245 #else
246 XTextProperty prop;
247 bool ok;
249 int st=XmbTextListToTextProperty(ioncore_g.dpy, (char **)ptr, n,
250 XUTF8StringStyle, &prop);
251 ok=(st>=0);
253 if(!ok)
254 return;
256 XSetTextProperty(ioncore_g.dpy, win, &prop, a);
257 XFree(prop.value);
258 #endif
262 /*}}}*/
265 /*{{{ Exports */
268 /*EXTL_DOC
269 * Create a new atom. See \code{XInternAtom}(3) manual page for details.
271 EXTL_EXPORT
272 int ioncore_x_intern_atom(const char *name, bool only_if_exists)
274 return XInternAtom(ioncore_g.dpy, name, only_if_exists);
278 /*EXTL_DOC
279 * Get the name of an atom. See \code{XGetAtomName}(3) manual page for
280 * details.
282 EXTL_EXPORT
283 char *ioncore_x_get_atom_name(int atom)
285 char *xatomname, *atomname;
287 xatomname = XGetAtomName(ioncore_g.dpy, atom);
288 atomname = scopy(xatomname);
289 XFree(xatomname);
291 return atomname;
295 #define CP(TYPE) \
297 TYPE *d=(TYPE*)p; \
298 for(i=0; i<n; i++) extl_table_seti_i(tab, i+1, d[i]); \
302 /*EXTL_DOC
303 * Get a property \var{atom} of type \var{atom_type} for window \var{win}.
304 * The \var{n32expected} parameter indicates the expected number of 32bit
305 * words, and \var{more} indicates whether all or just this amount of data
306 * should be fetched. Each 8, 16 or 32bit element of the property, as
307 * deciphered from \var{atom_type} is a field in the returned table.
308 * See \code{XGetWindowProperty}(3) manual page for more information.
310 EXTL_SAFE
311 EXTL_EXPORT
312 ExtlTab ioncore_x_get_window_property(int win, int atom, int atom_type,
313 int n32expected, bool more)
315 uchar *p=NULL;
316 ExtlTab tab;
317 int format=0;
318 int i, n;
320 n=xwindow_get_property_(win, atom, atom_type, n32expected, more, &p,
321 &format);
323 if(p==NULL)
324 return extl_table_none();
326 if(n<=0 || (format!=8 && format!=16 && format!=32)){
327 free(p);
328 return extl_table_none();
331 tab=extl_create_table();
333 switch(format){
334 case 8: CP(char); break;
335 case 16: CP(short); break;
336 case 32: CP(long); break;
339 return tab;
343 #define GET(TYPE) \
345 TYPE *d=ALLOC_N(TYPE, n); \
346 if(d==NULL) return; \
347 for(i=0; i<n; i++) { \
348 if(!extl_table_geti_i(tab, i+1, &tmp)) return; \
349 d[i]=tmp; \
351 p=(uchar*)d; \
355 static bool get_mode(const char *mode, int *m)
357 if(strcmp(mode, "replace")==0)
358 *m=PropModeReplace;
359 else if(strcmp(mode, "prepend")==0)
360 *m=PropModePrepend;
361 else if(strcmp(mode, "append")==0)
362 *m=PropModeAppend;
363 else
364 return FALSE;
366 return TRUE;
370 /*EXTL_DOC
371 * Modify a window property. The \var{mode} is one of
372 * \codestr{replace}, \codestr{prepend} or \codestr{append}, and format
373 * is either 8, 16 or 32. Also see \fnref{ioncore.x_get_window_property}
374 * and the \code{XChangeProperty}(3) manual page.
376 EXTL_EXPORT
377 void ioncore_x_change_property(int win, int atom, int atom_type,
378 int format, const char *mode, ExtlTab tab)
380 int tmp, m, i, n=extl_table_get_n(tab);
381 uchar *p;
383 if(n<0 || !get_mode(mode, &m)){
384 warn(TR("Invalid arguments."));
385 return;
388 switch(format){
389 case 8: GET(char); break;
390 case 16: GET(short); break;
391 case 32: GET(long); break;
392 default:
393 warn(TR("Invalid arguments."));
394 return;
397 XChangeProperty(ioncore_g.dpy, win, atom, atom_type, format, m, p, n);
399 free(p);
403 /*EXTL_DOC
404 * Delete a window property.
406 EXTL_EXPORT
407 void ioncore_x_delete_property(int win, int atom)
409 XDeleteProperty(ioncore_g.dpy, win, atom);
413 /*EXTL_DOC
414 * Get a text property for a window. The fields in the returned
415 * table (starting from 1) are the null-separated parts of the property.
416 * See the \code{XGetTextProperty}(3) manual page for more information.
418 EXTL_SAFE
419 EXTL_EXPORT
420 ExtlTab ioncore_x_get_text_property(int win, int atom)
422 char **list;
423 int i, n;
424 ExtlTab tab=extl_table_none();
426 list=xwindow_get_text_property(win, atom, &n);
428 if(list!=NULL){
429 if(n!=0){
430 tab=extl_create_table();
431 for(i=0; i<n; i++)
432 extl_table_seti_s(tab, i+1, list[i]);
434 XFreeStringList(list);
437 return tab;
441 /*EXTL_DOC
442 * Set a text property for a window. The fields of \var{tab} starting from
443 * 1 should be the different null-separated parts of the property.
444 * See the \code{XSetTextProperty}(3) manual page for more information.
446 EXTL_EXPORT
447 void ioncore_x_set_text_property(int win, int atom, ExtlTab tab)
449 char **list;
450 int i, n=extl_table_get_n(tab);
452 list=ALLOC_N(char*, n);
454 if(list==NULL)
455 return;
457 for(i=0; i<n; i++){
458 list[i]=NULL;
459 extl_table_geti_s(tab, i+1, &(list[i]));
462 xwindow_set_text_property(win, atom, (const char **)list, n);
464 XFreeStringList(list);
467 /*EXTL_DOC
468 * Set a \code{UTF8\_STRING} property for a window. The fields of \var{tab} starting
469 * from 1 should be the different null-separated parts of the property.
470 * See the \code{XSetTextProperty}(3) manual page for more information.
472 EXTL_EXPORT
473 void ioncore_x_set_utf8_property(int win, int atom, ExtlTab tab)
475 char **list;
476 int i, n=extl_table_get_n(tab);
478 list=ALLOC_N(char*, n);
480 if(list==NULL)
481 return;
483 for(i=0; i<n; i++){
484 list[i]=NULL;
485 extl_table_geti_s(tab, i+1, &(list[i]));
488 xwindow_set_utf8_property(win, atom, (const char **)list, n);
490 XFreeStringList(list);
495 /*}}}*/
498 /*{{{ Cardinal */
501 bool xwindow_get_cardinal_property(Window win, Atom a, CARD32 *vret)
503 long *p=NULL;
504 ulong n;
506 n=xwindow_get_property(win, a, XA_CARDINAL, 1L, FALSE, (uchar**)&p);
508 if(n>0 && p!=NULL){
509 *vret=*p;
510 XFree((void*)p);
511 return TRUE;
514 return FALSE;
518 /*}}}*/