summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 29891d8)
raw | patch | inline | side by side (parent: 29891d8)
author | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Sun, 28 Mar 2010 20:17:31 +0000 (22:17 +0200) | ||
committer | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Sun, 28 Mar 2010 20:17:31 +0000 (22:17 +0200) |
index 60623191f290c3fc2e6ce53bf32f434797723504..256996663c056ce1262d474daffcd324ba321a1d 100644 (file)
#include <unistd.h>
#include <errno.h>
+#include <glib.h>
+#include <glib/gstdio.h>
#include <gtkmm.h>
#include "ui/view/view.h"
\param interpNameArg The name of the interpreter that we're looking
for, should be an entry in interpreterTab
*/
-Glib::ustring Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg)
+std::string Script::resolveInterpreterExecutable(const Glib::ustring &interpNameArg)
{
- Glib::ustring interpName = interpNameArg;
-
interpreter_t const *interp = 0;
bool foundInterp = false;
for (interp = interpreterTab ; interp->identity ; interp++ ){
- if (interpName == interp->identity) {
+ if (interpNameArg == interp->identity) {
foundInterp = true;
break;
}
@@ -118,55 +118,26 @@ Glib::ustring Script::resolveInterpreterExecutable(const Glib::ustring &interpNa
if (!foundInterp) {
return "";
}
- interpName = interp->defaultval;
+ std::string interpreter_path = Glib::filename_from_utf8(interp->defaultval);
- // 1. Check preferences
+ // 1. Check preferences for an override.
+ // Note: this must be an absolute path.
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
Glib::ustring prefInterp = prefs->getString("/extensions/" + Glib::ustring(interp->prefstring));
if (!prefInterp.empty()) {
- interpName = prefInterp;
- return interpName;
- }
-
-#ifdef WIN32
-
- // 2. Windows. Try looking relative to inkscape.exe
- RegistryTool rt;
- Glib::ustring fullPath;
- Glib::ustring path;
- Glib::ustring exeName;
- if (rt.getExeInfo(fullPath, path, exeName)) {
-// TODO replace with proper glib/glibmm path building routines:
- Glib::ustring interpPath = path;
- interpPath.append("\\");
- interpPath.append(interpNameArg);
- interpPath.append("\\");
- interpPath.append(interpName);
- interpPath.append(".exe");
- struct stat finfo;
- if (stat(interpPath .c_str(), &finfo) == 0) {
- g_message("Found local interpreter, '%s', Size: %d",
- interpPath .c_str(),
- (int)finfo.st_size);
- return interpPath;
- }
+ interpreter_path = Glib::filename_from_utf8(prefInterp);
}
- // 3. Try searching the path
- char szExePath[MAX_PATH] = {0};
- char szCurrentDir[MAX_PATH] = {0};
- GetCurrentDirectory(sizeof(szCurrentDir), szCurrentDir);
- HINSTANCE ret = FindExecutable(interpName.c_str(), szCurrentDir, szExePath);
- if (ret > reinterpret_cast<HINSTANCE>(32)) {
- interpName = szExePath;
- return interpName;
+ // 2. Search the path.
+ // Do this on all systems, for consistency.
+ // PATH is set up to contain the Python and Perl binary directories
+ // on Windows, so no extra code is necessary.
+ if (!Glib::path_is_absolute(interpreter_path)) {
+ interpreter_path = Glib::find_program_in_path(interpreter_path);
}
-
-#endif // win32
-
-
- return interpName;
+ printf("Interpreter name: %s\n", interpreter_path.data());
+ return interpreter_path;
}
/** \brief This function creates a script object and sets up the
string. This means that the caller of this function can always
free what they are given (and should do it too!).
*/
-Glib::ustring
+std::string
Script::solve_reldir(Inkscape::XML::Node *reprin) {
gchar const *s = reprin->attribute("reldir");
- if (!s) {
+ // right now the only recognized relative directory is "extensions"
+ if (!s || Glib::ustring(s) != "extensions") {
Glib::ustring str = sp_repr_children(reprin)->content();
return str;
}
Glib::ustring reldir = s;
- if (reldir == "extensions") {
-
- for (unsigned int i=0;
- i < Inkscape::Extension::Extension::search_path.size();
- i++) {
+ for (unsigned int i=0;
+ i < Inkscape::Extension::Extension::search_path.size();
+ i++) {
- gchar * fname = g_build_filename(
- Inkscape::Extension::Extension::search_path[i],
- sp_repr_children(reprin)->content(),
- NULL);
- Glib::ustring filename = fname;
- g_free(fname);
+ gchar * fname = g_build_filename(
+ Inkscape::Extension::Extension::search_path[i],
+ sp_repr_children(reprin)->content(),
+ NULL);
+ Glib::ustring filename = fname;
+ g_free(fname);
- if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) {
- return filename;
- }
+ if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) {
+ return Glib::filename_from_utf8(filename);
}
- } else {
- Glib::ustring str = sp_repr_children(reprin)->content();
- return str;
}
return "";
then a TRUE is returned. If we get all the way through the path
then a FALSE is returned, the command could not be found.
*/
-bool Script::check_existance(const Glib::ustring &command)
+bool Script::check_existence(const std::string &command)
{
// Check the simple case first
- if (command.size() == 0) {
+ if (command.empty()) {
return false;
}
- //Don't search when it contains a slash. */
- if (command.find(G_DIR_SEPARATOR) != command.npos) {
- if (Inkscape::IO::file_test(command.c_str(), G_FILE_TEST_EXISTS)) {
+ //Don't search when it is an absolute path. */
+ if (!Glib::path_is_absolute(command)) {
+ if (Glib::file_test(command, Glib::FILE_TEST_EXISTS)) {
return true;
} else {
return false;
}
}
-
- Glib::ustring path;
- gchar *s = (gchar *) g_getenv("PATH");
- if (s) {
- path = s;
- } else {
+ std::string path = Glib::getenv("PATH");
+ if (path.empty()) {
/* There is no `PATH' in the environment.
The default search path is the current directory */
path = G_SEARCHPATH_SEPARATOR_S;
std::string::size_type pos2 = 0;
while ( pos < path.size() ) {
- Glib::ustring localPath;
+ std::string localPath;
pos2 = path.find(G_SEARCHPATH_SEPARATOR, pos);
if (pos2 == path.npos) {
}
//printf("### %s\n", localPath.c_str());
- Glib::ustring candidatePath =
+ std::string candidatePath =
Glib::build_filename(localPath, command);
- if (Inkscape::IO::file_test(candidatePath .c_str(),
- G_FILE_TEST_EXISTS)) {
+ if (Glib::file_test(candidatePath,
+ Glib::FILE_TEST_EXISTS)) {
return true;
}
if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "command")) {
const gchar *interpretstr = child_repr->attribute("interpreter");
if (interpretstr != NULL) {
- Glib::ustring interpString =
- resolveInterpreterExecutable(interpretstr);
- //g_message("Found: %s and %s",interpString.c_str(),interpretstr);
- command.insert(command.end(), interpretstr);
+ std::string interpString = resolveInterpreterExecutable(interpretstr);
+ command.insert(command.end(), interpString);
}
- Glib::ustring tmp = "\"";
- tmp += solve_reldir(child_repr);
- tmp += "\"";
-
- command.insert(command.end(), tmp);
+ command.insert(command.end(), solve_reldir(child_repr));
}
if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "helper_extension")) {
helper_extension = sp_repr_children(child_repr)->content();
child_repr = sp_repr_children(child_repr);
while (child_repr != NULL) {
if (!strcmp(child_repr->name(), INKSCAPE_EXTENSION_NS "check")) {
- Glib::ustring command_text = solve_reldir(child_repr);
- if (command_text.size() > 0) {
+ std::string command_text = solve_reldir(child_repr);
+ if (!command_text.empty()) {
/* I've got the command */
- bool existance = check_existance(command_text);
+ bool existance = check_existence(command_text);
if (!existance)
return false;
}
// make sure we don't leak file descriptors from g_file_open_tmp
close(tempfd_out);
- // FIXME: convert to utf8 (from "filename encoding") and unlink_utf8name
- unlink(tempfilename_out.c_str());
+ g_unlink(tempfilename_out.c_str());
/* Do something with mydoc.... */
if (mydoc) {
const Glib::ustring &filein,
file_listener &fileout)
{
- g_return_val_if_fail(in_command.size() > 0, 0);
+ g_return_val_if_fail(!in_command.empty(), 0);
// printf("Executing\n");
- std::vector <std::string> argv;
-
-/*
- for (std::list<std::string>::const_iterator i = in_command.begin();
- i != in_command.end(); i++) {
- argv.push_back(*i);
- }
-*/
- // according to http://www.gtk.org/api/2.6/glib/glib-Spawning-Processes.html spawn quotes parameter containing spaces
- // we tokenize so that spwan does not need to quote over all params
- for (std::list<std::string>::const_iterator i = in_command.begin();
- i != in_command.end(); i++) {
- std::string param_str = *i;
- do {
- //g_message("param: %s", param_str.c_str());
- size_t first_space = param_str.find_first_of(' ');
- size_t first_quote = param_str.find_first_of('"');
- //std::cout << "first space " << first_space << std::endl;
- //std::cout << "first quote " << first_quote << std::endl;
-
- if ((first_quote != std::string::npos) && (first_quote == 0)) {
- size_t next_quote = param_str.find_first_of('"', first_quote + 1);
- //std::cout << "next quote " << next_quote << std::endl;
-
- if (next_quote != std::string::npos) {
- //std::cout << "now split " << next_quote << std::endl;
- //std::cout << "now split " << param_str.substr(1, next_quote - 1) << std::endl;
- //std::cout << "now split " << param_str.substr(next_quote + 1) << std::endl;
- std::string part_str = param_str.substr(1, next_quote - 1);
- if (part_str.size() > 0)
- argv.push_back(part_str);
- param_str = param_str.substr(next_quote + 1);
-
- } else {
- if (param_str.size() > 0)
- argv.push_back(param_str);
- param_str = "";
- }
-
- } else if (first_space != std::string::npos) {
- //std::cout << "now split " << first_space << std::endl;
- //std::cout << "now split " << param_str.substr(0, first_space) << std::endl;
- //std::cout << "now split " << param_str.substr(first_space + 1) << std::endl;
- std::string part_str = param_str.substr(0, first_space);
- if (part_str.size() > 0) {
- argv.push_back(part_str);
- }
- param_str = param_str.substr(first_space + 1);
- } else {
- if (param_str.size() > 0) {
- argv.push_back(param_str);
- }
- param_str = "";
- }
- } while (param_str.size() > 0);
- }
-
- for (std::list<std::string>::const_iterator i = in_params.begin();
- i != in_params.end(); i++) {
- //g_message("Script parameter: %s",(*i)g.c_str());
- argv.push_back(*i);
- }
-
- if (!(filein.empty())) {
+ std::vector<std::string> argv;
+
+ bool interpreted = (in_command.size() == 2);
+ std::string program = in_command.front();
+ std::string script = interpreted ? in_command.back() : "";
+ std::string working_directory = "";
+
+ // Use Glib::find_program_in_path instead of the equivalent
+ // Glib::spawn_* functionality, because _wspawnp is broken on Windows:
+ // it doesn't work when PATH contains Unicode directories
+ if (!Glib::path_is_absolute(program)) {
+ program = Glib::find_program_in_path(program);
+ }
+ argv.push_back(program);
+
+ if (interpreted) {
+ // On Windows, Python garbles Unicode command line parameters
+ // in an useless way. This means extensions fail when Inkscape
+ // is run from an Unicode directory.
+ // As a workaround, we set the working directory to the one
+ // containing the script.
+ working_directory = Glib::path_get_dirname(script);
+ script = Glib::path_get_basename(script);
+ #ifdef G_OS_WIN32
+ // ANNOYING: glibmm does not wrap g_win32_locale_filename_from_utf8
+ gchar *workdir_s = g_win32_locale_filename_from_utf8(working_directory.data());
+ working_directory = workdir_s;
+ g_free(workdir_s);
+ #endif
+
+ argv.push_back(script);
+ }
+
+ // assemble the rest of argv
+ std::copy(in_params.begin(), in_params.end(), std::back_inserter(argv));
+ if (!filein.empty()) {
argv.push_back(filein);
}
int stdout_pipe, stderr_pipe;
try {
- Inkscape::IO::spawn_async_with_pipes(Glib::get_current_dir(), // working directory
+ Glib::spawn_async_with_pipes(working_directory, // working directory
argv, // arg v
- Glib::SPAWN_SEARCH_PATH /*| Glib::SPAWN_DO_NOT_REAP_CHILD*/,
+ static_cast<Glib::SpawnFlags>(0), // no flags
sigc::slot<void>(),
&_pid, // Pid
NULL, // STDIN
&stdout_pipe, // STDOUT
&stderr_pipe); // STDERR
- } catch (Glib::SpawnError e) {
- printf("Can't Spawn!!! spawn returns: %d\n", e.code());
+ } catch (Glib::Error e) {
+ printf("Can't Spawn!!! spawn returns: %s\n", e.what().data());
return 0;
}
index e0b6701bf105cb5b8435c1c04a0692f0f28558f6..f37f2796656b05678c1ada8daa93058c5ee54779 100644 (file)
*/
Glib::ustring helper_extension;
- /**
- * Just a quick function to find and resolve relative paths for
- * the incoming scripts
- */
- Glib::ustring solve_reldir (Inkscape::XML::Node *reprin);
-
- /**
- *
- */
- bool check_existance (const Glib::ustring &command);
-
- /**
- *
- */
+ std::string solve_reldir (Inkscape::XML::Node *reprin);
+ bool check_existence (const std::string &command);
void copy_doc (Inkscape::XML::Node * olddoc,
Inkscape::XML::Node * newdoc);
-
- /**
- *
- */
void checkStderr (const Glib::ustring &filename,
Gtk::MessageType type,
const Glib::ustring &message);
-
class file_listener {
Glib::ustring _string;
sigc::connection _conn;
return true;
};
- // Note, doing a copy here, on purpose
Glib::ustring string (void) { return _string; };
bool toFile (const Glib::ustring &name) {
};
static interpreter_t const interpreterTab[];
- Glib::ustring resolveInterpreterExecutable(const Glib::ustring &interpNameArg);
+ std::string resolveInterpreterExecutable(const Glib::ustring &interpNameArg);
}; // class Script
diff --git a/src/io/sys.cpp b/src/io/sys.cpp
index 34160b64801f2c195a98515f47d7e92415d3d2ed..a68d027079816059886210824230c2e57ecf41ff 100644 (file)
--- a/src/io/sys.cpp
+++ b/src/io/sys.cpp
#include "sys.h"
#ifdef WIN32
-
-#define BYPASS_GLIB_SPAWN 1
-
-#ifdef BYPASS_GLIB_SPAWN
-
-#include <process.h> // declares spawn functions
-#include <wchar.h> // declares _wspawn functions
-
-#ifndef __MINGW32__
-# ifdef __cplusplus
-extern "C" {
-# endif
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnl (int, const wchar_t*, const wchar_t*, ...);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnle (int, const wchar_t*, const wchar_t*, ...);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnlp (int, const wchar_t*, const wchar_t*, ...);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnlpe (int, const wchar_t*, const wchar_t*, ...);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnv (int, const wchar_t*, const wchar_t* const*);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnve (int, const wchar_t*, const wchar_t* const*, const wchar_t* const*);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnvp (int, const wchar_t*, const wchar_t* const*);
-_CRTIMP int __cdecl __MINGW_NOTHROW _wspawnvpe (int, const wchar_t*, const wchar_t* const*, const wchar_t* const*);
-# ifdef __cplusplus
-}
-# endif
-#endif
-#include <unistd.h>
-#include <glibmm/i18n.h>
-#include <fcntl.h>
-#include <io.h>
-
-#endif // BYPASS_GLIB_SPAWN
-
// For now to get at is_os_wide().
#include "extension/internal/win32.h"
using Inkscape::Extension::Internal::PrintWin32;
-
#endif // WIN32
//#define INK_DUMP_FILENAME_CONV 1
* */
int Inkscape::IO::file_open_tmp(std::string& name_used, const std::string& prefix)
{
-#ifndef WIN32
return Glib::file_open_tmp(name_used, prefix);
-#else
- /* Special case for WIN32 due to a bug in glibmm
- * (only needed for Windows Vista, but since there is only one windows build all builds get the workaround)
- * The workaround can be removed if the bug is fixed in glibmm
- *
- * The code is mostly identical to the implementation in glibmm
- * http://svn.gnome.org/svn/glibmm/branches/glibmm-2-12/glib/src/fileutils.ccg
- * */
-
- std::string basename_template (prefix);
- basename_template += "XXXXXX"; // this sillyness shouldn't be in the interface
-
- GError* error = 0;
- gchar *buf_name_used;
-
- gint fileno = g_file_open_tmp(basename_template.c_str(), &buf_name_used, &error);
-
- if(error)
- Glib::Error::throw_exception(error);
-
- name_used = g_strdup(buf_name_used);
- g_free(buf_name_used);
- return fileno;
-#endif
}
bool Inkscape::IO::file_test( char const *utf8name, GFileTest test )
return result;
}
-#ifdef BYPASS_GLIB_SPAWN
-/*
- this code was taken from the original glib sources
-*/
-#define GSPAWN_HELPER
-
-enum
-{
- CHILD_NO_ERROR,
- CHILD_CHDIR_FAILED,
- CHILD_SPAWN_FAILED,
-};
-
-enum {
- ARG_CHILD_ERR_REPORT = 1,
- ARG_HELPER_SYNC,
- ARG_STDIN,
- ARG_STDOUT,
- ARG_STDERR,
- ARG_WORKING_DIRECTORY,
- ARG_CLOSE_DESCRIPTORS,
- ARG_USE_PATH,
- ARG_WAIT,
- ARG_PROGRAM,
- ARG_COUNT = ARG_PROGRAM
-};
-static int debug = 0;
-#define HELPER_PROCESS "gspawn-win32-helper"
-
-
-static int
-dup_noninherited (int fd,
- int mode)
-{
- HANDLE filehandle;
-
- DuplicateHandle (GetCurrentProcess (), (LPHANDLE) _get_osfhandle (fd),
- GetCurrentProcess (), &filehandle,
- 0, FALSE, DUPLICATE_SAME_ACCESS);
- close (fd);
- return _open_osfhandle(reinterpret_cast<LONG_PTR>(filehandle), mode | _O_NOINHERIT);
-}
-
-/* The helper process writes a status report back to us, through a
- * pipe, consisting of two ints.
- */
-static gboolean
-read_helper_report (int fd,
- gint report[2],
- GError **error)
-{
- gint bytes = 0;
-
- while (bytes < sizeof(gint)*2)
- {
- gint chunk;
-
- if (debug)
- g_print ("%s:read_helper_report: read %d...\n",
- __FILE__,
- sizeof(gint)*2 - bytes);
-
- chunk = read (fd, ((gchar*)report) + bytes,
- sizeof(gint)*2 - bytes);
-
- if (debug)
- g_print ("...got %d bytes\n", chunk);
-
- if (chunk < 0)
- {
- /* Some weird shit happened, bail out */
-
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to read from child pipe (%s)"),
- g_strerror (errno));
-
- return FALSE;
- }
- else if (chunk == 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to read from child pipe (%s)"),
- "EOF");
- break; /* EOF */
- }
- else
- bytes += chunk;
- }
-
- if (bytes < sizeof(gint)*2)
- return FALSE;
-
- return TRUE;
-}
-
-
-static void
-set_child_error (gint report[2],
- const gchar *working_directory,
- GError **error)
-{
- switch (report[0])
- {
- case CHILD_CHDIR_FAILED:
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
- _("Failed to change to directory '%s' (%s)"),
- working_directory,
- g_strerror (report[1]));
- break;
- case CHILD_SPAWN_FAILED:
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute child process (%s)"),
- g_strerror (report[1]));
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static gchar *
-protect_argv_string (const gchar *string)
-{
- const gchar *p = string;
- gchar *retval, *q;
- gint len = 0;
- gboolean need_dblquotes = FALSE;
- while (*p)
- {
- if (*p == ' ' || *p == '\t')
- need_dblquotes = TRUE;
- else if (*p == '"')
- len++;
- else if (*p == '\\')
- {
- const gchar *pp = p;
- while (*pp && *pp == '\\')
- pp++;
- if (*pp == '"')
- len++;
- }
- len++;
- p++;
- }
-
- q = retval = (gchar *)g_malloc (len + need_dblquotes*2 + 1);
- p = string;
-
- if (need_dblquotes)
- *q++ = '"';
-
- while (*p)
- {
- if (*p == '"')
- *q++ = '\\';
- else if (*p == '\\')
- {
- const gchar *pp = p;
- while (*pp && *pp == '\\')
- pp++;
- if (*pp == '"')
- *q++ = '\\';
- }
- *q++ = *p;
- p++;
- }
-
- if (need_dblquotes)
- *q++ = '"';
- *q++ = '\0';
-
- return retval;
-}
-
-
-static gint
-protect_argv (gchar **argv,
- gchar ***new_argv)
-{
- gint i;
- gint argc = 0;
-
- while (argv[argc])
- ++argc;
- *new_argv = g_new (gchar *, argc+1);
-
- /* Quote each argv element if necessary, so that it will get
- * reconstructed correctly in the C runtime startup code. Note that
- * the unquoting algorithm in the C runtime is really weird, and
- * rather different than what Unix shells do. See stdargv.c in the C
- * runtime sources (in the Platform SDK, in src/crt).
- *
- * Note that an new_argv[0] constructed by this function should
- * *not* be passed as the filename argument to a spawn* or exec*
- * family function. That argument should be the real file name
- * without any quoting.
- */
- for (i = 0; i < argc; i++)
- (*new_argv)[i] = protect_argv_string (argv[i]);
-
- (*new_argv)[argc] = NULL;
-
- return argc;
-}
-
-
-static gboolean
-utf8_charv_to_wcharv (char **utf8_charv,
- wchar_t ***wcharv,
- int *error_index,
- GError **error)
-{
- wchar_t **retval = NULL;
-
- *wcharv = NULL;
- if (utf8_charv != NULL)
- {
- int n = 0, i;
-
- while (utf8_charv[n])
- n++;
- retval = g_new (wchar_t *, n + 1);
-
- for (i = 0; i < n; i++)
- {
- retval[i] = (wchar_t *)g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error);
- if (retval[i] == NULL)
- {
- if (error_index)
- *error_index = i;
- while (i)
- g_free (retval[--i]);
- g_free (retval);
- return FALSE;
- }
- }
-
- retval[n] = NULL;
- }
- *wcharv = retval;
- return TRUE;
-}
-
-
-/* Avoids a danger in threaded situations (calling close()
- * on a file descriptor twice, and another thread has
- * re-opened it since the first close)
- */
-static void
-close_and_invalidate (gint *fd)
-{
- if (*fd < 0)
- return;
-
- close (*fd);
- *fd = -1;
-}
-
-
-static gboolean
-do_spawn_directly (gint *exit_status,
- gboolean do_return_handle,
- GSpawnFlags flags,
- gchar **argv,
- char **envp,
- char **protected_argv,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- GError **error)
-{
- const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
- char **new_argv;
- int rc = -1;
- int saved_errno;
- GError *conv_error = NULL;
- gint conv_error_index;
- wchar_t *wargv0, **wargv, **wenvp;
-
- new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
-
- wargv0 = (wchar_t *)g_utf8_to_utf16 (argv[0], -1, NULL, NULL, &conv_error);
- if (wargv0 == NULL)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid program name: %s"),
- conv_error->message);
- g_error_free (conv_error);
-
- return FALSE;
- }
-
- if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in argument vector at %d: %s"),
- conv_error_index, conv_error->message);
- g_error_free (conv_error);
- g_free (wargv0);
-
- return FALSE;
- }
-
- if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in environment: %s"),
- conv_error->message);
- g_error_free (conv_error);
- g_free (wargv0);
- g_strfreev ((gchar **) wargv);
-
- return FALSE;
- }
-
- if (child_setup)
- (* child_setup) (user_data);
-
- if (flags & G_SPAWN_SEARCH_PATH)
- if (wenvp != NULL)
- rc = _wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv);
- else
- if (wenvp != NULL)
- rc = _wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv);
-
- g_free (wargv0);
- g_strfreev ((gchar **) wargv);
- g_strfreev ((gchar **) wenvp);
-
- saved_errno = errno;
-
- if (rc == -1 && saved_errno != 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute child process (%s)"),
- g_strerror (saved_errno));
- return FALSE;
- }
-
- if (exit_status == NULL)
- {
- if (child_handle && do_return_handle)
- *child_handle = (GPid) rc;
- else
- {
- CloseHandle ((HANDLE) rc);
- if (child_handle)
- *child_handle = 0;
- }
- }
- else
- *exit_status = rc;
-
- return TRUE;
-}
-
-static gboolean
-make_pipe (gint p[2],
- GError **error)
-{
- if (_pipe (p, 4096, _O_BINARY) < 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to create pipe for communicating with child process (%s)"),
- g_strerror (errno));
- return FALSE;
- }
- else
- return TRUE;
-}
-
-
-static gboolean
-do_spawn_with_pipes (gint *exit_status,
- gboolean do_return_handle,
- const gchar *working_directory,
- gchar **argv,
- char **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- gint *err_report,
- GError **error)
-{
- char **protected_argv;
- char args[ARG_COUNT][10];
- char **new_argv;
- int i;
- int rc = -1;
- int saved_errno;
- int argc;
- int stdin_pipe[2] = { -1, -1 };
- int stdout_pipe[2] = { -1, -1 };
- int stderr_pipe[2] = { -1, -1 };
- int child_err_report_pipe[2] = { -1, -1 };
- int helper_sync_pipe[2] = { -1, -1 };
- int helper_report[2];
- static gboolean warned_about_child_setup = FALSE;
- GError *conv_error = NULL;
- gint conv_error_index;
- gchar *helper_process;
- CONSOLE_CURSOR_INFO cursor_info;
- wchar_t *whelper, **wargv, **wenvp;
- //extern gchar *_glib_get_installation_directory (void);
- gchar *glib_top;
-
- if (child_setup && !warned_about_child_setup)
- {
- warned_about_child_setup = TRUE;
- g_warning ("passing a child setup function to the g_spawn functions is pointless and dangerous on Win32");
- }
-
- argc = protect_argv (argv, &protected_argv);
-
- if (!standard_input && !standard_output && !standard_error &&
- (flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL) &&
- (working_directory == NULL || !*working_directory) &&
- (flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
- {
- /* We can do without the helper process */
- gboolean retval =
- do_spawn_directly (exit_status, do_return_handle, flags,
- argv, envp, protected_argv,
- child_setup, user_data, child_handle,
- error);
- g_strfreev (protected_argv);
- return retval;
- }
-
- if (standard_input && !make_pipe (stdin_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_output && !make_pipe (stdout_pipe, error))
- goto cleanup_and_fail;
-
- if (standard_error && !make_pipe (stderr_pipe, error))
- goto cleanup_and_fail;
-
- if (!make_pipe (child_err_report_pipe, error))
- goto cleanup_and_fail;
-
- if (!make_pipe (helper_sync_pipe, error))
- goto cleanup_and_fail;
-
- new_argv = g_new (char *, argc + 1 + ARG_COUNT);
- if (GetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cursor_info))
- helper_process = HELPER_PROCESS "-console.exe";
- else
- helper_process = HELPER_PROCESS ".exe";
-
- glib_top = NULL;
- if (glib_top != NULL)
- {
- helper_process = g_build_filename (glib_top, "bin", helper_process, NULL);
- g_free (glib_top);
- }
- else
- helper_process = g_strdup (helper_process);
-
- new_argv[0] = protect_argv_string (helper_process);
-
- sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);
- new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
-
- /* Make the read end of the child error report pipe
- * noninherited. Otherwise it will needlessly be inherited by the
- * helper process, and the started actual user process. As such that
- * shouldn't harm, but it is unnecessary.
- */
- child_err_report_pipe[0] = dup_noninherited (child_err_report_pipe[0], _O_RDONLY);
-
- if (flags & G_SPAWN_FILE_AND_ARGV_ZERO)
- {
- /* Overload ARG_CHILD_ERR_REPORT to also encode the
- * G_SPAWN_FILE_AND_ARGV_ZERO functionality.
- */
- strcat (args[ARG_CHILD_ERR_REPORT], "#");
- }
-
- sprintf (args[ARG_HELPER_SYNC], "%d", helper_sync_pipe[0]);
- new_argv[ARG_HELPER_SYNC] = args[ARG_HELPER_SYNC];
-
- /* Make the write end of the sync pipe noninherited. Otherwise the
- * helper process will inherit it, and thus if this process happens
- * to crash before writing the sync byte to the pipe, the helper
- * process won't read but won't get any EOF either, as it has the
- * write end open itself.
- */
- helper_sync_pipe[1] = dup_noninherited (helper_sync_pipe[1], _O_WRONLY);
-
- if (standard_input)
- {
- sprintf (args[ARG_STDIN], "%d", stdin_pipe[0]);
- new_argv[ARG_STDIN] = args[ARG_STDIN];
- }
- else if (flags & G_SPAWN_CHILD_INHERITS_STDIN)
- {
- /* Let stdin be alone */
- new_argv[ARG_STDIN] = "-";
- }
- else
- {
- /* Keep process from blocking on a read of stdin */
- new_argv[ARG_STDIN] = "z";
- }
-
- if (standard_output)
- {
- sprintf (args[ARG_STDOUT], "%d", stdout_pipe[1]);
- new_argv[ARG_STDOUT] = args[ARG_STDOUT];
- }
- else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL)
- {
- new_argv[ARG_STDOUT] = "z";
- }
- else
- {
- new_argv[ARG_STDOUT] = "-";
- }
-
- if (standard_error)
- {
- sprintf (args[ARG_STDERR], "%d", stderr_pipe[1]);
- new_argv[ARG_STDERR] = args[ARG_STDERR];
- }
- else if (flags & G_SPAWN_STDERR_TO_DEV_NULL)
- {
- new_argv[ARG_STDERR] = "z";
- }
- else
- {
- new_argv[ARG_STDERR] = "-";
- }
-
- if (working_directory && *working_directory)
- new_argv[ARG_WORKING_DIRECTORY] = protect_argv_string (working_directory);
- else
- new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-");
-
- if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
- new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
- else
- new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
-
- if (flags & G_SPAWN_SEARCH_PATH)
- new_argv[ARG_USE_PATH] = "y";
- else
- new_argv[ARG_USE_PATH] = "-";
-
- if (exit_status == NULL)
- new_argv[ARG_WAIT] = "-";
- else
- new_argv[ARG_WAIT] = "w";
-
- for (i = 0; i <= argc; i++)
- new_argv[ARG_PROGRAM + i] = protected_argv[i];
-
- //SETUP_DEBUG();
-
- if (debug)
- {
- g_print ("calling %s with argv:\n", helper_process);
- for (i = 0; i < argc + 1 + ARG_COUNT; i++)
- g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
- }
-
- if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
- {
- if (conv_error_index == ARG_WORKING_DIRECTORY)
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
- _("Invalid working directory: %s"),
- conv_error->message);
- else
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in argument vector at %d: %s"),
- conv_error_index - ARG_PROGRAM, conv_error->message);
- g_error_free (conv_error);
- g_strfreev (protected_argv);
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
- g_free (helper_process);
-
- goto cleanup_and_fail;
- }
-
- if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Invalid string in environment: %s"),
- conv_error->message);
- g_error_free (conv_error);
- g_strfreev (protected_argv);
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
- g_free (helper_process);
- g_strfreev ((gchar **) wargv);
-
- goto cleanup_and_fail;
- }
-
- if (child_setup)
- (* child_setup) (user_data);
-
- whelper = (wchar_t *)g_utf8_to_utf16 (helper_process, -1, NULL, NULL, NULL);
- g_free (helper_process);
-
- if (wenvp != NULL)
- rc = _wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp);
- else
- rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);
-
- saved_errno = errno;
-
- g_free (whelper);
- g_strfreev ((gchar **) wargv);
- g_strfreev ((gchar **) wenvp);
-
- /* Close the other process's ends of the pipes in this process,
- * otherwise the reader will never get EOF.
- */
- close_and_invalidate (&child_err_report_pipe[1]);
- close_and_invalidate (&helper_sync_pipe[0]);
- close_and_invalidate (&stdin_pipe[0]);
- close_and_invalidate (&stdout_pipe[1]);
- close_and_invalidate (&stderr_pipe[1]);
-
- g_strfreev (protected_argv);
-
- g_free (new_argv[0]);
- g_free (new_argv[ARG_WORKING_DIRECTORY]);
- g_free (new_argv);
-
- /* Check if gspawn-win32-helper couldn't be run */
- if (rc == -1 && saved_errno != 0)
- {
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
- _("Failed to execute helper program (%s)"),
- g_strerror (saved_errno));
- goto cleanup_and_fail;
- }
-
- if (exit_status != NULL)
- {
- /* Synchronous case. Pass helper's report pipe back to caller,
- * which takes care of reading it after the grandchild has
- * finished.
- */
- g_assert (err_report != NULL);
- *err_report = child_err_report_pipe[0];
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- }
- else
- {
- /* Asynchronous case. We read the helper's report right away. */
- if (!read_helper_report (child_err_report_pipe[0], helper_report, error))
- goto cleanup_and_fail;
-
- close_and_invalidate (&child_err_report_pipe[0]);
-
- switch (helper_report[0])
- {
- case CHILD_NO_ERROR:
- if (child_handle && do_return_handle)
- {
- /* rc is our HANDLE for gspawn-win32-helper. It has
- * told us the HANDLE of its child. Duplicate that into
- * a HANDLE valid in this process.
- */
- if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1],
- GetCurrentProcess (), (LPHANDLE) child_handle,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- char *emsg = g_win32_error_message (GetLastError ());
- g_print("%s\n", emsg);
- *child_handle = 0;
- }
- }
- else if (child_handle)
- *child_handle = 0;
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- break;
-
- default:
- write (helper_sync_pipe[1], " ", 1);
- close_and_invalidate (&helper_sync_pipe[1]);
- set_child_error (helper_report, working_directory, error);
- goto cleanup_and_fail;
- }
- }
-
- /* Success against all odds! return the information */
-
- if (standard_input)
- *standard_input = stdin_pipe[1];
- if (standard_output)
- *standard_output = stdout_pipe[0];
- if (standard_error)
- *standard_error = stderr_pipe[0];
- if (rc != -1)
- CloseHandle ((HANDLE) rc);
-
- return TRUE;
-
- cleanup_and_fail:
-
- if (rc != -1)
- CloseHandle ((HANDLE) rc);
- if (child_err_report_pipe[0] != -1)
- close (child_err_report_pipe[0]);
- if (child_err_report_pipe[1] != -1)
- close (child_err_report_pipe[1]);
- if (helper_sync_pipe[0] != -1)
- close (helper_sync_pipe[0]);
- if (helper_sync_pipe[1] != -1)
- close (helper_sync_pipe[1]);
- if (stdin_pipe[0] != -1)
- close (stdin_pipe[0]);
- if (stdin_pipe[1] != -1)
- close (stdin_pipe[1]);
- if (stdout_pipe[0] != -1)
- close (stdout_pipe[0]);
- if (stdout_pipe[1] != -1)
- close (stdout_pipe[1]);
- if (stderr_pipe[0] != -1)
- close (stderr_pipe[0]);
- if (stderr_pipe[1] != -1)
- close (stderr_pipe[1]);
-
- return FALSE;
-}
-
-gboolean
-my_spawn_async_with_pipes_utf8 (const gchar *working_directory,
- gchar **argv,
- gchar **envp,
- GSpawnFlags flags,
- GSpawnChildSetupFunc child_setup,
- gpointer user_data,
- GPid *child_handle,
- gint *standard_input,
- gint *standard_output,
- gint *standard_error,
- GError **error)
-{
- g_return_val_if_fail (argv != NULL, FALSE);
- g_return_val_if_fail (standard_output == NULL ||
- !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
- g_return_val_if_fail (standard_error == NULL ||
- !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
- /* can't inherit stdin if we have an input pipe. */
- g_return_val_if_fail (standard_input == NULL ||
- !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
-
- return do_spawn_with_pipes (NULL,
- (flags & G_SPAWN_DO_NOT_REAP_CHILD),
- working_directory,
- argv,
- envp,
- flags,
- child_setup,
- user_data,
- child_handle,
- standard_input,
- standard_output,
- standard_error,
- NULL,
- error);
-}
-
-typedef GPid Pid;
-
-// _WRAP_ENUM(SpawnFlags, GSpawnFlags, NO_GTYPE)
-
-/* Helper callback to invoke the actual sigc++ slot.
- * We don't need to worry about (un)referencing, since the
- * child process gets its own copy of the parent's memory anyway.
- */
-static void child_setup_callback(void* user_data)
-{
- #ifdef GLIBMM_EXCEPTIONS_ENABLED
- try
- {
- #endif //GLIBMM_EXCEPTIONS_ENABLED
- (*reinterpret_cast<sigc::slot<void>*>(user_data))();
- #ifdef GLIBMM_EXCEPTIONS_ENABLED
- }
- catch(...)
- {
- Glib::exception_handlers_invoke();
- }
- #endif //GLIBMM_EXCEPTIONS_ENABLED
-}
-
-
-void my_spawn_async_with_pipes(const std::string& working_directory,
- const Glib::ArrayHandle<std::string>& argv,
- GSpawnFlags flags,
- const sigc::slot<void>& child_setup,
- Pid* child_pid,
- int* standard_input,
- int* standard_output,
- int* standard_error)
-{
- const bool setup_slot = !child_setup.empty();
- sigc::slot<void> child_setup_ = child_setup;
- GError* error = 0;
-
- my_spawn_async_with_pipes_utf8(
- working_directory.c_str(),
- const_cast<char**>(argv.data()), 0,
- static_cast<GSpawnFlags>(unsigned(flags)),
- (setup_slot) ? &child_setup_callback : 0,
- (setup_slot) ? &child_setup_ : 0,
- child_pid,
- standard_input, standard_output, standard_error,
- &error);
-
- if(error)
- Glib::Error::throw_exception(error);
-}
-
-#endif
-
void
Inkscape::IO::spawn_async_with_pipes( const std::string& working_directory,
const Glib::ArrayHandle<std::string>& argv,
int* standard_output,
int* standard_error)
{
-#ifndef BYPASS_GLIB_SPAWN
Glib::spawn_async_with_pipes(working_directory,
argv,
flags,
standard_input,
standard_output,
standard_error);
-#else
- my_spawn_async_with_pipes(working_directory,
- argv,
- static_cast<GSpawnFlags>(flags),
- child_setup,
- child_pid,
- standard_input,
- standard_output,
- standard_error);
-#endif
}
diff --git a/src/main.cpp b/src/main.cpp
index d11222203778b3728d0fec669d76494fae9bec3f..a4ed5d77bf47dc88de096fc0c6e978c83ec23f10 100644 (file)
--- a/src/main.cpp
+++ b/src/main.cpp
#endif /* Not def: POPT_TABLEEND */
#include <libxml/tree.h>
+#include <glib.h>
+#include <glib/gprintf.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <gtk/gtkmain.h>
#ifdef WIN32
-/**
- * Return the directory of the .exe that is currently running
- */
-static Glib::ustring _win32_getExePath()
-{
- char exeName[MAX_PATH+1];
- // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
- GetModuleFileName(NULL, exeName, MAX_PATH);
- char *slashPos = strrchr(exeName, '\\');
- if (slashPos) {
- *slashPos = '\0';
- }
- Glib::ustring s = exeName;
- return s;
-}
-
/**
* Set up the PATH and PYTHONPATH environment variables on
* win32
+ * @param exe Inkscape executable directory in UTF-8
*/
-static int _win32_set_inkscape_env(const Glib::ustring &exePath)
+static void _win32_set_inkscape_env(gchar const *exe)
{
- // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
-
- char *oldenv = getenv("PATH");
- Glib::ustring tmp = "PATH=";
- tmp += exePath;
- tmp += ";";
- tmp += exePath;
- tmp += "\\python;";
- tmp += exePath;
- tmp += "\\python\\Scripts;"; // for uniconv.cmd
- tmp += exePath;
- tmp += "\\perl";
- if(oldenv != NULL) {
- tmp += ";";
- tmp += oldenv;
+ gchar const *path = g_getenv("PATH");
+ gchar const *pythonpath = g_getenv("PYTHONPATH");
+
+ gchar *python = g_build_filename(exe, "python", NULL);
+ gchar *scripts = g_build_filename(exe, "python", "Scripts", NULL);
+ gchar *perl = g_build_filename(exe, "python", NULL);
+ gchar *pythonlib = g_build_filename(exe, "python", "Lib", NULL);
+ gchar *pythondll = g_build_filename(exe, "python", "DLLs", NULL);
+
+ // Python 2.x needs short paths in PYTHONPATH.
+ // Otherwise it doesn't work when Inkscape is installed in Unicode directories.
+ // g_win32_locale_filename_from_utf8 is the Glib equivalent
+ // of GetShortPathName.
+ // Remove this once we move to Python 3.0.
+ gchar *python_s = g_win32_locale_filename_from_utf8(python);
+ gchar *pythonlib_s = g_win32_locale_filename_from_utf8(pythonlib);
+ gchar *pythondll_s = g_win32_locale_filename_from_utf8(pythondll);
+
+ gchar *new_path;
+ gchar *new_pythonpath;
+ if (path) {
+ new_path = g_strdup_printf("%s;%s;%s;%s;%s", exe, python, scripts, perl, path);
+ } else {
+ new_path = g_strdup_printf("%s;%s;%s;%s", exe, python, scripts, perl);
}
- _putenv(tmp.c_str());
-
- oldenv = getenv("PYTHONPATH");
- tmp = "PYTHONPATH=";
- tmp += exePath;
- tmp += "\\python;";
- tmp += exePath;
- tmp += "\\python\\Lib;";
- tmp += exePath;
- tmp += "\\python\\DLLs";
- if(oldenv != NULL) {
- tmp += ";";
- tmp += oldenv;
+ if (pythonpath) {
+ new_pythonpath = g_strdup_printf("%s;%s;%s;%s", python_s, pythonlib_s, pythondll_s, pythonpath);
+ } else {
+ new_pythonpath = g_strdup_printf("%s;%s;%s", python_s, pythonlib_s, pythondll_s);
}
- _putenv(tmp.c_str());
- return 0;
+ g_setenv("PATH", new_path, TRUE);
+ g_setenv("PYTHONPATH", new_pythonpath, TRUE);
+
+ /*
+ printf("PATH = %s\n\n", g_getenv("PATH"));
+ printf("PYTHONPATH = %s\n\n", g_getenv("PYTHONPATH"));
+
+ gchar *p = g_find_program_in_path("python");
+ if (p) {
+ printf("python in %s\n\n", p);
+ g_free(p);
+ } else {
+ printf("python not found\n\n");
+ }*/
+
+ g_free(python);
+ g_free(scripts);
+ g_free(perl);
+ g_free(pythonlib);
+ g_free(pythondll);
+
+ g_free(python_s);
+ g_free(pythonlib_s);
+ g_free(pythondll_s);
+
+ g_free(new_path);
+ g_free(new_pythonpath);
}
#endif
when inkscape.exe is executed from another directory.
We use relative paths on win32.
HKCR\svgfile\shell\open\command is a good example
+
+ TODO: this breaks the CLI on Windows, see LP #167455
+ However, the CLI is broken anyway, because we are a GUI app
*/
- Glib::ustring homedir = _win32_getExePath();
- // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
- SetCurrentDirectory(homedir.c_str());
- _win32_set_inkscape_env(homedir);
+ const int pathbuf = 2048;
+ gunichar2 *path = g_new(gunichar2, pathbuf);
+ GetModuleFileNameW(NULL, (WCHAR*) path, pathbuf);
+ gchar *inkscape = g_utf16_to_utf8(path, -1, NULL, NULL, NULL);
+ gchar *exedir = g_path_get_dirname(inkscape);
+ gunichar2 *dirw = g_utf8_to_utf16(exedir, -1, NULL, NULL, NULL);
+ SetCurrentDirectoryW((WCHAR*) dirw);
+ _win32_set_inkscape_env(exedir);
+
+# ifdef ENABLE_NLS
+ // obtain short path to executable dir and pass it
+ // to bindtextdomain (it doesn't understand UTF-8)
+ gchar *shortexedir = g_win32_locale_filename_from_utf8(exedir);
+ gchar *localepath = g_build_filename(shortexedir, PACKAGE_LOCALE_DIR, NULL);
+ bindtextdomain(GETTEXT_PACKAGE, localepath);
+ g_free(shortexedir);
+ g_free(localepath);
+# endif
+
+ g_free(path);
+ g_free(inkscape);
+ g_free(exedir);
+ g_free(dirw);
+
// Don't touch the registry (works fine without it) for Inkscape Portable
gchar const *val = g_getenv("INKSCAPE_PORTABLE_PROFILE_DIR");
if (!val) {
RegistryTool rt;
rt.setPathInfo();
}
-#endif
-
- // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
- Gtk::Main::init_gtkmm_internals();
-
- // Bug #197475
- set_extensions_env();
-
- /**
- * Call bindtextdomain() for various machines's paths
- */
-#ifdef ENABLE_NLS
-#ifdef WIN32
- Glib::ustring localePath = homedir;
- localePath += "\\";
- localePath += PACKAGE_LOCALE_DIR;
- bindtextdomain(GETTEXT_PACKAGE, localePath.c_str());
-#else
-#ifdef ENABLE_BINRELOC
+#elif defined(ENABLE_NLS)
+# ifdef ENABLE_BINRELOC
bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
-#else
+# else
bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+# endif
#endif
-#endif
+
+ // the bit below compiles regardless of platform
+#ifdef ENABLE_NLS
// Allow the user to override the locale directory by setting
// the environment variable INKSCAPE_LOCALEDIR.
- char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
+ char const *inkscape_localedir = g_getenv("INKSCAPE_LOCALEDIR");
if (inkscape_localedir != NULL) {
bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
}
-#endif
+ // common setup
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
-
-#ifdef ENABLE_NLS
textdomain(GETTEXT_PACKAGE);
#endif
+ // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
+ Gtk::Main::init_gtkmm_internals();
+
+ // Bug #197475
+ set_extensions_env();
+
LIBXML_TEST_VERSION
Inkscape::GC::init();
gboolean use_gui;
#ifndef WIN32
- // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
- use_gui = (getenv("DISPLAY") != NULL);
+ use_gui = (g_getenv("DISPLAY") != NULL);
#else
use_gui = TRUE;
#endif
diff --git a/src/prefix.cpp b/src/prefix.cpp
index f1fa3c2cdfae7e9eaff1da5c14b134de645d1103..8c1dd4f0022857dff53fef33a80e8c10f77c961b 100644 (file)
--- a/src/prefix.cpp
+++ b/src/prefix.cpp
#endif
-/* PLEASE NOTE: We use GThreads now for portability */
-/* @see http://developer.gnome.org/doc/API/2.0/glib/glib-Threads.html */
-#ifndef BR_THREADS
- /* Change 1 to 0 if you don't want thread support */
- #define BR_THREADS 1
- #include <glib.h> //for GThreads
-#endif /* BR_THREADS */
-
+#include <glib.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#define NULL ((void *) 0)
#ifdef __GNUC__
- #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
+ #define br_return_val_if_fail(expr,val) if (!(expr)) {fprintf (stderr, "** BinReloc (%s): assertion %s failed\n", __PRETTY_FUNCTION__, #expr); return val;}
#else
- #define br_return_val_if_fail(expr,val) if (!(expr)) return val
+ #define br_return_val_if_fail(expr,val) if (!(expr)) return val
#endif /* __GNUC__ */
* br_locate:
* symbol: A symbol that belongs to the app/library you want to locate.
* Returns: A newly allocated string containing the full path of the
- * app/library that func belongs to, or NULL on error. This
- * string should be freed when not when no longer needed.
+ * app/library that func belongs to, or NULL on error. This
+ * string should be freed when not when no longer needed.
*
* Finds out to which application or library symbol belongs, then locate
* the full path of that application or library.
* #include "libfoo.h"
*
* int main (int argc, char *argv[]) {
- * printf ("Full path of this app: %s\n", br_locate (&argc));
- * libfoo_start ();
- * return 0;
+ * printf ("Full path of this app: %s\n", br_locate (&argc));
+ * libfoo_start ();
+ * return 0;
* }
*
* --> libfoo.c starts here
* #include "prefix.h"
*
* void libfoo_start () {
- * --> "" is a symbol that belongs to libfoo (because it's called
- * --> from libfoo_start()); that's why this works.
- * printf ("libfoo is located in: %s\n", br_locate (""));
+ * --> "" is a symbol that belongs to libfoo (because it's called
+ * --> from libfoo_start()); that's why this works.
+ * printf ("libfoo is located in: %s\n", br_locate (""));
* }
*/
char *
br_locate (void *symbol)
{
- char line[5000];
- FILE *f;
- char *path;
-
- br_return_val_if_fail (symbol != NULL, NULL);
-
- f = fopen ("/proc/self/maps", "r");
- if (!f)
- return NULL;
-
- while (!feof (f))
- {
- unsigned long start, end;
-
- if (!fgets (line, sizeof (line), f))
- continue;
- if (!strstr (line, " r-xp ") || !strchr (line, '/'))
- continue;
-
- sscanf (line, "%lx-%lx ", &start, &end);
- if (symbol >= (void *) start && symbol < (void *) end)
- {
- char *tmp;
- size_t len;
-
- /* Extract the filename; it is always an absolute path */
- path = strchr (line, '/');
-
- /* Get rid of the newline */
- tmp = strrchr (path, '\n');
- if (tmp) *tmp = 0;
-
- /* Get rid of "(deleted)" */
- len = strlen (path);
- if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
- {
- tmp = path + len - 10;
- *tmp = 0;
- }
-
- fclose(f);
- return strdup (path);
- }
- }
-
- fclose (f);
- return NULL;
+ char line[5000];
+ FILE *f;
+ char *path;
+
+ br_return_val_if_fail (symbol != NULL, NULL);
+
+ f = fopen ("/proc/self/maps", "r");
+ if (!f)
+ return NULL;
+
+ while (!feof (f))
+ {
+ unsigned long start, end;
+
+ if (!fgets (line, sizeof (line), f))
+ continue;
+ if (!strstr (line, " r-xp ") || !strchr (line, '/'))
+ continue;
+
+ sscanf (line, "%lx-%lx ", &start, &end);
+ if (symbol >= (void *) start && symbol < (void *) end)
+ {
+ char *tmp;
+ size_t len;
+
+ /* Extract the filename; it is always an absolute path */
+ path = strchr (line, '/');
+
+ /* Get rid of the newline */
+ tmp = strrchr (path, '\n');
+ if (tmp) *tmp = 0;
+
+ /* Get rid of "(deleted)" */
+ len = strlen (path);
+ if (len > 10 && strcmp (path + len - 10, " (deleted)") == 0)
+ {
+ tmp = path + len - 10;
+ *tmp = 0;
+ }
+
+ fclose(f);
+ return strdup (path);
+ }
+ }
+
+ fclose (f);
+ return NULL;
}
char *
br_locate_prefix (void *symbol)
{
- char *path, *prefix;
+ char *path, *prefix;
- br_return_val_if_fail (symbol != NULL, NULL);
+ br_return_val_if_fail (symbol != NULL, NULL);
- path = br_locate (symbol);
- if (!path) return NULL;
+ path = br_locate (symbol);
+ if (!path) return NULL;
- prefix = br_extract_prefix (path);
- free (path);
- return prefix;
+ prefix = br_extract_prefix (path);
+ free (path);
+ return prefix;
}
* symbol: A symbol that belongs to the app/library you want to locate.
* path: The path that you want to prepend the prefix to.
* Returns: The new path, or NULL on error. This string should be freed when no
- * longer needed.
+ * longer needed.
*
* Gets the prefix of the app/library that symbol belongs to. Prepend that prefix to path.
* Note that symbol cannot be a pointer to a function. That will not work.
char *
br_prepend_prefix (void *symbol, char *path)
{
- char *tmp, *newpath;
+ char *tmp, *newpath;
- br_return_val_if_fail (symbol != NULL, NULL);
- br_return_val_if_fail (path != NULL, NULL);
+ br_return_val_if_fail (symbol != NULL, NULL);
+ br_return_val_if_fail (path != NULL, NULL);
- tmp = br_locate_prefix (symbol);
- if (!tmp) return NULL;
+ tmp = br_locate_prefix (symbol);
+ if (!tmp) return NULL;
- if (strcmp (tmp, "/") == 0)
- newpath = strdup (path);
- else
- newpath = br_strcat (tmp, path);
+ if (strcmp (tmp, "/") == 0)
+ newpath = strdup (path);
+ else
+ newpath = br_strcat (tmp, path);
- /* Get rid of compiler warning ("br_prepend_prefix never used") */
- if (0) br_prepend_prefix (NULL, NULL);
+ /* Get rid of compiler warning ("br_prepend_prefix never used") */
+ if (0) br_prepend_prefix (NULL, NULL);
- free (tmp);
- return newpath;
+ free (tmp);
+ return newpath;
}
#endif /* ENABLE_BINRELOC */
const char *
br_thread_local_store (char *str)
{
- #if BR_THREADS
+ #if BR_THREADS
if (!g_thread_supported ())
{
g_thread_init ((GThreadFunctions *)NULL);
br_thread_key = g_private_new (g_free);
}
- char *specific = (char *) g_private_get (br_thread_key);
- if (specific)
+ char *specific = (char *) g_private_get (br_thread_key);
+ if (specific)
free (specific);
g_private_set (br_thread_key, str);
- #else /* !BR_THREADS */
- static int initialized = 0;
+ #else /* !BR_THREADS */
+ static int initialized = 0;
- if (!initialized)
- {
- atexit (br_free_last_value);
- initialized = 1;
- }
+ if (!initialized)
+ {
+ atexit (br_free_last_value);
+ initialized = 1;
+ }
- if (br_last_value)
- free (br_last_value);
- br_last_value = str;
- #endif /* BR_THREADS */
+ if (br_last_value)
+ free (br_last_value);
+ br_last_value = str;
+ #endif /* BR_THREADS */
- return (const char *) str;
+ return (const char *) str;
}
char *
br_strcat (const char *str1, const char *str2)
{
- char *result;
- size_t len1, len2;
+ char *result;
+ size_t len1, len2;
- if (!str1) str1 = "";
- if (!str2) str2 = "";
+ if (!str1) str1 = "";
+ if (!str2) str2 = "";
- len1 = strlen (str1);
- len2 = strlen (str2);
+ len1 = strlen (str1);
+ len2 = strlen (str2);
- result = (char *) malloc (len1 + len2 + 1);
- memcpy (result, str1, len1);
- memcpy (result + len1, str2, len2);
- result[len1 + len2] = '\0';
+ result = (char *) malloc (len1 + len2 + 1);
+ memcpy (result, str1, len1);
+ memcpy (result + len1, str2, len2);
+ result[len1 + len2] = '\0';
- return result;
+ return result;
}
static char *
br_strndup (char *str, size_t size)
{
- char *result = (char*)NULL;
- size_t len;
+ char *result = (char*)NULL;
+ size_t len;
- br_return_val_if_fail (str != (char*)NULL, (char*)NULL);
+ br_return_val_if_fail (str != (char*)NULL, (char*)NULL);
- len = strlen (str);
- if (!len) return strdup ("");
- if (size > len) size = len;
+ len = strlen (str);
+ if (!len) return strdup ("");
+ if (size > len) size = len;
- result = (char *) calloc (sizeof (char), len + 1);
- memcpy (result, str, size);
- return result;
+ result = (char *) calloc (sizeof (char), len + 1);
+ memcpy (result, str, size);
+ return result;
}
char *
br_extract_dir (const char *path)
{
- const char *end;
- char *result;
-
- br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
-
- end = strrchr (path, '/');
- if (!end) return strdup (".");
-
- while (end > path && *end == '/')
- end--;
- result = br_strndup ((char *) path, end - path + 1);
- if (!*result)
- {
- free (result);
- return strdup ("/");
- } else
- return result;
+ const char *end;
+ char *result;
+
+ br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
+
+ end = strrchr (path, '/');
+ if (!end) return strdup (".");
+
+ while (end > path && *end == '/')
+ end--;
+ result = br_strndup ((char *) path, end - path + 1);
+ if (!*result)
+ {
+ free (result);
+ return strdup ("/");
+ } else
+ return result;
}
char *
br_extract_prefix (const char *path)
{
- const char *end;
- char *tmp, *result;
-
- br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
-
- if (!*path) return strdup ("/");
- end = strrchr (path, '/');
- if (!end) return strdup (path);
-
- tmp = br_strndup ((char *) path, end - path);
- if (!*tmp)
- {
- free (tmp);
- return strdup ("/");
- }
- end = strrchr (tmp, '/');
- if (!end) return tmp;
-
- result = br_strndup (tmp, end - tmp);
- free (tmp);
-
- if (!*result)
- {
- free (result);
- result = strdup ("/");
- }
-
- return result;
+ const char *end;
+ char *tmp, *result;
+
+ br_return_val_if_fail (path != (char*)NULL, (char*)NULL);
+
+ if (!*path) return strdup ("/");
+ end = strrchr (path, '/');
+ if (!end) return strdup (path);
+
+ tmp = br_strndup ((char *) path, end - path);
+ if (!*tmp)
+ {
+ free (tmp);
+ return strdup ("/");
+ }
+ end = strrchr (tmp, '/');
+ if (!end) return tmp;
+
+ result = br_strndup (tmp, end - tmp);
+ free (tmp);
+
+ if (!*result)
+ {
+ free (result);
+ result = strdup ("/");
+ }
+
+ return result;
}
*/
static Glib::ustring win32_getExePath()
{
- char exeName[MAX_PATH+1];
- GetModuleFileName(NULL, exeName, MAX_PATH);
- char *slashPos = strrchr(exeName, '\\');
- if (slashPos)
- *slashPos = '\0';
- Glib::ustring s = exeName;
- return s;
+ gunichar2 path[2048];
+ GetModuleFileNameW(NULL, (WCHAR*) path, 2048);
+ gchar *exe = g_utf16_to_utf8(path, -1, NULL, NULL, NULL);
+ gchar *dir = g_path_get_dirname(exe);
+ Glib::ustring ret = dir;
+ g_free(dir);
+ g_free(exe);
+ return ret;
}
static Glib::ustring win32_getDataDir()
{
Glib::ustring dir = win32_getExePath();
- if (INKSCAPE_DATADIR && *INKSCAPE_DATADIR &&
- strcmp(INKSCAPE_DATADIR, ".") != 0)
+ if (INKSCAPE_DATADIR && *INKSCAPE_DATADIR &&
+ strcmp(INKSCAPE_DATADIR, ".") != 0)
{
dir += "\\";
dir += INKSCAPE_DATADIR;
diff --git a/src/registrytool.cpp b/src/registrytool.cpp
index 2017f50c756b6ccb4fdf7f4eeaf882420cfdd20d..af41c3eaf963807e35293d8bebfc49a03fd358db 100644 (file)
--- a/src/registrytool.cpp
+++ b/src/registrytool.cpp
const Glib::ustring &value)
{
Glib::ustring keyName = keyNameArg;
+ bool ret = false;
HKEY rootKey = HKEY_LOCAL_MACHINE; //default root
//Trim out the root key if necessary
//printf("trimmed string: '%s'\n", keyName.c_str());
//Get or create the key
+ gunichar2 *keyw = g_utf8_to_utf16(keyName.data(), -1, 0,0,0);
+ gunichar2 *valuenamew = g_utf8_to_utf16(valueName.data(), -1, 0,0,0);
+
HKEY key;
- if (RegCreateKeyEx(rootKey, keyName.c_str(),
+ if (RegCreateKeyExW(rootKey, (WCHAR*) keyw,
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_WRITE, NULL, &key, NULL))
- {
+ {
fprintf(stderr, "RegistryTool: Could not create the registry key '%s'\n", keyName.c_str());
- return false;
- }
+ goto fail;
+ }
- //Set the value
- if (RegSetValueEx(key, valueName.c_str(),
- 0, REG_SZ, (LPBYTE) value.c_str(), (DWORD) value.size()))
- {
+ // Set the value
+ if (RegSetValueExW(key, (WCHAR*) valuenamew,
+ 0, REG_SZ, (LPBYTE) value.data(), (DWORD) (value.size() + 1)))
+ {
fprintf(stderr, "RegistryTool: Could not set the value '%s'\n", value.c_str());
- RegCloseKey(key);
- return false;
- }
-
+ goto failkey;
+ }
+ ret = true;
+
+ failkey:
RegCloseKey(key);
-
- return true;
+
+ fail:
+ g_free(keyw);
+ g_free(valuenamew);
+ return ret;
}
Glib::ustring &path,
Glib::ustring &exeName)
{
+ const int pathbuf = 2048;
+ gunichar2 pathw[pathbuf];
+ GetModuleFileNameW(NULL, (WCHAR*) pathw, pathbuf);
- char buf[MAX_PATH+1];
- if (!GetModuleFileName(NULL, buf, MAX_PATH))
- {
- fprintf(stderr, "Could not fetch executable file name\n");
- return false;
- }
- else
- {
- //printf("Executable file name: '%s'\n", buf);
- }
+ gchar *utf8path = g_utf16_to_utf8(pathw, -1, 0,0,0);
+ fullPath = utf8path;
+ g_free(utf8path);
- fullPath = buf;
path = "";
exeName = "";
Glib::ustring::size_type pos = fullPath.rfind('\\');