Revert "Remove dead 'uses_root' flag from WScreen"
[notion.git] / de / style.c
blobd5debb9c6530b3b9925dddda292943c924ee86a2
1 /*
2 * ion/de/style.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
11 #include <libextl/extl.h>
13 #include <ioncore/common.h>
14 #include <ioncore/rootwin.h>
15 #include <ioncore/extlconv.h>
16 #include <ioncore/ioncore.h>
18 #include "brush.h"
19 #include "font.h"
20 #include "colour.h"
21 #include "private.h"
22 #include "style.h"
25 /*{{{ GC creation */
28 static void create_normal_gc(DEStyle *style, WRootWin *rootwin)
30 XGCValues gcv;
31 ulong gcvmask;
32 GC gc;
34 /* Create normal gc */
35 gcv.line_style=LineSolid;
36 gcv.line_width=1;
37 gcv.join_style=JoinBevel;
38 gcv.cap_style=CapButt;
39 gcv.fill_style=FillSolid;
40 gcvmask=(GCLineStyle|GCLineWidth|GCFillStyle|
41 GCJoinStyle|GCCapStyle);
43 style->normal_gc=XCreateGC(ioncore_g.dpy, WROOTWIN_ROOT(rootwin),
44 gcvmask, &gcv);
48 void destyle_create_tab_gcs(DEStyle *style)
50 Display *dpy=ioncore_g.dpy;
51 WRootWin *rootwin=style->rootwin;
52 Window root=WROOTWIN_ROOT(rootwin);
53 Pixmap stipple_pixmap;
54 XGCValues gcv;
55 ulong gcvmask;
56 GC tmp_gc;
58 /* Create a temporary 1-bit GC for drawing the tag and stipple pixmaps */
59 stipple_pixmap=XCreatePixmap(dpy, root, 2, 2, 1);
60 gcv.foreground=1;
61 tmp_gc=XCreateGC(dpy, stipple_pixmap, GCForeground, &gcv);
63 /* Create stipple pattern and stipple GC */
64 XDrawPoint(dpy, stipple_pixmap, tmp_gc, 0, 0);
65 XDrawPoint(dpy, stipple_pixmap, tmp_gc, 1, 1);
66 XSetForeground(dpy, tmp_gc, 0);
67 XDrawPoint(dpy, stipple_pixmap, tmp_gc, 1, 0);
68 XDrawPoint(dpy, stipple_pixmap, tmp_gc, 0, 1);
70 gcv.fill_style=FillStippled;
71 /*gcv.function=GXclear;*/
72 gcv.stipple=stipple_pixmap;
73 gcvmask=GCFillStyle|GCStipple/*|GCFunction*/;
74 if(style->font!=NULL && style->font->fontstruct!=NULL){
75 gcv.font=style->font->fontstruct->fid;
76 gcvmask|=GCFont;
79 style->stipple_gc=XCreateGC(dpy, root, gcvmask, &gcv);
80 XCopyGC(dpy, style->normal_gc,
81 GCLineStyle|GCLineWidth|GCJoinStyle|GCCapStyle,
82 style->stipple_gc);
84 XFreePixmap(dpy, stipple_pixmap);
86 /* Create tag pixmap and copying GC */
87 style->tag_pixmap_w=5;
88 style->tag_pixmap_h=5;
89 style->tag_pixmap=XCreatePixmap(dpy, root, 5, 5, 1);
91 XSetForeground(dpy, tmp_gc, 0);
92 XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 0, 0, 5, 5);
93 XSetForeground(dpy, tmp_gc, 1);
94 XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 0, 0, 5, 2);
95 XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 3, 2, 2, 3);
97 gcv.foreground=DE_BLACK(rootwin);
98 gcv.background=DE_WHITE(rootwin);
99 gcv.line_width=2;
100 gcvmask=GCLineWidth|GCForeground|GCBackground;
102 style->copy_gc=XCreateGC(dpy, root, gcvmask, &gcv);
104 XFreeGC(dpy, tmp_gc);
106 style->tabbrush_data_ok=TRUE;
110 /*}}}*/
113 /*{{{ Style lookup */
116 static DEStyle *styles=NULL;
119 DEStyle *de_get_style(WRootWin *rootwin, const GrStyleSpec *spec)
121 DEStyle *style, *maxstyle=NULL;
122 int score, maxscore=0;
124 for(style=styles; style!=NULL; style=style->next){
125 if(style->rootwin!=rootwin)
126 continue;
127 score=gr_stylespec_score(&style->spec, spec);
128 if(score>maxscore){
129 maxstyle=style;
130 maxscore=score;
134 return maxstyle;
138 /*}}}*/
141 /*{{{ Style initialisation and deinitialisation */
144 void destyle_unref(DEStyle *style)
146 style->usecount--;
147 if(style->usecount==0){
148 destyle_deinit(style);
149 free(style);
154 void destyle_deinit(DEStyle *style)
156 int i;
158 UNLINK_ITEM(styles, style, next, prev);
160 gr_stylespec_unalloc(&style->spec);
162 if(style->font!=NULL){
163 de_free_font(style->font);
164 style->font=NULL;
167 if(style->cgrp_alloced)
168 de_free_colour_group(style->rootwin, &(style->cgrp));
170 for(i=0; i<style->n_extra_cgrps; i++)
171 de_free_colour_group(style->rootwin, style->extra_cgrps+i);
173 if(style->extra_cgrps!=NULL)
174 free(style->extra_cgrps);
176 extl_unref_table(style->extras_table);
178 XFreeGC(ioncore_g.dpy, style->normal_gc);
180 if(style->tabbrush_data_ok){
181 XFreeGC(ioncore_g.dpy, style->copy_gc);
182 XFreeGC(ioncore_g.dpy, style->stipple_gc);
183 XFreePixmap(ioncore_g.dpy, style->tag_pixmap);
186 XSync(ioncore_g.dpy, False);
188 if(style->based_on!=NULL){
189 destyle_unref(style->based_on);
190 style->based_on=NULL;
195 void destyle_dump(DEStyle *style)
197 /* Allow the style still be used but get if off the list. */
198 UNLINK_ITEM(styles, style, next, prev);
199 destyle_unref(style);
203 bool destyle_init(DEStyle *style, WRootWin *rootwin, const char *name)
205 if(!gr_stylespec_load(&style->spec, name))
206 return FALSE;
208 style->based_on=NULL;
210 style->usecount=1;
211 /* Fallback brushes are not released on de_reset() */
212 style->is_fallback=FALSE;
214 style->rootwin=rootwin;
216 style->border.sh=1;
217 style->border.hl=1;
218 style->border.pad=1;
219 style->border.style=DEBORDER_INLAID;
220 style->border.sides=DEBORDER_ALL;
222 style->spacing=0;
224 style->textalign=DEALIGN_CENTER;
226 style->cgrp_alloced=FALSE;
227 style->cgrp.bg=DE_BLACK(rootwin);
228 style->cgrp.pad=DE_BLACK(rootwin);
229 style->cgrp.fg=DE_WHITE(rootwin);
230 style->cgrp.hl=DE_WHITE(rootwin);
231 style->cgrp.sh=DE_WHITE(rootwin);
232 gr_stylespec_init(&style->cgrp.spec);
234 style->font=NULL;
236 style->transparency_mode=GR_TRANSPARENCY_NO;
238 style->n_extra_cgrps=0;
239 style->extra_cgrps=NULL;
241 style->extras_table=extl_table_none();
243 create_normal_gc(style, rootwin);
245 style->tabbrush_data_ok=FALSE;
247 return TRUE;
251 DEStyle *de_create_style(WRootWin *rootwin, const char *name)
253 DEStyle *style=ALLOC(DEStyle);
254 if(style!=NULL){
255 if(!destyle_init(style, rootwin, name)){
256 free(style);
257 return NULL;
260 return style;
264 void destyle_add(DEStyle *style)
266 LINK_ITEM_FIRST(styles, style, next, prev);
270 /*EXTL_DOC
271 * Clear all styles from drawing engine memory.
273 EXTL_EXPORT
274 void de_reset()
276 DEStyle *style, *next;
277 for(style=styles; style!=NULL; style=next){
278 next=style->next;
279 if(!style->is_fallback)
280 destyle_dump(style);
285 void de_deinit_styles()
287 DEStyle *style, *next;
288 for(style=styles; style!=NULL; style=next){
289 next=style->next;
290 if(style->usecount>1){
291 warn(TR("Style is still in use [%d] but the module "
292 "is being unloaded!"), style->usecount);
294 destyle_dump(style);
299 /*}}}*/