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