* 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 "gdkx.h"
+
+#if GDK_WINDOWING == 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 <stdlib.h>
+
+#ifndef HAVE_LSTAT
+#define lstat stat
+#endif
+
+#ifdef NATIVE_WIN32
+#include <io.h>
+#endif
+
#include "gtkrc.h"
#include "gtkbindings.h"
#include "gtkthemes.h"
+#include "gtkintl.h"
typedef struct _GtkRcSet GtkRcSet;
typedef struct _GtkRcNode GtkRcNode;
static void gtk_rc_append_default_pixmap_path (void);
static void gtk_rc_append_default_module_path (void);
static void gtk_rc_append_pixmap_path (gchar *dir);
+static void gtk_rc_add_initial_default_files (void);
-static GScannerConfig gtk_rc_scanner_config =
+static const GScannerConfig gtk_rc_scanner_config =
{
(
- " \t\n"
+ " \t\r\n"
) /* cset_skip_characters */,
(
G_CSET_a_2_z
FALSE /* scope_0_fallback */,
};
-static struct
+static const struct
{
gchar *name;
guint token;
{ "module_path", GTK_RC_TOKEN_MODULE_PATH },
};
-static guint n_symbols = 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_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
/* RC file handling */
+#ifdef NATIVE_WIN32
+
+static gchar *
+get_gtk_sysconf_directory ()
+{
+ static gchar gtk_sysconf_dir[200];
+ gchar win_dir[100];
+
+ GetWindowsDirectory (win_dir, sizeof (win_dir));
+ sprintf (gtk_sysconf_dir, "%s\\gtk", win_dir);
+ return gtk_sysconf_dir;
+}
+
+static gchar *
+get_themes_directory ()
+{
+ /* We really should fetch this from the Registry. The GIMP
+ * installation program stores the Themes installation
+ * directory in HKLM\Software\GNU\GTk+\Themes\InstallDirectory.
+ * Later.
+ */
+ static gchar themes_dir[200];
+
+ sprintf (themes_dir, "%s\\themes", get_gtk_sysconf_directory ());
+ return themes_dir;
+}
+
+#endif
+
gchar *
gtk_rc_get_theme_dir(void)
{
gchar *var, *path;
+#ifndef NATIVE_WIN32
var = getenv("GTK_DATA_PREFIX");
if (var)
- {
- path = g_malloc(strlen(var) + strlen("/share/themes") +1);
- sprintf(path, "%s%s", var, "/share/themes");
- }
+ path = g_strdup_printf("%s%s", var, "/share/themes");
else
- {
- path = g_malloc(strlen(GTK_DATA_PREFIX) + strlen("/share/themes") +1);
- sprintf(path, "%s%s", GTK_DATA_PREFIX, "/share/themes");
- }
+ path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/themes");
+#else
+ path = g_strdup (get_themes_directory ());
+#endif
+
return path;
}
{
gchar *var, *path;
+#ifndef NATIVE_WIN32
var = getenv("GTK_EXE_PREFIX");
if (var)
- {
- path = g_malloc(strlen(var) + strlen("/lib/gtk/themes/engines") +1);
- sprintf(path, "%s%s", var, "/lib/gtk/themes/engines");
- }
+ path = g_strdup_printf("%s%s", var, "/lib/gtk/themes/engines");
else
- {
- path = g_malloc(strlen(GTK_EXE_PREFIX) + strlen("/lib/gtk/themes/engines") +1);
- sprintf(path, "%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
- }
+ path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
+#else
+ path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
+#endif
+
return path;
}
gchar *var, *path;
gint n;
+#ifndef NATIVE_WIN32
var = getenv("GTK_DATA_PREFIX");
if (var)
- {
- path = g_malloc(strlen(var) + strlen("/share/gtk/themes") +1);
- sprintf(path, "%s%s", var, "/share/gtk/themes");
- }
+ path = g_strdup_printf("%s%s", var, "/share/gtk/themes");
else
- {
- path = g_malloc(strlen(GTK_DATA_PREFIX) + strlen("/share/gtk/themes") +1);
- sprintf(path, "%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
- }
+ path = g_strdup_printf("%s%s", GTK_DATA_PREFIX, "/share/gtk/themes");
+#else
+ path = g_strdup (get_themes_directory ());
+#endif
for (n = 0; pixmap_path[n]; n++) ;
if (n >= GTK_RC_MAX_PIXMAP_PATHS - 1)
- return;
- pixmap_path[n++] = g_strdup(path);
+ {
+ g_free (path);
+ return;
+ }
+ pixmap_path[n++] = path;
pixmap_path[n] = NULL;
- g_free(path);
}
static void
if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
return;
+#ifndef NATIVE_WIN32
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");
+#else
+ path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
+#endif
+ module_path[n++] = path;
+
+ var = g_get_home_dir ();
if (var)
{
- path = g_malloc(strlen(var) + strlen("/lib/gtk/themes/engines") +1);
- sprintf(path, "%s%s", var, "/lib/gtk/themes/engines");
+#ifndef NATIVE_WIN32
+ path = g_strdup_printf ("%s%s", var, "/.gtk/lib/themes/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
{
- path = g_malloc(strlen(GTK_EXE_PREFIX) + strlen("/lib/gtk/themes/engines") +1);
- sprintf(path, "%s%s", GTK_EXE_PREFIX, "/lib/gtk/themes/engines");
+#ifndef NATIVE_WIN32
+ str = g_strdup (GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk" G_DIR_SEPARATOR_S "gtkrc");
+#else
+ str = g_strdup_printf ("%s\\gtkrc", get_gtk_sysconf_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", var);
+ gtk_rc_add_default_file (str);
+ g_free (str);
+ }
}
- module_path[n++] = g_strdup(path);
- g_free(path);
- var = getenv("HOME");
- if (var)
+}
+
+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])
{
- path = g_malloc(strlen(var) + strlen(".gtk/lib/themes/engines") +1);
- sprintf(path, "%s%s", var, ".gtk/lib/themes/engines");
+ g_free (gtk_rc_default_files[i]);
+ i++;
}
- module_path[n++] = g_strdup(path);
- module_path[n] = NULL;
- g_free(path);
+
+ 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;
}
void
gtk_rc_init (void)
{
+ gchar *locale_suffixes[3];
+ gint n_locale_suffixes = 0;
+ gint i, j;
+#ifdef HAVE_LC_MESSAGES
+ char *locale = setlocale (LC_MESSAGES, NULL);
+#else
+ char *locale = setlocale (LC_CTYPE, NULL);
+#endif
+ guint length;
+ char *p;
+
rc_style_ht = g_hash_table_new ((GHashFunc) gtk_rc_style_hash,
(GCompareFunc) gtk_rc_style_compare);
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++;
+ }
+ }
void
gtk_rc_parse_string (const gchar *rc_string)
{
/* 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
{
str = g_string_new (cwd);
g_free (cwd);
- g_string_append_c (str, '/');
+ g_string_append_c (str, G_DIR_SEPARATOR);
g_string_append (str, rc_file->name);
rc_file->canonical_name = str->str;
gchar *dir;
dir = g_strdup(rc_file->canonical_name);
- for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != '/'); i--)
+ for (i = strlen(dir) - 1; (i >= 0) && (dir[i] != G_DIR_SEPARATOR); i--)
dir[i] = 0;
gtk_rc_append_pixmap_path(dir);
g_free(dir);
gint i;
g_return_if_fail (rc_style != NULL);
+ g_return_if_fail (rc_style->ref_count > 0);
rc_style->ref_count--;
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)
{
tmp_styles = tmp_styles->next;
}
+ for (i=0; i<5; i++)
+ if (proto_style->bg_pixmap_name[i] &&
+ (strcmp (proto_style->bg_pixmap_name[i], "<none>") == 0))
+ {
+ g_free (proto_style->bg_pixmap_name[i]);
+ proto_style->bg_pixmap_name[i] = NULL;
+ }
+
style = gtk_rc_style_to_style (proto_style);
g_hash_table_insert (realized_style_ht, rc_styles, style);
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)
{
for (i = 0; (i < GTK_RC_MAX_PIXMAP_PATHS) && (pixmap_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",
+ pixmap_path[i], pixmap_file);
fd = open (buf, O_RDONLY);
if (fd >= 0)
}
if (scanner)
- g_warning ("Unable to locate image file in pixmap_path: \"%s\" line %d",
+ 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\"",
+ g_warning (_("Unable to locate image file in pixmap_path: \"%s\""),
pixmap_file);
return NULL;
}
gchar*
-gtk_rc_find_module_in_path (GScanner *scanner,
- const gchar *module_file)
+gtk_rc_find_module_in_path (const gchar *module_file)
{
gint i;
gint fd;
for (i = 0; (i < GTK_RC_MAX_MODULE_PATHS) && (module_path[i] != NULL); i++)
{
- buf = g_malloc (strlen (module_path[i]) + strlen (module_file) + 2);
- sprintf (buf, "%s%c%s", module_path[i], '/', module_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);
}
-
- if (scanner)
- g_warning ("Unable to locate loadable module in module_path: \"%s\" line %d",
- module_file, scanner->line);
- else
- g_warning ("Unable to locate loadable module in module_path: \"%s\",",
- module_file);
return NULL;
}
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';
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';