fix crash when copy'ing latent plugins
[ardour.git] / libs / clearlooks-older / clearlooks_rc_style.c
1 /* Clearlooks theme engine
2  * Copyright (C) 2005 Richard Stellingwerff.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Written by Owen Taylor <otaylor@redhat.com>
20  * and by Alexander Larsson <alexl@redhat.com>
21  * Modified by Richard Stellingwerff <remenic@gmail.com>
22  */
23
24 #include "clearlooks_style.h"
25 #include "clearlooks_rc_style.h"
26
27 static void      clearlooks_rc_style_init         (ClearlooksRcStyle      *style);
28 static void      clearlooks_rc_style_class_init   (ClearlooksRcStyleClass *klass);
29 static GtkStyle *clearlooks_rc_style_create_style (GtkRcStyle             *rc_style);
30 static guint     clearlooks_rc_style_parse        (GtkRcStyle             *rc_style,
31                                                    GtkSettings            *settings,
32                                                    GScanner               *scanner);
33 static void      clearlooks_rc_style_merge        (GtkRcStyle             *dest,
34                                                    GtkRcStyle             *src);
35
36
37 static GtkRcStyleClass *parent_class;
38
39 GType clearlooks_type_rc_style = 0;
40
41 enum
42 {
43   TOKEN_SPOTCOLOR = G_TOKEN_LAST + 1,
44   TOKEN_CONTRAST,
45   TOKEN_SUNKENMENU,
46   TOKEN_PROGRESSBARSTYLE,
47   TOKEN_MENUBARSTYLE,
48   TOKEN_MENUITEMSTYLE,
49   TOKEN_LISTVIEWITEMSTYLE
50 };
51
52 static struct
53   {
54     const gchar        *name;
55     guint               token;
56   }
57 theme_symbols[] =
58 {
59   { "spotcolor",                TOKEN_SPOTCOLOR  },
60   { "contrast",                 TOKEN_CONTRAST  },
61   { "sunkenmenubar",    TOKEN_SUNKENMENU },
62   { "progressbarstyle",  TOKEN_PROGRESSBARSTYLE },
63   { "menubarstyle",     TOKEN_MENUBARSTYLE },
64   { "menuitemstyle",    TOKEN_MENUITEMSTYLE },
65   { "listviewitemstyle", TOKEN_LISTVIEWITEMSTYLE }
66 };
67
68
69 void
70 clearlooks_rc_style_register_type (GTypeModule *module)
71 {
72   static const GTypeInfo object_info =
73   {
74     sizeof (ClearlooksRcStyleClass),
75     (GBaseInitFunc) NULL,
76     (GBaseFinalizeFunc) NULL,
77     (GClassInitFunc) clearlooks_rc_style_class_init,
78     NULL,           /* class_finalize */
79     NULL,           /* class_data */
80     sizeof (ClearlooksRcStyle),
81     0,              /* n_preallocs */
82     (GInstanceInitFunc) clearlooks_rc_style_init,
83     NULL
84   };
85
86   clearlooks_type_rc_style = g_type_module_register_type (module,
87                                                      GTK_TYPE_RC_STYLE,
88                                                      "ClearlooksRcStyle",
89                                                      &object_info, 0);
90 }
91
92 static void
93 clearlooks_rc_style_init (ClearlooksRcStyle *clearlooks_rc)
94 {
95   clearlooks_rc->has_spot_color = FALSE;
96   clearlooks_rc->contrast = 1.0;
97   clearlooks_rc->sunkenmenubar = 1;
98   clearlooks_rc->progressbarstyle = 0;
99   clearlooks_rc->menubarstyle = 0;
100   clearlooks_rc->menuitemstyle = 1;
101   clearlooks_rc->listviewitemstyle = 1;
102 }
103
104 static void
105 clearlooks_rc_style_class_init (ClearlooksRcStyleClass *klass)
106 {
107   GtkRcStyleClass *rc_style_class = GTK_RC_STYLE_CLASS (klass);
108
109   parent_class = g_type_class_peek_parent (klass);
110
111   rc_style_class->parse = clearlooks_rc_style_parse;
112   rc_style_class->create_style = clearlooks_rc_style_create_style;
113   rc_style_class->merge = clearlooks_rc_style_merge;
114 }
115
116 static guint
117 theme_parse_color(GtkSettings  *settings,
118                   GScanner     *scanner,
119                   GdkColor     *color)
120 {
121   guint token;
122
123   /* Skip 'blah_color' */
124   token = g_scanner_get_next_token(scanner);
125
126   token = g_scanner_get_next_token(scanner);
127   if (token != G_TOKEN_EQUAL_SIGN)
128     return G_TOKEN_EQUAL_SIGN;
129
130   return gtk_rc_parse_color (scanner, color);
131 }
132
133 static guint
134 theme_parse_contrast(GtkSettings  *settings,
135                      GScanner     *scanner,
136                      double       *contrast)
137 {
138   guint token;
139
140   /* Skip 'contrast' */
141   token = g_scanner_get_next_token(scanner);
142
143   token = g_scanner_get_next_token(scanner);
144   if (token != G_TOKEN_EQUAL_SIGN)
145     return G_TOKEN_EQUAL_SIGN;
146
147   token = g_scanner_get_next_token(scanner);
148   if (token != G_TOKEN_FLOAT)
149     return G_TOKEN_FLOAT;
150
151   *contrast = scanner->value.v_float;
152
153   return G_TOKEN_NONE;
154 }
155
156 static guint
157 theme_parse_sunkenmenubar(GtkSettings  *settings,
158                      GScanner     *scanner,
159                      guint8       *sunken)
160 {
161   guint token;
162
163   /* Skip 'sunkenmenubar' */
164   token = g_scanner_get_next_token(scanner);
165
166   token = g_scanner_get_next_token(scanner);
167   if (token != G_TOKEN_EQUAL_SIGN)
168     return G_TOKEN_EQUAL_SIGN;
169
170   token = g_scanner_get_next_token(scanner);
171   if (token != G_TOKEN_INT)
172     return G_TOKEN_INT;
173
174   *sunken = scanner->value.v_int;
175
176   return G_TOKEN_NONE;
177 }
178
179 static guint
180 theme_parse_progressbarstyle(GtkSettings  *settings,
181                      GScanner     *scanner,
182                      guint8       *progressbarstyle)
183 {
184   guint token;
185
186   /* Skip 'sunkenmenubar' */
187   token = g_scanner_get_next_token(scanner);
188
189   token = g_scanner_get_next_token(scanner);
190   if (token != G_TOKEN_EQUAL_SIGN)
191     return G_TOKEN_EQUAL_SIGN;
192
193   token = g_scanner_get_next_token(scanner);
194   if (token != G_TOKEN_INT)
195     return G_TOKEN_INT;
196
197   *progressbarstyle = scanner->value.v_int;
198
199   return G_TOKEN_NONE;
200 }
201
202 static guint
203 theme_parse_menubarstyle(GtkSettings  *settings,
204                      GScanner     *scanner,
205                      guint8       *menubarstyle)
206 {
207   guint token;
208
209   /* Skip 'menubarstyle' */
210   token = g_scanner_get_next_token(scanner);
211
212   token = g_scanner_get_next_token(scanner);
213   if (token != G_TOKEN_EQUAL_SIGN)
214     return G_TOKEN_EQUAL_SIGN;
215
216   token = g_scanner_get_next_token(scanner);
217   if (token != G_TOKEN_INT)
218     return G_TOKEN_INT;
219
220   *menubarstyle = scanner->value.v_int;
221
222   return G_TOKEN_NONE;
223 }
224
225 static guint
226 theme_parse_menuitemstyle(GtkSettings  *settings,
227                      GScanner     *scanner,
228                      guint8       *menuitemstyle)
229 {
230   guint token;
231
232   /* Skip 'sunkenmenubar' */
233   token = g_scanner_get_next_token(scanner);
234
235   token = g_scanner_get_next_token(scanner);
236   if (token != G_TOKEN_EQUAL_SIGN)
237     return G_TOKEN_EQUAL_SIGN;
238
239   token = g_scanner_get_next_token(scanner);
240   if (token != G_TOKEN_INT)
241     return G_TOKEN_INT;
242
243   *menuitemstyle = scanner->value.v_int;
244
245   return G_TOKEN_NONE;
246 }
247
248 static guint
249 theme_parse_listviewitemstyle(GtkSettings  *settings,
250                           GScanner     *scanner,
251                           guint8       *listviewitemstyle)
252 {
253   guint token;
254
255   token = g_scanner_get_next_token(scanner);
256
257   token = g_scanner_get_next_token(scanner);
258
259   if (token != G_TOKEN_EQUAL_SIGN)
260      return G_TOKEN_EQUAL_SIGN;
261
262   token = g_scanner_get_next_token(scanner);
263   if (token != G_TOKEN_INT)
264     return G_TOKEN_INT;
265
266   *listviewitemstyle = scanner->value.v_int;
267
268   return G_TOKEN_NONE;
269 }
270
271 static guint
272 clearlooks_rc_style_parse (GtkRcStyle *rc_style,
273                            GtkSettings  *settings,
274                            GScanner   *scanner)
275
276 {
277   static GQuark scope_id = 0;
278   ClearlooksRcStyle *clearlooks_style = CLEARLOOKS_RC_STYLE (rc_style);
279
280   guint old_scope;
281   guint token;
282   guint i;
283
284   /* Set up a new scope in this scanner. */
285
286   if (!scope_id)
287     scope_id = g_quark_from_string("clearlooks_theme_engine");
288
289   /* If we bail out due to errors, we *don't* reset the scope, so the
290    * error messaging code can make sense of our tokens.
291    */
292   old_scope = g_scanner_set_scope(scanner, scope_id);
293
294   /* Now check if we already added our symbols to this scope
295    * (in some previous call to clearlooks_rc_style_parse for the
296    * same scanner.
297    */
298
299   if (!g_scanner_lookup_symbol(scanner, theme_symbols[0].name))
300     {
301       g_scanner_freeze_symbol_table(scanner);
302       for (i = 0; i < G_N_ELEMENTS (theme_symbols); i++)
303         g_scanner_scope_add_symbol(scanner, scope_id,
304                                    theme_symbols[i].name,
305                                    GINT_TO_POINTER(theme_symbols[i].token));
306       g_scanner_thaw_symbol_table(scanner);
307     }
308
309   /* We're ready to go, now parse the top level */
310
311   token = g_scanner_peek_next_token(scanner);
312   while (token != G_TOKEN_RIGHT_CURLY)
313     {
314       switch (token)
315         {
316         case TOKEN_SPOTCOLOR:
317           token = theme_parse_color(settings, scanner, &clearlooks_style->spot_color);
318           clearlooks_style->has_spot_color = TRUE;
319           break;
320         case TOKEN_CONTRAST:
321           token = theme_parse_contrast(settings, scanner, &clearlooks_style->contrast);
322           break;
323         case TOKEN_SUNKENMENU:
324           token = theme_parse_sunkenmenubar(settings, scanner, &clearlooks_style->sunkenmenubar);
325           break;
326         case TOKEN_PROGRESSBARSTYLE:
327           token = theme_parse_progressbarstyle(settings, scanner, &clearlooks_style->progressbarstyle);
328           break;
329         case TOKEN_MENUBARSTYLE:
330           token = theme_parse_menubarstyle(settings, scanner, &clearlooks_style->menubarstyle);
331           break;
332         case TOKEN_MENUITEMSTYLE:
333           token = theme_parse_menuitemstyle(settings, scanner, &clearlooks_style->menuitemstyle);
334           break;
335         case TOKEN_LISTVIEWITEMSTYLE:
336           token = theme_parse_listviewitemstyle(settings, scanner, &clearlooks_style->listviewitemstyle);
337           break;
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         return token;
346
347       token = g_scanner_peek_next_token(scanner);
348     }
349
350   g_scanner_get_next_token(scanner);
351
352   g_scanner_set_scope(scanner, old_scope);
353
354   return G_TOKEN_NONE;
355 }
356
357 static void
358 clearlooks_rc_style_merge (GtkRcStyle *dest,
359                            GtkRcStyle *src)
360 {
361         ClearlooksRcStyle *dest_w, *src_w;
362
363         parent_class->merge (dest, src);
364
365         if (!CLEARLOOKS_IS_RC_STYLE (src))
366                 return;
367
368         src_w = CLEARLOOKS_RC_STYLE (src);
369         dest_w = CLEARLOOKS_RC_STYLE (dest);
370
371         dest_w->contrast = src_w->contrast;
372         dest_w->sunkenmenubar = src_w->sunkenmenubar;
373         dest_w->progressbarstyle = src_w->progressbarstyle;
374         dest_w->menubarstyle = src_w->menubarstyle;
375         dest_w->menuitemstyle = src_w->menuitemstyle;
376         dest_w->listviewitemstyle = src_w->listviewitemstyle;
377
378         if (src_w->has_spot_color)
379         {
380                 dest_w->has_spot_color = TRUE;
381                 dest_w->spot_color = src_w->spot_color;
382         }
383 }
384
385
386 /* Create an empty style suitable to this RC style
387  */
388 static GtkStyle *
389 clearlooks_rc_style_create_style (GtkRcStyle *rc_style)
390 {
391   return GTK_STYLE (g_object_new (CLEARLOOKS_TYPE_STYLE, NULL));
392 }