summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 0a095f9)
raw | patch | inline | side by side (parent: 0a095f9)
author | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Mon, 29 Mar 2010 20:32:32 +0000 (22:32 +0200) | ||
committer | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Mon, 29 Mar 2010 20:32:32 +0000 (22:32 +0200) |
which provides Unix-like behavior on Windows.
.bzrignore | patch | blob | history | |
build.xml | patch | blob | history | |
share/extensions/webslicer_create_group.py | [changed mode: 0755->0644] | patch | blob | history |
src/winconsole.cpp | [new file with mode: 0644] | patch | blob |
diff --git a/.bzrignore b/.bzrignore
index 3c299bb337c4127dda48e9b7fb59f6947412568d..4d9683c279caa52dd3543153fe7a882b0e2965ee 100644 (file)
--- a/.bzrignore
+++ b/.bzrignore
src/util/makefile
src/widgets/makefile
src/xml/makefile
+src/test-main.cpp
+src/test-src.cpp
+src/display/test-display.cpp
+src/helper/test-helper.cpp
+src/libnr/test-nr.cpp
+src/svg/test-svg.cpp
+src/util/test-util.cpp
+src/xml/test-xml.cpp
+gc.log
diff --git a/build.xml b/build.xml
index 69a80008248de78c8eb8f7a8d4ba4b61e86e0048..0c895fb567e9acc41bd4818cba6592ffa553f905 100755 (executable)
--- a/build.xml
+++ b/build.xml
</link>
</target>
+<!--
+ ########################################################################
+ ## T A R G E T : L I N K C O N S O L E
+ ########################################################################
+ -->
+ <target name="linkconsole" depends="compile"
+ description="link console helper">
-
-
+ <link command="${arch}g++" out="${build}/inkscape-console.exe"
+ strip="true" stripcommand="${archutil}strip">
+ <flags>
+ -mconsole
+ -mthreads
+ </flags>
+ <fileset dir="${build}">
+ <include name="obj/winconsole.o"/>
+ </fileset>
+ <libs></libs>
+ </link>
+ </target>
<!--
########################################################################
## T A R G E T : D I S T - I N K S C A P E
########################################################################
-->
- <target name="dist-inkscape" depends="link,distbase"
+ <target name="dist-inkscape" depends="link,linkconsole,distbase"
description="copy inkscape to the distribution directory">
<!-- Create the distribution directory -->
<copy todir="${dist}" file="${build}/inkscape.exe"/>
<copy todir="${dist}" file="${build}/inkscape.dbg"/>
+ <copy file="${build}/inkscape-console.exe" tofile="${dist}/inkscape.com"/>
</target>
diff --git a/share/extensions/webslicer_create_group.py b/share/extensions/webslicer_create_group.py
old mode 100755 (executable)
new mode 100644 (file)
new mode 100644 (file)
diff --git a/src/winconsole.cpp b/src/winconsole.cpp
--- /dev/null
+++ b/src/winconsole.cpp
@@ -0,0 +1,153 @@
+/** \file
+ * @brief Command-line wrapper for Windows.
+ *
+ * Windows has two types of executables: GUI and console.
+ * The GUI executables detach immediately when run from the command
+ * prompt (cmd.exe), and whatever you write to standard output
+ * disappears into a black hole. Console executables handle
+ * do display standard output and take standard input from the console,
+ * but when you run them from the GUI, an extra console window appears.
+ * It's possible to hide it, but it still flashes from a fraction
+ * of a second.
+ *
+ * To provide an Unix-like experienve, where the application will behave
+ * correctly in command line mode and at the same time won't create
+ * the ugly console window when run from the GUI, we have to have two
+ * executables. The first one, inkscape.exe, is the GUI application.
+ * Its entry points are in main.cpp and winmain.cpp. The second one,
+ * called inkscape.com, is a small helper application contained in
+ * this file. It spawns the GUI application and redirects its output
+ * to the console.
+ *
+ * Note that inkscape.com has nothing to do with "compact executables"
+ * from DOS. It's a normal PE executable renamed to .com. The trick
+ * is that cmd.exe picks .com over .exe when both are present in PATH,
+ * so when you type "inkscape" into the command prompt, inkscape.com
+ * gets run. The Windows program loader does not inspect the extension,
+ * just like an Unix program loader; it determines the binary format
+ * based on the contents of the file.
+ *
+ *//*
+ * Authors:
+ * Jos Hirth <jh@kaioa.com>
+ * Krzysztof Kosiñski <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2008-2010 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef WIN32
+#undef DATADIR
+#include <windows.h>
+
+struct echo_thread_info {
+ HANDLE echo_read;
+ HANDLE echo_write;
+ unsigned buffer_size;
+};
+
+// thread function for echoing from one file handle to another
+DWORD WINAPI echo_thread(void *info_void)
+{
+ echo_thread_info *info = static_cast<echo_thread_info*>(info_void);
+ char *buffer = reinterpret_cast<char *>(LocalAlloc(LMEM_FIXED, info->buffer_size));
+ DWORD bytes_read, bytes_written;
+
+ while(true){
+ if (!ReadFile(info->echo_read, buffer, info->buffer_size, &bytes_read, NULL) || bytes_read == 0)
+ if (GetLastError() == ERROR_BROKEN_PIPE)
+ break;
+
+ if (!WriteFile(info->echo_write, buffer, bytes_read, &bytes_written, NULL)) {
+ if (GetLastError() == ERROR_NO_DATA)
+ break;
+ }
+ }
+
+ LocalFree(reinterpret_cast<HLOCAL>(buffer));
+ CloseHandle(info->echo_read);
+ CloseHandle(info->echo_write);
+
+ return 1;
+}
+
+int main()
+{
+ // structs that will store information for our I/O threads
+ echo_thread_info stdin = {NULL, NULL, 4096};
+ echo_thread_info stdout = {NULL, NULL, 4096};
+ echo_thread_info stderr = {NULL, NULL, 4096};
+ // handles we'll pass to inkscape.exe
+ HANDLE inkscape_stdin, inkscape_stdout, inkscape_stderr;
+ HANDLE stdin_thread, stdout_thread, stderr_thread;
+
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength=sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor=NULL;
+ sa.bInheritHandle=TRUE;
+
+ // Determine the path to the Inkscape executable.
+ // Do this by looking up the name of this one and redacting the extension to ".exe"
+ const int pathbuf = 2048;
+ WCHAR *inkscape = reinterpret_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, pathbuf * sizeof(WCHAR)));
+ GetModuleFileNameW(NULL, inkscape, pathbuf);
+ WCHAR *dot_index = wcsrchr(inkscape, L'.');
+ wcsncpy(dot_index, L".exe", 4);
+
+ // we simply reuse our own command line for inkscape.exe
+ // it guarantees perfect behavior w.r.t. quoting
+ WCHAR *cmd = GetCommandLineW();
+
+ // set up the pipes and handles
+ stdin.echo_read = GetStdHandle(STD_INPUT_HANDLE);
+ stdout.echo_write = GetStdHandle(STD_OUTPUT_HANDLE);
+ stderr.echo_write = GetStdHandle(STD_ERROR_HANDLE);
+ CreatePipe(&inkscape_stdin, &stdin.echo_write, &sa, 0);
+ CreatePipe(&stdout.echo_read, &inkscape_stdout, &sa, 0);
+ CreatePipe(&stderr.echo_read, &inkscape_stderr, &sa, 0);
+
+ // fill in standard IO handles to be used by the process
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+
+ ZeroMemory(&si,sizeof(STARTUPINFO));
+ si.cb = sizeof(STARTUPINFO);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = inkscape_stdin;
+ si.hStdOutput = inkscape_stdout;
+ si.hStdError = inkscape_stderr;
+
+ // spawn inkscape.exe
+ CreateProcessW(inkscape, // path to inkscape.exe
+ cmd, // command line as a single string
+ NULL, // process security attributes - unused
+ NULL, // thread security attributes - unused
+ TRUE, // inherit handles
+ 0, // flags
+ NULL, // environment - NULL = inherit from us
+ NULL, // working directory - NULL = inherit ours
+ &si, // startup info - see above
+ &pi); // information about the created process - unused
+
+ // clean up a bit
+ LocalFree(reinterpret_cast<HLOCAL>(inkscape));
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ CloseHandle(inkscape_stdin);
+ CloseHandle(inkscape_stdout);
+ CloseHandle(inkscape_stderr);
+
+ // create IO echo threads
+ DWORD unused;
+ stdin_thread = CreateThread(NULL, 0, echo_thread, (void*) &stdin, 0, &unused);
+ stdout_thread = CreateThread(NULL, 0, echo_thread, (void*) &stdout, 0, &unused);
+ stderr_thread = CreateThread(NULL, 0, echo_thread, (void*) &stderr, 0, &unused);
+
+ // wait until the standard output thread terminates
+ WaitForSingleObject(stdout_thread, INFINITE);
+
+ return 0;
+}
+
+#endif