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
)
187 uint i
=0, nfailed
=0, n
=extl_table_get_n(tab
);
193 style
->extra_cgrps
=ALLOC_N(DEColourGroup
, n
);
195 if(style
->extra_cgrps
==NULL
)
198 for(i
=0; i
<n
-nfailed
; i
++){
201 if(!extl_table_geti_t(tab
, i
+1, &sub
))
204 if(!get_spec(sub
, "substyle_pattern", &spec
, NULL
)){
205 extl_unref_table(sub
);
209 style
->extra_cgrps
[i
-nfailed
].spec
=spec
;
211 de_get_colour_group(rootwin
, style
->extra_cgrps
+i
-nfailed
, sub
,
214 extl_unref_table(sub
);
218 warn(TR("Corrupt substyle table %d."), i
);
223 free(style
->extra_cgrps
);
224 style
->extra_cgrps
=NULL
;
227 style
->n_extra_cgrps
=n
-nfailed
;
237 void de_get_text_align(int *alignret
, ExtlTab tab
)
241 if(!extl_table_gets_s(tab
, "text_align", &align
))
244 if(strcmp(align
, "left")==0)
245 *alignret
=DEALIGN_LEFT
;
246 else if(strcmp(align
, "right")==0)
247 *alignret
=DEALIGN_RIGHT
;
248 else if(strcmp(align
, "center")==0)
249 *alignret
=DEALIGN_CENTER
;
251 warn(TR("Unknown text alignment \"%s\"."), align
);
257 void de_get_transparent_background(uint
*mode
, ExtlTab tab
)
261 if(extl_table_gets_b(tab
, "transparent_background", &b
))
269 /*{{{ Extras filter/copy */
272 static const char * const known_values
[]={
291 static bool filter_extras_iter_fn(ExtlAny k
, ExtlAny v
, void *p
)
293 ExtlTab
*tgt
=(ExtlTab
*)p
;
296 if(k
.type
!='s' && k
.type
!='S')
299 for(i
=0; known_values
[i
]; i
++){
300 if(strcmp(known_values
[i
], k
.value
.s
)==0)
304 if(*tgt
==extl_table_none())
305 *tgt
=extl_create_table();
307 extl_table_set(*tgt
, 'a', 'a', k
, v
);
313 static void filter_extras(ExtlTab
*tgt
, ExtlTab src
)
315 /* Copy any unknown string-keyed values from src to tgt,
316 * possibly creating tgt.
318 extl_table_iter(src
, filter_extras_iter_fn
, tgt
);
328 void de_get_nonfont(WRootWin
*rootwin
, DEStyle
*style
, ExtlTab tab
)
330 DEStyle
*based_on
=style
->based_on
;
333 style
->border
=based_on
->border
;
334 style
->transparency_mode
=based_on
->transparency_mode
;
335 style
->textalign
=based_on
->textalign
;
336 style
->spacing
=based_on
->spacing
;
339 de_get_border(&(style
->border
), tab
);
340 de_get_border_val(&(style
->spacing
), tab
, "spacing");
342 de_get_text_align(&(style
->textalign
), tab
);
344 de_get_transparent_background(&(style
->transparency_mode
), tab
);
346 style
->cgrp_alloced
=TRUE
;
347 de_get_colour_group(rootwin
, &(style
->cgrp
), tab
, based_on
);
348 de_get_extra_cgrps(rootwin
, style
, tab
);
355 * Define a style for the root window \var{rootwin}.
358 bool de_defstyle_rootwin(WRootWin
*rootwin
, const char *name
, ExtlTab tab
)
360 DEStyle
*style
, *based_on
=NULL
;
366 style
=de_create_style(rootwin
, name
);
371 if(extl_table_gets_s(tab
, "based_on", &bss
)){
374 gr_stylespec_load(&bs
, bss
);
376 based_on
=de_get_style(rootwin
, &bs
);
378 gr_stylespec_unalloc(&bs
);
381 based_on
=de_get_style(rootwin
, &style
->spec
);
385 style
->based_on
=based_on
;
386 based_on
->usecount
++;
389 de_get_nonfont(rootwin
, style
, tab
);
391 if(extl_table_gets_s(tab
, "font", &fnt
)){
392 de_load_font_for_style(style
, fnt
);
394 }else if(based_on
!=NULL
&& based_on
->font
!=NULL
){
395 de_set_font_for_style(style
, based_on
->font
);
398 if(style
->font
==NULL
)
399 de_load_font_for_style(style
, de_default_fontname());
402 gr_stylespec_equals(&based_on
->spec
, &style
->spec
)){
404 /* The new style replaces based_on, so it may be dumped. */
405 if(!based_on
->is_fallback
)
406 destyle_dump(based_on
);
408 if(based_on
->usecount
==1){
409 uint nb
=based_on
->n_extra_cgrps
;
410 uint ns
=style
->n_extra_cgrps
;
411 /* Nothing else is using based_on: optimise and move
412 * extra colour groups here, so that based_on can be freed.
416 DEColourGroup
*cgs
=ALLOC_N(DEColourGroup
, nb
+ns
);
419 memcpy(cgs
, based_on
->extra_cgrps
, sizeof(DEColourGroup
)*nb
);
420 memcpy(cgs
+nb
, style
->extra_cgrps
, sizeof(DEColourGroup
)*ns
);
422 free(style
->extra_cgrps
);
423 style
->extra_cgrps
=cgs
;
424 style
->n_extra_cgrps
=nb
+ns
;
426 free(based_on
->extra_cgrps
);
427 based_on
->extra_cgrps
=NULL
;
428 based_on
->n_extra_cgrps
=0;
433 /* style->extras_table should be none still */
434 style
->extras_table
=based_on
->extras_table
;
435 based_on
->extras_table
=extl_table_none();
437 style
->based_on
=based_on
->based_on
;
438 based_on
->based_on
=NULL
;
440 destyle_unref(based_on
);
445 filter_extras(&style
->extras_table
, tab
);
457 bool de_defstyle(const char *name
, ExtlTab tab
)
462 FOR_ALL_ROOTWINS(rw
){
463 if(!de_defstyle_rootwin(rw
, name
, tab
))
476 ExtlTab
de_substyle(const char *pattern
, ExtlTab tab
)
478 extl_table_sets_s(tab
, "substyle_pattern", pattern
);
479 return extl_ref_table(tab
);
486 /*{{{ Module initialisation */
489 #include "../version.h"
491 char de_ion_api_version
[]=NOTION_API_VERSION
;
499 if(!de_register_exports())
502 if(!gr_register_engine("de", (GrGetBrushFn
*)&de_get_brush
))
505 /* Create fallback brushes */
506 FOR_ALL_ROOTWINS(rootwin
){
507 style
=de_create_style(rootwin
, "*");
509 style
->is_fallback
=TRUE
;
510 de_load_font_for_style(style
, de_default_fontname());
517 de_unregister_exports();
524 gr_unregister_engine("de");
525 de_unregister_exports();