📄 gtkrc.c
字号:
/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * 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 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * 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 <X11/Xlocale.h> /* so we get the right setlocale */#include <ctype.h>#include <unistd.h>#include <sys/stat.h>#include <sys/param.h>#include <fcntl.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include "gtkrc.h"#include "gtkbindings.h"#include "gtkthemes.h"#include "gtkintl.h"typedef struct _GtkRcSet GtkRcSet;typedef struct _GtkRcNode GtkRcNode;typedef struct _GtkRcFile GtkRcFile;typedef struct _GtkRcStylePrivate GtkRcStylePrivate;struct _GtkRcSet{ GtkPatternSpec pspec; GtkRcStyle *rc_style;};struct _GtkRcFile{ time_t mtime; gchar *name; gchar *canonical_name; gboolean reload;};struct _GtkRcStylePrivate{ GtkRcStyle style; guint ref_count; /* list of RC style lists including this RC style */ GSList *rc_style_lists;};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_style_init (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_base (GScanner *scanner, GtkRcStyle *style);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_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_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_pixmap_path (void);static void gtk_rc_append_default_module_path (void);static void gtk_rc_add_initial_default_files (void);static const GScannerConfig gtk_rc_scanner_config ={ ( " \t\n" ) /* cset_skip_characters */, ( G_CSET_a_2_z "_" G_CSET_A_2_Z ) /* cset_identifier_first */, ( G_CSET_a_2_z "_-0123456789" 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 */, TRUE /* scan_string_sq */, TRUE /* scan_string_dq */, TRUE /* numbers_2_int */, FALSE /* int_2_float */, FALSE /* identifier_2_string */, TRUE /* char_2_token */, TRUE /* symbol_2_token */, FALSE /* scope_0_fallback */,};static const struct{ gchar *name; guint token;} symbols[] = { { "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 }, { "base", GTK_RC_TOKEN_BASE }, { "text", GTK_RC_TOKEN_TEXT }, { "font", GTK_RC_TOKEN_FONT }, { "fontset", GTK_RC_TOKEN_FONTSET }, { "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 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 128static gchar *gtk_rc_default_files[GTK_RC_MAX_DEFAULT_FILES];static gboolean gtk_rc_auto_parse = TRUE;#define GTK_RC_MAX_PIXMAP_PATHS 128static gchar *pixmap_path[GTK_RC_MAX_PIXMAP_PATHS];#define GTK_RC_MAX_MODULE_PATHS 128static 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 */gchar *gtk_rc_get_theme_dir(void){ gchar *var, *path; 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"); return path;}gchar *gtk_rc_get_module_dir(void){ gchar *var, *path; var = getenv("GTK_EXE_PREFIX"); if (var) path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines"); else path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines"); return path;}static voidgtk_rc_append_default_pixmap_path(void){ gchar *var, *path; gint n; var = getenv("GTK_DATA_PREFIX"); if (var) path = g_strdup_printf("%s%s", var, "/share/gtk/themes"); else path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes"); for (n = 0; pixmap_path[n]; n++) ; if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1) return; pixmap_path[n++] = g_strdup(path); pixmap_path[n] = NULL; g_free(path);}static voidgtk_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; var = getenv("GTK_EXE_PREFIX"); if (var) path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines"); else path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines"); module_path[n++] = g_strdup(path); g_free(path); var = g_get_home_dir (); if (var) path = g_strdup_printf("%s%s", var, "/.gtk/lib/themes/engines"); module_path[n++] = g_strdup(path); module_path[n] = NULL; g_free(path);}static voidgtk_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 = getenv("GTK_RC_FILES"); if (var) { files = g_strsplit (var, ":", 128); i=0; while (files[i]) { gtk_rc_add_default_file (files[i]); i++; } g_strfreev (files); } else { str = g_strdup_printf ("%s%s", GTK_SYSCONFDIR, "/gtk/gtkrc"); gtk_rc_add_default_file (str); g_free (str); str = g_strdup_printf ("%s%s", g_get_home_dir (), "/.gtkrc"); gtk_rc_add_default_file (str); g_free (str); }}voidgtk_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;}voidgtk_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;}voidgtk_rc_init (void){ gchar *locale_suffixes[3]; gint n_locale_suffixes = 0; gint i, j;#if defined (HAVE_LC_MESSAGES) && !defined (X_LOCALE) char *locale = setlocale (LC_MESSAGES, NULL);#else char *locale = setlocale (LC_CTYPE, NULL);#endif guint length; char *p; pixmap_path[0] = NULL; module_path[0] = NULL; gtk_rc_append_default_pixmap_path(); 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 */ p = strchr (locale, '@'); length = p ? (p -locale) : strlen (locale); p = strchr (locale, '.'); if (p) { locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length); length = p - locale; } p = strchr (locale, '_'); if (p) { locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length); length = p - locale; } locale_suffixes[n_locale_suffixes++] = g_strndup (locale, length); } 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++; } }voidgtk_rc_parse_string (const gchar *rc_string){ g_return_if_fail (rc_string != NULL); gtk_rc_parse_any ("-", -1, rc_string);}static voidgtk_rc_parse_file (const gchar *filename, gboolean reload){ GtkRcFile *rc_file = NULL; struct stat statbuf; GSList *tmp_list; g_return_if_fail (filename != NULL); tmp_list = rc_files; while (tmp_list) { rc_file = tmp_list->data; if (!strcmp (rc_file->name, filename)) break; tmp_list = tmp_list->next; } if (!tmp_list) { rc_file = g_new (GtkRcFile, 1); rc_file->name = g_strdup (filename); rc_file->canonical_name = NULL; rc_file->mtime = 0; rc_file->reload = reload; rc_files = g_slist_append (rc_files, rc_file); } if (!rc_file->canonical_name) { /* Get the absolute pathname */ if (rc_file->name[0] == '/') rc_file->canonical_name = rc_file->name; else { GString *str; gchar *cwd; cwd = g_get_current_dir (); str = g_string_new (cwd); g_free (cwd); g_string_append_c (str, '/'); g_string_append (str, rc_file->name); rc_file->canonical_name = str->str; g_string_free (str, FALSE); } } if (!lstat (rc_file->canonical_name, &statbuf)) { gint fd; GSList *tmp_list; rc_file->mtime = statbuf.st_mtime; fd = open (rc_file->canonical_name, O_RDONLY); 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); }}voidgtk_rc_parse (const gchar *filename){ g_return_if_fail (filename != NULL); gtk_rc_parse_file (filename, TRUE);}/* Handling of RC styles */GtkRcStyle *gtk_rc_style_new (void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -