gtkrc.c 64.2 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * 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.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

27
#include "config.h"
28 29 30

#include <locale.h>
#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>
Elliot Lee's avatar
Elliot Lee committed
38
#include <string.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41

42

Owen Taylor's avatar
Owen Taylor committed
43
#include <glib.h>
44
#include <glib/gstdio.h>
45
#include "gdk/gdk.h"
Owen Taylor's avatar
Owen Taylor committed
46

47
#include "gtkversion.h"
Elliot Lee's avatar
Elliot Lee committed
48
#include "gtkrc.h"
Tim Janik's avatar
Tim Janik committed
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"
Elliot Lee's avatar
Elliot Lee committed
57

Tor Lillqvist's avatar
Tor Lillqvist committed
58 59 60 61
#ifdef G_OS_WIN32
#include <io.h>
#endif

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723

/**
 * SECTION:gtkrc
 * @Short_description: Deprecated routines for handling resource files
 * @Title: Resource Files
 *
 * GTK+ provides resource file mechanism for configuring
 * various aspects of the operation of a GTK+ program
 * at runtime.
 *
 * <warning>
 * In GTK+ 3.0, resource files have been deprecated and replaced
 * by CSS-like style sheets, which are understood by #GtkCssProvider.
 * </warning>
 *
 * <refsect2>
 * <title>Default files</title>
 * <para>
 * An application can cause GTK+ to parse a specific RC
 * file by calling gtk_rc_parse(). In addition to this,
 * certain files will be read at the end of gtk_init().
 * Unless modified, the files looked for will be
 * <filename>&lt;SYSCONFDIR&gt;/gtk-2.0/gtkrc</filename>
 * and <filename>.gtkrc-3.0</filename> in the users home directory.
 * (<filename>&lt;SYSCONFDIR&gt;</filename> defaults to
 * <filename>/usr/local/etc</filename>. It can be changed with the
 * <option>--prefix</option> or <option>--sysconfdir</option> options when
 * configuring GTK+.)
 *
 * The set of these <firstterm>default</firstterm> files
 * can be retrieved with gtk_rc_get_default_files()
 * and modified with gtk_rc_add_default_file() and
 * gtk_rc_set_default_files().
 * Additionally, the <envar>GTK2_RC_FILES</envar> environment variable
 * can be set to a #G_SEARCHPATH_SEPARATOR_S-separated list of files
 * in order to overwrite the set of default files at runtime.
 * <para><anchor id="locale-specific-rc"/>
 * For each RC file, in addition to the file itself, GTK+ will look for
 * a locale-specific file that will be parsed after the main file.
 * For instance, if <envar>LANG</envar> is set to <literal>ja_JP.ujis</literal>,
 * when loading the default file <filename>~/.gtkrc</filename> then GTK+ looks
 * for <filename>~/.gtkrc.ja_JP</filename> and <filename>~/.gtkrc.ja</filename>,
 * and parses the first of those that exists.</para>
 * </para>
 * </refsect2>
 * <refsect2>
 * <title>Pathnames and patterns</title>
 * <anchor id="gtkrc-pathnames-and-patterns"/>
 * <para>
 * A resource file defines a number of styles and key bindings and
 * attaches them to particular widgets. The attachment is done
 * by the <literal>widget</literal>, <literal>widget_class</literal>,
 * and <literal>class</literal> declarations. As an example
 * of such a statement:
 *
 * <informalexample><programlisting>
 * widget "mywindow.*.GtkEntry" style "my-entry-class"
 * </programlisting></informalexample>
 *
 * attaches the style <literal>"my-entry-class"</literal> to all
 * widgets  whose <firstterm>widget path</firstterm> matches the
 * <firstterm>pattern</firstterm> <literal>"mywindow.*.GtkEntry"</literal>.
 * That is, all #GtkEntry widgets which are part of a #GtkWindow named
 * <literal>"mywindow"</literal>.
 *
 * The patterns here are given in the standard shell glob syntax.
 * The <literal>"?"</literal> wildcard matches any character, while
 * <literal>"*"</literal> matches zero or more of any character.
 * The three types of matching are against the widget path, the
 * <firstterm>class path</firstterm> and the class hierarchy. Both the
 * widget path and the class path consist of a <literal>"."</literal>
 * separated list of all the parents of the widget and the widget itself
 * from outermost to innermost. The difference is that in the widget path,
 * the name assigned by gtk_widget_set_name() is used if present, otherwise
 * the class name of the widget, while for the class path, the class name is
 * always used.
 *
 * Since GTK+ 2.10, <literal>widget_class</literal> paths can also contain
 * <literal>&lt;classname&gt;</literal> substrings, which are matching
 * the class with the given name and any derived classes. For instance,
 * <informalexample><programlisting>
 * widget_class "*&lt;GtkMenuItem&gt;.GtkLabel" style "my-style"
 * </programlisting></informalexample>
 * will match #GtkLabel widgets which are contained in any kind of menu item.
 *
 * So, if you have a #GtkEntry named <literal>"myentry"</literal>, inside of a
 * horizontal box in a window named <literal>"mywindow"</literal>, then the
 * widget path is: <literal>"mywindow.GtkHBox.myentry"</literal>
 * while the class path is: <literal>"GtkWindow.GtkHBox.GtkEntry"</literal>.
 *
 * Matching against class is a little different. The pattern match is done
 * against all class names in the widgets class hierarchy (not the layout
 * hierarchy) in sequence, so the pattern:
 * <informalexample><programlisting>
 * class "GtkButton" style "my-style"
 * </programlisting></informalexample>
 * will match not just #GtkButton widgets, but also #GtkToggleButton and
 * #GtkCheckButton widgets, since those classes derive from #GtkButton.
 *
 * Additionally, a priority can be specified for each pattern, and styles
 * override other styles first by priority, then by pattern type and then
 * by order of specification (later overrides earlier). The priorities
 * that can be specified are (highest to lowest):
 * <simplelist>
 * <member><literal>highest</literal></member>
 * <member><literal>rc</literal></member>
 * <member><literal>theme</literal></member>
 * <member><literal>application</literal></member>
 * <member><literal>gtk</literal></member>
 * <member><literal>lowest</literal></member>
 * </simplelist>
 * <literal>rc</literal> is the default for styles
 * read from an RC file, <literal>theme</literal>
 * is the default for styles read from theme RC files,
 * <literal>application</literal>
 * should be used for styles an application sets
 * up, and <literal>gtk</literal> is used for styles
 * that GTK+ creates internally.
 * </para>
 * </refsect2>
 * <refsect2>
 * <title>Theme gtkrc files</title>
 * <anchor id="theme-gtkrc-files"/>
 * <para>
 * Theme RC files are loaded first from under the <filename>~/.themes/</filename>,
 * then from the directory from gtk_rc_get_theme_dir(). The files looked at will
 * be <filename>gtk-3.0/gtkrc</filename>.
 *
 * When the application prefers dark themes
 * (see the #GtkSettings:gtk-application-prefer-dark-theme property for details),
 * <filename>gtk-3.0/gtkrc-dark</filename> will be loaded first, and if not present
 * <filename>gtk-3.0/gtkrc</filename> will be loaded.
 * </para>
 * </refsect2>
 * <refsect2>
 * <title>Optimizing RC Style Matches</title>
 * <anchor id="optimizing-rc-style-matches"/>
 * <para>
 * Everytime a widget is created and added to the layout hierarchy of a #GtkWindow
 * ("anchored" to be exact), a list of matching RC styles out of all RC styles read
 * in so far is composed.
 * For this, every RC style is matched against the widgets class path,
 * the widgets name path and widgets inheritance hierarchy.
 * As a consequence, significant slowdown can be caused by utilization of many
 * RC styles and by using RC style patterns that are slow or complicated to match
 * against a given widget.
 * The following ordered list provides a number of advices (prioritized by
 * effectiveness) to reduce the performance overhead associated with RC style
 * matches:
 *
 * <orderedlist>
 *   <listitem><para>
 *   Move RC styles for specific applications into RC files dedicated to those
 *   applications and parse application specific RC files only from
 *   applications that are affected by them.
 *   This reduces the overall amount of RC styles that have to be considered
 *   for a match across a group of applications.
 *   </para></listitem>
 *   <listitem><para>
 *   Merge multiple styles which use the same matching rule, for instance:
 *   <informalexample><programlisting>
 *      style "Foo" { foo_content }
 *      class "X" style "Foo"
 *      style "Bar" { bar_content }
 *      class "X" style "Bar"
 *   </programlisting></informalexample>
 *   is faster to match as:
 *   <informalexample><programlisting>
 *      style "FooBar" { foo_content bar_content }
 *      class "X" style "FooBar"
 *   </programlisting></informalexample>
 *   </para></listitem>
 *   <listitem><para>
 *   Use of wildcards should be avoided, this can reduce the individual RC style
 *   match to a single integer comparison in most cases.
 *   </para></listitem>
 *   <listitem><para>
 *   To avoid complex recursive matching, specification of full class names
 *   (for <literal>class</literal> matches) or full path names (for
 *   <literal>widget</literal> and <literal>widget_class</literal> matches)
 *   is to be preferred over shortened names
 *   containing <literal>"*"</literal> or <literal>"?"</literal>.
 *   </para></listitem>
 *   <listitem><para>
 *   If at all necessary, wildcards should only be used at the tail or head
 *   of a pattern. This reduces the match complexity to a string comparison
 *   per RC style.
 *   </para></listitem>
 *   <listitem><para>
 *   When using wildcards, use of <literal>"?"</literal> should be preferred
 *   over <literal>"*"</literal>. This can reduce the matching complexity from
 *   O(n^2) to O(n). For example <literal>"Gtk*Box"</literal> can be turned into
 *   <literal>"Gtk?Box"</literal> and will still match #GtkHBox and #GtkVBox.
 *   </para></listitem>
 *  <listitem><para>
 *   The use of <literal>"*"</literal> wildcards should be restricted as much
 *   as possible, because matching <literal>"A*B*C*RestString"</literal> can
 *   result in matching complexities of O(n^2) worst case.
 *   </para></listitem>
 * </orderedlist>
 * </para>
 * </refsect2>
 * <refsect2>
 * <title>Toplevel declarations</title>
 * <para>
 * An RC file is a text file which is composed of a sequence
 * of declarations. <literal>'#'</literal> characters delimit comments and
 * the portion of a line after a <literal>'#'</literal> is ignored when parsing
 * an RC file.
 *
 * The possible toplevel declarations are:
 *
 * <variablelist>
 *   <varlistentry>
 *     <term><literal>binding <replaceable>name</replaceable>
 *      { ... }</literal></term>
 *     <listitem>
 *       <para>Declares a binding set.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>class <replaceable>pattern</replaceable>
 *           [ style | binding ][ : <replaceable>priority</replaceable> ]
 *           <replaceable>name</replaceable></literal></term>
 *     <listitem>
 *      <para>Specifies a style or binding set for a particular
 *      branch of the inheritance hierarchy.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>include <replaceable>filename</replaceable></literal></term>
 *     <listitem>
 *       <para>Parses another file at this point. If
 *         <replaceable>filename</replaceable> is not an absolute filename,
 *         it is searched in the directories of the currently open RC files.</para>
 *       <para>GTK+ also tries to load a
 *         <link linkend="locale-specific-rc">locale-specific variant</link> of
 *         the included file.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>module_path <replaceable>path</replaceable></literal></term>
 *     <listitem>
 *       <para>Sets a path (a list of directories separated
 *       by colons) that will be searched for theme engines referenced in
 *       RC files.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>pixmap_path <replaceable>path</replaceable></literal></term>
 *     <listitem>
 *       <para>Sets a path (a list of directories separated
 *       by colons) that will be searched for pixmaps referenced in
 *       RC files.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>im_module_file <replaceable>pathname</replaceable></literal></term>
 *     <listitem>
 *       <para>Sets the pathname for the IM modules file. Setting this from RC files
 *       is deprecated; you should use the environment variable <envar>GTK_IM_MODULE_FILE</envar>
 *       instead.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>style <replaceable>name</replaceable> [ =
 *     <replaceable>parent</replaceable> ] { ... }</literal></term>
 *     <listitem>
 *       <para>Declares a style.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>widget <replaceable>pattern</replaceable>
 *           [ style | binding ][ : <replaceable>priority</replaceable> ]
 *           <replaceable>name</replaceable></literal></term>
 *     <listitem>
 *      <para>Specifies a style or binding set for a particular
 *      group of widgets by matching on the widget pathname.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>widget_class <replaceable>pattern</replaceable>
 *           [ style | binding ][ : <replaceable>priority</replaceable> ]
 *           <replaceable>name</replaceable></literal></term>
 *     <listitem>
 *      <para>Specifies a style or binding set for a particular
 *      group of widgets by matching on the class pathname.</para>
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><replaceable>setting</replaceable> = <replaceable>value</replaceable></term>
 *     <listitem>
 *       <para>Specifies a value for a <link linkend="GtkSettings">setting</link>.
 *         Note that settings in RC files are overwritten by system-wide settings
 *         (which are managed by an XSettings manager on X11).</para>
 *     </listitem>
 *   </varlistentry>
 * </variablelist>
 * </para>
 * </refsect2>
 * <refsect2>
 * <title>Styles</title>
 * <para>
 * A RC style is specified by a <literal>style</literal>
 * declaration in a RC file, and then bound to widgets
 * with a <literal>widget</literal>, <literal>widget_class</literal>,
 * or <literal>class</literal> declaration. All styles
 * applying to a particular widget are composited together
 * with <literal>widget</literal> declarations overriding
 * <literal>widget_class</literal> declarations which, in
 * turn, override <literal>class</literal> declarations.
 * Within each type of declaration, later declarations override
 * earlier ones.
 *
 * Within a <literal>style</literal> declaration, the possible
 * elements are:
 *
 * <variablelist>
 *   <varlistentry>
 *     <term><literal>bg[<replaceable>state</replaceable>] =
 *       <replaceable>color</replaceable></literal></term>
 *      <listitem>
 *          Sets the color used for the background of most widgets.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>fg[<replaceable>state</replaceable>] =
 *       <replaceable>color</replaceable></literal></term>
 *      <listitem>
 *          Sets the color used for the foreground of most widgets.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>base[<replaceable>state</replaceable>] =
 *       <replaceable>color</replaceable></literal></term>
 *      <listitem>
 *          Sets the color used for the background of widgets displaying
 *          editable text. This color is used for the background
 *          of, among others, #GtkText, #GtkEntry, #GtkList, and #GtkCList.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>text[<replaceable>state</replaceable>] =
 *       <replaceable>color</replaceable></literal></term>
 *      <listitem>
 *          Sets the color used for foreground of widgets using
 *          <literal>base</literal> for the background color.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>xthickness =
 *       <replaceable>number</replaceable></literal></term>
 *      <listitem>
 *          Sets the xthickness, which is used for various horizontal padding
 *          values in GTK+.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>ythickness =
 *       <replaceable>number</replaceable></literal></term>
 *      <listitem>
 *          Sets the ythickness, which is used for various vertical padding
 *          values in GTK+.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>bg_pixmap[<replaceable>state</replaceable>] =
 *       <replaceable>pixmap</replaceable></literal></term>
 *      <listitem>
 *          Sets a background pixmap to be used in place of
 *          the <literal>bg</literal> color (or for #GtkText,
 *          in place of the <literal>base</literal> color. The special
 *          value <literal>"&lt;parent&gt;"</literal> may be used to indicate that the widget should
 *          use the same background pixmap as its parent. The special value
 *          <literal>"&lt;none&gt;"</literal> may be used to indicate no background pixmap.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>font = <replaceable>font</replaceable></literal></term>
 *      <listitem>
 *          Starting with GTK+ 2.0, the "font" and "fontset"
 *          declarations are ignored; use "font_name" declarations instead.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>fontset = <replaceable>font</replaceable></literal></term>
 *      <listitem>
 *          Starting with GTK+ 2.0, the "font" and "fontset"
 *          declarations are ignored; use "font_name" declarations instead.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>font_name = <replaceable>font</replaceable></literal></term>
 *      <listitem>
 *          Sets the font for a widget. <replaceable>font</replaceable> must be
 *          a Pango font name, e.g. <literal>"Sans Italic 10"</literal>.
 *          For details about Pango font names, see
 *          pango_font_description_from_string().
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>stock[<replaceable>"stock-id"</replaceable>] = { <replaceable>icon source specifications</replaceable> }</literal></term>
 *      <listitem>
 *         Defines the icon for a stock item.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>color[<replaceable>"color-name"</replaceable>] = <replaceable>color specification</replaceable></literal></term>
 *      <listitem>
 *         Since 2.10, this element can be used to defines symbolic colors. See below for
 *         the syntax of color specifications.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>engine <replaceable>"engine"</replaceable> { <replaceable>engine-specific
 * settings</replaceable> }</literal></term>
 *      <listitem>
 *         Defines the engine to be used when drawing with this style.
 *      </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal><replaceable>class</replaceable>::<replaceable>property</replaceable> = <replaceable>value</replaceable></literal></term>
 *      <listitem>
 *         Sets a <link linkend="style-properties">style property</link> for a widget class.
 *      </listitem>
 *   </varlistentry>
 * </variablelist>
 *
 * The colors and background pixmaps are specified as a function of the
 * state of the widget. The states are:
 *
 * <variablelist>
 *   <varlistentry>
 *     <term><literal>NORMAL</literal></term>
 *     <listitem>
 *         A color used for a widget in its normal state.
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>ACTIVE</literal></term>
 *     <listitem>
 *         A variant of the <literal>NORMAL</literal> color used when the
 *         widget is in the %GTK_STATE_ACTIVE state, and also for
 *         the trough of a ScrollBar, tabs of a NoteBook
 *         other than the current tab and similar areas.
 *         Frequently, this should be a darker variant
 *         of the <literal>NORMAL</literal> color.
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>PRELIGHT</literal></term>
 *     <listitem>
 *         A color used for widgets in the %GTK_STATE_PRELIGHT state. This
 *         state is the used for Buttons and MenuItems
 *         that have the mouse cursor over them, and for
 *         their children.
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>SELECTED</literal></term>
 *     <listitem>
 *         A color used to highlight data selected by the user.
 *         for instance, the selected items in a list widget, and the
 *         selection in an editable widget.
 *     </listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><literal>INSENSITIVE</literal></term>
 *     <listitem>
 *         A color used for the background of widgets that have
 *         been set insensitive with gtk_widget_set_sensitive().
 *     </listitem>
 *   </varlistentry>
 * </variablelist>
 *
 * <anchor id="color-format"/>
 * Colors can be specified as a string containing a color name (GTK+ knows
 * all names from the X color database <filename>/usr/lib/X11/rgb.txt</filename>),
 * in one of the hexadecimal forms <literal>#rrrrggggbbbb</literal>,
 * <literal>#rrrgggbbb</literal>, <literal>#rrggbb</literal>,
 * or <literal>#rgb</literal>, where <literal>r</literal>,
 * <literal>g</literal> and <literal>b</literal> are
 * hex digits, or they can be specified as a triplet
 * <literal>{ <replaceable>r</replaceable>, <replaceable>g</replaceable>,
 * <replaceable>b</replaceable>}</literal>, where <literal>r</literal>,
 * <literal>g</literal> and <literal>b</literal> are either integers in
 * the range 0-65535 or floats in the range 0.0-1.0.
 *
 * Since 2.10, colors can also be specified by refering to a symbolic color, as
 * follows: <literal>@<!-- -->color-name</literal>, or by using expressions to combine
 * colors. The following expressions are currently supported:
 *   <variablelist>
 *     <varlistentry>
 *       <term>mix (<replaceable>factor</replaceable>, <replaceable>color1</replaceable>, <replaceable>color2</replaceable>)</term>
 *       <listitem><para>
 *         Computes a new color by mixing <replaceable>color1</replaceable> and
 *         <replaceable>color2</replaceable>. The <replaceable>factor</replaceable>
 *         determines how close the new color is to <replaceable>color1</replaceable>.
 *         A factor of 1.0 gives pure <replaceable>color1</replaceable>, a factor of
 *         0.0 gives pure <replaceable>color2</replaceable>.
 *       </para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term>shade (<replaceable>factor</replaceable>, <replaceable>color</replaceable>)</term>
 *       <listitem><para>
 *         Computes a lighter or darker variant of <replaceable>color</replaceable>.
 *         A <replaceable>factor</replaceable> of 1.0 leaves the color unchanged, smaller
 *         factors yield darker colors, larger factors yield lighter colors.
 *       </para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term>lighter (<replaceable>color</replaceable>)</term>
 *       <listitem><para>
 *         This is an abbreviation for
 *         <literal>shade (1.3, <replaceable>color</replaceable>)</literal>.
 *       </para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term>darker (<replaceable>color</replaceable>)</term>
 *       <listitem><para>
 *         This is an abbreviation for
 *         <literal>shade (0.7, <replaceable>color</replaceable>)</literal>.
 *       </para></listitem>
 *     </varlistentry>
 *   </variablelist>
 *
 * Here are some examples of color expressions:
 *
 * <informalexample><programlisting>
 *  mix (0.5, "red", "blue")
 *  shade (1.5, mix (0.3, "#0abbc0", { 0.3, 0.5, 0.9 }))
 *  lighter (@<!-- -->foreground)
 * </programlisting></informalexample>
 *
 * In a <literal>stock</literal> definition, icon sources are specified as a
 * 4-tuple of image filename or icon name, text direction, widget state, and size, in that
 * order.  Each icon source specifies an image filename or icon name to use with a given
 * direction, state, and size. Filenames are specified as a string such
 * as <literal>"itemltr.png"</literal>, while icon names (looked up
 * in the current icon theme), are specified with a leading
 * <literal>@</literal>, such as <literal>@"item-ltr"</literal>.
 * The <literal>*</literal> character can be used as a
 * wildcard, and if direction/state/size are omitted they default to
 * <literal>*</literal>. So for example, the following specifies different icons to
 * use for left-to-right and right-to-left languages:
 *
 * <informalexample><programlisting>
 * stock["my-stock-item"] =
 * {
 *   { "itemltr.png", LTR, *, * },
 *   { "itemrtl.png", RTL, *, * }
 * }
 * </programlisting></informalexample>
 *
 * This could be abbreviated as follows:
 *
 * <informalexample><programlisting>
 * stock["my-stock-item"] =
 * {
 *   { "itemltr.png", LTR },
 *   { "itemrtl.png", RTL }
 * }
 * </programlisting></informalexample>
 *
 * You can specify custom icons for specific sizes, as follows:
 *
 * <informalexample><programlisting>
 * stock["my-stock-item"] =
 * {
 *   { "itemmenusize.png", *, *, "gtk-menu" },
 *   { "itemtoolbarsize.png", *, *, "gtk-large-toolbar" }
 *   { "itemgeneric.png" } // implicit *, *, * as a fallback
 * }
 * </programlisting></informalexample>
 *
 * The sizes that come with GTK+ itself are <literal>"gtk-menu"</literal>,
 * <literal>"gtk-small-toolbar"</literal>, <literal>"gtk-large-toolbar"</literal>,
 * <literal>"gtk-button"</literal>, <literal>"gtk-dialog"</literal>. Applications
 * can define other sizes.
 *
 * It's also possible to use custom icons for a given state, for example:
 *
 * <informalexample><programlisting>
 * stock["my-stock-item"] =
 * {
 *   { "itemprelight.png", *, PRELIGHT },
 *   { "iteminsensitive.png", *, INSENSITIVE },
 *   { "itemgeneric.png" } // implicit *, *, * as a fallback
 * }
 * </programlisting></informalexample>
 *
 * When selecting an icon source to use, GTK+ will consider text direction most
 * important, state second, and size third. It will select the best match based on
 * those criteria. If an attribute matches exactly (e.g. you specified
 * <literal>PRELIGHT</literal> or specified the size), GTK+ won't modify the image;
 * if the attribute matches with a wildcard, GTK+ will scale or modify the image to
 * match the state and size the user requested.
 * </para>
 * </refsect2>
 * <refsect2>
 * <title>Key bindings</title>
 * <para>
 * Key bindings allow the user to specify actions to be
 * taken on particular key presses. The form of a binding
 * set declaration is:
 *
 * <informalexample><programlisting>
 * binding <replaceable>name</replaceable> {
 *   bind <replaceable>key</replaceable> {
 *     <replaceable>signalname</replaceable> (<replaceable>param</replaceable>, ...)
 *     ...
 *   }
 *   ...
 * }
 * </programlisting></informalexample>
 *
 * <replaceable>key</replaceable> is a string consisting of a
 * series of modifiers followed by the name of a key. The
 * modifiers can be:
 * <simplelist>
 * <member><literal>&lt;alt&gt;</literal></member>
 * <member><literal>&lt;ctl&gt;</literal></member>
 * <member><literal>&lt;control&gt;</literal></member>
 * <member><literal>&lt;meta&gt;</literal></member>
 * <member><literal>&lt;hyper&gt;</literal></member>
 * <member><literal>&lt;super&gt;</literal></member>
 * <member><literal>&lt;mod1&gt;</literal></member>
 * <member><literal>&lt;mod2&gt;</literal></member>
 * <member><literal>&lt;mod3&gt;</literal></member>
 * <member><literal>&lt;mod4&gt;</literal></member>
 * <member><literal>&lt;mod5&gt;</literal></member>
 * <member><literal>&lt;release&gt;</literal></member>
 * <member><literal>&lt;shft&gt;</literal></member>
 * <member><literal>&lt;shift&gt;</literal></member>
 * </simplelist>
 * <literal>&lt;shft&gt;</literal> is an alias for
 * <literal>&lt;shift&gt;</literal>,
 * <literal>&lt;ctl&gt;</literal> is an alias for
 * <literal>&lt;control&gt;</literal>,
 *  and
 * <literal>&lt;alt&gt;</literal> is an alias for
 * <literal>&lt;mod1&gt;</literal>.
 *
 * The action that is bound to the key is a sequence
 * of signal names (strings) followed by parameters for
 * each signal. The signals must be action signals.
 * (See g_signal_new()). Each parameter can be
 * a float, integer, string, or unquoted string
 * representing an enumeration value. The types of
 * the parameters specified must match the types of the
 * parameters of the signal.
 *
 * Binding sets are connected to widgets in the same manner as styles,
 * with one difference: Binding sets override other binding sets first
 * by pattern type, then by priority and then by order of specification.
 * The priorities that can be specified and their default values are the
 * same as for styles.
 * </para>
 * </refsect2>
 */


