4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
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>
28 /*{{{ Style specifications */
31 static bool get_spec(ExtlTab tab
, const char *name
, GrStyleSpec
*spec
,
37 if(!extl_table_gets_s(tab
, name
, &str
))
40 res
=gr_stylespec_load(spec
, str
);
57 #define CF_BORDER_VAL_SANITY_CHECK 16
59 void de_get_border_val(uint
*val
, ExtlTab tab
, const char *what
)
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
);
72 void de_get_border_style(uint
*ret
, ExtlTab tab
)
76 if(!extl_table_gets_s(tab
, "border_style", &style
))
79 if(strcmp(style
, "inlaid")==0)
81 else if(strcmp(style
, "elevated")==0)
82 *ret
=DEBORDER_ELEVATED
;
83 else if(strcmp(style
, "groove")==0)
85 else if(strcmp(style
, "ridge")==0)
88 warn(TR("Unknown border style \"%s\"."), style
);
94 void de_get_border_sides(uint
*ret
, ExtlTab tab
)
98 if(!extl_table_gets_s(tab
, "border_sides", &style
))
101 if(strcmp(style
, "all")==0)
103 else if(strcmp(style
, "tb")==0)
105 else if(strcmp(style
, "lr")==0)
108 warn(TR("Unknown border side configuration \"%s\"."), 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
);
130 static bool de_get_colour_(WRootWin
*rootwin
, DEColour
*ret
,
131 ExtlTab tab
, const char *what
,
132 DEColour substitute
, DEColour inherit
)
137 if(extl_table_gets_s(tab
, what
, &name
)){
138 if(strcmp(name
, "inherit")==0){
139 set
=de_duplicate_colour(rootwin
, inherit
, ret
);
141 set
=de_alloc_colour(rootwin
, ret
, name
);
144 warn(TR("Unable to allocate colour \"%s\"."), name
);
150 de_duplicate_colour(rootwin
, substitute
, ret
);
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
)
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
);
195 style
->extra_cgrps
=ALLOC_N(DEColourGroup
, n
);
197 if(style
->extra_cgrps
==NULL
)
200 for(i
=0; i
<n
-nfailed
; i
++){
203 if(!extl_table_geti_t(tab
, i
+1, &sub
))
206 if(!get_spec(sub
, "substyle_pattern", &spec
, NULL
)){
207 extl_unref_table(sub
);
211 style
->extra_cgrps
[i
-nfailed
].spec
=spec
;
213 de_get_colour_group(rootwin
, style
->extra_cgrps
+i
-nfailed
, sub
,
216 extl_unref_table(sub
);
220 warn(TR("Corrupt substyle table %d."), i
);
225 free(style
->extra_cgrps
);
226 style
->extra_cgrps
=NULL
;
229 style
->n_extra_cgrps
=n
-nfailed
;
239 void de_get_text_align(int *alignret
, ExtlTab tab
)
243 if(!extl_table_gets_s(tab
, "text_align", &align
))
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
;
253 warn(TR("Unknown text alignment \"%s\"."), align
);
259 void de_get_transparent_background(uint
*mode
, ExtlTab tab
)
263 if(extl_table_gets_b(tab
, "transparent_background", &b
))
271 /*{{{ Extras filter/copy */
274 static const char * const known_values
[]={
293 static bool filter_extras_iter_fn(ExtlAny k
, ExtlAny v
, void *p
)
295 ExtlTab
*tgt
=(ExtlTab
*)p
;
299 if(k
.type
!='s' && k
.type
!='S')
302 for(i
=0; known_values
[i
]; i
++){
303 if(strcmp(known_values
[i
], k
.value
.s
)==0)
307 if(*tgt
==extl_table_none())
308 *tgt
=extl_create_table();
310 extl_table_set(*tgt
, 'a', 'a', k
, v
);
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
);
331 void de_get_nonfont(WRootWin
*rootwin
, DEStyle
*style
, ExtlTab tab
)
333 DEStyle
*based_on
=style
->based_on
;
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
);
358 * Define a style for the root window \var{rootwin}.
361 bool de_defstyle_rootwin(WRootWin
*rootwin
, const char *name
, ExtlTab tab
)
363 DEStyle
*style
, *based_on
=NULL
;
364 int based_on_score
=-1;
371 style
=de_create_style(rootwin
, name
);
376 if(extl_table_gets_s(tab
, "based_on", &bss
)){
379 gr_stylespec_load(&bs
, bss
);
381 based_on
=de_get_style(rootwin
, &bs
);
383 gr_stylespec_unalloc(&bs
);
386 based_on
=de_get_style(rootwin
, &style
->spec
);
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
);
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());
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.
421 DEColourGroup
*cgs
=ALLOC_N(DEColourGroup
, nb
+ns
);
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
);
462 bool de_defstyle(const char *name
, ExtlTab tab
)
467 FOR_ALL_ROOTWINS(rw
){
468 if(!de_defstyle_rootwin(rw
, name
, tab
))
481 ExtlTab
de_substyle(const char *pattern
, ExtlTab tab
)
483 extl_table_sets_s(tab
, "substyle_pattern", pattern
);
484 return extl_ref_table(tab
);
491 /*{{{ Module initialisation */
494 #include "../version.h"
496 char de_ion_api_version
[]=NOTION_API_VERSION
;
504 if(!de_register_exports())
507 if(!gr_register_engine("de", (GrGetBrushFn
*)&de_get_brush
))
510 /* Create fallback brushes */
511 FOR_ALL_ROOTWINS(rootwin
){
512 style
=de_create_style(rootwin
, "*");
514 style
->is_fallback
=TRUE
;
515 de_load_font_for_style(style
, de_default_fontname());
522 de_unregister_exports();
529 gr_unregister_engine("de");
530 de_unregister_exports();