]> Pileus Git - ~andy/gtk/blob - gtk/gtkrc.c
Updated Slovenian translation
[~andy/gtk] / gtk / gtkrc.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28
29 #include <locale.h>
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 #include <sys/stat.h>
34 #ifdef HAVE_SYS_PARAM_H
35 #include <sys/param.h>
36 #endif
37 #include <fcntl.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41
42
43 #include <glib.h>
44 #include <glib/gstdio.h>
45 #include "gdk/gdk.h"
46
47 #include "gtkversion.h"
48 #include "gtkrc.h"
49 #include "gtkbindings.h"
50 #include "gtkintl.h"
51 #include "gtkiconfactory.h"
52 #include "gtkmain.h"
53 #include "gtkmodules.h"
54 #include "gtkprivate.h"
55 #include "gtksettingsprivate.h"
56 #include "gtkwindow.h"
57
58 #ifdef G_OS_WIN32
59 #include <io.h>
60 #endif
61
62
63 /**
64  * SECTION:gtkrc
65  * @Short_description: Deprecated routines for handling resource files
66  * @Title: Resource Files
67  *
68  * GTK+ provides resource file mechanism for configuring
69  * various aspects of the operation of a GTK+ program
70  * at runtime.
71  *
72  * <warning>
73  * In GTK+ 3.0, resource files have been deprecated and replaced
74  * by CSS-like style sheets, which are understood by #GtkCssProvider.
75  * </warning>
76  *
77  * <refsect2>
78  * <title>Default files</title>
79  * <para>
80  * An application can cause GTK+ to parse a specific RC
81  * file by calling gtk_rc_parse(). In addition to this,
82  * certain files will be read at the end of gtk_init().
83  * Unless modified, the files looked for will be
84  * <filename>&lt;SYSCONFDIR&gt;/gtk-2.0/gtkrc</filename>
85  * and <filename>.gtkrc-3.0</filename> in the users home directory.
86  * (<filename>&lt;SYSCONFDIR&gt;</filename> defaults to
87  * <filename>/usr/local/etc</filename>. It can be changed with the
88  * <option>--prefix</option> or <option>--sysconfdir</option> options when
89  * configuring GTK+.)
90  *
91  * The set of these <firstterm>default</firstterm> files
92  * can be retrieved with gtk_rc_get_default_files()
93  * and modified with gtk_rc_add_default_file() and
94  * gtk_rc_set_default_files().
95  * Additionally, the <envar>GTK2_RC_FILES</envar> environment variable
96  * can be set to a #G_SEARCHPATH_SEPARATOR_S-separated list of files
97  * in order to overwrite the set of default files at runtime.
98  * <para><anchor id="locale-specific-rc"/>
99  * For each RC file, in addition to the file itself, GTK+ will look for
100  * a locale-specific file that will be parsed after the main file.
101  * For instance, if <envar>LANG</envar> is set to <literal>ja_JP.ujis</literal>,
102  * when loading the default file <filename>~/.gtkrc</filename> then GTK+ looks
103  * for <filename>~/.gtkrc.ja_JP</filename> and <filename>~/.gtkrc.ja</filename>,
104  * and parses the first of those that exists.</para>
105  * </para>
106  * </refsect2>
107  * <refsect2>
108  * <title>Pathnames and patterns</title>
109  * <anchor id="gtkrc-pathnames-and-patterns"/>
110  * <para>
111  * A resource file defines a number of styles and key bindings and
112  * attaches them to particular widgets. The attachment is done
113  * by the <literal>widget</literal>, <literal>widget_class</literal>,
114  * and <literal>class</literal> declarations. As an example
115  * of such a statement:
116  *
117  * <informalexample><programlisting>
118  * widget "mywindow.*.GtkEntry" style "my-entry-class"
119  * </programlisting></informalexample>
120  *
121  * attaches the style <literal>"my-entry-class"</literal> to all
122  * widgets  whose <firstterm>widget path</firstterm> matches the
123  * <firstterm>pattern</firstterm> <literal>"mywindow.*.GtkEntry"</literal>.
124  * That is, all #GtkEntry widgets which are part of a #GtkWindow named
125  * <literal>"mywindow"</literal>.
126  *
127  * The patterns here are given in the standard shell glob syntax.
128  * The <literal>"?"</literal> wildcard matches any character, while
129  * <literal>"*"</literal> matches zero or more of any character.
130  * The three types of matching are against the widget path, the
131  * <firstterm>class path</firstterm> and the class hierarchy. Both the
132  * widget path and the class path consist of a <literal>"."</literal>
133  * separated list of all the parents of the widget and the widget itself
134  * from outermost to innermost. The difference is that in the widget path,
135  * the name assigned by gtk_widget_set_name() is used if present, otherwise
136  * the class name of the widget, while for the class path, the class name is
137  * always used.
138  *
139  * Since GTK+ 2.10, <literal>widget_class</literal> paths can also contain
140  * <literal>&lt;classname&gt;</literal> substrings, which are matching
141  * the class with the given name and any derived classes. For instance,
142  * <informalexample><programlisting>
143  * widget_class "*&lt;GtkMenuItem&gt;.GtkLabel" style "my-style"
144  * </programlisting></informalexample>
145  * will match #GtkLabel widgets which are contained in any kind of menu item.
146  *
147  * So, if you have a #GtkEntry named <literal>"myentry"</literal>, inside of a
148  * horizontal box in a window named <literal>"mywindow"</literal>, then the
149  * widget path is: <literal>"mywindow.GtkHBox.myentry"</literal>
150  * while the class path is: <literal>"GtkWindow.GtkHBox.GtkEntry"</literal>.
151  *
152  * Matching against class is a little different. The pattern match is done
153  * against all class names in the widgets class hierarchy (not the layout
154  * hierarchy) in sequence, so the pattern:
155  * <informalexample><programlisting>
156  * class "GtkButton" style "my-style"
157  * </programlisting></informalexample>
158  * will match not just #GtkButton widgets, but also #GtkToggleButton and
159  * #GtkCheckButton widgets, since those classes derive from #GtkButton.
160  *
161  * Additionally, a priority can be specified for each pattern, and styles
162  * override other styles first by priority, then by pattern type and then
163  * by order of specification (later overrides earlier). The priorities
164  * that can be specified are (highest to lowest):
165  * <simplelist>
166  * <member><literal>highest</literal></member>
167  * <member><literal>rc</literal></member>
168  * <member><literal>theme</literal></member>
169  * <member><literal>application</literal></member>
170  * <member><literal>gtk</literal></member>
171  * <member><literal>lowest</literal></member>
172  * </simplelist>
173  * <literal>rc</literal> is the default for styles
174  * read from an RC file, <literal>theme</literal>
175  * is the default for styles read from theme RC files,
176  * <literal>application</literal>
177  * should be used for styles an application sets
178  * up, and <literal>gtk</literal> is used for styles
179  * that GTK+ creates internally.
180  * </para>
181  * </refsect2>
182  * <refsect2>
183  * <title>Theme gtkrc files</title>
184  * <anchor id="theme-gtkrc-files"/>
185  * <para>
186  * Theme RC files are loaded first from under the <filename>~/.themes/</filename>,
187  * then from the directory from gtk_rc_get_theme_dir(). The files looked at will
188  * be <filename>gtk-3.0/gtkrc</filename>.
189  *
190  * When the application prefers dark themes
191  * (see the #GtkSettings:gtk-application-prefer-dark-theme property for details),
192  * <filename>gtk-3.0/gtkrc-dark</filename> will be loaded first, and if not present
193  * <filename>gtk-3.0/gtkrc</filename> will be loaded.
194  * </para>
195  * </refsect2>
196  * <refsect2>
197  * <title>Optimizing RC Style Matches</title>
198  * <anchor id="optimizing-rc-style-matches"/>
199  * <para>
200  * Everytime a widget is created and added to the layout hierarchy of a #GtkWindow
201  * ("anchored" to be exact), a list of matching RC styles out of all RC styles read
202  * in so far is composed.
203  * For this, every RC style is matched against the widgets class path,
204  * the widgets name path and widgets inheritance hierarchy.
205  * As a consequence, significant slowdown can be caused by utilization of many
206  * RC styles and by using RC style patterns that are slow or complicated to match
207  * against a given widget.
208  * The following ordered list provides a number of advices (prioritized by
209  * effectiveness) to reduce the performance overhead associated with RC style
210  * matches:
211  *
212  * <orderedlist>
213  *   <listitem><para>
214  *   Move RC styles for specific applications into RC files dedicated to those
215  *   applications and parse application specific RC files only from
216  *   applications that are affected by them.
217  *   This reduces the overall amount of RC styles that have to be considered
218  *   for a match across a group of applications.
219  *   </para></listitem>
220  *   <listitem><para>
221  *   Merge multiple styles which use the same matching rule, for instance:
222  *   <informalexample><programlisting>
223  *      style "Foo" { foo_content }
224  *      class "X" style "Foo"
225  *      style "Bar" { bar_content }
226  *      class "X" style "Bar"
227  *   </programlisting></informalexample>
228  *   is faster to match as:
229  *   <informalexample><programlisting>
230  *      style "FooBar" { foo_content bar_content }
231  *      class "X" style "FooBar"
232  *   </programlisting></informalexample>
233  *   </para></listitem>
234  *   <listitem><para>
235  *   Use of wildcards should be avoided, this can reduce the individual RC style
236  *   match to a single integer comparison in most cases.
237  *   </para></listitem>
238  *   <listitem><para>
239  *   To avoid complex recursive matching, specification of full class names
240  *   (for <literal>class</literal> matches) or full path names (for
241  *   <literal>widget</literal> and <literal>widget_class</literal> matches)
242  *   is to be preferred over shortened names
243  *   containing <literal>"*"</literal> or <literal>"?"</literal>.
244  *   </para></listitem>
245  *   <listitem><para>
246  *   If at all necessary, wildcards should only be used at the tail or head
247  *   of a pattern. This reduces the match complexity to a string comparison
248  *   per RC style.
249  *   </para></listitem>
250  *   <listitem><para>
251  *   When using wildcards, use of <literal>"?"</literal> should be preferred
252  *   over <literal>"*"</literal>. This can reduce the matching complexity from
253  *   O(n^2) to O(n). For example <literal>"Gtk*Box"</literal> can be turned into
254  *   <literal>"Gtk?Box"</literal> and will still match #GtkHBox and #GtkVBox.
255  *   </para></listitem>
256  *  <listitem><para>
257  *   The use of <literal>"*"</literal> wildcards should be restricted as much
258  *   as possible, because matching <literal>"A*B*C*RestString"</literal> can
259  *   result in matching complexities of O(n^2) worst case.
260  *   </para></listitem>
261  * </orderedlist>
262  * </para>
263  * </refsect2>
264  * <refsect2>
265  * <title>Toplevel declarations</title>
266  * <para>
267  * An RC file is a text file which is composed of a sequence
268  * of declarations. <literal>'#'</literal> characters delimit comments and
269  * the portion of a line after a <literal>'#'</literal> is ignored when parsing
270  * an RC file.
271  *
272  * The possible toplevel declarations are:
273  *
274  * <variablelist>
275  *   <varlistentry>
276  *     <term><literal>binding <replaceable>name</replaceable>
277  *      { ... }</literal></term>
278  *     <listitem>
279  *       <para>Declares a binding set.</para>
280  *     </listitem>
281  *   </varlistentry>
282  *   <varlistentry>
283  *     <term><literal>class <replaceable>pattern</replaceable>
284  *           [ style | binding ][ : <replaceable>priority</replaceable> ]
285  *           <replaceable>name</replaceable></literal></term>
286  *     <listitem>
287  *      <para>Specifies a style or binding set for a particular
288  *      branch of the inheritance hierarchy.</para>
289  *     </listitem>
290  *   </varlistentry>
291  *   <varlistentry>
292  *     <term><literal>include <replaceable>filename</replaceable></literal></term>
293  *     <listitem>
294  *       <para>Parses another file at this point. If
295  *         <replaceable>filename</replaceable> is not an absolute filename,
296  *         it is searched in the directories of the currently open RC files.</para>
297  *       <para>GTK+ also tries to load a
298  *         <link linkend="locale-specific-rc">locale-specific variant</link> of
299  *         the included file.</para>
300  *     </listitem>
301  *   </varlistentry>
302  *   <varlistentry>
303  *     <term><literal>module_path <replaceable>path</replaceable></literal></term>
304  *     <listitem>
305  *       <para>Sets a path (a list of directories separated
306  *       by colons) that will be searched for theme engines referenced in
307  *       RC files.</para>
308  *     </listitem>
309  *   </varlistentry>
310  *   <varlistentry>
311  *     <term><literal>pixmap_path <replaceable>path</replaceable></literal></term>
312  *     <listitem>
313  *       <para>Sets a path (a list of directories separated
314  *       by colons) that will be searched for pixmaps referenced in
315  *       RC files.</para>
316  *     </listitem>
317  *   </varlistentry>
318  *   <varlistentry>
319  *     <term><literal>im_module_file <replaceable>pathname</replaceable></literal></term>
320  *     <listitem>
321  *       <para>Sets the pathname for the IM modules file. Setting this from RC files
322  *       is deprecated; you should use the environment variable <envar>GTK_IM_MODULE_FILE</envar>
323  *       instead.</para>
324  *     </listitem>
325  *   </varlistentry>
326  *   <varlistentry>
327  *     <term><literal>style <replaceable>name</replaceable> [ =
328  *     <replaceable>parent</replaceable> ] { ... }</literal></term>
329  *     <listitem>
330  *       <para>Declares a style.</para>
331  *     </listitem>
332  *   </varlistentry>
333  *   <varlistentry>
334  *     <term><literal>widget <replaceable>pattern</replaceable>
335  *           [ style | binding ][ : <replaceable>priority</replaceable> ]
336  *           <replaceable>name</replaceable></literal></term>
337  *     <listitem>
338  *      <para>Specifies a style or binding set for a particular
339  *      group of widgets by matching on the widget pathname.</para>
340  *     </listitem>
341  *   </varlistentry>
342  *   <varlistentry>
343  *     <term><literal>widget_class <replaceable>pattern</replaceable>
344  *           [ style | binding ][ : <replaceable>priority</replaceable> ]
345  *           <replaceable>name</replaceable></literal></term>
346  *     <listitem>
347  *      <para>Specifies a style or binding set for a particular
348  *      group of widgets by matching on the class pathname.</para>
349  *     </listitem>
350  *   </varlistentry>
351  *   <varlistentry>
352  *     <term><replaceable>setting</replaceable> = <replaceable>value</replaceable></term>
353  *     <listitem>
354  *       <para>Specifies a value for a <link linkend="GtkSettings">setting</link>.
355  *         Note that settings in RC files are overwritten by system-wide settings
356  *         (which are managed by an XSettings manager on X11).</para>
357  *     </listitem>
358  *   </varlistentry>
359  * </variablelist>
360  * </para>
361  * </refsect2>
362  * <refsect2>
363  * <title>Styles</title>
364  * <para>
365  * A RC style is specified by a <literal>style</literal>
366  * declaration in a RC file, and then bound to widgets
367  * with a <literal>widget</literal>, <literal>widget_class</literal>,
368  * or <literal>class</literal> declaration. All styles
369  * applying to a particular widget are composited together
370  * with <literal>widget</literal> declarations overriding
371  * <literal>widget_class</literal> declarations which, in
372  * turn, override <literal>class</literal> declarations.
373  * Within each type of declaration, later declarations override
374  * earlier ones.
375  *
376  * Within a <literal>style</literal> declaration, the possible
377  * elements are:
378  *
379  * <variablelist>
380  *   <varlistentry>
381  *     <term><literal>bg[<replaceable>state</replaceable>] =
382  *       <replaceable>color</replaceable></literal></term>
383  *      <listitem>
384  *          Sets the color used for the background of most widgets.
385  *      </listitem>
386  *   </varlistentry>
387  *   <varlistentry>
388  *     <term><literal>fg[<replaceable>state</replaceable>] =
389  *       <replaceable>color</replaceable></literal></term>
390  *      <listitem>
391  *          Sets the color used for the foreground of most widgets.
392  *      </listitem>
393  *   </varlistentry>
394  *   <varlistentry>
395  *     <term><literal>base[<replaceable>state</replaceable>] =
396  *       <replaceable>color</replaceable></literal></term>
397  *      <listitem>
398  *          Sets the color used for the background of widgets displaying
399  *          editable text. This color is used for the background
400  *          of, among others, #GtkText, #GtkEntry, #GtkList, and #GtkCList.
401  *      </listitem>
402  *   </varlistentry>
403  *   <varlistentry>
404  *     <term><literal>text[<replaceable>state</replaceable>] =
405  *       <replaceable>color</replaceable></literal></term>
406  *      <listitem>
407  *          Sets the color used for foreground of widgets using
408  *          <literal>base</literal> for the background color.
409  *      </listitem>
410  *   </varlistentry>
411  *   <varlistentry>
412  *     <term><literal>xthickness =
413  *       <replaceable>number</replaceable></literal></term>
414  *      <listitem>
415  *          Sets the xthickness, which is used for various horizontal padding
416  *          values in GTK+.
417  *      </listitem>
418  *   </varlistentry>
419  *   <varlistentry>
420  *     <term><literal>ythickness =
421  *       <replaceable>number</replaceable></literal></term>
422  *      <listitem>
423  *          Sets the ythickness, which is used for various vertical padding
424  *          values in GTK+.
425  *      </listitem>
426  *   </varlistentry>
427  *   <varlistentry>
428  *     <term><literal>bg_pixmap[<replaceable>state</replaceable>] =
429  *       <replaceable>pixmap</replaceable></literal></term>
430  *      <listitem>
431  *          Sets a background pixmap to be used in place of
432  *          the <literal>bg</literal> color (or for #GtkText,
433  *          in place of the <literal>base</literal> color. The special
434  *          value <literal>"&lt;parent&gt;"</literal> may be used to indicate that the widget should
435  *          use the same background pixmap as its parent. The special value
436  *          <literal>"&lt;none&gt;"</literal> may be used to indicate no background pixmap.
437  *      </listitem>
438  *   </varlistentry>
439  *   <varlistentry>
440  *     <term><literal>font = <replaceable>font</replaceable></literal></term>
441  *      <listitem>
442  *          Starting with GTK+ 2.0, the "font" and "fontset"
443  *          declarations are ignored; use "font_name" declarations instead.
444  *      </listitem>
445  *   </varlistentry>
446  *   <varlistentry>
447  *     <term><literal>fontset = <replaceable>font</replaceable></literal></term>
448  *      <listitem>
449  *          Starting with GTK+ 2.0, the "font" and "fontset"
450  *          declarations are ignored; use "font_name" declarations instead.
451  *      </listitem>
452  *   </varlistentry>
453  *   <varlistentry>
454  *     <term><literal>font_name = <replaceable>font</replaceable></literal></term>
455  *      <listitem>
456  *          Sets the font for a widget. <replaceable>font</replaceable> must be
457  *          a Pango font name, e.g. <literal>"Sans Italic 10"</literal>.
458  *          For details about Pango font names, see
459  *          pango_font_description_from_string().
460  *      </listitem>
461  *   </varlistentry>
462  *   <varlistentry>
463  *     <term><literal>stock[<replaceable>"stock-id"</replaceable>] = { <replaceable>icon source specifications</replaceable> }</literal></term>
464  *      <listitem>
465  *         Defines the icon for a stock item.
466  *      </listitem>
467  *   </varlistentry>
468  *   <varlistentry>
469  *     <term><literal>color[<replaceable>"color-name"</replaceable>] = <replaceable>color specification</replaceable></literal></term>
470  *      <listitem>
471  *         Since 2.10, this element can be used to defines symbolic colors. See below for
472  *         the syntax of color specifications.
473  *      </listitem>
474  *   </varlistentry>
475  *   <varlistentry>
476  *     <term><literal>engine <replaceable>"engine"</replaceable> { <replaceable>engine-specific
477  * settings</replaceable> }</literal></term>
478  *      <listitem>
479  *         Defines the engine to be used when drawing with this style.
480  *      </listitem>
481  *   </varlistentry>
482  *   <varlistentry>
483  *     <term><literal><replaceable>class</replaceable>::<replaceable>property</replaceable> = <replaceable>value</replaceable></literal></term>
484  *      <listitem>
485  *         Sets a <link linkend="style-properties">style property</link> for a widget class.
486  *      </listitem>
487  *   </varlistentry>
488  * </variablelist>
489  *
490  * The colors and background pixmaps are specified as a function of the
491  * state of the widget. The states are:
492  *
493  * <variablelist>
494  *   <varlistentry>
495  *     <term><literal>NORMAL</literal></term>
496  *     <listitem>
497  *         A color used for a widget in its normal state.
498  *     </listitem>
499  *   </varlistentry>
500  *   <varlistentry>
501  *     <term><literal>ACTIVE</literal></term>
502  *     <listitem>
503  *         A variant of the <literal>NORMAL</literal> color used when the
504  *         widget is in the %GTK_STATE_ACTIVE state, and also for
505  *         the trough of a ScrollBar, tabs of a NoteBook
506  *         other than the current tab and similar areas.
507  *         Frequently, this should be a darker variant
508  *         of the <literal>NORMAL</literal> color.
509  *     </listitem>
510  *   </varlistentry>
511  *   <varlistentry>
512  *     <term><literal>PRELIGHT</literal></term>
513  *     <listitem>
514  *         A color used for widgets in the %GTK_STATE_PRELIGHT state. This
515  *         state is the used for Buttons and MenuItems
516  *         that have the mouse cursor over them, and for
517  *         their children.
518  *     </listitem>
519  *   </varlistentry>
520  *   <varlistentry>
521  *     <term><literal>SELECTED</literal></term>
522  *     <listitem>
523  *         A color used to highlight data selected by the user.
524  *         for instance, the selected items in a list widget, and the
525  *         selection in an editable widget.
526  *     </listitem>
527  *   </varlistentry>
528  *   <varlistentry>
529  *     <term><literal>INSENSITIVE</literal></term>
530  *     <listitem>
531  *         A color used for the background of widgets that have
532  *         been set insensitive with gtk_widget_set_sensitive().
533  *     </listitem>
534  *   </varlistentry>
535  * </variablelist>
536  *
537  * <anchor id="color-format"/>
538  * Colors can be specified as a string containing a color name (GTK+ knows
539  * all names from the X color database <filename>/usr/lib/X11/rgb.txt</filename>),
540  * in one of the hexadecimal forms <literal>#rrrrggggbbbb</literal>,
541  * <literal>#rrrgggbbb</literal>, <literal>#rrggbb</literal>,
542  * or <literal>#rgb</literal>, where <literal>r</literal>,
543  * <literal>g</literal> and <literal>b</literal> are
544  * hex digits, or they can be specified as a triplet
545  * <literal>{ <replaceable>r</replaceable>, <replaceable>g</replaceable>,
546  * <replaceable>b</replaceable>}</literal>, where <literal>r</literal>,
547  * <literal>g</literal> and <literal>b</literal> are either integers in
548  * the range 0-65535 or floats in the range 0.0-1.0.
549  *
550  * Since 2.10, colors can also be specified by refering to a symbolic color, as
551  * follows: <literal>@<!-- -->color-name</literal>, or by using expressions to combine
552  * colors. The following expressions are currently supported:
553  *   <variablelist>
554  *     <varlistentry>
555  *       <term>mix (<replaceable>factor</replaceable>, <replaceable>color1</replaceable>, <replaceable>color2</replaceable>)</term>
556  *       <listitem><para>
557  *         Computes a new color by mixing <replaceable>color1</replaceable> and
558  *         <replaceable>color2</replaceable>. The <replaceable>factor</replaceable>
559  *         determines how close the new color is to <replaceable>color1</replaceable>.
560  *         A factor of 1.0 gives pure <replaceable>color1</replaceable>, a factor of
561  *         0.0 gives pure <replaceable>color2</replaceable>.
562  *       </para></listitem>
563  *     </varlistentry>
564  *     <varlistentry>
565  *       <term>shade (<replaceable>factor</replaceable>, <replaceable>color</replaceable>)</term>
566  *       <listitem><para>
567  *         Computes a lighter or darker variant of <replaceable>color</replaceable>.
568  *         A <replaceable>factor</replaceable> of 1.0 leaves the color unchanged, smaller
569  *         factors yield darker colors, larger factors yield lighter colors.
570  *       </para></listitem>
571  *     </varlistentry>
572  *     <varlistentry>
573  *       <term>lighter (<replaceable>color</replaceable>)</term>
574  *       <listitem><para>
575  *         This is an abbreviation for
576  *         <literal>shade (1.3, <replaceable>color</replaceable>)</literal>.
577  *       </para></listitem>
578  *     </varlistentry>
579  *     <varlistentry>
580  *       <term>darker (<replaceable>color</replaceable>)</term>
581  *       <listitem><para>
582  *         This is an abbreviation for
583  *         <literal>shade (0.7, <replaceable>color</replaceable>)</literal>.
584  *       </para></listitem>
585  *     </varlistentry>
586  *   </variablelist>
587  *
588  * Here are some examples of color expressions:
589  *
590  * <informalexample><programlisting>
591  *  mix (0.5, "red", "blue")
592  *  shade (1.5, mix (0.3, "#0abbc0", { 0.3, 0.5, 0.9 }))
593  *  lighter (@<!-- -->foreground)
594  * </programlisting></informalexample>
595  *
596  * In a <literal>stock</literal> definition, icon sources are specified as a
597  * 4-tuple of image filename or icon name, text direction, widget state, and size, in that
598  * order.  Each icon source specifies an image filename or icon name to use with a given
599  * direction, state, and size. Filenames are specified as a string such
600  * as <literal>"itemltr.png"</literal>, while icon names (looked up
601  * in the current icon theme), are specified with a leading
602  * <literal>@</literal>, such as <literal>@"item-ltr"</literal>.
603  * The <literal>*</literal> character can be used as a
604  * wildcard, and if direction/state/size are omitted they default to
605  * <literal>*</literal>. So for example, the following specifies different icons to
606  * use for left-to-right and right-to-left languages:
607  *
608  * <informalexample><programlisting>
609  * stock["my-stock-item"] =
610  * {
611  *   { "itemltr.png", LTR, *, * },
612  *   { "itemrtl.png", RTL, *, * }
613  * }
614  * </programlisting></informalexample>
615  *
616  * This could be abbreviated as follows:
617  *
618  * <informalexample><programlisting>
619  * stock["my-stock-item"] =
620  * {
621  *   { "itemltr.png", LTR },
622  *   { "itemrtl.png", RTL }
623  * }
624  * </programlisting></informalexample>
625  *
626  * You can specify custom icons for specific sizes, as follows:
627  *
628  * <informalexample><programlisting>
629  * stock["my-stock-item"] =
630  * {
631  *   { "itemmenusize.png", *, *, "gtk-menu" },
632  *   { "itemtoolbarsize.png", *, *, "gtk-large-toolbar" }
633  *   { "itemgeneric.png" } // implicit *, *, * as a fallback
634  * }
635  * </programlisting></informalexample>
636  *
637  * The sizes that come with GTK+ itself are <literal>"gtk-menu"</literal>,
638  * <literal>"gtk-small-toolbar"</literal>, <literal>"gtk-large-toolbar"</literal>,
639  * <literal>"gtk-button"</literal>, <literal>"gtk-dialog"</literal>. Applications
640  * can define other sizes.
641  *
642  * It's also possible to use custom icons for a given state, for example:
643  *
644  * <informalexample><programlisting>
645  * stock["my-stock-item"] =
646  * {
647  *   { "itemprelight.png", *, PRELIGHT },
648  *   { "iteminsensitive.png", *, INSENSITIVE },
649  *   { "itemgeneric.png" } // implicit *, *, * as a fallback
650  * }
651  * </programlisting></informalexample>
652  *
653  * When selecting an icon source to use, GTK+ will consider text direction most
654  * important, state second, and size third. It will select the best match based on
655  * those criteria. If an attribute matches exactly (e.g. you specified
656  * <literal>PRELIGHT</literal> or specified the size), GTK+ won't modify the image;
657  * if the attribute matches with a wildcard, GTK+ will scale or modify the image to
658  * match the state and size the user requested.
659  * </para>
660  * </refsect2>
661  * <refsect2>
662  * <title>Key bindings</title>
663  * <para>
664  * Key bindings allow the user to specify actions to be
665  * taken on particular key presses. The form of a binding
666  * set declaration is:
667  *
668  * <informalexample><programlisting>
669  * binding <replaceable>name</replaceable> {
670  *   bind <replaceable>key</replaceable> {
671  *     <replaceable>signalname</replaceable> (<replaceable>param</replaceable>, ...)
672  *     ...
673  *   }
674  *   ...
675  * }
676  * </programlisting></informalexample>
677  *
678  * <replaceable>key</replaceable> is a string consisting of a
679  * series of modifiers followed by the name of a key. The
680  * modifiers can be:
681  * <simplelist>
682  * <member><literal>&lt;alt&gt;</literal></member>
683  * <member><literal>&lt;ctl&gt;</literal></member>
684  * <member><literal>&lt;control&gt;</literal></member>
685  * <member><literal>&lt;meta&gt;</literal></member>
686  * <member><literal>&lt;hyper&gt;</literal></member>
687  * <member><literal>&lt;super&gt;</literal></member>
688  * <member><literal>&lt;mod1&gt;</literal></member>
689  * <member><literal>&lt;mod2&gt;</literal></member>
690  * <member><literal>&lt;mod3&gt;</literal></member>
691  * <member><literal>&lt;mod4&gt;</literal></member>
692  * <member><literal>&lt;mod5&gt;</literal></member>
693  * <member><literal>&lt;release&gt;</literal></member>
694  * <member><literal>&lt;shft&gt;</literal></member>
695  * <member><literal>&lt;shift&gt;</literal></member>
696  * </simplelist>
697  * <literal>&lt;shft&gt;</literal> is an alias for
698  * <literal>&lt;shift&gt;</literal>,
699  * <literal>&lt;ctl&gt;</literal> is an alias for
700  * <literal>&lt;control&gt;</literal>,
701  *  and
702  * <literal>&lt;alt&gt;</literal> is an alias for
703  * <literal>&lt;mod1&gt;</literal>.
704  *
705  * The action that is bound to the key is a sequence
706  * of signal names (strings) followed by parameters for
707  * each signal. The signals must be action signals.
708  * (See g_signal_new()). Each parameter can be
709  * a float, integer, string, or unquoted string
710  * representing an enumeration value. The types of
711  * the parameters specified must match the types of the
712  * parameters of the signal.
713  *
714  * Binding sets are connected to widgets in the same manner as styles,
715  * with one difference: Binding sets override other binding sets first
716  * by pattern type, then by priority and then by order of specification.
717  * The priorities that can be specified and their default values are the
718  * same as for styles.
719  * </para>
720  * </refsect2>
721  */
722
723
724 enum 
725 {
726   PATH_ELT_PSPEC,
727   PATH_ELT_UNRESOLVED,
728   PATH_ELT_TYPE
729 };
730
731 typedef struct
732 {
733   gint type;
734   union 
735   {
736     GType         class_type;
737     gchar        *class_name;
738     GPatternSpec *pspec;
739   } elt;
740 } PathElt;
741
742 #define GTK_RC_STYLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RC_STYLE, GtkRcStylePrivate))
743
744 typedef struct _GtkRcStylePrivate GtkRcStylePrivate;
745
746 struct _GtkRcStylePrivate
747 {
748   GSList *color_hashes;
749 };
750
751 static void        gtk_rc_style_finalize             (GObject         *object);
752 static void        gtk_rc_style_real_merge           (GtkRcStyle      *dest,
753                                                       GtkRcStyle      *src);
754 static GtkRcStyle* gtk_rc_style_real_create_rc_style (GtkRcStyle      *rc_style);
755 static GtkStyle*   gtk_rc_style_real_create_style    (GtkRcStyle      *rc_style);
756 static gint        gtk_rc_properties_cmp             (gconstpointer    bsearch_node1,
757                                                       gconstpointer    bsearch_node2);
758
759 static void        insert_rc_property                (GtkRcStyle      *style,
760                                                       GtkRcProperty   *property,
761                                                       gboolean         replace);
762
763
764 static const GScannerConfig gtk_rc_scanner_config =
765 {
766   (
767    " \t\r\n"
768    )                    /* cset_skip_characters */,
769   (
770    "_"
771    G_CSET_a_2_z
772    G_CSET_A_2_Z
773    )                    /* cset_identifier_first */,
774   (
775    G_CSET_DIGITS
776    "-_"
777    G_CSET_a_2_z
778    G_CSET_A_2_Z
779    )                    /* cset_identifier_nth */,
780   ( "#\n" )             /* cpair_comment_single */,
781   
782   TRUE                  /* case_sensitive */,
783   
784   TRUE                  /* skip_comment_multi */,
785   TRUE                  /* skip_comment_single */,
786   TRUE                  /* scan_comment_multi */,
787   TRUE                  /* scan_identifier */,
788   FALSE                 /* scan_identifier_1char */,
789   FALSE                 /* scan_identifier_NULL */,
790   TRUE                  /* scan_symbols */,
791   TRUE                  /* scan_binary */,
792   TRUE                  /* scan_octal */,
793   TRUE                  /* scan_float */,
794   TRUE                  /* scan_hex */,
795   TRUE                  /* scan_hex_dollar */,
796   TRUE                  /* scan_string_sq */,
797   TRUE                  /* scan_string_dq */,
798   TRUE                  /* numbers_2_int */,
799   FALSE                 /* int_2_float */,
800   FALSE                 /* identifier_2_string */,
801   TRUE                  /* char_2_token */,
802   TRUE                  /* symbol_2_token */,
803   FALSE                 /* scope_0_fallback */,
804 };
805  
806 static const gchar symbol_names[] = 
807   "include\0"
808   "NORMAL\0"
809   "ACTIVE\0"
810   "PRELIGHT\0"
811   "SELECTED\0"
812   "INSENSITIVE\0"
813   "fg\0"
814   "bg\0"
815   "text\0"
816   "base\0"
817   "xthickness\0"
818   "ythickness\0"
819   "font\0"
820   "fontset\0"
821   "font_name\0"
822   "bg_pixmap\0"
823   "pixmap_path\0"
824   "style\0"
825   "binding\0"
826   "bind\0"
827   "widget\0"
828   "widget_class\0"
829   "class\0"
830   "lowest\0"
831   "gtk\0"
832   "application\0"
833   "theme\0"
834   "rc\0"
835   "highest\0"
836   "engine\0"
837   "module_path\0"
838   "stock\0"
839   "im_module_file\0"
840   "LTR\0"
841   "RTL\0"
842   "color\0"
843   "unbind\0";
844
845 static const struct
846 {
847   guint name_offset;
848   guint token;
849 } symbols[] = {
850   {   0, GTK_RC_TOKEN_INCLUDE },
851   {   8, GTK_RC_TOKEN_NORMAL },
852   {  15, GTK_RC_TOKEN_ACTIVE },
853   {  22, GTK_RC_TOKEN_PRELIGHT },
854   {  31, GTK_RC_TOKEN_SELECTED },
855   {  40, GTK_RC_TOKEN_INSENSITIVE },
856   {  52, GTK_RC_TOKEN_FG },
857   {  55, GTK_RC_TOKEN_BG },
858   {  58, GTK_RC_TOKEN_TEXT },
859   {  63, GTK_RC_TOKEN_BASE },
860   {  68, GTK_RC_TOKEN_XTHICKNESS },
861   {  79, GTK_RC_TOKEN_YTHICKNESS },
862   {  90, GTK_RC_TOKEN_FONT },
863   {  95, GTK_RC_TOKEN_FONTSET },
864   { 103, GTK_RC_TOKEN_FONT_NAME },
865   { 113, GTK_RC_TOKEN_BG_PIXMAP },
866   { 123, GTK_RC_TOKEN_PIXMAP_PATH },
867   { 135, GTK_RC_TOKEN_STYLE },
868   { 141, GTK_RC_TOKEN_BINDING },
869   { 149, GTK_RC_TOKEN_BIND },
870   { 154, GTK_RC_TOKEN_WIDGET },
871   { 161, GTK_RC_TOKEN_WIDGET_CLASS },
872   { 174, GTK_RC_TOKEN_CLASS },
873   { 180, GTK_RC_TOKEN_LOWEST },
874   { 187, GTK_RC_TOKEN_GTK },
875   { 191, GTK_RC_TOKEN_APPLICATION },
876   { 203, GTK_RC_TOKEN_THEME },
877   { 209, GTK_RC_TOKEN_RC },
878   { 212, GTK_RC_TOKEN_HIGHEST },
879   { 220, GTK_RC_TOKEN_ENGINE },
880   { 227, GTK_RC_TOKEN_MODULE_PATH },
881   { 239, GTK_RC_TOKEN_STOCK },
882   { 245, GTK_RC_TOKEN_IM_MODULE_FILE },
883   { 260, GTK_RC_TOKEN_LTR },
884   { 264, GTK_RC_TOKEN_RTL },
885   { 268, GTK_RC_TOKEN_COLOR },
886   { 274, GTK_RC_TOKEN_UNBIND }
887 };
888
889 static GHashTable *realized_style_ht = NULL;
890
891 static gchar *im_module_file = NULL;
892
893 static gchar **gtk_rc_default_files = NULL;
894
895 /* RC file handling */
896
897 static gchar *
898 gtk_rc_make_default_dir (const gchar *type)
899 {
900   const gchar *var;
901   gchar *path;
902
903   var = g_getenv ("GTK_EXE_PREFIX");
904
905   if (var)
906     path = g_build_filename (var, "lib", "gtk-3.0", GTK_BINARY_VERSION, type, NULL);
907   else
908     path = g_build_filename (GTK_LIBDIR, "gtk-3.0", GTK_BINARY_VERSION, type, NULL);
909
910   return path;
911 }
912
913 /**
914  * gtk_rc_get_im_module_path:
915  * @returns: (type filename): a newly-allocated string containing the
916  *    path in which to look for IM modules.
917  *
918  * Obtains the path in which to look for IM modules. See the documentation
919  * of the <link linkend="im-module-path"><envar>GTK_PATH</envar></link>
920  * environment variable for more details about looking up modules. This
921  * function is useful solely for utilities supplied with GTK+ and should
922  * not be used by applications under normal circumstances.
923  *
924  * Deprecated: 3.0: Use #GtkCssProvider instead.
925  */
926 gchar *
927 gtk_rc_get_im_module_path (void)
928 {
929   gchar **paths = _gtk_get_module_path ("immodules");
930   gchar *result = g_strjoinv (G_SEARCHPATH_SEPARATOR_S, paths);
931   g_strfreev (paths);
932
933   return result;
934 }
935
936 /**
937  * gtk_rc_get_im_module_file:
938  * @returns: (type filename): a newly-allocated string containing the
939  *    name of the file listing the IM modules available for loading
940  *
941  * Obtains the path to the IM modules file. See the documentation
942  * of the <link linkend="im-module-file"><envar>GTK_IM_MODULE_FILE</envar></link>
943  * environment variable for more details.
944  *
945  * Deprecated: 3.0: Use #GtkCssProvider instead.
946  */
947 gchar *
948 gtk_rc_get_im_module_file (void)
949 {
950   const gchar *var = g_getenv ("GTK_IM_MODULE_FILE");
951   gchar *result = NULL;
952
953   if (var)
954     result = g_strdup (var);
955
956   if (!result)
957     {
958       if (im_module_file)
959         result = g_strdup (im_module_file);
960       else
961         result = gtk_rc_make_default_dir ("immodules.cache");
962     }
963
964   return result;
965 }
966
967 /**
968  * gtk_rc_get_theme_dir:
969  *
970  * Returns the standard directory in which themes should
971  * be installed. (GTK+ does not actually use this directory
972  * itself.)
973  *
974  * Returns: The directory (must be freed with g_free()).
975  *
976  * Deprecated: 3.0: Use #GtkCssProvider instead.
977  */
978 gchar *
979 gtk_rc_get_theme_dir (void)
980 {
981   const gchar *var;
982   gchar *path;
983
984   var = g_getenv ("GTK_DATA_PREFIX");
985
986   if (var)
987     path = g_build_filename (var, "share", "themes", NULL);
988   else
989     path = g_build_filename (GTK_DATA_PREFIX, "share", "themes", NULL);
990
991   return path;
992 }
993
994 /**
995  * gtk_rc_get_module_dir:
996  *
997  * Returns a directory in which GTK+ looks for theme engines.
998  * For full information about the search for theme engines,
999  * see the docs for <envar>GTK_PATH</envar> in
1000  * <xref linkend="gtk-running"/>.
1001  *
1002  * return value: (type filename): the directory. (Must be freed with g_free())
1003  *
1004  * Deprecated: 3.0: Use #GtkCssProvider instead.
1005  **/
1006 gchar *
1007 gtk_rc_get_module_dir (void)
1008 {
1009   return gtk_rc_make_default_dir ("engines");
1010 }
1011
1012 /**
1013  * gtk_rc_add_default_file:
1014  * @filename: (type filename): the pathname to the file. If @filename
1015  *    is not absolute, it is searched in the current directory.
1016  *
1017  * Adds a file to the list of files to be parsed at the
1018  * end of gtk_init().
1019  *
1020  * Deprecated:3.0: Use #GtkStyleContext with a custom #GtkStyleProvider instead
1021  **/
1022 void
1023 gtk_rc_add_default_file (const gchar *filename)
1024 {
1025 }
1026
1027 /**
1028  * gtk_rc_set_default_files:
1029  * @filenames: (array zero-terminated=1) (element-type filename): A
1030  *     %NULL-terminated list of filenames.
1031  *
1032  * Sets the list of files that GTK+ will read at the
1033  * end of gtk_init().
1034  *
1035  * Deprecated:3.0: Use #GtkStyleContext with a custom #GtkStyleProvider instead
1036  **/
1037 void
1038 gtk_rc_set_default_files (gchar **filenames)
1039 {
1040 }
1041
1042 /**
1043  * gtk_rc_get_default_files:
1044  *
1045  * Retrieves the current list of RC files that will be parsed
1046  * at the end of gtk_init().
1047  *
1048  * Return value: (transfer none) (array zero-terminated=1) (element-type filename):
1049  *      A %NULL-terminated array of filenames.  This memory is owned
1050  *     by GTK+ and must not be freed by the application.  If you want
1051  *     to store this information, you should make a copy.
1052  *
1053  * Deprecated:3.0: Use #GtkStyleContext instead
1054  **/
1055 gchar **
1056 gtk_rc_get_default_files (void)
1057 {
1058   return gtk_rc_default_files;
1059 }
1060
1061 /**
1062  * gtk_rc_parse_string:
1063  * @rc_string: a string to parse.
1064  *
1065  * Parses resource information directly from a string.
1066  *
1067  * Deprecated: 3.0: Use #GtkCssProvider instead.
1068  */
1069 void
1070 gtk_rc_parse_string (const gchar *rc_string)
1071 {
1072   g_return_if_fail (rc_string != NULL);
1073 }
1074
1075 /**
1076  * gtk_rc_parse:
1077  * @filename: the filename of a file to parse. If @filename is not absolute, it
1078  *  is searched in the current directory.
1079  *
1080  * Parses a given resource file.
1081  *
1082  * Deprecated: 3.0: Use #GtkCssProvider instead.
1083  */
1084 void
1085 gtk_rc_parse (const gchar *filename)
1086 {
1087   g_return_if_fail (filename != NULL);
1088 }
1089
1090 /* Handling of RC styles */
1091
1092 G_DEFINE_TYPE (GtkRcStyle, gtk_rc_style, G_TYPE_OBJECT)
1093
1094 static void
1095 gtk_rc_style_init (GtkRcStyle *style)
1096 {
1097   GtkRcStylePrivate *priv = GTK_RC_STYLE_GET_PRIVATE (style);
1098   guint i;
1099
1100   style->name = NULL;
1101   style->font_desc = NULL;
1102
1103   for (i = 0; i < 5; i++)
1104     {
1105       static const GdkColor init_color = { 0, 0, 0, 0, };
1106
1107       style->bg_pixmap_name[i] = NULL;
1108       style->color_flags[i] = 0;
1109       style->fg[i] = init_color;
1110       style->bg[i] = init_color;
1111       style->text[i] = init_color;
1112       style->base[i] = init_color;
1113     }
1114   style->xthickness = -1;
1115   style->ythickness = -1;
1116   style->rc_properties = NULL;
1117
1118   style->rc_style_lists = NULL;
1119   style->icon_factories = NULL;
1120
1121   priv->color_hashes = NULL;
1122 }
1123
1124 static void
1125 gtk_rc_style_class_init (GtkRcStyleClass *klass)
1126 {
1127   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1128
1129   object_class->finalize = gtk_rc_style_finalize;
1130
1131   klass->parse = NULL;
1132   klass->create_rc_style = gtk_rc_style_real_create_rc_style;
1133   klass->merge = gtk_rc_style_real_merge;
1134   klass->create_style = gtk_rc_style_real_create_style;
1135
1136   g_type_class_add_private (object_class, sizeof (GtkRcStylePrivate));
1137 }
1138
1139 static void
1140 gtk_rc_style_finalize (GObject *object)
1141 {
1142   GSList *tmp_list1, *tmp_list2;
1143   GtkRcStyle *rc_style;
1144   GtkRcStylePrivate *rc_priv;
1145   gint i;
1146
1147   rc_style = GTK_RC_STYLE (object);
1148   rc_priv = GTK_RC_STYLE_GET_PRIVATE (rc_style);
1149
1150   g_free (rc_style->name);
1151   if (rc_style->font_desc)
1152     pango_font_description_free (rc_style->font_desc);
1153
1154   for (i = 0; i < 5; i++)
1155     g_free (rc_style->bg_pixmap_name[i]);
1156
1157   /* Now remove all references to this rc_style from
1158    * realized_style_ht
1159    */
1160   tmp_list1 = rc_style->rc_style_lists;
1161   while (tmp_list1)
1162     {
1163       GSList *rc_styles = tmp_list1->data;
1164       GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
1165       g_object_unref (style);
1166
1167       /* Remove the list of styles from the other rc_styles
1168        * in the list
1169        */
1170       tmp_list2 = rc_styles;
1171       while (tmp_list2)
1172         {
1173           GtkRcStyle *other_style = tmp_list2->data;
1174
1175           if (other_style != rc_style)
1176             other_style->rc_style_lists = g_slist_remove_all (other_style->rc_style_lists,
1177                                                               rc_styles);
1178           tmp_list2 = tmp_list2->next;
1179         }
1180
1181       /* And from the hash table itself
1182        */
1183       g_hash_table_remove (realized_style_ht, rc_styles);
1184       g_slist_free (rc_styles);
1185
1186       tmp_list1 = tmp_list1->next;
1187     }
1188   g_slist_free (rc_style->rc_style_lists);
1189
1190   if (rc_style->rc_properties)
1191     {
1192       guint i;
1193
1194       for (i = 0; i < rc_style->rc_properties->len; i++)
1195         {
1196           GtkRcProperty *node = &g_array_index (rc_style->rc_properties, GtkRcProperty, i);
1197
1198           g_free (node->origin);
1199           g_value_unset (&node->value);
1200         }
1201       g_array_free (rc_style->rc_properties, TRUE);
1202       rc_style->rc_properties = NULL;
1203     }
1204
1205   g_slist_foreach (rc_style->icon_factories, (GFunc) g_object_unref, NULL);
1206   g_slist_free (rc_style->icon_factories);
1207
1208   g_slist_foreach (rc_priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
1209   g_slist_free (rc_priv->color_hashes);
1210
1211   G_OBJECT_CLASS (gtk_rc_style_parent_class)->finalize (object);
1212 }
1213
1214 /**
1215  * gtk_rc_style_new:
1216  *
1217  * Creates a new #GtkRcStyle with no fields set and
1218  * a reference count of 1.
1219  *
1220  * Returns: the newly-created #GtkRcStyle
1221  *
1222  * Deprecated: 3.0: Use #GtkCssProvider instead.
1223  */
1224 GtkRcStyle *
1225 gtk_rc_style_new (void)
1226 {
1227   GtkRcStyle *style;
1228
1229   style = g_object_new (GTK_TYPE_RC_STYLE, NULL);
1230
1231   return style;
1232 }
1233
1234 /**
1235  * gtk_rc_style_copy:
1236  * @orig: the style to copy
1237  *
1238  * Makes a copy of the specified #GtkRcStyle. This function
1239  * will correctly copy an RC style that is a member of a class
1240  * derived from #GtkRcStyle.
1241  *
1242  * Return value: (transfer full): the resulting #GtkRcStyle
1243  *
1244  * Deprecated: 3.0: Use #GtkCssProvider instead.
1245  **/
1246 GtkRcStyle *
1247 gtk_rc_style_copy (GtkRcStyle *orig)
1248 {
1249   GtkRcStyle *style;
1250
1251   g_return_val_if_fail (GTK_IS_RC_STYLE (orig), NULL);
1252   
1253   style = GTK_RC_STYLE_GET_CLASS (orig)->create_rc_style (orig);
1254   GTK_RC_STYLE_GET_CLASS (style)->merge (style, orig);
1255
1256   return style;
1257 }
1258
1259 static GtkRcStyle *
1260 gtk_rc_style_real_create_rc_style (GtkRcStyle *style)
1261 {
1262   return g_object_new (G_OBJECT_TYPE (style), NULL);
1263 }
1264
1265 static gint
1266 gtk_rc_properties_cmp (gconstpointer bsearch_node1,
1267                        gconstpointer bsearch_node2)
1268 {
1269   const GtkRcProperty *prop1 = bsearch_node1;
1270   const GtkRcProperty *prop2 = bsearch_node2;
1271
1272   if (prop1->type_name == prop2->type_name)
1273     return prop1->property_name < prop2->property_name ? -1 : prop1->property_name == prop2->property_name ? 0 : 1;
1274   else
1275     return prop1->type_name < prop2->type_name ? -1 : 1;
1276 }
1277
1278 static void
1279 insert_rc_property (GtkRcStyle    *style,
1280                     GtkRcProperty *property,
1281                     gboolean       replace)
1282 {
1283   guint i;
1284   GtkRcProperty *new_property = NULL;
1285   GtkRcProperty key = { 0, 0, NULL, { 0, }, };
1286
1287   key.type_name = property->type_name;
1288   key.property_name = property->property_name;
1289
1290   if (!style->rc_properties)
1291     style->rc_properties = g_array_new (FALSE, FALSE, sizeof (GtkRcProperty));
1292
1293   i = 0;
1294   while (i < style->rc_properties->len)
1295     {
1296       gint cmp = gtk_rc_properties_cmp (&key, &g_array_index (style->rc_properties, GtkRcProperty, i));
1297
1298       if (cmp == 0)
1299         {
1300           if (replace)
1301             {
1302               new_property = &g_array_index (style->rc_properties, GtkRcProperty, i);
1303               
1304               g_free (new_property->origin);
1305               g_value_unset (&new_property->value);
1306               
1307               *new_property = key;
1308               break;
1309             }
1310           else
1311             return;
1312         }
1313       else if (cmp < 0)
1314         break;
1315
1316       i++;
1317     }
1318
1319   if (!new_property)
1320     {
1321       g_array_insert_val (style->rc_properties, i, key);
1322       new_property = &g_array_index (style->rc_properties, GtkRcProperty, i);
1323     }
1324
1325   new_property->origin = g_strdup (property->origin);
1326   g_value_init (&new_property->value, G_VALUE_TYPE (&property->value));
1327   g_value_copy (&property->value, &new_property->value);
1328 }
1329
1330 static void
1331 gtk_rc_style_real_merge (GtkRcStyle *dest,
1332                          GtkRcStyle *src)
1333 {
1334   gint i;
1335
1336   for (i = 0; i < 5; i++)
1337     {
1338       if (!dest->bg_pixmap_name[i] && src->bg_pixmap_name[i])
1339         dest->bg_pixmap_name[i] = g_strdup (src->bg_pixmap_name[i]);
1340       
1341       if (!(dest->color_flags[i] & GTK_RC_FG) && 
1342           src->color_flags[i] & GTK_RC_FG)
1343         {
1344           dest->fg[i] = src->fg[i];
1345           dest->color_flags[i] |= GTK_RC_FG;
1346         }
1347       if (!(dest->color_flags[i] & GTK_RC_BG) && 
1348           src->color_flags[i] & GTK_RC_BG)
1349         {
1350           dest->bg[i] = src->bg[i];
1351           dest->color_flags[i] |= GTK_RC_BG;
1352         }
1353       if (!(dest->color_flags[i] & GTK_RC_TEXT) && 
1354           src->color_flags[i] & GTK_RC_TEXT)
1355         {
1356           dest->text[i] = src->text[i];
1357           dest->color_flags[i] |= GTK_RC_TEXT;
1358         }
1359       if (!(dest->color_flags[i] & GTK_RC_BASE) && 
1360           src->color_flags[i] & GTK_RC_BASE)
1361         {
1362           dest->base[i] = src->base[i];
1363           dest->color_flags[i] |= GTK_RC_BASE;
1364         }
1365     }
1366
1367   if (dest->xthickness < 0 && src->xthickness >= 0)
1368     dest->xthickness = src->xthickness;
1369   if (dest->ythickness < 0 && src->ythickness >= 0)
1370     dest->ythickness = src->ythickness;
1371
1372   if (src->font_desc)
1373     {
1374       if (!dest->font_desc)
1375         dest->font_desc = pango_font_description_copy (src->font_desc);
1376       else
1377         pango_font_description_merge (dest->font_desc, src->font_desc, FALSE);
1378     }
1379
1380   if (src->rc_properties)
1381     {
1382       guint i;
1383
1384       for (i = 0; i < src->rc_properties->len; i++)
1385         insert_rc_property (dest,
1386                             &g_array_index (src->rc_properties, GtkRcProperty, i),
1387                             FALSE);
1388     }
1389 }
1390
1391 static GtkStyle *
1392 gtk_rc_style_real_create_style (GtkRcStyle *rc_style)
1393 {
1394   return gtk_style_new ();
1395 }
1396
1397 /**
1398  * gtk_rc_reset_styles:
1399  * @settings: a #GtkSettings
1400  *
1401  * This function recomputes the styles for all widgets that use a
1402  * particular #GtkSettings object. (There is one #GtkSettings object
1403  * per #GdkScreen, see gtk_settings_get_for_screen()); It is useful
1404  * when some global parameter has changed that affects the appearance
1405  * of all widgets, because when a widget gets a new style, it will
1406  * both redraw and recompute any cached information about its
1407  * appearance. As an example, it is used when the default font size
1408  * set by the operating system changes. Note that this function
1409  * doesn't affect widgets that have a style set explicitely on them
1410  * with gtk_widget_set_style().
1411  *
1412  * Since: 2.4
1413  *
1414  * Deprecated: 3.0: Use #GtkCssProvider instead.
1415  **/
1416 void
1417 gtk_rc_reset_styles (GtkSettings *settings)
1418 {
1419   gtk_style_context_reset_widgets (_gtk_settings_get_screen (settings));
1420 }
1421
1422 /**
1423  * gtk_rc_reparse_all_for_settings:
1424  * @settings: a #GtkSettings
1425  * @force_load: load whether or not anything changed
1426  *
1427  * If the modification time on any previously read file
1428  * for the given #GtkSettings has changed, discard all style information
1429  * and then reread all previously read RC files.
1430  *
1431  * Return value: %TRUE if the files were reread.
1432  *
1433  * Deprecated: 3.0: Use #GtkCssProvider instead.
1434  **/
1435 gboolean
1436 gtk_rc_reparse_all_for_settings (GtkSettings *settings,
1437                                  gboolean     force_load)
1438 {
1439   return FALSE;
1440 }
1441
1442 /**
1443  * gtk_rc_reparse_all:
1444  *
1445  * If the modification time on any previously read file for the
1446  * default #GtkSettings has changed, discard all style information
1447  * and then reread all previously read RC files.
1448  *
1449  * Return value:  %TRUE if the files were reread.
1450  *
1451  * Deprecated: 3.0: Use #GtkCssProvider instead.
1452  **/
1453 gboolean
1454 gtk_rc_reparse_all (void)
1455 {
1456   return FALSE;
1457 }
1458
1459 /**
1460  * gtk_rc_get_style:
1461  * @widget: a #GtkWidget
1462  *
1463  * Finds all matching RC styles for a given widget,
1464  * composites them together, and then creates a
1465  * #GtkStyle representing the composite appearance.
1466  * (GTK+ actually keeps a cache of previously
1467  * created styles, so a new style may not be
1468  * created.)
1469  *
1470  * Returns: (transfer none): the resulting style. No refcount is added
1471  *   to the returned style, so if you want to save this style around,
1472  *   you should add a reference yourself.
1473  *
1474  * Deprecated:3.0: Use #GtkStyleContext instead
1475  **/
1476 GtkStyle *
1477 gtk_rc_get_style (GtkWidget *widget)
1478 {
1479   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
1480
1481   gtk_widget_ensure_style (widget);
1482
1483   return gtk_widget_get_style (widget);
1484 }
1485
1486 /**
1487  * gtk_rc_get_style_by_paths:
1488  * @settings: a #GtkSettings object
1489  * @widget_path: (allow-none): the widget path to use when looking up the
1490  *     style, or %NULL if no matching against the widget path should be done
1491  * @class_path: (allow-none): the class path to use when looking up the style,
1492  *     or %NULL if no matching against the class path should be done.
1493  * @type: a type that will be used along with parent types of this type
1494  *     when matching against class styles, or #G_TYPE_NONE
1495  *
1496  * Creates up a #GtkStyle from styles defined in a RC file by providing
1497  * the raw components used in matching. This function may be useful
1498  * when creating pseudo-widgets that should be themed like widgets but
1499  * don't actually have corresponding GTK+ widgets. An example of this
1500  * would be items inside a GNOME canvas widget.
1501  *
1502  * The action of gtk_rc_get_style() is similar to:
1503  * |[
1504  *  gtk_widget_path (widget, NULL, &path, NULL);
1505  *  gtk_widget_class_path (widget, NULL, &class_path, NULL);
1506  *  gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget),
1507  *                             path, class_path,
1508  *                             G_OBJECT_TYPE (widget));
1509  * ]|
1510  *
1511  * Return value: (transfer none): A style created by matching with the
1512  *     supplied paths, or %NULL if nothing matching was specified and the
1513  *     default style should be used. The returned value is owned by GTK+
1514  *     as part of an internal cache, so you must call g_object_ref() on
1515  *     the returned value if you want to keep a reference to it.
1516  *
1517  * Deprecated:3.0: Use #GtkStyleContext instead
1518  **/
1519 GtkStyle *
1520 gtk_rc_get_style_by_paths (GtkSettings *settings,
1521                            const char  *widget_path,
1522                            const char  *class_path,
1523                            GType        type)
1524 {
1525   GtkWidgetPath *path;
1526   GtkStyle *style;
1527
1528   path = gtk_widget_path_new ();
1529
1530   /* For compatibility, we return a GtkStyle based on a GtkStyleContext
1531    * with a GtkWidgetPath appropriate for the supplied information.
1532    *
1533    * GtkWidgetPath is composed of a list of GTypes with optional names;
1534    * In GTK+-2.0, widget_path consisted of the widget names, or
1535    * the class names for unnamed widgets, while class_path had the
1536    * class names always. So, use class_path to determine the GTypes
1537    * and extract widget names from widget_path as applicable.
1538    */
1539   if (class_path == NULL)
1540     {
1541       gtk_widget_path_append_type (path, type == G_TYPE_NONE ? GTK_TYPE_WIDGET : type);
1542     }
1543   else
1544     {
1545       const gchar *widget_p, *widget_next;
1546       const gchar *class_p, *class_next;
1547
1548       widget_next = widget_path;
1549       class_next = class_path;
1550
1551       while (*class_next)
1552         {
1553           GType component_type;
1554           gchar *component_class;
1555           gchar *component_name;
1556           gint pos;
1557
1558           class_p = class_next;
1559           if (*class_p == '.')
1560             class_p++;
1561
1562           widget_p = widget_next; /* Might be NULL */
1563           if (widget_p && *widget_p == '.')
1564             widget_p++;
1565
1566           class_next = strchr (class_p, '.');
1567           if (class_next == NULL)
1568             class_next = class_p + strlen (class_p);
1569
1570           if (widget_p)
1571             {
1572               widget_next = strchr (widget_p, '.');
1573               if (widget_next == NULL)
1574                 widget_next = widget_p + strlen (widget_p);
1575             }
1576
1577           component_class = g_strndup (class_p, class_next - class_p);
1578           if (widget_p && *widget_p)
1579             component_name = g_strndup (widget_p, widget_next - widget_p);
1580           else
1581             component_name = NULL;
1582
1583           component_type = g_type_from_name (component_class);
1584           if (component_type == G_TYPE_INVALID)
1585             component_type = GTK_TYPE_WIDGET;
1586
1587           pos = gtk_widget_path_append_type (path, component_type);
1588           if (component_name != NULL && strcmp (component_name, component_name) != 0)
1589             gtk_widget_path_iter_set_name (path, pos, component_name);
1590
1591           g_free (component_class);
1592           g_free (component_name);
1593         }
1594     }
1595
1596   style = _gtk_style_new_for_path (_gtk_settings_get_screen (settings),
1597                                    path);
1598
1599   gtk_widget_path_free (path);
1600
1601   return style;
1602 }
1603
1604 /**
1605  * gtk_rc_scanner_new: (skip)
1606  *
1607  * Deprecated:3.0: Use #GtkCssProvider instead
1608  */
1609 GScanner*
1610 gtk_rc_scanner_new (void)
1611 {
1612   return g_scanner_new (&gtk_rc_scanner_config);
1613 }
1614
1615 /*********************
1616  * Parsing functions *
1617  *********************/
1618
1619 static gboolean
1620 lookup_color (GtkRcStyle *style,
1621               const char *color_name,
1622               GdkColor   *color)
1623 {
1624   GtkRcStylePrivate *priv = GTK_RC_STYLE_GET_PRIVATE (style);
1625   GSList *iter;
1626
1627   for (iter = priv->color_hashes; iter != NULL; iter = iter->next)
1628     {
1629       GHashTable *hash  = iter->data;
1630       GdkColor   *match = g_hash_table_lookup (hash, color_name);
1631
1632       if (match)
1633         {
1634           color->red = match->red;
1635           color->green = match->green;
1636           color->blue = match->blue;
1637           return TRUE;
1638         }
1639     }
1640
1641   return FALSE;
1642 }
1643
1644 /**
1645  * gtk_rc_find_pixmap_in_path:
1646  * @settings: a #GtkSettings
1647  * @scanner: Scanner used to get line number information for the
1648  *   warning message, or %NULL
1649  * @pixmap_file: name of the pixmap file to locate.
1650  *
1651  * Looks up a file in pixmap path for the specified #GtkSettings.
1652  * If the file is not found, it outputs a warning message using
1653  * g_warning() and returns %NULL.
1654  *
1655  * Return value: (type filename): the filename.
1656  *
1657  * Deprecated: 3.0: Use #GtkCssProvider instead.
1658  **/
1659 gchar*
1660 gtk_rc_find_pixmap_in_path (GtkSettings  *settings,
1661                             GScanner     *scanner,
1662                             const gchar  *pixmap_file)
1663 {
1664   g_warning ("Unable to locate image file in pixmap_path: \"%s\"",
1665              pixmap_file);
1666   return NULL;
1667 }
1668
1669 /**
1670  * gtk_rc_find_module_in_path:
1671  * @module_file: name of a theme engine
1672  *
1673  * Searches for a theme engine in the GTK+ search path. This function
1674  * is not useful for applications and should not be used.
1675  *
1676  * Return value: (type filename): The filename, if found (must be
1677  *   freed with g_free()), otherwise %NULL.
1678  *
1679  * Deprecated: 3.0: Use #GtkCssProvider instead.
1680  **/
1681 gchar*
1682 gtk_rc_find_module_in_path (const gchar *module_file)
1683 {
1684   return _gtk_find_module (module_file, "engines");
1685 }
1686
1687 /**
1688  * gtk_rc_parse_state:
1689  * @scanner: a #GtkScanner (must be initialized for parsing an RC file)
1690  * @state: (out): A pointer to a #GtkStateType variable in which to
1691  *  store the result.
1692  *
1693  * Parses a #GtkStateType variable from the format expected
1694  * in a RC file.
1695  *
1696  * Returns: %G_TOKEN_NONE if parsing succeeded, otherwise the token
1697  *   that was expected but not found.
1698  *
1699  * Deprecated: 3.0: Use #GtkCssProvider instead
1700  */
1701 guint
1702 gtk_rc_parse_state (GScanner     *scanner,
1703                     GtkStateType *state)
1704 {
1705   guint old_scope;
1706   guint token;
1707
1708   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1709   g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
1710   
1711   /* we don't know where we got called from, so we reset the scope here.
1712    * if we bail out due to errors, we *don't* reset the scope, so the
1713    * error messaging code can make sense of our tokens.
1714    */
1715   old_scope = g_scanner_set_scope (scanner, 0);
1716   
1717   token = g_scanner_get_next_token (scanner);
1718   if (token != G_TOKEN_LEFT_BRACE)
1719     return G_TOKEN_LEFT_BRACE;
1720   
1721   token = g_scanner_get_next_token (scanner);
1722   switch (token)
1723     {
1724     case GTK_RC_TOKEN_ACTIVE:
1725       *state = GTK_STATE_ACTIVE;
1726       break;
1727     case GTK_RC_TOKEN_INSENSITIVE:
1728       *state = GTK_STATE_INSENSITIVE;
1729       break;
1730     case GTK_RC_TOKEN_NORMAL:
1731       *state = GTK_STATE_NORMAL;
1732       break;
1733     case GTK_RC_TOKEN_PRELIGHT:
1734       *state = GTK_STATE_PRELIGHT;
1735       break;
1736     case GTK_RC_TOKEN_SELECTED:
1737       *state = GTK_STATE_SELECTED;
1738       break;
1739     default:
1740       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1741     }
1742   
1743   token = g_scanner_get_next_token (scanner);
1744   if (token != G_TOKEN_RIGHT_BRACE)
1745     return G_TOKEN_RIGHT_BRACE;
1746   
1747   g_scanner_set_scope (scanner, old_scope);
1748
1749   return G_TOKEN_NONE;
1750 }
1751
1752 /**
1753  * gtk_rc_parse_priority:
1754  * @scanner: a #GtkScanner (must be initialized for parsing an RC file)
1755  * @priority: A pointer to #GtkPathPriorityType variable in which
1756  *  to store the result.
1757  *
1758  * Parses a #GtkPathPriorityType variable from the format expected
1759  * in a RC file.
1760  *
1761  * Returns: %G_TOKEN_NONE if parsing succeeded, otherwise the token
1762  *   that was expected but not found.
1763  *
1764  * Deprecated:3.0: Use #GtkCssProvider instead
1765  */
1766 guint
1767 gtk_rc_parse_priority (GScanner            *scanner,
1768                        GtkPathPriorityType *priority)
1769 {
1770   guint old_scope;
1771   guint token;
1772
1773   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1774   g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
1775
1776   /* we don't know where we got called from, so we reset the scope here.
1777    * if we bail out due to errors, we *don't* reset the scope, so the
1778    * error messaging code can make sense of our tokens.
1779    */
1780   old_scope = g_scanner_set_scope (scanner, 0);
1781   
1782   token = g_scanner_get_next_token (scanner);
1783   if (token != ':')
1784     return ':';
1785   
1786   token = g_scanner_get_next_token (scanner);
1787   switch (token)
1788     {
1789     case GTK_RC_TOKEN_LOWEST:
1790       *priority = GTK_PATH_PRIO_LOWEST;
1791       break;
1792     case GTK_RC_TOKEN_GTK:
1793       *priority = GTK_PATH_PRIO_GTK;
1794       break;
1795     case GTK_RC_TOKEN_APPLICATION:
1796       *priority = GTK_PATH_PRIO_APPLICATION;
1797       break;
1798     case GTK_RC_TOKEN_THEME:
1799       *priority = GTK_PATH_PRIO_THEME;
1800       break;
1801     case GTK_RC_TOKEN_RC:
1802       *priority = GTK_PATH_PRIO_RC;
1803       break;
1804     case GTK_RC_TOKEN_HIGHEST:
1805       *priority = GTK_PATH_PRIO_HIGHEST;
1806       break;
1807     default:
1808       return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
1809     }
1810   
1811   g_scanner_set_scope (scanner, old_scope);
1812
1813   return G_TOKEN_NONE;
1814 }
1815
1816 /**
1817  * gtk_rc_parse_color:
1818  * @scanner: a #GScanner
1819  * @color: (out): a pointer to a #GdkColor structure in which to store
1820  *     the result
1821  *
1822  * Parses a color in the <link linkend="color=format">format</link> expected
1823  * in a RC file.
1824  *
1825  * Note that theme engines should use gtk_rc_parse_color_full() in
1826  * order to support symbolic colors.
1827  *
1828  * Returns: %G_TOKEN_NONE if parsing succeeded, otherwise the token
1829  *     that was expected but not found
1830  *
1831  * Deprecated:3.0: Use #GtkCssProvider instead
1832  */
1833 guint
1834 gtk_rc_parse_color (GScanner *scanner,
1835                     GdkColor *color)
1836 {
1837   return gtk_rc_parse_color_full (scanner, NULL, color);
1838 }
1839
1840 /**
1841  * gtk_rc_parse_color_full:
1842  * @scanner: a #GScanner
1843  * @style: (allow-none): a #GtkRcStyle, or %NULL
1844  * @color: (out): a pointer to a #GdkColor structure in which to store
1845  *     the result
1846  *
1847  * Parses a color in the <link linkend="color=format">format</link> expected
1848  * in a RC file. If @style is not %NULL, it will be consulted to resolve
1849  * references to symbolic colors.
1850  *
1851  * Returns: %G_TOKEN_NONE if parsing succeeded, otherwise the token
1852  *     that was expected but not found
1853  *
1854  * Since: 2.12
1855  *
1856  * Deprecated:3.0: Use #GtkCssProvider instead
1857  */
1858 guint
1859 gtk_rc_parse_color_full (GScanner   *scanner,
1860                          GtkRcStyle *style,
1861                          GdkColor   *color)
1862 {
1863   guint token;
1864
1865   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1866
1867   /* we don't need to set our own scope here, because
1868    * we don't need own symbols
1869    */
1870   
1871   token = g_scanner_get_next_token (scanner);
1872   switch (token)
1873     {
1874       gint token_int;
1875       GdkColor c1, c2;
1876       gboolean negate;
1877       gdouble l;
1878
1879     case G_TOKEN_LEFT_CURLY:
1880       token = g_scanner_get_next_token (scanner);
1881       if (token == G_TOKEN_INT)
1882         token_int = scanner->value.v_int;
1883       else if (token == G_TOKEN_FLOAT)
1884         token_int = scanner->value.v_float * 65535.0;
1885       else
1886         return G_TOKEN_FLOAT;
1887       color->red = CLAMP (token_int, 0, 65535);
1888       
1889       token = g_scanner_get_next_token (scanner);
1890       if (token != G_TOKEN_COMMA)
1891         return G_TOKEN_COMMA;
1892       
1893       token = g_scanner_get_next_token (scanner);
1894       if (token == G_TOKEN_INT)
1895         token_int = scanner->value.v_int;
1896       else if (token == G_TOKEN_FLOAT)
1897         token_int = scanner->value.v_float * 65535.0;
1898       else
1899         return G_TOKEN_FLOAT;
1900       color->green = CLAMP (token_int, 0, 65535);
1901       
1902       token = g_scanner_get_next_token (scanner);
1903       if (token != G_TOKEN_COMMA)
1904         return G_TOKEN_COMMA;
1905       
1906       token = g_scanner_get_next_token (scanner);
1907       if (token == G_TOKEN_INT)
1908         token_int = scanner->value.v_int;
1909       else if (token == G_TOKEN_FLOAT)
1910         token_int = scanner->value.v_float * 65535.0;
1911       else
1912         return G_TOKEN_FLOAT;
1913       color->blue = CLAMP (token_int, 0, 65535);
1914       
1915       token = g_scanner_get_next_token (scanner);
1916       if (token != G_TOKEN_RIGHT_CURLY)
1917         return G_TOKEN_RIGHT_CURLY;
1918       return G_TOKEN_NONE;
1919       
1920     case G_TOKEN_STRING:
1921       if (!gdk_color_parse (scanner->value.v_string, color))
1922         {
1923           g_scanner_warn (scanner, "Invalid color constant '%s'",
1924                           scanner->value.v_string);
1925           return G_TOKEN_STRING;
1926         }
1927       return G_TOKEN_NONE;
1928
1929     case '@':
1930       token = g_scanner_get_next_token (scanner);
1931       if (token != G_TOKEN_IDENTIFIER)
1932         return G_TOKEN_IDENTIFIER;
1933
1934       if (!style || !lookup_color (style, scanner->value.v_identifier, color))
1935         {
1936           g_scanner_warn (scanner, "Invalid symbolic color '%s'",
1937                           scanner->value.v_identifier);
1938           return G_TOKEN_IDENTIFIER;
1939         }
1940
1941       return G_TOKEN_NONE;
1942
1943     case G_TOKEN_IDENTIFIER:
1944       if (strcmp (scanner->value.v_identifier, "mix") == 0)
1945         {
1946           token = g_scanner_get_next_token (scanner);
1947           if (token != G_TOKEN_LEFT_PAREN)
1948             return G_TOKEN_LEFT_PAREN;
1949
1950           negate = FALSE;
1951           if (g_scanner_peek_next_token (scanner) == '-')
1952             {
1953               g_scanner_get_next_token (scanner); /* eat sign */
1954               negate = TRUE;
1955             }
1956
1957           token = g_scanner_get_next_token (scanner);
1958           if (token != G_TOKEN_FLOAT)
1959             return G_TOKEN_FLOAT;
1960
1961           l = negate ? -scanner->value.v_float : scanner->value.v_float;
1962
1963           token = g_scanner_get_next_token (scanner);
1964           if (token != G_TOKEN_COMMA)
1965             return G_TOKEN_COMMA;
1966
1967           token = gtk_rc_parse_color_full (scanner, style, &c1);
1968           if (token != G_TOKEN_NONE)
1969             return token;
1970
1971           token = g_scanner_get_next_token (scanner);
1972           if (token != G_TOKEN_COMMA)
1973             return G_TOKEN_COMMA;
1974
1975           token = gtk_rc_parse_color_full (scanner, style, &c2);
1976           if (token != G_TOKEN_NONE)
1977             return token;
1978
1979           token = g_scanner_get_next_token (scanner);
1980           if (token != G_TOKEN_RIGHT_PAREN)
1981             return G_TOKEN_RIGHT_PAREN;
1982
1983           color->red   = l * c1.red   + (1.0 - l) * c2.red;
1984           color->green = l * c1.green + (1.0 - l) * c2.green;
1985           color->blue  = l * c1.blue  + (1.0 - l) * c2.blue;
1986
1987           return G_TOKEN_NONE;
1988         }
1989       else if (strcmp (scanner->value.v_identifier, "shade") == 0)
1990         {
1991           token = g_scanner_get_next_token (scanner);
1992           if (token != G_TOKEN_LEFT_PAREN)
1993             return G_TOKEN_LEFT_PAREN;
1994
1995           negate = FALSE;
1996           if (g_scanner_peek_next_token (scanner) == '-')
1997             {
1998               g_scanner_get_next_token (scanner); /* eat sign */
1999               negate = TRUE;
2000             }
2001
2002           token = g_scanner_get_next_token (scanner);
2003           if (token != G_TOKEN_FLOAT)
2004             return G_TOKEN_FLOAT;
2005
2006           l = negate ? -scanner->value.v_float : scanner->value.v_float;
2007
2008           token = g_scanner_get_next_token (scanner);
2009           if (token != G_TOKEN_COMMA)
2010             return G_TOKEN_COMMA;
2011
2012           token = gtk_rc_parse_color_full (scanner, style, &c1);
2013           if (token != G_TOKEN_NONE)
2014             return token;
2015
2016           token = g_scanner_get_next_token (scanner);
2017           if (token != G_TOKEN_RIGHT_PAREN)
2018             return G_TOKEN_RIGHT_PAREN;
2019
2020           _gtk_style_shade (&c1, color, l);
2021
2022           return G_TOKEN_NONE;
2023         }
2024       else if (strcmp (scanner->value.v_identifier, "lighter") == 0 ||
2025                strcmp (scanner->value.v_identifier, "darker") == 0)
2026         {
2027           if (scanner->value.v_identifier[0] == 'l')
2028             l = 1.3;
2029           else
2030             l = 0.7;
2031
2032           token = g_scanner_get_next_token (scanner);
2033           if (token != G_TOKEN_LEFT_PAREN)
2034             return G_TOKEN_LEFT_PAREN;
2035
2036           token = gtk_rc_parse_color_full (scanner, style, &c1);
2037           if (token != G_TOKEN_NONE)
2038             return token;
2039
2040           token = g_scanner_get_next_token (scanner);
2041           if (token != G_TOKEN_RIGHT_PAREN)
2042             return G_TOKEN_RIGHT_PAREN;
2043
2044           _gtk_style_shade (&c1, color, l);
2045
2046           return G_TOKEN_NONE;
2047         }
2048       else
2049         return G_TOKEN_IDENTIFIER;
2050
2051     default:
2052       return G_TOKEN_STRING;
2053     }
2054 }