724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
enum 
{
  PATH_ELT_PSPEC,
  PATH_ELT_UNRESOLVED,
  PATH_ELT_TYPE
};

typedef struct
{
  gint type;
  union 
  {
    GType         class_type;
    gchar        *class_name;
    GPatternSpec *pspec;
  } elt;
} PathElt;

742 743 744 745 746 747 748
#define GTK_RC_STYLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RC_STYLE, GtkRcStylePrivate))

typedef struct _GtkRcStylePrivate GtkRcStylePrivate;

struct _GtkRcStylePrivate
{
  GSList *color_hashes;
749 750
};

751 752 753
static void        gtk_rc_style_finalize             (GObject         *object);
static void        gtk_rc_style_real_merge           (GtkRcStyle      *dest,
                                                      GtkRcStyle      *src);
754 755 756 757
static GtkRcStyle* gtk_rc_style_real_create_rc_style (GtkRcStyle      *rc_style);
static GtkStyle*   gtk_rc_style_real_create_style    (GtkRcStyle      *rc_style);
static gint	   gtk_rc_properties_cmp	     (gconstpointer    bsearch_node1,
						      gconstpointer    bsearch_node2);
758

759 760 761 762
static void	   insert_rc_property		     (GtkRcStyle      *style,
						      GtkRcProperty   *property,
						      gboolean         replace);

