4 * Copyright (c) Tuomo Valkonen 1999-2007.
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.
14 #include <libextl/extl.h>
16 #include <ioncore/common.h>
17 #include <ioncore/rootwin.h>
18 #include <ioncore/extlconv.h>
19 #include <ioncore/ioncore.h>
31 static void create_normal_gc(DEStyle *style, WRootWin *rootwin)
37 /* Create normal gc */
38 gcv.line_style=LineSolid;
40 gcv.join_style=JoinBevel;
41 gcv.cap_style=CapButt;
42 gcv.fill_style=FillSolid;
43 gcvmask=(GCLineStyle|GCLineWidth|GCFillStyle|
44 GCJoinStyle|GCCapStyle);
46 style->normal_gc=XCreateGC(ioncore_g.dpy, WROOTWIN_ROOT(rootwin),
51 void destyle_create_tab_gcs(DEStyle *style)
53 Display *dpy=ioncore_g.dpy;
54 WRootWin *rootwin=style->rootwin;
55 Window root=WROOTWIN_ROOT(rootwin);
56 Pixmap stipple_pixmap;
61 /* Create a temporary 1-bit GC for drawing the tag and stipple pixmaps */
62 stipple_pixmap=XCreatePixmap(dpy, root, 2, 2, 1);
64 tmp_gc=XCreateGC(dpy, stipple_pixmap, GCForeground, &gcv);
66 /* Create stipple pattern and stipple GC */
67 XDrawPoint(dpy, stipple_pixmap, tmp_gc, 0, 0);
68 XDrawPoint(dpy, stipple_pixmap, tmp_gc, 1, 1);
69 XSetForeground(dpy, tmp_gc, 0);
70 XDrawPoint(dpy, stipple_pixmap, tmp_gc, 1, 0);
71 XDrawPoint(dpy, stipple_pixmap, tmp_gc, 0, 1);
73 gcv.fill_style=FillStippled;
74 /*gcv.function=GXclear;*/
75 gcv.stipple=stipple_pixmap;
76 gcvmask=GCFillStyle|GCStipple/*|GCFunction*/;
77 if(style->font!=NULL && style->font->fontstruct!=NULL){
78 gcv.font=style->font->fontstruct->fid;
82 style->stipple_gc=XCreateGC(dpy, root, gcvmask, &gcv);
83 XCopyGC(dpy, style->normal_gc,
84 GCLineStyle|GCLineWidth|GCJoinStyle|GCCapStyle,
87 XFreePixmap(dpy, stipple_pixmap);
89 /* Create tag pixmap and copying GC */
90 style->tag_pixmap_w=5;
91 style->tag_pixmap_h=5;
92 style->tag_pixmap=XCreatePixmap(dpy, root, 5, 5, 1);
94 XSetForeground(dpy, tmp_gc, 0);
95 XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 0, 0, 5, 5);
96 XSetForeground(dpy, tmp_gc, 1);
97 XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 0, 0, 5, 2);
98 XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 3, 2, 2, 3);
100 gcv.foreground=DE_BLACK(rootwin);
101 gcv.background=DE_WHITE(rootwin);
103 gcvmask=GCLineWidth|GCForeground|GCBackground;
105 style->copy_gc=XCreateGC(dpy, root, gcvmask, &gcv);
107 XFreeGC(dpy, tmp_gc);
109 style->tabbrush_data_ok=TRUE;
116 /*{{{ Style lookup */
119 static DEStyle *styles=NULL;
122 DEStyle *de_get_style(WRootWin *rootwin, const GrStyleSpec *spec)
124 DEStyle *style, *maxstyle=NULL;
125 int score, maxscore=0;
127 for(style=styles; style!=NULL; style=style->next){
128 if(style->rootwin!=rootwin)
130 score=gr_stylespec_score(&style->spec, spec);
144 /*{{{ Style initialisation and deinitialisation */
147 void destyle_unref(DEStyle *style)
150 if(style->usecount==0){
151 destyle_deinit(style);
157 void destyle_deinit(DEStyle *style)
161 UNLINK_ITEM(styles, style, next, prev);
163 gr_stylespec_unalloc(&style->spec);
165 if(style->font!=NULL){
166 de_free_font(style->font);
170 if(style->cgrp_alloced)
171 de_free_colour_group(style->rootwin, &(style->cgrp));
173 for(i=0; i<style->n_extra_cgrps; i++)
174 de_free_colour_group(style->rootwin, style->extra_cgrps+i);
176 if(style->extra_cgrps!=NULL)
177 free(style->extra_cgrps);
179 extl_unref_table(style->data_table);
181 XFreeGC(ioncore_g.dpy, style->normal_gc);
183 if(style->tabbrush_data_ok){
184 XFreeGC(ioncore_g.dpy, style->copy_gc);
185 XFreeGC(ioncore_g.dpy, style->stipple_gc);
186 XFreePixmap(ioncore_g.dpy, style->tag_pixmap);
189 XSync(ioncore_g.dpy, False);
191 if(style->based_on!=NULL){
192 destyle_unref(style->based_on);
193 style->based_on=NULL;
198 static void dump_style(DEStyle *style)
200 /* Allow the style still be used but get if off the list. */
201 UNLINK_ITEM(styles, style, next, prev);
202 destyle_unref(style);
206 bool destyle_init(DEStyle *style, WRootWin *rootwin, const char *name)
208 if(!gr_stylespec_load(&style->spec, name))
211 style->based_on=NULL;
214 /* Fallback brushes are not released on de_reset() */
215 style->is_fallback=FALSE;
217 style->rootwin=rootwin;
222 style->border.style=DEBORDER_INLAID;
223 style->border.sides=DEBORDER_ALL;
227 style->textalign=DEALIGN_CENTER;
229 style->cgrp_alloced=FALSE;
230 style->cgrp.bg=DE_BLACK(rootwin);
231 style->cgrp.pad=DE_BLACK(rootwin);
232 style->cgrp.fg=DE_WHITE(rootwin);
233 style->cgrp.hl=DE_WHITE(rootwin);
234 style->cgrp.sh=DE_WHITE(rootwin);
235 gr_stylespec_init(&style->cgrp.spec);
239 style->transparency_mode=GR_TRANSPARENCY_NO;
241 style->n_extra_cgrps=0;
242 style->extra_cgrps=NULL;
244 style->data_table=extl_table_none();
246 create_normal_gc(style, rootwin);
248 style->tabbrush_data_ok=FALSE;
254 static DEStyle *do_create_style(WRootWin *rootwin, const char *name)
256 DEStyle *style=ALLOC(DEStyle);
258 if(!destyle_init(style, rootwin, name)){
267 DEStyle *de_create_style(WRootWin *rootwin, const char *name)
269 DEStyle *oldstyle, *style;
272 style=do_create_style(rootwin, name);
277 for(oldstyle=styles; oldstyle!=NULL; oldstyle=oldstyle->next){
278 if(oldstyle->rootwin!=rootwin)
280 if(gr_stylespec_equals(&oldstyle->spec, &style->spec))
284 if(oldstyle!=NULL && !oldstyle->is_fallback)
285 dump_style(oldstyle);
287 LINK_ITEM_FIRST(styles, style, next, prev);
295 * Clear all styles from drawing engine memory.
300 DEStyle *style, *next;
301 for(style=styles; style!=NULL; style=next){
303 if(!style->is_fallback)
309 void de_deinit_styles()
311 DEStyle *style, *next;
312 for(style=styles; style!=NULL; style=next){
314 if(style->usecount>1){
315 warn(TR("Style is still in use [%d] but the module "
316 "is being unloaded!"), style->usecount);