#include "glib.h"
#include "gprintfint.h"
#include "gthreadprivate.h"
+#include "glibintl.h"
#include "galias.h"
#ifdef MAXPATHLEN
# ifndef CSIDL_COMMON_APPDATA
# define CSIDL_COMMON_APPDATA 35
# endif
+# ifndef CSIDL_MYPICTURES
+# define CSIDL_MYPICTURES 0x27
+# endif
# ifndef CSIDL_COMMON_DOCUMENTS
# define CSIDL_COMMON_DOCUMENTS 46
# endif
#include <langinfo.h>
#endif
-#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
-#include <libintl.h>
-#endif
-
const guint glib_major_version = GLIB_MAJOR_VERSION;
const guint glib_minor_version = GLIB_MINOR_VERSION;
const guint glib_micro_version = GLIB_MICRO_VERSION;
#ifdef G_PLATFORM_WIN32
-G_WIN32_DLLMAIN_FOR_DLL_NAME (static, dll_name)
+static HMODULE glib_dll = NULL;
+
+#ifdef DLL_EXPORT
+
+BOOL WINAPI
+DllMain (HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ glib_dll = hinstDLL;
+
+ return TRUE;
+}
+
+#endif
+
+gchar *
+_glib_get_dll_directory (void)
+{
+ gchar *retval;
+ gchar *p;
+ wchar_t wc_fn[MAX_PATH];
+
+#ifdef DLL_EXPORT
+ if (glib_dll == NULL)
+ return NULL;
+#endif
+
+ /* This code is different from that in
+ * g_win32_get_package_installation_directory_of_module() in that
+ * here we return the actual folder where the GLib DLL is. We don't
+ * do the check for it being in a "bin" or "lib" subfolder and then
+ * returning the parent of that.
+ *
+ * In a statically built GLib, glib_dll will be NULL and we will
+ * thus look up the application's .exe file's location.
+ */
+ if (!GetModuleFileNameW (glib_dll, wc_fn, MAX_PATH))
+ return NULL;
+
+ retval = g_utf16_to_utf8 (wc_fn, -1, NULL, NULL, NULL);
+
+ p = strrchr (retval, G_DIR_SEPARATOR);
+ if (p == NULL)
+ {
+ /* Wtf? */
+ return NULL;
+ }
+ *p = '\0';
+
+ return retval;
+}
#endif
/**
* g_parse_debug_string:
* @string: a list of debug options separated by colons, spaces, or
- * commas; or the string "all" to set all flags.
+ * commas, or %NULL.
* @keys: pointer to an array of #GDebugKey which associate
* strings with bit flags.
* @nkeys: the number of #GDebugKey<!-- -->s in the array.
* within GDK and GTK+ to parse the debug options passed on the
* command line or through environment variables.
*
+ * If @string is equal to "all", all flags are set. If @string
+ * is equal to "help", all the available keys in @keys are printed
+ * out to standard error.
+ *
* Returns: the combined set of bit flags.
*/
guint
guint i;
guint result = 0;
- g_return_val_if_fail (string != NULL, 0);
+ if (string == NULL)
+ return 0;
/* this function is used by gmem.c/gslice.c initialization code,
* so introducing malloc dependencies here would require adaptions
for (i=0; i<nkeys; i++)
result |= keys[i].value;
}
+ else if (!g_ascii_strcasecmp (string, "help"))
+ {
+ /* using stdio directly for the reason stated above */
+ fprintf (stderr, "Supported debug values: ");
+ for (i=0; i<nkeys; i++)
+ fprintf (stderr, " %s", keys[i].key);
+ fprintf (stderr, "\n");
+ }
else
{
const gchar *p = string;
#else /* !sun || !HAVE_GETCWD */
while (max_len < G_MAXULONG / 2)
{
+ g_free (buffer);
buffer = g_new (gchar, max_len + 1);
*buffer = 0;
dir = getcwd (buffer, max_len);
if (dir || errno != ERANGE)
break;
- g_free (buffer);
max_len *= 2;
}
#endif /* !sun || !HAVE_GETCWD */
static gchar **g_system_config_dirs = NULL;
static gchar **g_user_special_dirs = NULL;
-static time_t g_user_special_dirs_mtime = (time_t) -1;
-static time_t g_user_special_dirs_stat_time = (time_t) -1;
/* fifteen minutes of fame for everybody */
#define G_USER_DIRS_EXPIRE 15 * 60
static gchar *
get_special_folder (int csidl)
{
- union {
- char c[MAX_PATH+1];
- wchar_t wc[MAX_PATH+1];
- } path;
+ wchar_t path[MAX_PATH+1];
HRESULT hr;
LPITEMIDLIST pidl = NULL;
BOOL b;
hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl);
if (hr == S_OK)
{
- b = SHGetPathFromIDListW (pidl, path.wc);
+ b = SHGetPathFromIDListW (pidl, path);
if (b)
- retval = g_utf16_to_utf8 (path.wc, -1, NULL, NULL, NULL);
+ retval = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL);
CoTaskMemFree (pidl);
}
return retval;
*
* Note that in contrast to traditional UNIX tools, this function
* prefers <filename>passwd</filename> entries over the <envar>HOME</envar>
- * environment variable.
- *
- * Returns: the current user's home directory.
+ * environment variable.
+ *
+ * One of the reasons for this decision is that applications in many
+ * cases need special handling to deal with the case where
+ * <envar>HOME</envar> is
+ * <simplelist>
+ * <member>Not owned by the user</member>
+ * <member>Not writeable</member>
+ * <member>Not even readable</member>
+ * </simplelist>
+ * Since applications are in general <emphasis>not</emphasis> written
+ * to deal with these situations it was considered better to make
+ * g_get_home_dir() not pay attention to <envar>HOME</envar> and to
+ * return the real home directory for the user. If applications
+ * want to pay attention to <envar>HOME</envar>, they can do:
+ * |[
+ * const char *homedir = g_getenv ("HOME");
+ * if (!homedir)
+ * homedir = g_get_home_dir (<!-- -->);
+ * ]|
+ *
+ * Returns: the current user's home directory
*/
G_CONST_RETURN gchar*
g_get_home_dir (void)
* The application name will be used in contexts such as error messages,
* or when displaying an application's name in the task list.
*
+ * Since: 2.2
**/
void
g_set_application_name (const gchar *application_name)
static void
load_user_special_dirs (void)
{
+ typedef HRESULT (WINAPI *t_SHGetKnownFolderPath) (const GUID *rfid,
+ DWORD dwFlags,
+ HANDLE hToken,
+ PWSTR *ppszPath);
+ t_SHGetKnownFolderPath p_SHGetKnownFolderPath;
+ static const GUID FOLDERID_Downloads =
+ { 0x374de290, 0x123f, 0x4565, { 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b } };
+ static const GUID FOLDERID_Public =
+ { 0xDFDF76A2, 0xC82A, 0x4D63, { 0x90, 0x6A, 0x56, 0x44, 0xAC, 0x45, 0x73, 0x85 } };
+ wchar_t *wcp;
+
+ p_SHGetKnownFolderPath = (t_SHGetKnownFolderPath) GetProcAddress (LoadLibrary ("shell32.dll"),
+ "SHGetKnownFolderPath");
+
g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
g_user_special_dirs[G_USER_DIRECTORY_DOCUMENTS] = get_special_folder (CSIDL_PERSONAL);
- g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY); /* XXX correct ? */
- g_user_special_dirs[G_USER_DIRECTORY_MUSIC] = get_special_folder (CSIDL_MYMUSIC);
- g_user_special_dirs[G_USER_DIRECTORY_PICTURES] = get_special_folder (CSIDL_MYPICTURES);
- g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS); /* XXX correct ? */
- g_user_special_dirs[G_USER_DIRECTORY_TEMPLATES] = get_special_folder (CSIDL_TEMPLATES);
- g_user_special_dirs[G_USER_DIRECTORY_VIDEOS] = get_special_folder (CSIDL_MYVIDEO);
-}
-#endif /* G_OS_WIN32 */
-
-#if defined(G_OS_WIN32) || defined(HAVE_CARBON)
-static void
-maybe_expire_user_special_dirs (void)
-{
- /* expire the user dirs after G_USER_DIRS_EXPIRE seconds */
- time_t now;
- time (&now);
- if (now > g_user_special_dirs_mtime + G_USER_DIRS_EXPIRE &&
- g_user_special_dirs)
+ if (p_SHGetKnownFolderPath == NULL)
{
- gint i;
-
- for (i = 0; i < G_USER_N_DIRECTORIES; i++)
- g_free (g_user_special_dirs[i]);
-
- g_free (g_user_special_dirs);
- g_user_special_dirs = NULL;
+ g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
}
-
- if (g_user_special_dirs == NULL)
- g_user_special_dirs_mtime = now;
-}
-#endif
-
-#if defined(G_OS_UNIX) && !defined(HAVE_CARBON)
-
-/* expire g_user_special_dirs if the config file
- * was modified between different reads
- */
-static void
-maybe_expire_user_special_dirs (void)
-{
- gchar *config_file;
- struct stat stat_buf;
- time_t now;
-
- /* don't stat() the file more often than necessary */
- time (&now);
- if (now < g_user_special_dirs_stat_time + 5)
- return;
-
- g_user_special_dirs_stat_time = now;
-
- config_file = g_build_filename (g_user_config_dir,
- "user-dirs.dirs",
- NULL);
-
- if (stat (config_file, &stat_buf) < 0)
- goto out;
-
- if (stat_buf.st_mtime != g_user_special_dirs_mtime &&
- g_user_special_dirs != NULL)
+ else
{
- gint i;
-
- for (i = 0; i < G_USER_N_DIRECTORIES; i++)
- g_free (g_user_special_dirs[i]);
-
- g_free (g_user_special_dirs);
- g_user_special_dirs = NULL;
+ wcp = NULL;
+ (*p_SHGetKnownFolderPath) (&FOLDERID_Downloads, 0, NULL, &wcp);
+ g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
+ if (g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] == NULL)
+ g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
+ CoTaskMemFree (wcp);
}
- g_user_special_dirs_mtime = stat_buf.st_mtime;
+ g_user_special_dirs[G_USER_DIRECTORY_MUSIC] = get_special_folder (CSIDL_MYMUSIC);
+ g_user_special_dirs[G_USER_DIRECTORY_PICTURES] = get_special_folder (CSIDL_MYPICTURES);
-out:
- g_free (config_file);
+ if (p_SHGetKnownFolderPath == NULL)
+ {
+ /* XXX */
+ g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS);
+ }
+ else
+ {
+ wcp = NULL;
+ (*p_SHGetKnownFolderPath) (&FOLDERID_Public, 0, NULL, &wcp);
+ g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
+ if (g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] == NULL)
+ g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS);
+ CoTaskMemFree (wcp);
+ }
+
+ g_user_special_dirs[G_USER_DIRECTORY_TEMPLATES] = get_special_folder (CSIDL_TEMPLATES);
+ g_user_special_dirs[G_USER_DIRECTORY_VIDEOS] = get_special_folder (CSIDL_MYVIDEO);
}
-
+#endif /* G_OS_WIN32 */
static void g_init_user_config_dir (void);
+#if defined(G_OS_UNIX) && !defined(HAVE_CARBON)
+
/* adapted from xdg-user-dir-lookup.c
*
* Copyright (C) 2007 Red Hat Inc.
* Returns the full path of a special directory using its logical id.
*
* On Unix this is done using the XDG special user directories.
+ * For compatibility with existing practise, %G_USER_DIRECTORY_DESKTOP
+ * falls back to <filename>$HOME/Desktop</filename> when XDG special
+ * user directories have not been set up.
+ *
+ * Depending on the platform, the user might be able to change the path
+ * of the special directory without requiring the session to restart; GLib
+ * will not reflect any change once the special directories are loaded.
*
* Return value: the path to the specified special directory, or %NULL
* if the logical id was not found. The returned string is owned by
G_LOCK (g_utils_global);
- maybe_expire_user_special_dirs ();
- if (g_user_special_dirs == NULL)
+ if (G_UNLIKELY (g_user_special_dirs == NULL))
{
g_user_special_dirs = g_new0 (gchar *, G_USER_N_DIRECTORIES);
if (g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] == NULL)
{
g_get_any_init ();
- g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = g_build_filename (g_home_dir, "Desktop", NULL);
+
+ g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] =
+ g_build_filename (g_home_dir, "Desktop", NULL);
}
}
static gboolean beenhere = FALSE;
typedef BOOL (WINAPI *t_GetModuleHandleExA) (DWORD, LPCTSTR, HMODULE *);
static t_GetModuleHandleExA p_GetModuleHandleExA = NULL;
- HMODULE hmodule;
+ HMODULE hmodule = NULL;
if (!address)
return NULL;
get_module_share_dir (gconstpointer address)
{
HMODULE hmodule;
- gchar *filename = NULL;
- gchar *p, *retval;
- wchar_t wfilename[MAX_PATH];
+ gchar *filename;
+ gchar *retval;
hmodule = get_module_for_address (address);
if (hmodule == NULL)
return NULL;
- if (GetModuleFileNameW (hmodule, wfilename, G_N_ELEMENTS (wfilename)))
- filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
-
- if (filename == NULL)
- return NULL;
-
- if ((p = strrchr (filename, G_DIR_SEPARATOR)) != NULL)
- *p = '\0';
-
- p = strrchr (filename, G_DIR_SEPARATOR);
- if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0))
- *p = '\0';
-
+ filename = g_win32_get_package_installation_directory_of_module (hmodule);
retval = g_build_filename (filename, "share", NULL);
g_free (filename);
}
G_CONST_RETURN gchar * G_CONST_RETURN *
-g_win32_get_system_data_dirs_for_module (gconstpointer address)
+g_win32_get_system_data_dirs_for_module (void (*address_of_function)())
{
GArray *data_dirs;
HMODULE hmodule;
static GHashTable *per_module_data_dirs = NULL;
gchar **retval;
gchar *p;
+ gchar *exe_root;
- if (address)
+ if (address_of_function)
{
G_LOCK (g_utils_global);
- hmodule = get_module_for_address (address);
+ hmodule = get_module_for_address (address_of_function);
if (hmodule != NULL)
{
if (per_module_data_dirs == NULL)
* subdirectory of the installation directory for the package
* our caller is a part of.
*
- * The address parameter, if non-NULL, points to a function in the
- * calling module. Use that to determine that module's installation
- * folder, and use its "share" subfolder.
+ * The address_of_function parameter, if non-NULL, points to a
+ * function in the calling module. Use that to determine that
+ * module's installation folder, and use its "share" subfolder.
*
* Additionally, also use the "share" subfolder of the installation
* locations of GLib and the .exe file being run.
* function.
*/
- p = get_module_share_dir (address);
+ p = get_module_share_dir (address_of_function);
if (p)
g_array_append_val (data_dirs, p);
- p = g_win32_get_package_installation_subdirectory (NULL, dll_name, "share");
- if (p)
- g_array_append_val (data_dirs, p);
+ if (glib_dll != NULL)
+ {
+ gchar *glib_root = g_win32_get_package_installation_directory_of_module (glib_dll);
+ p = g_build_filename (glib_root, "share", NULL);
+ if (p)
+ g_array_append_val (data_dirs, p);
+ g_free (glib_root);
+ }
- p = g_win32_get_package_installation_subdirectory (NULL, NULL, "share");
+ exe_root = g_win32_get_package_installation_directory_of_module (NULL);
+ p = g_build_filename (exe_root, "share", NULL);
if (p)
g_array_append_val (data_dirs, p);
+ g_free (exe_root);
retval = (gchar **) g_array_free (data_dirs, FALSE);
- if (address)
+ if (address_of_function)
{
if (hmodule != NULL)
g_hash_table_insert (per_module_data_dirs, hmodule, retval);
g_get_language_names ();
}
-#ifdef ENABLE_NLS
-
-#include <libintl.h>
-
#ifdef G_OS_WIN32
/**
* _glib_get_locale_dir:
*
- * Return the path to the lib\locale subfolder of the GLib
- * installation folder. The path is in the system codepage. We have to
- * use system codepage as bindtextdomain() doesn't have a UTF-8
- * interface.
+ * Return the path to the share\locale or lib\locale subfolder of the
+ * GLib installation folder. The path is in the system codepage. We
+ * have to use system codepage as bindtextdomain() doesn't have a
+ * UTF-8 interface.
*/
-static const gchar *
+static gchar *
_glib_get_locale_dir (void)
{
- gchar *dir, *cp_dir;
+ gchar *install_dir = NULL, *locale_dir;
gchar *retval = NULL;
- dir = g_win32_get_package_installation_directory (GETTEXT_PACKAGE, dll_name);
- cp_dir = g_win32_locale_filename_from_utf8 (dir);
- g_free (dir);
+ if (glib_dll != NULL)
+ install_dir = g_win32_get_package_installation_directory_of_module (glib_dll);
- if (cp_dir)
+ if (install_dir)
{
- /* Don't use g_build_filename() on pathnames in the system
- * codepage. In CJK locales cp_dir might end with a double-byte
- * character whose trailing byte is a backslash.
+ /*
+ * Append "/share/locale" or "/lib/locale" depending on whether
+ * autoconfigury detected GNU gettext or not.
*/
- retval = g_strconcat (cp_dir, "\\lib\\locale", NULL);
- g_free (cp_dir);
+ const char *p = GLIB_LOCALE_DIR + strlen (GLIB_LOCALE_DIR);
+ while (*--p != '/')
+ ;
+ while (*--p != '/')
+ ;
+
+ locale_dir = g_build_filename (install_dir, p, NULL);
+
+ retval = g_win32_locale_filename_from_utf8 (locale_dir);
+
+ g_free (install_dir);
+ g_free (locale_dir);
}
if (retval)
}
#undef GLIB_LOCALE_DIR
-#define GLIB_LOCALE_DIR _glib_get_locale_dir ()
#endif /* G_OS_WIN32 */
+/**
+ * glib_gettext:
+ * @str: The string to be translated
+ *
+ * Returns the translated string from the glib translations.
+ * This is an internal function and should only be used by
+ * the internals of glib (such as libgio).
+ *
+ * Returns: the transation of @str to the current locale
+ */
G_CONST_RETURN gchar *
-_glib_gettext (const gchar *str)
+glib_gettext (const gchar *str)
{
static gboolean _glib_gettext_initialized = FALSE;
if (!_glib_gettext_initialized)
{
- bindtextdomain(GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
+#ifdef G_OS_WIN32
+ gchar *tmp = _glib_get_locale_dir ();
+ bindtextdomain (GETTEXT_PACKAGE, tmp);
+ g_free (tmp);
+#else
+ bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
+#endif
# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
# endif
_glib_gettext_initialized = TRUE;
}
- return dgettext (GETTEXT_PACKAGE, str);
+ return g_dgettext (GETTEXT_PACKAGE, str);
}
-#endif /* ENABLE_NLS */
-
-#ifdef G_OS_WIN32
+#if defined (G_OS_WIN32) && !defined (_WIN64)
/* Binary compatibility versions. Not for newly compiled code. */