763

764
static const GScannerConfig gtk_rc_scanner_config =
765 766
{
  (
767
   " \t\r\n"
768 769 770
   )			/* cset_skip_characters */,
  (
   "_"
771
   G_CSET_a_2_z
772 773 774
   G_CSET_A_2_Z
   )			/* cset_identifier_first */,
  (
775 776
   G_CSET_DIGITS
   "-_"
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
   G_CSET_a_2_z
   G_CSET_A_2_Z
   )			/* cset_identifier_nth */,
  ( "#\n" )		/* cpair_comment_single */,
  
  TRUE			/* case_sensitive */,
  
  TRUE			/* skip_comment_multi */,
  TRUE			/* skip_comment_single */,
  TRUE			/* scan_comment_multi */,
  TRUE			/* scan_identifier */,
  FALSE			/* scan_identifier_1char */,
  FALSE			/* scan_identifier_NULL */,
  TRUE			/* scan_symbols */,
  TRUE			/* scan_binary */,
  TRUE			/* scan_octal */,
  TRUE			/* scan_float */,
  TRUE			/* scan_hex */,
  TRUE			/* scan_hex_dollar */,
796
  TRUE			/* scan_string_sq */,
797 798 799
  TRUE			/* scan_string_dq */,
  TRUE			/* numbers_2_int */,
  FALSE			/* int_2_float */,
800
  FALSE			/* identifier_2_string */,
801 802
  TRUE			/* char_2_token */,
  TRUE			/* symbol_2_token */,
803
  FALSE			/* scope_0_fallback */,
804
};
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
 
