]> git.decadent.org.uk Git - ion3.git/blob - de/init.c
[svn-upgrade] Integrating new upstream version, ion3 (20070203)
[ion3.git] / de / init.c
1 /*
2  * ion/de/init.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * Ion is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <string.h>
13
14 #include <libextl/readconfig.h>
15 #include <libextl/extl.h>
16
17 #include <ioncore/common.h>
18 #include <ioncore/global.h>
19 #include <ioncore/rootwin.h>
20 #include <ioncore/extlconv.h>
21 #include <ioncore/ioncore.h>
22
23 #include "brush.h"
24 #include "font.h"
25 #include "colour.h"
26 #include "private.h"
27 #include "init.h"
28 #include "exports.h"
29
30
31 /*{{{ Style specifications */
32
33
34 static bool get_spec(ExtlTab tab, const char *name, GrStyleSpec *spec,
35                      char **pat_ret)
36 {
37     char *str;
38     bool res;
39     
40     if(!extl_table_gets_s(tab, name, &str))
41         return FALSE;
42         
43     res=gr_stylespec_load(spec, str);
44     
45     if(pat_ret==NULL)
46         free(str);
47     else
48         *pat_ret=str;
49     
50     return res;
51 }
52
53
54 /*}}}*/
55
56
57 /*{{{ Borders */
58
59
60 #define CF_BORDER_VAL_SANITY_CHECK 16
61
62 void de_get_border_val(uint *val, ExtlTab tab, const char *what)
63 {
64     int g;
65     
66     if(extl_table_gets_i(tab, what, &g)){
67         if(g>CF_BORDER_VAL_SANITY_CHECK || g<0)
68             warn(TR("Border attribute %s sanity check failed."), what);
69         else
70             *val=g;
71     }
72 }
73
74
75 void de_get_border_style(uint *ret, ExtlTab tab)
76 {
77     char *style=NULL;
78     
79     if(!extl_table_gets_s(tab, "border_style", &style))
80         return;
81     
82     if(strcmp(style, "inlaid")==0)
83         *ret=DEBORDER_INLAID;
84     else if(strcmp(style, "elevated")==0)
85         *ret=DEBORDER_ELEVATED;
86     else if(strcmp(style, "groove")==0)
87         *ret=DEBORDER_GROOVE;
88     else if(strcmp(style, "ridge")==0)
89         *ret=DEBORDER_RIDGE;
90     else
91         warn(TR("Unknown border style \"%s\"."), style);
92     
93     free(style);
94 }
95
96
97 void de_get_border(DEBorder *border, ExtlTab tab)
98 {
99     de_get_border_val(&(border->sh), tab, "shadow_pixels");
100     de_get_border_val(&(border->hl), tab, "highlight_pixels");
101     de_get_border_val(&(border->pad), tab, "padding_pixels");
102     de_get_border_style(&(border->style), tab);
103 }
104
105
106 /*}}}*/
107
108
109 /*{{{ Colours */
110
111
112 bool de_get_colour(WRootWin *rootwin, DEColour *ret, 
113                    ExtlTab tab, DEStyle *based_on,
114                    const char *what, DEColour substitute)
115 {
116     char *name=NULL;
117     bool ok=FALSE;
118     
119     if(extl_table_gets_s(tab, what, &name)){
120         ok=de_alloc_colour(rootwin, ret, name);
121     
122         if(!ok)
123             warn(TR("Unable to allocate colour \"%s\"."), name);
124
125         free(name);
126     }else if(based_on!=NULL){
127         return de_get_colour(rootwin, ret, based_on->data_table,
128                              based_on->based_on, what, substitute);
129     }
130     
131     if(!ok)
132         ok=de_duplicate_colour(rootwin, substitute, ret);
133     
134     return ok;
135 }
136
137
138 void de_get_colour_group(WRootWin *rootwin, DEColourGroup *cg, 
139                          ExtlTab tab, DEStyle *based_on)
140 {
141     de_get_colour(rootwin, &(cg->hl), tab, based_on, "highlight_colour",
142                   DE_WHITE(rootwin));
143     de_get_colour(rootwin, &(cg->sh), tab, based_on, "shadow_colour",
144                   DE_WHITE(rootwin));
145     de_get_colour(rootwin, &(cg->bg), tab, based_on, "background_colour",
146                   DE_BLACK(rootwin));
147     de_get_colour(rootwin, &(cg->fg), tab, based_on, "foreground_colour",
148                   DE_WHITE(rootwin));
149     de_get_colour(rootwin, &(cg->pad), tab, based_on, "padding_colour", 
150                   cg->bg);
151 }
152
153
154 void de_get_extra_cgrps(WRootWin *rootwin, DEStyle *style, ExtlTab tab)
155 {
156     
157     uint i=0, nfailed=0, n=extl_table_get_n(tab);
158     char *name;
159     ExtlTab sub;
160     
161     if(n==0)
162         return;
163     
164     style->extra_cgrps=ALLOC_N(DEColourGroup, n);
165     
166     if(style->extra_cgrps==NULL)
167         return;
168
169     for(i=0; i<n-nfailed; i++){
170         GrStyleSpec spec;
171         
172         if(!extl_table_geti_t(tab, i+1, &sub))
173             goto err;
174         
175         if(!get_spec(sub, "substyle_pattern", &spec, NULL)){
176             extl_unref_table(sub);
177             goto err;
178         }
179         
180         style->extra_cgrps[i-nfailed].spec=spec;
181         
182         de_get_colour_group(rootwin, style->extra_cgrps+i-nfailed, sub, 
183                             style);
184         
185         extl_unref_table(sub);
186         continue;
187         
188     err:
189         warn(TR("Corrupt substyle table %d."), i);
190         nfailed++;
191     }
192     
193     if(n-nfailed==0){
194         free(style->extra_cgrps);
195         style->extra_cgrps=NULL;
196     }
197     
198     style->n_extra_cgrps=n-nfailed;
199 }
200
201
202 /*}}}*/
203
204
205 /*{{{ Misc. */
206
207
208 void de_get_text_align(int *alignret, ExtlTab tab)
209 {
210     char *align=NULL;
211     
212     if(!extl_table_gets_s(tab, "text_align", &align))
213         return;
214     
215     if(strcmp(align, "left")==0)
216         *alignret=DEALIGN_LEFT;
217     else if(strcmp(align, "right")==0)
218         *alignret=DEALIGN_RIGHT;
219     else if(strcmp(align, "center")==0)
220         *alignret=DEALIGN_CENTER;
221     else
222         warn(TR("Unknown text alignment \"%s\"."), align);
223     
224     free(align);
225 }
226
227
228 void de_get_transparent_background(uint *mode, ExtlTab tab)
229 {
230     bool b;
231     
232     if(extl_table_gets_b(tab, "transparent_background", &b))
233         *mode=b;
234 }
235
236
237 /*}}}*/
238
239
240 /*{{{ de_defstyle */
241
242
243 void de_get_nonfont(WRootWin *rootwin, DEStyle *style, ExtlTab tab)
244 {
245     DEStyle *based_on=style->based_on;
246     
247     style->data_table=extl_ref_table(tab);
248
249     if(based_on!=NULL){
250         style->border=based_on->border;
251         style->transparency_mode=based_on->transparency_mode;
252         style->textalign=based_on->textalign;
253         style->spacing=based_on->spacing;
254     }
255     
256     de_get_border(&(style->border), tab);
257     de_get_border_val(&(style->spacing), tab, "spacing");
258
259     de_get_text_align(&(style->textalign), tab);
260
261     de_get_transparent_background(&(style->transparency_mode), tab);
262
263     style->cgrp_alloced=TRUE;
264     de_get_colour_group(rootwin, &(style->cgrp), tab, based_on);
265     de_get_extra_cgrps(rootwin, style, tab);
266 }
267
268
269
270
271 /*EXTL_DOC
272  * Define a style for the root window \var{rootwin}. 
273  */
274 EXTL_EXPORT
275 bool de_defstyle_rootwin(WRootWin *rootwin, const char *name, ExtlTab tab)
276 {
277     DEStyle *style;
278     char *fnt;
279     uint n;
280     char *based_on_name;
281     DEStyle *based_on=NULL;
282     GrStyleSpec based_on_spec;
283
284     if(name==NULL)
285         return FALSE;
286     
287     style=de_create_style(rootwin, name);
288
289     if(style==NULL)
290         return FALSE;
291
292     if(get_spec(tab, "based_on", &based_on_spec, &based_on_name)){
293         based_on=de_get_style(rootwin, &based_on_spec);
294         
295         gr_stylespec_unalloc(&based_on_spec);
296
297         if(based_on==style){
298             warn(TR("'based_on' for %s points back to the style itself."),
299                  name);
300         }else if(based_on==NULL){
301             warn(TR("Unknown base style. \"%s\""), based_on_name);
302         }else{
303             style->based_on=based_on;
304             based_on->usecount++;
305             /* Copy simple parameters */
306         }
307         
308         free(based_on_name);
309     }
310
311     de_get_nonfont(rootwin, style, tab);
312
313     if(extl_table_gets_s(tab, "font", &fnt)){
314         de_load_font_for_style(style, fnt);
315         free(fnt);
316     }else if(based_on!=NULL && based_on->font!=NULL){
317         de_set_font_for_style(style, based_on->font);
318     }
319     
320     if(style->font==NULL)
321         de_load_font_for_style(style, CF_FALLBACK_FONT_NAME);
322     
323     return TRUE;
324 }
325
326
327 /*EXTL_DOC
328  * Define a style.
329  */
330 EXTL_EXPORT
331 bool de_defstyle(const char *name, ExtlTab tab)
332 {
333     bool ok=TRUE;
334     WRootWin *rw;
335     
336     FOR_ALL_ROOTWINS(rw){
337         if(!de_defstyle_rootwin(rw, name, tab))
338             ok=FALSE;
339     }
340     
341     return ok;
342 }
343
344
345 /*EXTL_DOC
346  * Define a substyle.
347  */
348 EXTL_SAFE
349 EXTL_EXPORT
350 ExtlTab de_substyle(const char *pattern, ExtlTab tab)
351 {
352     extl_table_sets_s(tab, "substyle_pattern", pattern);
353     return extl_ref_table(tab);
354 }
355
356
357 /*}}}*/
358
359
360 /*{{{ Module initialisation */
361
362
363 #include "../version.h"
364
365 char de_ion_api_version[]=ION_API_VERSION;
366
367
368 bool de_init()
369 {
370     WRootWin *rootwin;
371     DEStyle *style;
372     
373     if(!de_register_exports())
374         return FALSE;
375     
376     if(!gr_register_engine("de", (GrGetBrushFn*)&de_get_brush))
377         goto fail;
378     
379     /* Create fallback brushes */
380     FOR_ALL_ROOTWINS(rootwin){
381         style=de_create_style(rootwin, "*");
382         if(style!=NULL){
383             style->is_fallback=TRUE;
384             de_load_font_for_style(style, CF_FALLBACK_FONT_NAME);
385         }
386     }
387     
388     return TRUE;
389     
390 fail:
391     de_unregister_exports();
392     return FALSE;
393 }
394
395
396 void de_deinit()
397 {
398     gr_unregister_engine("de");
399     de_unregister_exports();
400     de_deinit_styles();
401 }
402
403
404 /*}}}*/
405