Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
inkscape-main.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Inkscape - an ambitious vector drawing program
4 *
5 * Authors:
6 * Tavmjong Bah
7 *
8 * (C) 2018 Tavmjong Bah
9 *
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11 */
12
13#include <glibmm/miscutils.h>
14#include <gsl/gsl_errno.h>
15
16#ifdef _WIN32
17#include <windows.h> // SetDllDirectoryW, SetConsoleOutputCP
18#undef IGNORE
19#undef near
20#include <fcntl.h> // _O_BINARY
21#include <boost/algorithm/string/join.hpp>
22#endif
23
25#include "path-prefix.h"
26#include "io/resource.h"
27#include "util/statics.h"
28
29static void set_extensions_env()
30{
31 // add inkscape to PATH, so the correct version is always available to extensions by simply calling "inkscape"
32 char const *program_dir = get_program_dir();
33 if (program_dir) {
34 gchar const *path = g_getenv("PATH");
35 gchar *new_path = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "%s", program_dir, path);
36 g_setenv("PATH", new_path, true);
37 g_free(new_path);
38 }
39
40 // add various locations to PYTHONPATH so extensions find their modules
41 auto extensiondir_user = get_path_string(Inkscape::IO::Resource::USER, Inkscape::IO::Resource::EXTENSIONS);
42 auto extensiondir_system = get_path_string(Inkscape::IO::Resource::SYSTEM, Inkscape::IO::Resource::EXTENSIONS);
43
44 auto pythonpath = extensiondir_user + G_SEARCHPATH_SEPARATOR + extensiondir_system;
45
46 auto pythonpath_old = Glib::getenv("PYTHONPATH");
47 if (!pythonpath_old.empty()) {
48 pythonpath += G_SEARCHPATH_SEPARATOR + pythonpath_old;
49 }
50
51 pythonpath += G_SEARCHPATH_SEPARATOR + Glib::build_filename(extensiondir_system, "inkex", "deprecated-simple");
52
53 Glib::setenv("PYTHONPATH", pythonpath);
54
55 // Python 2.x attempts to encode output as ASCII by default when sent to a pipe.
56 Glib::setenv("PYTHONIOENCODING", "UTF-8");
57
58#ifdef _WIN32
59 // add inkscape directory to DLL search path so dynamically linked extension modules find their libraries
60 // should be fixed in Python 3.8 (https://github.com/python/cpython/commit/2438cdf0e932a341c7613bf4323d06b91ae9f1f1)
61 char const *installation_dir = get_program_dir();
62 wchar_t *installation_dir_w = (wchar_t *)g_utf8_to_utf16(installation_dir, -1, NULL, NULL, NULL);
63 SetDllDirectoryW(installation_dir_w);
64 g_free(installation_dir_w);
65#endif
66}
67
72static void set_themes_env()
73{
74 std::string xdg_data_dirs = Glib::getenv("XDG_DATA_DIRS");
75
76 if (xdg_data_dirs.empty()) {
77 // initialize with reasonable defaults (should match what glib would do if the variable were unset!)
78#ifdef _WIN32
79 // g_get_system_data_dirs is actually not cached on Windows,
80 // so we can just call it directly and modify XDG_DATA_DIRS later
81 auto data_dirs = Glib::get_system_data_dirs();
82 xdg_data_dirs = boost::join(data_dirs, G_SEARCHPATH_SEPARATOR_S);
83#elif defined(__APPLE__)
84 // we don't know what the default is, differs for MacPorts, Homebrew, etc.
85 return;
86#else
87 // initialize with glib default (don't call g_get_system_data_dirs; it's cached!)
88 xdg_data_dirs = "/usr/local/share/:/usr/share/";
89#endif
90 }
91
92 std::string inkscape_datadir = Glib::build_filename(get_inkscape_datadir(), "inkscape");
93 Glib::setenv("XDG_DATA_DIRS", xdg_data_dirs + G_SEARCHPATH_SEPARATOR_S + inkscape_datadir);
94}
95
96
97
98#ifdef _WIN32
99// some win32-specific environment adjustments
100static void set_win32_env()
101{
102 // activate "experimental" native DND implementation that uses OLE2
103 // - fixes some docking issues with the new dialog system
104 // - is likely to become the default at some point, see
105 // https://discourse.gnome.org/t/can-should-we-use-the-experimental-win32-ole2-dnd-implementation/4062
106 Glib::setenv("GDK_WIN32_USE_EXPERIMENTAL_OLE2_DND", "1");
107}
108#endif
109
115static void convert_legacy_options(int &argc, char **&argv)
116{
117 static std::vector<char *> argv_new;
118 char *file = nullptr;
119
120 for (int i = 0; i < argc; ++i) {
121 if (g_str_equal(argv[i], "--without-gui") || g_str_equal(argv[i], "-z")) {
122 std::cerr << "Warning: Option --without-gui= is deprecated" << std::endl;
123 continue;
124 }
125
126 if (g_str_has_prefix(argv[i], "--file=")) {
127 std::cerr << "Warning: Option --file= is deprecated" << std::endl;
128 file = argv[i] + 7;
129 continue;
130 }
131
132 bool found_legacy_export = false;
133
134 for (char const *type : { "png", "pdf", "ps", "eps", "emf", "wmf", "plain-svg" }) {
135 auto s = std::string("--export-").append(type).append("=");
136 if (g_str_has_prefix(argv[i], s.c_str())) {
137 std::cerr << "Warning: Option " << s << " is deprecated" << std::endl;
138
139 if (g_str_equal(type, "plain-svg")) {
140 argv_new.push_back(g_strdup("--export-plain-svg"));
141 type = "svg";
142 }
143
144 argv_new.push_back(g_strdup_printf("--export-type=%s", type));
145 argv_new.push_back(g_strdup_printf("--export-filename=%s", argv[i] + s.size()));
146
147 found_legacy_export = true;
148 break;
149 }
150 }
151
152 if (found_legacy_export) {
153 continue;
154 }
155
156 argv_new.push_back(argv[i]);
157 }
158
159 if (file) {
160 argv_new.push_back(file);
161 }
162
163 argc = argv_new.size();
164 argv = argv_new.data();
165}
166
167int main(int argc, char *argv[])
168{
169 Gtk::Application::wrap_in_search_entry2();
170
171#if !defined(_WIN32)
172 // Opt into handling EPIPE locally, rather than crashing.
173 signal(SIGPIPE, SIG_IGN);
174#endif
175
176 // Opt into handling GSL errors locally, rather than crashing.
177 gsl_set_error_handler_off();
178
179 convert_legacy_options(argc, argv);
180
181#ifdef __APPLE__
182 { // Check if we're inside an application bundle and adjust environment
183 // accordingly.
184
185 char const *program_dir = get_program_dir();
186 if (g_str_has_suffix(program_dir, "Contents/MacOS")) {
187
188 // Step 1
189 // Remove macOS session identifier from command line arguments.
190 // Code adopted from GIMP's app/main.c
191
192 int new_argc = 0;
193 for (int i = 0; i < argc; i++) {
194 // Rewrite argv[] without "-psn_..." argument.
195 if (!g_str_has_prefix(argv[i], "-psn_")) {
196 argv[new_argc] = argv[i];
197 new_argc++;
198 }
199 }
200 if (argc > new_argc) {
201 argv[new_argc] = nullptr; // glib expects null-terminated array
202 argc = new_argc;
203 }
204 }
205 }
206#elif defined _WIN32
207 // adjust environment
209
210 // temporarily switch console encoding to UTF8 while Inkscape runs
211 // as everything else is a mess and it seems to work just fine
212 const unsigned int initial_cp = GetConsoleOutputCP();
213 SetConsoleOutputCP(CP_UTF8);
214 fflush(stdout); // empty buffer, just to be safe (see warning in documentation for _setmode)
215 _setmode(_fileno(stdout), _O_BINARY); // binary mode seems required for this to work properly
216#endif
217
218 set_xdg_env();
221
222 auto ret = InkscapeApplication().gio_app()->run(argc, argv);
223
225
226#ifdef _WIN32
227 // switch back to initial console encoding
228 SetConsoleOutputCP(initial_cp);
229#endif
230
231 return ret;
232}
233
234/*
235 Local Variables:
236 mode:c++
237 c-file-style:"stroustrup"
238 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
239 indent-tabs-mode:nil
240 fill-column:99
241 End:
242*/
243// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
int main()
Gio::Application * gio_app()
The Gio application instance, never NULL.
static StaticsBin & get()
Definition statics.cpp:8
static void convert_legacy_options(int &argc, char **&argv)
Convert some legacy 0.92.x command line options to 1.0.x options.
static void set_extensions_env()
static void set_themes_env()
Adds the local inkscape directory to the XDG_DATA_DIRS so themes and other Gtk resources which are sp...
static void set_win32_env()
char const * get_inkscape_datadir()
Determine the location of the Inkscape data directory (typically the share/ folder from where Inkscap...
void set_xdg_env()
Sets environment variables for a relocatable application bundle.
char const * get_program_dir()
Gets the the full path to the directory containing the currently running program's executable.
TODO: insert short description here.
Inkscape::IO::Resource - simple resource API.
Static objects with destruction before main() exit.