static const gchar symbol_names[] = 
  "include\0"
  "NORMAL\0"
  "ACTIVE\0"
  "PRELIGHT\0"
  "SELECTED\0"
  "INSENSITIVE\0"
  "fg\0"
  "bg\0"
  "text\0"
  "base\0"
  "xthickness\0"
  "ythickness\0"
  "font\0"
  "fontset\0"
  "font_name\0"
  "bg_pixmap\0"
  "pixmap_path\0"
  "style\0"
  "binding\0"
  "bind\0"
  "widget\0"
  "widget_class\0"
  "class\0"
  "lowest\0"
  "gtk\0"
  "application\0"
  "theme\0"
  "rc\0"
  "highest\0"
  "engine\0"
  "module_path\0"
  "stock\0"
  "im_module_file\0"
  "LTR\0"
  "RTL\0"
842 843
  "color\0"
  "unbind\0";
844

845
static const struct
Elliot Lee's avatar
Elliot Lee committed
846
{
847
  guint name_offset;
848
  guint token;
849
} symbols[] = {
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
  {   0, GTK_RC_TOKEN_INCLUDE },
  {   8, GTK_RC_TOKEN_NORMAL },
  {  15, GTK_RC_TOKEN_ACTIVE },
  {  22, GTK_RC_TOKEN_PRELIGHT },
  {  31, GTK_RC_TOKEN_SELECTED },
  {  40, GTK_RC_TOKEN_INSENSITIVE },
  {  52, GTK_RC_TOKEN_FG },
  {  55, GTK_RC_TOKEN_BG },
  {  58, GTK_RC_TOKEN_TEXT },
  {  63, GTK_RC_TOKEN_BASE },
  {  68, GTK_RC_TOKEN_XTHICKNESS },
  {  79, GTK_RC_TOKEN_YTHICKNESS },
  {  90, GTK_RC_TOKEN_FONT },
  {  95, GTK_RC_TOKEN_FONTSET },
  { 103, GTK_RC_TOKEN_FONT_NAME },
  { 113, GTK_RC_TOKEN_BG_PIXMAP },
  { 123, GTK_RC_TOKEN_PIXMAP_PATH },
  { 135, GTK_RC_TOKEN_STYLE },
  { 141, GTK_RC_TOKEN_BINDING },
  { 149, GTK_RC_TOKEN_BIND },
  { 154, GTK_RC_TOKEN_WIDGET },
  { 161, GTK_RC_TOKEN_WIDGET_CLASS },
  { 174, GTK_RC_TOKEN_CLASS },
  { 180, GTK_RC_TOKEN_LOWEST },
  { 187, GTK_RC_TOKEN_GTK },
  { 191, GTK_RC_TOKEN_APPLICATION },
  { 203, GTK_RC_TOKEN_THEME },
  { 209, GTK_RC_TOKEN_RC },
  { 212, GTK_RC_TOKEN_HIGHEST },
  { 220, GTK_RC_TOKEN_ENGINE },
  { 227, GTK_RC_TOKEN_MODULE_PATH },
  { 239, GTK_RC_TOKEN_STOCK },
  { 245, GTK_RC_TOKEN_IM_MODULE_FILE },
  { 260, GTK_RC_TOKEN_LTR },
  { 264, GTK_RC_TOKEN_RTL },
885 886
  { 268, GTK_RC_TOKEN_COLOR },
  { 274, GTK_RC_TOKEN_UNBIND }
887
};
888

