Releasing version 3-2014010501
[notion/jeffpc.git] / de / init.c
bloba49af1e63b5d822d828bd1fb03a8897bea227dec
1 /*
2 * ion/de/init.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
11 #include <libextl/readconfig.h>
12 #include <libextl/extl.h>
14 #include <ioncore/common.h>
15 #include <ioncore/global.h>
16 #include <ioncore/rootwin.h>
17 #include <ioncore/extlconv.h>
18 #include <ioncore/ioncore.h>
20 #include "brush.h"
21 #include "font.h"
22 #include "colour.h"
23 #include "private.h"
24 #include "init.h"
25 #include "exports.h"
28 /*{{{ Style specifications */
31 static bool get_spec(ExtlTab tab, const char *name, GrStyleSpec *spec,
32 char **pat_ret)
34 char *str;
35 bool res;
37 if(!extl_table_gets_s(tab, name, &str))
38 return FALSE;
40 res=gr_stylespec_load(spec, str);
42 if(pat_ret==NULL)
43 free(str);
44 else
45 *pat_ret=str;
47 return res;
51 /*}}}*/
54 /*{{{ Borders */
57 #define CF_BORDER_VAL_SANITY_CHECK 16
59 void de_get_border_val(uint *val, ExtlTab tab, const char *what)
61 int g;
63 if(extl_table_gets_i(tab, what, &g)){
64 if(g>CF_BORDER_VAL_SANITY_CHECK || g<0)
65 warn(TR("Border attribute %s sanity check failed."), what);
66 else
67 *val=g;
72 void de_get_border_style(uint *ret, ExtlTab tab)
74 char *style=NULL;
76 if(!extl_table_gets_s(tab, "border_style", &style))
77 return;
79 if(strcmp(style, "inlaid")==0)
80 *ret=DEBORDER_INLAID;
81 else if(strcmp(style, "elevated")==0)
82 *ret=DEBORDER_ELEVATED;
83 else if(strcmp(style, "groove")==0)
84 *ret=DEBORDER_GROOVE;
85 else if(strcmp(style, "ridge")==0)
86 *ret=DEBORDER_RIDGE;
87 else
88 warn(TR("Unknown border style \"%s\"."), style);
90 free(style);
94 void de_get_border_sides(uint *ret, ExtlTab tab)
96 char *style=NULL;
98 if(!extl_table_gets_s(tab, "border_sides", &style))
99 return;
101 if(strcmp(style, "all")==0)
102 *ret=DEBORDER_ALL;
103 else if(strcmp(style, "tb")==0)
104 *ret=DEBORDER_TB;
105 else if(strcmp(style, "lr")==0)
106 *ret=DEBORDER_LR;
107 else
108 warn(TR("Unknown border side configuration \"%s\"."), style);
110 free(style);
114 void de_get_border(DEBorder *border, ExtlTab tab)
116 de_get_border_val(&(border->sh), tab, "shadow_pixels");
117 de_get_border_val(&(border->hl), tab, "highlight_pixels");
118 de_get_border_val(&(border->pad), tab, "padding_pixels");
119 de_get_border_style(&(border->style), tab);
120 de_get_border_sides(&(border->sides), tab);
124 /*}}}*/
127 /*{{{ Colours */
130 static bool de_get_colour_(WRootWin *rootwin, DEColour *ret,
131 ExtlTab tab, const char *what,
132 DEColour substitute, DEColour inherit)
134 char *name=NULL;
135 bool set=FALSE;
137 if(extl_table_gets_s(tab, what, &name)){
138 if(strcmp(name, "inherit")==0){
139 set=de_duplicate_colour(rootwin, inherit, ret);
140 }else{
141 set=de_alloc_colour(rootwin, ret, name);
143 if(!set)
144 warn(TR("Unable to allocate colour \"%s\"."), name);
146 free(name);
149 if(!set)
150 de_duplicate_colour(rootwin, substitute, ret);
152 return set;
156 static bool de_get_colour(WRootWin *rootwin, DEColour *ret,
157 ExtlTab tab, const char *what, DEColour substitute)
159 return de_get_colour_(rootwin, ret, tab, what, substitute, substitute);
163 void de_get_colour_group(WRootWin *rootwin, DEColourGroup *cg,
164 ExtlTab tab, DEStyle *based_on)
166 bool bgset;
167 DEColour padinh;
169 de_get_colour(rootwin, &(cg->hl), tab, "highlight_colour",
170 (based_on ? based_on->cgrp.hl : DE_WHITE(rootwin)));
171 de_get_colour(rootwin, &(cg->sh), tab, "shadow_colour",
172 (based_on ? based_on->cgrp.sh : DE_WHITE(rootwin)));
173 de_get_colour(rootwin, &(cg->fg), tab, "foreground_colour",
174 (based_on ? based_on->cgrp.fg : DE_WHITE(rootwin)));
175 bgset=de_get_colour(rootwin, &(cg->bg), tab, "background_colour",
176 (based_on ? based_on->cgrp.bg : DE_BLACK(rootwin)));
178 padinh=(based_on ? based_on->cgrp.pad : DE_WHITE(rootwin));
180 de_get_colour_(rootwin, &(cg->pad), tab, "padding_colour",
181 (bgset ? cg->bg : padinh), padinh);
185 void de_get_extra_cgrps(WRootWin *rootwin, DEStyle *style, ExtlTab tab)
188 uint i=0, nfailed=0, n=extl_table_get_n(tab);
189 char *name;
190 ExtlTab sub;
192 if(n==0)
193 return;
195 style->extra_cgrps=ALLOC_N(DEColourGroup, n);
197 if(style->extra_cgrps==NULL)
198 return;
200 for(i=0; i<n-nfailed; i++){
201 GrStyleSpec spec;
203 if(!extl_table_geti_t(tab, i+1, &sub))
204 goto err;
206 if(!get_spec(sub, "substyle_pattern", &spec, NULL)){
207 extl_unref_table(sub);
208 goto err;
211 style->extra_cgrps[i-nfailed].spec=spec;
213 de_get_colour_group(rootwin, style->extra_cgrps+i-nfailed, sub,
214 style);
216 extl_unref_table(sub);
217 continue;
219 err:
220 warn(TR("Corrupt substyle table %d."), i);
221 nfailed++;
224 if(n-nfailed==0){
225 free(style->extra_cgrps);
226 style->extra_cgrps=NULL;
229 style->n_extra_cgrps=n-nfailed;
233 /*}}}*/
236 /*{{{ Misc. */
239 void de_get_text_align(int *alignret, ExtlTab tab)
241 char *align=NULL;
243 if(!extl_table_gets_s(tab, "text_align", &align))
244 return;
246 if(strcmp(align, "left")==0)
247 *alignret=DEALIGN_LEFT;
248 else if(strcmp(align, "right")==0)
249 *alignret=DEALIGN_RIGHT;
250 else if(strcmp(align, "center")==0)
251 *alignret=DEALIGN_CENTER;
252 else
253 warn(TR("Unknown text alignment \"%s\"."), align);
255 free(align);
259 void de_get_transparent_background(uint *mode, ExtlTab tab)
261 bool b;
263 if(extl_table_gets_b(tab, "transparent_background", &b))
264 *mode=b;
268 /*}}}*/
271 /*{{{ Extras filter/copy */
274 static const char * const known_values[]={
275 "based_on",
276 "font",
277 "shadow_pixels",
278 "highlight_pixels",
279 "padding_pixels",
280 "border_style",
281 "border_sides",
282 "spacing",
283 "foreground_colour",
284 "background_colour",
285 "shadow_colour",
286 "highlight_colour",
287 "padding_colour",
288 "text_align",
289 NULL
293 static bool filter_extras_iter_fn(ExtlAny k, ExtlAny v, void *p)
295 ExtlTab *tgt=(ExtlTab*)p;
296 const char *s;
297 int i;
299 if(k.type!='s' && k.type!='S')
300 return TRUE;
302 for(i=0; known_values[i]; i++){
303 if(strcmp(known_values[i], k.value.s)==0)
304 return TRUE;
307 if(*tgt==extl_table_none())
308 *tgt=extl_create_table();
310 extl_table_set(*tgt, 'a', 'a', k, v);
312 return TRUE;
316 static void filter_extras(ExtlTab *tgt, ExtlTab src)
318 /* Copy any unknown string-keyed values from src to tgt,
319 * possibly creating tgt.
321 extl_table_iter(src, filter_extras_iter_fn, tgt);
325 /*}}}*/
328 /*{{{ de_defstyle */
331 void de_get_nonfont(WRootWin *rootwin, DEStyle *style, ExtlTab tab)
333 DEStyle *based_on=style->based_on;
335 if(based_on!=NULL){
336 style->border=based_on->border;
337 style->transparency_mode=based_on->transparency_mode;
338 style->textalign=based_on->textalign;
339 style->spacing=based_on->spacing;
342 de_get_border(&(style->border), tab);
343 de_get_border_val(&(style->spacing), tab, "spacing");
345 de_get_text_align(&(style->textalign), tab);
347 de_get_transparent_background(&(style->transparency_mode), tab);
349 style->cgrp_alloced=TRUE;
350 de_get_colour_group(rootwin, &(style->cgrp), tab, based_on);
351 de_get_extra_cgrps(rootwin, style, tab);
357 /*EXTL_DOC
358 * Define a style for the root window \var{rootwin}.
360 EXTL_EXPORT
361 bool de_defstyle_rootwin(WRootWin *rootwin, const char *name, ExtlTab tab)
363 DEStyle *style, *based_on=NULL;
364 int based_on_score=-1;
365 char *fnt, *bss;
366 uint n;
368 if(name==NULL)
369 return FALSE;
371 style=de_create_style(rootwin, name);
373 if(style==NULL)
374 return FALSE;
376 if(extl_table_gets_s(tab, "based_on", &bss)){
377 GrStyleSpec bs;
379 gr_stylespec_load(&bs, bss);
381 based_on=de_get_style(rootwin, &bs);
383 gr_stylespec_unalloc(&bs);
384 free(bss);
385 }else{
386 based_on=de_get_style(rootwin, &style->spec);
389 if(based_on!=NULL){
390 style->based_on=based_on;
391 based_on->usecount++;
394 de_get_nonfont(rootwin, style, tab);
396 if(extl_table_gets_s(tab, "font", &fnt)){
397 de_load_font_for_style(style, fnt);
398 free(fnt);
399 }else if(based_on!=NULL && based_on->font!=NULL){
400 de_set_font_for_style(style, based_on->font);
403 if(style->font==NULL)
404 de_load_font_for_style(style, de_default_fontname());
406 if(based_on!=NULL &&
407 gr_stylespec_equals(&based_on->spec, &style->spec)){
409 /* The new style replaces based_on, so it may be dumped. */
410 if(!based_on->is_fallback)
411 destyle_dump(based_on);
413 if(based_on->usecount==1){
414 uint nb=based_on->n_extra_cgrps;
415 uint ns=style->n_extra_cgrps;
416 /* Nothing else is using based_on: optimise and move
417 * extra colour groups here, so that based_on can be freed.
420 if(nb>0){
421 DEColourGroup *cgs=ALLOC_N(DEColourGroup, nb+ns);
423 if(cgs!=NULL){
424 memcpy(cgs, based_on->extra_cgrps, sizeof(DEColourGroup)*nb);
425 memcpy(cgs+nb, style->extra_cgrps, sizeof(DEColourGroup)*ns);
427 free(style->extra_cgrps);
428 style->extra_cgrps=cgs;
429 style->n_extra_cgrps=nb+ns;
431 free(based_on->extra_cgrps);
432 based_on->extra_cgrps=NULL;
433 based_on->n_extra_cgrps=0;
438 /* style->extras_table should be none still */
439 style->extras_table=based_on->extras_table;
440 based_on->extras_table=extl_table_none();
442 style->based_on=based_on->based_on;
443 based_on->based_on=NULL;
445 destyle_unref(based_on);
450 filter_extras(&style->extras_table, tab);
452 destyle_add(style);
454 return TRUE;
458 /*EXTL_DOC
459 * Define a style.
461 EXTL_EXPORT
462 bool de_defstyle(const char *name, ExtlTab tab)
464 bool ok=TRUE;
465 WRootWin *rw;
467 FOR_ALL_ROOTWINS(rw){
468 if(!de_defstyle_rootwin(rw, name, tab))
469 ok=FALSE;
472 return ok;
476 /*EXTL_DOC
477 * Define a substyle.
479 EXTL_SAFE
480 EXTL_EXPORT
481 ExtlTab de_substyle(const char *pattern, ExtlTab tab)
483 extl_table_sets_s(tab, "substyle_pattern", pattern);
484 return extl_ref_table(tab);
488 /*}}}*/
491 /*{{{ Module initialisation */
494 #include "../version.h"
496 char de_ion_api_version[]=NOTION_API_VERSION;
499 bool de_init()
501 WRootWin *rootwin;
502 DEStyle *style;
504 if(!de_register_exports())
505 return FALSE;
507 if(!gr_register_engine("de", (GrGetBrushFn*)&de_get_brush))
508 goto fail;
510 /* Create fallback brushes */
511 FOR_ALL_ROOTWINS(rootwin){
512 style=de_create_style(rootwin, "*");
513 if(style!=NULL){
514 style->is_fallback=TRUE;
515 de_load_font_for_style(style, de_default_fontname());
519 return TRUE;
521 fail:
522 de_unregister_exports();
523 return FALSE;
527 void de_deinit()
529 gr_unregister_engine("de");
530 de_unregister_exports();
531 de_deinit_styles();
535 /*}}}*/