add all functions for getting and setting window properties
[dana/openbox.git] / cwmcc / prop.c
1 #include "cwmcc_internal.h"
2
3 #include <X11/Xutil.h>
4 #include <glib.h>
5 #ifdef HAVE_STRING_H
6 #  include <string.h>
7 #endif
8
9 /* this just isn't used...
10 static gboolean get(Window win, Atom prop, Atom type, int size,
11                     guchar **data, gulong num)
12 {
13     gboolean ret = FALSE;
14     int res;
15     guchar *xdata = NULL;
16     Atom ret_type;
17     int ret_size;
18     gulong ret_items, bytes_left;
19     long num32 = 32 / size * num; /\* num in 32-bit elements *\/
20
21     res = XGetWindowProperty(cwmcc_display, win, prop, 0l, num32,
22                              FALSE, type, &ret_type, &ret_size,
23                              &ret_items, &bytes_left, &xdata);
24     if (res == Success && ret_items && xdata) {
25         if (ret_size == size && ret_items >= num) {
26             *data = g_memdup(xdata, num * (size / 8));
27             ret = TRUE;
28         }
29         XFree(xdata);
30     }
31     return ret;
32 }
33 */
34
35 static gboolean get_prealloc(Window win, Atom prop, Atom type, int size,
36                              guchar *data, gulong num)
37 {
38     gboolean ret = FALSE;
39     int res;
40     guchar *xdata = NULL;
41     Atom ret_type;
42     int ret_size;
43     gulong ret_items, bytes_left;
44     long num32 = 32 / size * num; /* num in 32-bit elements */
45
46     res = XGetWindowProperty(cwmcc_display, win, prop, 0l, num32,
47                              FALSE, type, &ret_type, &ret_size,
48                              &ret_items, &bytes_left, &xdata);
49     if (res == Success && ret_items && xdata) {
50         if (ret_size == size && ret_items >= num) {
51             gulong i;
52             for (i = 0; i < num; ++i)
53                 switch (size) {
54                 case 8:
55                     data[i] = xdata[i];
56                     break;
57                 case 16:
58                     ((guint16*)data)[i] = ((guint16*)xdata)[i];
59                     break;
60                 case 32:
61                     ((guint32*)data)[i] = ((guint32*)xdata)[i];
62                     break;
63                 default:
64                     g_assert_not_reached(); /* unhandled size */
65                 }
66             ret = TRUE;
67         }
68         XFree(xdata);
69     }
70     return ret;
71 }
72
73 static gboolean get_all(Window win, Atom prop, Atom type, int size,
74                         guchar **data, gulong *num)
75 {
76     gboolean ret = FALSE;
77     int res;
78     guchar *xdata = NULL;
79     Atom ret_type;
80     int ret_size;
81     gulong ret_items, bytes_left;
82
83     res = XGetWindowProperty(cwmcc_display, win, prop, 0l, G_MAXLONG,
84                              FALSE, type, &ret_type, &ret_size,
85                              &ret_items, &bytes_left, &xdata);
86     if (res == Success) {
87         if (ret_size == size && ret_items > 0) {
88             *data = g_memdup(xdata, ret_items * (size / 8));
89             *num = ret_items;
90             ret = TRUE;
91         }
92         XFree(xdata);
93     }
94     return ret;
95 }
96
97 static gboolean get_stringlist(Window win, Atom prop, char ***list, int *nstr)
98 {
99     XTextProperty tprop;
100     gboolean ret = FALSE;
101
102     if (XGetTextProperty(cwmcc_display, win, &tprop, prop) && tprop.nitems) {
103         if (XTextPropertyToStringList(&tprop, list, nstr))
104             ret = TRUE;
105         XFree(tprop.value);
106     }
107     return ret;
108 }
109
110 gboolean prop_get32(Window win, Atom prop, Atom type, gulong *ret)
111 {
112     return get_prealloc(win, prop, type, 32, (guchar*)ret, 1);
113 }
114
115 gboolean prop_get_array32(Window win, Atom prop, Atom type, gulong **ret,
116                           gulong *nret)
117 {
118     return get_all(win, prop, type, 32, (guchar**)ret, nret);
119 }
120
121 gboolean prop_get_string_locale(Window win, Atom prop, char **data)
122 {
123     char **list;
124     int nstr;
125
126     if (get_stringlist(win, prop, &list, &nstr) && nstr) {
127         *data = g_locale_to_utf8(list[0], -1, NULL, NULL, NULL);
128         XFreeStringList(list);
129         if (data) return TRUE;
130     }
131     return FALSE;
132 }
133
134 gboolean prop_get_string_utf(Window win, Atom prop, Atom type, char **ret)
135 {
136     char *raw;
137     gulong num;
138      
139     if (get_all(win, prop, type, 8, (guchar**)&raw, &num)) {
140         *ret = g_strdup(raw); /* grab the first string from the list */
141         g_free(raw);
142         return TRUE;
143     }
144     return FALSE;
145 }
146
147 gboolean prop_get_strings_utf(Window win, Atom prop, Atom type, char ***ret)
148 {
149     char *raw, *p;
150     gulong num, i;
151
152     if (get_all(win, prop, type, 8, (guchar**)&raw, &num)) {
153         *ret = g_new(char*, num + 1);
154         (*ret)[num] = NULL; /* null terminated list */
155
156         p = raw;
157         for (i = 0; i < num; ++i) {
158             (*ret)[i] = g_strdup(p);
159             p = strchr(p, '\0');
160         }
161         g_free(raw);
162         return TRUE;
163     }
164     return FALSE;
165 }
166
167 gboolean prop_get_strings_locale(Window win, Atom prop, Atom type,char ***ret){
168     char *raw, *p;
169     gulong num, i;
170
171     if (get_all(win, prop, type, 8, (guchar**)&raw, &num)) {
172         *ret = g_new(char*, num + 1);
173         (*ret)[num] = NULL; /* null terminated list */
174
175         p = raw;
176         for (i = 0; i < num; ++i) {
177             (*ret)[i] = g_locale_to_utf8(p, -1, NULL, NULL, NULL);
178             /* make sure translation did not fail */
179             if (!(*ret)[i]) {
180                 g_strfreev(*ret); /* free what we did so far */
181                 break; /* the force is not strong with us */
182             }
183             p = strchr(p, '\0');
184         }
185         g_free(raw);
186         if (i == num)
187             return TRUE;
188     }
189     return FALSE;
190 }
191
192 void prop_set_strings_utf(Window win, Atom prop, Atom type, char **strs)
193 {
194     GString *str;
195     guint i;
196
197     str = g_string_sized_new(0);
198     for (i = 0; strs[i]; ++i) {
199         str = g_string_append(str, strs[i]);
200         str = g_string_append_c(str, '\0');
201     }
202     XChangeProperty(cwmcc_display, win, prop, type, 8,
203                     PropModeReplace, (guchar*)str->str, str->len);
204 }
205
206 void prop_erase(Window win, Atom prop)
207 {
208     XDeleteProperty(cwmcc_display, win, prop);
209 }
210