]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkrc.c
Support added for building using a GNU toolchain on Win32,
[~andy/gtk] / gtk / gtkrc.c
index 91e5bd06ce84ba916715d640317419bdca00a544..09d22a49b8a2f316e5f7d26bc0f74daf3b1d6e46 100644 (file)
  * 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;
@@ -102,7 +133,7 @@ static void        gtk_rc_add_initial_default_files  (void);
 static const GScannerConfig    gtk_rc_scanner_config =
 {
   (
-   " \t\n"
+   " \t\r\n"
    )                   /* cset_skip_characters */,
   (
    G_CSET_a_2_z
@@ -199,22 +230,50 @@ static GtkImageLoader image_loader = NULL;
 /* 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;
 }
 
@@ -223,17 +282,16 @@ gtk_rc_get_module_dir(void)
 {
   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;
 }
 
@@ -243,24 +301,24 @@ gtk_rc_append_default_pixmap_path(void)
   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
@@ -285,28 +343,28 @@ gtk_rc_append_default_module_path(void)
   if (n >= GTK_RC_MAX_MODULE_PATHS - 1)
     return;
   
+#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");
-    }
-  module_path[n++] = g_strdup(path);
-  g_free(path);
-  var = getenv("HOME");
+    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(".gtk/lib/themes/engines") +1);
-      sprintf(path, "%s%s", var, ".gtk/lib/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++] = g_strdup(path);
   module_path[n] = NULL;
-  g_free(path);
 }
 
 static void
@@ -323,27 +381,35 @@ gtk_rc_add_initial_default_files (void)
   gtk_rc_default_files[0] = NULL;
   init = TRUE;
 
-  var = getenv("GTK_RC_FILES");
+  var = g_getenv("GTK_RC_FILES");
   if (var)
     {
-      files = g_strsplit (var, ":", 128);
+      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
     {
-      str = g_malloc (strlen(GTK_SYSCONFDIR) + strlen("/gtkrc") + 1);
-      sprintf (str, "%s%s", GTK_SYSCONFDIR, "/gtkrc");
+#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 ();
-      str = g_malloc (strlen(var) + strlen("/.gtkrc") + 1);
-      sprintf (str, "%s%s", var, "/.gtkrc");
-      gtk_rc_add_default_file (str);
+      if (var)
+       {
+         str = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".gtkrc", var);
+         gtk_rc_add_default_file (str);
+         g_free (str);
+       }
     }
 }
 
@@ -398,7 +464,16 @@ gtk_rc_get_default_files (void)
 void
 gtk_rc_init (void)
 {
-  guint i;
+  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);
@@ -409,13 +484,50 @@ gtk_rc_init (void)
 
   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)
@@ -459,7 +571,7 @@ gtk_rc_parse_file (const gchar *filename, gboolean reload)
     {
       /* 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
        {
@@ -470,7 +582,7 @@ gtk_rc_parse_file (const gchar *filename, gboolean reload)
 
          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;
@@ -493,7 +605,7 @@ gtk_rc_parse_file (const gchar *filename, gboolean reload)
          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);
@@ -539,6 +651,7 @@ gtk_rc_style_unref (GtkRcStyle  *rc_style)
   gint i;
 
   g_return_if_fail (rc_style != NULL);
+  g_return_if_fail (rc_style->ref_count > 0);
 
   rc_style->ref_count--;
 
@@ -832,7 +945,7 @@ gtk_rc_parse_any (const gchar  *input_name,
   guint           i;
   gboolean done;
   
-  scanner = g_scanner_new (&gtk_rc_scanner_config);
+  scanner = g_scanner_new ((GScannerConfig *) &gtk_rc_scanner_config);
   
   if (input_fd >= 0)
     {
@@ -1098,6 +1211,14 @@ gtk_rc_style_init (GSList *rc_styles)
          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);
@@ -1445,10 +1566,11 @@ gtk_rc_parse_bg_pixmap (GScanner   *scanner,
   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)
     {
@@ -1470,8 +1592,8 @@ gtk_rc_find_pixmap_in_path (GScanner *scanner,
   
   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)
@@ -1484,10 +1606,10 @@ gtk_rc_find_pixmap_in_path (GScanner *scanner,
     }
 
   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;
@@ -1502,8 +1624,8 @@ gtk_rc_find_module_in_path (const gchar *module_file)
   
   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)
@@ -1867,7 +1989,7 @@ gtk_rc_parse_pixmap_path_string (gchar *pix_path)
   
   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';
@@ -1923,7 +2045,7 @@ gtk_rc_parse_module_path_string (gchar *mod_path)
   
   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';