1 #include "thinice_rc_style.h"
2 #include "thinice_style.h"
3
4 G_DEFINE_DYNAMIC_TYPE (ThiniceRcStyle, thinice_rc_style, GTK_TYPE_RC_STYLE)
5
6
7 static guint thinice_rc_style_parse (GtkRcStyle *rc_style,
8 GtkSettings *settings,
9 GScanner *scanner);
10 static void thinice_rc_style_merge (GtkRcStyle *dest,
11 GtkRcStyle *src);
12
13 static GtkStyle *thinice_rc_style_create_style (GtkRcStyle *rc_style);
14
15
16 static struct
17 {
18 gchar *name;
19 guint token;
20 }
21 thinice_rc_symbols[] =
22 {
23 { "rect_scrollbar", TOKEN_RECTSCROLLBAR },
24 { "scrollbar_marks", TOKEN_SCROLLBARMARKS },
25 { "scroll_button_marks", TOKEN_SCROLLBUTTONMARKS },
26 { "handlebox_marks", TOKEN_HANDLEBOXMARKS },
27 { "mark_type1", TOKEN_MARKTYPE1 },
28 { "mark_type2", TOKEN_MARKTYPE2 },
29 { "paned_dots", TOKEN_PANEDDOTS },
30
31 { "TRUE", TOKEN_TRUE },
32 { "FALSE", TOKEN_FALSE },
33
34 { "NOTHING", TOKEN_NOTHING },
35 { "SLASH", TOKEN_SLASH },
36 { "INVSLASH", TOKEN_INVSLASH },
37 { "DOT", TOKEN_DOT },
38 { "INVDOT", TOKEN_INVDOT },
39 { "ARROW", TOKEN_ARROW },
40
41 { "FULL", TOKEN_FULL },
42 { "SOME", TOKEN_SOME },
43 { "NONE", TOKEN_NONE },
44
45 };
46
47 static guint n_thinice_rc_symbols = sizeof(thinice_rc_symbols) / sizeof(thinice_rc_symbols[0]);
48
49 void
thinice_rc_style_register_types(GTypeModule * module)50 thinice_rc_style_register_types (GTypeModule *module)
51 {
52 thinice_rc_style_register_type (module);
53 }
54
55 static void
thinice_rc_style_init(ThiniceRcStyle * style)56 thinice_rc_style_init (ThiniceRcStyle *style)
57 {
58 style->flags = 0;
59 }
60
61 static void
thinice_rc_style_class_init(ThiniceRcStyleClass * klass)62 thinice_rc_style_class_init (ThiniceRcStyleClass *klass)
63 {
64 GtkRcStyleClass *rc_style_class = GTK_RC_STYLE_CLASS (klass);
65
66 rc_style_class->parse = thinice_rc_style_parse;
67 rc_style_class->merge = thinice_rc_style_merge;
68 rc_style_class->create_style = thinice_rc_style_create_style;
69 }
70
71 static void
thinice_rc_style_class_finalize(ThiniceRcStyleClass * klass)72 thinice_rc_style_class_finalize (ThiniceRcStyleClass *klass)
73 {
74 }
75
76 #if 0
77 static guint
78 thinice_rc_parse_int(GScanner *scanner,
79 GTokenType wanted_token,
80 guint *retval)
81 {
82 guint token;
83
84 token = g_scanner_get_next_token(scanner);
85 if (token != wanted_token)
86 return wanted_token;
87
88 token = g_scanner_get_next_token(scanner);
89 if (token != G_TOKEN_EQUAL_SIGN)
90 return wanted_token;
91
92 token = g_scanner_get_next_token(scanner);
93 if (token != G_TOKEN_INT)
94 return G_TOKEN_INT;
95
96 *retval = g_scanner_cur_value(scanner).v_int;
97
98 return G_TOKEN_NONE;
99 }
100 #endif
101
102 static guint
thinice_rc_parse_boolean(GScanner * scanner,GTokenType wanted_token,guint * retval)103 thinice_rc_parse_boolean(GScanner *scanner,
104 GTokenType wanted_token,
105 guint *retval)
106 {
107 guint token;
108
109 token = g_scanner_get_next_token(scanner);
110 if (token != wanted_token)
111 return wanted_token;
112
113 token = g_scanner_get_next_token(scanner);
114 if (token != G_TOKEN_EQUAL_SIGN)
115 return G_TOKEN_EQUAL_SIGN;
116
117 token = g_scanner_get_next_token(scanner);
118 if (token == TOKEN_TRUE)
119 *retval = TRUE;
120 else if (token == TOKEN_FALSE)
121 *retval = FALSE;
122 else
123 return TOKEN_TRUE;
124
125 return G_TOKEN_NONE;
126 }
127
128 static guint
thinice_rc_parse_marktype(GScanner * scanner,GTokenType wanted_token,guint * retval)129 thinice_rc_parse_marktype(GScanner *scanner,
130 GTokenType wanted_token,
131 guint *retval)
132 {
133 guint token;
134
135 token = g_scanner_get_next_token(scanner);
136 if (token != wanted_token)
137 return wanted_token;
138
139 token = g_scanner_get_next_token(scanner);
140 if (token != G_TOKEN_EQUAL_SIGN)
141 return G_TOKEN_EQUAL_SIGN;
142
143 token = g_scanner_get_next_token(scanner);
144 switch (token)
145 {
146 case TOKEN_NOTHING:
147 *retval = MARKS_NOTHING;
148 break;
149 case TOKEN_SLASH:
150 *retval = MARKS_SLASH;
151 break;
152 case TOKEN_INVSLASH:
153 *retval = MARKS_INVSLASH;
154 break;
155 case TOKEN_DOT:
156 *retval = MARKS_DOT;
157 break;
158 case TOKEN_INVDOT:
159 *retval = MARKS_INVDOT;
160 break;
161 case TOKEN_ARROW:
162 *retval = MARKS_ARROW;
163 break;
164 default:
165 return TOKEN_NOTHING;
166 }
167
168 return G_TOKEN_NONE;
169 }
170
171 static guint
thinice_rc_parse_paned(GScanner * scanner,GTokenType wanted_token,guint * retval)172 thinice_rc_parse_paned(GScanner *scanner,
173 GTokenType wanted_token,
174 guint *retval)
175 {
176 guint token;
177
178 token = g_scanner_get_next_token(scanner);
179 if (token != wanted_token)
180 return wanted_token;
181
182 token = g_scanner_get_next_token(scanner);
183 if (token != G_TOKEN_EQUAL_SIGN)
184 return G_TOKEN_EQUAL_SIGN;
185
186 token = g_scanner_get_next_token(scanner);
187 switch (token)
188 {
189 case TOKEN_NONE:
190 *retval = PANED_DOTSNONE;
191 break;
192 case TOKEN_SOME:
193 *retval = PANED_DOTSSOME;
194 break;
195 case TOKEN_FULL:
196 *retval = PANED_DOTSFULL;
197 break;
198 default:
199 return TOKEN_NOTHING;
200 }
201
202 return G_TOKEN_NONE;
203 }
204
205 static guint
thinice_rc_style_parse(GtkRcStyle * rc_style,GtkSettings * settings,GScanner * scanner)206 thinice_rc_style_parse (GtkRcStyle *rc_style,
207 GtkSettings *settings,
208 GScanner *scanner)
209 {
210 static GQuark scope_id = 0;
211 ThiniceRcStyle *theme_data = THINICE_RC_STYLE (rc_style);
212 guint old_scope;
213 guint token;
214 guint i;
215
216 /* Set up a new scope in this scanner. */
217
218 /*
219 g_print("thinice_rc_parse_rc_style(\"%s\")\n", rc_style->name);
220 */
221 if (!scope_id)
222 scope_id = g_quark_from_string("thinice_theme_engine");
223
224 /* If we bail out due to errors, we *don't* reset the scope, so the
225 * error messaging code can make sense of our tokens.
226 */
227 old_scope = g_scanner_set_scope(scanner, scope_id);
228
229 /* Now check if we already added our symbols to this scope
230 * (in some previous call to thinice_rc_parse_rc_style for the
231 * same scanner.
232 */
233
234 if (!g_scanner_lookup_symbol(scanner, thinice_rc_symbols[0].name))
235 {
236 for (i = 0; i < n_thinice_rc_symbols; i++)
237 {
238 g_scanner_scope_add_symbol(scanner, scope_id,
239 thinice_rc_symbols[i].name,
240 GINT_TO_POINTER(thinice_rc_symbols[i].token));
241 }
242 }
243
244 /* We're ready to go, now parse the top level */
245
246 theme_data->scrollbar_type = DEFAULT_SCROLLSHAPE;
247 theme_data->scrollbar_marks = DEFAULT_SCROLLBARMARKS;
248 theme_data->scroll_button_marks = DEFAULT_SCROLLBUTTONMARKS;
249 theme_data->handlebox_marks = DEFAULT_HANDLEBOXMARKS;
250 theme_data->mark_type1 = DEFAULT_MARKTYPE1;
251 theme_data->mark_type2 = DEFAULT_MARKTYPE2;
252
253 token = g_scanner_peek_next_token(scanner);
254 while (token != G_TOKEN_RIGHT_CURLY)
255 {
256 switch (token)
257 {
258 case TOKEN_RECTSCROLLBAR:
259 token = thinice_rc_parse_boolean(scanner, TOKEN_RECTSCROLLBAR, &i);
260 if (token != G_TOKEN_NONE)
261 break;
262 if (i == FALSE)
263 theme_data->scrollbar_type = SCROLL_SHAPED;
264 else
265 theme_data->scrollbar_type = SCROLL_RECT;
266 theme_data->flags |= THINICE_FLAG_SCROLLBAR_TYPE;
267 break;
268
269 case TOKEN_SCROLLBUTTONMARKS:
270 token = thinice_rc_parse_boolean(scanner, TOKEN_SCROLLBUTTONMARKS, &i);
271 if (token != G_TOKEN_NONE)
272 break;
273 if (i == TRUE)
274 theme_data->mark_type2 = MARKS_SLASH;
275 else
276 theme_data->mark_type2 = MARKS_NOTHING;
277 theme_data->flags |= THINICE_FLAG_MARK_TYPE2;
278 /*
279 if (i == TRUE)
280 theme_data->scroll_button_marks = MARKS_ON;
281 else
282 theme_data->scroll_button_marks = MARKS_OFF;
283 */
284 break;
285
286 case TOKEN_SCROLLBARMARKS:
287 token = thinice_rc_parse_boolean(scanner, TOKEN_SCROLLBARMARKS, &i);
288 if (token != G_TOKEN_NONE)
289 break;
290 if (i == TRUE)
291 theme_data->mark_type1 = MARKS_SLASH;
292 else
293 theme_data->mark_type1 = MARKS_NOTHING;
294 theme_data->flags |= THINICE_FLAG_MARK_TYPE1;
295 /*
296 if (i == TRUE)
297 theme_data->scrollbar_marks = MARKS_ON;
298 else
299 theme_data->scrollbar_marks = MARKS_OFF;
300 */
301 break;
302
303 case TOKEN_HANDLEBOXMARKS:
304 token = thinice_rc_parse_boolean(scanner, TOKEN_HANDLEBOXMARKS, &i);
305 if (token != G_TOKEN_NONE)
306 break;
307 if (i == TRUE)
308 theme_data->handlebox_marks = MARKS_ON;
309 else
310 theme_data->handlebox_marks = MARKS_OFF;
311 theme_data->flags |= THINICE_FLAG_HANDLEBOX_MARKS;
312 break;
313
314 case TOKEN_MARKTYPE1:
315 token = thinice_rc_parse_marktype(scanner, TOKEN_MARKTYPE1, &i);
316 if (token != G_TOKEN_NONE)
317 break;
318 theme_data->mark_type1 = i;
319 theme_data->flags |= THINICE_FLAG_MARK_TYPE1;
320 break;
321
322 case TOKEN_MARKTYPE2:
323 token = thinice_rc_parse_marktype(scanner, TOKEN_MARKTYPE2, &i);
324 if (token != G_TOKEN_NONE)
325 break;
326 theme_data->mark_type2 = i;
327 theme_data->flags |= THINICE_FLAG_MARK_TYPE2;
328 break;
329
330 case TOKEN_PANEDDOTS:
331 token = thinice_rc_parse_paned(scanner, TOKEN_PANEDDOTS, &i);
332 if (token != G_TOKEN_NONE)
333 break;
334 theme_data->paned_dots = i;
335 theme_data->flags |= THINICE_FLAG_PANED_DOTS;
336 break;
337
338 default:
339 g_scanner_get_next_token(scanner);
340 token = G_TOKEN_RIGHT_CURLY;
341 break;
342 }
343
344 if (token != G_TOKEN_NONE)
345 {
346 return token;
347 }
348 token = g_scanner_peek_next_token(scanner);
349 }
350
351 g_scanner_get_next_token(scanner);
352
353 g_scanner_set_scope(scanner, old_scope);
354
355 return G_TOKEN_NONE;
356 }
357
358 static void
thinice_rc_style_merge(GtkRcStyle * dest,GtkRcStyle * src)359 thinice_rc_style_merge (GtkRcStyle * dest,
360 GtkRcStyle * src)
361 {
362 if (THINICE_IS_RC_STYLE (src)) {
363 ThiniceRcFlags flags;
364 ThiniceRcStyle *src_data = THINICE_RC_STYLE (src);
365 ThiniceRcStyle *dest_data = THINICE_RC_STYLE (dest);
366
367 flags = (~dest_data->flags) & src_data->flags;
368
369 if (flags & THINICE_FLAG_SCROLLBAR_TYPE)
370 dest_data->scrollbar_type = src_data->scrollbar_type;
371 if (flags & THINICE_FLAG_SCROLLBAR_MARKS)
372 dest_data->scrollbar_marks = src_data->scrollbar_marks;
373 if (flags & THINICE_FLAG_SCROLL_BUTTON_MARKS)
374 dest_data->scroll_button_marks = src_data->scroll_button_marks;
375 if (flags & THINICE_FLAG_HANDLEBOX_MARKS)
376 dest_data->handlebox_marks = src_data->handlebox_marks;
377 if (flags & THINICE_FLAG_MARK_TYPE1)
378 dest_data->mark_type1 = src_data->mark_type1;
379 if (flags & THINICE_FLAG_MARK_TYPE2)
380 dest_data->mark_type2 = src_data->mark_type2;
381 if (flags & THINICE_FLAG_PANED_DOTS)
382 dest_data->paned_dots = src_data->paned_dots;
383
384 dest_data->flags = dest_data->flags | src_data->flags;
385 }
386
387 GTK_RC_STYLE_CLASS (thinice_rc_style_parent_class)->merge (dest, src);
388 }
389
390 /* Create an empty style suitable to this RC style
391 */
392 static GtkStyle *
thinice_rc_style_create_style(GtkRcStyle * rc_style)393 thinice_rc_style_create_style (GtkRcStyle *rc_style)
394 {
395 return GTK_STYLE (g_object_new (THINICE_TYPE_STYLE, NULL));
396 }
397