889
static GHashTable *realized_style_ht = NULL;
Elliot Lee's avatar
Elliot Lee committed
890

Owen Taylor's avatar
Owen Taylor committed
891 892
static gchar *im_module_file = NULL;

893
static gchar **gtk_rc_default_files = NULL;
894

895 896
/* RC file handling */

Owen Taylor's avatar
Owen Taylor committed
897 898
static gchar *
gtk_rc_make_default_dir (const gchar *type)
899
{
900 901
  const gchar *var;
  gchar *path;
902

Matthias Clasen's avatar
Matthias Clasen committed
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 911 912
  return path;
}

913 914
/**
 * gtk_rc_get_im_module_path:
915 916
 * @returns: (type filename): a newly-allocated string containing the
 *    path in which to look for IM modules.
917 918
 *
 * Obtains the path in which to look for IM modules. See the documentation
919 920 921 922
 * of the <link linkend="im-module-path"><envar>GTK_PATH</envar></link>
 * environment variable for more details about looking up modules. This
 * function is useful solely for utilities supplied with GTK+ and should
 * not be used by applications under normal circumstances.
923 924
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead.
925
 */
926
gchar *
Owen Taylor's avatar
Owen Taylor committed
927 928
gtk_rc_get_im_module_path (void)
{
929 930 931
  gchar **paths = _gtk_get_module_path ("immodules");
  gchar *result = g_strjoinv (G_SEARCHPATH_SEPARATOR_S, paths);
  g_strfreev (paths);
Owen Taylor's avatar
Owen Taylor committed
932

933
  return result;
Owen Taylor's avatar
Owen Taylor committed
934 935
}

936 937
/**
 * gtk_rc_get_im_module_file:
938 939
 * @returns: (type filename): a newly-allocated string containing the
 *    name of the file listing the IM modules available for loading
940 941 942 943
 *
 * Obtains the path to the IM modules file. See the documentation
 * of the <link linkend="im-module-file"><envar>GTK_IM_MODULE_FILE</envar></link>
 * environment variable for more details.
944 945
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead.
jacob berkman's avatar
jacob berkman committed
946
 */
Owen Taylor's avatar
Owen Taylor committed
947 948 949
gchar *
gtk_rc_get_im_module_file (void)
{
950 951 952 953 954
  const gchar *var = g_getenv ("GTK_IM_MODULE_FILE");
  gchar *result = NULL;

  if (var)
    result = g_strdup (var);
Owen Taylor's avatar
Owen Taylor committed
955 956 957 958

  if (!result)
    {
      if (im_module_file)
959
        result = g_strdup (im_module_file);
Owen Taylor's avatar
Owen Taylor committed
960
      else
961
        result = gtk_rc_make_default_dir ("immodules.cache");
Owen Taylor's avatar
Owen Taylor committed
962 963
    }

Tor Lillqvist's avatar
Tor Lillqvist committed
964
  return result;
Owen Taylor's avatar
Owen Taylor committed
965 966
}

967 968 969 970 971 972 973 974 975 976 977
/**
 * gtk_rc_get_theme_dir:
 *
 * Returns the standard directory in which themes should
 * be installed. (GTK+ does not actually use this directory
 * itself.)
 *
 * Returns: The directory (must be freed with g_free()).
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead.
 */
Owen Taylor's avatar
Owen Taylor committed
978
gchar *
Hans Breuer's avatar
Hans Breuer committed
979
gtk_rc_get_theme_dir (void)
980
{
981 982
  const gchar *var;
  gchar *path;
983

Matthias Clasen's avatar
Matthias Clasen committed
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 992 993
  return path;
}

994 995
/**
 * gtk_rc_get_module_dir:
996
 *
997 998
 * Returns a directory in which GTK+ looks for theme engines.
 * For full information about the search for theme engines,
Matthias Clasen's avatar
Matthias Clasen committed
999 1000
 * see the docs for <envar>GTK_PATH</envar> in
 * <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
 **/
Owen Taylor's avatar
Owen Taylor committed
1006
gchar *
Hans Breuer's avatar
Hans Breuer committed
1007
gtk_rc_get_module_dir (void)
Owen Taylor's avatar
Owen Taylor committed
1008 1009 1010 1011
{
  return gtk_rc_make_default_dir ("engines");
}

1012 1013
/**
 * gtk_rc_add_default_file:
1014 1015
 * @filename: (type filename): the pathname to the file. If @filename
 *    is not absolute, it is searched in the current directory.
1016
 *
1017 1018
 * Adds a file to the list of files to be parsed at the
 * 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 1030
 * @filenames: (array zero-terminated=1) (element-type filename): A
 *     %NULL-terminated list of filenames.
1031
 *
1032
 * Sets the list of files that GTK+ will read at the
Matthias Clasen's avatar
Matthias Clasen committed
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
Matthias Clasen's avatar
Matthias Clasen committed
1046
 * at the end of gtk_init().
1047
 *
1048 1049 1050 1051
 * Return value: (transfer none) (array zero-terminated=1) (element-type filename):
 *      A %NULL-terminated array of filenames.  This memory is owned
 *     by GTK+ and must not be freed by the application.  If you want
 *     to store this information, you should make a copy.
1052 1053
 *
 * Deprecated:3.0: Use #GtkStyleContext instead
1054
 **/
1055 1056 1057 1058 1059 1060
gchar **
gtk_rc_get_default_files (void)
{
  return gtk_rc_default_files;
}

1061 1062 1063 1064 1065 1066 1067 1068
/**
 * gtk_rc_parse_string:
 * @rc_string: a string to parse.
 *
 * Parses resource information directly from a string.
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead.
 */
Elliot Lee's avatar
Elliot Lee committed
1069
void
1070
gtk_rc_parse_string (const gchar *rc_string)
Elliot Lee's avatar
Elliot Lee committed
1071
{
1072
  g_return_if_fail (rc_string != NULL);
1073 1074
}

1075 1076 1077 1078 1079 1080 1081 1082 1083
/**
 * gtk_rc_parse:
 * @filename: the filename of a file to parse. If @filename is not absolute, it
 *  is searched in the current directory.
 *
 * Parses a given resource file.
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead.
 */
1084
void
1085 1086
gtk_rc_parse (const gchar *filename)
{
1087
  g_return_if_fail (filename != NULL);
1088 1089
}

1090 1091
/* Handling of RC styles */

Matthias Clasen's avatar
Matthias Clasen committed
1092
G_DEFINE_TYPE (GtkRcStyle, gtk_rc_style, G_TYPE_OBJECT)
1093

