glib/libglib/src/gutils.c
branchRCL_3
changeset 57 2efc27d87e1c
parent 0 e4d67989cc36
equal deleted inserted replaced
56:acd3cd4aaceb 57:2efc27d87e1c
       
     1 /* GLIB - Library of useful routines for C programming
       
     2  * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
       
     3  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Lesser General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
       
    13  * Lesser General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Lesser General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 /*
       
    22  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    23  * file for a list of people on the GLib Team.  See the ChangeLog
       
    24  * files for a list of changes.  These files are distributed with
       
    25  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    26  */
       
    27 
       
    28 /* 
       
    29  * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
       
    30  */
       
    31 
       
    32 #include "config.h"
       
    33 
       
    34 #ifdef HAVE_UNISTD_H
       
    35 #include <unistd.h>
       
    36 #endif
       
    37 #include <stdarg.h>
       
    38 #include <stdlib.h>
       
    39 #include <stdio.h>
       
    40 #include <locale.h>
       
    41 #include <string.h>
       
    42 #include <errno.h>
       
    43 #ifdef HAVE_PWD_H
       
    44 #include <pwd.h>
       
    45 #endif
       
    46 #include <sys/types.h>
       
    47 #ifdef HAVE_SYS_PARAM_H
       
    48 #include <sys/param.h>
       
    49 #endif
       
    50 #ifdef HAVE_CRT_EXTERNS_H 
       
    51 #include <crt_externs.h> /* for _NSGetEnviron */
       
    52 #endif
       
    53 
       
    54 /* implement gutils's inline functions
       
    55  */
       
    56 #define	G_IMPLEMENT_INLINES 1
       
    57 #define	__G_UTILS_C__
       
    58 #include "glib.h"
       
    59 #include "gprintfint.h"
       
    60 #include "gthreadinit.h"
       
    61 #include "galias.h"
       
    62 
       
    63 #ifdef __SYMBIAN32__
       
    64 #include "glibbackend.h"
       
    65 #include <glib_wsd.h>
       
    66 
       
    67 #define G_MALLOC_VOID(numbytes , var) { \
       
    68 	if(numbytes) \
       
    69 	{ \
       
    70 		var = g_try_malloc(numbytes); \
       
    71 		if(!var) \
       
    72 			return; \
       
    73 	} \
       
    74 	else\
       
    75 		var = NULL;\
       
    76 }
       
    77                                       
       
    78 #endif //__SYMBIAN32__
       
    79 
       
    80 #if EMULATOR
       
    81 #define g_thread_functions_for_glib_use (*_g_thread_functions_for_glib_use())
       
    82 #define g_thread_use_default_impl (*_g_thread_use_default_impl())
       
    83 #endif /* EMULATOR */
       
    84 
       
    85 
       
    86 
       
    87 #ifdef	MAXPATHLEN
       
    88 #define	G_PATH_LENGTH	MAXPATHLEN
       
    89 #elif	defined (PATH_MAX)
       
    90 #define	G_PATH_LENGTH	PATH_MAX
       
    91 #elif   defined (_PC_PATH_MAX)
       
    92 #define	G_PATH_LENGTH	sysconf(_PC_PATH_MAX)
       
    93 #else	
       
    94 #define G_PATH_LENGTH   2048
       
    95 #endif
       
    96 
       
    97 #ifdef G_PLATFORM_WIN32
       
    98 #  define STRICT		/* Strict typing, please */
       
    99 #  include <windows.h>
       
   100 #  undef STRICT
       
   101 #  ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
       
   102 #    define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
       
   103 #    define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
       
   104 #  endif
       
   105 #  include <lmcons.h>		/* For UNLEN */
       
   106 #endif /* G_PLATFORM_WIN32 */
       
   107 
       
   108 #ifdef G_OS_WIN32
       
   109 #  include <direct.h>
       
   110 #  include <shlobj.h>
       
   111    /* older SDK (e.g. msvc 5.0) does not have these*/
       
   112 #  ifndef CSIDL_INTERNET_CACHE
       
   113 #    define CSIDL_INTERNET_CACHE 32
       
   114 #  endif
       
   115 #  ifndef CSIDL_COMMON_APPDATA
       
   116 #    define CSIDL_COMMON_APPDATA 35
       
   117 #  endif
       
   118 #  ifndef CSIDL_COMMON_DOCUMENTS
       
   119 #    define CSIDL_COMMON_DOCUMENTS 46
       
   120 #  endif
       
   121 #  ifndef CSIDL_PROFILE
       
   122 #    define CSIDL_PROFILE 40
       
   123 #  endif
       
   124 #  include <process.h>
       
   125 #endif
       
   126 
       
   127 #ifdef HAVE_CODESET
       
   128 #include <langinfo.h>
       
   129 #endif
       
   130 
       
   131 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
       
   132 #include <libintl.h>    //puneet
       
   133 #endif
       
   134 
       
   135 const guint glib_major_version = GLIB_MAJOR_VERSION;
       
   136 const guint glib_minor_version = GLIB_MINOR_VERSION;
       
   137 const guint glib_micro_version = GLIB_MICRO_VERSION;
       
   138 const guint glib_interface_age = GLIB_INTERFACE_AGE;
       
   139 const guint glib_binary_age = GLIB_BINARY_AGE;
       
   140 
       
   141 #ifdef __SYMBIAN32__
       
   142 EXPORT_C const  guint *_glib_major_version()
       
   143 {
       
   144 	return &glib_major_version;
       
   145 }
       
   146 EXPORT_C const  guint *_glib_minor_version()
       
   147 {
       
   148 	return &glib_minor_version;
       
   149 }
       
   150 EXPORT_C const  guint *_glib_micro_version()
       
   151 {
       
   152 	return &glib_micro_version;
       
   153 }
       
   154 EXPORT_C const  guint *_glib_interface_age()
       
   155 {
       
   156 	return &glib_interface_age;
       
   157 }
       
   158 EXPORT_C const  guint *_glib_binary_age()
       
   159 {
       
   160 	return &glib_binary_age;
       
   161 }
       
   162 #endif /* __SYMBIAN32__ */
       
   163 
       
   164 #ifdef G_PLATFORM_WIN32
       
   165 
       
   166 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
       
   167 
       
   168 #endif
       
   169 
       
   170 /**
       
   171  * glib_check_version:
       
   172  * @required_major: the required major version.
       
   173  * @required_minor: the required minor version.
       
   174  * @required_micro: the required micro version.
       
   175  *
       
   176  * Checks that the GLib library in use is compatible with the
       
   177  * given version. Generally you would pass in the constants
       
   178  * #GLIB_MAJOR_VERSION, #GLIB_MINOR_VERSION, #GLIB_MICRO_VERSION
       
   179  * as the three arguments to this function; that produces
       
   180  * a check that the library in use is compatible with
       
   181  * the version of GLib the application or module was compiled
       
   182  * against.
       
   183  *
       
   184  * Compatibility is defined by two things: first the version
       
   185  * of the running library is newer than the version
       
   186  * @required_major.required_minor.@required_micro. Second
       
   187  * the running library must be binary compatible with the
       
   188  * version @required_major.required_minor.@required_micro
       
   189  * (same major version.)
       
   190  *
       
   191  * Return value: %NULL if the GLib library is compatible with the
       
   192  *   given version, or a string describing the version mismatch.
       
   193  *   The returned string is owned by GLib and must not be modified
       
   194  *   or freed.
       
   195  *
       
   196  * Since: 2.6
       
   197  **/
       
   198 EXPORT_C const gchar *
       
   199 glib_check_version (guint required_major,
       
   200                     guint required_minor,
       
   201                     guint required_micro)
       
   202 {
       
   203   gint glib_effective_micro = 100 * GLIB_MINOR_VERSION + GLIB_MICRO_VERSION;
       
   204   gint required_effective_micro = 100 * required_minor + required_micro;
       
   205 
       
   206   if (required_major > GLIB_MAJOR_VERSION)
       
   207     return "GLib version too old (major mismatch)";
       
   208   if (required_major < GLIB_MAJOR_VERSION)
       
   209     return "GLib version too new (major mismatch)";
       
   210   if (required_effective_micro < glib_effective_micro - GLIB_BINARY_AGE)
       
   211     return "GLib version too new (micro mismatch)";
       
   212   if (required_effective_micro > glib_effective_micro)
       
   213     return "GLib version too old (micro mismatch)";
       
   214   return NULL;
       
   215 }
       
   216 
       
   217 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
       
   218 /**
       
   219  * g_memmove: 
       
   220  * @dest: the destination address to copy the bytes to.
       
   221  * @src: the source address to copy the bytes from.
       
   222  * @len: the number of bytes to copy.
       
   223  *
       
   224  * Copies a block of memory @len bytes long, from @src to @dest.
       
   225  * The source and destination areas may overlap.
       
   226  *
       
   227  * In order to use this function, you must include 
       
   228  * <filename>string.h</filename> yourself, because this macro will 
       
   229  * typically simply resolve to memmove() and GLib does not include 
       
   230  * <filename>string.h</filename> for you.
       
   231  */
       
   232 void 
       
   233 g_memmove (gpointer      dest, 
       
   234 	   gconstpointer src, 
       
   235 	   gulong        len)
       
   236 {
       
   237   gchar* destptr = dest;
       
   238   const gchar* srcptr = src;
       
   239   if (src + len < dest || dest + len < src)
       
   240     {
       
   241       bcopy (src, dest, len);
       
   242       return;
       
   243     }
       
   244   else if (dest <= src)
       
   245     {
       
   246       while (len--)
       
   247 	*(destptr++) = *(srcptr++);
       
   248     }
       
   249   else
       
   250     {
       
   251       destptr += len;
       
   252       srcptr += len;
       
   253       while (len--)
       
   254 	*(--destptr) = *(--srcptr);
       
   255     }
       
   256 }
       
   257 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
       
   258 
       
   259 #ifdef G_OS_WIN32
       
   260 #undef g_atexit
       
   261 #endif
       
   262 
       
   263 /**
       
   264  * g_atexit:
       
   265  * @func: the function to call on normal program termination.
       
   266  * 
       
   267  * Specifies a function to be called at normal program termination.
       
   268  *
       
   269  * Since GLib 2.8.2, on Windows g_atexit() actually is a preprocessor
       
   270  * macro that maps to a call to the atexit() function in the C
       
   271  * library. This means that in case the code that calls g_atexit(),
       
   272  * i.e. atexit(), is in a DLL, the function will be called when the
       
   273  * DLL is detached from the program. This typically makes more sense
       
   274  * than that the function is called when the GLib DLL is detached,
       
   275  * which happened earlier when g_atexit() was a function in the GLib
       
   276  * DLL.
       
   277  *
       
   278  * The behaviour of atexit() in the context of dynamically loaded
       
   279  * modules is not formally specified and varies wildly.
       
   280  *
       
   281  * On POSIX systems, calling g_atexit() (or atexit()) in a dynamically
       
   282  * loaded module which is unloaded before the program terminates might
       
   283  * well cause a crash at program exit.
       
   284  *
       
   285  * Some POSIX systems implement atexit() like Windows, and have each
       
   286  * dynamically loaded module maintain an own atexit chain that is
       
   287  * called when the module is unloaded.
       
   288  *
       
   289  * On other POSIX systems, before a dynamically loaded module is
       
   290  * unloaded, the registered atexit functions (if any) residing in that
       
   291  * module are called, regardless where the code that registered them
       
   292  * resided. This is presumably the most robust approach.
       
   293  *
       
   294  * As can be seen from the above, for portability it's best to avoid
       
   295  * calling g_atexit() (or atexit()) except in the main executable of a
       
   296  * program.
       
   297  */
       
   298 EXPORT_C void
       
   299 g_atexit (GVoidFunc func)
       
   300 {
       
   301   gint result;
       
   302   const gchar *error = NULL;
       
   303 
       
   304   /* keep this in sync with glib.h */
       
   305 
       
   306 #ifdef	G_NATIVE_ATEXIT
       
   307   result = ATEXIT (func);
       
   308   if (result)
       
   309     error = g_strerror (errno);
       
   310 #elif defined (HAVE_ATEXIT)
       
   311 #  ifdef NeXT /* @#%@! NeXTStep */
       
   312   result = !atexit ((void (*)(void)) func);
       
   313   if (result)
       
   314     error = g_strerror (errno);
       
   315 #  else
       
   316   result = atexit ((void (*)(void)) func);
       
   317   if (result)
       
   318     error = g_strerror (errno);
       
   319 #  endif /* NeXT */
       
   320 #elif defined (HAVE_ON_EXIT)
       
   321   result = on_exit ((void (*)(int, void *)) func, NULL);
       
   322   if (result)
       
   323     error = g_strerror (errno);
       
   324 #else
       
   325   result = 0;
       
   326   error = "no implementation";
       
   327 #endif /* G_NATIVE_ATEXIT */
       
   328 
       
   329   if (error)
       
   330     g_error ("Could not register atexit() function: %s", error);
       
   331 }
       
   332 
       
   333 /* Based on execvp() from GNU Libc.
       
   334  * Some of this code is cut-and-pasted into gspawn.c
       
   335  */
       
   336 
       
   337 static gchar*
       
   338 my_strchrnul (const gchar *str, 
       
   339 	      gchar        c)
       
   340 {
       
   341   gchar *p = (gchar*)str;
       
   342   while (*p && (*p != c))
       
   343     ++p;
       
   344 
       
   345   return p;
       
   346 }
       
   347 
       
   348 #ifdef G_OS_WIN32
       
   349 
       
   350 static gchar *inner_find_program_in_path (const gchar *program);
       
   351 
       
   352 EXPORT_C gchar*
       
   353 g_find_program_in_path (const gchar *program)
       
   354 {
       
   355   #ifdef __SYMBIAN32__
       
   356   return getProgPath(program);
       
   357   #endif /* __SYMBIAN32__ */
       
   358   const gchar *last_dot = strrchr (program, '.');
       
   359 
       
   360   if (last_dot == NULL ||
       
   361       strchr (last_dot, '\\') != NULL ||
       
   362       strchr (last_dot, '/') != NULL)
       
   363     {
       
   364       const gint program_length = strlen (program);
       
   365       gchar *pathext = g_build_path (";",
       
   366 				     ".exe;.cmd;.bat;.com",
       
   367 				     g_getenv ("PATHEXT"),
       
   368 				     NULL);
       
   369       gchar *p;
       
   370       gchar *decorated_program;
       
   371       gchar *retval;
       
   372 
       
   373       p = pathext;
       
   374       do
       
   375 	{
       
   376 	  gchar *q = my_strchrnul (p, ';');
       
   377 	  decorated_program = g_malloc (program_length + (q-p) + 1);
       
   378 	  memcpy (decorated_program, program, program_length);
       
   379 	  memcpy (decorated_program+program_length, p, q-p);
       
   380 	  decorated_program [program_length + (q-p)] = '\0';
       
   381 	  
       
   382 	  retval = inner_find_program_in_path (decorated_program);
       
   383 	  g_free (decorated_program);
       
   384 
       
   385 	  if (retval != NULL)
       
   386 	    {
       
   387 	      g_free (pathext);
       
   388 	      return retval;
       
   389 	    }
       
   390 	  p = q;
       
   391 	} while (*p++ != '\0');
       
   392       g_free (pathext);
       
   393       return NULL;
       
   394     }
       
   395   else
       
   396     return inner_find_program_in_path (program);
       
   397 }
       
   398 
       
   399 #endif
       
   400 
       
   401 /**
       
   402  * g_find_program_in_path:
       
   403  * @program: a program name in the GLib file name encoding
       
   404  * 
       
   405  * Locates the first executable named @program in the user's path, in the
       
   406  * same way that execvp() would locate it. Returns an allocated string
       
   407  * with the absolute path name, or %NULL if the program is not found in
       
   408  * the path. If @program is already an absolute path, returns a copy of
       
   409  * @program if @program exists and is executable, and %NULL otherwise.
       
   410  *  
       
   411  * On Windows, if @program does not have a file type suffix, tries
       
   412  * with the suffixes .exe, .cmd, .bat and .com, and the suffixes in
       
   413  * the <envar>PATHEXT</envar> environment variable. 
       
   414  * 
       
   415  * On Windows, it looks for the file in the same way as CreateProcess() 
       
   416  * would. This means first in the directory where the executing
       
   417  * program was loaded from, then in the current directory, then in the
       
   418  * Windows 32-bit system directory, then in the Windows directory, and
       
   419  * finally in the directories in the <envar>PATH</envar> environment 
       
   420  * variable. If the program is found, the return value contains the 
       
   421  * full name including the type suffix.
       
   422  *
       
   423  * Return value: absolute path, or %NULL
       
   424  **/
       
   425 #ifdef G_OS_WIN32
       
   426 static gchar *
       
   427 inner_find_program_in_path (const gchar *program)
       
   428 #else
       
   429 EXPORT_C gchar*
       
   430 g_find_program_in_path (const gchar *program)
       
   431 #endif
       
   432 {  
       
   433   const gchar *path, *p;
       
   434   gchar *name, *freeme;
       
   435 #ifdef G_OS_WIN32
       
   436   const gchar *path_copy;
       
   437   gchar *filename = NULL, *appdir = NULL;
       
   438   gchar *sysdir = NULL, *windir = NULL;
       
   439 #endif
       
   440   size_t len;
       
   441   size_t pathlen;
       
   442 
       
   443   g_return_val_if_fail (program != NULL, NULL);
       
   444 #ifdef __SYMBIAN32__
       
   445   return getProgPath((char *)program);
       
   446 #endif /* __SYMBIAN32__ */
       
   447 
       
   448 
       
   449   /* If it is an absolute path, or a relative path including subdirectories,
       
   450    * don't look in PATH.
       
   451    */
       
   452   if (g_path_is_absolute (program)
       
   453       || strchr (program, G_DIR_SEPARATOR) != NULL
       
   454 #ifdef G_OS_WIN32
       
   455       || strchr (program, '/') != NULL
       
   456 #endif
       
   457       )
       
   458     {
       
   459       if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE) &&
       
   460 	  !g_file_test (program, G_FILE_TEST_IS_DIR))
       
   461         return g_strdup (program);
       
   462       else
       
   463         return NULL;
       
   464     }
       
   465   
       
   466   path = g_getenv ("PATH");
       
   467 #if defined(G_OS_UNIX) || defined(G_OS_BEOS)
       
   468   if (path == NULL)
       
   469     {
       
   470       /* There is no `PATH' in the environment.  The default
       
   471        * search path in GNU libc is the current directory followed by
       
   472        * the path `confstr' returns for `_CS_PATH'.
       
   473        */
       
   474       
       
   475       /* In GLib we put . last, for security, and don't use the
       
   476        * unportable confstr(); UNIX98 does not actually specify
       
   477        * what to search if PATH is unset. POSIX may, dunno.
       
   478        */
       
   479       
       
   480       path = "/bin:/usr/bin:.";
       
   481     }
       
   482 #else
       
   483   if (G_WIN32_HAVE_WIDECHAR_API ())
       
   484     {
       
   485       int n;
       
   486       wchar_t wfilename[MAXPATHLEN], wsysdir[MAXPATHLEN],
       
   487 	wwindir[MAXPATHLEN];
       
   488       
       
   489       n = GetModuleFileNameW (NULL, wfilename, MAXPATHLEN);
       
   490       if (n > 0 && n < MAXPATHLEN)
       
   491 	filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
       
   492       
       
   493       n = GetSystemDirectoryW (wsysdir, MAXPATHLEN);
       
   494       if (n > 0 && n < MAXPATHLEN)
       
   495 	sysdir = g_utf16_to_utf8 (wsysdir, -1, NULL, NULL, NULL);
       
   496       
       
   497       n = GetWindowsDirectoryW (wwindir, MAXPATHLEN);
       
   498       if (n > 0 && n < MAXPATHLEN)
       
   499 	windir = g_utf16_to_utf8 (wwindir, -1, NULL, NULL, NULL);
       
   500     }
       
   501   else
       
   502     {
       
   503       int n;
       
   504       gchar cpfilename[MAXPATHLEN], cpsysdir[MAXPATHLEN],
       
   505 	cpwindir[MAXPATHLEN];
       
   506       
       
   507       n = GetModuleFileNameA (NULL, cpfilename, MAXPATHLEN);
       
   508       if (n > 0 && n < MAXPATHLEN)
       
   509 	filename = g_locale_to_utf8 (cpfilename, -1, NULL, NULL, NULL);
       
   510       
       
   511       n = GetSystemDirectoryA (cpsysdir, MAXPATHLEN);
       
   512       if (n > 0 && n < MAXPATHLEN)
       
   513 	sysdir = g_locale_to_utf8 (cpsysdir, -1, NULL, NULL, NULL);
       
   514       
       
   515       n = GetWindowsDirectoryA (cpwindir, MAXPATHLEN);
       
   516       if (n > 0 && n < MAXPATHLEN)
       
   517 	windir = g_locale_to_utf8 (cpwindir, -1, NULL, NULL, NULL);
       
   518     }
       
   519   
       
   520   if (filename)
       
   521     {
       
   522       appdir = g_path_get_dirname (filename);
       
   523       g_free (filename);
       
   524     }
       
   525   
       
   526   path = g_strdup (path);
       
   527 
       
   528   if (windir)
       
   529     {
       
   530       const gchar *tem = path;
       
   531       path = g_strconcat (windir, ";", path, NULL);
       
   532       g_free ((gchar *) tem);
       
   533       g_free (windir);
       
   534     }
       
   535   
       
   536   if (sysdir)
       
   537     {
       
   538       const gchar *tem = path;
       
   539       path = g_strconcat (sysdir, ";", path, NULL);
       
   540       g_free ((gchar *) tem);
       
   541       g_free (sysdir);
       
   542     }
       
   543   
       
   544   {
       
   545     const gchar *tem = path;
       
   546     path = g_strconcat (".;", path, NULL);
       
   547     g_free ((gchar *) tem);
       
   548   }
       
   549   
       
   550   if (appdir)
       
   551     {
       
   552       const gchar *tem = path;
       
   553       path = g_strconcat (appdir, ";", path, NULL);
       
   554       g_free ((gchar *) tem);
       
   555       g_free (appdir);
       
   556     }
       
   557 
       
   558   path_copy = path;
       
   559 #endif
       
   560   
       
   561   len = strlen (program) + 1;
       
   562   pathlen = strlen (path);
       
   563   freeme = name = g_malloc (pathlen + len + 1);   
       
   564   
       
   565   /* Copy the file name at the top, including '\0'  */
       
   566   memcpy (name + pathlen + 1, program, len);
       
   567   name = name + pathlen;
       
   568   /* And add the slash before the filename  */
       
   569   *name = G_DIR_SEPARATOR;
       
   570   
       
   571   p = path;
       
   572   do
       
   573     {
       
   574       char *startp;
       
   575 
       
   576       path = p;
       
   577       p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR);
       
   578 
       
   579       if (p == path)
       
   580         /* Two adjacent colons, or a colon at the beginning or the end
       
   581          * of `PATH' means to search the current directory.
       
   582          */
       
   583         startp = name + 1;
       
   584       else
       
   585         startp = memcpy (name - (p - path), path, p - path);
       
   586 
       
   587       if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE) &&
       
   588 	  !g_file_test (startp, G_FILE_TEST_IS_DIR))
       
   589         {
       
   590           gchar *ret;
       
   591           ret = g_strdup (startp);
       
   592           g_free (freeme);
       
   593 #ifdef G_OS_WIN32
       
   594 	  g_free ((gchar *) path_copy);
       
   595 #endif
       
   596           return ret;
       
   597         }
       
   598     }
       
   599   while (*p++ != '\0');
       
   600   
       
   601   g_free (freeme);
       
   602 #ifdef G_OS_WIN32
       
   603   g_free ((gchar *) path_copy);
       
   604 #endif
       
   605 
       
   606   return NULL;
       
   607 }
       
   608 
       
   609 /**
       
   610  * g_parse_debug_string:
       
   611  * @string: a list of debug options separated by ':' or "all" 
       
   612  *     to set all flags.
       
   613  * @keys: pointer to an array of #GDebugKey which associate 
       
   614  *     strings with bit flags.
       
   615  * @nkeys: the number of #GDebugKey<!-- -->s in the array.
       
   616  *
       
   617  * Parses a string containing debugging options separated 
       
   618  * by ':' into a %guint containing bit flags. This is used 
       
   619  * within GDK and GTK+ to parse the debug options passed on the
       
   620  * command line or through environment variables.
       
   621  *
       
   622  * Returns: the combined set of bit flags.
       
   623  */
       
   624 EXPORT_C guint	     
       
   625 g_parse_debug_string  (const gchar     *string, 
       
   626 		       const GDebugKey *keys, 
       
   627 		       guint	        nkeys)
       
   628 {
       
   629   guint i;
       
   630   guint result = 0;
       
   631   
       
   632   g_return_val_if_fail (string != NULL, 0);
       
   633 
       
   634   /* this function is used by gmem.c/gslice.c initialization code,
       
   635    * so introducing malloc dependencies here would require adaptions
       
   636    * of those code portions.
       
   637    */
       
   638   
       
   639   if (!g_ascii_strcasecmp (string, "all"))
       
   640     {
       
   641       for (i=0; i<nkeys; i++)
       
   642 	result |= keys[i].value;
       
   643     }
       
   644   else
       
   645     {
       
   646       const gchar *p = string;
       
   647       const gchar *q;
       
   648       
       
   649       while (*p)
       
   650 	{
       
   651 	  q = strchr (p, ':');
       
   652 	  if (!q)
       
   653 	    q = p + strlen(p);
       
   654 	  
       
   655 	  for (i = 0; i < nkeys; i++)
       
   656 	    if (g_ascii_strncasecmp (keys[i].key, p, q - p) == 0 &&
       
   657 		keys[i].key[q - p] == '\0')
       
   658 	      result |= keys[i].value;
       
   659 	  
       
   660 	  p = q;
       
   661 	  if (*p == ':')
       
   662 	    p++;
       
   663 	}
       
   664     }
       
   665   
       
   666   return result;
       
   667 }
       
   668 
       
   669 /**
       
   670  * g_basename:
       
   671  * @file_name: the name of the file.
       
   672  * 
       
   673  * Gets the name of the file without any leading directory components.  
       
   674  * It returns a pointer into the given file name string.
       
   675  * 
       
   676  * Return value: the name of the file without any leading directory components.
       
   677  *
       
   678  * Deprecated:2.2: Use g_path_get_basename() instead, but notice that
       
   679  * g_path_get_basename() allocates new memory for the returned string, unlike
       
   680  * this function which returns a pointer into the argument.
       
   681  **/
       
   682 EXPORT_C G_CONST_RETURN gchar*
       
   683 g_basename (const gchar	   *file_name)
       
   684 {
       
   685   register gchar *base;
       
   686   
       
   687   g_return_val_if_fail (file_name != NULL, NULL);
       
   688   
       
   689   base = strrchr (file_name, G_DIR_SEPARATOR);
       
   690 
       
   691 #ifdef G_OS_WIN32
       
   692   {
       
   693     gchar *q = strrchr (file_name, '/');
       
   694     if (base == NULL || (q != NULL && q > base))
       
   695 	base = q;
       
   696   }
       
   697 #endif
       
   698 
       
   699   if (base)
       
   700     return base + 1;
       
   701 
       
   702 #ifdef G_OS_WIN32
       
   703   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
       
   704     return (gchar*) file_name + 2;
       
   705 #endif /* G_OS_WIN32 */
       
   706   
       
   707   return (gchar*) file_name;
       
   708 }
       
   709 
       
   710 /**
       
   711  * g_path_get_basename:
       
   712  * @file_name: the name of the file.
       
   713  *
       
   714  * Gets the last component of the filename. If @file_name ends with a 
       
   715  * directory separator it gets the component before the last slash. If 
       
   716  * @file_name consists only of directory separators (and on Windows, 
       
   717  * possibly a drive letter), a single separator is returned. If
       
   718  * @file_name is empty, it gets ".".
       
   719  *
       
   720  * Return value: a newly allocated string containing the last component of 
       
   721  *   the filename.
       
   722  */
       
   723 EXPORT_C gchar*
       
   724 g_path_get_basename (const gchar   *file_name)
       
   725 {
       
   726   register gssize base;             
       
   727   register gssize last_nonslash;    
       
   728   gsize len;    
       
   729   gchar *retval;
       
   730  
       
   731   g_return_val_if_fail (file_name != NULL, NULL);
       
   732 
       
   733   if (file_name[0] == '\0')
       
   734     /* empty string */
       
   735     return g_strdup (".");
       
   736   
       
   737   last_nonslash = strlen (file_name) - 1;
       
   738 
       
   739   while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash]))
       
   740     last_nonslash--;
       
   741 
       
   742   if (last_nonslash == -1)
       
   743     /* string only containing slashes */
       
   744     return g_strdup (G_DIR_SEPARATOR_S);
       
   745 
       
   746 #ifdef G_OS_WIN32
       
   747   if (last_nonslash == 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
       
   748     /* string only containing slashes and a drive */
       
   749     return g_strdup (G_DIR_SEPARATOR_S);
       
   750 #endif /* G_OS_WIN32 */
       
   751 
       
   752   base = last_nonslash;
       
   753 
       
   754   while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base]))
       
   755     base--;
       
   756 
       
   757 #ifdef G_OS_WIN32
       
   758   if (base == -1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
       
   759     base = 1;
       
   760 #endif /* G_OS_WIN32 */
       
   761 
       
   762   len = last_nonslash - base;
       
   763   retval = g_malloc (len + 1);
       
   764   memcpy (retval, file_name + base + 1, len);
       
   765   retval [len] = '\0';
       
   766   return retval;
       
   767 }
       
   768 
       
   769 /**
       
   770  * g_path_is_absolute:
       
   771  * @file_name: a file name.
       
   772  *
       
   773  * Returns %TRUE if the given @file_name is an absolute file name,
       
   774  * i.e. it contains a full path from the root directory such as "/usr/local"
       
   775  * on UNIX or "C:\windows" on Windows systems.
       
   776  *
       
   777  * Returns: %TRUE if @file_name is an absolute path. 
       
   778  */
       
   779 EXPORT_C gboolean
       
   780 g_path_is_absolute (const gchar *file_name)
       
   781 {
       
   782   g_return_val_if_fail (file_name != NULL, FALSE);
       
   783 
       
   784   #ifdef __SYMBIAN32__
       
   785   /* Recognize drive letter on __SYMBIAN32__ */
       
   786   if (g_ascii_isalpha (file_name[0]) && 
       
   787       file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
       
   788     return TRUE;
       
   789 #endif /* __SYMBIAN32__*/
       
   790 
       
   791   if (G_IS_DIR_SEPARATOR (file_name[0]))
       
   792     return TRUE;
       
   793 
       
   794 #ifdef G_OS_WIN32
       
   795   /* Recognize drive letter on native Windows */
       
   796   if (g_ascii_isalpha (file_name[0]) && 
       
   797       file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
       
   798     return TRUE;
       
   799 #endif /* G_OS_WIN32 */
       
   800 
       
   801   return FALSE;
       
   802 }
       
   803 
       
   804 /**
       
   805  * g_path_skip_root:
       
   806  * @file_name: a file name.
       
   807  *
       
   808  * Returns a pointer into @file_name after the root component, i.e. after
       
   809  * the "/" in UNIX or "C:\" under Windows. If @file_name is not an absolute
       
   810  * path it returns %NULL.
       
   811  *
       
   812  * Returns: a pointer into @file_name after the root component.
       
   813  */
       
   814 EXPORT_C G_CONST_RETURN gchar*
       
   815 g_path_skip_root (const gchar *file_name)
       
   816 {
       
   817   g_return_val_if_fail (file_name != NULL, NULL);
       
   818   
       
   819 #ifdef G_PLATFORM_WIN32
       
   820   /* Skip \\server\share or //server/share */
       
   821   if (G_IS_DIR_SEPARATOR (file_name[0]) &&
       
   822       G_IS_DIR_SEPARATOR (file_name[1]) &&
       
   823       file_name[2] &&
       
   824       !G_IS_DIR_SEPARATOR (file_name[2]))
       
   825     {
       
   826       gchar *p;
       
   827 
       
   828       p = strchr (file_name + 2, G_DIR_SEPARATOR);
       
   829 #ifdef G_OS_WIN32
       
   830       {
       
   831 	gchar *q = strchr (file_name + 2, '/');
       
   832 	if (p == NULL || (q != NULL && q < p))
       
   833 	  p = q;
       
   834       }
       
   835 #endif
       
   836       if (p &&
       
   837 	  p > file_name + 2 &&
       
   838 	  p[1])
       
   839 	{
       
   840 	  file_name = p + 1;
       
   841 
       
   842 	  while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0]))
       
   843 	    file_name++;
       
   844 
       
   845 	  /* Possibly skip a backslash after the share name */
       
   846 	  if (G_IS_DIR_SEPARATOR (file_name[0]))
       
   847 	    file_name++;
       
   848 
       
   849 	  return (gchar *)file_name;
       
   850 	}
       
   851     }
       
   852 #endif
       
   853   
       
   854   /* Skip initial slashes */
       
   855   if (G_IS_DIR_SEPARATOR (file_name[0]))
       
   856     {
       
   857       while (G_IS_DIR_SEPARATOR (file_name[0]))
       
   858 	file_name++;
       
   859       return (gchar *)file_name;
       
   860     }
       
   861 
       
   862 #if defined(G_OS_WIN32) || defined(__SYMBIAN32__)
       
   863   /* Skip X:\ */
       
   864   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
       
   865     return (gchar *)file_name + 3;
       
   866 #endif
       
   867 
       
   868   return NULL;
       
   869 }
       
   870 
       
   871 /**
       
   872  * g_path_get_dirname:
       
   873  * @file_name: the name of the file.
       
   874  *
       
   875  * Gets the directory components of a file name.  If the file name has no
       
   876  * directory components "." is returned.  The returned string should be
       
   877  * freed when no longer needed.
       
   878  * 
       
   879  * Returns: the directory components of the file.
       
   880  */
       
   881 EXPORT_C gchar*
       
   882 g_path_get_dirname (const gchar	   *file_name)
       
   883 {
       
   884   register gchar *base;
       
   885   register gsize len;    
       
   886   
       
   887   g_return_val_if_fail (file_name != NULL, NULL);
       
   888   
       
   889   base = strrchr (file_name, G_DIR_SEPARATOR);
       
   890 #if defined(G_OS_WIN32) || defined(__SYMBIAN32__)
       
   891   {
       
   892     gchar *q = strrchr (file_name, '/');
       
   893     if (base == NULL || (q != NULL && q > base))
       
   894 	base = q;
       
   895   }
       
   896 #endif
       
   897   if (!base)
       
   898     {
       
   899 #ifdef G_OS_WIN32
       
   900       if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
       
   901 	{
       
   902 	  gchar drive_colon_dot[4];
       
   903 
       
   904 	  drive_colon_dot[0] = file_name[0];
       
   905 	  drive_colon_dot[1] = ':';
       
   906 	  drive_colon_dot[2] = '.';
       
   907 	  drive_colon_dot[3] = '\0';
       
   908 
       
   909 	  return g_strdup (drive_colon_dot);
       
   910 	}
       
   911 #endif
       
   912     return g_strdup (".");
       
   913     }
       
   914 
       
   915   while (base > file_name && G_IS_DIR_SEPARATOR (*base))
       
   916     base--;
       
   917 
       
   918 #ifdef G_OS_WIN32
       
   919   /* base points to the char before the last slash.
       
   920    *
       
   921    * In case file_name is the root of a drive (X:\) or a child of the
       
   922    * root of a drive (X:\foo), include the slash.
       
   923    *
       
   924    * In case file_name is the root share of an UNC path
       
   925    * (\\server\share), add a slash, returning \\server\share\ .
       
   926    *
       
   927    * In case file_name is a direct child of a share in an UNC path
       
   928    * (\\server\share\foo), include the slash after the share name,
       
   929    * returning \\server\share\ .
       
   930    */
       
   931   if (base == file_name + 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
       
   932     base++;
       
   933   else if (G_IS_DIR_SEPARATOR (file_name[0]) &&
       
   934 	   G_IS_DIR_SEPARATOR (file_name[1]) &&
       
   935 	   file_name[2] &&
       
   936 	   !G_IS_DIR_SEPARATOR (file_name[2]) &&
       
   937 	   base >= file_name + 2)
       
   938     {
       
   939       const gchar *p = file_name + 2;
       
   940       while (*p && !G_IS_DIR_SEPARATOR (*p))
       
   941 	p++;
       
   942       if (p == base + 1)
       
   943 	{
       
   944 	  len = (guint) strlen (file_name) + 1;
       
   945 	  base = g_new (gchar, len + 1);
       
   946 	  strcpy (base, file_name);
       
   947 	  base[len-1] = G_DIR_SEPARATOR;
       
   948 	  base[len] = 0;
       
   949 	  return base;
       
   950 	}
       
   951       if (G_IS_DIR_SEPARATOR (*p))
       
   952 	{
       
   953 	  p++;
       
   954 	  while (*p && !G_IS_DIR_SEPARATOR (*p))
       
   955 	    p++;
       
   956 	  if (p == base + 1)
       
   957 	    base++;
       
   958 	}
       
   959     }
       
   960 #endif
       
   961 
       
   962   len = (guint) 1 + base - file_name;
       
   963   base = g_new (gchar, len + 1);
       
   964     
       
   965   g_memmove (base, file_name, len);
       
   966   base[len] = 0;
       
   967   
       
   968   return base;
       
   969 }
       
   970 
       
   971 /**
       
   972  * g_get_current_dir:
       
   973  *
       
   974  * Gets the current directory.
       
   975  * The returned string should be freed when no longer needed. The encoding 
       
   976  * of the returned string is system defined. On Windows, it is always UTF-8.
       
   977  * 
       
   978  * Returns: the current directory.
       
   979  */
       
   980 
       
   981 #if EMULATOR
       
   982 
       
   983 PLS(max_len,g_get_current_dir ,gulong)
       
   984 #define max_len (*FUNCTION_NAME(max_len,g_get_current_dir )())
       
   985 
       
   986 #endif /* EMULATOR */
       
   987 
       
   988 EXPORT_C gchar*
       
   989 g_get_current_dir (void)
       
   990 {
       
   991 #ifdef G_OS_WIN32
       
   992 
       
   993   gchar *dir = NULL;
       
   994 
       
   995   if (G_WIN32_HAVE_WIDECHAR_API ())
       
   996     {
       
   997       wchar_t dummy[2], *wdir;
       
   998       int len;
       
   999 
       
  1000       len = GetCurrentDirectoryW (2, dummy);
       
  1001       wdir = g_new (wchar_t, len);
       
  1002 
       
  1003       if (GetCurrentDirectoryW (len, wdir) == len - 1)
       
  1004 	dir = g_utf16_to_utf8 (wdir, -1, NULL, NULL, NULL);
       
  1005 
       
  1006       g_free (wdir);
       
  1007     }
       
  1008   else
       
  1009     {
       
  1010       gchar dummy[2], *cpdir;
       
  1011       int len;
       
  1012 
       
  1013       len = GetCurrentDirectoryA (2, dummy);
       
  1014       cpdir = g_new (gchar, len);            
       
  1015 
       
  1016       if (GetCurrentDirectoryA (len, cpdir) == len - 1)
       
  1017 	dir = g_locale_to_utf8 (cpdir, -1, NULL, NULL, NULL);
       
  1018 
       
  1019       g_free (cpdir);
       
  1020     }
       
  1021 
       
  1022   if (dir == NULL)
       
  1023     dir = g_strdup ("\\");
       
  1024 
       
  1025   return dir;
       
  1026 
       
  1027 #else
       
  1028 
       
  1029   gchar *buffer = NULL;
       
  1030   gchar *dir = NULL;
       
  1031 
       
  1032   #if !(EMULATOR)
       
  1033   static gulong max_len = 0;
       
  1034   #endif /* EMULATOR */
       
  1035 
       
  1036   if (max_len == 0) 
       
  1037     max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
       
  1038   
       
  1039   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
       
  1040    * and, if that wasn't bad enough, hangs in doing so.
       
  1041    */
       
  1042 #if	(defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
       
  1043   buffer = g_new (gchar, max_len + 1);
       
  1044   *buffer = 0;
       
  1045   dir = getwd (buffer);
       
  1046 #else	/* !sun || !HAVE_GETCWD */
       
  1047   while (max_len < G_MAXULONG / 2)
       
  1048     {
       
  1049       buffer = g_new (gchar, max_len + 1);
       
  1050       *buffer = 0;
       
  1051       dir = getcwd (buffer, max_len);
       
  1052 
       
  1053       if (dir || errno != ERANGE)
       
  1054 	break;
       
  1055 
       
  1056       g_free (buffer);
       
  1057       max_len *= 2;
       
  1058     }
       
  1059 #endif	/* !sun || !HAVE_GETCWD */
       
  1060   
       
  1061   if (!dir || !*buffer)
       
  1062     {
       
  1063       /* hm, should we g_error() out here?
       
  1064        * this can happen if e.g. "./" has mode \0000
       
  1065        */
       
  1066       buffer[0] = G_DIR_SEPARATOR;
       
  1067       buffer[1] = 0;
       
  1068     }
       
  1069 
       
  1070   dir = g_strdup (buffer);
       
  1071   g_free (buffer);
       
  1072   
       
  1073   return dir;
       
  1074 #endif /* !Win32 */
       
  1075 }
       
  1076 
       
  1077 #if EMULATOR
       
  1078 #undef max_len 
       
  1079 #endif /* EMULATOR */
       
  1080 
       
  1081 /**
       
  1082  * g_getenv:
       
  1083  * @variable: the environment variable to get, in the GLib file name encoding.
       
  1084  * 
       
  1085  * Returns the value of an environment variable. The name and value
       
  1086  * are in the GLib file name encoding. On UNIX, this means the actual
       
  1087  * bytes which might or might not be in some consistent character set
       
  1088  * and encoding. On Windows, it is in UTF-8. On Windows, in case the
       
  1089  * environment variable's value contains references to other
       
  1090  * environment variables, they are expanded.
       
  1091  * 
       
  1092  * Return value: the value of the environment variable, or %NULL if
       
  1093  * the environment variable is not found. The returned string may be
       
  1094  * overwritten by the next call to g_getenv(), g_setenv() or
       
  1095  * g_unsetenv().
       
  1096  **/
       
  1097 EXPORT_C G_CONST_RETURN gchar*
       
  1098 g_getenv (const gchar *variable)
       
  1099 {
       
  1100 #ifndef G_OS_WIN32
       
  1101 
       
  1102   g_return_val_if_fail (variable != NULL, NULL);
       
  1103 
       
  1104   return getenv (variable);
       
  1105 
       
  1106 #else /* G_OS_WIN32 */
       
  1107 
       
  1108   GQuark quark;
       
  1109   gchar *value;
       
  1110 
       
  1111   g_return_val_if_fail (variable != NULL, NULL);
       
  1112   g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
       
  1113 
       
  1114   /* On Windows NT, it is relatively typical that environment
       
  1115    * variables contain references to other environment variables. If
       
  1116    * so, use ExpandEnvironmentStrings(). (In an ideal world, such
       
  1117    * environment variables would be stored in the Registry as
       
  1118    * REG_EXPAND_SZ type values, and would then get automatically
       
  1119    * expanded before a program sees them. But there is broken software
       
  1120    * that stores environment variables as REG_SZ values even if they
       
  1121    * contain references to other environment variables.)
       
  1122    */
       
  1123 
       
  1124   if (G_WIN32_HAVE_WIDECHAR_API ())
       
  1125     {
       
  1126       wchar_t dummy[2], *wname, *wvalue;
       
  1127       int len;
       
  1128       
       
  1129       wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
       
  1130 
       
  1131       len = GetEnvironmentVariableW (wname, dummy, 2);
       
  1132 
       
  1133       if (len == 0)
       
  1134 	{
       
  1135 	  g_free (wname);
       
  1136 	  return NULL;
       
  1137 	}
       
  1138       else if (len == 1)
       
  1139 		len = 2;
       
  1140       wvalue = g_new (wchar_t, len);
       
  1141 
       
  1142       if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1)
       
  1143 	{
       
  1144 	  g_free (wname);
       
  1145 	  g_free (wvalue);
       
  1146 	  return NULL;
       
  1147 	}
       
  1148 
       
  1149       if (wcschr (wvalue, L'%') != NULL)
       
  1150 	{
       
  1151 	  wchar_t *tem = wvalue;
       
  1152 
       
  1153 	  len = ExpandEnvironmentStringsW (wvalue, dummy, 2);
       
  1154 
       
  1155 	  if (len > 0)
       
  1156 	    {
       
  1157 	      wvalue = g_new (wchar_t, len);
       
  1158 
       
  1159 	      if (ExpandEnvironmentStringsW (tem, wvalue, len) != len)
       
  1160 		{
       
  1161 		  g_free (wvalue);
       
  1162 		  wvalue = tem;
       
  1163 		}
       
  1164 	      else
       
  1165 		g_free (tem);
       
  1166 	    }
       
  1167 	}
       
  1168 
       
  1169       value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
       
  1170 
       
  1171       g_free (wname);
       
  1172       g_free (wvalue);
       
  1173     }
       
  1174   else
       
  1175     {
       
  1176       gchar dummy[3], *cpname, *cpvalue;
       
  1177       int len;
       
  1178       
       
  1179       cpname = g_locale_from_utf8 (variable, -1, NULL, NULL, NULL);
       
  1180 
       
  1181       g_return_val_if_fail (cpname != NULL, NULL);
       
  1182 
       
  1183       len = GetEnvironmentVariableA (cpname, dummy, 2);
       
  1184 
       
  1185       if (len == 0)
       
  1186 	{
       
  1187 	  g_free (cpname);
       
  1188 	  return NULL;
       
  1189 	}
       
  1190       else if (len == 1)
       
  1191 	len = 2;
       
  1192       cpvalue = g_new (gchar, len);
       
  1193 
       
  1194       if (GetEnvironmentVariableA (cpname, cpvalue, len) != len - 1)
       
  1195 	{
       
  1196 	  g_free (cpname);
       
  1197 	  g_free (cpvalue);
       
  1198 	  return NULL;
       
  1199 	}
       
  1200 
       
  1201       if (strchr (cpvalue, '%') != NULL)
       
  1202 	{
       
  1203 	  gchar *tem = cpvalue;
       
  1204 
       
  1205 	  len = ExpandEnvironmentStringsA (cpvalue, dummy, 3);
       
  1206 
       
  1207 	  if (len > 0)
       
  1208 	    {
       
  1209 	      cpvalue = g_new (gchar, len);
       
  1210 
       
  1211 	      if (ExpandEnvironmentStringsA (tem, cpvalue, len) != len)
       
  1212 		{
       
  1213 		  g_free (cpvalue);
       
  1214 		  cpvalue = tem;
       
  1215 		}
       
  1216 	      else
       
  1217 		g_free (tem);
       
  1218 	    }
       
  1219 	}
       
  1220 
       
  1221       value = g_locale_to_utf8 (cpvalue, -1, NULL, NULL, NULL);
       
  1222 
       
  1223       g_free (cpname);
       
  1224       g_free (cpvalue);
       
  1225     }
       
  1226 
       
  1227   quark = g_quark_from_string (value);
       
  1228   g_free (value);
       
  1229   
       
  1230   return g_quark_to_string (quark);
       
  1231 
       
  1232 #endif /* G_OS_WIN32 */
       
  1233 }
       
  1234 
       
  1235 /* _g_getenv_nomalloc
       
  1236  * this function does a getenv() without doing any kind of allocation
       
  1237  * through glib. it's suitable for chars <= 127 only (both, for the
       
  1238  * variable name and the contents) and for contents < 1024 chars in
       
  1239  * length. also, it aliases "" to a NULL return value.
       
  1240  **/
       
  1241 const gchar*
       
  1242 _g_getenv_nomalloc (const gchar *variable,
       
  1243                     gchar        buffer[1024])
       
  1244 {
       
  1245   const gchar *retval = getenv (variable);
       
  1246   if (retval && retval[0])
       
  1247     {
       
  1248       gint l = strlen (retval);
       
  1249       if (l < 1024)
       
  1250         {
       
  1251           strncpy (buffer, retval, l);
       
  1252           buffer[l] = 0;
       
  1253           return buffer;
       
  1254         }
       
  1255     }
       
  1256   return NULL;
       
  1257 }
       
  1258 
       
  1259 /**
       
  1260  * g_setenv:
       
  1261  * @variable: the environment variable to set, must not contain '='.
       
  1262  * @value: the value for to set the variable to.
       
  1263  * @overwrite: whether to change the variable if it already exists.
       
  1264  *
       
  1265  * Sets an environment variable. Both the variable's name and value
       
  1266  * should be in the GLib file name encoding. On UNIX, this means that
       
  1267  * they can be any sequence of bytes. On Windows, they should be in
       
  1268  * UTF-8.
       
  1269  *
       
  1270  * Note that on some systems, when variables are overwritten, the memory 
       
  1271  * used for the previous variables and its value isn't reclaimed.
       
  1272  *
       
  1273  * Returns: %FALSE if the environment variable couldn't be set.
       
  1274  *
       
  1275  * Since: 2.4
       
  1276  */
       
  1277 EXPORT_C gboolean
       
  1278 g_setenv (const gchar *variable, 
       
  1279 	  const gchar *value, 
       
  1280 	  gboolean     overwrite)
       
  1281 {
       
  1282 #ifndef G_OS_WIN32
       
  1283 
       
  1284   gint result;
       
  1285 #ifndef HAVE_SETENV
       
  1286   gchar *string;
       
  1287 #endif
       
  1288 
       
  1289   g_return_val_if_fail (variable != NULL, FALSE);
       
  1290   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
       
  1291 
       
  1292 #ifdef HAVE_SETENV
       
  1293   result = setenv (variable, value, overwrite);
       
  1294 #else
       
  1295   if (!overwrite && getenv (variable) != NULL)
       
  1296     return TRUE;
       
  1297   
       
  1298   /* This results in a leak when you overwrite existing
       
  1299    * settings. It would be fairly easy to fix this by keeping
       
  1300    * our own parallel array or hash table.
       
  1301    */
       
  1302   string = g_strconcat (variable, "=", value, NULL);
       
  1303   result = putenv (string);
       
  1304 #endif
       
  1305   return result == 0;
       
  1306 
       
  1307 #else /* G_OS_WIN32 */
       
  1308 
       
  1309   gboolean retval;
       
  1310 
       
  1311   g_return_val_if_fail (variable != NULL, FALSE);
       
  1312   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
       
  1313   g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE);
       
  1314   g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
       
  1315 
       
  1316   if (!overwrite && g_getenv (variable) != NULL)
       
  1317     return TRUE;
       
  1318 
       
  1319   /* We want to (if possible) set both the environment variable copy
       
  1320    * kept by the C runtime and the one kept by the system.
       
  1321    *
       
  1322    * We can't use only the C runtime's putenv or _wputenv() as that
       
  1323    * won't work for arbitrary Unicode strings in a "non-Unicode" app
       
  1324    * (with main() and not wmain()). In a "main()" app the C runtime
       
  1325    * initializes the C runtime's environment table by converting the
       
  1326    * real (wide char) environment variables to system codepage, thus
       
  1327    * breaking those that aren't representable in the system codepage.
       
  1328    *
       
  1329    * As the C runtime's putenv() will also set the system copy, we do
       
  1330    * the putenv() first, then call SetEnvironmentValueW ourselves.
       
  1331    */
       
  1332 
       
  1333   if (G_WIN32_HAVE_WIDECHAR_API ())
       
  1334     {
       
  1335       wchar_t *wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
       
  1336       wchar_t *wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL);
       
  1337       gchar *tem = g_strconcat (variable, "=", value, NULL);
       
  1338       wchar_t *wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
       
  1339       
       
  1340       g_free (tem);
       
  1341       _wputenv (wassignment);
       
  1342       g_free (wassignment);
       
  1343 
       
  1344       retval = (SetEnvironmentVariableW (wname, wvalue) != 0);
       
  1345 
       
  1346       g_free (wname);
       
  1347       g_free (wvalue);
       
  1348     }
       
  1349   else
       
  1350     {
       
  1351       /* In the non-Unicode case (Win9x), just putenv() is good
       
  1352        * enough.
       
  1353        */
       
  1354       gchar *tem = g_strconcat (variable, "=", value, NULL);
       
  1355       gchar *cpassignment = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL);
       
  1356 
       
  1357       g_free (tem);
       
  1358       
       
  1359       retval = (putenv (cpassignment) == 0);
       
  1360 
       
  1361       g_free (cpassignment);
       
  1362     }
       
  1363 
       
  1364   return retval;
       
  1365 
       
  1366 #endif /* G_OS_WIN32 */
       
  1367 }
       
  1368 
       
  1369 #ifdef HAVE__NSGETENVIRON
       
  1370 #define environ (*_NSGetEnviron())
       
  1371 #elif !defined(G_OS_WIN32)
       
  1372 
       
  1373 /* According to the Single Unix Specification, environ is not in 
       
  1374  * any system header, although unistd.h often declares it.
       
  1375  */
       
  1376 #if !defined(__SYMBIAN32__)
       
  1377 extern char **environ;
       
  1378 #endif  /* __SYMBIAN32__ */
       
  1379 #endif
       
  1380 
       
  1381 /**
       
  1382  * g_unsetenv:
       
  1383  * @variable: the environment variable to remove, must not contain '='.
       
  1384  * 
       
  1385  * Removes an environment variable from the environment.
       
  1386  *
       
  1387  * Note that on some systems, when variables are overwritten, the memory 
       
  1388  * used for the previous variables and its value isn't reclaimed.
       
  1389  * Furthermore, this function can't be guaranteed to operate in a 
       
  1390  * threadsafe way.
       
  1391  *
       
  1392  * Since: 2.4 
       
  1393  **/
       
  1394 EXPORT_C void
       
  1395 g_unsetenv (const gchar *variable)
       
  1396 {
       
  1397 #ifndef G_OS_WIN32
       
  1398 
       
  1399 #ifdef HAVE_UNSETENV
       
  1400   g_return_if_fail (variable != NULL);
       
  1401   g_return_if_fail (strchr (variable, '=') == NULL);
       
  1402 
       
  1403   unsetenv (variable);
       
  1404 #else /* !HAVE_UNSETENV */
       
  1405   int len;
       
  1406   gchar **e, **f;
       
  1407 
       
  1408   g_return_if_fail (variable != NULL);
       
  1409   g_return_if_fail (strchr (variable, '=') == NULL);
       
  1410 
       
  1411   len = strlen (variable);
       
  1412   
       
  1413   /* Mess directly with the environ array.
       
  1414    * This seems to be the only portable way to do this.
       
  1415    *
       
  1416    * Note that we remove *all* environment entries for
       
  1417    * the variable name, not just the first.
       
  1418    */
       
  1419   e = f = environ;
       
  1420   while (*e != NULL) 
       
  1421     {
       
  1422       if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=') 
       
  1423 	{
       
  1424 	  *f = *e;
       
  1425 	  f++;
       
  1426 	}
       
  1427       e++;
       
  1428     }
       
  1429   *f = NULL;
       
  1430 #endif /* !HAVE_UNSETENV */
       
  1431 
       
  1432 #else  /* G_OS_WIN32 */
       
  1433 
       
  1434   g_return_if_fail (variable != NULL);
       
  1435   g_return_if_fail (strchr (variable, '=') == NULL);
       
  1436   g_return_if_fail (g_utf8_validate (variable, -1, NULL));
       
  1437 
       
  1438   if (G_WIN32_HAVE_WIDECHAR_API ())
       
  1439     {
       
  1440       wchar_t *wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
       
  1441       gchar *tem = g_strconcat (variable, "=", NULL);
       
  1442       wchar_t *wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
       
  1443       
       
  1444       g_free (tem);
       
  1445       _wputenv (wassignment);
       
  1446       g_free (wassignment);
       
  1447 
       
  1448       SetEnvironmentVariableW (wname, NULL);
       
  1449 
       
  1450       g_free (wname);
       
  1451     }
       
  1452   else
       
  1453     {
       
  1454       /* In the non-Unicode case (Win9x), just putenv() is good
       
  1455        * enough.
       
  1456        */
       
  1457       gchar *tem = g_strconcat (variable, "=", NULL);
       
  1458       gchar *cpassignment = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL);
       
  1459 
       
  1460       g_free (tem);
       
  1461       
       
  1462       putenv (cpassignment);
       
  1463 
       
  1464       g_free (cpassignment);
       
  1465     }
       
  1466 
       
  1467 #endif /* G_OS_WIN32 */
       
  1468 }
       
  1469 
       
  1470 /**
       
  1471  * g_listenv:
       
  1472  *
       
  1473  * Gets the names of all variables set in the environment.
       
  1474  * 
       
  1475  * Returns: a %NULL-terminated list of strings which must be freed
       
  1476  * with g_strfreev().
       
  1477  *
       
  1478  * Since: 2.8
       
  1479  */
       
  1480 EXPORT_C gchar **
       
  1481 g_listenv (void)
       
  1482 {
       
  1483 #ifndef G_OS_WIN32
       
  1484   gchar **result, *eq;
       
  1485   gint len, i, j;
       
  1486 
       
  1487   len = g_strv_length (environ);
       
  1488   result = g_new0 (gchar *, len + 1);
       
  1489   
       
  1490   j = 0;
       
  1491   for (i = 0; i < len; i++)
       
  1492     {
       
  1493       eq = strchr (environ[i], '=');
       
  1494       if (eq)
       
  1495 	result[j++] = g_strndup (environ[i], eq - environ[i]);
       
  1496     }
       
  1497 
       
  1498   result[j] = NULL;
       
  1499 
       
  1500   return result;
       
  1501 #else
       
  1502   gchar **result, *eq;
       
  1503   gint len = 0, i, j;
       
  1504 
       
  1505   if (G_WIN32_HAVE_WIDECHAR_API ())
       
  1506     {
       
  1507       wchar_t *p, *q;
       
  1508 
       
  1509       p = (wchar_t *) GetEnvironmentStringsW ();
       
  1510       if (p != NULL)
       
  1511 	{
       
  1512 	  q = p;
       
  1513 	  while (*q)
       
  1514 	    {
       
  1515 	      q += wcslen (q) + 1;
       
  1516 	      len++;
       
  1517 	    }
       
  1518 	}
       
  1519       result = g_new0 (gchar *, len + 1);
       
  1520 
       
  1521       j = 0;
       
  1522       q = p;
       
  1523       while (*q)
       
  1524 	{
       
  1525 	  result[j] = g_utf16_to_utf8 (q, -1, NULL, NULL, NULL);
       
  1526 	  if (result[j] != NULL)
       
  1527 	    {
       
  1528 	      eq = strchr (result[j], '=');
       
  1529 	      if (eq && eq > result[j])
       
  1530 		{
       
  1531 		  *eq = '\0';
       
  1532 		  j++;
       
  1533 		}
       
  1534 	      else
       
  1535 		g_free (result[j]);
       
  1536 	    }
       
  1537 	  q += wcslen (q) + 1;
       
  1538 	}
       
  1539       result[j] = NULL;
       
  1540       FreeEnvironmentStringsW (p);
       
  1541     }
       
  1542   else
       
  1543     {
       
  1544       len = g_strv_length (environ);
       
  1545       result = g_new0 (gchar *, len + 1);
       
  1546       
       
  1547       j = 0;
       
  1548       for (i = 0; i < len; i++)
       
  1549 	{
       
  1550 	  result[j] = g_locale_to_utf8 (environ[i], -1, NULL, NULL, NULL);
       
  1551 	  if (result[j] != NULL)
       
  1552 	    {
       
  1553 	      eq = strchr (result[j], '=');
       
  1554 	      if (eq && eq > result[j])
       
  1555 		{
       
  1556 		  *eq = '\0';
       
  1557 		  j++;
       
  1558 		}
       
  1559 	      else
       
  1560 		g_free (result[j]);
       
  1561 	    }
       
  1562 	}
       
  1563       result[j] = NULL;
       
  1564     }
       
  1565 
       
  1566   return result;
       
  1567 #endif
       
  1568 }
       
  1569 
       
  1570 #if EMULATOR
       
  1571 
       
  1572 PLS_MACRO(g_utils_global,gutils,GStaticMutex)
       
  1573 PLS(g_tmp_dir,gutils,gchar *)
       
  1574 PLS(g_user_name,gutils,gchar *)
       
  1575 PLS(g_real_name,gutils,gchar *)
       
  1576 PLS(g_home_dir,gutils,gchar *)
       
  1577 PLS(g_host_name,gutils,gchar *)
       
  1578 
       
  1579 #define g__g_utils_global_lock (*FUNCTION_NAME_MACRO(g_utils_global,gutils)())
       
  1580 #define g_tmp_dir (*FUNCTION_NAME(g_tmp_dir,gutils)())
       
  1581 #define g_user_name (*FUNCTION_NAME(g_user_name,gutils)())
       
  1582 #define g_real_name (*FUNCTION_NAME(g_real_name,gutils)())
       
  1583 #define g_home_dir (*FUNCTION_NAME(g_home_dir,gutils)())
       
  1584 #define g_host_name (*FUNCTION_NAME(g_host_name,gutils)())
       
  1585 
       
  1586 #else
       
  1587 
       
  1588 G_LOCK_DEFINE_STATIC (g_utils_global);
       
  1589 
       
  1590 static	gchar	*g_tmp_dir = NULL;
       
  1591 static	gchar	*g_user_name = NULL;
       
  1592 static	gchar	*g_real_name = NULL;
       
  1593 static	gchar	*g_home_dir = NULL;
       
  1594 static	gchar	*g_host_name = NULL;
       
  1595 
       
  1596 #endif /* EMULATOR */
       
  1597 
       
  1598 #ifdef G_OS_WIN32
       
  1599 /* System codepage versions of the above, kept at file level so that they,
       
  1600  * too, are produced only once.
       
  1601  */
       
  1602 static	gchar	*g_tmp_dir_cp = NULL;
       
  1603 static	gchar	*g_user_name_cp = NULL;
       
  1604 static	gchar	*g_real_name_cp = NULL;
       
  1605 static	gchar	*g_home_dir_cp = NULL;
       
  1606 #endif
       
  1607 
       
  1608 #if EMULATOR
       
  1609 
       
  1610 PLS(g_user_data_dir ,gutils,gchar *)
       
  1611 PLS(g_system_data_dirs,gutils,gchar **)
       
  1612 PLS(g_user_cache_dir,gutils,gchar *)
       
  1613 PLS(g_user_config_dir,gutils,gchar *)
       
  1614 PLS(g_system_config_dirs,gutils,gchar **)
       
  1615 
       
  1616 #define g_user_data_dir  (*FUNCTION_NAME(g_user_data_dir ,gutils)())
       
  1617 #define g_system_data_dirs (*FUNCTION_NAME(g_system_data_dirs,gutils)())
       
  1618 #define g_user_cache_dir (*FUNCTION_NAME(g_user_cache_dir,gutils)())
       
  1619 #define g_user_config_dir (*FUNCTION_NAME(g_user_config_dir,gutils)())
       
  1620 #define g_system_config_dirs (*FUNCTION_NAME(g_system_config_dirs,gutils)())
       
  1621 
       
  1622 #else
       
  1623 
       
  1624 static  gchar   *g_user_data_dir = NULL;
       
  1625 static  gchar  **g_system_data_dirs = NULL;
       
  1626 static  gchar   *g_user_cache_dir = NULL;
       
  1627 static  gchar   *g_user_config_dir = NULL;
       
  1628 static  gchar  **g_system_config_dirs = NULL;
       
  1629 
       
  1630 #endif /* EMULATOR */
       
  1631 
       
  1632 #ifdef G_OS_WIN32
       
  1633 
       
  1634 static gchar *
       
  1635 get_special_folder (int csidl)
       
  1636 {
       
  1637   union {
       
  1638     char c[MAX_PATH+1];
       
  1639     wchar_t wc[MAX_PATH+1];
       
  1640   } path;
       
  1641   HRESULT hr;
       
  1642   LPITEMIDLIST pidl = NULL;
       
  1643   BOOL b;
       
  1644   gchar *retval = NULL;
       
  1645 
       
  1646   hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl);
       
  1647   if (hr == S_OK)
       
  1648     {
       
  1649       if (G_WIN32_HAVE_WIDECHAR_API ())
       
  1650 	{
       
  1651 	  b = SHGetPathFromIDListW (pidl, path.wc);
       
  1652 	  if (b)
       
  1653 	    retval = g_utf16_to_utf8 (path.wc, -1, NULL, NULL, NULL);
       
  1654 	}
       
  1655       else
       
  1656 	{
       
  1657 	  b = SHGetPathFromIDListA (pidl, path.c);
       
  1658 	  if (b)
       
  1659 	    retval = g_locale_to_utf8 (path.c, -1, NULL, NULL, NULL);
       
  1660 	}
       
  1661       CoTaskMemFree (pidl);
       
  1662     }
       
  1663   return retval;
       
  1664 }
       
  1665 
       
  1666 static char *
       
  1667 get_windows_directory_root (void)
       
  1668 {
       
  1669   char windowsdir[MAX_PATH];
       
  1670 
       
  1671   if (GetWindowsDirectory (windowsdir, sizeof (windowsdir)))
       
  1672     {
       
  1673       /* Usually X:\Windows, but in terminal server environments
       
  1674        * might be an UNC path, AFAIK.
       
  1675        */
       
  1676       char *p = (char *) g_path_skip_root (windowsdir);
       
  1677       if (G_IS_DIR_SEPARATOR (p[-1]) && p[-2] != ':')
       
  1678 	p--;
       
  1679       *p = '\0';
       
  1680       return g_strdup (windowsdir);
       
  1681     }
       
  1682   else
       
  1683     return g_strdup ("C:\\");
       
  1684 }
       
  1685 
       
  1686 #endif
       
  1687 
       
  1688 /* HOLDS: g_utils_global_lock */
       
  1689 static void
       
  1690 g_get_any_init_do (void)
       
  1691 {
       
  1692   gchar hostname[100];
       
  1693 
       
  1694   g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
       
  1695   if (!g_tmp_dir)
       
  1696     g_tmp_dir = g_strdup (g_getenv ("TMP"));
       
  1697   if (!g_tmp_dir)
       
  1698     g_tmp_dir = g_strdup (g_getenv ("TEMP"));
       
  1699 
       
  1700 #ifdef G_OS_WIN32
       
  1701   if (!g_tmp_dir)
       
  1702     g_tmp_dir = get_windows_directory_root ();
       
  1703 #else  
       
  1704 #ifdef P_tmpdir
       
  1705   if (!g_tmp_dir)
       
  1706     {
       
  1707       gsize k;    
       
  1708       g_tmp_dir = g_strdup (P_tmpdir);
       
  1709       k = strlen (g_tmp_dir);
       
  1710       if (k > 1 && G_IS_DIR_SEPARATOR (g_tmp_dir[k - 1]))
       
  1711 	g_tmp_dir[k - 1] = '\0';
       
  1712     }
       
  1713 #endif
       
  1714   
       
  1715   if (!g_tmp_dir)
       
  1716     {
       
  1717       g_tmp_dir = g_strdup ("/tmp");
       
  1718     }
       
  1719 #endif	/* !G_OS_WIN32 */
       
  1720   
       
  1721 #ifdef G_OS_WIN32
       
  1722   /* We check $HOME first for Win32, though it is a last resort for Unix
       
  1723    * where we prefer the results of getpwuid().
       
  1724    */
       
  1725   g_home_dir = g_strdup (g_getenv ("HOME"));
       
  1726 
       
  1727   /* Only believe HOME if it is an absolute path and exists */
       
  1728   if (g_home_dir)
       
  1729     {
       
  1730       if (!(g_path_is_absolute (g_home_dir) &&
       
  1731 	    g_file_test (g_home_dir, G_FILE_TEST_IS_DIR)))
       
  1732 	{
       
  1733 	  g_free (g_home_dir);
       
  1734 	  g_home_dir = NULL;
       
  1735 	}
       
  1736     }
       
  1737   
       
  1738   /* In case HOME is Unix-style (it happens), convert it to
       
  1739    * Windows style.
       
  1740    */
       
  1741   if (g_home_dir)
       
  1742     {
       
  1743       gchar *p;
       
  1744       while ((p = strchr (g_home_dir, '/')) != NULL)
       
  1745 	*p = '\\';
       
  1746     }
       
  1747 
       
  1748   if (!g_home_dir)
       
  1749     {
       
  1750       /* USERPROFILE is probably the closest equivalent to $HOME? */
       
  1751       if (g_getenv ("USERPROFILE") != NULL)
       
  1752 	g_home_dir = g_strdup (g_getenv ("USERPROFILE"));
       
  1753     }
       
  1754 
       
  1755   if (!g_home_dir)
       
  1756     g_home_dir = get_special_folder (CSIDL_PROFILE);
       
  1757   
       
  1758   if (!g_home_dir)
       
  1759     g_home_dir = get_windows_directory_root ();
       
  1760 #endif /* G_OS_WIN32 */
       
  1761   
       
  1762 #ifdef HAVE_PWD_H
       
  1763   {
       
  1764     struct passwd *pw = NULL;
       
  1765     gpointer buffer = NULL;
       
  1766     gint error;
       
  1767     gchar *logname;
       
  1768 
       
  1769 #  if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
       
  1770     struct passwd pwd;
       
  1771 #    ifdef _SC_GETPW_R_SIZE_MAX  
       
  1772     /* This reurns the maximum length */
       
  1773     glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
       
  1774     
       
  1775     if (bufsize < 0)
       
  1776       bufsize = 64;
       
  1777 #    else /* _SC_GETPW_R_SIZE_MAX */
       
  1778     glong bufsize = 64;
       
  1779 #    endif /* _SC_GETPW_R_SIZE_MAX */
       
  1780 
       
  1781     logname = (gchar *) g_getenv ("LOGNAME");
       
  1782         
       
  1783     do
       
  1784       {
       
  1785 	g_free (buffer);
       
  1786 	/* we allocate 6 extra bytes to work around a bug in 
       
  1787 	 * Mac OS < 10.3. See #156446
       
  1788 	 */
       
  1789 	buffer = g_malloc (bufsize + 6);
       
  1790 	errno = 0;
       
  1791 	
       
  1792 #    ifdef HAVE_POSIX_GETPWUID_R
       
  1793 	if (logname) {
       
  1794 	  error = getpwnam_r (logname, &pwd, buffer, bufsize, &pw);
       
  1795 	  if (!pw || (pw->pw_uid != getuid ())) {
       
  1796 	    /* LOGNAME is lying, fall back to looking up the uid */
       
  1797 	    error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
       
  1798 	  }
       
  1799 	} else {
       
  1800 	  error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
       
  1801 	}
       
  1802 	error = error < 0 ? errno : error;
       
  1803 #    else /* HAVE_NONPOSIX_GETPWUID_R */
       
  1804    /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
       
  1805 #      if defined(_AIX) || defined(__hpux)
       
  1806 	error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
       
  1807 	pw = error == 0 ? &pwd : NULL;
       
  1808 #      else /* !_AIX */
       
  1809 	if (logname) {
       
  1810 	  pw = getpwnam_r (logname, &pwd, buffer, bufsize);
       
  1811 	  if (!pw || (pw->pw_uid != getuid ())) {
       
  1812 	    /* LOGNAME is lying, fall back to looking up the uid */
       
  1813 	    pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
       
  1814 	  }
       
  1815 	} else {
       
  1816 	  pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
       
  1817 	}
       
  1818 	error = pw ? 0 : errno;
       
  1819 #      endif /* !_AIX */            
       
  1820 #    endif /* HAVE_NONPOSIX_GETPWUID_R */
       
  1821 	
       
  1822 	if (!pw)
       
  1823 	  {
       
  1824 	    /* we bail out prematurely if the user id can't be found
       
  1825 	     * (should be pretty rare case actually), or if the buffer
       
  1826 	     * should be sufficiently big and lookups are still not
       
  1827 	     * successfull.
       
  1828 	     */
       
  1829 	    if (error == 0 || error == ENOENT)
       
  1830 	      {
       
  1831 		g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
       
  1832 			   (gulong) getuid ());
       
  1833 		break;
       
  1834 	      }
       
  1835 	    if (bufsize > 32 * 1024)
       
  1836 	      {
       
  1837 		g_warning ("getpwuid_r(): failed due to: %s.",
       
  1838 			   g_strerror (error));
       
  1839 		break;
       
  1840 	      }
       
  1841 	    
       
  1842 	    bufsize *= 2;
       
  1843 	  }
       
  1844       }
       
  1845     while (!pw);
       
  1846 #  endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
       
  1847     
       
  1848     if (!pw)
       
  1849       {
       
  1850 	setpwent ();
       
  1851 	pw = getpwuid (getuid ());
       
  1852 	endpwent ();
       
  1853       }
       
  1854     if (pw)
       
  1855       {
       
  1856 	g_user_name = g_strdup (pw->pw_name);
       
  1857 
       
  1858 	if (pw->pw_gecos && *pw->pw_gecos != '\0') 
       
  1859 	  {
       
  1860 	    gchar **gecos_fields;
       
  1861 	    gchar **name_parts;
       
  1862 
       
  1863 	    /* split the gecos field and substitute '&' */
       
  1864 	    gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
       
  1865 	    name_parts = g_strsplit (gecos_fields[0], "&", 0);
       
  1866 	    pw->pw_name[0] = g_ascii_toupper (pw->pw_name[0]);
       
  1867 	    g_real_name = g_strjoinv (pw->pw_name, name_parts);
       
  1868 	    g_strfreev (gecos_fields);
       
  1869 	    g_strfreev (name_parts);
       
  1870 	  }
       
  1871 
       
  1872 	if (!g_home_dir)
       
  1873 	  g_home_dir = g_strdup (pw->pw_dir);
       
  1874       }
       
  1875     g_free (buffer);
       
  1876   }
       
  1877   
       
  1878 #else /* !HAVE_PWD_H */
       
  1879   
       
  1880 #ifdef G_OS_WIN32
       
  1881   if (G_WIN32_HAVE_WIDECHAR_API ())
       
  1882     {
       
  1883       guint len = UNLEN+1;
       
  1884       wchar_t buffer[UNLEN+1];
       
  1885       
       
  1886       if (GetUserNameW (buffer, (LPDWORD) &len))
       
  1887 	{
       
  1888 	  g_user_name = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
       
  1889 	  g_real_name = g_strdup (g_user_name);
       
  1890 	}
       
  1891     }
       
  1892   else
       
  1893     {
       
  1894       guint len = UNLEN+1;
       
  1895       char buffer[UNLEN+1];
       
  1896       
       
  1897       if (GetUserNameA (buffer, (LPDWORD) &len))
       
  1898 	{
       
  1899 	  g_user_name = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
       
  1900 	  g_real_name = g_strdup (g_user_name);
       
  1901 	}
       
  1902     }
       
  1903 #endif /* G_OS_WIN32 */
       
  1904 
       
  1905 #endif /* !HAVE_PWD_H */
       
  1906 
       
  1907 #ifndef G_OS_WIN32
       
  1908   if (!g_home_dir)
       
  1909     g_home_dir = g_strdup (g_getenv ("HOME"));
       
  1910 #endif
       
  1911 
       
  1912 #ifdef __EMX__
       
  1913   /* change '\\' in %HOME% to '/' */
       
  1914   g_strdelimit (g_home_dir, "\\",'/');
       
  1915 #endif
       
  1916   if (!g_user_name)
       
  1917     g_user_name = g_strdup ("somebody");
       
  1918   if (!g_real_name)
       
  1919     g_real_name = g_strdup ("Unknown");
       
  1920 
       
  1921   {
       
  1922 #ifndef G_OS_WIN32
       
  1923     gboolean hostname_fail = (gethostname (hostname, sizeof (hostname)) == -1);
       
  1924 #else
       
  1925     DWORD size = sizeof (hostname);
       
  1926     gboolean hostname_fail = (!GetComputerName (hostname, &size));
       
  1927 #endif
       
  1928     g_host_name = g_strdup (hostname_fail ? "localhost" : hostname);
       
  1929   }
       
  1930 
       
  1931 #ifdef G_OS_WIN32
       
  1932   g_tmp_dir_cp = g_locale_from_utf8 (g_tmp_dir, -1, NULL, NULL, NULL);
       
  1933   g_user_name_cp = g_locale_from_utf8 (g_user_name, -1, NULL, NULL, NULL);
       
  1934   g_real_name_cp = g_locale_from_utf8 (g_real_name, -1, NULL, NULL, NULL);
       
  1935 
       
  1936   if (!g_tmp_dir_cp)
       
  1937     g_tmp_dir_cp = g_strdup ("\\");
       
  1938   if (!g_user_name_cp)
       
  1939     g_user_name_cp = g_strdup ("somebody");
       
  1940   if (!g_real_name_cp)
       
  1941     g_real_name_cp = g_strdup ("Unknown");
       
  1942 
       
  1943   /* home_dir might be NULL, unlike tmp_dir, user_name and
       
  1944    * real_name.
       
  1945    */
       
  1946   if (g_home_dir)
       
  1947     g_home_dir_cp = g_locale_from_utf8 (g_home_dir, -1, NULL, NULL, NULL);
       
  1948   else
       
  1949     g_home_dir_cp = NULL;
       
  1950 #endif /* G_OS_WIN32 */
       
  1951 }
       
  1952 
       
  1953 static inline void
       
  1954 g_get_any_init (void)
       
  1955 {
       
  1956   if (!g_tmp_dir)
       
  1957     g_get_any_init_do ();
       
  1958 }
       
  1959 
       
  1960 static inline void
       
  1961 g_get_any_init_locked (void)
       
  1962 {
       
  1963   G_LOCK (g_utils_global);
       
  1964   g_get_any_init ();
       
  1965   G_UNLOCK (g_utils_global);
       
  1966 }
       
  1967 
       
  1968 
       
  1969 /**
       
  1970  * g_get_user_name:
       
  1971  *
       
  1972  * Gets the user name of the current user. The encoding of the returned
       
  1973  * string is system-defined. On UNIX, it might be the preferred file name
       
  1974  * encoding, or something else, and there is no guarantee that it is even
       
  1975  * consistent on a machine. On Windows, it is always UTF-8.
       
  1976  *
       
  1977  * Returns: the user name of the current user.
       
  1978  */
       
  1979 EXPORT_C G_CONST_RETURN gchar*
       
  1980 g_get_user_name (void)
       
  1981 {
       
  1982   g_get_any_init_locked ();
       
  1983   return g_user_name;
       
  1984 }
       
  1985 
       
  1986 /**
       
  1987  * g_get_real_name:
       
  1988  *
       
  1989  * Gets the real name of the user. This usually comes from the user's entry 
       
  1990  * in the <filename>passwd</filename> file. The encoding of the returned 
       
  1991  * string is system-defined. (On Windows, it is, however, always UTF-8.) 
       
  1992  * If the real user name cannot be determined, the string "Unknown" is 
       
  1993  * returned.
       
  1994  *
       
  1995  * Returns: the user's real name.
       
  1996  */
       
  1997 EXPORT_C G_CONST_RETURN gchar*
       
  1998 g_get_real_name (void)
       
  1999 {
       
  2000   g_get_any_init_locked ();
       
  2001   return g_real_name;
       
  2002 }
       
  2003 
       
  2004 /**
       
  2005  * g_get_home_dir:
       
  2006  *
       
  2007  * Gets the current user's home directory. 
       
  2008  *
       
  2009  * Note that in contrast to traditional UNIX tools, this function 
       
  2010  * prefers <filename>passwd</filename> entries over the <envar>HOME</envar> 
       
  2011  * environment variable.
       
  2012  *
       
  2013  * Returns: the current user's home directory.
       
  2014  */
       
  2015 EXPORT_C G_CONST_RETURN gchar*
       
  2016 g_get_home_dir (void)
       
  2017 {
       
  2018   g_get_any_init_locked ();
       
  2019   return g_home_dir;
       
  2020 }
       
  2021 
       
  2022 /**
       
  2023  * g_get_tmp_dir:
       
  2024  *
       
  2025  * Gets the directory to use for temporary files. This is found from 
       
  2026  * inspecting the environment variables <envar>TMPDIR</envar>, 
       
  2027  * <envar>TMP</envar>, and <envar>TEMP</envar> in that order. If none 
       
  2028  * of those are defined "/tmp" is returned on UNIX and "C:\" on Windows. 
       
  2029  * The encoding of the returned string is system-defined. On Windows, 
       
  2030  * it is always UTF-8. The return value is never %NULL.
       
  2031  *
       
  2032  * Returns: the directory to use for temporary files.
       
  2033  */
       
  2034 EXPORT_C G_CONST_RETURN gchar*
       
  2035 g_get_tmp_dir (void)
       
  2036 {
       
  2037   g_get_any_init_locked ();
       
  2038   return g_tmp_dir;
       
  2039 }
       
  2040 
       
  2041 /**
       
  2042  * g_get_host_name:
       
  2043  *
       
  2044  * Return a name for the machine. 
       
  2045  *
       
  2046  * The returned name is not necessarily a fully-qualified domain name,
       
  2047  * or even present in DNS or some other name service at all. It need
       
  2048  * not even be unique on your local network or site, but usually it
       
  2049  * is. Callers should not rely on the return value having any specific
       
  2050  * properties like uniqueness for security purposes. Even if the name
       
  2051  * of the machine is changed while an application is running, the
       
  2052  * return value from this function does not change. The returned
       
  2053  * string is owned by GLib and should not be modified or freed. If no
       
  2054  * name can be determined, a default fixed string "localhost" is
       
  2055  * returned.
       
  2056  *
       
  2057  * Returns: the host name of the machine.
       
  2058  *
       
  2059  * Since: 2.8
       
  2060  */
       
  2061 EXPORT_C const gchar *
       
  2062 g_get_host_name (void)
       
  2063 {
       
  2064   g_get_any_init_locked ();
       
  2065   return g_host_name;
       
  2066 }
       
  2067 
       
  2068 #if EMULATOR
       
  2069 
       
  2070 PLS_MACRO(g_prgname,gutils,GStaticMutex)
       
  2071 PLS(g_prgname,gutils,gchar *)
       
  2072 
       
  2073 #define g__g_prgname_lock (*FUNCTION_NAME_MACRO(g_prgname,gutils)())
       
  2074 #define g_prgname (*FUNCTION_NAME(g_prgname,gutils)())
       
  2075 
       
  2076 #else
       
  2077 
       
  2078 G_LOCK_DEFINE_STATIC (g_prgname);
       
  2079 static gchar *g_prgname = NULL;
       
  2080 
       
  2081 #endif /* EMULATOR */
       
  2082 
       
  2083 /**
       
  2084  * g_get_prgname:
       
  2085  *
       
  2086  * Gets the name of the program. This name should <emphasis>not</emphasis> 
       
  2087  * be localized, contrast with g_get_application_name().
       
  2088  * (If you are using GDK or GTK+ the program name is set in gdk_init(), 
       
  2089  * which is called by gtk_init(). The program name is found by taking 
       
  2090  * the last component of <literal>argv[0]</literal>.)
       
  2091  *
       
  2092  * Returns: the name of the program. The returned string belongs 
       
  2093  * to GLib and must not be modified or freed.
       
  2094  */
       
  2095 EXPORT_C gchar*
       
  2096 g_get_prgname (void)
       
  2097 {
       
  2098   gchar* retval;
       
  2099 
       
  2100   #if EMULATOR
       
  2101   #undef g_prgname
       
  2102   #endif /* EMULATOR */
       
  2103 
       
  2104   G_LOCK (g_prgname);
       
  2105 
       
  2106   #if EMULATOR
       
  2107   #define g_prgname (*FUNCTION_NAME(g_prgname,gutils)())
       
  2108   #endif /* EMULATOR */
       
  2109 
       
  2110 #ifdef G_OS_WIN32
       
  2111   if (g_prgname == NULL)
       
  2112     {
       
  2113       static gboolean beenhere = FALSE;
       
  2114 
       
  2115       if (!beenhere)
       
  2116 	{
       
  2117 	  gchar *utf8_buf = NULL;
       
  2118 
       
  2119 	  beenhere = TRUE;
       
  2120 	  if (G_WIN32_HAVE_WIDECHAR_API ())
       
  2121 	    {
       
  2122 	      wchar_t buf[MAX_PATH+1];
       
  2123 	      if (GetModuleFileNameW (GetModuleHandle (NULL),
       
  2124 				      buf, G_N_ELEMENTS (buf)) > 0)
       
  2125 		utf8_buf = g_utf16_to_utf8 (buf, -1, NULL, NULL, NULL);
       
  2126 	    }
       
  2127 	  else
       
  2128 	    {
       
  2129 	      gchar buf[MAX_PATH+1];
       
  2130 	      if (GetModuleFileNameA (GetModuleHandle (NULL),
       
  2131 				      buf, G_N_ELEMENTS (buf)) > 0)
       
  2132 		utf8_buf = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL);
       
  2133 	    }
       
  2134 	  if (utf8_buf)
       
  2135 	    {
       
  2136 	      g_prgname = g_path_get_basename (utf8_buf);
       
  2137 	      g_free (utf8_buf);
       
  2138 	    }
       
  2139 	}
       
  2140     }
       
  2141 #endif
       
  2142   retval = g_prgname;
       
  2143 
       
  2144   #if EMULATOR
       
  2145   #undef g_prgname
       
  2146   #endif /* EMULATOR */
       
  2147 
       
  2148   G_UNLOCK (g_prgname);
       
  2149 
       
  2150   #if EMULATOR
       
  2151   #define g_prgname (*FUNCTION_NAME(g_prgname,gutils)())
       
  2152   #endif /* EMULATOR */
       
  2153 
       
  2154 
       
  2155   return retval;
       
  2156 }
       
  2157 
       
  2158 /**
       
  2159  * g_set_prgname:
       
  2160  * @prgname: the name of the program.
       
  2161  *
       
  2162  * Sets the name of the program. This name should <emphasis>not</emphasis> 
       
  2163  * be localized, contrast with g_set_application_name(). Note that for 
       
  2164  * thread-safety reasons this function can only be called once.
       
  2165  */
       
  2166 EXPORT_C void
       
  2167 g_set_prgname (const gchar *prgname)
       
  2168 {
       
  2169   #if EMULATOR
       
  2170   #undef g_prgname
       
  2171   #endif /* EMULATOR */
       
  2172 
       
  2173   G_LOCK (g_prgname);
       
  2174 
       
  2175   #if EMULATOR
       
  2176   #define g_prgname (*FUNCTION_NAME(g_prgname,gutils)())
       
  2177   #endif /* EMULATOR */
       
  2178 
       
  2179   g_free (g_prgname);
       
  2180   g_prgname = g_strdup (prgname);
       
  2181 
       
  2182   #if EMULATOR
       
  2183   #undef g_prgname
       
  2184   #endif /* EMULATOR */
       
  2185 
       
  2186   G_UNLOCK (g_prgname);
       
  2187 
       
  2188   #if EMULATOR
       
  2189   #define g_prgname (*FUNCTION_NAME(g_prgname,gutils)())
       
  2190   #endif /* EMULATOR */
       
  2191 
       
  2192 }
       
  2193 
       
  2194 #if EMULATOR
       
  2195 
       
  2196 PLS_MACRO(g_application_name ,gutils,GStaticMutex)
       
  2197 PLS(g_application_name ,gutils,gchar *)
       
  2198 
       
  2199 #define g__g_application_name_lock (*FUNCTION_NAME_MACRO(g_application_name,gutils)())
       
  2200 #define g_application_name  (*FUNCTION_NAME(g_application_name ,gutils)())
       
  2201 
       
  2202 #else
       
  2203 
       
  2204 G_LOCK_DEFINE_STATIC (g_application_name);
       
  2205 static gchar *g_application_name = NULL;
       
  2206 
       
  2207 #endif /* EMULATOR */
       
  2208 
       
  2209 /**
       
  2210  * g_get_application_name:
       
  2211  * 
       
  2212  * Gets a human-readable name for the application, as set by
       
  2213  * g_set_application_name(). This name should be localized if
       
  2214  * possible, and is intended for display to the user.  Contrast with
       
  2215  * g_get_prgname(), which gets a non-localized name. If
       
  2216  * g_set_application_name() has not been called, returns the result of
       
  2217  * g_get_prgname() (which may be %NULL if g_set_prgname() has also not
       
  2218  * been called).
       
  2219  * 
       
  2220  * Return value: human-readable application name. may return %NULL
       
  2221  *
       
  2222  * Since: 2.2
       
  2223  **/
       
  2224 EXPORT_C G_CONST_RETURN gchar*
       
  2225 g_get_application_name (void)
       
  2226 {
       
  2227   gchar* retval;
       
  2228 
       
  2229   #if EMULATOR
       
  2230   #undef g_application_name
       
  2231   #endif /* EMULATOR */
       
  2232 
       
  2233   G_LOCK (g_application_name);
       
  2234 
       
  2235   #if EMULATOR
       
  2236   #define g_application_name  (*FUNCTION_NAME(g_application_name ,gutils)())
       
  2237   #endif /* EMULATOR */
       
  2238   
       
  2239   retval = g_application_name;
       
  2240 
       
  2241   #if EMULATOR
       
  2242   #undef g_application_name
       
  2243   #endif /* EMULATOR */
       
  2244 
       
  2245   G_UNLOCK (g_application_name);
       
  2246 
       
  2247   #if EMULATOR
       
  2248   #define g_application_name (*FUNCTION_NAME(g_application_name,gutils)())
       
  2249   #endif /* EMULATOR */
       
  2250 
       
  2251   if (retval == NULL)
       
  2252     return g_get_prgname ();
       
  2253   
       
  2254   return retval;
       
  2255 }
       
  2256 
       
  2257 /**
       
  2258  * g_set_application_name:
       
  2259  * @application_name: localized name of the application
       
  2260  *
       
  2261  * Sets a human-readable name for the application. This name should be
       
  2262  * localized if possible, and is intended for display to the user.
       
  2263  * Contrast with g_set_prgname(), which sets a non-localized name.
       
  2264  * g_set_prgname() will be called automatically by gtk_init(),
       
  2265  * but g_set_application_name() will not.
       
  2266  *
       
  2267  * Note that for thread safety reasons, this function can only
       
  2268  * be called once.
       
  2269  *
       
  2270  * The application name will be used in contexts such as error messages,
       
  2271  * or when displaying an application's name in the task list.
       
  2272  * 
       
  2273  **/
       
  2274 EXPORT_C void
       
  2275 g_set_application_name (const gchar *application_name)
       
  2276 {
       
  2277   gboolean already_set = FALSE;
       
  2278 	
       
  2279   #if EMULATOR
       
  2280   #undef g_application_name
       
  2281   #endif /* EMULATOR */
       
  2282 
       
  2283   G_LOCK (g_application_name);
       
  2284 
       
  2285   #if EMULATOR
       
  2286   #define g_application_name  (*FUNCTION_NAME(g_application_name ,gutils)())
       
  2287   #endif /* EMULATOR */
       
  2288   
       
  2289   if (g_application_name)
       
  2290     already_set = TRUE;
       
  2291   else
       
  2292     g_application_name = g_strdup (application_name);
       
  2293 
       
  2294   #if EMULATOR
       
  2295   #undef g_application_name
       
  2296   #endif /* EMULATOR */
       
  2297 
       
  2298   G_UNLOCK (g_application_name);
       
  2299 
       
  2300   #if EMULATOR
       
  2301   #define g_application_name  (*FUNCTION_NAME(g_application_name ,gutils)())
       
  2302   #endif /* EMULATOR */
       
  2303   
       
  2304   if (already_set)
       
  2305     g_warning ("g_set_application() name called multiple times");
       
  2306 }
       
  2307 
       
  2308 /**
       
  2309  * g_get_user_data_dir:
       
  2310  * 
       
  2311  * Returns a base directory in which to access application data such
       
  2312  * as icons that is customized for a particular user.  
       
  2313  *
       
  2314  * On UNIX platforms this is determined using the mechanisms described in
       
  2315  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
       
  2316  * XDG Base Directory Specification</ulink>
       
  2317  * 
       
  2318  * Return value: a string owned by GLib that must not be modified 
       
  2319  *               or freed.
       
  2320  * Since: 2.6
       
  2321  **/
       
  2322 EXPORT_C G_CONST_RETURN gchar*
       
  2323 g_get_user_data_dir (void)
       
  2324 {
       
  2325   gchar *data_dir;  
       
  2326 
       
  2327   G_LOCK (g_utils_global);
       
  2328 
       
  2329   if (!g_user_data_dir)
       
  2330     {
       
  2331 #ifdef G_OS_WIN32
       
  2332       data_dir = get_special_folder (CSIDL_PERSONAL);
       
  2333 #elif defined(__SYMBIAN32__)
       
  2334 	  data_dir = applicationpath();
       
  2335 	  G_UNLOCK (g_utils_global);
       
  2336 	  return data_dir;
       
  2337 #else
       
  2338       data_dir = (gchar *) g_getenv ("XDG_DATA_HOME");
       
  2339 
       
  2340       if (data_dir && data_dir[0])
       
  2341         data_dir = g_strdup (data_dir);
       
  2342 #endif
       
  2343       if (!data_dir || !data_dir[0])
       
  2344 	{
       
  2345 	  g_get_any_init ();
       
  2346 
       
  2347 	  if (g_home_dir)
       
  2348 	    data_dir = g_build_filename (g_home_dir, ".local", 
       
  2349 					 "share", NULL);
       
  2350 	  else
       
  2351 	    data_dir = g_build_filename (g_tmp_dir, g_user_name, ".local", 
       
  2352 					 "share", NULL);
       
  2353 	}
       
  2354 
       
  2355       g_user_data_dir = data_dir;
       
  2356     }
       
  2357   else
       
  2358     data_dir = g_user_data_dir;
       
  2359 
       
  2360   G_UNLOCK (g_utils_global);
       
  2361 
       
  2362   return data_dir;
       
  2363 }
       
  2364 
       
  2365 /**
       
  2366  * g_get_user_config_dir:
       
  2367  * 
       
  2368  * Returns a base directory in which to store user-specific application 
       
  2369  * configuration information such as user preferences and settings. 
       
  2370  *
       
  2371  * On UNIX platforms this is determined using the mechanisms described in
       
  2372  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
       
  2373  * XDG Base Directory Specification</ulink>
       
  2374  * 
       
  2375  * Return value: a string owned by GLib that must not be modified 
       
  2376  *               or freed.
       
  2377  * Since: 2.6
       
  2378  **/
       
  2379 EXPORT_C G_CONST_RETURN gchar*
       
  2380 g_get_user_config_dir (void)
       
  2381 {
       
  2382   gchar *config_dir;  
       
  2383 
       
  2384   G_LOCK (g_utils_global);
       
  2385 
       
  2386   if (!g_user_config_dir)
       
  2387     {
       
  2388 #ifdef G_OS_WIN32
       
  2389       config_dir = get_special_folder (CSIDL_APPDATA);
       
  2390 #elif defined(__SYMBIAN32__)
       
  2391 	  config_dir = applicationpath();
       
  2392 	  G_UNLOCK (g_utils_global);
       
  2393 	  return config_dir;
       
  2394 #else
       
  2395       config_dir = (gchar *) g_getenv ("XDG_CONFIG_HOME");
       
  2396 
       
  2397       if (config_dir && config_dir[0])
       
  2398 	config_dir = g_strdup (config_dir);
       
  2399 #endif
       
  2400       if (!config_dir || !config_dir[0])
       
  2401 	{
       
  2402 	  g_get_any_init ();
       
  2403 
       
  2404 	  if (g_home_dir)
       
  2405 	    config_dir = g_build_filename (g_home_dir, ".config", NULL);
       
  2406 	  else
       
  2407 	    config_dir = g_build_filename (g_tmp_dir, g_user_name, ".config", NULL);
       
  2408 	}
       
  2409       g_user_config_dir = config_dir;
       
  2410     }
       
  2411   else
       
  2412     config_dir = g_user_config_dir;
       
  2413 
       
  2414   G_UNLOCK (g_utils_global);
       
  2415 
       
  2416   return config_dir;
       
  2417 }
       
  2418 
       
  2419 /**
       
  2420  * g_get_user_cache_dir:
       
  2421  * 
       
  2422  * Returns a base directory in which to store non-essential, cached
       
  2423  * data specific to particular user.
       
  2424  *
       
  2425  * On UNIX platforms this is determined using the mechanisms described in
       
  2426  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
       
  2427  * XDG Base Directory Specification</ulink>
       
  2428  * 
       
  2429  * Return value: a string owned by GLib that must not be modified 
       
  2430  *               or freed.
       
  2431  * Since: 2.6
       
  2432  **/
       
  2433 EXPORT_C G_CONST_RETURN gchar*
       
  2434 g_get_user_cache_dir (void)
       
  2435 {
       
  2436   gchar *cache_dir;  
       
  2437 
       
  2438   G_LOCK (g_utils_global);
       
  2439 
       
  2440   if (!g_user_cache_dir)
       
  2441     {
       
  2442 #ifdef G_OS_WIN32
       
  2443       cache_dir = get_special_folder (CSIDL_INTERNET_CACHE); /* XXX correct? */
       
  2444 #elif defined(__SYMBIAN32__)
       
  2445 	  cache_dir = applicationpath();
       
  2446 	  G_UNLOCK (g_utils_global);
       
  2447 	  return cache_dir;
       
  2448 #else
       
  2449       cache_dir = (gchar *) g_getenv ("XDG_CACHE_HOME");
       
  2450 
       
  2451       if (cache_dir && cache_dir[0])
       
  2452           cache_dir = g_strdup (cache_dir);
       
  2453 #endif
       
  2454       if (!cache_dir || !cache_dir[0])
       
  2455 	{
       
  2456 	  g_get_any_init ();
       
  2457 	
       
  2458 	  if (g_home_dir)
       
  2459 	    cache_dir = g_build_filename (g_home_dir, ".cache", NULL);
       
  2460 	  else
       
  2461 	    cache_dir = g_build_filename (g_tmp_dir, g_user_name, ".cache", NULL);
       
  2462 	}
       
  2463       g_user_cache_dir = cache_dir;
       
  2464     }
       
  2465   else
       
  2466     cache_dir = g_user_cache_dir;
       
  2467 
       
  2468   G_UNLOCK (g_utils_global);
       
  2469 
       
  2470   return cache_dir;
       
  2471 }
       
  2472 
       
  2473 #ifdef G_OS_WIN32
       
  2474 
       
  2475 #undef g_get_system_data_dirs
       
  2476 
       
  2477 static HMODULE
       
  2478 get_module_for_address (gconstpointer address)
       
  2479 {
       
  2480   /* Holds the g_utils_global lock */
       
  2481 
       
  2482   static gboolean beenhere = FALSE;
       
  2483   typedef BOOL (WINAPI *t_GetModuleHandleExA) (DWORD, LPCTSTR, HMODULE *);
       
  2484   static t_GetModuleHandleExA p_GetModuleHandleExA = NULL;
       
  2485   HMODULE hmodule;
       
  2486 
       
  2487   if (!address)
       
  2488     return NULL;
       
  2489 
       
  2490   if (!beenhere)
       
  2491     {
       
  2492       p_GetModuleHandleExA =
       
  2493 	(t_GetModuleHandleExA) GetProcAddress (LoadLibrary ("kernel32.dll"),
       
  2494 					       "GetModuleHandleExA");
       
  2495       beenhere = TRUE;
       
  2496     }
       
  2497 
       
  2498   if (p_GetModuleHandleExA == NULL ||
       
  2499       !(*p_GetModuleHandleExA) (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
       
  2500 				GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
       
  2501 				address, &hmodule))
       
  2502     {
       
  2503       MEMORY_BASIC_INFORMATION mbi;
       
  2504       VirtualQuery (address, &mbi, sizeof (mbi));
       
  2505       hmodule = (HMODULE) mbi.AllocationBase;
       
  2506     }
       
  2507 
       
  2508   return hmodule;
       
  2509 }
       
  2510 
       
  2511 static gchar *
       
  2512 get_module_share_dir (gconstpointer address)
       
  2513 {
       
  2514   HMODULE hmodule;
       
  2515   gchar *filename = NULL;
       
  2516   gchar *p, *retval;
       
  2517 
       
  2518   hmodule = get_module_for_address (address);
       
  2519   if (hmodule == NULL)
       
  2520     return NULL;
       
  2521 
       
  2522   if (G_WIN32_IS_NT_BASED ())
       
  2523     {
       
  2524       wchar_t wfilename[MAX_PATH];
       
  2525       if (GetModuleFileNameW (hmodule, wfilename, G_N_ELEMENTS (wfilename)))
       
  2526 	filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
       
  2527     }
       
  2528   else
       
  2529     {
       
  2530       char cpfilename[MAX_PATH];
       
  2531       if (GetModuleFileNameA (hmodule, cpfilename, G_N_ELEMENTS (cpfilename)))
       
  2532 	filename = g_locale_to_utf8 (cpfilename, -1, NULL, NULL, NULL);
       
  2533     }
       
  2534 
       
  2535   if (filename == NULL)
       
  2536     return NULL;
       
  2537 
       
  2538   if ((p = strrchr (filename, G_DIR_SEPARATOR)) != NULL)
       
  2539     *p = '\0';
       
  2540 
       
  2541   p = strrchr (filename, G_DIR_SEPARATOR);
       
  2542   if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0))
       
  2543     *p = '\0';
       
  2544 
       
  2545   retval = g_build_filename (filename, "share", NULL);
       
  2546   g_free (filename);
       
  2547 
       
  2548   return retval;
       
  2549 }
       
  2550 
       
  2551 G_CONST_RETURN gchar * G_CONST_RETURN *
       
  2552 g_win32_get_system_data_dirs_for_module (gconstpointer address)
       
  2553 {
       
  2554   GArray *data_dirs;
       
  2555   HMODULE hmodule;
       
  2556   static GHashTable *per_module_data_dirs = NULL;
       
  2557   gchar **retval;
       
  2558   gchar *p;
       
  2559       
       
  2560   if (address)
       
  2561     {
       
  2562       G_LOCK (g_utils_global);
       
  2563       hmodule = get_module_for_address (address);
       
  2564       if (hmodule != NULL)
       
  2565 	{
       
  2566 	  if (per_module_data_dirs == NULL)
       
  2567 	    per_module_data_dirs = g_hash_table_new (NULL, NULL);
       
  2568 	  else
       
  2569 	    {
       
  2570 	      retval = g_hash_table_lookup (per_module_data_dirs, hmodule);
       
  2571 	      
       
  2572 	      if (retval != NULL)
       
  2573 		{
       
  2574 		  G_UNLOCK (g_utils_global);
       
  2575 		  return (G_CONST_RETURN gchar * G_CONST_RETURN *) retval;
       
  2576 		}
       
  2577 	    }
       
  2578 	}
       
  2579     }
       
  2580 
       
  2581   data_dirs = g_array_new (TRUE, TRUE, sizeof (char *));
       
  2582 
       
  2583   /* Documents and Settings\All Users\Application Data */
       
  2584   p = get_special_folder (CSIDL_COMMON_APPDATA);
       
  2585   if (p)
       
  2586     g_array_append_val (data_dirs, p);
       
  2587   
       
  2588   /* Documents and Settings\All Users\Documents */
       
  2589   p = get_special_folder (CSIDL_COMMON_DOCUMENTS);
       
  2590   if (p)
       
  2591     g_array_append_val (data_dirs, p);
       
  2592 	
       
  2593   /* Using the above subfolders of Documents and Settings perhaps
       
  2594    * makes sense from a Windows perspective.
       
  2595    *
       
  2596    * But looking at the actual use cases of this function in GTK+
       
  2597    * and GNOME software, what we really want is the "share"
       
  2598    * subdirectory of the installation directory for the package
       
  2599    * our caller is a part of.
       
  2600    *
       
  2601    * The address parameter, if non-NULL, points to a function in the
       
  2602    * calling module. Use that to determine that module's installation
       
  2603    * folder, and use its "share" subfolder.
       
  2604    *
       
  2605    * Additionally, also use the "share" subfolder of the installation
       
  2606    * locations of GLib and the .exe file being run.
       
  2607    *
       
  2608    * To guard against none of the above being what is really wanted,
       
  2609    * callers of this function should have Win32-specific code to look
       
  2610    * up their installation folder themselves, and handle a subfolder
       
  2611    * "share" of it in the same way as the folders returned from this
       
  2612    * function.
       
  2613    */
       
  2614 
       
  2615   p = get_module_share_dir (address);
       
  2616   if (p)
       
  2617     g_array_append_val (data_dirs, p);
       
  2618     
       
  2619   p = g_win32_get_package_installation_subdirectory (NULL, dll_name, "share");
       
  2620   if (p)
       
  2621     g_array_append_val (data_dirs, p);
       
  2622   
       
  2623   p = g_win32_get_package_installation_subdirectory (NULL, NULL, "share");
       
  2624   if (p)
       
  2625     g_array_append_val (data_dirs, p);
       
  2626 
       
  2627   retval = (gchar **) g_array_free (data_dirs, FALSE);
       
  2628 
       
  2629   if (address)
       
  2630     {
       
  2631       if (hmodule != NULL)
       
  2632 	g_hash_table_insert (per_module_data_dirs, hmodule, retval);
       
  2633       G_UNLOCK (g_utils_global);
       
  2634     }
       
  2635 
       
  2636   return (G_CONST_RETURN gchar * G_CONST_RETURN *) retval;
       
  2637 }
       
  2638 
       
  2639 #endif
       
  2640 
       
  2641 /**
       
  2642  * g_get_system_data_dirs:
       
  2643  * 
       
  2644  * Returns an ordered list of base directories in which to access 
       
  2645  * system-wide application data.
       
  2646  *
       
  2647  * On UNIX platforms this is determined using the mechanisms described in
       
  2648  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
       
  2649  * XDG Base Directory Specification</ulink>
       
  2650  * 
       
  2651  * On Windows the first elements in the list are the Application Data
       
  2652  * and Documents folders for All Users. (These can be determined only
       
  2653  * on Windows 2000 or later and are not present in the list on other
       
  2654  * Windows versions.) See documentation for CSIDL_COMMON_APPDATA and
       
  2655  * CSIDL_COMMON_DOCUMENTS.
       
  2656  *
       
  2657  * Then follows the "share" subfolder in the installation folder for
       
  2658  * the package containing the DLL that calls this function, if it can
       
  2659  * be determined.
       
  2660  * 
       
  2661  * Finally the list contains the "share" subfolder in the installation
       
  2662  * folder for GLib, and in the installation folder for the package the
       
  2663  * application's .exe file belongs to.
       
  2664  *
       
  2665  * The installation folders above are determined by looking up the
       
  2666  * folder where the module (DLL or EXE) in question is located. If the
       
  2667  * folder's name is "bin", its parent is used, otherwise the folder
       
  2668  * itself.
       
  2669  *
       
  2670  * Note that on Windows the returned list can vary depending on where
       
  2671  * this function is called.
       
  2672  *
       
  2673  * Return value: a %NULL-terminated array of strings owned by GLib that must 
       
  2674  *               not be modified or freed.
       
  2675  * Since: 2.6
       
  2676  **/
       
  2677 EXPORT_C G_CONST_RETURN gchar * G_CONST_RETURN * 
       
  2678 g_get_system_data_dirs (void)
       
  2679 {
       
  2680   gchar **data_dir_vector;
       
  2681 
       
  2682   G_LOCK (g_utils_global);
       
  2683 
       
  2684   if (!g_system_data_dirs)
       
  2685     {
       
  2686 #ifdef G_OS_WIN32
       
  2687       data_dir_vector = (gchar **) g_win32_get_system_data_dirs_for_module (NULL);
       
  2688 #elif defined(__SYMBIAN32__)
       
  2689 	  gchar *data_dirs = applicationpath();
       
  2690 	  data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
       
  2691 #else
       
  2692       gchar *data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
       
  2693 
       
  2694       if (!data_dirs || !data_dirs[0])
       
  2695           data_dirs = "/usr/local/share/:/usr/share/";
       
  2696 
       
  2697       data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
       
  2698 #endif
       
  2699 
       
  2700       g_system_data_dirs = data_dir_vector;
       
  2701     }
       
  2702   else
       
  2703     data_dir_vector = g_system_data_dirs;
       
  2704 
       
  2705   G_UNLOCK (g_utils_global);
       
  2706 
       
  2707   return (G_CONST_RETURN gchar * G_CONST_RETURN *) data_dir_vector;
       
  2708 }
       
  2709 
       
  2710 /**
       
  2711  * g_get_system_config_dirs:
       
  2712  * 
       
  2713  * Returns an ordered list of base directories in which to access 
       
  2714  * system-wide configuration information.
       
  2715  *
       
  2716  * On UNIX platforms this is determined using the mechanisms described in
       
  2717  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
       
  2718  * XDG Base Directory Specification</ulink>
       
  2719  * 
       
  2720  * Return value: a %NULL-terminated array of strings owned by GLib that must 
       
  2721  *               not be modified or freed.
       
  2722  * Since: 2.6
       
  2723  **/
       
  2724 EXPORT_C G_CONST_RETURN gchar * G_CONST_RETURN *
       
  2725 g_get_system_config_dirs (void)
       
  2726 {
       
  2727   gchar *conf_dirs, **conf_dir_vector;
       
  2728 
       
  2729   G_LOCK (g_utils_global);
       
  2730 
       
  2731   if (!g_system_config_dirs)
       
  2732     {
       
  2733 #ifdef G_OS_WIN32
       
  2734       conf_dirs = get_special_folder (CSIDL_COMMON_APPDATA);
       
  2735       if (conf_dirs)
       
  2736 	{
       
  2737 	  conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
       
  2738 	  g_free (conf_dirs);
       
  2739 	}
       
  2740       else
       
  2741 	{
       
  2742 	  /* Return empty list */
       
  2743 	  conf_dir_vector = g_strsplit ("", G_SEARCHPATH_SEPARATOR_S, 0);
       
  2744 	}
       
  2745 #elif defined(__SYMBIAN32__)
       
  2746 	  conf_dirs = applicationpath();
       
  2747 	  conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
       
  2748 
       
  2749 #else
       
  2750       conf_dirs = (gchar *) g_getenv ("XDG_CONFIG_DIRS");
       
  2751 
       
  2752       if (!conf_dirs || !conf_dirs[0])
       
  2753           conf_dirs = "/etc/xdg";
       
  2754 
       
  2755       conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
       
  2756 #endif
       
  2757 
       
  2758       g_system_config_dirs = conf_dir_vector;
       
  2759     }
       
  2760   else
       
  2761     conf_dir_vector = g_system_config_dirs;
       
  2762   G_UNLOCK (g_utils_global);
       
  2763 
       
  2764   return (G_CONST_RETURN gchar * G_CONST_RETURN *) conf_dir_vector;
       
  2765 }
       
  2766 
       
  2767 #ifndef G_OS_WIN32
       
  2768 
       
  2769 #if EMULATOR
       
  2770 
       
  2771 PLS(alias_table ,gutils,GHashTable *)
       
  2772 #define alias_table  (*FUNCTION_NAME(alias_table ,gutils)())
       
  2773 
       
  2774 #else
       
  2775 
       
  2776 static GHashTable *alias_table = NULL;
       
  2777 
       
  2778 #endif /* EMULATOR */
       
  2779 
       
  2780 /* read an alias file for the locales */
       
  2781 static void
       
  2782 read_aliases (gchar *file)
       
  2783 {
       
  2784   FILE *fp;
       
  2785   char buf[256];
       
  2786   
       
  2787   if (!alias_table)
       
  2788     alias_table = g_hash_table_new (g_str_hash, g_str_equal);
       
  2789   fp = fopen (file,"r");
       
  2790   if (!fp)
       
  2791     return;
       
  2792   while (fgets (buf, 256, fp))
       
  2793     {
       
  2794       char *p, *q;
       
  2795 
       
  2796       g_strstrip (buf);
       
  2797 
       
  2798       /* Line is a comment */
       
  2799       if ((buf[0] == '#') || (buf[0] == '\0'))
       
  2800 	continue;
       
  2801 
       
  2802       /* Reads first column */
       
  2803       for (p = buf, q = NULL; *p; p++) {
       
  2804 	if ((*p == '\t') || (*p == ' ') || (*p == ':')) {
       
  2805 	  *p = '\0';
       
  2806 	  q = p+1;
       
  2807 	  while ((*q == '\t') || (*q == ' ')) {
       
  2808 	    q++;
       
  2809 	  }
       
  2810 	  break;
       
  2811 	}
       
  2812       }
       
  2813       /* The line only had one column */
       
  2814       if (!q || *q == '\0')
       
  2815 	continue;
       
  2816       
       
  2817       /* Read second column */
       
  2818       for (p = q; *p; p++) {
       
  2819 	if ((*p == '\t') || (*p == ' ')) {
       
  2820 	  *p = '\0';
       
  2821 	  break;
       
  2822 	}
       
  2823       }
       
  2824 
       
  2825       /* Add to alias table if necessary */
       
  2826       if (!g_hash_table_lookup (alias_table, buf)) {
       
  2827 	g_hash_table_insert (alias_table, g_strdup (buf), g_strdup (q));
       
  2828       }
       
  2829     }
       
  2830   fclose (fp);
       
  2831 }
       
  2832 
       
  2833 #endif
       
  2834 
       
  2835 #if EMULATOR
       
  2836 
       
  2837 PLS(said_before ,unalias_lang,gboolean)
       
  2838 #define said_before  (*FUNCTION_NAME(said_before ,unalias_lang)())
       
  2839 
       
  2840 #endif /* EMULATOR */
       
  2841 
       
  2842 
       
  2843 static char *
       
  2844 unalias_lang (char *lang)
       
  2845 {
       
  2846 #ifndef G_OS_WIN32
       
  2847   char *p;
       
  2848   int i;
       
  2849 
       
  2850   if (!alias_table)
       
  2851     read_aliases ("/usr/share/locale/locale.alias");
       
  2852 
       
  2853   i = 0;
       
  2854   while ((p = g_hash_table_lookup (alias_table, lang)) && (strcmp (p, lang) != 0))
       
  2855     {
       
  2856       lang = p;
       
  2857       if (i++ == 30)
       
  2858         {
       
  2859           #if !(EMULATOR) 
       
  2860           static gboolean said_before = FALSE;
       
  2861           #endif /* EMULATOR */
       
  2862 	  if (!said_before)
       
  2863             g_warning ("Too many alias levels for a locale, "
       
  2864 		       "may indicate a loop");
       
  2865 	  said_before = TRUE;
       
  2866 	  return lang;
       
  2867 	}
       
  2868     }
       
  2869 #endif
       
  2870   return lang;
       
  2871 }
       
  2872 
       
  2873 #if EMULATOR
       
  2874 #undef said_before 
       
  2875 #endif /* EMULATOR */
       
  2876 
       
  2877 /* Mask for components of locale spec. The ordering here is from
       
  2878  * least significant to most significant
       
  2879  */
       
  2880 enum
       
  2881 {
       
  2882   COMPONENT_CODESET =   1 << 0,
       
  2883   COMPONENT_TERRITORY = 1 << 1,
       
  2884   COMPONENT_MODIFIER =  1 << 2
       
  2885 };
       
  2886 
       
  2887 /* Break an X/Open style locale specification into components
       
  2888  */
       
  2889 static guint
       
  2890 explode_locale (const gchar *locale,
       
  2891 		gchar      **language, 
       
  2892 		gchar      **territory, 
       
  2893 		gchar      **codeset, 
       
  2894 		gchar      **modifier)
       
  2895 {
       
  2896   const gchar *uscore_pos;
       
  2897   const gchar *at_pos;
       
  2898   const gchar *dot_pos;
       
  2899 
       
  2900   guint mask = 0;
       
  2901 
       
  2902   uscore_pos = strchr (locale, '_');
       
  2903   dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
       
  2904   at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
       
  2905 
       
  2906   if (at_pos)
       
  2907     {
       
  2908       mask |= COMPONENT_MODIFIER;
       
  2909       *modifier = g_strdup (at_pos);
       
  2910     }
       
  2911   else
       
  2912     at_pos = locale + strlen (locale);
       
  2913 
       
  2914   if (dot_pos)
       
  2915     {
       
  2916       mask |= COMPONENT_CODESET;
       
  2917       *codeset = g_strndup (dot_pos, at_pos - dot_pos);
       
  2918     }
       
  2919   else
       
  2920     dot_pos = at_pos;
       
  2921 
       
  2922   if (uscore_pos)
       
  2923     {
       
  2924       mask |= COMPONENT_TERRITORY;
       
  2925       *territory = g_strndup (uscore_pos, dot_pos - uscore_pos);
       
  2926     }
       
  2927   else
       
  2928     uscore_pos = dot_pos;
       
  2929 
       
  2930   *language = g_strndup (locale, uscore_pos - locale);
       
  2931 
       
  2932   return mask;
       
  2933 }
       
  2934 
       
  2935 /*
       
  2936  * Compute all interesting variants for a given locale name -
       
  2937  * by stripping off different components of the value.
       
  2938  *
       
  2939  * For simplicity, we assume that the locale is in
       
  2940  * X/Open format: language[_territory][.codeset][@modifier]
       
  2941  *
       
  2942  * TODO: Extend this to handle the CEN format (see the GNUlibc docs)
       
  2943  *       as well. We could just copy the code from glibc wholesale
       
  2944  *       but it is big, ugly, and complicated, so I'm reluctant
       
  2945  *       to do so when this should handle 99% of the time...
       
  2946  */
       
  2947 GSList *
       
  2948 _g_compute_locale_variants (const gchar *locale)
       
  2949 {
       
  2950   GSList *retval = NULL;
       
  2951 
       
  2952   gchar *language = NULL;
       
  2953   gchar *territory = NULL;
       
  2954   gchar *codeset = NULL;
       
  2955   gchar *modifier = NULL;
       
  2956 
       
  2957   guint mask;
       
  2958   guint i;
       
  2959 
       
  2960   g_return_val_if_fail (locale != NULL, NULL);
       
  2961 
       
  2962   mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
       
  2963 
       
  2964   /* Iterate through all possible combinations, from least attractive
       
  2965    * to most attractive.
       
  2966    */
       
  2967   for (i = 0; i <= mask; i++)
       
  2968     if ((i & ~mask) == 0)
       
  2969       {
       
  2970 	gchar *val = g_strconcat (language,
       
  2971 				  (i & COMPONENT_TERRITORY) ? territory : "",
       
  2972 				  (i & COMPONENT_CODESET) ? codeset : "",
       
  2973 				  (i & COMPONENT_MODIFIER) ? modifier : "",
       
  2974 				  NULL);
       
  2975 	retval = g_slist_prepend (retval, val);
       
  2976       }
       
  2977 
       
  2978   g_free (language);
       
  2979   if (mask & COMPONENT_CODESET)
       
  2980     g_free (codeset);
       
  2981   if (mask & COMPONENT_TERRITORY)
       
  2982     g_free (territory);
       
  2983   if (mask & COMPONENT_MODIFIER)
       
  2984     g_free (modifier);
       
  2985 
       
  2986   return retval;
       
  2987 }
       
  2988 
       
  2989 /* The following is (partly) taken from the gettext package.
       
  2990    Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.  */
       
  2991 
       
  2992 static const gchar *
       
  2993 guess_category_value (const gchar *category_name)
       
  2994 {
       
  2995   const gchar *retval;
       
  2996 
       
  2997   /* The highest priority value is the `LANGUAGE' environment
       
  2998      variable.  This is a GNU extension.  */
       
  2999   retval = g_getenv ("LANGUAGE");
       
  3000   if ((retval != NULL) && (retval[0] != '\0'))
       
  3001     return retval;
       
  3002 
       
  3003   /* `LANGUAGE' is not set.  So we have to proceed with the POSIX
       
  3004      methods of looking to `LC_ALL', `LC_xxx', and `LANG'.  On some
       
  3005      systems this can be done by the `setlocale' function itself.  */
       
  3006 
       
  3007   /* Setting of LC_ALL overwrites all other.  */
       
  3008   retval = g_getenv ("LC_ALL");  
       
  3009   if ((retval != NULL) && (retval[0] != '\0'))
       
  3010     return retval;
       
  3011 
       
  3012   /* Next comes the name of the desired category.  */
       
  3013   retval = g_getenv (category_name);
       
  3014   if ((retval != NULL) && (retval[0] != '\0'))
       
  3015     return retval;
       
  3016 
       
  3017   /* Last possibility is the LANG environment variable.  */
       
  3018   retval = g_getenv ("LANG");
       
  3019   if ((retval != NULL) && (retval[0] != '\0'))
       
  3020     return retval;
       
  3021 
       
  3022 #ifdef G_PLATFORM_WIN32
       
  3023   /* g_win32_getlocale() first checks for LC_ALL, LC_MESSAGES and
       
  3024    * LANG, which we already did above. Oh well. The main point of
       
  3025    * calling g_win32_getlocale() is to get the thread's locale as used
       
  3026    * by Windows and the Microsoft C runtime (in the "English_United
       
  3027    * States" format) translated into the Unixish format.
       
  3028    */
       
  3029   retval = g_win32_getlocale ();
       
  3030   if ((retval != NULL) && (retval[0] != '\0'))
       
  3031     return retval;
       
  3032 #endif  
       
  3033 
       
  3034   return NULL;
       
  3035 }
       
  3036 
       
  3037 typedef struct _GLanguageNamesCache GLanguageNamesCache;
       
  3038 
       
  3039 struct _GLanguageNamesCache {
       
  3040   gchar *languages;
       
  3041   gchar **language_names;
       
  3042 };
       
  3043 
       
  3044 static void
       
  3045 language_names_cache_free (gpointer data)
       
  3046 {
       
  3047   GLanguageNamesCache *cache = data;
       
  3048   g_free (cache->languages);
       
  3049   g_strfreev (cache->language_names);
       
  3050   g_free (cache);
       
  3051 }
       
  3052 
       
  3053 /**
       
  3054  * g_get_language_names:
       
  3055  * 
       
  3056  * Computes a list of applicable locale names, which can be used to 
       
  3057  * e.g. construct locale-dependent filenames or search paths. The returned 
       
  3058  * list is sorted from most desirable to least desirable and always contains 
       
  3059  * the default locale "C".
       
  3060  *
       
  3061  * For example, if LANGUAGE=de:en_US, then the returned list is
       
  3062  * "de", "en_US", "en", "C".
       
  3063  *
       
  3064  * This function consults the environment variables <envar>LANGUAGE</envar>, 
       
  3065  * <envar>LC_ALL</envar>, <envar>LC_MESSAGES</envar> and <envar>LANG</envar> 
       
  3066  * to find the list of locales specified by the user.
       
  3067  * 
       
  3068  * Return value: a %NULL-terminated array of strings owned by GLib 
       
  3069  *    that must not be modified or freed.
       
  3070  *
       
  3071  * Since: 2.6
       
  3072  **/
       
  3073 
       
  3074 #if EMULATOR
       
  3075 
       
  3076 PLS(cache_private ,g_get_language_names ,GStaticPrivate)
       
  3077 #define cache_private  (*FUNCTION_NAME(cache_private ,g_get_language_names )())
       
  3078 
       
  3079 #endif /* EMULATOR */
       
  3080 
       
  3081 EXPORT_C G_CONST_RETURN gchar * G_CONST_RETURN * 
       
  3082 g_get_language_names (void)
       
  3083 {
       
  3084   #if !(EMULATOR)
       
  3085   static GStaticPrivate cache_private = G_STATIC_PRIVATE_INIT;
       
  3086   #endif /*EMULATOR */
       
  3087   GLanguageNamesCache *cache = g_static_private_get (&cache_private);
       
  3088   const gchar *value;
       
  3089 
       
  3090   if (!cache)
       
  3091     {
       
  3092       cache = g_new0 (GLanguageNamesCache, 1);
       
  3093       g_static_private_set (&cache_private, cache, language_names_cache_free);
       
  3094     }
       
  3095 
       
  3096   value = guess_category_value ("LC_MESSAGES");
       
  3097   if (!value)
       
  3098     value = "C";
       
  3099 
       
  3100   if (!(cache->languages && strcmp (cache->languages, value) == 0))
       
  3101     {
       
  3102       gchar **languages;
       
  3103       gchar **alist, **a;
       
  3104       GSList *list, *l;
       
  3105       gint i;
       
  3106 
       
  3107       g_free (cache->languages);
       
  3108       g_strfreev (cache->language_names);
       
  3109       cache->languages = g_strdup (value);
       
  3110 
       
  3111       alist = g_strsplit (value, ":", 0);
       
  3112       list = NULL;
       
  3113       for (a = alist; *a; a++)
       
  3114 	{
       
  3115 	  gchar *b = unalias_lang (*a);
       
  3116 	  list = g_slist_concat (list, _g_compute_locale_variants (b));
       
  3117 	}
       
  3118       g_strfreev (alist);
       
  3119       list = g_slist_append (list, g_strdup ("C"));
       
  3120       cache->language_names = languages = g_new (gchar *, g_slist_length (list) + 1);
       
  3121       for (l = list, i = 0; l; l = l->next, i++)
       
  3122 	languages[i] = l->data;
       
  3123       languages[i] = NULL;
       
  3124 
       
  3125       g_slist_free (list);
       
  3126     }
       
  3127 
       
  3128   return (G_CONST_RETURN gchar * G_CONST_RETURN *) cache->language_names;
       
  3129 }
       
  3130 
       
  3131 #if EMULATOR
       
  3132 #undef cache_private 
       
  3133 #endif /*EMULATOR */
       
  3134 
       
  3135 /**
       
  3136  * g_direct_hash:
       
  3137  * @v: a #gpointer key
       
  3138  *
       
  3139  * Converts a gpointer to a hash value.
       
  3140  * It can be passed to g_hash_table_new() as the @hash_func parameter, 
       
  3141  * when using pointers as keys in a #GHashTable.
       
  3142  *
       
  3143  * Returns: a hash value corresponding to the key.
       
  3144  */
       
  3145 EXPORT_C guint
       
  3146 g_direct_hash (gconstpointer v)
       
  3147 {
       
  3148   return GPOINTER_TO_UINT (v);
       
  3149 }
       
  3150 
       
  3151 /**
       
  3152  * g_direct_equal:
       
  3153  * @v1: a key.
       
  3154  * @v2: a key to compare with @v1.
       
  3155  *
       
  3156  * Compares two #gpointer arguments and returns %TRUE if they are equal.
       
  3157  * It can be passed to g_hash_table_new() as the @key_equal_func
       
  3158  * parameter, when using pointers as keys in a #GHashTable.
       
  3159  * 
       
  3160  * Returns: %TRUE if the two keys match.
       
  3161  */
       
  3162 EXPORT_C gboolean
       
  3163 g_direct_equal (gconstpointer v1,
       
  3164 		gconstpointer v2)
       
  3165 {
       
  3166   return v1 == v2;
       
  3167 }
       
  3168 
       
  3169 /**
       
  3170  * g_int_equal:
       
  3171  * @v1: a pointer to a #gint key.
       
  3172  * @v2: a pointer to a #gint key to compare with @v1.
       
  3173  *
       
  3174  * Compares the two #gint values being pointed to and returns 
       
  3175  * %TRUE if they are equal.
       
  3176  * It can be passed to g_hash_table_new() as the @key_equal_func
       
  3177  * parameter, when using pointers to integers as keys in a #GHashTable.
       
  3178  * 
       
  3179  * Returns: %TRUE if the two keys match.
       
  3180  */
       
  3181 EXPORT_C gboolean
       
  3182 g_int_equal (gconstpointer v1,
       
  3183 	     gconstpointer v2)
       
  3184 {
       
  3185   return *((const gint*) v1) == *((const gint*) v2);
       
  3186 }
       
  3187 
       
  3188 /**
       
  3189  * g_int_hash:
       
  3190  * @v: a pointer to a #gint key
       
  3191  *
       
  3192  * Converts a pointer to a #gint to a hash value.
       
  3193  * It can be passed to g_hash_table_new() as the @hash_func parameter, 
       
  3194  * when using pointers to integers values as keys in a #GHashTable.
       
  3195  *
       
  3196  * Returns: a hash value corresponding to the key.
       
  3197  */
       
  3198 EXPORT_C guint
       
  3199 g_int_hash (gconstpointer v)
       
  3200 {
       
  3201   return *(const gint*) v;
       
  3202 }
       
  3203 
       
  3204 /**
       
  3205  * g_nullify_pointer:
       
  3206  * @nullify_location: the memory address of the pointer.
       
  3207  * 
       
  3208  * Set the pointer at the specified location to %NULL.
       
  3209  **/
       
  3210 EXPORT_C void
       
  3211 g_nullify_pointer (gpointer *nullify_location)
       
  3212 {
       
  3213   g_return_if_fail (nullify_location != NULL);
       
  3214 
       
  3215   *nullify_location = NULL;
       
  3216 }
       
  3217 
       
  3218 /**
       
  3219  * g_get_codeset:
       
  3220  * 
       
  3221  * Get the codeset for the current locale.
       
  3222  * 
       
  3223  * Return value: a newly allocated string containing the name
       
  3224  * of the codeset. This string must be freed with g_free().
       
  3225  **/
       
  3226 gchar *
       
  3227 g_get_codeset (void)
       
  3228 {
       
  3229   const gchar *charset;
       
  3230 
       
  3231   g_get_charset (&charset);
       
  3232 
       
  3233   return g_strdup (charset);
       
  3234 }
       
  3235 
       
  3236 /* This is called from g_thread_init(). It's used to
       
  3237  * initialize some static data in a threadsafe way.
       
  3238  */
       
  3239 void
       
  3240 _g_utils_thread_init (void)
       
  3241 {
       
  3242   g_get_language_names ();
       
  3243 }
       
  3244 
       
  3245 #ifdef ENABLE_NLS
       
  3246 
       
  3247 #include <libintl.h>    //puneetpuneet
       
  3248 
       
  3249 #ifdef G_OS_WIN32
       
  3250 
       
  3251 /**
       
  3252  * _glib_get_locale_dir:
       
  3253  *
       
  3254  * Return the path to the lib\locale subfolder of the GLib
       
  3255  * installation folder. The path is in the system codepage. We have to
       
  3256  * use system codepage as bindtextdomain() doesn't have a UTF-8
       
  3257  * interface.
       
  3258  */
       
  3259 static const gchar *
       
  3260 _glib_get_locale_dir (void)
       
  3261 {
       
  3262   gchar *dir, *cp_dir;
       
  3263   gchar *retval = NULL;
       
  3264 
       
  3265   dir = g_win32_get_package_installation_directory (GETTEXT_PACKAGE, dll_name);
       
  3266   cp_dir = g_win32_locale_filename_from_utf8 (dir);
       
  3267   g_free (dir);
       
  3268 
       
  3269   if (cp_dir)
       
  3270     {
       
  3271       /* Don't use g_build_filename() on pathnames in the system
       
  3272        * codepage. In CJK locales cp_dir might end with a double-byte
       
  3273        * character whose trailing byte is a backslash.
       
  3274        */
       
  3275       retval = g_strconcat (cp_dir, "\\lib\\locale", NULL);
       
  3276       g_free (cp_dir);
       
  3277     }
       
  3278 
       
  3279   if (retval)
       
  3280     return retval;
       
  3281   else
       
  3282     return g_strdup ("");
       
  3283 }
       
  3284 
       
  3285 #undef GLIB_LOCALE_DIR
       
  3286 #define GLIB_LOCALE_DIR _glib_get_locale_dir ()
       
  3287 
       
  3288 #endif /* G_OS_WIN32 */
       
  3289 
       
  3290 #if EMULATOR
       
  3291 
       
  3292 PLS(_glib_gettext_initialized,_glib_gettext,gboolean)
       
  3293 #define _glib_gettext_initialized (*FUNCTION_NAME(_glib_gettext_initialized,_glib_gettext)())
       
  3294 
       
  3295 #endif /* EMULATOR */
       
  3296 
       
  3297 G_CONST_RETURN gchar *
       
  3298 _glib_gettext (const gchar *str)
       
  3299 {
       
  3300   #if !(EMULATOR)
       
  3301   static gboolean _glib_gettext_initialized = FALSE;
       
  3302   #endif /* !(EMULATOR) */
       
  3303 
       
  3304   if (!_glib_gettext_initialized)
       
  3305     {
       
  3306       bindtextdomain(GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
       
  3307 #    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
       
  3308       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
       
  3309 #    endif
       
  3310       _glib_gettext_initialized = TRUE;
       
  3311     }
       
  3312   
       
  3313   return dgettext (GETTEXT_PACKAGE, str);
       
  3314 }
       
  3315 
       
  3316 #if EMULATOR
       
  3317 #undef _glib_gettext_initialized
       
  3318 #endif /* EMULATOR */
       
  3319 
       
  3320 #endif /* ENABLE_NLS */
       
  3321 
       
  3322 #ifdef G_OS_WIN32
       
  3323 
       
  3324 /* Binary compatibility versions. Not for newly compiled code. */
       
  3325 
       
  3326 #undef g_find_program_in_path
       
  3327 
       
  3328 EXPORT_C gchar*
       
  3329 g_find_program_in_path (const gchar *program)
       
  3330 {
       
  3331   gchar *utf8_program = g_locale_to_utf8 (program, -1, NULL, NULL, NULL);
       
  3332   gchar *utf8_retval = g_find_program_in_path_utf8 (utf8_program);
       
  3333   gchar *retval;
       
  3334 
       
  3335   g_free (utf8_program);
       
  3336   if (utf8_retval == NULL)
       
  3337     return NULL;
       
  3338   retval = g_locale_from_utf8 (utf8_retval, -1, NULL, NULL, NULL);
       
  3339   g_free (utf8_retval);
       
  3340 
       
  3341   return retval;
       
  3342 }
       
  3343 
       
  3344 #undef g_get_current_dir
       
  3345 
       
  3346 EXPORT_C gchar*
       
  3347 g_get_current_dir (void)
       
  3348 {
       
  3349   gchar *utf8_dir = g_get_current_dir_utf8 ();
       
  3350   gchar *dir = g_locale_from_utf8 (utf8_dir, -1, NULL, NULL, NULL);
       
  3351   g_free (utf8_dir);
       
  3352   return dir;
       
  3353 }
       
  3354 
       
  3355 #undef g_getenv
       
  3356 
       
  3357 EXPORT_C G_CONST_RETURN gchar*
       
  3358 g_getenv (const gchar *variable)
       
  3359 {
       
  3360   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
       
  3361   const gchar *utf8_value = g_getenv_utf8 (utf8_variable);
       
  3362   gchar *value;
       
  3363   GQuark quark;
       
  3364 
       
  3365   g_free (utf8_variable);
       
  3366   if (!utf8_value)
       
  3367     return NULL;
       
  3368   value = g_locale_from_utf8 (utf8_value, -1, NULL, NULL, NULL);
       
  3369   quark = g_quark_from_string (value);
       
  3370   g_free (value);
       
  3371 
       
  3372   return g_quark_to_string (quark);
       
  3373 }
       
  3374 
       
  3375 #undef g_setenv
       
  3376 
       
  3377 EXPORT_C gboolean
       
  3378 g_setenv (const gchar *variable, 
       
  3379 	  const gchar *value, 
       
  3380 	  gboolean     overwrite)
       
  3381 {
       
  3382   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
       
  3383   gchar *utf8_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
       
  3384   gboolean retval = g_setenv_utf8 (utf8_variable, utf8_value, overwrite);
       
  3385 
       
  3386   g_free (utf8_variable);
       
  3387   g_free (utf8_value);
       
  3388 
       
  3389   return retval;
       
  3390 }
       
  3391 
       
  3392 #undef g_unsetenv
       
  3393 
       
  3394 EXPORT_C void
       
  3395 g_unsetenv (const gchar *variable)
       
  3396 {
       
  3397   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
       
  3398 
       
  3399   g_unsetenv_utf8 (utf8_variable);
       
  3400 
       
  3401   g_free (utf8_variable);
       
  3402 }
       
  3403 
       
  3404 #undef g_get_user_name
       
  3405 
       
  3406 EXPORT_C G_CONST_RETURN gchar*
       
  3407 g_get_user_name (void)
       
  3408 {
       
  3409   g_get_any_init_locked ();
       
  3410   return g_user_name_cp;
       
  3411 }
       
  3412 
       
  3413 #undef g_get_real_name
       
  3414 
       
  3415 EXPORT_C G_CONST_RETURN gchar*
       
  3416 g_get_real_name (void)
       
  3417 {
       
  3418   g_get_any_init_locked ();
       
  3419   return g_real_name_cp;
       
  3420 }
       
  3421 
       
  3422 #undef g_get_home_dir
       
  3423 
       
  3424 EXPORT_C G_CONST_RETURN gchar*
       
  3425 g_get_home_dir (void)
       
  3426 {
       
  3427   g_get_any_init_locked ();
       
  3428   return g_home_dir_cp;
       
  3429 }
       
  3430 
       
  3431 #undef g_get_tmp_dir
       
  3432 
       
  3433 EXPORT_C G_CONST_RETURN gchar*
       
  3434 g_get_tmp_dir (void)
       
  3435 {
       
  3436   g_get_any_init_locked ();
       
  3437   return g_tmp_dir_cp;
       
  3438 }
       
  3439 
       
  3440 #endif
       
  3441 
       
  3442 #define __G_UTILS_C__
       
  3443 #include "galiasdef.c"