]> git.decadent.org.uk Git - ion3.git/blob - de/init.c
bc771d08144a2407022505bf282c4e47bf7f0ac9
[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_sides(uint *ret, ExtlTab tab)
98 {
99     char *style=NULL;
100     
101     if(!extl_table_gets_s(tab, "border_sides", &style))
102         return;
103     
104     if(strcmp(style, "all")==0)
105         *ret=DEBORDER_ALL;
106     else if(strcmp(style, "tb")==0)
107         *ret=DEBORDER_TB;
108     else if(strcmp(style, "lr")==0)
109         *ret=DEBORDER_LR;
110     else
111         warn(TR("Unknown border side configuration \"%s\"."), style);
112     
113     free(style);
114 }
115
116
117 void de_get_border(DEBorder *border, ExtlTab tab)
118 {
119     de_get_border_val(&(border->sh), tab, "shadow_pixels");
120     de_get_border_val(&(border->hl), tab, "highlight_pixels");
121     de_get_border_val(&(border->pad), tab, "padding_pixels");
122     de_get_border_style(&(border->style), tab);
123     de_get_border_sides(&(border->sides), tab);
124 }
125
126
127 /*}}}*/
128
129
130 /*{{{ Colours */
131
132
133 bool de_get_colour(WRootWin *rootwin, DEColour *ret, 
134                    ExtlTab tab, DEStyle *based_on,
135                    const char *what, DEColour substitute)
136 {
137     char *name=NULL;
138     bool ok=FALSE;
139     
140     if(extl_table_gets_s(tab, what, &name)){
141         ok=de_alloc_colour(rootwin, ret, name);
142     
143         if(!ok)
144             warn(TR("Unable to allocate colour \"%s\"."), name);
145
146         free(name);
147     }else if(based_on!=NULL){
148         return de_get_colour(rootwin, ret, based_on->data_table,
149                              based_on->based_on, what, substitute);
150     }
151     
152     if(!ok)
153         ok=de_duplicate_colour(rootwin, substitute, ret);
154     
155     return ok;
156 }
157
158
159 void de_get_colour_group(WRootWin *rootwin, DEColourGroup *cg, 
160                          ExtlTab tab, DEStyle *based_on)
161 {
162     de_get_colour(rootwin, &(cg->hl), tab, based_on, "highlight_colour",
163                   DE_WHITE(rootwin));
164     de_get_colour(rootwin, &(cg->sh), tab, based_on, "shadow_colour",
165                   DE_WHITE(rootwin));
166     de_get_colour(rootwin, &(cg->bg), tab, based_on, "background_colour",
167                   DE_BLACK(rootwin));
168     de_get_colour(rootwin, &(cg->fg), tab, based_on, "foreground_colour",
169                   DE_WHITE(rootwin));
170     de_get_colour(rootwin, &(cg->pad), tab, based_on, "padding_colour", 
171                   cg->bg);
172 }
173
174
175 void de_get_extra_cgrps(WRootWin *rootwin, DEStyle *style, ExtlTab tab)
176 {
177     
178     uint i=0, nfailed=0, n=extl_table_get_n(tab);
179     char *name;
180     ExtlTab sub;
181     
182     if(n==0)
183         return;
184     
185     style->extra_cgrps=ALLOC_N(DEColourGroup, n);
186     
187     if(style->extra_cgrps==NULL)
188         return;
189
190     for(i=0; i<n-nfailed; i++){
191         GrStyleSpec spec;
192         
193         if(!extl_table_geti_t(tab, i+1, &sub))
194             goto err;
195         
196         if(!get_spec(sub, "substyle_pattern", &spec, NULL)){
197             extl_unref_table(sub);
198             goto err;
199         }
200         
201         style->extra_cgrps[i-nfailed].spec=spec;
202         
203         de_get_colour_group(rootwin, style->extra_cgrps+i-nfailed, sub, 
204                             style);
205         
206         extl_unref_table(sub);
207         continue;
208         
209     err:
210         warn(TR("Corrupt substyle table %d."), i);
211         nfailed++;
212     }
213     
214     if(n-nfailed==0){
215         free(style->extra_cgrps);
216         style->extra_cgrps=NULL;
217     }
218     
219     style->n_extra_cgrps=n-nfailed;
220 }
221
222
223 /*}}}*/
224
225
226 /*{{{ Misc. */
227
228
229 void de_get_text_align(int *alignret, ExtlTab tab)
230 {
231     char *align=NULL;
232     
233     if(!extl_table_gets_s(tab, "text_align", &align))
234         return;
235     
236     if(strcmp(align, "left")==0)
237         *alignret=DEALIGN_LEFT;
238     else if(strcmp(align, "right")==0)
239         *alignret=DEALIGN_RIGHT;
240     else if(strcmp(align, "center")==0)
241         *alignret=DEALIGN_CENTER;
242     else
243         warn(TR("Unknown text alignment \"%s\"."), align);
244     
245     free(align);
246 }
247
248
249 void de_get_transparent_background(uint *mode, ExtlTab tab)
250 {
251     bool b;
252     
253     if(extl_table_gets_b(tab, "transparent_background", &b))
254         *mode=b;
255 }
256
257
258 /*}}}*/
259
260
261 /*{{{ de_defstyle */
262
263
264 void de_get_nonfont(WRootWin *rootwin, DEStyle *style, ExtlTab tab)
265 {
266     DEStyle *based_on=style->based_on;
267     
268     style->data_table=extl_ref_table(tab);
269
270     if(based_on!=NULL){
271         style->border=based_on->border;
272         style->transparency_mode=based_on->transparency_mode;
273         style->textalign=based_on->textalign;
274         style->spacing=based_on->spacing;
275     }
276     
277     de_get_border(&(style->border), tab);
278     de_get_border_val(&(style->spacing), tab, "spacing");
279
280     de_get_text_align(&(style->textalign), tab);
281
282     de_get_transparent_background(&(style->transparency_mode), tab);
283
284     style->cgrp_alloced=TRUE;
285     de_get_colour_group(rootwin, &(style->cgrp), tab, based_on);
286     de_get_extra_cgrps(rootwin, style, tab);
287 }
288
289
290
291
292 /*EXTL_DOC
293  * Define a style for the root window \var{rootwin}. 
294  */
295 EXTL_EXPORT
296 bool de_defstyle_rootwin(WRootWin *rootwin, const char *name, ExtlTab tab)
297 {
298     DEStyle *style;
299     char *fnt;
300     uint n;
301     char *based_on_name;
302     DEStyle *based_on=NULL;
303     GrStyleSpec based_on_spec;
304
305     if(name==NULL)
306         return FALSE;
307     
308     style=de_create_style(rootwin, name);
309
310     if(style==NULL)
311         return FALSE;
312
313     if(get_spec(tab, "based_on", &based_on_spec, &based_on_name)){
314         based_on=de_get_style(rootwin, &based_on_spec);
315         
316         gr_stylespec_unalloc(&based_on_spec);
317
318         if(based_on==style){
319             warn(TR("'based_on' for %s points back to the style itself."),
320                  name);
321         }else if(based_on==NULL){
322             warn(TR("Unknown base style. \"%s\""), based_on_name);
323         }else{
324             style->based_on=based_on;
325             based_on->usecount++;
326             /* Copy simple parameters */
327         }
328         
329         free(based_on_name);
330     }
331
332     de_get_nonfont(rootwin, style, tab);
333
334     if(extl_table_gets_s(tab, "font", &fnt)){
335         de_load_font_for_style(style, fnt);
336         free(fnt);
337     }else if(based_on!=NULL && based_on->font!=NULL){
338         de_set_font_for_style(style, based_on->font);
339     }
340     
341     if(style->font==NULL)
342         de_load_font_for_style(style, CF_FALLBACK_FONT_NAME);
343     
344     return TRUE;
345 }
346
347
348 /*EXTL_DOC
349  * Define a style.
350  */
351 EXTL_EXPORT
352 bool de_defstyle(const char *name, ExtlTab tab)
353 {
354     bool ok=TRUE;
355     WRootWin *rw;
356     
357     FOR_ALL_ROOTWINS(rw){
358         if(!de_defstyle_rootwin(rw, name, tab))
359             ok=FALSE;
360     }
361     
362     return ok;
363 }
364
365
366 /*EXTL_DOC
367  * Define a substyle.
368  */
369 EXTL_SAFE
370 EXTL_EXPORT
371 ExtlTab de_substyle(const char *pattern, ExtlTab tab)
372 {
373     extl_table_sets_s(tab, "substyle_pattern", pattern);
374     return extl_ref_table(tab);
375 }
376
377
378 /*}}}*/
379
380
381 /*{{{ Module initialisation */
382
383
384 #include "../version.h"
385
386 char de_ion_api_version[]=ION_API_VERSION;
387
388
389 bool de_init()
390 {
391     WRootWin *rootwin;
392     DEStyle *style;
393     
394     if(!de_register_exports())
395         return FALSE;
396     
397     if(!gr_register_engine("de", (GrGetBrushFn*)&de_get_brush))
398         goto fail;
399     
400     /* Create fallback brushes */
401     FOR_ALL_ROOTWINS(rootwin){
402         style=de_create_style(rootwin, "*");
403         if(style!=NULL){
404             style->is_fallback=TRUE;
405             de_load_font_for_style(style, CF_FALLBACK_FONT_NAME);
406         }
407     }
408     
409     return TRUE;
410     
411 fail:
412     de_unregister_exports();
413     return FALSE;
414 }
415
416
417 void de_deinit()
418 {
419     gr_unregister_engine("de");
420     de_unregister_exports();
421     de_deinit_styles();
422 }
423
424
425 /*}}}*/
426