1094 1095 1096
static void
gtk_rc_style_init (GtkRcStyle *style)
{
1097
  GtkRcStylePrivate *priv = GTK_RC_STYLE_GET_PRIVATE (style);
1098 1099 1100
  guint i;

  style->name = NULL;
1101 1102
  style->font_desc = NULL;

1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
  for (i = 0; i < 5; i++)
    {
      static const GdkColor init_color = { 0, 0, 0, 0, };

      style->bg_pixmap_name[i] = NULL;
      style->color_flags[i] = 0;
      style->fg[i] = init_color;
      style->bg[i] = init_color;
      style->text[i] = init_color;
      style->base[i] = init_color;
    }
  style->xthickness = -1;
  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 1125
static void
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 1134
  klass->merge = gtk_rc_style_real_merge;
  klass->create_style = gtk_rc_style_real_create_style;
1135 1136

  g_type_class_add_private (object_class, sizeof (GtkRcStylePrivate));
1137 1138
}

1139 1140
static void
gtk_rc_style_finalize (GObject *object)
1141
{
1142 1143
  GSList *tmp_list1, *tmp_list2;
  GtkRcStyle *rc_style;
1144
  GtkRcStylePrivate *rc_priv;
1145
  gint i;
1146

1147
  rc_style = GTK_RC_STYLE (object);
1148 1149
  rc_priv = GTK_RC_STYLE_GET_PRIVATE (rc_style);

1150
  g_free (rc_style->name);
1151 1152
  if (rc_style->font_desc)
    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 1158 1159 1160 1161 1162 1163 1164
  /* Now remove all references to this rc_style from
   * realized_style_ht
   */
  tmp_list1 = rc_style->rc_style_lists;
  while (tmp_list1)
    {
      GSList *rc_styles = tmp_list1->data;
      GtkStyle *style = g_hash_table_lookup (realized_style_ht, rc_styles);
Manish Singh's avatar
Manish Singh committed
1165
      g_object_unref (style);
1166 1167 1168

      /* Remove the list of styles from the other rc_styles
       * in the list
1169
       */
1170 1171 1172 1173 1174 1175
      tmp_list2 = rc_styles;
      while (tmp_list2)
        {
          GtkRcStyle *other_style = tmp_list2->data;

          if (other_style != rc_style)
1176 1177
            other_style->rc_style_lists = g_slist_remove_all (other_style->rc_style_lists,
							      rc_styles);
1178 1179
          tmp_list2 = tmp_list2->next;
        }
1180

1181 1182 1183 1184
      /* And from the hash table itself
       */
      g_hash_table_remove (realized_style_ht, rc_styles);
      g_slist_free (rc_styles);
1185

1186 1187 1188
      tmp_list1 = tmp_list1->next;
    }
  g_slist_free (rc_style->rc_style_lists);
1189

1190 1191 1192 1193
  if (rc_style->rc_properties)
    {
      guint i;

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 1199 1200

	  g_free (node->origin);
	  g_value_unset (&node->value);
	}
1201
      g_array_free (rc_style->rc_properties, TRUE);
1202 1203 1204
      rc_style->rc_properties = NULL;
    }

1205
  g_slist_foreach (rc_style->icon_factories, (GFunc) g_object_unref, NULL);
1206
  g_slist_free (rc_style->icon_factories);
1207 1208 1209 1210

  g_slist_foreach (rc_priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
  g_slist_free (rc_priv->color_hashes);

Matthias Clasen's avatar
Matthias Clasen committed
1211
  G_OBJECT_CLASS (gtk_rc_style_parent_class)->finalize (object);
1212
}
1213

1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
/**
 * gtk_rc_style_new:
 *
 * Creates a new #GtkRcStyle with no fields set and
 * a reference count of 1.
 *
 * Returns: the newly-created #GtkRcStyle
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead.
 */
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 1232
  return style;
}
1233

1234 1235 1236
/**
 * gtk_rc_style_copy:
 * @orig: the style to copy
1237
 *
Matthias Clasen's avatar
Matthias Clasen committed
1238
 * Makes a copy of the specified #GtkRcStyle. This function
Matthias Clasen's avatar
Matthias Clasen committed
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 1247 1248 1249 1250
 **/
GtkRcStyle *
gtk_rc_style_copy (GtkRcStyle *orig)
{
  GtkRcStyle *style;

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 1255 1256 1257 1258
  GTK_RC_STYLE_GET_CLASS (style)->merge (style, orig);

  return style;
}

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 1266 1267 1268 1269 1270 1271
static gint
gtk_rc_properties_cmp (gconstpointer bsearch_node1,
		       gconstpointer bsearch_node2)
{
  const GtkRcProperty *prop1 = bsearch_node1;
  const GtkRcProperty *prop2 = bsearch_node2;

1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
  if (prop1->type_name == prop2->type_name)
    return prop1->property_name < prop2->property_name ? -1 : prop1->property_name == prop2->property_name ? 0 : 1;
  else
    return prop1->type_name < prop2->type_name ? -1 : 1;
}

static void
insert_rc_property (GtkRcStyle    *style,
		    GtkRcProperty *property,
		    gboolean       replace)
{
  guint i;
  GtkRcProperty *new_property = NULL;
  GtkRcProperty key = { 0, 0, NULL, { 0, }, };

  key.type_name = property->type_name;
  key.property_name = property->property_name;

  if (!style->rc_properties)
    style->rc_properties = g_array_new (FALSE, FALSE, sizeof (GtkRcProperty));

  i = 0;
  while (i < style->rc_properties->len)
    {
      gint cmp = gtk_rc_properties_cmp (&key, &g_array_index (style->rc_properties, GtkRcProperty, i));
1297

1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
      if (cmp == 0)
	{
	  if (replace)
	    {
	      new_property = &g_array_index (style->rc_properties, GtkRcProperty, i);
	      
	      g_free (new_property->origin);
	      g_value_unset (&new_property->value);
	      
	      *new_property = key;
	      break;
	    }
	  else
	    return;
	}
1313
      else if (cmp < 0)
1314
	break;
1315

1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
      i++;
    }

  if (!new_property)
    {
      g_array_insert_val (style->rc_properties, i, key);
      new_property = &g_array_index (style->rc_properties, GtkRcProperty, i);
    }

  new_property->origin = g_strdup (property->origin);
  g_value_init (&new_property->value, G_VALUE_TYPE (&property->value));
  g_value_copy (&property->value, &new_property->value);
1328 1329
}

1330 1331 1332 1333 1334
static void
gtk_rc_style_real_merge (GtkRcStyle *dest,
			 GtkRcStyle *src)
{
  gint i;
1335

1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371
  for (i = 0; i < 5; i++)
    {
      if (!dest->bg_pixmap_name[i] && src->bg_pixmap_name[i])
	dest->bg_pixmap_name[i] = g_strdup (src->bg_pixmap_name[i]);
      
      if (!(dest->color_flags[i] & GTK_RC_FG) && 
	  src->color_flags[i] & GTK_RC_FG)
	{
	  dest->fg[i] = src->fg[i];
	  dest->color_flags[i] |= GTK_RC_FG;
	}
      if (!(dest->color_flags[i] & GTK_RC_BG) && 
	  src->color_flags[i] & GTK_RC_BG)
	{
	  dest->bg[i] = src->bg[i];
	  dest->color_flags[i] |= GTK_RC_BG;
	}
      if (!(dest->color_flags[i] & GTK_RC_TEXT) && 
	  src->color_flags[i] & GTK_RC_TEXT)
	{
	  dest->text[i] = src->text[i];
	  dest->color_flags[i] |= GTK_RC_TEXT;
	}
      if (!(dest->color_flags[i] & GTK_RC_BASE) && 
	  src->color_flags[i] & GTK_RC_BASE)
	{
	  dest->base[i] = src->base[i];
	  dest->color_flags[i] |= GTK_RC_BASE;
	}
    }

  if (dest->xthickness < 0 && src->xthickness >= 0)
    dest->xthickness = src->xthickness;
  if (dest->ythickness < 0 && src->ythickness >= 0)
    dest->ythickness = src->ythickness;

1372 1373 1374 1375 1376 1377 1378
  if (src->font_desc)
    {
      if (!dest->font_desc)
	dest->font_desc = pango_font_description_copy (src->font_desc);
      else
	pango_font_description_merge (dest->font_desc, src->font_desc, FALSE);
    }
1379 1380 1381 1382 1383

  if (src->rc_properties)
    {
      guint i;

1384 1385 1386 1387
      for (i = 0; i < src->rc_properties->len; i++)
	insert_rc_property (dest,
			    &g_array_index (src->rc_properties, GtkRcProperty, i),
			    FALSE);
1388
    }
1389 1390 1391 1392 1393 1394 1395 1396
}

