* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * 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/.
+ */
+
+#include "config.h"
+
+#include "glib.h"
+#include "gdkconfig.h"
+
+#ifdef GDK_WINDOWING_X11
+#include <X11/Xlocale.h> /* so we get the right setlocale */
+#else
+#include <locale.h>
+#endif
#include <ctype.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <sys/stat.h>
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
+#endif
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
-#include "gtkrc.h"
-#include "gtkbindings.h"
+#include <stdlib.h>
+#ifndef HAVE_LSTAT
+#define lstat stat
+#endif
-enum {
- TOKEN_INVALID = G_TOKEN_LAST,
- TOKEN_INCLUDE,
- TOKEN_ACTIVE,
- TOKEN_BASE,
- TOKEN_BG,
- TOKEN_BG_PIXMAP,
- TOKEN_FG,
- TOKEN_FONT,
- TOKEN_FONTSET,
- TOKEN_INSENSITIVE,
- TOKEN_NORMAL,
- TOKEN_PIXMAP_PATH,
- TOKEN_PRELIGHT,
- TOKEN_SELECTED,
- TOKEN_STYLE,
- TOKEN_TEXT,
- TOKEN_WIDGET,
- TOKEN_WIDGET_CLASS,
- TOKEN_LAST
-};
+#ifdef G_OS_WIN32
+#include <windows.h> /* For GetWindowsDirectory */
+#include <io.h>
+#endif
+
+#include "gtkrc.h"
+#include "gtkbindings.h"
+#include "gtkthemes.h"
+#include "gtkintl.h"
-typedef struct _GtkRcStyle GtkRcStyle;
typedef struct _GtkRcSet GtkRcSet;
typedef struct _GtkRcNode GtkRcNode;
typedef struct _GtkRcFile GtkRcFile;
-struct _GtkRcNode
-{
- GdkColormap *cmap;
- GtkStyle *style;
-};
-
-struct _GtkRcStyle
-{
- char *name;
- char *font_name;
- char *fontset_name;
- char *bg_pixmap_name[5];
- GtkStyle *proto_style;
- GList *styles;
-};
-
struct _GtkRcSet
{
GtkPatternSpec pspec;
gboolean reload;
};
-static guint gtk_rc_style_hash (const char *name);
-static gint gtk_rc_style_compare (const char *a,
- const char *b);
-static GtkRcStyle* gtk_rc_style_find (const char *name);
-static GtkRcStyle* gtk_rc_styles_match (GSList *sets,
- guint path_length,
- gchar *path,
- gchar *path_reversed);
-static GtkStyle* gtk_rc_style_init (GtkRcStyle *rc_style,
- GdkColormap *cmap);
-static void gtk_rc_parse_file (const gchar *filename,
- gboolean reload);
-
-static void gtk_rc_parse_any (const gchar *input_name,
- gint input_fd,
- const gchar *input_string);
-static guint gtk_rc_parse_statement (GScanner *scanner);
-static guint gtk_rc_parse_style (GScanner *scanner);
-static guint gtk_rc_parse_base (GScanner *scanner,
- GtkStyle *style);
-static guint gtk_rc_parse_bg (GScanner *scanner,
- GtkStyle *style);
-static guint gtk_rc_parse_fg (GScanner *scanner,
- GtkStyle *style);
-static guint gtk_rc_parse_text (GScanner *scanner,
- GtkStyle *style);
-static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
- GtkRcStyle *rc_style);
-static guint gtk_rc_parse_font (GScanner *scanner,
- GtkRcStyle *rc_style);
-static guint gtk_rc_parse_fontset (GScanner *scanner,
- GtkRcStyle *rc_style);
-static guint gtk_rc_parse_state (GScanner *scanner,
- GtkStateType *state);
-static guint gtk_rc_parse_color (GScanner *scanner,
- GdkColor *color);
-static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
-static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
-static char* gtk_rc_find_pixmap_in_path (GScanner *scanner,
- gchar *pixmap_file);
-static guint gtk_rc_parse_widget_style (GScanner *scanner);
-static guint gtk_rc_parse_widget_class_style (GScanner *scanner);
-static void gtk_rc_clear_hash_node (gpointer key,
- gpointer data,
- gpointer user_data);
-static void gtk_rc_clear_styles (void);
-
-
-
-static GScannerConfig gtk_rc_scanner_config =
+static guint gtk_rc_style_hash (const char *name);
+static gint gtk_rc_style_compare (const char *a,
+ const char *b);
+static guint gtk_rc_styles_hash (const GSList *rc_styles);
+static gint gtk_rc_styles_compare (const GSList *a,
+ const GSList *b);
+static GtkRcStyle* gtk_rc_style_find (const char *name);
+static GSList * gtk_rc_styles_match (GSList *rc_styles,
+ GSList *sets,
+ guint path_length,
+ gchar *path,
+ gchar *path_reversed);
+static GtkStyle * gtk_rc_style_to_style (GtkRcStyle *rc_style);
+static GtkStyle* gtk_rc_init_style (GSList *rc_styles);
+static void gtk_rc_parse_file (const gchar *filename,
+ gboolean reload);
+static void gtk_rc_parse_any (const gchar *input_name,
+ gint input_fd,
+ const gchar *input_string);
+static guint gtk_rc_parse_statement (GScanner *scanner);
+static guint gtk_rc_parse_style (GScanner *scanner);
+static guint gtk_rc_parse_bg (GScanner *scanner,
+ GtkRcStyle *style);
+static guint gtk_rc_parse_fg (GScanner *scanner,
+ GtkRcStyle *style);
+static guint gtk_rc_parse_text (GScanner *scanner,
+ GtkRcStyle *style);
+static guint gtk_rc_parse_base (GScanner *scanner,
+ GtkRcStyle *style);
+static guint gtk_rc_parse_xthickness (GScanner *scanner,
+ GtkRcStyle *style);
+static guint gtk_rc_parse_ythickness (GScanner *scanner,
+ GtkRcStyle *style);
+static guint gtk_rc_parse_bg_pixmap (GScanner *scanner,
+ GtkRcStyle *rc_style);
+static guint gtk_rc_parse_font (GScanner *scanner,
+ GtkRcStyle *rc_style);
+static guint gtk_rc_parse_fontset (GScanner *scanner,
+ GtkRcStyle *rc_style);
+static guint gtk_rc_parse_font_name (GScanner *scanner,
+ GtkRcStyle *rc_style);
+static guint gtk_rc_parse_engine (GScanner *scanner,
+ GtkRcStyle **rc_style);
+static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
+static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
+static guint gtk_rc_parse_module_path (GScanner *scanner);
+static void gtk_rc_parse_module_path_string (gchar *mod_path);
+static guint gtk_rc_parse_path_pattern (GScanner *scanner);
+static void gtk_rc_clear_hash_node (gpointer key,
+ gpointer data,
+ gpointer user_data);
+static void gtk_rc_clear_styles (void);
+static void gtk_rc_append_default_module_path (void);
+static void gtk_rc_add_initial_default_files (void);
+
+static void gtk_rc_style_init (GtkRcStyle *style);
+static void gtk_rc_style_class_init (GtkRcStyleClass *klass);
+static void gtk_rc_style_finalize (GObject *object);
+static void gtk_rc_style_real_merge (GtkRcStyle *dest,
+ GtkRcStyle *src);
+static GtkRcStyle *gtk_rc_style_real_clone (GtkRcStyle *rc_style);
+static GtkStyle * gtk_rc_style_real_create_style (GtkRcStyle *rc_style);
+
+static gpointer parent_class = NULL;
+
+static const GScannerConfig gtk_rc_scanner_config =
{
(
- " \t\n"
+ " \t\r\n"
) /* cset_skip_characters */,
(
G_CSET_a_2_z
) /* cset_identifier_first */,
(
G_CSET_a_2_z
- "_0123456789"
+ "_-0123456789"
G_CSET_A_2_Z
- G_CSET_LATINS
- G_CSET_LATINC
) /* cset_identifier_nth */,
( "#\n" ) /* cpair_comment_single */,
TRUE /* scan_string_dq */,
TRUE /* numbers_2_int */,
FALSE /* int_2_float */,
- TRUE /* identifier_2_string */,
+ FALSE /* identifier_2_string */,
TRUE /* char_2_token */,
TRUE /* symbol_2_token */,
+ FALSE /* scope_0_fallback */,
};
-static struct
+static const struct
{
gchar *name;
guint token;
} symbols[] = {
- { "include", TOKEN_INCLUDE },
- { "ACTIVE", TOKEN_ACTIVE },
- { "base", TOKEN_BASE },
- { "bg", TOKEN_BG },
- { "bg_pixmap", TOKEN_BG_PIXMAP },
- { "fg", TOKEN_FG },
- { "font", TOKEN_FONT },
- { "fontset", TOKEN_FONTSET },
- { "INSENSITIVE", TOKEN_INSENSITIVE },
- { "NORMAL", TOKEN_NORMAL },
- { "pixmap_path", TOKEN_PIXMAP_PATH },
- { "PRELIGHT", TOKEN_PRELIGHT },
- { "SELECTED", TOKEN_SELECTED },
- { "style", TOKEN_STYLE },
- { "text", TOKEN_TEXT },
- { "widget", TOKEN_WIDGET },
- { "widget_class", TOKEN_WIDGET_CLASS },
+ { "include", GTK_RC_TOKEN_INCLUDE },
+ { "NORMAL", GTK_RC_TOKEN_NORMAL },
+ { "ACTIVE", GTK_RC_TOKEN_ACTIVE },
+ { "PRELIGHT", GTK_RC_TOKEN_PRELIGHT },
+ { "SELECTED", GTK_RC_TOKEN_SELECTED },
+ { "INSENSITIVE", GTK_RC_TOKEN_INSENSITIVE },
+ { "fg", GTK_RC_TOKEN_FG },
+ { "bg", GTK_RC_TOKEN_BG },
+ { "text", GTK_RC_TOKEN_TEXT },
+ { "base", GTK_RC_TOKEN_BASE },
+ { "xthickness", GTK_RC_TOKEN_XTHICKNESS },
+ { "ythickness", GTK_RC_TOKEN_YTHICKNESS },
+ { "font", GTK_RC_TOKEN_FONT },
+ { "fontset", GTK_RC_TOKEN_FONTSET },
+ { "font_name", GTK_RC_TOKEN_FONT_NAME },
+ { "bg_pixmap", GTK_RC_TOKEN_BG_PIXMAP },
+ { "pixmap_path", GTK_RC_TOKEN_PIXMAP_PATH },
+ { "style", GTK_RC_TOKEN_STYLE },
+ { "binding", GTK_RC_TOKEN_BINDING },
+ { "bind", GTK_RC_TOKEN_BIND },
+ { "widget", GTK_RC_TOKEN_WIDGET },
+ { "widget_class", GTK_RC_TOKEN_WIDGET_CLASS },
+ { "class", GTK_RC_TOKEN_CLASS },
+ { "lowest", GTK_RC_TOKEN_LOWEST },
+ { "gtk", GTK_RC_TOKEN_GTK },
+ { "application", GTK_RC_TOKEN_APPLICATION },
+ { "rc", GTK_RC_TOKEN_RC },
+ { "highest", GTK_RC_TOKEN_HIGHEST },
+ { "engine", GTK_RC_TOKEN_ENGINE },
+ { "module_path", GTK_RC_TOKEN_MODULE_PATH },
};
-static guint nsymbols = sizeof (symbols) / sizeof (symbols[0]);
+
+static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
static GHashTable *rc_style_ht = NULL;
+static GHashTable *realized_style_ht = NULL;
static GSList *gtk_rc_sets_widget = NULL;
static GSList *gtk_rc_sets_widget_class = NULL;
+static GSList *gtk_rc_sets_class = NULL;
+
+#define GTK_RC_MAX_DEFAULT_FILES 128
+static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];
+static gboolean gtk_rc_auto_parse = TRUE;
#define GTK_RC_MAX_PIXMAP_PATHS 128
static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];
+#define GTK_RC_MAX_MODULE_PATHS 128
+static gchar *module_path[GTK_RC_MAX_MODULE_PATHS];
+
+/* A stack of directories for RC files we are parsing currently.
+ * these are implicitely added to the end of PIXMAP_PATHS
+ */
+GSList *rc_dir_stack = NULL;
/* The files we have parsed, to reread later if necessary */
GSList *rc_files = NULL;
static GtkImageLoader image_loader = NULL;
+/* RC file handling */
+
+
+#ifdef G_OS_WIN32
+
+gchar *
+gtk_win32_get_installation_directory (void)
+{
+ static gboolean been_here = FALSE;
+ static gchar gtk_installation_dir[200];
+ gchar win_dir[100];
+ HKEY reg_key = NULL;
+ DWORD type;
+ DWORD nbytes = sizeof (gtk_installation_dir);
+
+ if (been_here)
+ return gtk_installation_dir;
+
+ been_here = TRUE;
+
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\GNU\\GTk+", 0,
+ KEY_QUERY_VALUE, ®_key) != ERROR_SUCCESS
+ || RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+ &type, gtk_installation_dir, &nbytes) != ERROR_SUCCESS
+ || type != REG_SZ)
+ {
+ /* Uh oh. Use the old hard-coded %WinDir%\GTk+ value */
+ GetWindowsDirectory (win_dir, sizeof (win_dir));
+ sprintf (gtk_installation_dir, "%s\\gtk+", win_dir);
+ }
+
+ if (reg_key != NULL)
+ RegCloseKey (reg_key);
+
+ return gtk_installation_dir;
+}
+
+static gchar *
+get_themes_directory (void)
+{
+ static gchar themes_dir[200];
+
+ sprintf (themes_dir, "%s\\themes", gtk_win32_get_installation_directory ());
+ return themes_dir;
+}
+
+#endif
+
+gchar *
+gtk_rc_get_theme_dir(void)
+{
+ gchar *var, *path;
+
+#ifndef G_OS_WIN32
+ var = getenv("GTK_DATA_PREFIX");
+ if (var)
+ path = g_strdup_printf("%s%s", var, "/share/themes");
+ else
+ path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
+#else
+ path = g_strdup (get_themes_directory ());
+#endif
+
+ return path;
+}
+
+gchar *
+gtk_rc_get_module_dir(void)
+{
+ gchar *var, *path;
+
+#ifndef G_OS_WIN32
+ var = getenv("GTK_EXE_PREFIX");
+ if (var)
+ path = g_strdup_printf("%s%s", var, "/lib/gtk-2.0/" GTK_VERSION "/engines");
+ else
+ path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk-2.0/" GTK_VERSION "/engines");
+#else
+ path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
+#endif
+
+ return path;
+}
+
+static void
+gtk_rc_append_default_module_path(void)
+{
+ gchar *var, *path;
+ gint n;
+
+ for (n = 0; module_path[n]; n++) ;
+ if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
+ return;
+
+#ifndef G_OS_WIN32
+ var = getenv("GTK_EXE_PREFIX");
+ if (var)
+ path = g_strdup_printf("%s%s", var, "/lib/gtk-2.0/" GTK_VERSION "/engines");
+ else
+ path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk-2.0/" GTK_VERSION "/engines");
+#else
+ path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
+#endif
+ module_path[n++] = path;
+
+ var = g_get_home_dir ();
+ if (var)
+ {
+#ifndef G_OS_WIN32
+ path = g_strdup_printf ("%s%s", var, "/.gtk-2.0/" GTK_VERSION "/engines");
+#else
+ path = g_strdup_printf ("%s%s", var, "\\_gtk\\themes\\engines");
+#endif
+ module_path[n++] = path;
+ }
+ module_path[n] = NULL;
+}
+
+static void
+gtk_rc_add_initial_default_files (void)
+{
+ static gint init = FALSE;
+ gchar *var, *str;
+ gchar **files;
+ gint i;
+
+ if (init)
+ return;
+
+ gtk_rc_default_files[0] = NULL;
+ init = TRUE;
+
+ var = g_getenv("GTK_RC_FILES");
+ if (var)
+ {
+ files = g_strsplit (var, G_SEARCHPATH_SEPARATOR_S, 128);
+ i=0;
+ while (files[i])
+ {
+ gtk_rc_add_default_file (files[i]);
+ i++;
+ }
+ g_strfreev (files);
+ }
+ else
+ {
+#ifndef G_OS_WIN32
+ str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk-2.0" G_DIR_SEPARATOR_S "gtkrc");
+#else
+ str = g_strdup_printf ("%s\\gtkrc", gtk_win32_get_installation_directory ());
+#endif
+
+ gtk_rc_add_default_file (str);
+ g_free (str);
+
+ var = g_get_home_dir ();
+ if (var)
+ {
+ str = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".gtkrc-2.0", var);
+ gtk_rc_add_default_file (str);
+ g_free (str);
+ }
+ }
+}
+
+void
+gtk_rc_add_default_file (const gchar *file)
+{
+ guint n;
+
+ gtk_rc_add_initial_default_files ();
+
+ for (n = 0; gtk_rc_default_files[n]; n++) ;
+ if (n >= GTK_RC_MAX_DEFAULT_FILES - 1)
+ return;
+
+ gtk_rc_default_files[n++] = g_strdup (file);
+ gtk_rc_default_files[n] = NULL;
+}
+
+void
+gtk_rc_set_default_files (gchar **files)
+{
+ gint i;
+
+ gtk_rc_add_initial_default_files ();
+
+ i = 0;
+ while (gtk_rc_default_files[i])
+ {
+ g_free (gtk_rc_default_files[i]);
+ i++;
+ }
+
+ gtk_rc_default_files[0] = NULL;
+ gtk_rc_auto_parse = FALSE;
+
+ i = 0;
+ while (files[i] != NULL)
+ {
+ gtk_rc_add_default_file (files[i]);
+ i++;
+ }
+}
+
+gchar **
+gtk_rc_get_default_files (void)
+{
+ gtk_rc_add_initial_default_files ();
+
+ return gtk_rc_default_files;
+}
+
+ /* The following routine is based on _nl_normalize_codeset from
+ * the GNU C library. Contributed by
+ *
+ * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ *
+ * Normalize codeset name. There is no standard for the codeset
+ * names. Normalization allows the user to use any of the common
+ * names.
+ */
+ static char *
+ _gtk_normalize_codeset (const char *codeset, int name_len)
+ {
+ int len = 0;
+ int only_digit = 1;
+ char *retval;
+ char *wp;
+ int cnt;
+
+ for (cnt = 0; cnt < name_len; ++cnt)
+ if (isalnum (codeset[cnt]))
+ {
+ ++len;
+
+ if (isalpha (codeset[cnt]))
+ only_digit = 0;
+ }
+
+ retval = g_malloc ((only_digit ? 3 : 0) + len + 1);
+
+ if (only_digit)
+ {
+ strcpy (retval, "iso");
+ wp = retval + 3;
+ }
+ else
+ wp = retval;
+
+ for (cnt = 0; cnt < name_len; ++cnt)
+ if (isalpha (codeset[cnt]))
+ *wp++ = isupper(codeset[cnt]) ? tolower (codeset[cnt]) : codeset[cnt];
+ else if (isdigit (codeset[cnt]))
+ *wp++ = codeset[cnt];
+
+ *wp = '\0';
+
+ return retval;
+ }
+
void
gtk_rc_init (void)
{
- rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
- (GCompareFunc) gtk_rc_style_compare);
+ static gchar *locale_suffixes[3];
+ static gint n_locale_suffixes = 0;
+
+ gint i, j;
+
+ static gboolean initted = FALSE;
+
+ if (!initted)
+ {
+ gint length;
+ gchar *locale;
+ gchar *p;
+
+#ifdef G_OS_WIN32
+ locale = g_win32_getlocale ();
+#else
+ locale = setlocale (LC_CTYPE, NULL);
+#endif
+
+ initted = TRUE;
+
+ pixmap_path[0] = NULL;
+ module_path[0] = NULL;
+ gtk_rc_append_default_module_path();
+
+ gtk_rc_add_initial_default_files ();
+
+ if (strcmp (locale, "C") && strcmp (locale, "POSIX"))
+ {
+ /* Determine locale-specific suffixes for RC files
+ *
+ * We normalize the charset into a standard form,
+ * which has all '-' and '_' characters removed,
+ * and is lowercase.
+ */
+ gchar *normalized_locale;
+
+ p = strchr (locale, '@');
+ length = p ? (p -locale) : strlen (locale);
+
+ p = strchr (locale, '.');
+ if (p)
+ {
+ gchar *tmp1 = g_strndup (locale, p - locale + 1);
+ gchar *tmp2 = _gtk_normalize_codeset (p + 1, length - (p - locale + 1));
+
+ normalized_locale = g_strconcat (tmp1, tmp2, NULL);
+ g_free (tmp1);
+ g_free (tmp2);
+
+ locale_suffixes[n_locale_suffixes++] = g_strdup (normalized_locale);
+ length = p - locale;
+ }
+ else
+ normalized_locale = g_strndup (locale, length);
+
+ p = strchr (normalized_locale, '_');
+ if (p)
+ {
+ locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
+ length = p - normalized_locale;
+ }
+
+ locale_suffixes[n_locale_suffixes++] = g_strndup (normalized_locale, length);
+
+ g_free (normalized_locale);
+ }
+ }
+
+ i = 0;
+ while (gtk_rc_default_files[i] != NULL)
+ {
+ /* Try to find a locale specific RC file corresponding to
+ * to parse before the default file.
+ */
+ for (j=n_locale_suffixes-1; j>=0; j--)
+ {
+ gchar *name = g_strconcat (gtk_rc_default_files[i],
+ ".",
+ locale_suffixes[j],
+ NULL);
+ gtk_rc_parse (name);
+ g_free (name);
+ }
+
+ gtk_rc_parse (gtk_rc_default_files[i]);
+ i++;
+ }
}
void
{
/* Get the absolute pathname */
- if (rc_file->name[0] == '/')
+ if (g_path_is_absolute (rc_file->name))
rc_file->canonical_name = rc_file->name;
else
{
GString *str;
- gchar buffer[MAXPATHLEN];
-
-#if defined(sun) && !defined(__SVR4)
- if(!getwd(buffer))
-#else
- if(!getcwd(buffer, MAXPATHLEN))
-#endif
- return;
+ gchar *cwd;
- str = g_string_new (buffer);
- g_string_append_c (str, '/');
+ cwd = g_get_current_dir ();
+
+ str = g_string_new (cwd);
+ g_free (cwd);
+ g_string_append_c (str, G_DIR_SEPARATOR);
g_string_append (str, rc_file->name);
rc_file->canonical_name = str->str;
if (!lstat (rc_file->canonical_name, &statbuf))
{
gint fd;
+ GSList *tmp_list;
rc_file->mtime = statbuf.st_mtime;
if (fd < 0)
return;
+ /* Temporarily push directory name for this file on
+ * a stack of directory names while parsing it
+ */
+ rc_dir_stack = g_slist_prepend (rc_dir_stack,
+ g_dirname (rc_file->canonical_name));
gtk_rc_parse_any (filename, fd, NULL);
+
+ tmp_list = rc_dir_stack;
+ rc_dir_stack = rc_dir_stack->next;
+
+ g_free (tmp_list->data);
+ g_slist_free_1 (tmp_list);
close (fd);
}
gtk_rc_parse_file (filename, TRUE);
}
+/* Handling of RC styles */
+
+GType
+gtk_rc_style_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (GtkRcStyleClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) gtk_rc_style_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GtkRcStyle),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gtk_rc_style_init,
+ };
+
+ object_type = g_type_register_static (G_TYPE_OBJECT,
+ "GtkRcStyle",
+ &object_info);
+ }
+
+ return object_type;
+}
+
static void
-gtk_rc_clear_hash_node (gpointer key,
- gpointer data,
- gpointer user_data)
+gtk_rc_style_init (GtkRcStyle *style)
{
- int i;
- GtkRcStyle *rc_style = data;
- GList *tmp_list;
+ guint i;
- g_free (rc_style->name);
- g_free (rc_style->font_name);
- g_free (rc_style->fontset_name);
+ style->name = NULL;
+ 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;
+ style->rc_style_lists = NULL;
+}
+
+static void
+gtk_rc_style_class_init (GtkRcStyleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
- for (i=0 ; i<5 ; i++)
- g_free (rc_style->bg_pixmap_name[i]);
+ object_class->finalize = gtk_rc_style_finalize;
- gtk_style_unref (rc_style->proto_style);
+ klass->parse = NULL;
+ klass->clone = gtk_rc_style_real_clone;
+ klass->merge = gtk_rc_style_real_merge;
+ klass->create_style = gtk_rc_style_real_create_style;
+}
- tmp_list = rc_style->styles;
- while (tmp_list)
+/* Like g_slist_remove, but remove all copies of data */
+static GSList*
+gtk_rc_slist_remove_all (GSList *list,
+ gpointer data)
+{
+ GSList *tmp;
+ GSList *prev;
+
+ prev = NULL;
+ tmp = list;
+
+ while (tmp)
{
- GtkRcNode *node = tmp_list->data;
+ if (tmp->data == data)
+ {
+ if (list == tmp)
+ list = list->next;
- gdk_colormap_unref (node->cmap);
- gtk_style_unref (node->style);
+ if (prev)
+ prev->next = tmp->next;
- g_free (node);
- tmp_list = tmp_list->next;
+ g_slist_free_1 (tmp);
+
+ if (prev)
+ tmp = prev->next;
+ else
+ tmp = list;
+ }
+ else
+ {
+ prev = tmp;
+ tmp = tmp->next;
+ }
}
- g_free (rc_style);
+ return list;
}
static void
-gtk_rc_clear_styles (void)
+gtk_rc_style_finalize (GObject *object)
{
- GSList *tmp_list;
+ gint i;
+ GSList *tmp_list1, *tmp_list2;
+ GtkRcStyle *rc_style;
- /* Clear out all old rc_styles */
+ rc_style = GTK_RC_STYLE (object);
+
+ if (rc_style->name)
+ g_free (rc_style->name);
+ if (rc_style->font_desc)
+ pango_font_description_free (rc_style->font_desc);
+
+ for (i=0 ; i < 5 ; i++)
+ if (rc_style->bg_pixmap_name[i])
+ g_free (rc_style->bg_pixmap_name[i]);
+
+ /* 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);
+ gtk_style_unref (style);
- g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
- g_hash_table_destroy (rc_style_ht);
- rc_style_ht = NULL;
+ /* Remove the list of styles from the other rc_styles
+ * in the list
+ */
+ tmp_list2 = rc_styles;
+ while (tmp_list2)
+ {
+ GtkRcStyle *other_style = tmp_list2->data;
+
+ if (other_style != rc_style)
+ other_style->rc_style_lists =
+ gtk_rc_slist_remove_all (other_style->rc_style_lists, rc_styles);
+
+ tmp_list2 = tmp_list2->next;
+ }
+
+ /* And from the hash table itself
+ */
+ g_hash_table_remove (realized_style_ht, rc_styles);
+ g_slist_free (rc_styles);
- tmp_list = gtk_rc_sets_widget;
- while (tmp_list)
- {
- GtkRcSet *rc_set;
+ tmp_list1 = tmp_list1->next;
+ }
+ g_slist_free (rc_style->rc_style_lists);
- rc_set = tmp_list->data;
- gtk_pattern_spec_free_segs (&rc_set->pspec);
- g_free (rc_set);
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+GtkRcStyle *
+gtk_rc_style_new (void)
+{
+ GtkRcStyle *style;
+
+ style = g_object_new (GTK_TYPE_RC_STYLE, NULL);
+
+ return style;
+}
+
+void
+gtk_rc_style_ref (GtkRcStyle *rc_style)
+{
+ g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
+
+ g_object_ref (G_OBJECT (rc_style));
+}
+
+void
+gtk_rc_style_unref (GtkRcStyle *rc_style)
+{
+ g_return_if_fail (GTK_IS_RC_STYLE (rc_style));
+
+ g_object_unref (G_OBJECT (rc_style));
+}
+
+static GtkRcStyle *
+gtk_rc_style_real_clone (GtkRcStyle *style)
+{
+ return GTK_RC_STYLE (g_object_new (G_OBJECT_TYPE (style), NULL));
+}
+
+static void
+gtk_rc_style_real_merge (GtkRcStyle *dest,
+ GtkRcStyle *src)
+{
+ gint i;
+
+ 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]);
- tmp_list = tmp_list->next;
+ 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;
+ }
}
- g_slist_free (gtk_rc_sets_widget);
- gtk_rc_sets_widget = NULL;
- tmp_list = gtk_rc_sets_widget_class;
- while (tmp_list)
+ if (dest->xthickness < 0 && src->xthickness >= 0)
+ dest->xthickness = src->xthickness;
+ if (dest->ythickness < 0 && src->ythickness >= 0)
+ dest->ythickness = src->ythickness;
+
+ if (!dest->font_desc && src->font_desc)
+ dest->font_desc = pango_font_description_copy (src->font_desc);
+}
+
+static GtkStyle *
+gtk_rc_style_real_create_style (GtkRcStyle *rc_style)
+{
+ return gtk_style_new ();
+}
+
+static void
+gtk_rc_clear_hash_node (gpointer key,
+ gpointer data,
+ gpointer user_data)
+{
+ gtk_rc_style_unref (data);
+}
+
+static void
+gtk_rc_free_rc_sets (GSList *slist)
+{
+ while (slist)
{
GtkRcSet *rc_set;
- rc_set = tmp_list->data;
+ rc_set = slist->data;
gtk_pattern_spec_free_segs (&rc_set->pspec);
g_free (rc_set);
-
- tmp_list = tmp_list->next;
+
+ slist = slist->next;
}
+}
+
+static void
+gtk_rc_clear_styles (void)
+{
+ /* Clear out all old rc_styles */
+
+ if (rc_style_ht)
+ {
+ g_hash_table_foreach (rc_style_ht, gtk_rc_clear_hash_node, NULL);
+ g_hash_table_destroy (rc_style_ht);
+ rc_style_ht = NULL;
+ }
+
+ gtk_rc_free_rc_sets (gtk_rc_sets_widget);
+ g_slist_free (gtk_rc_sets_widget);
+ gtk_rc_sets_widget = NULL;
+
+ gtk_rc_free_rc_sets (gtk_rc_sets_widget_class);
g_slist_free (gtk_rc_sets_widget_class);
gtk_rc_sets_widget_class = NULL;
- gtk_rc_init ();
+ gtk_rc_free_rc_sets (gtk_rc_sets_class);
+ g_slist_free (gtk_rc_sets_class);
+ gtk_rc_sets_class = NULL;
}
gboolean
return mtime_modified;
}
+static GSList *
+gtk_rc_styles_match (GSList *rc_styles,
+ GSList *sets,
+ guint path_length,
+ gchar *path,
+ gchar *path_reversed)
+
+{
+ GtkRcSet *rc_set;
+
+ while (sets)
+ {
+ rc_set = sets->data;
+ sets = sets->next;
+
+ if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
+ rc_styles = g_slist_append (rc_styles, rc_set->rc_style);
+ }
+
+ return rc_styles;
+}
+
GtkStyle*
gtk_rc_get_style (GtkWidget *widget)
{
- GtkRcStyle *rc_style;
+ GtkRcStyle *widget_rc_style;
+ GSList *rc_styles = NULL;
+
+ static guint rc_style_key_id = 0;
+
+ /* We allow the specification of a single rc style to be bound
+ * tightly to a widget, for application modifications
+ */
+ if (!rc_style_key_id)
+ rc_style_key_id = g_quark_from_static_string ("gtk-rc-style");
+
+ widget_rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
+ rc_style_key_id);
+
+ if (widget_rc_style)
+ rc_styles = g_slist_prepend (rc_styles, widget_rc_style);
if (gtk_rc_sets_widget)
{
guint path_length;
gtk_widget_path (widget, &path_length, &path, &path_reversed);
- rc_style = gtk_rc_styles_match (gtk_rc_sets_widget, path_length, path, path_reversed);
+ rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget, path_length, path, path_reversed);
g_free (path);
g_free (path_reversed);
- if (rc_style)
- return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
}
if (gtk_rc_sets_widget_class)
guint path_length;
gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
- rc_style = gtk_rc_styles_match (gtk_rc_sets_widget_class, path_length, path, path_reversed);
+ rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_widget_class, path_length, path, path_reversed);
g_free (path);
g_free (path_reversed);
+ }
+
+ if (gtk_rc_sets_class)
+ {
+ GtkType type;
+
+ type = GTK_OBJECT_TYPE (widget);
+ while (type)
+ {
+ gchar *path, *path_reversed;
+ guint path_length;
+
+ path = gtk_type_name (type);
+ path_length = strlen (path);
+ path_reversed = g_strdup (path);
+ g_strreverse (path_reversed);
+
+ rc_styles = gtk_rc_styles_match (rc_styles, gtk_rc_sets_class, path_length, path, path_reversed);
+ g_free (path_reversed);
- if (rc_style)
- return gtk_rc_style_init (rc_style, gtk_widget_get_colormap (widget));
+ type = gtk_type_parent (type);
+ }
}
+ if (rc_styles)
+ return gtk_rc_init_style (rc_styles);
+
return NULL;
}
-void
-gtk_rc_add_widget_name_style (GtkStyle *style,
- const char *pattern)
+static GSList*
+gtk_rc_add_rc_sets (GSList *slist,
+ GtkRcStyle *rc_style,
+ const char *pattern)
{
- GtkRcStyle *rc_style;
+ GtkRcStyle *new_style;
GtkRcSet *rc_set;
- int i;
-
- gtk_style_ref (style);
+ guint i;
- rc_style = g_new (GtkRcStyle, 1);
- rc_style->name = NULL;
- rc_style->font_name = NULL;
- rc_style->fontset_name = NULL;
+ new_style = gtk_rc_style_new ();
+ *new_style = *rc_style;
+ new_style->name = g_strdup (rc_style->name);
+ if (rc_style->font_desc)
+ new_style->font_desc = pango_font_description_copy (rc_style->font_desc);
for (i = 0; i < 5; i++)
- rc_style->bg_pixmap_name[i] = NULL;
+ new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
- rc_style->styles = g_list_append (NULL, style);
-
rc_set = g_new (GtkRcSet, 1);
gtk_pattern_spec_init (&rc_set->pspec, pattern);
rc_set->rc_style = rc_style;
- gtk_rc_sets_widget = g_slist_append (gtk_rc_sets_widget, rc_set);
+ return g_slist_prepend (slist, rc_set);
}
void
-gtk_rc_add_widget_class_style (GtkStyle *style,
- const char *pattern)
+gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
+ const gchar *pattern)
{
- GtkRcStyle *rc_style;
- GtkRcSet *rc_set;
- int i;
-
- gtk_style_ref (style);
-
- rc_style = g_new (GtkRcStyle, 1);
- rc_style->name = NULL;
- rc_style->font_name = NULL;
- rc_style->fontset_name = NULL;
-
- for (i = 0; i < 5; i++)
- rc_style->bg_pixmap_name[i] = NULL;
-
- rc_style->styles = g_list_append (NULL, style);
-
- rc_set = g_new (GtkRcSet, 1);
- gtk_pattern_spec_init (&rc_set->pspec, pattern);
- rc_set->rc_style = rc_style;
-
- gtk_rc_sets_widget_class = g_slist_append (gtk_rc_sets_widget_class, rc_set);
+ g_return_if_fail (rc_style != NULL);
+ g_return_if_fail (pattern != NULL);
+
+ gtk_rc_sets_widget = gtk_rc_add_rc_sets (gtk_rc_sets_widget, rc_style, pattern);
+}
+
+void
+gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
+ const gchar *pattern)
+{
+ g_return_if_fail (rc_style != NULL);
+ g_return_if_fail (pattern != NULL);
+
+ gtk_rc_sets_widget_class = gtk_rc_add_rc_sets (gtk_rc_sets_widget_class, rc_style, pattern);
+}
+
+void
+gtk_rc_add_class_style (GtkRcStyle *rc_style,
+ const gchar *pattern)
+{
+ g_return_if_fail (rc_style != NULL);
+ g_return_if_fail (pattern != NULL);
+
+ gtk_rc_sets_class = gtk_rc_add_rc_sets (gtk_rc_sets_class, rc_style, pattern);
}
static void
guint i;
gboolean done;
- scanner = g_scanner_new (>k_rc_scanner_config);
+ scanner = g_scanner_new ((GScannerConfig *) >k_rc_scanner_config);
if (input_fd >= 0)
{
g_scanner_input_text (scanner, input_string, strlen (input_string));
}
scanner->input_name = input_name;
-
+
g_scanner_freeze_symbol_table (scanner);
- for (i = 0; i < nsymbols; i++)
+ for (i = 0; i < n_symbols; i++)
g_scanner_add_symbol (scanner, symbols[i].name, GINT_TO_POINTER (symbols[i].token));
g_scanner_thaw_symbol_table (scanner);
gchar *msg;
msg = NULL;
- if (expected_token > TOKEN_INVALID &&
- expected_token < TOKEN_LAST)
- {
- for (i = 0; i < nsymbols; i++)
- if (symbols[i].token == expected_token)
- msg = symbols[i].name;
- if (msg)
- msg = g_strconcat ("e.g. `", msg, "'", NULL);
- }
- if (scanner->token > TOKEN_INVALID &&
- scanner->token < TOKEN_LAST)
+ symbol_name = NULL;
+ if (scanner->scope_id == 0)
{
- symbol_name = "???";
- for (i = 0; i < nsymbols; i++)
- if (symbols[i].token == scanner->token)
- symbol_name = symbols[i].name;
+ /* if we are in scope 0, we know the symbol names
+ * that are associated with certaintoken values.
+ * so we look them up to make the error messages
+ * more readable.
+ */
+ if (expected_token > GTK_RC_TOKEN_INVALID &&
+ expected_token < GTK_RC_TOKEN_LAST)
+ {
+ for (i = 0; i < n_symbols; i++)
+ if (symbols[i].token == expected_token)
+ msg = symbols[i].name;
+ if (msg)
+ msg = g_strconcat ("e.g. `", msg, "'", NULL);
+ }
+ if (scanner->token > GTK_RC_TOKEN_INVALID &&
+ scanner->token < GTK_RC_TOKEN_LAST)
+ {
+ symbol_name = "???";
+ for (i = 0; i < n_symbols; i++)
+ if (symbols[i].token == scanner->token)
+ symbol_name = symbols[i].name;
+ }
}
- else
- symbol_name = NULL;
g_scanner_unexp_token (scanner,
expected_token,
NULL,
g_scanner_destroy (scanner);
}
+static guint
+gtk_rc_styles_hash (const GSList *rc_styles)
+{
+ guint result;
+
+ result = 0;
+ while (rc_styles)
+ {
+ result += (result << 9) + GPOINTER_TO_UINT (rc_styles->data);
+ rc_styles = rc_styles->next;
+ }
+
+ return result;
+}
+
+static gint
+gtk_rc_styles_compare (const GSList *a,
+ const GSList *b)
+{
+ while (a && b)
+ {
+ if (a->data != b->data)
+ return FALSE;
+ a = a->next;
+ b = b->next;
+ }
+
+ return (a == b);
+}
+
static guint
gtk_rc_style_hash (const char *name)
{
static GtkRcStyle*
gtk_rc_style_find (const char *name)
{
- GtkRcStyle *rc_style;
-
- rc_style = g_hash_table_lookup (rc_style_ht, (gpointer) name);
-
- return rc_style;
+ if (rc_style_ht)
+ return g_hash_table_lookup (rc_style_ht, (gpointer) name);
+ else
+ return NULL;
}
-static GtkRcStyle*
-gtk_rc_styles_match (GSList *sets,
- guint path_length,
- gchar *path,
- gchar *path_reversed)
+static GtkStyle *
+gtk_rc_style_to_style (GtkRcStyle *rc_style)
{
- GtkRcSet *rc_set;
+ GtkStyle *style;
- while (sets)
- {
- rc_set = sets->data;
- sets = sets->next;
+ style = GTK_RC_STYLE_GET_CLASS (rc_style)->create_style (rc_style);
- if (gtk_pattern_match (&rc_set->pspec, path_length, path, path_reversed))
- return rc_set->rc_style;
- }
+ style->rc_style = rc_style;
+ gtk_rc_style_ref (rc_style);
- return NULL;
+ GTK_STYLE_GET_CLASS (style)->init_from_rc (style, rc_style);
+
+ return style;
}
+/* Reuses or frees rc_styles */
static GtkStyle *
-gtk_rc_style_init (GtkRcStyle *rc_style, GdkColormap *cmap)
+gtk_rc_init_style (GSList *rc_styles)
{
- GdkFont *old_font;
- gboolean match_cmap = FALSE;
- gint i;
-
- GList *tmp_list;
GtkStyle *style = NULL;
- GtkRcNode *node;
-
- tmp_list = rc_style->styles;
+ gint i;
- for (i=0; i<5; i++)
- if (rc_style->bg_pixmap_name[i])
- match_cmap = TRUE;
-
- while (tmp_list)
- {
- node = (GtkRcNode *)tmp_list->data;
+ g_return_val_if_fail (rc_styles != NULL, NULL);
+
+ if (!realized_style_ht)
+ realized_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_styles_hash,
+ (GCompareFunc) gtk_rc_styles_compare);
- if (!match_cmap || (node->cmap == cmap))
- {
- style = node->style;
- break;
- }
+ style = g_hash_table_lookup (realized_style_ht, rc_styles);
- tmp_list = tmp_list->next;
- }
-
if (!style)
{
- node = g_new (GtkRcNode, 1);
- style = gtk_style_copy (rc_style->proto_style);
-
- /* FIXME, this leaks colormaps, but if we don't do this, then we'll
- * be screwed, because we identify colormaps by address equality
+ GtkRcStyle *base_style = NULL;
+ GtkRcStyle *proto_style;
+ GtkRcStyleClass *proto_style_class;
+ GSList *tmp_styles;
+ GType rc_style_type = GTK_TYPE_RC_STYLE;
+
+ /* Find the first derived style in the list, and use that to
+ * create the merged style. If we only have raw GtkRcStyles, use
+ * the first style to create the merged style.
*/
- gdk_colormap_ref (cmap);
-
- node->style = style;
- node->cmap = cmap;
-
- if (rc_style->fontset_name)
+ base_style = rc_styles->data;
+ tmp_styles = rc_styles;
+ while (tmp_styles)
{
- old_font = style->font;
- style->font = gdk_fontset_load (rc_style->fontset_name);
- if (style->font)
- gdk_font_unref (old_font);
- else
- style->font = old_font;
+ GtkRcStyle *rc_style = tmp_styles->data;
+
+ if (G_OBJECT_TYPE (rc_style) != rc_style_type)
+ {
+ base_style = rc_style;
+ break;
+ }
+
+ tmp_styles = tmp_styles->next;
}
- else if (rc_style->font_name)
+
+ proto_style_class = GTK_RC_STYLE_GET_CLASS (base_style);
+ proto_style = proto_style_class->clone (base_style);
+
+ tmp_styles = rc_styles;
+ while (tmp_styles)
{
- old_font = style->font;
- style->font = gdk_font_load (rc_style->font_name);
- if (style->font)
- gdk_font_unref (old_font);
- else
- style->font = old_font;
+ GtkRcStyle *rc_style = tmp_styles->data;
+
+ proto_style_class->merge (proto_style, rc_style);
+
+ /* Point from each rc_style to the list of styles */
+ if (!g_slist_find (rc_style->rc_style_lists, rc_styles))
+ rc_style->rc_style_lists = g_slist_prepend (rc_style->rc_style_lists, rc_styles);
+
+ tmp_styles = tmp_styles->next;
}
-
+
for (i = 0; i < 5; i++)
- if (rc_style->bg_pixmap_name[i])
+ if (proto_style->bg_pixmap_name[i] &&
+ (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
{
- if (strcmp (rc_style->bg_pixmap_name[i], "<parent>") == 0)
- style->bg_pixmap[i] = (GdkPixmap*) GDK_PARENT_RELATIVE;
- else
- {
- if(image_loader)
- style->bg_pixmap[i] = image_loader(NULL, cmap, NULL,
- &style->bg[i],
- rc_style->bg_pixmap_name[i]);
- else
- style->bg_pixmap[i] =
- gdk_pixmap_colormap_create_from_xpm (NULL, cmap,
- NULL,
- &style->bg[i],
- rc_style->bg_pixmap_name[i]);
- }
+ g_free (proto_style->bg_pixmap_name[i]);
+ proto_style->bg_pixmap_name[i] = NULL;
}
- rc_style->styles = g_list_append (rc_style->styles, node);
+ style = gtk_rc_style_to_style (proto_style);
+ gtk_rc_style_unref (proto_style);
+
+ g_hash_table_insert (realized_style_ht, rc_styles, style);
}
+ else
+ g_slist_free (rc_styles);
return style;
}
+/*********************
+ * Parsing functions *
+ *********************/
+
static guint
gtk_rc_parse_statement (GScanner *scanner)
{
switch (token)
{
- case TOKEN_INCLUDE:
+ case GTK_RC_TOKEN_INCLUDE:
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_INCLUDE)
- return TOKEN_INCLUDE;
+ if (token != GTK_RC_TOKEN_INCLUDE)
+ return GTK_RC_TOKEN_INCLUDE;
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
gtk_rc_parse_file (scanner->value.v_string, FALSE);
return G_TOKEN_NONE;
- case TOKEN_STYLE:
+ case GTK_RC_TOKEN_STYLE:
return gtk_rc_parse_style (scanner);
- case TOKEN_PIXMAP_PATH:
+ case GTK_RC_TOKEN_BINDING:
+ return gtk_binding_parse_binding (scanner);
+
+ case GTK_RC_TOKEN_PIXMAP_PATH:
return gtk_rc_parse_pixmap_path (scanner);
- case TOKEN_WIDGET:
- return gtk_rc_parse_widget_style (scanner);
+ case GTK_RC_TOKEN_WIDGET:
+ return gtk_rc_parse_path_pattern (scanner);
- case TOKEN_WIDGET_CLASS:
- return gtk_rc_parse_widget_class_style (scanner);
+ case GTK_RC_TOKEN_WIDGET_CLASS:
+ return gtk_rc_parse_path_pattern (scanner);
+ case GTK_RC_TOKEN_CLASS:
+ return gtk_rc_parse_path_pattern (scanner);
+
+ case GTK_RC_TOKEN_MODULE_PATH:
+ return gtk_rc_parse_module_path (scanner);
+
default:
g_scanner_get_next_token (scanner);
- return /* G_TOKEN_SYMBOL */ TOKEN_STYLE;
+ return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
}
}
gint i;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_STYLE)
- return TOKEN_STYLE;
+ if (token != GTK_RC_TOKEN_STYLE)
+ return GTK_RC_TOKEN_STYLE;
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
insert = FALSE;
- rc_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
+ rc_style = gtk_rc_style_find (scanner->value.v_string);
if (!rc_style)
{
insert = TRUE;
- rc_style = g_new (GtkRcStyle, 1);
+ rc_style = gtk_rc_style_new ();
rc_style->name = g_strdup (scanner->value.v_string);
- rc_style->font_name = NULL;
- rc_style->fontset_name = NULL;
for (i = 0; i < 5; i++)
rc_style->bg_pixmap_name[i] = NULL;
- rc_style->proto_style = gtk_style_new();
- rc_style->styles = NULL;
+ for (i = 0; i < 5; i++)
+ rc_style->color_flags[i] = 0;
}
token = g_scanner_peek_next_token (scanner);
if (token != G_TOKEN_STRING)
{
if (insert)
- {
- gtk_style_unref (rc_style->proto_style);
- g_free (rc_style);
- }
+ g_free (rc_style);
+
return G_TOKEN_STRING;
}
- parent_style = g_hash_table_lookup (rc_style_ht, scanner->value.v_string);
+ parent_style = gtk_rc_style_find (scanner->value.v_string);
if (parent_style)
{
for (i = 0; i < 5; i++)
{
- rc_style->proto_style->fg[i] = parent_style->proto_style->fg[i];
- rc_style->proto_style->bg[i] = parent_style->proto_style->bg[i];
- rc_style->proto_style->light[i] = parent_style->proto_style->light[i];
- rc_style->proto_style->dark[i] = parent_style->proto_style->dark[i];
- rc_style->proto_style->mid[i] = parent_style->proto_style->mid[i];
- rc_style->proto_style->text[i] = parent_style->proto_style->text[i];
- rc_style->proto_style->base[i] = parent_style->proto_style->base[i];
+ rc_style->color_flags[i] = parent_style->color_flags[i];
+ rc_style->fg[i] = parent_style->fg[i];
+ rc_style->bg[i] = parent_style->bg[i];
+ rc_style->text[i] = parent_style->text[i];
+ rc_style->base[i] = parent_style->base[i];
}
+
+ rc_style->xthickness = parent_style->xthickness;
+ rc_style->ythickness = parent_style->ythickness;
- rc_style->proto_style->black = parent_style->proto_style->black;
- rc_style->proto_style->white = parent_style->proto_style->white;
-
- if (rc_style->fontset_name)
+ if (parent_style->font_desc)
{
- g_free (rc_style->fontset_name);
- rc_style->fontset_name = g_strdup (parent_style->fontset_name);
- }
- else if (rc_style->font_name)
- {
- g_free (rc_style->font_name);
- rc_style->font_name = g_strdup (parent_style->font_name);
+ if (rc_style->font_desc)
+ pango_font_description_free (rc_style->font_desc);
+ rc_style->font_desc = pango_font_description_copy (parent_style->font_desc);
}
for (i = 0; i < 5; i++)
if (token != G_TOKEN_LEFT_CURLY)
{
if (insert)
- {
- gtk_style_unref (rc_style->proto_style);
- g_free (rc_style);
- }
+ g_free (rc_style);
+
return G_TOKEN_LEFT_CURLY;
}
{
switch (token)
{
- case TOKEN_BASE:
- token = gtk_rc_parse_base (scanner, rc_style->proto_style);
+ case GTK_RC_TOKEN_BG:
+ token = gtk_rc_parse_bg (scanner, rc_style);
+ break;
+ case GTK_RC_TOKEN_FG:
+ token = gtk_rc_parse_fg (scanner, rc_style);
break;
- case TOKEN_BG:
- token = gtk_rc_parse_bg (scanner, rc_style->proto_style);
+ case GTK_RC_TOKEN_TEXT:
+ token = gtk_rc_parse_text (scanner, rc_style);
break;
- case TOKEN_FG:
- token = gtk_rc_parse_fg (scanner, rc_style->proto_style);
+ case GTK_RC_TOKEN_BASE:
+ token = gtk_rc_parse_base (scanner, rc_style);
break;
- case TOKEN_TEXT:
- token = gtk_rc_parse_text (scanner, rc_style->proto_style);
+ case GTK_RC_TOKEN_XTHICKNESS:
+ token = gtk_rc_parse_xthickness (scanner, rc_style);
break;
- case TOKEN_BG_PIXMAP:
+ case GTK_RC_TOKEN_YTHICKNESS:
+ token = gtk_rc_parse_ythickness (scanner, rc_style);
+ break;
+ case GTK_RC_TOKEN_BG_PIXMAP:
token = gtk_rc_parse_bg_pixmap (scanner, rc_style);
break;
- case TOKEN_FONT:
+ case GTK_RC_TOKEN_FONT:
token = gtk_rc_parse_font (scanner, rc_style);
break;
- case TOKEN_FONTSET:
+ case GTK_RC_TOKEN_FONTSET:
token = gtk_rc_parse_fontset (scanner, rc_style);
break;
+ case GTK_RC_TOKEN_FONT_NAME:
+ token = gtk_rc_parse_font_name (scanner, rc_style);
+ break;
+ case GTK_RC_TOKEN_ENGINE:
+ token = gtk_rc_parse_engine (scanner, &rc_style);
+ break;
default:
g_scanner_get_next_token (scanner);
token = G_TOKEN_RIGHT_CURLY;
{
if (insert)
{
- if (rc_style->fontset_name)
- g_free (rc_style->fontset_name);
- if (rc_style->font_name)
- g_free (rc_style->font_name);
+ if (rc_style->font_desc)
+ pango_font_description_free (rc_style->font_desc);
+
for (i = 0; i < 5; i++)
if (rc_style->bg_pixmap_name[i])
g_free (rc_style->bg_pixmap_name[i]);
- gtk_style_unref (rc_style->proto_style);
g_free (rc_style);
}
return token;
{
if (insert)
{
- if (rc_style->fontset_name)
- g_free (rc_style->fontset_name);
- if (rc_style->font_name)
- g_free (rc_style->font_name);
+ if (rc_style->font_desc)
+ pango_font_description_free (rc_style->font_desc);
for (i = 0; i < 5; i++)
if (rc_style->bg_pixmap_name[i])
g_free (rc_style->bg_pixmap_name[i]);
- gtk_style_unref (rc_style->proto_style);
g_free (rc_style);
}
return G_TOKEN_RIGHT_CURLY;
}
- if (insert)
- g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
-
+ if (insert)
+ {
+ if (!rc_style_ht)
+ rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
+ (GCompareFunc) gtk_rc_style_compare);
+
+ g_hash_table_insert (rc_style_ht, rc_style->name, rc_style);
+ }
+
return G_TOKEN_NONE;
}
static guint
-gtk_rc_parse_base (GScanner *scanner,
- GtkStyle *style)
+gtk_rc_parse_bg (GScanner *scanner,
+ GtkRcStyle *style)
{
GtkStateType state;
guint token;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_BASE)
- return TOKEN_BASE;
+ if (token != GTK_RC_TOKEN_BG)
+ return GTK_RC_TOKEN_BG;
token = gtk_rc_parse_state (scanner, &state);
if (token != G_TOKEN_NONE)
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
-
- return gtk_rc_parse_color (scanner, &style->base[state]);
+
+ style->color_flags[state] |= GTK_RC_BG;
+ return gtk_rc_parse_color (scanner, &style->bg[state]);
}
static guint
-gtk_rc_parse_bg (GScanner *scanner,
- GtkStyle *style)
+gtk_rc_parse_fg (GScanner *scanner,
+ GtkRcStyle *style)
{
GtkStateType state;
guint token;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_BG)
- return TOKEN_BG;
+ if (token != GTK_RC_TOKEN_FG)
+ return GTK_RC_TOKEN_FG;
token = gtk_rc_parse_state (scanner, &state);
if (token != G_TOKEN_NONE)
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
- return gtk_rc_parse_color (scanner, &style->bg[state]);
+ style->color_flags[state] |= GTK_RC_FG;
+ return gtk_rc_parse_color (scanner, &style->fg[state]);
}
static guint
-gtk_rc_parse_fg (GScanner *scanner,
- GtkStyle *style)
+gtk_rc_parse_text (GScanner *scanner,
+ GtkRcStyle *style)
{
GtkStateType state;
guint token;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_FG)
- return TOKEN_FG;
+ if (token != GTK_RC_TOKEN_TEXT)
+ return GTK_RC_TOKEN_TEXT;
token = gtk_rc_parse_state (scanner, &state);
if (token != G_TOKEN_NONE)
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
- return gtk_rc_parse_color (scanner, &style->fg[state]);
+ style->color_flags[state] |= GTK_RC_TEXT;
+ return gtk_rc_parse_color (scanner, &style->text[state]);
}
static guint
-gtk_rc_parse_text (GScanner *scanner,
- GtkStyle *style)
+gtk_rc_parse_base (GScanner *scanner,
+ GtkRcStyle *style)
{
GtkStateType state;
guint token;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_TEXT)
- return TOKEN_TEXT;
+ if (token != GTK_RC_TOKEN_BASE)
+ return GTK_RC_TOKEN_BASE;
token = gtk_rc_parse_state (scanner, &state);
if (token != G_TOKEN_NONE)
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
-
- return gtk_rc_parse_color (scanner, &style->text[state]);
+
+ style->color_flags[state] |= GTK_RC_BASE;
+ return gtk_rc_parse_color (scanner, &style->base[state]);
+}
+
+static guint
+gtk_rc_parse_xthickness (GScanner *scanner,
+ GtkRcStyle *style)
+{
+ if (g_scanner_get_next_token (scanner) != GTK_RC_TOKEN_XTHICKNESS)
+ return GTK_RC_TOKEN_XTHICKNESS;
+
+ if (g_scanner_get_next_token (scanner) != G_TOKEN_EQUAL_SIGN)
+ return G_TOKEN_EQUAL_SIGN;
+
+ if (g_scanner_get_next_token (scanner) != G_TOKEN_INT)
+ return G_TOKEN_INT;
+
+ style->xthickness = scanner->value.v_int;
+
+ return G_TOKEN_NONE;
+}
+
+static guint
+gtk_rc_parse_ythickness (GScanner *scanner,
+ GtkRcStyle *style)
+{
+ if (g_scanner_get_next_token (scanner) != GTK_RC_TOKEN_YTHICKNESS)
+ return GTK_RC_TOKEN_YTHICKNESS;
+
+ if (g_scanner_get_next_token (scanner) != G_TOKEN_EQUAL_SIGN)
+ return G_TOKEN_EQUAL_SIGN;
+
+ if (g_scanner_get_next_token (scanner) != G_TOKEN_INT)
+ return G_TOKEN_INT;
+
+ style->ythickness = scanner->value.v_int;
+
+ return G_TOKEN_NONE;
}
static guint
gchar *pixmap_file;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_BG_PIXMAP)
- return TOKEN_BG_PIXMAP;
+ if (token != GTK_RC_TOKEN_BG_PIXMAP)
+ return GTK_RC_TOKEN_BG_PIXMAP;
token = gtk_rc_parse_state (scanner, &state);
if (token != G_TOKEN_NONE)
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
- if (strcmp (scanner->value.v_string, "<parent>"))
- pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
- else
+ if ((strcmp (scanner->value.v_string, "<parent>") == 0) ||
+ (strcmp (scanner->value.v_string, "<none>") == 0))
pixmap_file = g_strdup (scanner->value.v_string);
+ else
+ pixmap_file = gtk_rc_find_pixmap_in_path (scanner, scanner->value.v_string);
if (pixmap_file)
{
}
static gchar*
+gtk_rc_check_pixmap_dir (const gchar *dir, const gchar *pixmap_file)
+{
+ gchar *buf;
+ gint fd;
+
+ buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s", dir, pixmap_file);
+
+ fd = open (buf, O_RDONLY);
+ if (fd >= 0)
+ {
+ close (fd);
+ return buf;
+ }
+
+ g_free (buf);
+
+ return NULL;
+ }
+
+gchar*
gtk_rc_find_pixmap_in_path (GScanner *scanner,
- gchar *pixmap_file)
+ const gchar *pixmap_file)
+{
+ gint i;
+ gchar *filename;
+ GSList *tmp_list;
+
+ for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
+ {
+ filename = gtk_rc_check_pixmap_dir (pixmap_path[i], pixmap_file);
+ if (filename)
+ return filename;
+ }
+
+ tmp_list = rc_dir_stack;
+ while (tmp_list)
+ {
+ filename = gtk_rc_check_pixmap_dir (tmp_list->data, pixmap_file);
+ if (filename)
+ return filename;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (scanner)
+ g_warning (_("Unable to locate image file in pixmap_path: \"%s\" line %d"),
+ pixmap_file, scanner->line);
+ else
+ g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
+ pixmap_file);
+
+ return NULL;
+}
+
+gchar*
+gtk_rc_find_module_in_path (const gchar *module_file)
{
gint i;
gint fd;
gchar *buf;
- for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_path[i] != NULL); i++)
+ for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
{
- buf = g_malloc (strlen (pixmap_path[i]) + strlen (pixmap_file) + 2);
- sprintf (buf, "%s%c%s", pixmap_path[i], '/', pixmap_file);
+ buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
+ module_path[i], module_file);
fd = open (buf, O_RDONLY);
if (fd >= 0)
g_free (buf);
}
-
- g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d",
- pixmap_file, scanner->line);
-
+
return NULL;
}
guint token;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_FONT)
- return TOKEN_FONT;
+ if (token != GTK_RC_TOKEN_FONT)
+ return GTK_RC_TOKEN_FONT;
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_EQUAL_SIGN)
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
-
- if (rc_style->font_name)
- g_free (rc_style->font_name);
- rc_style->font_name = g_strdup (scanner->value.v_string);
+
+ /* Ignore, do nothing */
return G_TOKEN_NONE;
}
guint token;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_FONTSET)
- return TOKEN_FONTSET;
+ if (token != GTK_RC_TOKEN_FONTSET)
+ return GTK_RC_TOKEN_FONTSET;
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_EQUAL_SIGN)
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
-
- if (rc_style->fontset_name)
- g_free (rc_style->fontset_name);
- rc_style->fontset_name = g_strdup (scanner->value.v_string);
+
+ /* Do nothing - silently ignore */
return G_TOKEN_NONE;
}
static guint
+gtk_rc_parse_font_name (GScanner *scanner,
+ GtkRcStyle *rc_style)
+{
+ guint token;
+
+ token = g_scanner_get_next_token (scanner);
+ if (token != GTK_RC_TOKEN_FONT_NAME)
+ return GTK_RC_TOKEN_FONT;
+
+ token = g_scanner_get_next_token (scanner);
+ if (token != G_TOKEN_EQUAL_SIGN)
+ return G_TOKEN_EQUAL_SIGN;
+
+ token = g_scanner_get_next_token (scanner);
+ if (token != G_TOKEN_STRING)
+ return G_TOKEN_STRING;
+
+ rc_style->font_desc = pango_font_description_from_string (scanner->value.v_string);
+
+ return G_TOKEN_NONE;
+}
+
+static guint
+gtk_rc_parse_engine (GScanner *scanner,
+ GtkRcStyle **rc_style)
+{
+ guint token;
+ GtkThemeEngine *engine;
+ guint result = G_TOKEN_NONE;
+ GtkRcStyle *new_style = NULL;
+ gboolean parsed_curlies = FALSE;
+
+ token = g_scanner_get_next_token (scanner);
+ if (token != GTK_RC_TOKEN_ENGINE)
+ return GTK_RC_TOKEN_ENGINE;
+
+ token = g_scanner_get_next_token (scanner);
+ if (token != G_TOKEN_STRING)
+ return G_TOKEN_STRING;
+
+ engine = gtk_theme_engine_get (scanner->value.v_string);
+
+ token = g_scanner_get_next_token (scanner);
+ if (token != G_TOKEN_LEFT_CURLY)
+ return G_TOKEN_LEFT_CURLY;
+
+ if (engine)
+ {
+ GtkRcStyleClass *new_class;
+
+ new_style = gtk_theme_engine_create_rc_style (engine);
+ gtk_theme_engine_unref (engine);
+
+ new_class = GTK_RC_STYLE_GET_CLASS (new_style);
+
+ new_class->merge (new_style, *rc_style);
+ if ((*rc_style)->name)
+ new_style->name = g_strdup ((*rc_style)->name);
+
+ if (new_class->parse)
+ {
+ parsed_curlies = TRUE;
+ result = new_class->parse (new_style, scanner);
+
+ if (result != G_TOKEN_NONE)
+ {
+ g_object_unref (G_OBJECT (new_style));
+ new_style = NULL;
+ }
+ }
+ }
+
+ if (!parsed_curlies)
+ {
+ /* Skip over remainder, looking for nested {}'s
+ */
+ guint count = 1;
+
+ result = G_TOKEN_RIGHT_CURLY;
+ while ((token = g_scanner_get_next_token (scanner)) != G_TOKEN_EOF)
+ {
+ if (token == G_TOKEN_LEFT_CURLY)
+ count++;
+ else if (token == G_TOKEN_RIGHT_CURLY)
+ count--;
+
+ if (count == 0)
+ {
+ result = G_TOKEN_NONE;
+ break;
+ }
+ }
+ }
+
+ if (new_style)
+ {
+ g_object_unref (G_OBJECT (*rc_style));
+ *rc_style = new_style;
+ }
+
+ return result;
+}
+
+guint
gtk_rc_parse_state (GScanner *scanner,
GtkStateType *state)
{
+ guint old_scope;
guint token;
+
+ 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)
token = g_scanner_get_next_token (scanner);
switch (token)
{
- case TOKEN_ACTIVE:
+ case GTK_RC_TOKEN_ACTIVE:
*state = GTK_STATE_ACTIVE;
break;
- case TOKEN_INSENSITIVE:
+ case GTK_RC_TOKEN_INSENSITIVE:
*state = GTK_STATE_INSENSITIVE;
break;
- case TOKEN_NORMAL:
+ case GTK_RC_TOKEN_NORMAL:
*state = GTK_STATE_NORMAL;
break;
- case TOKEN_PRELIGHT:
+ case GTK_RC_TOKEN_PRELIGHT:
*state = GTK_STATE_PRELIGHT;
break;
- case TOKEN_SELECTED:
+ case GTK_RC_TOKEN_SELECTED:
*state = GTK_STATE_SELECTED;
break;
default:
- return /* G_TOKEN_SYMBOL */ TOKEN_NORMAL;
+ return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_NORMAL;
}
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);
+
return G_TOKEN_NONE;
}
-static guint
+guint
+gtk_rc_parse_priority (GScanner *scanner,
+ GtkPathPriorityType *priority)
+{
+ guint old_scope;
+ guint token;
+
+ g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
+ g_return_val_if_fail (priority != 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 != ':')
+ return ':';
+
+ token = g_scanner_get_next_token (scanner);
+ switch (token)
+ {
+ 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_RC:
+ *priority = GTK_PATH_PRIO_RC;
+ break;
+ case GTK_RC_TOKEN_HIGHEST:
+ *priority = GTK_PATH_PRIO_HIGHEST;
+ break;
+ default:
+ return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_APPLICATION;
+ }
+
+ g_scanner_set_scope (scanner, old_scope);
+
+ return G_TOKEN_NONE;
+}
+
+guint
gtk_rc_parse_color (GScanner *scanner,
GdkColor *color)
{
guint token;
+
+ g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
+
+ /* we don't need to set our own scop here, because
+ * we don't need own symbols
+ */
token = g_scanner_get_next_token (scanner);
switch (token)
guint token;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_PIXMAP_PATH)
- return TOKEN_PIXMAP_PATH;
+ if (token != GTK_RC_TOKEN_PIXMAP_PATH)
+ return GTK_RC_TOKEN_PIXMAP_PATH;
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
for (end_offset = 0; end_offset <= path_len; end_offset++)
{
- if ((buf[end_offset] == ':') ||
+ if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
(end_offset == path_len))
{
buf[end_offset] = '\0';
}
static guint
-gtk_rc_parse_widget_style (GScanner *scanner)
+gtk_rc_parse_module_path (GScanner *scanner)
{
- GtkRcSet *rc_set;
guint token;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_WIDGET)
- return TOKEN_WIDGET;
+ if (token != GTK_RC_TOKEN_MODULE_PATH)
+ return GTK_RC_TOKEN_MODULE_PATH;
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
+
+ gtk_rc_parse_module_path_string (scanner->value.v_string);
+
+ return G_TOKEN_NONE;
+}
- rc_set = g_new (GtkRcSet, 1);
- gtk_pattern_spec_init (&rc_set->pspec, scanner->value.v_string);
+static void
+gtk_rc_parse_module_path_string (gchar *mod_path)
+{
+ gchar *buf;
+ gint end_offset;
+ gint start_offset = 0;
+ gint path_len;
+ gint path_num;
- token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_STYLE)
+ /* free the old one, or just add to the old one ? */
+ for (path_num=0; module_path[path_num]; path_num++)
{
- gtk_pattern_spec_free_segs (&rc_set->pspec);
- g_free (rc_set);
- return TOKEN_STYLE;
+ g_free (module_path[path_num]);
+ module_path[path_num] = NULL;
}
- token = g_scanner_get_next_token (scanner);
- if (token != G_TOKEN_STRING)
- {
- gtk_pattern_spec_free_segs (&rc_set->pspec);
- g_free (rc_set);
- return G_TOKEN_STRING;
- }
+ path_num = 0;
- rc_set->rc_style = gtk_rc_style_find (scanner->value.v_string);
- if (!rc_set->rc_style)
- {
- gtk_pattern_spec_free_segs (&rc_set->pspec);
- g_free (rc_set);
- return G_TOKEN_STRING;
- }
+ path_len = strlen (mod_path);
- gtk_rc_sets_widget = g_slist_append (gtk_rc_sets_widget, rc_set);
+ buf = g_strdup (mod_path);
- return G_TOKEN_NONE;
+ for (end_offset = 0; end_offset <= path_len; end_offset++)
+ {
+ if ((buf[end_offset] == G_SEARCHPATH_SEPARATOR) ||
+ (end_offset == path_len))
+ {
+ buf[end_offset] = '\0';
+ module_path[path_num] = g_strdup (buf + start_offset);
+ path_num++;
+ module_path[path_num] = NULL;
+ start_offset = end_offset + 1;
+ }
+ }
+ g_free (buf);
+ gtk_rc_append_default_module_path();
}
static guint
-gtk_rc_parse_widget_class_style (GScanner *scanner)
+gtk_rc_parse_path_pattern (GScanner *scanner)
{
- GtkRcSet *rc_set;
guint token;
+ GtkPathType path_type;
+ gchar *pattern;
+ gboolean is_binding;
+ GtkPathPriorityType priority = GTK_PATH_PRIO_RC;
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_WIDGET_CLASS)
- return TOKEN_WIDGET_CLASS;
+ switch (token)
+ {
+ case GTK_RC_TOKEN_WIDGET:
+ path_type = GTK_PATH_WIDGET;
+ break;
+ case GTK_RC_TOKEN_WIDGET_CLASS:
+ path_type = GTK_PATH_WIDGET_CLASS;
+ break;
+ case GTK_RC_TOKEN_CLASS:
+ path_type = GTK_PATH_CLASS;
+ break;
+ default:
+ return GTK_RC_TOKEN_WIDGET_CLASS;
+ }
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
-
- rc_set = g_new (GtkRcSet, 1);
- gtk_pattern_spec_init (&rc_set->pspec, scanner->value.v_string);
+
+ pattern = g_strdup (scanner->value.v_string);
token = g_scanner_get_next_token (scanner);
- if (token != TOKEN_STYLE)
+ if (token == GTK_RC_TOKEN_STYLE)
+ is_binding = FALSE;
+ else if (token == GTK_RC_TOKEN_BINDING)
{
- gtk_pattern_spec_free_segs (&rc_set->pspec);
- g_free (rc_set);
- return G_TOKEN_STRING;
+ is_binding = TRUE;
+ if (g_scanner_peek_next_token (scanner) == ':')
+ {
+ token = gtk_rc_parse_priority (scanner, &priority);
+ if (token != G_TOKEN_NONE)
+ {
+ g_free (pattern);
+ return token;
+ }
+ }
+ }
+ else
+ {
+ g_free (pattern);
+ return GTK_RC_TOKEN_STYLE;
}
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
{
- gtk_pattern_spec_free_segs (&rc_set->pspec);
- g_free (rc_set);
+ g_free (pattern);
return G_TOKEN_STRING;
}
-
- rc_set->rc_style = gtk_rc_style_find (scanner->value.v_string);
- if (!rc_set->rc_style)
+
+ if (is_binding)
{
- gtk_pattern_spec_free_segs (&rc_set->pspec);
- g_free (rc_set);
- return G_TOKEN_STRING;
+ GtkBindingSet *binding;
+
+ binding = gtk_binding_set_find (scanner->value.v_string);
+ if (!binding)
+ {
+ g_free (pattern);
+ return G_TOKEN_STRING;
+ }
+ gtk_binding_set_add_path (binding, path_type, pattern, priority);
}
-
- gtk_rc_sets_widget_class = g_slist_append (gtk_rc_sets_widget_class, rc_set);
-
+ else
+ {
+ GtkRcStyle *rc_style;
+ GtkRcSet *rc_set;
+
+ rc_style = gtk_rc_style_find (scanner->value.v_string);
+
+ if (!rc_style)
+ {
+ g_free (pattern);
+ return G_TOKEN_STRING;
+ }
+
+ rc_set = g_new (GtkRcSet, 1);
+ gtk_pattern_spec_init (&rc_set->pspec, pattern);
+ rc_set->rc_style = rc_style;
+
+ if (path_type == GTK_PATH_WIDGET)
+ gtk_rc_sets_widget = g_slist_prepend (gtk_rc_sets_widget, rc_set);
+ else if (path_type == GTK_PATH_WIDGET_CLASS)
+ gtk_rc_sets_widget_class = g_slist_prepend (gtk_rc_sets_widget_class, rc_set);
+ else
+ gtk_rc_sets_class = g_slist_prepend (gtk_rc_sets_class, rc_set);
+ }
+
+ g_free (pattern);
return G_TOKEN_NONE;
}
void
gtk_rc_set_image_loader(GtkImageLoader loader)
{
- image_loader = loader;
+ image_loader = loader;
}
+GdkPixmap *
+gtk_rc_load_image (GdkColormap *colormap,
+ GdkColor *transparent_color,
+ const gchar *filename)
+{
+ if (strcmp (filename, "<parent>") == 0)
+ return (GdkPixmap*) GDK_PARENT_RELATIVE;
+ else
+ {
+ if(image_loader)
+ return image_loader(NULL, colormap, NULL,
+ transparent_color,
+ filename);
+ else
+ return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
+ transparent_color,
+ filename);
+ }
+}