1cb2613defe3e5da2a61b365cc2702253c54c52a
[platform/upstream/glib.git] / glib / gutils.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* 
28  * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
29  */
30
31 #include "config.h"
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <locale.h>
40 #include <string.h>
41 #include <errno.h>
42 #ifdef HAVE_PWD_H
43 #include <pwd.h>
44 #endif
45 #include <sys/types.h>
46 #ifdef HAVE_SYS_PARAM_H
47 #include <sys/param.h>
48 #endif
49
50 /* implement gutils's inline functions
51  */
52 #define G_IMPLEMENT_INLINES 1
53 #define __G_UTILS_C__
54 #include "galias.h"
55 #include "glib.h"
56 #include "gprintfint.h"
57 #include "gthreadinit.h"
58
59 #ifdef  MAXPATHLEN
60 #define G_PATH_LENGTH   MAXPATHLEN
61 #elif   defined (PATH_MAX)
62 #define G_PATH_LENGTH   PATH_MAX
63 #elif   defined (_PC_PATH_MAX)
64 #define G_PATH_LENGTH   sysconf(_PC_PATH_MAX)
65 #else   
66 #define G_PATH_LENGTH   2048
67 #endif
68
69 #ifdef G_PLATFORM_WIN32
70 #  define STRICT                /* Strict typing, please */
71 #  include <windows.h>
72 #  undef STRICT
73 #  include <lmcons.h>           /* For UNLEN */
74 #endif /* G_PLATFORM_WIN32 */
75
76 #ifdef G_OS_WIN32
77 #  include <direct.h>
78 #  include <shlobj.h>
79    /* older SDK (e.g. msvc 5.0) does not have these*/
80 #  ifndef CSIDL_INTERNET_CACHE
81 #    define CSIDL_INTERNET_CACHE 32
82 #  endif
83 #  ifndef CSIDL_COMMON_APPDATA
84 #    define CSIDL_COMMON_APPDATA 35
85 #  endif
86 #  ifndef CSIDL_COMMON_DOCUMENTS
87 #    define CSIDL_COMMON_DOCUMENTS 46
88 #  endif
89 #  ifndef CSIDL_PROFILE
90 #    define CSIDL_PROFILE 40
91 #  endif
92 #endif
93
94 #ifdef HAVE_CODESET
95 #include <langinfo.h>
96 #endif
97
98 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
99 #include <libintl.h>
100 #endif
101
102 const guint glib_major_version = GLIB_MAJOR_VERSION;
103 const guint glib_minor_version = GLIB_MINOR_VERSION;
104 const guint glib_micro_version = GLIB_MICRO_VERSION;
105 const guint glib_interface_age = GLIB_INTERFACE_AGE;
106 const guint glib_binary_age = GLIB_BINARY_AGE;
107
108 /**
109  * glib_check_version:
110  * @required_major: the required major version.
111  * @required_minor: the required major version.
112  * @required_micro: the required major version.
113  *
114  * Checks that the GLib library in use is compatible with the
115  * given version. Generally you would pass in the constants
116  * #GLIB_MAJOR_VERSION, #GLIB_MINOR_VERSION, #GLIB_MICRO_VERSION
117  * as the three arguments to this function; that produces
118  * a check that the library in use is compatible with
119  * the version of GLib the application or module was compiled
120  * against.
121  *
122  * Compatibility is defined by two things: first the version
123  * of the running library is newer than the version
124  * @required_major.required_minor.@required_micro. Second
125  * the running library must be binary compatible with the
126  * version @required_major.required_minor.@required_micro
127  * (same major version.)
128  *
129  * Return value: %NULL if the GLib library is compatible with the
130  *   given version, or a string describing the version mismatch.
131  *   The returned string is owned by GLib and must not be modified
132  *   or freed.
133  *
134  * Since: 2.6
135  **/
136 const gchar *
137 glib_check_version (guint required_major,
138                     guint required_minor,
139                     guint required_micro)
140 {
141   gint glib_effective_micro = 100 * GLIB_MINOR_VERSION + GLIB_MICRO_VERSION;
142   gint required_effective_micro = 100 * required_minor + required_micro;
143
144   if (required_major > GLIB_MAJOR_VERSION)
145     return "GLib version too old (major mismatch)";
146   if (required_major < GLIB_MAJOR_VERSION)
147     return "GLib version too new (major mismatch)";
148   if (required_effective_micro < glib_effective_micro - GLIB_BINARY_AGE)
149     return "GLib version too new (micro mismatch)";
150   if (required_effective_micro > glib_effective_micro)
151     return "GLib version too old (micro mismatch)";
152   return NULL;
153 }
154
155 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
156 /**
157  * g_memmove: 
158  * @dest: the destination address to copy the bytes to.
159  * @src: the source address to copy the bytes from.
160  * @len: the number of bytes to copy.
161  *
162  * Copies a block of memory @len bytes long, from @src to @dest.
163  * The source and destination areas may overlap.
164  *
165  * In order to use this function, you must include 
166  * <filename>string.h</filename> yourself, because this macro will 
167  * typically simply resolve to memmove() and GLib does not include 
168  * <filename>string.h</filename> for you.
169  */
170 void 
171 g_memmove (gpointer      dest, 
172            gconstpointer src, 
173            gulong        len)
174 {
175   gchar* destptr = dest;
176   const gchar* srcptr = src;
177   if (src + len < dest || dest + len < src)
178     {
179       bcopy (src, dest, len);
180       return;
181     }
182   else if (dest <= src)
183     {
184       while (len--)
185         *(destptr++) = *(srcptr++);
186     }
187   else
188     {
189       destptr += len;
190       srcptr += len;
191       while (len--)
192         *(--destptr) = *(--srcptr);
193     }
194 }
195 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
196
197 /**
198  * g_atexit:
199  * @func: the function to call on normal program termination.
200  * 
201  * Specifies a function to be called at normal program termination.
202  */
203 void
204 g_atexit (GVoidFunc func)
205 {
206   gint result;
207   const gchar *error = NULL;
208
209   /* keep this in sync with glib.h */
210
211 #ifdef  G_NATIVE_ATEXIT
212   result = ATEXIT (func);
213   if (result)
214     error = g_strerror (errno);
215 #elif defined (HAVE_ATEXIT)
216 #  ifdef NeXT /* @#%@! NeXTStep */
217   result = !atexit ((void (*)(void)) func);
218   if (result)
219     error = g_strerror (errno);
220 #  else
221   result = atexit ((void (*)(void)) func);
222   if (result)
223     error = g_strerror (errno);
224 #  endif /* NeXT */
225 #elif defined (HAVE_ON_EXIT)
226   result = on_exit ((void (*)(int, void *)) func, NULL);
227   if (result)
228     error = g_strerror (errno);
229 #else
230   result = 0;
231   error = "no implementation";
232 #endif /* G_NATIVE_ATEXIT */
233
234   if (error)
235     g_error ("Could not register atexit() function: %s", error);
236 }
237
238 /* Based on execvp() from GNU Libc.
239  * Some of this code is cut-and-pasted into gspawn.c
240  */
241
242 static gchar*
243 my_strchrnul (const gchar *str, 
244               gchar        c)
245 {
246   gchar *p = (gchar*)str;
247   while (*p && (*p != c))
248     ++p;
249
250   return p;
251 }
252
253 #ifdef G_OS_WIN32
254
255 static gchar *inner_find_program_in_path (const gchar *program);
256
257 gchar*
258 g_find_program_in_path (const gchar *program)
259 {
260   const gchar *last_dot = strrchr (program, '.');
261
262   if (last_dot == NULL ||
263       strchr (last_dot, '\\') != NULL ||
264       strchr (last_dot, '/') != NULL)
265     {
266       const gint program_length = strlen (program);
267       gchar *pathext = g_build_path (";",
268                                      ".exe;.cmd;.bat;.com",
269                                      g_getenv ("PATHEXT"),
270                                      NULL);
271       gchar *p;
272       gchar *decorated_program;
273       gchar *retval;
274
275       p = pathext;
276       do
277         {
278           gchar *q = my_strchrnul (p, ';');
279
280           decorated_program = g_malloc (program_length + (q-p) + 1);
281           memcpy (decorated_program, program, program_length);
282           memcpy (decorated_program+program_length, p, q-p);
283           decorated_program [program_length + (q-p)] = '\0';
284           
285           retval = inner_find_program_in_path (decorated_program);
286           g_free (decorated_program);
287
288           if (retval != NULL)
289             {
290               g_free (pathext);
291               return retval;
292             }
293           p = q;
294         } while (*p++ != '\0');
295       g_free (pathext);
296       return NULL;
297     }
298   else
299     return inner_find_program_in_path (program);
300 }
301
302 #endif
303
304 /**
305  * g_find_program_in_path:
306  * @program: a program name in the GLib file name encoding
307  * 
308  * Locates the first executable named @program in the user's path, in the
309  * same way that execvp() would locate it. Returns an allocated string
310  * with the absolute path name, or %NULL if the program is not found in
311  * the path. If @program is already an absolute path, returns a copy of
312  * @program if @program exists and is executable, and %NULL otherwise.
313  *  
314  * On Windows, if @program does not have a file type suffix, tries
315  * with the suffixes .exe, .cmd, .bat and .com, and the suffixes in
316  * the <envar>PATHEXT</envar> environment variable. 
317  * 
318  * On Windows, it looks for the file in the same way as CreateProcess() 
319  * would. This means first in the directory where the executing
320  * program was loaded from, then in the current directory, then in the
321  * Windows 32-bit system directory, then in the Windows directory, and
322  * finally in the directories in the <envar>PATH</envar> environment 
323  * variable. If the program is found, the return value contains the 
324  * full name including the type suffix.
325  *
326  * Return value: absolute path, or %NULL
327  **/
328 #ifdef G_OS_WIN32
329 static gchar *
330 inner_find_program_in_path (const gchar *program)
331 #else
332 gchar*
333 g_find_program_in_path (const gchar *program)
334 #endif
335 {
336   const gchar *path, *p;
337   gchar *name, *freeme;
338 #ifdef G_OS_WIN32
339   const gchar *path_copy;
340   gchar *filename = NULL, *appdir = NULL;
341   gchar *sysdir = NULL, *windir = NULL;
342 #endif
343   size_t len;
344   size_t pathlen;
345
346   g_return_val_if_fail (program != NULL, NULL);
347
348   /* If it is an absolute path, or a relative path including subdirectories,
349    * don't look in PATH.
350    */
351   if (g_path_is_absolute (program)
352       || strchr (program, G_DIR_SEPARATOR) != NULL
353 #ifdef G_OS_WIN32
354       || strchr (program, '/') != NULL
355 #endif
356       )
357     {
358       if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE) &&
359           !g_file_test (program, G_FILE_TEST_IS_DIR))
360         return g_strdup (program);
361       else
362         return NULL;
363     }
364   
365   path = g_getenv ("PATH");
366 #ifdef G_OS_UNIX
367   if (path == NULL)
368     {
369       /* There is no `PATH' in the environment.  The default
370        * search path in GNU libc is the current directory followed by
371        * the path `confstr' returns for `_CS_PATH'.
372        */
373       
374       /* In GLib we put . last, for security, and don't use the
375        * unportable confstr(); UNIX98 does not actually specify
376        * what to search if PATH is unset. POSIX may, dunno.
377        */
378       
379       path = "/bin:/usr/bin:.";
380     }
381 #else
382   if (G_WIN32_HAVE_WIDECHAR_API ())
383     {
384       int n;
385       wchar_t wfilename[MAXPATHLEN], wsysdir[MAXPATHLEN],
386         wwindir[MAXPATHLEN];
387       
388       n = GetModuleFileNameW (NULL, wfilename, MAXPATHLEN);
389       if (n > 0 && n < MAXPATHLEN)
390         filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
391       
392       n = GetSystemDirectoryW (wsysdir, MAXPATHLEN);
393       if (n > 0 && n < MAXPATHLEN)
394         sysdir = g_utf16_to_utf8 (wsysdir, -1, NULL, NULL, NULL);
395       
396       n = GetWindowsDirectoryW (wwindir, MAXPATHLEN);
397       if (n > 0 && n < MAXPATHLEN)
398         windir = g_utf16_to_utf8 (wwindir, -1, NULL, NULL, NULL);
399     }
400   else
401     {
402       int n;
403       gchar cpfilename[MAXPATHLEN], cpsysdir[MAXPATHLEN],
404         cpwindir[MAXPATHLEN];
405       
406       n = GetModuleFileNameA (NULL, cpfilename, MAXPATHLEN);
407       if (n > 0 && n < MAXPATHLEN)
408         filename = g_locale_to_utf8 (cpfilename, -1, NULL, NULL, NULL);
409       
410       n = GetSystemDirectoryA (cpsysdir, MAXPATHLEN);
411       if (n > 0 && n < MAXPATHLEN)
412         sysdir = g_locale_to_utf8 (cpsysdir, -1, NULL, NULL, NULL);
413       
414       n = GetWindowsDirectoryA (cpwindir, MAXPATHLEN);
415       if (n > 0 && n < MAXPATHLEN)
416         windir = g_locale_to_utf8 (cpwindir, -1, NULL, NULL, NULL);
417     }
418   
419   if (filename)
420     {
421       appdir = g_path_get_dirname (filename);
422       g_free (filename);
423     }
424   
425   path = g_strdup (path);
426
427   if (windir)
428     {
429       const gchar *tem = path;
430       path = g_strconcat (windir, ";", path, NULL);
431       g_free ((gchar *) tem);
432       g_free (windir);
433     }
434   
435   if (sysdir)
436     {
437       const gchar *tem = path;
438       path = g_strconcat (sysdir, ";", path, NULL);
439       g_free ((gchar *) tem);
440       g_free (sysdir);
441     }
442   
443   {
444     const gchar *tem = path;
445     path = g_strconcat (".;", path, NULL);
446     g_free ((gchar *) tem);
447   }
448   
449   if (appdir)
450     {
451       const gchar *tem = path;
452       path = g_strconcat (appdir, ";", path, NULL);
453       g_free ((gchar *) tem);
454       g_free (appdir);
455     }
456
457   path_copy = path;
458 #endif
459   
460   len = strlen (program) + 1;
461   pathlen = strlen (path);
462   freeme = name = g_malloc (pathlen + len + 1);
463   
464   /* Copy the file name at the top, including '\0'  */
465   memcpy (name + pathlen + 1, program, len);
466   name = name + pathlen;
467   /* And add the slash before the filename  */
468   *name = G_DIR_SEPARATOR;
469   
470   p = path;
471   do
472     {
473       char *startp;
474
475       path = p;
476       p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR);
477
478       if (p == path)
479         /* Two adjacent colons, or a colon at the beginning or the end
480          * of `PATH' means to search the current directory.
481          */
482         startp = name + 1;
483       else
484         startp = memcpy (name - (p - path), path, p - path);
485
486       if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE) &&
487           !g_file_test (startp, G_FILE_TEST_IS_DIR))
488         {
489           gchar *ret;
490           ret = g_strdup (startp);
491           g_free (freeme);
492 #ifdef G_OS_WIN32
493           g_free ((gchar *) path_copy);
494 #endif
495           return ret;
496         }
497     }
498   while (*p++ != '\0');
499   
500   g_free (freeme);
501 #ifdef G_OS_WIN32
502   g_free ((gchar *) path_copy);
503 #endif
504
505   return NULL;
506 }
507
508 /**
509  * g_parse_debug_string:
510  * @string: a list of debug options separated by ':' or "all" 
511  *     to set all flags.
512  * @keys: pointer to an array of #GDebugKey which associate 
513  *     strings with bit flags.
514  * @nkeys: the number of #GDebugKey<!-- -->s in the array.
515  *
516  * Parses a string containing debugging options separated 
517  * by ':' into a %guint containing bit flags. This is used 
518  * within GDK and GTK+ to parse the debug options passed on the
519  * command line or through environment variables.
520  *
521  * Returns: the combined set of bit flags.
522  */
523 guint        
524 g_parse_debug_string  (const gchar     *string, 
525                        const GDebugKey *keys, 
526                        guint            nkeys)
527 {
528   guint i;
529   guint result = 0;
530   
531   g_return_val_if_fail (string != NULL, 0);
532   
533   if (!g_ascii_strcasecmp (string, "all"))
534     {
535       for (i=0; i<nkeys; i++)
536         result |= keys[i].value;
537     }
538   else
539     {
540       const gchar *p = string;
541       const gchar *q;
542       gboolean done = FALSE;
543       
544       while (*p && !done)
545         {
546           q = strchr (p, ':');
547           if (!q)
548             {
549               q = p + strlen(p);
550               done = TRUE;
551             }
552           
553           for (i=0; i<nkeys; i++)
554             if (g_ascii_strncasecmp (keys[i].key, p, q - p) == 0 &&
555                 keys[i].key[q - p] == '\0')
556               result |= keys[i].value;
557           
558           p = q + 1;
559         }
560     }
561   
562   return result;
563 }
564
565 /**
566  * g_basename:
567  * @file_name: the name of the file.
568  * 
569  * Gets the name of the file without any leading directory components.  
570  * It returns a pointer into the given file name string.
571  * 
572  * Return value: the name of the file without any leading directory components.
573  *
574  * Deprecated: Use g_path_get_basename() instead, but notice that
575  * g_path_get_basename() allocates new memory for the returned string, unlike
576  * this function which returns a pointer into the argument.
577  **/
578 G_CONST_RETURN gchar*
579 g_basename (const gchar    *file_name)
580 {
581   register gchar *base;
582   
583   g_return_val_if_fail (file_name != NULL, NULL);
584   
585   base = strrchr (file_name, G_DIR_SEPARATOR);
586
587 #ifdef G_OS_WIN32
588   {
589     gchar *q = strrchr (file_name, '/');
590     if (base == NULL || (q != NULL && q > base))
591         base = q;
592   }
593 #endif
594
595   if (base)
596     return base + 1;
597
598 #ifdef G_OS_WIN32
599   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
600     return (gchar*) file_name + 2;
601 #endif /* G_OS_WIN32 */
602   
603   return (gchar*) file_name;
604 }
605
606 /**
607  * g_path_get_basename:
608  * @file_name: the name of the file.
609  *
610  * Gets the last component of the filename. If @file_name ends with a 
611  * directory separator it gets the component before the last slash. If 
612  * @file_name consists only of directory separators (and on Windows, 
613  * possibly a drive letter), a single separator is returned. If
614  * @file_name is empty, it gets ".".
615  *
616  * Return value: a newly allocated string containing the last component of 
617  *   the filename.
618  */
619 gchar*
620 g_path_get_basename (const gchar   *file_name)
621 {
622   register gssize base;             
623   register gssize last_nonslash;    
624   gsize len;    
625   gchar *retval;
626  
627   g_return_val_if_fail (file_name != NULL, NULL);
628
629   if (file_name[0] == '\0')
630     /* empty string */
631     return g_strdup (".");
632   
633   last_nonslash = strlen (file_name) - 1;
634
635   while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash]))
636     last_nonslash--;
637
638   if (last_nonslash == -1)
639     /* string only containing slashes */
640     return g_strdup (G_DIR_SEPARATOR_S);
641
642 #ifdef G_OS_WIN32
643   if (last_nonslash == 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
644     /* string only containing slashes and a drive */
645     return g_strdup (G_DIR_SEPARATOR_S);
646 #endif /* G_OS_WIN32 */
647
648   base = last_nonslash;
649
650   while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base]))
651     base--;
652
653 #ifdef G_OS_WIN32
654   if (base == -1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
655     base = 1;
656 #endif /* G_OS_WIN32 */
657
658   len = last_nonslash - base;
659   retval = g_malloc (len + 1);
660   memcpy (retval, file_name + base + 1, len);
661   retval [len] = '\0';
662   return retval;
663 }
664
665 /**
666  * g_path_is_absolute:
667  * @file_name: a file name.
668  *
669  * Returns %TRUE if the given @file_name is an absolute file name,
670  * i.e. it contains a full path from the root directory such as "/usr/local"
671  * on UNIX or "C:\windows" on Windows systems.
672  *
673  * Returns: %TRUE if @file_name is an absolute path. 
674  */
675 gboolean
676 g_path_is_absolute (const gchar *file_name)
677 {
678   g_return_val_if_fail (file_name != NULL, FALSE);
679   
680   if (G_IS_DIR_SEPARATOR (file_name[0]))
681     return TRUE;
682
683 #ifdef G_OS_WIN32
684   /* Recognize drive letter on native Windows */
685   if (g_ascii_isalpha (file_name[0]) && 
686       file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
687     return TRUE;
688 #endif /* G_OS_WIN32 */
689
690   return FALSE;
691 }
692
693 /**
694  * g_path_skip_root:
695  * @file_name: a file name.
696  *
697  * Returns a pointer into @file_name after the root component, i.e. after
698  * the "/" in UNIX or "C:\" under Windows. If @file_name is not an absolute
699  * path it returns %NULL.
700  *
701  * Returns: a pointer into @file_name after the root component.
702  */
703 G_CONST_RETURN gchar*
704 g_path_skip_root (const gchar *file_name)
705 {
706   g_return_val_if_fail (file_name != NULL, NULL);
707   
708 #ifdef G_PLATFORM_WIN32
709   /* Skip \\server\share or //server/share */
710   if (G_IS_DIR_SEPARATOR (file_name[0]) &&
711       G_IS_DIR_SEPARATOR (file_name[1]) &&
712       file_name[2] &&
713       !G_IS_DIR_SEPARATOR (file_name[2]))
714     {
715       gchar *p;
716
717       p = strchr (file_name + 2, G_DIR_SEPARATOR);
718 #ifdef G_OS_WIN32
719       {
720         gchar *q = strchr (file_name + 2, '/');
721         if (p == NULL || (q != NULL && q < p))
722           p = q;
723       }
724 #endif
725       if (p &&
726           p > file_name + 2 &&
727           p[1])
728         {
729           file_name = p + 1;
730
731           while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0]))
732             file_name++;
733
734           /* Possibly skip a backslash after the share name */
735           if (G_IS_DIR_SEPARATOR (file_name[0]))
736             file_name++;
737
738           return (gchar *)file_name;
739         }
740     }
741 #endif
742   
743   /* Skip initial slashes */
744   if (G_IS_DIR_SEPARATOR (file_name[0]))
745     {
746       while (G_IS_DIR_SEPARATOR (file_name[0]))
747         file_name++;
748       return (gchar *)file_name;
749     }
750
751 #ifdef G_OS_WIN32
752   /* Skip X:\ */
753   if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
754     return (gchar *)file_name + 3;
755 #endif
756
757   return NULL;
758 }
759
760 /**
761  * g_path_get_dirname:
762  * @file_name: the name of the file.
763  *
764  * Gets the directory components of a file name.  If the file name has no
765  * directory components "." is returned.  The returned string should be
766  * freed when no longer needed.
767  * 
768  * Returns: the directory components of the file.
769  */
770 gchar*
771 g_path_get_dirname (const gchar    *file_name)
772 {
773   register gchar *base;
774   register gsize len;    
775   
776   g_return_val_if_fail (file_name != NULL, NULL);
777   
778   base = strrchr (file_name, G_DIR_SEPARATOR);
779 #ifdef G_OS_WIN32
780   {
781     gchar *q = strrchr (file_name, '/');
782     if (base == NULL || (q != NULL && q > base))
783         base = q;
784   }
785 #endif
786   if (!base)
787     {
788 #ifdef G_OS_WIN32
789       if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
790         {
791           gchar drive_colon_dot[4];
792
793           drive_colon_dot[0] = file_name[0];
794           drive_colon_dot[1] = ':';
795           drive_colon_dot[2] = '.';
796           drive_colon_dot[3] = '\0';
797
798           return g_strdup (drive_colon_dot);
799         }
800 #endif
801     return g_strdup (".");
802     }
803
804   while (base > file_name && G_IS_DIR_SEPARATOR (*base))
805     base--;
806
807 #ifdef G_OS_WIN32
808   /* base points to the char before the last slash.
809    *
810    * In case file_name is the root of a drive (X:\) or a child of the
811    * root of a drive (X:\foo), include the slash.
812    *
813    * In case file_name is the root share of an UNC path
814    * (\\server\share), add a slash, returning \\server\share\ .
815    *
816    * In case file_name is a direct child of a share in an UNC path
817    * (\\server\share\foo), include the slash after the share name,
818    * returning \\server\share\ .
819    */
820   if (base == file_name + 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
821     base++;
822   else if (G_IS_DIR_SEPARATOR (file_name[0]) &&
823            G_IS_DIR_SEPARATOR (file_name[1]) &&
824            file_name[2] &&
825            !G_IS_DIR_SEPARATOR (file_name[2]) &&
826            base >= file_name + 2)
827     {
828       const gchar *p = file_name + 2;
829       while (*p && !G_IS_DIR_SEPARATOR (*p))
830         p++;
831       if (p == base + 1)
832         {
833           len = (guint) strlen (file_name) + 1;
834           base = g_new (gchar, len + 1);
835           strcpy (base, file_name);
836           base[len-1] = G_DIR_SEPARATOR;
837           base[len] = 0;
838           return base;
839         }
840       if (G_IS_DIR_SEPARATOR (*p))
841         {
842           p++;
843           while (*p && !G_IS_DIR_SEPARATOR (*p))
844             p++;
845           if (p == base + 1)
846             base++;
847         }
848     }
849 #endif
850
851   len = (guint) 1 + base - file_name;
852   
853   base = g_new (gchar, len + 1);
854   g_memmove (base, file_name, len);
855   base[len] = 0;
856   
857   return base;
858 }
859
860 /**
861  * g_get_current_dir:
862  *
863  * Gets the current directory.
864  * The returned string should be freed when no longer needed. The encoding 
865  * of the returned string is system defined. On Windows, it is always UTF-8.
866  * 
867  * Returns: the current directory.
868  */
869 gchar*
870 g_get_current_dir (void)
871 {
872 #ifdef G_OS_WIN32
873
874   gchar *dir = NULL;
875
876   if (G_WIN32_HAVE_WIDECHAR_API ())
877     {
878       wchar_t dummy[2], *wdir;
879       int len;
880
881       len = GetCurrentDirectoryW (2, dummy);
882       wdir = g_new (wchar_t, len);
883
884       if (GetCurrentDirectoryW (len, wdir) == len - 1)
885         dir = g_utf16_to_utf8 (wdir, -1, NULL, NULL, NULL);
886
887       g_free (wdir);
888     }
889   else
890     {
891       gchar dummy[2], *cpdir;
892       int len;
893
894       len = GetCurrentDirectoryA (2, dummy);
895       cpdir = g_new (gchar, len);
896
897       if (GetCurrentDirectoryA (len, cpdir) == len - 1)
898         dir = g_locale_to_utf8 (cpdir, -1, NULL, NULL, NULL);
899
900       g_free (cpdir);
901     }
902
903   if (dir == NULL)
904     dir = g_strdup ("\\");
905
906   return dir;
907
908 #else
909
910   gchar *buffer = NULL;
911   gchar *dir = NULL;
912   static gulong max_len = 0;
913
914   if (max_len == 0) 
915     max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
916   
917   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
918    * and, if that wasn't bad enough, hangs in doing so.
919    */
920 #if     (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
921   buffer = g_new (gchar, max_len + 1);
922   *buffer = 0;
923   dir = getwd (buffer);
924 #else   /* !sun || !HAVE_GETCWD */
925   while (max_len < G_MAXULONG / 2)
926     {
927       buffer = g_new (gchar, max_len + 1);
928       *buffer = 0;
929       dir = getcwd (buffer, max_len);
930
931       if (dir || errno != ERANGE)
932         break;
933
934       g_free (buffer);
935       max_len *= 2;
936     }
937 #endif  /* !sun || !HAVE_GETCWD */
938   
939   if (!dir || !*buffer)
940     {
941       /* hm, should we g_error() out here?
942        * this can happen if e.g. "./" has mode \0000
943        */
944       buffer[0] = G_DIR_SEPARATOR;
945       buffer[1] = 0;
946     }
947
948   dir = g_strdup (buffer);
949   g_free (buffer);
950   
951   return dir;
952 #endif /* !Win32 */
953 }
954
955 /**
956  * g_getenv:
957  * @variable: the environment variable to get, in the GLib file name encoding.
958  * 
959  * Returns the value of an environment variable. The name and value
960  * are in the GLib file name encoding. On UNIX, this means the actual
961  * bytes which might or might not be in some consistent character set
962  * and encoding. On Windows, it is in UTF-8. On Windows, in case the
963  * environment variable's value contains references to other
964  * environment variables, they are expanded.
965  * 
966  * Return value: the value of the environment variable, or %NULL if
967  * the environment variable is not found. The returned string may be
968  * overwritten by the next call to g_getenv(), g_setenv() or
969  * g_unsetenv().
970  **/
971 G_CONST_RETURN gchar*
972 g_getenv (const gchar *variable)
973 {
974 #ifndef G_OS_WIN32
975
976   g_return_val_if_fail (variable != NULL, NULL);
977
978   return getenv (variable);
979
980 #else /* G_OS_WIN32 */
981
982   GQuark quark;
983   gchar *value;
984
985   g_return_val_if_fail (variable != NULL, NULL);
986   g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
987
988   /* On Windows NT, it is relatively typical that environment
989    * variables contain references to other environment variables. If
990    * so, use ExpandEnvironmentStrings(). (In an ideal world, such
991    * environment variables would be stored in the Registry as
992    * REG_EXPAND_SZ type values, and would then get automatically
993    * expanded before a program sees them. But there is broken software
994    * that stores environment variables as REG_SZ values even if they
995    * contain references to other environment variables.)
996    */
997
998   if (G_WIN32_HAVE_WIDECHAR_API ())
999     {
1000       wchar_t dummy[2], *wname, *wvalue;
1001       int len;
1002       
1003       wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
1004
1005       len = GetEnvironmentVariableW (wname, dummy, 2);
1006
1007       if (len == 0)
1008         {
1009           g_free (wname);
1010           return NULL;
1011         }
1012
1013       wvalue = g_new (wchar_t, len);
1014
1015       if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1)
1016         {
1017           g_free (wname);
1018           g_free (wvalue);
1019           return NULL;
1020         }
1021
1022       if (wcschr (wvalue, L'%') != NULL)
1023         {
1024           wchar_t *tem = wvalue;
1025
1026           len = ExpandEnvironmentStringsW (wvalue, dummy, 2);
1027
1028           if (len > 0)
1029             {
1030               wvalue = g_new (wchar_t, len);
1031
1032               if (ExpandEnvironmentStringsW (tem, wvalue, len) != len)
1033                 {
1034                   g_free (wvalue);
1035                   wvalue = tem;
1036                 }
1037               else
1038                 g_free (tem);
1039             }
1040         }
1041
1042       value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
1043
1044       g_free (wname);
1045       g_free (wvalue);
1046     }
1047   else
1048     {
1049       gchar dummy[3], *cpname, *cpvalue;
1050       int len;
1051       
1052       cpname = g_locale_from_utf8 (variable, -1, NULL, NULL, NULL);
1053
1054       g_return_val_if_fail (cpname != NULL, NULL);
1055
1056       len = GetEnvironmentVariableA (cpname, dummy, 2);
1057
1058       if (len == 0)
1059         {
1060           g_free (cpname);
1061           return NULL;
1062         }
1063
1064       cpvalue = g_new (gchar, len);
1065
1066       if (GetEnvironmentVariableA (cpname, cpvalue, len) != len - 1)
1067         {
1068           g_free (cpname);
1069           g_free (cpvalue);
1070           return NULL;
1071         }
1072
1073       if (strchr (cpvalue, '%') != NULL)
1074         {
1075           gchar *tem = cpvalue;
1076
1077           len = ExpandEnvironmentStringsA (cpvalue, dummy, 3);
1078
1079           if (len > 0)
1080             {
1081               cpvalue = g_new (gchar, len);
1082
1083               if (ExpandEnvironmentStringsA (tem, cpvalue, len) != len)
1084                 {
1085                   g_free (cpvalue);
1086                   cpvalue = tem;
1087                 }
1088               else
1089                 g_free (tem);
1090             }
1091         }
1092
1093       value = g_locale_to_utf8 (cpvalue, -1, NULL, NULL, NULL);
1094
1095       g_free (cpname);
1096       g_free (cpvalue);
1097     }
1098
1099   quark = g_quark_from_string (value);
1100   g_free (value);
1101   
1102   return g_quark_to_string (quark);
1103
1104 #endif /* G_OS_WIN32 */
1105 }
1106
1107 /**
1108  * g_setenv:
1109  * @variable: the environment variable to set, must not contain '='.
1110  * @value: the value for to set the variable to.
1111  * @overwrite: whether to change the variable if it already exists.
1112  *
1113  * Sets an environment variable. Both the variable's name and value
1114  * should be in the GLib file name encoding. On UNIX, this means that
1115  * they can be any sequence of bytes. On Windows, they should be in
1116  * UTF-8.
1117  *
1118  * Note that on some systems, when variables are overwritten, the memory 
1119  * used for the previous variables and its value isn't reclaimed.
1120  *
1121  * Returns: %FALSE if the environment variable couldn't be set.
1122  *
1123  * Since: 2.4
1124  */
1125 gboolean
1126 g_setenv (const gchar *variable, 
1127           const gchar *value, 
1128           gboolean     overwrite)
1129 {
1130 #ifndef G_OS_WIN32
1131
1132   gint result;
1133 #ifndef HAVE_SETENV
1134   gchar *string;
1135 #endif
1136
1137   g_return_val_if_fail (variable != NULL, FALSE);
1138   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
1139
1140 #ifdef HAVE_SETENV
1141   result = setenv (variable, value, overwrite);
1142 #else
1143   if (!overwrite && getenv (variable) != NULL)
1144     return TRUE;
1145   
1146   /* This results in a leak when you overwrite existing
1147    * settings. It would be fairly easy to fix this by keeping
1148    * our own parallel array or hash table.
1149    */
1150   string = g_strconcat (variable, "=", value, NULL);
1151   result = putenv (string);
1152 #endif
1153   return result == 0;
1154
1155 #else /* G_OS_WIN32 */
1156
1157   gboolean retval;
1158
1159   g_return_val_if_fail (variable != NULL, FALSE);
1160   g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
1161   g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), FALSE);
1162   g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
1163
1164   if (!overwrite && g_getenv (variable) != NULL)
1165     return TRUE;
1166
1167   /* We want to (if possible) set both the environment variable copy
1168    * kept by the C runtime and the one kept by the system.
1169    *
1170    * We can't use only the C runtime's putenv or _wputenv() as that
1171    * won't work for arbitrary Unicode strings in a "non-Unicode" app
1172    * (with main() and not wmain()). In a "main()" app the C runtime
1173    * initializes the C runtime's environment table by converting the
1174    * real (wide char) environment variables to system codepage, thus
1175    * breaking those that aren't representable in the system codepage.
1176    *
1177    * As the C runtime's putenv() will also set the system copy, we do
1178    * the putenv() first, then call SetEnvironmentValueW ourselves.
1179    */
1180
1181   if (G_WIN32_HAVE_WIDECHAR_API ())
1182     {
1183       wchar_t *wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
1184       wchar_t *wvalue = g_utf8_to_utf16 (value, -1, NULL, NULL, NULL);
1185       gchar *tem = g_strconcat (variable, "=", value, NULL);
1186       wchar_t *wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
1187       
1188       g_free (tem);
1189       _wputenv (wassignment);
1190       g_free (wassignment);
1191
1192       retval = (SetEnvironmentVariableW (wname, wvalue) != 0);
1193
1194       g_free (wname);
1195       g_free (wvalue);
1196     }
1197   else
1198     {
1199       /* In the non-Unicode case (Win9x), just putenv() is good
1200        * enough.
1201        */
1202       gchar *tem = g_strconcat (variable, "=", value, NULL);
1203       gchar *cpassignment = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL);
1204
1205       g_free (tem);
1206       
1207       retval = (putenv (cpassignment) == 0);
1208
1209       g_free (cpassignment);
1210     }
1211
1212   return retval;
1213
1214 #endif /* G_OS_WIN32 */
1215 }
1216
1217 #ifndef G_OS_WIN32
1218
1219 /* According to the Single Unix Specification, environ is not in 
1220  * any system header, although unistd.h often declares it.
1221  */
1222 extern char **environ;
1223
1224 #endif
1225            
1226 /**
1227  * g_unsetenv:
1228  * @variable: the environment variable to remove, must not contain '='.
1229  * 
1230  * Removes an environment variable from the environment.
1231  *
1232  * Note that on some systems, when variables are overwritten, the memory 
1233  * used for the previous variables and its value isn't reclaimed.
1234  * Furthermore, this function can't be guaranteed to operate in a 
1235  * threadsafe way.
1236  *
1237  * Since: 2.4 
1238  **/
1239 void
1240 g_unsetenv (const gchar *variable)
1241 {
1242 #ifndef G_OS_WIN32
1243
1244 #ifdef HAVE_UNSETENV
1245   g_return_if_fail (variable != NULL);
1246   g_return_if_fail (strchr (variable, '=') == NULL);
1247
1248   unsetenv (variable);
1249 #else /* !HAVE_UNSETENV */
1250   int len;
1251   gchar **e, **f;
1252
1253   g_return_if_fail (variable != NULL);
1254   g_return_if_fail (strchr (variable, '=') == NULL);
1255
1256   len = strlen (variable);
1257   
1258   /* Mess directly with the environ array.
1259    * This seems to be the only portable way to do this.
1260    *
1261    * Note that we remove *all* environment entries for
1262    * the variable name, not just the first.
1263    */
1264   e = f = environ;
1265   while (*e != NULL) 
1266     {
1267       if (strncmp (*e, variable, len) != 0 || (*e)[len] != '=') 
1268         {
1269           *f = *e;
1270           f++;
1271         }
1272       e++;
1273     }
1274   *f = NULL;
1275 #endif /* !HAVE_UNSETENV */
1276
1277 #else  /* G_OS_WIN32 */
1278
1279   g_return_if_fail (variable != NULL);
1280   g_return_if_fail (strchr (variable, '=') == NULL);
1281   g_return_if_fail (g_utf8_validate (variable, -1, NULL));
1282
1283   if (G_WIN32_HAVE_WIDECHAR_API ())
1284     {
1285       wchar_t *wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
1286       gchar *tem = g_strconcat (variable, "=", NULL);
1287       wchar_t *wassignment = g_utf8_to_utf16 (tem, -1, NULL, NULL, NULL);
1288       
1289       g_free (tem);
1290       _wputenv (wassignment);
1291       g_free (wassignment);
1292
1293       SetEnvironmentVariableW (wname, NULL);
1294
1295       g_free (wname);
1296     }
1297   else
1298     {
1299       /* In the non-Unicode case (Win9x), just putenv() is good
1300        * enough.
1301        */
1302       gchar *tem = g_strconcat (variable, "=", NULL);
1303       gchar *cpassignment = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL);
1304
1305       g_free (tem);
1306       
1307       putenv (cpassignment);
1308
1309       g_free (cpassignment);
1310     }
1311
1312 #endif /* G_OS_WIN32 */
1313 }
1314
1315 /**
1316  * g_listenv:
1317  *
1318  * Gets the names of all variables set in the environment.
1319  * 
1320  * Return: a NUL-terminated list of strings which must be freed
1321  * with g_strfreev().
1322  *
1323  * Since: 2.8
1324  */
1325 gchar **
1326 g_listenv (void)
1327 {
1328   gchar **result, *eq;
1329   gint len, i;
1330
1331   len = g_strv_length (environ);
1332   result = g_new0 (gchar *, len + 1);
1333   
1334   for (i = 0; i < len; i++)
1335     {
1336       eq = strchr (environ[i], '=');
1337       result[i] = g_strndup (environ[i], eq - environ[i]);
1338     }
1339
1340   result[len] = NULL;
1341
1342   return result;
1343 }
1344
1345 G_LOCK_DEFINE_STATIC (g_utils_global);
1346
1347 static  gchar   *g_tmp_dir = NULL;
1348 static  gchar   *g_user_name = NULL;
1349 static  gchar   *g_real_name = NULL;
1350 static  gchar   *g_home_dir = NULL;
1351
1352 #ifdef G_OS_WIN32
1353 /* System codepage versions of the above, kept at file level so that they,
1354  * too, are produced only once.
1355  */
1356 static  gchar   *g_tmp_dir_cp = NULL;
1357 static  gchar   *g_user_name_cp = NULL;
1358 static  gchar   *g_real_name_cp = NULL;
1359 static  gchar   *g_home_dir_cp = NULL;
1360 #endif
1361
1362 static  gchar   *g_user_data_dir = NULL;
1363 static  gchar  **g_system_data_dirs = NULL;
1364 static  gchar   *g_user_cache_dir = NULL;
1365 static  gchar   *g_user_config_dir = NULL;
1366 static  gchar  **g_system_config_dirs = NULL;
1367
1368 #ifdef G_OS_WIN32
1369
1370 static gchar *
1371 get_special_folder (int csidl)
1372 {
1373   union {
1374     char c[MAX_PATH+1];
1375     wchar_t wc[MAX_PATH+1];
1376   } path;
1377   HRESULT hr;
1378   LPITEMIDLIST pidl = NULL;
1379   BOOL b;
1380   gchar *retval = NULL;
1381
1382   hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl);
1383   if (hr == S_OK)
1384     {
1385       if (G_WIN32_HAVE_WIDECHAR_API ())
1386         {
1387           b = SHGetPathFromIDListW (pidl, path.wc);
1388           if (b)
1389             retval = g_utf16_to_utf8 (path.wc, -1, NULL, NULL, NULL);
1390         }
1391       else
1392         {
1393           b = SHGetPathFromIDListA (pidl, path.c);
1394           if (b)
1395             retval = g_locale_to_utf8 (path.c, -1, NULL, NULL, NULL);
1396         }
1397       CoTaskMemFree (pidl);
1398     }
1399   return retval;
1400 }
1401
1402 #endif
1403
1404 /* HOLDS: g_utils_global_lock */
1405 static void
1406 g_get_any_init (void)
1407 {
1408   if (!g_tmp_dir)
1409     {
1410       g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
1411       if (!g_tmp_dir)
1412         g_tmp_dir = g_strdup (g_getenv ("TMP"));
1413       if (!g_tmp_dir)
1414         g_tmp_dir = g_strdup (g_getenv ("TEMP"));
1415       
1416 #ifdef P_tmpdir
1417       if (!g_tmp_dir)
1418         {
1419           gsize k;    
1420           g_tmp_dir = g_strdup (P_tmpdir);
1421           k = strlen (g_tmp_dir);
1422           if (k > 1 && G_IS_DIR_SEPARATOR (g_tmp_dir[k - 1]))
1423             g_tmp_dir[k - 1] = '\0';
1424         }
1425 #endif
1426       
1427       if (!g_tmp_dir)
1428         {
1429 #ifndef G_OS_WIN32
1430           g_tmp_dir = g_strdup ("/tmp");
1431 #else /* G_OS_WIN32 */
1432           g_tmp_dir = g_strdup ("\\");
1433 #endif /* G_OS_WIN32 */
1434         }
1435       
1436 #ifdef G_OS_WIN32
1437       /* We check $HOME first for Win32, though it is a last resort for Unix
1438        * where we prefer the results of getpwuid().
1439        */
1440       g_home_dir = g_strdup (g_getenv ("HOME"));
1441
1442       /* Only believe HOME if it is an absolute path and exists */
1443       if (g_home_dir)
1444         {
1445           if (!(g_path_is_absolute (g_home_dir) &&
1446                 g_file_test (g_home_dir, G_FILE_TEST_IS_DIR)))
1447             {
1448               g_free (g_home_dir);
1449               g_home_dir = NULL;
1450             }
1451         }
1452       
1453       /* In case HOME is Unix-style (it happens), convert it to
1454        * Windows style.
1455        */
1456       if (g_home_dir)
1457         {
1458           gchar *p;
1459           while ((p = strchr (g_home_dir, '/')) != NULL)
1460             *p = '\\';
1461         }
1462
1463       if (!g_home_dir)
1464         {
1465           /* USERPROFILE is probably the closest equivalent to $HOME? */
1466           if (g_getenv ("USERPROFILE") != NULL)
1467             g_home_dir = g_strdup (g_getenv ("USERPROFILE"));
1468         }
1469
1470       if (!g_home_dir)
1471         g_home_dir = get_special_folder (CSIDL_PROFILE);
1472       
1473       if (!g_home_dir)
1474         {
1475           /* At least at some time, HOMEDRIVE and HOMEPATH were used
1476            * to point to the home directory, I think. But on Windows
1477            * 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and
1478            * HOMEPATH is its root "\"?
1479            */
1480           if (g_getenv ("HOMEDRIVE") != NULL && g_getenv ("HOMEPATH") != NULL)
1481             g_home_dir = g_strconcat (g_getenv ("HOMEDRIVE"),
1482                                       g_getenv ("HOMEPATH"),
1483                                       NULL);
1484         }
1485 #endif /* G_OS_WIN32 */
1486       
1487 #ifdef HAVE_PWD_H
1488       {
1489         struct passwd *pw = NULL;
1490         gpointer buffer = NULL;
1491         gint error;
1492         
1493 #  if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
1494         struct passwd pwd;
1495 #    ifdef _SC_GETPW_R_SIZE_MAX  
1496         /* This reurns the maximum length */
1497         glong bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
1498         
1499         if (bufsize < 0)
1500           bufsize = 64;
1501 #    else /* _SC_GETPW_R_SIZE_MAX */
1502         glong bufsize = 64;
1503 #    endif /* _SC_GETPW_R_SIZE_MAX */
1504         
1505         do
1506           {
1507             g_free (buffer);
1508             /* we allocate 6 extra bytes to work around a bug in 
1509              * Mac OS < 10.3. See #156446
1510              */
1511             buffer = g_malloc (bufsize + 6);
1512             errno = 0;
1513             
1514 #    ifdef HAVE_POSIX_GETPWUID_R
1515             error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
1516             error = error < 0 ? errno : error;
1517 #    else /* HAVE_NONPOSIX_GETPWUID_R */
1518        /* HPUX 11 falls into the HAVE_POSIX_GETPWUID_R case */
1519 #      if defined(_AIX) || defined(__hpux)
1520             error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
1521             pw = error == 0 ? &pwd : NULL;
1522 #      else /* !_AIX */
1523             pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
1524             error = pw ? 0 : errno;
1525 #      endif /* !_AIX */            
1526 #    endif /* HAVE_NONPOSIX_GETPWUID_R */
1527             
1528             if (!pw)
1529               {
1530                 /* we bail out prematurely if the user id can't be found
1531                  * (should be pretty rare case actually), or if the buffer
1532                  * should be sufficiently big and lookups are still not
1533                  * successfull.
1534                  */
1535                 if (error == 0 || error == ENOENT)
1536                   {
1537                     g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
1538                                (gulong) getuid ());
1539                     break;
1540                   }
1541                 if (bufsize > 32 * 1024)
1542                   {
1543                     g_warning ("getpwuid_r(): failed due to: %s.",
1544                                g_strerror (error));
1545                     break;
1546                   }
1547                 
1548                 bufsize *= 2;
1549               }
1550           }
1551         while (!pw);
1552 #  endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
1553         
1554         if (!pw)
1555           {
1556             setpwent ();
1557             pw = getpwuid (getuid ());
1558             endpwent ();
1559           }
1560         if (pw)
1561           {
1562             g_user_name = g_strdup (pw->pw_name);
1563
1564             if (pw->pw_gecos && *pw->pw_gecos != '\0') 
1565               {
1566                 gchar **gecos_fields;
1567                 gchar **name_parts;
1568
1569                 /* split the gecos field and substitute '&' */
1570                 gecos_fields = g_strsplit (pw->pw_gecos, ",", 0);
1571                 name_parts = g_strsplit (gecos_fields[0], "&", 0);
1572                 pw->pw_name[0] = g_ascii_toupper (pw->pw_name[0]);
1573                 g_real_name = g_strjoinv (pw->pw_name, name_parts);
1574                 g_strfreev (gecos_fields);
1575                 g_strfreev (name_parts);
1576               }
1577
1578             if (!g_home_dir)
1579               g_home_dir = g_strdup (pw->pw_dir);
1580           }
1581         g_free (buffer);
1582       }
1583       
1584 #else /* !HAVE_PWD_H */
1585       
1586 #ifdef G_OS_WIN32
1587       if (G_WIN32_HAVE_WIDECHAR_API ())
1588         {
1589           guint len = UNLEN+1;
1590           wchar_t buffer[UNLEN+1];
1591           
1592           if (GetUserNameW (buffer, (LPDWORD) &len))
1593             {
1594               g_user_name = g_utf16_to_utf8 (buffer, -1, NULL, NULL, NULL);
1595               g_real_name = g_strdup (g_user_name);
1596             }
1597         }
1598       else
1599         {
1600           guint len = UNLEN+1;
1601           char buffer[UNLEN+1];
1602           
1603           if (GetUserNameA (buffer, (LPDWORD) &len))
1604             {
1605               g_user_name = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
1606               g_real_name = g_strdup (g_user_name);
1607             }
1608         }
1609 #endif /* G_OS_WIN32 */
1610
1611 #endif /* !HAVE_PWD_H */
1612
1613 #ifndef G_OS_WIN32
1614       if (!g_home_dir)
1615         g_home_dir = g_strdup (g_getenv ("HOME"));
1616 #endif
1617
1618 #ifdef __EMX__
1619       /* change '\\' in %HOME% to '/' */
1620       g_strdelimit (g_home_dir, "\\",'/');
1621 #endif
1622       if (!g_user_name)
1623         g_user_name = g_strdup ("somebody");
1624       if (!g_real_name)
1625         g_real_name = g_strdup ("Unknown");
1626
1627 #ifdef G_OS_WIN32
1628       g_tmp_dir_cp = g_locale_from_utf8 (g_tmp_dir, -1, NULL, NULL, NULL);
1629       g_user_name_cp = g_locale_from_utf8 (g_user_name, -1, NULL, NULL, NULL);
1630       g_real_name_cp = g_locale_from_utf8 (g_real_name, -1, NULL, NULL, NULL);
1631
1632       if (!g_tmp_dir_cp)
1633         g_tmp_dir_cp = g_strdup ("\\");
1634       if (!g_user_name_cp)
1635         g_user_name_cp = g_strdup ("somebody");
1636       if (!g_real_name_cp)
1637         g_real_name_cp = g_strdup ("Unknown");
1638
1639       /* home_dir might be NULL, unlike tmp_dir, user_name and
1640        * real_name.
1641        */
1642       if (g_home_dir)
1643         g_home_dir_cp = g_locale_from_utf8 (g_home_dir, -1, NULL, NULL, NULL);
1644       else
1645         g_home_dir_cp = NULL;
1646 #endif /* G_OS_WIN32 */
1647     }
1648 }
1649
1650 /**
1651  * g_get_user_name:
1652  *
1653  * Gets the user name of the current user. The encoding of the returned
1654  * string is system-defined. On UNIX, it might be the preferred file name
1655  * encoding, or something else, and there is no guarantee that it is even
1656  * consistent on a machine. On Windows, it is always UTF-8.
1657  *
1658  * Returns: the user name of the current user.
1659  */
1660 G_CONST_RETURN gchar*
1661 g_get_user_name (void)
1662 {
1663   G_LOCK (g_utils_global);
1664   if (!g_tmp_dir)
1665     g_get_any_init ();
1666   G_UNLOCK (g_utils_global);
1667   
1668   return g_user_name;
1669 }
1670
1671 /**
1672  * g_get_real_name:
1673  *
1674  * Gets the real name of the user. This usually comes from the user's entry 
1675  * in the <filename>passwd</filename> file. The encoding of the returned 
1676  * string is system-defined. (On Windows, it is, however, always UTF-8.) 
1677  * If the real user name cannot be determined, the string "Unknown" is 
1678  * returned.
1679  *
1680  * Returns: the user's real name.
1681  */
1682 G_CONST_RETURN gchar*
1683 g_get_real_name (void)
1684 {
1685   G_LOCK (g_utils_global);
1686   if (!g_tmp_dir)
1687     g_get_any_init ();
1688   G_UNLOCK (g_utils_global);
1689  
1690   return g_real_name;
1691 }
1692
1693 /**
1694  * g_get_home_dir:
1695  *
1696  * Gets the current user's home directory. 
1697  *
1698  * Note that in contrast to traditional UNIX tools, this function 
1699  * prefers <filename>passwd</filename> entries over the <envar>HOME</envar> 
1700  * environment variable.
1701  *
1702  * Returns: the current user's home directory.
1703  */
1704 G_CONST_RETURN gchar*
1705 g_get_home_dir (void)
1706 {
1707   G_LOCK (g_utils_global);
1708   if (!g_tmp_dir)
1709     g_get_any_init ();
1710   G_UNLOCK (g_utils_global);
1711   
1712   return g_home_dir;
1713 }
1714
1715 /**
1716  * g_get_tmp_dir:
1717  *
1718  * Gets the directory to use for temporary files. This is found from 
1719  * inspecting the environment variables <envar>TMPDIR</envar>, 
1720  * <envar>TMP</envar>, and <envar>TEMP</envar> in that order. If none 
1721  * of those are defined "/tmp" is returned on UNIX and "C:\" on Windows. 
1722  * The encoding of the returned string is system-defined. On Windows, 
1723  * it is always UTF-8. The return value is never %NULL.
1724  *
1725  * Returns: the directory to use for temporary files.
1726  */
1727 G_CONST_RETURN gchar*
1728 g_get_tmp_dir (void)
1729 {
1730   G_LOCK (g_utils_global);
1731   if (!g_tmp_dir)
1732     g_get_any_init ();
1733   G_UNLOCK (g_utils_global);
1734   
1735   return g_tmp_dir;
1736 }
1737
1738 G_LOCK_DEFINE_STATIC (g_prgname);
1739 static gchar *g_prgname = NULL;
1740
1741 /**
1742  * g_get_prgname:
1743  *
1744  * Gets the name of the program. This name should <emphasis>not</emphasis> 
1745  * be localized, contrast with g_get_application_name().
1746  * (If you are using GDK or GTK+ the program name is set in gdk_init(), 
1747  * which is called by gtk_init(). The program name is found by taking 
1748  * the last component of <literal>argv[0]</literal>.)
1749  *
1750  * Returns: the name of the program. The returned string belongs 
1751  * to GLib and must not be modified or freed.
1752  */
1753 gchar*
1754 g_get_prgname (void)
1755 {
1756   gchar* retval;
1757
1758   G_LOCK (g_prgname);
1759   retval = g_prgname;
1760   G_UNLOCK (g_prgname);
1761
1762   return retval;
1763 }
1764
1765 /**
1766  * g_set_prgname:
1767  * @prgname: the name of the program.
1768  *
1769  * Sets the name of the program. This name should <emphasis>not</emphasis> 
1770  * be localized, contrast with g_set_application_name(). Note that for 
1771  * thread-safety reasons this function can only be called once.
1772  */
1773 void
1774 g_set_prgname (const gchar *prgname)
1775 {
1776   G_LOCK (g_prgname);
1777   g_free (g_prgname);
1778   g_prgname = g_strdup (prgname);
1779   G_UNLOCK (g_prgname);
1780 }
1781
1782 G_LOCK_DEFINE_STATIC (g_application_name);
1783 static gchar *g_application_name = NULL;
1784
1785 /**
1786  * g_get_application_name:
1787  * 
1788  * Gets a human-readable name for the application, as set by
1789  * g_set_application_name(). This name should be localized if
1790  * possible, and is intended for display to the user.  Contrast with
1791  * g_get_prgname(), which gets a non-localized name. If
1792  * g_set_application_name() has not been called, returns the result of
1793  * g_get_prgname() (which may be %NULL if g_set_prgname() has also not
1794  * been called).
1795  * 
1796  * Return value: human-readable application name. may return %NULL
1797  *
1798  * Since: 2.2
1799  **/
1800 G_CONST_RETURN gchar*
1801 g_get_application_name (void)
1802 {
1803   gchar* retval;
1804
1805   G_LOCK (g_application_name);
1806   retval = g_application_name;
1807   G_UNLOCK (g_application_name);
1808
1809   if (retval == NULL)
1810     return g_get_prgname ();
1811   
1812   return retval;
1813 }
1814
1815 /**
1816  * g_set_application_name:
1817  * @application_name: localized name of the application
1818  *
1819  * Sets a human-readable name for the application. This name should be
1820  * localized if possible, and is intended for display to the user.
1821  * Contrast with g_set_prgname(), which sets a non-localized name.
1822  * g_set_prgname() will be called automatically by gtk_init(),
1823  * but g_set_application_name() will not.
1824  *
1825  * Note that for thread safety reasons, this function can only
1826  * be called once.
1827  *
1828  * The application name will be used in contexts such as error messages,
1829  * or when displaying an application's name in the task list.
1830  * 
1831  **/
1832 void
1833 g_set_application_name (const gchar *application_name)
1834 {
1835   gboolean already_set = FALSE;
1836         
1837   G_LOCK (g_application_name);
1838   if (g_application_name)
1839     already_set = TRUE;
1840   else
1841     g_application_name = g_strdup (application_name);
1842   G_UNLOCK (g_application_name);
1843
1844   if (already_set)
1845     g_warning ("g_set_application() name called multiple times");
1846 }
1847
1848 /**
1849  * g_get_user_data_dir:
1850  * 
1851  * Returns a base directory in which to access application data such
1852  * as icons that is customized for a particular user.  
1853  *
1854  * On UNIX platforms this is determined using the mechanisms described in
1855  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1856  * XDG Base Directory Specification</ulink>
1857  * 
1858  * Return value: a string owned by GLib that must not be modified 
1859  *               or freed.
1860  * Since: 2.6
1861  **/
1862 G_CONST_RETURN gchar*
1863 g_get_user_data_dir (void)
1864 {
1865   gchar *data_dir;  
1866
1867   G_LOCK (g_utils_global);
1868
1869   if (!g_user_data_dir)
1870     {
1871 #ifdef G_OS_WIN32
1872       data_dir = get_special_folder (CSIDL_PERSONAL);
1873 #else
1874       data_dir = (gchar *) g_getenv ("XDG_DATA_HOME");
1875 #endif
1876
1877       if (data_dir && data_dir[0])
1878         data_dir = g_strdup (data_dir);
1879       else
1880         {
1881           if (!g_tmp_dir)
1882             g_get_any_init ();
1883
1884           data_dir = g_build_filename (g_home_dir, ".local", 
1885                                        "share", NULL);
1886         }
1887
1888       g_user_data_dir = data_dir;
1889     }
1890   else
1891     data_dir = g_user_data_dir;
1892
1893   G_UNLOCK (g_utils_global);
1894
1895   return data_dir;
1896 }
1897
1898 /**
1899  * g_get_user_config_dir:
1900  * 
1901  * Returns a base directory in which to store user-specific application 
1902  * configuration information such as user preferences and settings. 
1903  *
1904  * On UNIX platforms this is determined using the mechanisms described in
1905  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1906  * XDG Base Directory Specification</ulink>
1907  * 
1908  * Return value: a string owned by GLib that must not be modified 
1909  *               or freed.
1910  * Since: 2.6
1911  **/
1912 G_CONST_RETURN gchar*
1913 g_get_user_config_dir (void)
1914 {
1915   gchar *config_dir;  
1916
1917   G_LOCK (g_utils_global);
1918
1919   if (!g_user_config_dir)
1920     {
1921 #ifdef G_OS_WIN32
1922       config_dir = get_special_folder (CSIDL_APPDATA);
1923 #else
1924       config_dir = (gchar *) g_getenv ("XDG_CONFIG_HOME");
1925 #endif
1926
1927       if (config_dir && config_dir[0])
1928         config_dir = g_strdup (config_dir);
1929       else
1930         {
1931           if (!g_tmp_dir)
1932             g_get_any_init ();
1933           
1934           config_dir = g_build_filename (g_home_dir, ".config", NULL);
1935         }
1936       g_user_config_dir = config_dir;
1937     }
1938   else
1939     config_dir = g_user_config_dir;
1940
1941   G_UNLOCK (g_utils_global);
1942
1943   return config_dir;
1944 }
1945
1946 /**
1947  * g_get_user_cache_dir:
1948  * 
1949  * Returns a base directory in which to store non-essential, cached
1950  * data specific to particular user.
1951  *
1952  * On UNIX platforms this is determined using the mechanisms described in
1953  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
1954  * XDG Base Directory Specification</ulink>
1955  * 
1956  * Return value: a string owned by GLib that must not be modified 
1957  *               or freed.
1958  * Since: 2.6
1959  **/
1960 G_CONST_RETURN gchar*
1961 g_get_user_cache_dir (void)
1962 {
1963   gchar *cache_dir;  
1964
1965   G_LOCK (g_utils_global);
1966
1967   if (!g_user_cache_dir)
1968     {
1969 #ifdef G_OS_WIN32
1970       cache_dir = get_special_folder (CSIDL_INTERNET_CACHE); /* XXX correct? */
1971 #else
1972       cache_dir = (gchar *) g_getenv ("XDG_CACHE_HOME");
1973 #endif
1974       if (cache_dir && cache_dir[0])
1975           cache_dir = g_strdup (cache_dir);
1976       else
1977         {
1978           if (!g_tmp_dir)
1979             g_get_any_init ();
1980
1981           cache_dir = g_build_filename (g_home_dir, ".cache", NULL);
1982         }
1983       g_user_cache_dir = cache_dir;
1984     }
1985   else
1986     cache_dir = g_user_cache_dir;
1987
1988   G_UNLOCK (g_utils_global);
1989
1990   return cache_dir;
1991 }
1992
1993 /**
1994  * g_get_system_data_dirs:
1995  * 
1996  * Returns an ordered list of base directories in which to access 
1997  * system-wide application data.
1998  *
1999  * On UNIX platforms this is determined using the mechanisms described in
2000  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
2001  * XDG Base Directory Specification</ulink>
2002  * 
2003  * Return value: a %NULL-terminated array of strings owned by GLib that must 
2004  *               not be modified or freed.
2005  * Since: 2.6
2006  **/
2007 G_CONST_RETURN gchar * G_CONST_RETURN * 
2008 g_get_system_data_dirs (void)
2009 {
2010   gchar *data_dirs, **data_dir_vector;
2011
2012   G_LOCK (g_utils_global);
2013
2014   if (!g_system_data_dirs)
2015     {
2016 #ifdef G_OS_WIN32
2017       data_dirs = g_strconcat (get_special_folder (CSIDL_COMMON_APPDATA),
2018                                G_SEARCHPATH_SEPARATOR_S,
2019                                get_special_folder (CSIDL_COMMON_DOCUMENTS),
2020                                NULL);
2021 #else
2022       data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
2023
2024       if (!data_dirs || !data_dirs[0])
2025           data_dirs = "/usr/local/share/:/usr/share/";
2026 #endif
2027       data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
2028
2029       g_system_data_dirs = data_dir_vector;
2030     }
2031   else
2032     data_dir_vector = g_system_data_dirs;
2033
2034   G_UNLOCK (g_utils_global);
2035
2036   return (G_CONST_RETURN gchar * G_CONST_RETURN *) data_dir_vector;
2037 }
2038
2039 /**
2040  * g_get_system_config_dirs:
2041  * 
2042  * Returns an ordered list of base directories in which to access 
2043  * system-wide configuration information.
2044  *
2045  * On UNIX platforms this is determined using the mechanisms described in
2046  * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
2047  * XDG Base Directory Specification</ulink>
2048  * 
2049  * Return value: a %NULL-terminated array of strings owned by GLib that must 
2050  *               not be modified or freed.
2051  * Since: 2.6
2052  **/
2053 G_CONST_RETURN gchar * G_CONST_RETURN *
2054 g_get_system_config_dirs (void)
2055 {
2056   gchar *conf_dirs, **conf_dir_vector;
2057
2058   G_LOCK (g_utils_global);
2059
2060   if (!g_system_config_dirs)
2061     {
2062 #ifdef G_OS_WIN32
2063       conf_dirs = get_special_folder (CSIDL_COMMON_APPDATA);
2064 #else
2065       conf_dirs = (gchar *) g_getenv ("XDG_CONFIG_DIRS");
2066
2067       if (!conf_dirs || !conf_dirs[0])
2068           conf_dirs = "/etc/xdg";
2069 #endif
2070       conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
2071
2072       g_system_config_dirs = conf_dir_vector;
2073     }
2074   else
2075     conf_dir_vector = g_system_config_dirs;
2076   G_UNLOCK (g_utils_global);
2077
2078   return (G_CONST_RETURN gchar * G_CONST_RETURN *) conf_dir_vector;
2079 }
2080
2081 static GHashTable *alias_table = NULL;
2082
2083 /* read an alias file for the locales */
2084 static void
2085 read_aliases (gchar *file)
2086 {
2087   FILE *fp;
2088   char buf[256];
2089   
2090   if (!alias_table)
2091     alias_table = g_hash_table_new (g_str_hash, g_str_equal);
2092   fp = fopen (file,"r");
2093   if (!fp)
2094     return;
2095   while (fgets (buf, 256, fp))
2096     {
2097       char *p, *q;
2098
2099       g_strstrip (buf);
2100
2101       /* Line is a comment */
2102       if ((buf[0] == '#') || (buf[0] == '\0'))
2103         continue;
2104
2105       /* Reads first column */
2106       for (p = buf, q = NULL; *p; p++) {
2107         if ((*p == '\t') || (*p == ' ') || (*p == ':')) {
2108           *p = '\0';
2109           q = p+1;
2110           while ((*q == '\t') || (*q == ' ')) {
2111             q++;
2112           }
2113           break;
2114         }
2115       }
2116       /* The line only had one column */
2117       if (!q || *q == '\0')
2118         continue;
2119       
2120       /* Read second column */
2121       for (p = q; *p; p++) {
2122         if ((*p == '\t') || (*p == ' ')) {
2123           *p = '\0';
2124           break;
2125         }
2126       }
2127
2128       /* Add to alias table if necessary */
2129       if (!g_hash_table_lookup (alias_table, buf)) {
2130         g_hash_table_insert (alias_table, g_strdup (buf), g_strdup (q));
2131       }
2132     }
2133   fclose (fp);
2134 }
2135
2136 static char *
2137 unalias_lang (char *lang)
2138 {
2139   char *p;
2140   int i;
2141
2142   if (!alias_table)
2143     read_aliases ("/usr/share/locale/locale.alias");
2144
2145   i = 0;
2146   while ((p = g_hash_table_lookup (alias_table, lang)) && (strcmp (p, lang) != 0))
2147     {
2148       lang = p;
2149       if (i++ == 30)
2150         {
2151           static gboolean said_before = FALSE;
2152           if (!said_before)
2153             g_warning ("Too many alias levels for a locale, "
2154                        "may indicate a loop");
2155           said_before = TRUE;
2156           return lang;
2157         }
2158     }
2159   return lang;
2160 }
2161
2162 /* Mask for components of locale spec. The ordering here is from
2163  * least significant to most significant
2164  */
2165 enum
2166 {
2167   COMPONENT_CODESET =   1 << 0,
2168   COMPONENT_TERRITORY = 1 << 1,
2169   COMPONENT_MODIFIER =  1 << 2
2170 };
2171
2172 /* Break an X/Open style locale specification into components
2173  */
2174 static guint
2175 explode_locale (const gchar *locale,
2176                 gchar      **language, 
2177                 gchar      **territory, 
2178                 gchar      **codeset, 
2179                 gchar      **modifier)
2180 {
2181   const gchar *uscore_pos;
2182   const gchar *at_pos;
2183   const gchar *dot_pos;
2184
2185   guint mask = 0;
2186
2187   uscore_pos = strchr (locale, '_');
2188   dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
2189   at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
2190
2191   if (at_pos)
2192     {
2193       mask |= COMPONENT_MODIFIER;
2194       *modifier = g_strdup (at_pos);
2195     }
2196   else
2197     at_pos = locale + strlen (locale);
2198
2199   if (dot_pos)
2200     {
2201       mask |= COMPONENT_CODESET;
2202       *codeset = g_strndup (dot_pos, at_pos - dot_pos);
2203     }
2204   else
2205     dot_pos = at_pos;
2206
2207   if (uscore_pos)
2208     {
2209       mask |= COMPONENT_TERRITORY;
2210       *territory = g_strndup (uscore_pos, dot_pos - uscore_pos);
2211     }
2212   else
2213     uscore_pos = dot_pos;
2214
2215   *language = g_strndup (locale, uscore_pos - locale);
2216
2217   return mask;
2218 }
2219
2220 /*
2221  * Compute all interesting variants for a given locale name -
2222  * by stripping off different components of the value.
2223  *
2224  * For simplicity, we assume that the locale is in
2225  * X/Open format: language[_territory][.codeset][@modifier]
2226  *
2227  * TODO: Extend this to handle the CEN format (see the GNUlibc docs)
2228  *       as well. We could just copy the code from glibc wholesale
2229  *       but it is big, ugly, and complicated, so I'm reluctant
2230  *       to do so when this should handle 99% of the time...
2231  */
2232 GSList *
2233 _g_compute_locale_variants (const gchar *locale)
2234 {
2235   GSList *retval = NULL;
2236
2237   gchar *language;
2238   gchar *territory;
2239   gchar *codeset;
2240   gchar *modifier;
2241
2242   guint mask;
2243   guint i;
2244
2245   g_return_val_if_fail (locale != NULL, NULL);
2246
2247   mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
2248
2249   /* Iterate through all possible combinations, from least attractive
2250    * to most attractive.
2251    */
2252   for (i = 0; i <= mask; i++)
2253     if ((i & ~mask) == 0)
2254       {
2255         gchar *val = g_strconcat (language,
2256                                   (i & COMPONENT_TERRITORY) ? territory : "",
2257                                   (i & COMPONENT_CODESET) ? codeset : "",
2258                                   (i & COMPONENT_MODIFIER) ? modifier : "",
2259                                   NULL);
2260         retval = g_slist_prepend (retval, val);
2261       }
2262
2263   g_free (language);
2264   if (mask & COMPONENT_CODESET)
2265     g_free (codeset);
2266   if (mask & COMPONENT_TERRITORY)
2267     g_free (territory);
2268   if (mask & COMPONENT_MODIFIER)
2269     g_free (modifier);
2270
2271   return retval;
2272 }
2273
2274 /* The following is (partly) taken from the gettext package.
2275    Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.  */
2276
2277 static const gchar *
2278 guess_category_value (const gchar *category_name)
2279 {
2280   const gchar *retval;
2281
2282   /* The highest priority value is the `LANGUAGE' environment
2283      variable.  This is a GNU extension.  */
2284   retval = g_getenv ("LANGUAGE");
2285   if ((retval != NULL) && (retval[0] != '\0'))
2286     return retval;
2287
2288   /* `LANGUAGE' is not set.  So we have to proceed with the POSIX
2289      methods of looking to `LC_ALL', `LC_xxx', and `LANG'.  On some
2290      systems this can be done by the `setlocale' function itself.  */
2291
2292   /* Setting of LC_ALL overwrites all other.  */
2293   retval = g_getenv ("LC_ALL");  
2294   if ((retval != NULL) && (retval[0] != '\0'))
2295     return retval;
2296
2297   /* Next comes the name of the desired category.  */
2298   retval = g_getenv (category_name);
2299   if ((retval != NULL) && (retval[0] != '\0'))
2300     return retval;
2301
2302   /* Last possibility is the LANG environment variable.  */
2303   retval = g_getenv ("LANG");
2304   if ((retval != NULL) && (retval[0] != '\0'))
2305     return retval;
2306
2307 #ifdef G_PLATFORM_WIN32
2308   /* g_win32_getlocale() first checks for LC_ALL, LC_MESSAGES and
2309    * LANG, which we already did above. Oh well. The main point of
2310    * calling g_win32_getlocale() is to get the thread's locale as used
2311    * by Windows and the Microsoft C runtime (in the "English_United
2312    * States" format) translated into the Unixish format.
2313    */
2314   retval = g_win32_getlocale ();
2315   if ((retval != NULL) && (retval[0] != '\0'))
2316     return retval;
2317 #endif  
2318
2319   return NULL;
2320 }
2321
2322 typedef struct _GLanguageNamesCache GLanguageNamesCache;
2323
2324 struct _GLanguageNamesCache {
2325   gchar *languages;
2326   gchar **language_names;
2327 };
2328
2329 static void
2330 language_names_cache_free (gpointer data)
2331 {
2332   GLanguageNamesCache *cache = data;
2333   g_free (cache->languages);
2334   g_strfreev (cache->language_names);
2335   g_free (cache);
2336 }
2337
2338 /**
2339  * g_get_language_names:
2340  * 
2341  * Computes a list of applicable locale names, which can be used to 
2342  * e.g. construct locale-dependent filenames or search paths. The returned 
2343  * list is sorted from most desirable to least desirable and always contains 
2344  * the default locale "C".
2345  *
2346  * For example, if LANGUAGE=de:en_US, then the returned list is
2347  * "de", "en_US", "en", "C".
2348  *
2349  * This function consults the environment variables <envar>LANGUAGE</envar>, 
2350  * <envar>LC_ALL</envar>, <envar>LC_MESSAGES</envar> and <envar>LANG</envar> 
2351  * to find the list of locales specified by the user.
2352  * 
2353  * Return value: a %NULL-terminated array of strings owned by GLib 
2354  *    that must not be modified or freed.
2355  *
2356  * Since: 2.6
2357  **/
2358 G_CONST_RETURN gchar * G_CONST_RETURN * 
2359 g_get_language_names (void)
2360 {
2361   static GStaticPrivate cache_private = G_STATIC_PRIVATE_INIT;
2362   GLanguageNamesCache *cache = g_static_private_get (&cache_private);
2363   const gchar *value;
2364
2365   if (!cache)
2366     {
2367       cache = g_new0 (GLanguageNamesCache, 1);
2368       g_static_private_set (&cache_private, cache, language_names_cache_free);
2369     }
2370
2371   value = guess_category_value ("LC_MESSAGES");
2372   if (!value)
2373     value = "C";
2374
2375   if (!(cache->languages && strcmp (cache->languages, value) == 0))
2376     {
2377       gchar **languages;
2378       gchar **alist, **a;
2379       GSList *list, *l;
2380       gint i;
2381
2382       g_free (cache->languages);
2383       g_strfreev (cache->language_names);
2384       cache->languages = g_strdup (value);
2385
2386       alist = g_strsplit (value, ":", 0);
2387       list = NULL;
2388       for (a = alist; *a; a++)
2389         {
2390           gchar *b = unalias_lang (*a);
2391           list = g_slist_concat (list, _g_compute_locale_variants (b));
2392         }
2393       g_strfreev (alist);
2394       list = g_slist_append (list, g_strdup ("C"));
2395
2396       cache->language_names = languages = g_new (gchar *, g_slist_length (list) + 1);
2397       for (l = list, i = 0; l; l = l->next, i++)
2398         languages[i] = l->data;
2399       languages[i] = NULL;
2400
2401       g_slist_free (list);
2402     }
2403
2404   return (G_CONST_RETURN gchar * G_CONST_RETURN *) cache->language_names;
2405 }
2406
2407 /**
2408  * g_direct_hash:
2409  * @v: a #gpointer key
2410  *
2411  * Converts a gpointer to a hash value.
2412  * It can be passed to g_hash_table_new() as the @hash_func parameter, 
2413  * when using pointers as keys in a #GHashTable.
2414  *
2415  * Returns: a hash value corresponding to the key.
2416  */
2417 guint
2418 g_direct_hash (gconstpointer v)
2419 {
2420   return GPOINTER_TO_UINT (v);
2421 }
2422
2423 /**
2424  * g_direct_equal:
2425  * @v1: a key.
2426  * @v2: a key to compare with @v1.
2427  *
2428  * Compares two #gpointer arguments and returns %TRUE if they are equal.
2429  * It can be passed to g_hash_table_new() as the @key_equal_func
2430  * parameter, when using pointers as keys in a #GHashTable.
2431  * 
2432  * Returns: %TRUE if the two keys match.
2433  */
2434 gboolean
2435 g_direct_equal (gconstpointer v1,
2436                 gconstpointer v2)
2437 {
2438   return v1 == v2;
2439 }
2440
2441 /**
2442  * g_int_equal:
2443  * @v1: a pointer to a #gint key.
2444  * @v2: a pointer to a #gint key to compare with @v1.
2445  *
2446  * Compares the two #gint values being pointed to and returns 
2447  * %TRUE if they are equal.
2448  * It can be passed to g_hash_table_new() as the @key_equal_func
2449  * parameter, when using pointers to integers as keys in a #GHashTable.
2450  * 
2451  * Returns: %TRUE if the two keys match.
2452  */
2453 gboolean
2454 g_int_equal (gconstpointer v1,
2455              gconstpointer v2)
2456 {
2457   return *((const gint*) v1) == *((const gint*) v2);
2458 }
2459
2460 /**
2461  * g_int_hash:
2462  * @v: a pointer to a #gint key
2463  *
2464  * Converts a pointer to a #gint to a hash value.
2465  * It can be passed to g_hash_table_new() as the @hash_func parameter, 
2466  * when using pointers to integers values as keys in a #GHashTable.
2467  *
2468  * Returns: a hash value corresponding to the key.
2469  */
2470 guint
2471 g_int_hash (gconstpointer v)
2472 {
2473   return *(const gint*) v;
2474 }
2475
2476 /**
2477  * g_nullify_pointer:
2478  * @nullify_location: the memory address of the pointer.
2479  * 
2480  * Set the pointer at the specified location to %NULL.
2481  **/
2482 void
2483 g_nullify_pointer (gpointer *nullify_location)
2484 {
2485   g_return_if_fail (nullify_location != NULL);
2486
2487   *nullify_location = NULL;
2488 }
2489
2490 /**
2491  * g_get_codeset:
2492  * 
2493  * Get the codeset for the current locale.
2494  * 
2495  * Return value: a newly allocated string containing the name
2496  * of the codeset. This string must be freed with g_free().
2497  **/
2498 gchar *
2499 g_get_codeset (void)
2500 {
2501   const gchar *charset;
2502
2503   g_get_charset (&charset);
2504
2505   return g_strdup (charset);
2506 }
2507
2508 /* This is called from g_thread_init(). It's used to
2509  * initialize some static data in a threadsafe way.
2510  */
2511 void
2512 _g_utils_thread_init (void)
2513 {
2514   g_get_language_names ();
2515 }
2516
2517 #ifdef ENABLE_NLS
2518
2519 #include <libintl.h>
2520
2521 #ifdef G_PLATFORM_WIN32
2522
2523 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
2524
2525 static const gchar *
2526 _glib_get_locale_dir (void)
2527 {
2528   static const gchar *cache = NULL;
2529   if (cache == NULL)
2530     cache = g_win32_get_package_installation_subdirectory
2531       (GETTEXT_PACKAGE, dll_name, "lib\\locale");
2532
2533   return cache;
2534 }
2535
2536 #undef GLIB_LOCALE_DIR
2537 #define GLIB_LOCALE_DIR _glib_get_locale_dir ()
2538
2539 #endif /* G_PLATFORM_WIN32 */
2540
2541 G_CONST_RETURN gchar *
2542 _glib_gettext (const gchar *str)
2543 {
2544   static gboolean _glib_gettext_initialized = FALSE;
2545
2546   if (!_glib_gettext_initialized)
2547     {
2548       bindtextdomain(GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
2549 #    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
2550       bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2551 #    endif
2552       _glib_gettext_initialized = TRUE;
2553     }
2554   
2555   return dgettext (GETTEXT_PACKAGE, str);
2556 }
2557
2558 #endif /* ENABLE_NLS */
2559
2560 #ifdef G_OS_WIN32
2561
2562 /* Binary compatibility versions. Not for newly compiled code. */
2563
2564 #undef g_find_program_in_path
2565
2566 gchar*
2567 g_find_program_in_path (const gchar *program)
2568 {
2569   gchar *utf8_program = g_locale_to_utf8 (program, -1, NULL, NULL, NULL);
2570   gchar *utf8_retval = g_find_program_in_path_utf8 (utf8_program);
2571   gchar *retval;
2572
2573   g_free (utf8_program);
2574   if (utf8_retval == NULL)
2575     return NULL;
2576   retval = g_locale_from_utf8 (utf8_retval, -1, NULL, NULL, NULL);
2577   g_free (utf8_retval);
2578
2579   return retval;
2580 }
2581
2582 #undef g_get_current_dir
2583
2584 gchar*
2585 g_get_current_dir (void)
2586 {
2587   gchar *utf8_dir = g_get_current_dir_utf8 ();
2588   gchar *dir = g_locale_from_utf8 (utf8_dir, -1, NULL, NULL, NULL);
2589   g_free (utf8_dir);
2590   return dir;
2591 }
2592
2593 #undef g_getenv
2594
2595 G_CONST_RETURN gchar*
2596 g_getenv (const gchar *variable)
2597 {
2598   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
2599   const gchar *utf8_value = g_getenv_utf8 (utf8_variable);
2600   gchar *value;
2601   GQuark quark;
2602
2603   g_free (utf8_variable);
2604   if (!utf8_value)
2605     return NULL;
2606   value = g_locale_from_utf8 (utf8_value, -1, NULL, NULL, NULL);
2607   quark = g_quark_from_string (value);
2608   g_free (value);
2609
2610   return g_quark_to_string (quark);
2611 }
2612
2613 #undef g_setenv
2614
2615 gboolean
2616 g_setenv (const gchar *variable, 
2617           const gchar *value, 
2618           gboolean     overwrite)
2619 {
2620   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
2621   gchar *utf8_value = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
2622   gboolean retval = g_setenv_utf8 (utf8_variable, utf8_value, overwrite);
2623
2624   g_free (utf8_variable);
2625   g_free (utf8_value);
2626
2627   return retval;
2628 }
2629
2630 #undef g_unsetenv
2631
2632 void
2633 g_unsetenv (const gchar *variable)
2634 {
2635   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
2636
2637   g_unsetenv_utf8 (utf8_variable);
2638
2639   g_free (utf8_variable);
2640 }
2641
2642 #undef g_get_user_name
2643
2644 G_CONST_RETURN gchar*
2645 g_get_user_name (void)
2646 {
2647   G_LOCK (g_utils_global);
2648   if (!g_tmp_dir)
2649     g_get_any_init ();
2650   G_UNLOCK (g_utils_global);
2651   
2652   return g_user_name_cp;
2653 }
2654
2655 #undef g_get_real_name
2656
2657 G_CONST_RETURN gchar*
2658 g_get_real_name (void)
2659 {
2660   G_LOCK (g_utils_global);
2661   if (!g_tmp_dir)
2662     g_get_any_init ();
2663   G_UNLOCK (g_utils_global);
2664  
2665   return g_real_name_cp;
2666 }
2667
2668 #undef g_get_home_dir
2669
2670 G_CONST_RETURN gchar*
2671 g_get_home_dir (void)
2672 {
2673   G_LOCK (g_utils_global);
2674   if (!g_tmp_dir)
2675     g_get_any_init ();
2676   G_UNLOCK (g_utils_global);
2677
2678   return g_home_dir_cp;
2679 }
2680
2681 #undef g_get_tmp_dir
2682
2683 G_CONST_RETURN gchar*
2684 g_get_tmp_dir (void)
2685 {
2686   G_LOCK (g_utils_global);
2687   if (!g_tmp_dir)
2688     g_get_any_init ();
2689   G_UNLOCK (g_utils_global);
2690
2691   return g_tmp_dir_cp;
2692 }
2693
2694 #endif