static GtkStyle *
gtk_rc_style_real_create_style (GtkRcStyle *rc_style)
{
  return gtk_style_new ();
}

1397
/**
1398
 * gtk_rc_reset_styles:
1399
 * @settings: a #GtkSettings
1400
 *
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410
 * This function recomputes the styles for all widgets that use a
 * particular #GtkSettings object. (There is one #GtkSettings object
 * per #GdkScreen, see gtk_settings_get_for_screen()); It is useful
 * when some global parameter has changed that affects the appearance
 * of all widgets, because when a widget gets a new style, it will
 * both redraw and recompute any cached information about its
 * appearance. As an example, it is used when the default font size
 * set by the operating system changes. Note that this function
 * doesn't affect widgets that have a style set explicitely on them
 * with gtk_widget_set_style().
Matthias Clasen's avatar
Matthias Clasen committed
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 1424
/**
 * gtk_rc_reparse_all_for_settings:
 * @settings: a #GtkSettings
1425
 * @force_load: load whether or not anything changed
1426
 *
1427 1428 1429
 * If the modification time on any previously read file
 * for the given #GtkSettings has changed, discard all style information
 * 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 1436 1437
 **/
gboolean
gtk_rc_reparse_all_for_settings (GtkSettings *settings,
				 gboolean     force_load)
1438
{
1439
  return FALSE;
1440 1441
}

1442 1443
/**
 * gtk_rc_reparse_all:
1444
 *
1445 1446 1447
 * If the modification time on any previously read file for the
 * default #GtkSettings has changed, discard all style information
 * 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 1454
 **/
gboolean
gtk_rc_reparse_all (void)
1455
{
1456
  return FALSE;
1457 1458
}

1459 1460 1461
/**
 * gtk_rc_get_style:
 * @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 1468
 * created styles, so a new style may not be
 * created.)
1469
 *
1470 1471 1472
 * Returns: (transfer none): the resulting style. No refcount is added
 *   to the returned style, so if you want to save this style around,
 *   you should add a reference yourself.
1473 1474
 *
 * Deprecated:3.0: Use #GtkStyleContext instead
1475
 **/
1476
GtkStyle *
Elliot Lee's avatar
Elliot Lee committed
1477 1478
gtk_rc_get_style (GtkWidget *widget)
{
1479 1480
  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);

1481
  gtk_widget_ensure_style (widget);
1482

1483
  return gtk_widget_get_style (widget);
Elliot Lee's avatar
Elliot Lee committed
1484 1485
}

1486 1487 1488
/**
 * gtk_rc_get_style_by_paths:
 * @settings: a #GtkSettings object
1489 1490 1491 1492
 * @widget_path: (allow-none): the widget path to use when looking up the
 *     style, or %NULL if no matching against the widget path should be done
 * @class_path: (allow-none): the class path to use when looking up the style,
 *     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 1497 1498 1499 1500 1501 1502
 * Creates up a #GtkStyle from styles defined in a RC file by providing
 * the raw components used in matching. This function may be useful
 * when creating pseudo-widgets that should be themed like widgets but
 * don't actually have corresponding GTK+ widgets. An example of this
 * would be items inside a GNOME canvas widget.
 *
 * The action of gtk_rc_get_style() is similar to:
Matthias Clasen's avatar
Matthias Clasen committed
1503 1504 1505
 * |[
 *  gtk_widget_path (widget, NULL, &path, NULL);
 *  gtk_widget_class_path (widget, NULL, &class_path, NULL);
1506
 *  gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget),
Matthias Clasen's avatar
Matthias Clasen committed
1507
 *                             path, class_path,
1508
 *                             G_OBJECT_TYPE (widget));
Matthias Clasen's avatar
Matthias Clasen committed
1509
 * ]|
1510
 *
1511 1512 1513 1514 1515
 * Return value: (transfer none): A style created by matching with the
 *     supplied paths, or %NULL if nothing matching was specified and the
 *     default style should be used. The returned value is owned by GTK+
 *     as part of an internal cache, so you must call g_object_ref() on
 *     the returned value if you want to keep a reference to it.
1516 1517
 *
 * Deprecated:3.0: Use #GtkStyleContext instead
1518 1519 1520 1521 1522 1523 1524
 **/
GtkStyle *
gtk_rc_get_style_by_paths (GtkSettings *settings,
			   const char  *widget_path,
			   const char  *class_path,
			   GType        type)
{
1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601
  GtkWidgetPath *path;
  GtkStyle *style;

  path = gtk_widget_path_new ();

  /* For compatibility, we return a GtkStyle based on a GtkStyleContext
   * with a GtkWidgetPath appropriate for the supplied information.
   *
   * GtkWidgetPath is composed of a list of GTypes with optional names;
   * In GTK+-2.0, widget_path consisted of the widget names, or
   * the class names for unnamed widgets, while class_path had the
   * class names always. So, use class_path to determine the GTypes
   * and extract widget names from widget_path as applicable.
   */
  if (class_path == NULL)
    {
      gtk_widget_path_append_type (path, type == G_TYPE_NONE ? GTK_TYPE_WIDGET : type);
    }
  else
    {
      const gchar *widget_p, *widget_next;
      const gchar *class_p, *class_next;

      widget_next = widget_path;
      class_next = class_path;

      while (*class_next)
	{
	  GType component_type;
	  gchar *component_class;
	  gchar *component_name;
	  gint pos;

	  class_p = class_next;
	  if (*class_p == '.')
	    class_p++;

	  widget_p = widget_next; /* Might be NULL */
	  if (widget_p && *widget_p == '.')
	    widget_p++;

	  class_next = strchr (class_p, '.');
	  if (class_next == NULL)
	    class_next = class_p + strlen (class_p);

	  if (widget_p)
	    {
	      widget_next = strchr (widget_p, '.');
	      if (widget_next == NULL)
		widget_next = widget_p + strlen (widget_p);
	    }

	  component_class = g_strndup (class_p, class_next - class_p);
	  if (widget_p && *widget_p)
	    component_name = g_strndup (widget_p, widget_next - widget_p);
	  else
	    component_name = NULL;

	  component_type = g_type_from_name (component_class);
	  if (component_type == G_TYPE_INVALID)
	    component_type = GTK_TYPE_WIDGET;

	  pos = gtk_widget_path_append_type (path, component_type);
	  if (component_name != NULL && strcmp (component_name, component_name) != 0)
	    gtk_widget_path_iter_set_name (path, pos, component_name);

	  g_free (component_class);
	  g_free (component_name);
	}
    }

  style = _gtk_style_new_for_path (_gtk_settings_get_screen (settings),
				   path);

  gtk_widget_path_free (path);

  return style;
1602 1603
}

1604
/**
1605
 * gtk_rc_scanner_new: (skip)
1606 1607 1608
 *
 * Deprecated:3.0: Use #GtkCssProvider instead
 */
1609 1610 1611 1612 1613 1614
GScanner*
gtk_rc_scanner_new (void)
{
  return g_scanner_new (&gtk_rc_scanner_config);
}

1615 1616 1617 1618
/*********************
 * Parsing functions *
 *********************/

