1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
28 * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
46 #include <sys/types.h>
47 #ifdef HAVE_SYS_PARAM_H
48 #include <sys/param.h>
51 /* implement gutils's inline functions
53 #define G_IMPLEMENT_INLINES 1
58 #define G_PATH_LENGTH MAXPATHLEN
59 #elif defined (PATH_MAX)
60 #define G_PATH_LENGTH PATH_MAX
61 #elif defined (_PC_PATH_MAX)
62 #define G_PATH_LENGTH sysconf(_PC_PATH_MAX)
64 #define G_PATH_LENGTH 2048
67 #ifdef G_PLATFORM_WIN32
68 # define STRICT /* Strict typing, please */
72 #endif /* G_PLATFORM_WIN32 */
82 const guint glib_major_version
= GLIB_MAJOR_VERSION
;
83 const guint glib_minor_version
= GLIB_MINOR_VERSION
;
84 const guint glib_micro_version
= GLIB_MICRO_VERSION
;
85 const guint glib_interface_age
= GLIB_INTERFACE_AGE
;
86 const guint glib_binary_age
= GLIB_BINARY_AGE
;
88 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
90 g_memmove (gpointer dest
, gconstpointer src
, gulong len
)
92 gchar
* destptr
= dest
;
93 const gchar
* srcptr
= src
;
94 if (src
+ len
< dest
|| dest
+ len
< src
)
96 bcopy (src
, dest
, len
);
102 *(destptr
++) = *(srcptr
++);
109 *(--destptr
) = *(--srcptr
);
112 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
115 g_atexit (GVoidFunc func
)
118 const gchar
*error
= NULL
;
120 /* keep this in sync with glib.h */
122 #ifdef G_NATIVE_ATEXIT
123 result
= ATEXIT (func
);
125 error
= g_strerror (errno
);
126 #elif defined (HAVE_ATEXIT)
127 # ifdef NeXT /* @#%@! NeXTStep */
128 result
= !atexit ((void (*)(void)) func
);
130 error
= g_strerror (errno
);
132 result
= atexit ((void (*)(void)) func
);
134 error
= g_strerror (errno
);
136 #elif defined (HAVE_ON_EXIT)
137 result
= on_exit ((void (*)(int, void *)) func
, NULL
);
139 error
= g_strerror (errno
);
142 error
= "no implementation";
143 #endif /* G_NATIVE_ATEXIT */
146 g_error ("Could not register atexit() function: %s", error
);
149 /* Based on execvp() from GNU Libc.
150 * Some of this code is cut-and-pasted into gspawn.c
154 my_strchrnul (const gchar
*str
, gchar c
)
156 gchar
*p
= (gchar
*)str
;
157 while (*p
&& (*p
!= c
))
165 gchar
*inner_find_program_in_path (const gchar
*program
);
168 g_find_program_in_path (const gchar
*program
)
170 const gchar
*last_dot
= strrchr (program
, '.');
172 if (last_dot
== NULL
|| strchr (last_dot
, '\\') != NULL
)
174 const gint program_length
= strlen (program
);
175 const gchar
*pathext
= getenv ("PATHEXT");
177 gchar
*decorated_program
;
181 pathext
= ".com;.exe;.bat";
187 p
= my_strchrnul (pathext
, ';');
189 decorated_program
= g_malloc (program_length
+ (p
-pathext
) + 1);
190 memcpy (decorated_program
, program
, program_length
);
191 memcpy (decorated_program
+program_length
, pathext
, p
-pathext
);
192 decorated_program
[program_length
+ (p
-pathext
)] = '\0';
194 retval
= inner_find_program_in_path (decorated_program
);
195 g_free (decorated_program
);
199 } while (*p
++ != '\0');
203 return inner_find_program_in_path (program
);
206 #define g_find_program_in_path inner_find_program_in_path
210 * g_find_program_in_path:
211 * @program: a program name
213 * Locates the first executable named @program in the user's path, in the
214 * same way that execvp() would locate it. Returns an allocated string
215 * with the absolute path name, or NULL if the program is not found in
216 * the path. If @program is already an absolute path, returns a copy of
217 * @program if @program exists and is executable, and NULL otherwise.
219 * On Windows, if @program does not have a file type suffix, tries to
220 * append the suffixes in the PATHEXT environment variable (if that
221 * doesn't exists, the suffixes .com, .exe, and .bat) in turn, and
222 * then look for the resulting file name in the same way as
223 * CreateProcess() would. This means first in the directory where the
224 * program was loaded from, then in the current directory, then in the
225 * Windows 32-bit system directory, then in the Windows directory, and
226 * finally in the directories in the PATH environment variable. If
227 * the program is found, the return value contains the full name
228 * including the type suffix.
230 * Return value: absolute path, or NULL
233 g_find_program_in_path (const gchar
*program
)
235 const gchar
*path
, *p
;
236 gchar
*name
, *freeme
;
243 g_return_val_if_fail (program
!= NULL
, NULL
);
245 /* If it is an absolute path, or a relative path including subdirectories,
246 * don't look in PATH.
248 if (g_path_is_absolute (program
)
249 || strchr (program
, G_DIR_SEPARATOR
) != NULL
)
251 if (g_file_test (program
, G_FILE_TEST_IS_EXECUTABLE
))
252 return g_strdup (program
);
257 path
= g_getenv ("PATH");
261 /* There is no `PATH' in the environment. The default
262 * search path in GNU libc is the current directory followed by
263 * the path `confstr' returns for `_CS_PATH'.
266 /* In GLib we put . last, for security, and don't use the
267 * unportable confstr(); UNIX98 does not actually specify
268 * what to search if PATH is unset. POSIX may, dunno.
271 path
= "/bin:/usr/bin:.";
276 gchar moddir
[MAXPATHLEN
], sysdir
[MAXPATHLEN
], windir
[MAXPATHLEN
];
278 GetModuleFileName (NULL
, moddir
, sizeof (moddir
));
279 tmp
= g_path_get_dirname (moddir
);
280 GetSystemDirectory (sysdir
, sizeof (sysdir
));
281 GetWindowsDirectory (windir
, sizeof (windir
));
282 path_tmp
= g_strconcat (tmp
, ";.;", sysdir
, ";", windir
,
283 (path
!= NULL
? ";" : NULL
),
284 (path
!= NULL
? path
: NULL
),
291 len
= strlen (program
) + 1;
292 pathlen
= strlen (path
);
293 freeme
= name
= g_malloc (pathlen
+ len
+ 1);
295 /* Copy the file name at the top, including '\0' */
296 memcpy (name
+ pathlen
+ 1, program
, len
);
297 name
= name
+ pathlen
;
298 /* And add the slash before the filename */
299 *name
= G_DIR_SEPARATOR
;
307 p
= my_strchrnul (path
, G_SEARCHPATH_SEPARATOR
);
310 /* Two adjacent colons, or a colon at the beginning or the end
311 * of `PATH' means to search the current directory.
315 startp
= memcpy (name
- (p
- path
), path
, p
- path
);
317 if (g_file_test (startp
, G_FILE_TEST_IS_EXECUTABLE
))
320 ret
= g_strdup (startp
);
328 while (*p
++ != '\0');
339 g_snprintf (gchar
*str
,
344 #ifdef HAVE_VSNPRINTF
348 g_return_val_if_fail (str
!= NULL
, 0);
349 g_return_val_if_fail (n
> 0, 0);
350 g_return_val_if_fail (fmt
!= NULL
, 0);
352 va_start (args
, fmt
);
353 retval
= vsnprintf (str
, n
, fmt
, args
);
359 retval
= strlen (str
);
363 #else /* !HAVE_VSNPRINTF */
367 g_return_val_if_fail (str
!= NULL
, 0);
368 g_return_val_if_fail (n
> 0, 0);
369 g_return_val_if_fail (fmt
!= NULL
, 0);
371 va_start (args
, fmt
);
372 printed
= g_strdup_vprintf (fmt
, args
);
375 strncpy (str
, printed
, n
);
381 #endif /* !HAVE_VSNPRINTF */
385 g_vsnprintf (gchar
*str
,
390 #ifdef HAVE_VSNPRINTF
393 g_return_val_if_fail (str
!= NULL
, 0);
394 g_return_val_if_fail (n
> 0, 0);
395 g_return_val_if_fail (fmt
!= NULL
, 0);
397 retval
= vsnprintf (str
, n
, fmt
, args
);
402 retval
= strlen (str
);
406 #else /* !HAVE_VSNPRINTF */
409 g_return_val_if_fail (str
!= NULL
, 0);
410 g_return_val_if_fail (n
> 0, 0);
411 g_return_val_if_fail (fmt
!= NULL
, 0);
413 printed
= g_strdup_vprintf (fmt
, args
);
414 strncpy (str
, printed
, n
);
420 #endif /* !HAVE_VSNPRINTF */
424 g_parse_debug_string (const gchar
*string
,
425 const GDebugKey
*keys
,
431 g_return_val_if_fail (string
!= NULL
, 0);
433 if (!g_ascii_strcasecmp (string
, "all"))
435 for (i
=0; i
<nkeys
; i
++)
436 result
|= keys
[i
].value
;
440 const gchar
*p
= string
;
442 gboolean done
= FALSE
;
453 for (i
=0; i
<nkeys
; i
++)
454 if (g_ascii_strncasecmp(keys
[i
].key
, p
, q
- p
) == 0 &&
455 keys
[i
].key
[q
- p
] == '\0')
456 result
|= keys
[i
].value
;
465 G_CONST_RETURN gchar
*
466 g_basename (const gchar
*file_name
)
468 register gchar
*base
;
470 g_return_val_if_fail (file_name
!= NULL
, NULL
);
472 base
= strrchr (file_name
, G_DIR_SEPARATOR
);
477 if (g_ascii_isalpha (file_name
[0]) && file_name
[1] == ':')
478 return (gchar
*) file_name
+ 2;
479 #endif /* G_OS_WIN32 */
481 return (gchar
*) file_name
;
485 g_path_get_basename (const gchar
*file_name
)
487 register gssize base
;
488 register gssize last_nonslash
;
492 g_return_val_if_fail (file_name
!= NULL
, NULL
);
494 if (file_name
[0] == '\0')
496 return g_strdup (".");
498 last_nonslash
= strlen (file_name
) - 1;
500 while (last_nonslash
>= 0 && file_name
[last_nonslash
] == G_DIR_SEPARATOR
)
503 if (last_nonslash
== -1)
504 /* string only containing slashes */
505 return g_strdup (G_DIR_SEPARATOR_S
);
508 if (last_nonslash
== 1 && g_ascii_isalpha (file_name
[0]) && file_name
[1] == ':')
509 /* string only containing slashes and a drive */
510 return g_strdup (G_DIR_SEPARATOR_S
);
511 #endif /* G_OS_WIN32 */
513 base
= last_nonslash
;
515 while (base
>=0 && file_name
[base
] != G_DIR_SEPARATOR
)
519 if (base
== -1 && g_ascii_isalpha (file_name
[0]) && file_name
[1] == ':')
521 #endif /* G_OS_WIN32 */
523 len
= last_nonslash
- base
;
524 retval
= g_malloc (len
+ 1);
525 memcpy (retval
, file_name
+ base
+ 1, len
);
531 g_path_is_absolute (const gchar
*file_name
)
533 g_return_val_if_fail (file_name
!= NULL
, FALSE
);
535 if (file_name
[0] == G_DIR_SEPARATOR
537 || file_name
[0] == '/'
543 /* Recognize drive letter on native Windows */
544 if (g_ascii_isalpha (file_name
[0]) && file_name
[1] == ':' && (file_name
[2] == G_DIR_SEPARATOR
|| file_name
[2] == '/'))
546 #endif /* G_OS_WIN32 */
551 G_CONST_RETURN gchar
*
552 g_path_skip_root (const gchar
*file_name
)
554 g_return_val_if_fail (file_name
!= NULL
, NULL
);
556 #ifdef G_PLATFORM_WIN32
557 /* Skip \\server\share (Win32) or //server/share (Cygwin) */
558 if (file_name
[0] == G_DIR_SEPARATOR
&&
559 file_name
[1] == G_DIR_SEPARATOR
&&
564 if ((p
= strchr (file_name
+ 2, G_DIR_SEPARATOR
)) > file_name
+ 2 &&
569 while (file_name
[0] && file_name
[0] != G_DIR_SEPARATOR
)
572 /* Possibly skip a backslash after the share name */
573 if (file_name
[0] == G_DIR_SEPARATOR
)
576 return (gchar
*)file_name
;
581 /* Skip initial slashes */
582 if (file_name
[0] == G_DIR_SEPARATOR
)
584 while (file_name
[0] == G_DIR_SEPARATOR
)
586 return (gchar
*)file_name
;
591 if (g_ascii_isalpha (file_name
[0]) && file_name
[1] == ':' && file_name
[2] == G_DIR_SEPARATOR
)
592 return (gchar
*)file_name
+ 3;
599 g_path_get_dirname (const gchar
*file_name
)
601 register gchar
*base
;
604 g_return_val_if_fail (file_name
!= NULL
, NULL
);
606 base
= strrchr (file_name
, G_DIR_SEPARATOR
);
608 return g_strdup (".");
609 while (base
> file_name
&& *base
== G_DIR_SEPARATOR
)
611 len
= (guint
) 1 + base
- file_name
;
613 base
= g_new (gchar
, len
+ 1);
614 g_memmove (base
, file_name
, len
);
621 g_get_current_dir (void)
623 gchar
*buffer
= NULL
;
625 static gulong max_len
= 0;
628 max_len
= (G_PATH_LENGTH
== -1) ? 2048 : G_PATH_LENGTH
;
630 /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
631 * and, if that wasn't bad enough, hangs in doing so.
633 #if (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
634 buffer
= g_new (gchar
, max_len
+ 1);
636 dir
= getwd (buffer
);
637 #else /* !sun || !HAVE_GETCWD */
638 while (max_len
< G_MAXULONG
/ 2)
640 buffer
= g_new (gchar
, max_len
+ 1);
642 dir
= getcwd (buffer
, max_len
);
644 if (dir
|| errno
!= ERANGE
)
650 #endif /* !sun || !HAVE_GETCWD */
652 if (!dir
|| !*buffer
)
654 /* hm, should we g_error() out here?
655 * this can happen if e.g. "./" has mode \0000
657 buffer
[0] = G_DIR_SEPARATOR
;
661 dir
= g_strdup (buffer
);
667 G_CONST_RETURN gchar
*
668 g_getenv (const gchar
*variable
)
671 g_return_val_if_fail (variable
!= NULL
, NULL
);
673 return getenv (variable
);
675 G_LOCK_DEFINE_STATIC (getenv
);
681 static GArray
*environs
= NULL
;
686 g_return_val_if_fail (variable
!= NULL
, NULL
);
691 environs
= g_array_new (FALSE
, FALSE
, sizeof (struct env_struct
));
693 /* First we try to find the envinronment variable inside the already
697 for (i
= 0; i
< environs
->len
; i
++)
699 env
= &g_array_index (environs
, struct env_struct
, i
);
700 if (strcmp (env
->key
, variable
) == 0)
702 g_assert (env
->value
);
708 /* If not found, we ask the system */
710 system_env
= getenv (variable
);
717 /* On Windows NT, it is relatively typical that environment variables
718 * contain references to other environment variables. Handle that by
719 * calling ExpandEnvironmentStrings.
722 g_array_set_size (environs
, environs
->len
+ 1);
724 env
= &g_array_index (environs
, struct env_struct
, environs
->len
- 1);
726 /* First check how much space we need */
727 length
= ExpandEnvironmentStrings (system_env
, dummy
, 2);
729 /* Then allocate that much, and actualy do the expansion and insert
730 * the new found pair into our buffer
733 env
->value
= g_malloc (length
);
734 env
->key
= g_strdup (variable
);
736 ExpandEnvironmentStrings (system_env
, env
->value
, length
);
744 G_LOCK_DEFINE_STATIC (g_utils_global
);
746 static gchar
*g_tmp_dir
= NULL
;
747 static gchar
*g_user_name
= NULL
;
748 static gchar
*g_real_name
= NULL
;
749 static gchar
*g_home_dir
= NULL
;
751 /* HOLDS: g_utils_global_lock */
753 g_get_any_init (void)
757 g_tmp_dir
= g_strdup (g_getenv ("TMPDIR"));
759 g_tmp_dir
= g_strdup (g_getenv ("TMP"));
761 g_tmp_dir
= g_strdup (g_getenv ("TEMP"));
767 g_tmp_dir
= g_strdup (P_tmpdir
);
768 k
= strlen (g_tmp_dir
);
769 if (k
> 1 && g_tmp_dir
[k
- 1] == G_DIR_SEPARATOR
)
770 g_tmp_dir
[k
- 1] = '\0';
777 g_tmp_dir
= g_strdup ("/tmp");
778 #else /* G_OS_WIN32 */
779 g_tmp_dir
= g_strdup ("C:\\");
780 #endif /* G_OS_WIN32 */
784 g_home_dir
= g_strdup (g_getenv ("HOME"));
787 /* In case HOME is Unix-style (it happens), convert it to
793 while ((p
= strchr (g_home_dir
, '/')) != NULL
)
799 /* USERPROFILE is probably the closest equivalent to $HOME? */
800 if (getenv ("USERPROFILE") != NULL
)
801 g_home_dir
= g_strdup (g_getenv ("USERPROFILE"));
806 /* At least at some time, HOMEDRIVE and HOMEPATH were used
807 * to point to the home directory, I think. But on Windows
808 * 2000 HOMEDRIVE seems to be equal to SYSTEMDRIVE, and
809 * HOMEPATH is its root "\"?
811 if (getenv ("HOMEDRIVE") != NULL
&& getenv ("HOMEPATH") != NULL
)
813 gchar
*homedrive
, *homepath
;
815 homedrive
= g_strdup (g_getenv ("HOMEDRIVE"));
816 homepath
= g_strdup (g_getenv ("HOMEPATH"));
818 g_home_dir
= g_strconcat (homedrive
, homepath
, NULL
);
823 #endif /* G_OS_WIN32 */
827 struct passwd
*pw
= NULL
;
828 gpointer buffer
= NULL
;
831 # if defined (HAVE_POSIX_GETPWUID_R) || defined (HAVE_NONPOSIX_GETPWUID_R)
833 # ifdef _SC_GETPW_R_SIZE_MAX
834 /* This reurns the maximum length */
835 glong bufsize
= sysconf (_SC_GETPW_R_SIZE_MAX
);
839 # else /* _SC_GETPW_R_SIZE_MAX */
841 # endif /* _SC_GETPW_R_SIZE_MAX */
846 buffer
= g_malloc (bufsize
);
849 # ifdef HAVE_POSIX_GETPWUID_R
850 error
= getpwuid_r (getuid (), &pwd
, buffer
, bufsize
, &pw
);
851 error
= error
< 0 ? errno
: error
;
852 # else /* HAVE_NONPOSIX_GETPWUID_R */
854 error
= getpwuid_r (getuid (), &pwd
, buffer
, bufsize
);
855 pw
= error
== 0 ? &pwd
: NULL
;
857 pw
= getpwuid_r (getuid (), &pwd
, buffer
, bufsize
);
858 error
= pw
? 0 : errno
;
860 # endif /* HAVE_NONPOSIX_GETPWUID_R */
864 /* we bail out prematurely if the user id can't be found
865 * (should be pretty rare case actually), or if the buffer
866 * should be sufficiently big and lookups are still not
869 if (error
== 0 || error
== ENOENT
)
871 g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
875 if (bufsize
> 32 * 1024)
877 g_warning ("getpwuid_r(): failed due to: %s.",
886 # endif /* HAVE_POSIX_GETPWUID_R || HAVE_NONPOSIX_GETPWUID_R */
891 pw
= getpwuid (getuid ());
896 g_user_name
= g_strdup (pw
->pw_name
);
897 g_real_name
= g_strdup (pw
->pw_gecos
);
899 g_home_dir
= g_strdup (pw
->pw_dir
);
904 #else /* !HAVE_PWD_H */
911 if (GetUserName ((LPTSTR
) buffer
, (LPDWORD
) &len
))
913 g_user_name
= g_strdup (buffer
);
914 g_real_name
= g_strdup (buffer
);
917 # endif /* G_OS_WIN32 */
919 #endif /* !HAVE_PWD_H */
922 /* change '\\' in %HOME% to '/' */
923 g_strdelimit (g_home_dir
, "\\",'/');
926 g_user_name
= g_strdup ("somebody");
928 g_real_name
= g_strdup ("Unknown");
933 for (p
= g_real_name
; *p
; p
++)
937 p
= g_strdup (g_real_name
);
938 g_free (g_real_name
);
946 G_CONST_RETURN gchar
*
947 g_get_user_name (void)
949 G_LOCK (g_utils_global
);
952 G_UNLOCK (g_utils_global
);
957 G_CONST_RETURN gchar
*
958 g_get_real_name (void)
960 G_LOCK (g_utils_global
);
963 G_UNLOCK (g_utils_global
);
968 /* Return the home directory of the user. If there is a HOME
969 * environment variable, its value is returned, otherwise use some
970 * system-dependent way of finding it out. If no home directory can be
971 * deduced, return NULL.
974 G_CONST_RETURN gchar
*
975 g_get_home_dir (void)
977 G_LOCK (g_utils_global
);
980 G_UNLOCK (g_utils_global
);
985 /* Return a directory to be used to store temporary files. This is the
986 * value of the TMPDIR, TMP or TEMP environment variables (they are
987 * checked in that order). If none of those exist, use P_tmpdir from
988 * stdio.h. If that isn't defined, return "/tmp" on POSIXly systems,
989 * and C:\ on Windows.
992 G_CONST_RETURN gchar
*
995 G_LOCK (g_utils_global
);
998 G_UNLOCK (g_utils_global
);
1003 G_LOCK_DEFINE (g_prgname
);
1004 static gchar
*g_prgname
= NULL
;
1007 g_get_prgname (void)
1013 G_UNLOCK (g_prgname
);
1019 g_set_prgname (const gchar
*prgname
)
1023 g_prgname
= g_strdup (prgname
);
1024 G_UNLOCK (g_prgname
);
1028 g_direct_hash (gconstpointer v
)
1030 return GPOINTER_TO_UINT (v
);
1034 g_direct_equal (gconstpointer v1
,
1041 g_int_equal (gconstpointer v1
,
1044 return *((const gint
*) v1
) == *((const gint
*) v2
);
1048 g_int_hash (gconstpointer v
)
1050 return *(const gint
*) v
;
1054 * g_nullify_pointer:
1055 * @nullify_location: the memory address of the pointer.
1057 * Set the pointer at the specified location to %NULL.
1060 g_nullify_pointer (gpointer
*nullify_location
)
1062 g_return_if_fail (nullify_location
!= NULL
);
1064 *nullify_location
= NULL
;
1070 * Get the codeset for the current locale.
1072 * Return value: a newly allocated string containing the name
1073 * of the codeset. This string must be freed with g_free().
1076 g_get_codeset (void)
1079 char *result
= nl_langinfo (CODESET
);
1080 return g_strdup (result
);
1082 #ifdef G_PLATFORM_WIN32
1083 return g_strdup_printf ("CP%d", GetACP ());
1085 /* FIXME: Do something more intelligent based on setlocale (LC_CTYPE, NULL)
1087 return g_strdup ("ISO-8859-1");
1094 #include <libintl.h>
1096 #ifdef G_PLATFORM_WIN32
1098 G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name
)
1100 static const gchar
*
1101 _glib_get_locale_dir (void)
1103 static const gchar
*cache
= NULL
;
1105 cache
= g_win32_get_package_installation_subdirectory
1106 (GETTEXT_PACKAGE
, dll_name
, "lib\\locale");
1111 #undef GLIB_LOCALE_DIR
1112 #define GLIB_LOCALE_DIR _glib_get_locale_dir ()
1114 #endif /* G_PLATFORM_WIN32 */
1116 G_CONST_RETURN gchar
*
1117 _glib_gettext (const gchar
*str
)
1119 static gboolean _glib_gettext_initialized
= FALSE
;
1121 if (!_glib_gettext_initialized
)
1123 bindtextdomain(GETTEXT_PACKAGE
, GLIB_LOCALE_DIR
);
1124 _glib_gettext_initialized
= TRUE
;
1127 return dgettext (GETTEXT_PACKAGE
, str
);
1130 #endif /* ENABLE_NLS */