aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/file-utils.c85
-rw-r--r--src/file-utils.h12
-rw-r--r--src/interface-gtk/interface.c32
-rw-r--r--src/main.c23
4 files changed, 118 insertions, 34 deletions
diff --git a/src/file-utils.c b/src/file-utils.c
index 3f8f721..b7e5418 100644
--- a/src/file-utils.c
+++ b/src/file-utils.c
@@ -19,6 +19,7 @@
#include "config.h"
#endif
+#define _GNU_SOURCE
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -35,6 +36,10 @@
#include <glib.h>
#include <glib/gstdio.h>
+#ifdef G_OS_UNIX
+#include <dlfcn.h>
+#endif
+
#include "sciteco.h"
#include "qreg.h"
#include "interface.h"
@@ -179,6 +184,86 @@ teco_file_is_visible(const gchar *path)
#endif /* !G_OS_WIN32 */
+#ifdef G_OS_WIN32
+
+gchar *
+teco_file_get_program_path(void)
+{
+ TCHAR buf[MAX_PATH];
+ if (!GetModuleFileNameW(NULL, buf, G_N_ELEMENTS(buf))
+ return g_get_current_dir();
+ g_autofree gchar *exe = g_utf16_to_utf8(buf, -1, NULL, NULL, NULL);
+ return g_path_get_dirname(exe);
+}
+
+#elif defined(__linux__)
+
+gchar *
+teco_file_get_program_path(void)
+{
+ gchar buf[PATH_MAX];
+ ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf)-1);
+ if (G_UNLIKELY(len < 0))
+ /* almost certainly wrong */
+ return g_get_current_dir();
+ buf[len] = '\0';
+
+ return g_path_get_dirname(buf);
+}
+
+#elif defined(G_OS_UNIX)
+
+/*
+ * At least works on FreeBSD, even though it also has
+ * sysctl(KERN_PROC_PATHNAME).
+ * We assume it works on all other UNIXes as well.
+ */
+gchar *
+teco_file_get_program_path(void)
+{
+ Dl_info info;
+ return dladdr(teco_file_get_program_path, &info)
+ ? g_path_get_dirname(info.dli_fname) : g_get_current_dir();
+}
+
+#else /* !G_OS_WIN32 && !__linux__ && !G_OS_UNIX */
+
+/*
+ * This is almost guaranteed to be wrong,
+ * meaning that SciTECO cannot be made relocatable on these platforms.
+ * It may be worth evaluating argv[0] on these platforms.
+ */
+gchar *
+teco_file_get_program_path(void)
+{
+ return g_get_current_dir();
+}
+
+#endif
+
+/**
+ * Get the datadir.
+ *
+ * By default it is hardcoded to an absolute path at
+ * build time.
+ * However, you can also build relocateable binaries
+ * where the datadir is relative to the program's executable.
+ *
+ * @note Beginning with glib v2.58, we could directly use
+ * g_canonicalize_filename().
+ */
+gchar *
+teco_file_get_datadir(void)
+{
+ if (g_path_is_absolute(SCITECODATADIR))
+ return g_strdup(SCITECODATADIR);
+
+ /* relocateable binary - datadir is relative to binary */
+ g_autofree gchar *program_path = teco_file_get_program_path();
+ g_autofree gchar *datadir = g_build_filename(program_path, SCITECODATADIR, NULL);
+ return teco_file_get_absolute_path(datadir);
+}
+
/**
* Perform tilde expansion on a file name or path.
*
diff --git a/src/file-utils.h b/src/file-utils.h
index 4ee59e6..e974e2f 100644
--- a/src/file-utils.h
+++ b/src/file-utils.h
@@ -68,6 +68,18 @@ teco_file_normalize_path(gchar *path)
gboolean teco_file_is_visible(const gchar *path);
+/**
+ * Get absolute path of the program executable.
+ *
+ * This may return the current working directory on
+ * unsupported platforms.
+ *
+ * @return Newly-allocated path.
+ */
+gchar *teco_file_get_program_path(void);
+
+gchar *teco_file_get_datadir(void);
+
gchar *teco_file_expand_path(const gchar *path);
/**
diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c
index 3121b05..829310a 100644
--- a/src/interface-gtk/interface.c
+++ b/src/interface-gtk/interface.c
@@ -51,6 +51,7 @@
#include "sciteco.h"
#include "error.h"
#include "string-utils.h"
+#include "file-utils.h"
#include "cmdline.h"
#include "qreg.h"
#include "ring.h"
@@ -1124,6 +1125,8 @@ teco_interface_event_loop(GError **error)
}
g_assert(scitecoconfig.data != NULL);
+ g_autofree gchar *datadir = teco_file_get_datadir();
+
/*
* Initialize the CSS variable provider and the CSS provider
* for the included fallback.css.
@@ -1138,14 +1141,7 @@ teco_interface_event_loop(GError **error)
if (!g_file_test(user_css_file, G_FILE_TEST_IS_REGULAR)) {
/* use fallback CSS */
g_free(user_css_file);
- /*
- * FIXME: See above for icons.
- */
-#ifdef G_OS_WIN32
- user_css_file = g_build_filename(scitecoconfig.data, "fallback.css", NULL);
-#else
- user_css_file = g_build_filename(SCITECODATADIR, "fallback.css", NULL);
-#endif
+ user_css_file = g_build_filename(datadir, "fallback.css", NULL);
}
GtkCssProvider *user_css_provider = gtk_css_provider_new();
@@ -1170,15 +1166,10 @@ teco_interface_event_loop(GError **error)
/*
* FIXME: This is necessary so that the icon themes are found in the same
* directory as sciteco.exe.
- * This fails of course when $SCITECOCONFIG is changed.
- * We should perhaps always use the absolute path of sciteco.exe.
- * If you want to install SciTECO differently, you can still set
- * $XDG_DATA_DIRS.
- *
- * FIXME FIXME FIXME: This is also currently broken.
*/
- //g_autofree char *theme_path = g_build_filename(scitecoconfig.data, "icons");
- //gtk_icon_theme_prepend_search_path(gtk_icon_theme_get_default(), theme_path);
+ g_autofree gchar *program_path = teco_file_get_program_path();
+ g_autofree gchar *theme_path = g_build_filename(program_path, "icons", NULL);
+ gtk_icon_theme_prepend_search_path(gtk_icon_theme_get_default(), theme_path);
#else
/*
* Load icons for the GTK window.
@@ -1186,17 +1177,16 @@ teco_interface_event_loop(GError **error)
* as a resource will be used by default.
*/
static const gchar *icon_files[] = {
- SCITECODATADIR G_DIR_SEPARATOR_S "sciteco-48.png",
- SCITECODATADIR G_DIR_SEPARATOR_S "sciteco-32.png",
- SCITECODATADIR G_DIR_SEPARATOR_S "sciteco-16.png"
+ "sciteco-48.png", "sciteco-32.png", "sciteco-16.png"
};
GList *icon_list = NULL;
for (gint i = 0; i < G_N_ELEMENTS(icon_files); i++) {
- GdkPixbuf *icon_pixbuf = gdk_pixbuf_new_from_file(icon_files[i], NULL);
+ g_autofree gchar *icon_file = g_build_filename(datadir, icon_files[i], NULL);
+ GdkPixbuf *icon_pixbuf = gdk_pixbuf_new_from_file(icon_file, NULL);
/* fail silently if there's a problem with one of the icons */
- if (icon_pixbuf)
+ if (G_LIKELY(icon_pixbuf != NULL))
icon_list = g_list_append(icon_list, icon_pixbuf);
}
diff --git a/src/main.c b/src/main.c
index 45149e6..e2c6b9e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -77,15 +77,15 @@ volatile sig_atomic_t teco_interrupted = FALSE;
* program's directory.
*/
static inline gchar *
-teco_get_default_config_path(const gchar *program)
+teco_get_default_config_path(void)
{
- return g_path_get_dirname(program);
+ return teco_file_get_program_path();
}
#elif defined(G_OS_UNIX) && !defined(__HAIKU__)
static inline gchar *
-teco_get_default_config_path(const gchar *program)
+teco_get_default_config_path(void)
{
return g_strdup(g_get_home_dir());
}
@@ -99,7 +99,7 @@ teco_get_default_config_path(const gchar *program)
* with config files.
*/
static inline gchar *
-teco_get_default_config_path(const gchar *program)
+teco_get_default_config_path(void)
{
return g_strdup(g_get_user_config_dir());
}
@@ -210,7 +210,7 @@ teco_process_options(gchar ***argv)
}
static void
-teco_initialize_environment(const gchar *program)
+teco_initialize_environment(void)
{
g_autoptr(GError) error = NULL;
gchar *abs_path;
@@ -252,14 +252,11 @@ teco_initialize_environment(const gchar *program)
/*
* Initialize $SCITECOCONFIG and $SCITECOPATH
*/
- g_autofree gchar *default_configpath = teco_get_default_config_path(program);
+ g_autofree gchar *default_configpath = teco_get_default_config_path();
g_setenv("SCITECOCONFIG", default_configpath, FALSE);
-#ifdef G_OS_WIN32
- g_autofree gchar *default_scitecopath = g_build_filename(default_configpath, "lib", NULL);
- g_setenv("SCITECOPATH", default_scitecopath, FALSE);
-#else
- g_setenv("SCITECOPATH", SCITECOLIBDIR, FALSE);
-#endif
+ g_autofree gchar *datadir = teco_file_get_datadir();
+ g_autofree gchar *default_libdir = g_build_filename(datadir, "lib", NULL);
+ g_setenv("SCITECOPATH", default_libdir, FALSE);
/*
* $SCITECOCONFIG and $SCITECOPATH may still be relative.
@@ -389,7 +386,7 @@ main(int argc, char **argv)
/* current working directory ("$") */
teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_workingdir_new());
/* environment defaults and registers */
- teco_initialize_environment(argv_utf8[0]);
+ teco_initialize_environment();
teco_qreg_table_t local_qregs;
teco_qreg_table_init(&local_qregs, TRUE);