1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
static gboolean
lookup_color (GtkRcStyle *style,
              const char *color_name,
              GdkColor   *color)
{
  GtkRcStylePrivate *priv = GTK_RC_STYLE_GET_PRIVATE (style);
  GSList *iter;

  for (iter = priv->color_hashes; iter != NULL; iter = iter->next)
    {
      GHashTable *hash  = iter->data;
      GdkColor   *match = g_hash_table_lookup (hash, color_name);

      if (match)
        {
          color->red = match->red;
          color->green = match->green;
          color->blue = match->blue;
          return TRUE;
        }
    }

  return FALSE;
}

1644 1645 1646 1647 1648 1649
/**
 * gtk_rc_find_pixmap_in_path:
 * @settings: a #GtkSettings
 * @scanner: Scanner used to get line number information for the
 *   warning message, or %NULL
 * @pixmap_file: name of the pixmap file to locate.
1650
 *
1651 1652 1653 1654
 * Looks up a file in pixmap path for the specified #GtkSettings.
 * If the file is not found, it outputs a warning message using
 * g_warning() and returns %NULL.
 *
1655 1656 1657
 * Return value: (type filename): the filename.
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead.
1658 1659 1660 1661 1662 1663
 **/
gchar*
gtk_rc_find_pixmap_in_path (GtkSettings  *settings,
			    GScanner     *scanner,
			    const gchar  *pixmap_file)
{
1664
  g_warning ("Unable to locate image file in pixmap_path: \"%s\"",
1665
             pixmap_file);
1666 1667 1668 1669 1670 1671
  return NULL;
}

/**
 * gtk_rc_find_module_in_path:
 * @module_file: name of a theme engine
1672
 *
1673 1674
 * Searches for a theme engine in the GTK+ search path. This function
 * is not useful for applications and should not be used.
1675
 *
1676 1677
 * Return value: (type filename): The filename, if found (must be
 *   freed with g_free()), otherwise %NULL.
1678 1679
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead.
1680 1681 1682 1683 1684 1685 1686 1687 1688
 **/
gchar*
gtk_rc_find_module_in_path (const gchar *module_file)
{
  return _gtk_find_module (module_file, "engines");
}

/**
 * gtk_rc_parse_state:
1689 1690 1691
 * @scanner: a #GtkScanner (must be initialized for parsing an RC file)
 * @state: (out): A pointer to a #GtkStateType variable in which to
 *  store the result.
1692
 *
1693 1694 1695 1696 1697 1698 1699
 * Parses a #GtkStateType variable from the format expected
 * in a RC file.
 *
 * Returns: %G_TOKEN_NONE if parsing succeeded, otherwise the token
 *   that was expected but not found.
 *
 * Deprecated: 3.0: Use #GtkCssProvider instead
1700 1701 1702 1703 1704 1705 1706
 */
guint
gtk_rc_parse_state (GScanner	 *scanner,
		    GtkStateType *state)
{
  guint old_scope;
  guint token;
1707

1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721
  g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
  g_return_val_if_fail (state != NULL, G_TOKEN_ERROR);
  
  /* we don't know where we got called from, so we reset the scope here.
   * if we bail out due to errors, we *don't* reset the scope, so the
   * error messaging code can make sense of our tokens.
   */
  old_scope = g_scanner_set_scope (scanner, 0);
  
  token = g_scanner_get_next_token (scanner);
  if (token != G_TOKEN_LEFT_BRACE)
    return G_TOKEN_LEFT_BRACE;
  
  token = g_scanner_get_next_token (scanner);
1722 1723
  switch (token)
    {
1724 1725
    case GTK_RC_TOKEN_ACTIVE:
      *state = GTK_STATE_ACTIVE;
1726
      break;
1727 1728
    case GTK_RC_TOKEN_INSENSITIVE:
      *state = GTK_STATE_INSENSITIVE;
1729
      break;
1730 1731
    case GTK_RC_TOKEN_NORMAL:
      *state = GTK_STATE_NORMAL;
1732
      break;
1733 1734
    case GTK_RC_TOKEN_PRELIGHT:
      *state = GTK_STATE_PRELIGHT;
1735
      break;
1736 1737 1738 1739 1740
    case GTK_RC_TOKEN_SELECTED:
      *state = GTK_STATE_SELECTED;
      break;
    default:
      return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
1741
    }
1742 1743 1744 1745 1746 1747
  
  token = g_scanner_get_next_token (scanner);
  if (token != G_TOKEN_RIGHT_BRACE)
    return G_TOKEN_RIGHT_BRACE;
  
  g_scanner_set_scope (scanner, old_scope);
1748

1749
  return G_TOKEN_NONE;
Elliot Lee's avatar
Elliot Lee committed
1750 1751
}

1752 1753
/**
 * gtk_rc_parse_priority:
1754 1755 1756 1757 1758 1759 1760 1761 1762
 * @scanner: a #GtkScanner (must be initialized for parsing an RC file)
 * @priority: A pointer to #GtkPathPriorityType variable in which
 *  to store the result.
 *
 * Parses a #GtkPathPriorityType variable from the format expected
 * in a RC file.
 *
 * Returns: %G_TOKEN_NONE if parsing succeeded, otherwise the token
 *   that was expected but not found.
1763 1764 1765 1766 1767 1768
 *
 * Deprecated:3.0: Use #GtkCssProvider instead
 */
guint
gtk_rc_parse_priority (GScanner	           *scanner,
		       GtkPathPriorityType *priority)
1769
{
1770
  guint old_scope;
1771 1772
  guint token;

1773 1774
  g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
  g_return_val_if_fail (priority != NULL, G_TOKEN_ERROR);
Owen Taylor's avatar
Owen Taylor committed
1775

1776 1777 1778 1779 1780
  /* we don't know where we got called from, so we reset the scope here.
   * if we bail out due to errors, we *don't* reset the scope, so the
   * error messaging code can make sense of our tokens.
   */
  old_scope = g_scanner_set_scope (scanner, 0);
Owen Taylor's avatar
Owen Taylor committed
1781 1782
  
  token = g_scanner_get_next_token (scanner);
1783 1784
  if (token != ':')
    return ':';
1785 1786
  
  token = g_scanner_get_next_token (scanner);
1787 1788
  switch (token)
    {
1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799
    case GTK_RC_TOKEN_LOWEST:
      *priority = GTK_PATH_PRIO_LOWEST;
      break;
    case GTK_RC_TOKEN_GTK:
      *priority = GTK_PATH_PRIO_GTK;
      break;
    case GTK_RC_TOKEN_APPLICATION:
      *priority = GTK_PATH_PRIO_APPLICATION;
      break;
    case GTK_RC_TOKEN_THEME:
      *priority = GTK_PATH_PRIO_THEME;
1800
      break;
1801 1802
    case GTK_RC_TOKEN_RC:
      *priority = GTK_PATH_PRIO_RC;
1803
      break;
1804 1805
    case GTK_RC_TOKEN_HIGHEST:
      *priority = GTK_PATH_PRIO_HIGHEST;
1806 1807
      break;
    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;
Elliot Lee's avatar
Elliot Lee committed
1814 1815
}

1816 1817 1818
/**
 * gtk_rc_parse_color:
 * @scanner: a #GScanner
1819 1820
 * @color: (out): a pointer to a #GdkColor structure in which to store
 *     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 1827 1828 1829 1830 1831 1832 1833 1834 1835
 * order to support symbolic colors.
 *
 * Returns: %G_TOKEN_NONE if parsing succeeded, otherwise the token
 *     that was expected but not found
 *
 * Deprecated:3.0: Use #GtkCssProvider instead
 */
guint
gtk_rc_parse_color (GScanner *scanner,
		    GdkColor *color)
1836
{
1837
  return gtk_rc_parse_color_full (scanner, NULL, color);
1838 1839
}

1840 1841 1842 1843
/**
 * gtk_rc_parse_color_full:
 * @scanner: a #GScanner
 * @style: (allow-none): a #GtkRcStyle, or %NULL
1844 1845
 * @color: (out): a pointer to a #GdkColor structure in which to store
 *     the result