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