diff options
-rw-r--r-- | openscad.pro | 5 | ||||
-rw-r--r-- | scripts/installer.nsi | 1 | ||||
-rwxr-xr-x | scripts/release-common.sh | 9 | ||||
-rw-r--r-- | src/winconsole.c | 146 | ||||
-rw-r--r-- | winconsole.pri | 28 |
5 files changed, 189 insertions, 0 deletions
diff --git a/openscad.pro b/openscad.pro index b11f45b..a7088ec 100644 --- a/openscad.pro +++ b/openscad.pro @@ -344,3 +344,8 @@ INSTALLS += applications icons.path = $$PREFIX/share/pixmaps icons.files = icons/openscad.png INSTALLS += icons + +CONFIG(winconsole) { + include(winconsole.pri) +} + diff --git a/scripts/installer.nsi b/scripts/installer.nsi index 87ec18d..1841431 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -6,6 +6,7 @@ DirText "This will install OpenSCAD on your computer. Choose a directory" Section "install" SetOutPath $INSTDIR File openscad.exe +File openscad.com File /r /x mingw-cross-env examples File /r /x mingw-cross-env libraries ${registerExtension} "$INSTDIR\openscad.exe" ".scad" "OpenSCAD_File" diff --git a/scripts/release-common.sh b/scripts/release-common.sh index ae856df..de14cb1 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -166,7 +166,14 @@ fi case $OS in LINXWIN) # dont use paralell builds, it can error-out on parser_yacc. + + # make main openscad.exe cd $DEPLOYDIR && make $TARGET + + # make console pipe-able openscad.com - see winconsole.pri for info + i686-pc-mingw32-qmake CONFIG+=winconsole ../openscad.pro + make + cd $OPENSCADDIR ;; *) @@ -232,6 +239,7 @@ case $OS in #package cp win32deps/* openscad-$VERSION cp $TARGET/openscad.exe openscad-$VERSION + cp $TARGET/openscad.com openscad-$VERSION rm -f openscad-$VERSION.zip "$ZIP" $ZIPARGS openscad-$VERSION.zip openscad-$VERSION rm -rf openscad-$VERSION @@ -242,6 +250,7 @@ case $OS in echo "Creating binary package" cd $DEPLOYDIR cp $TARGET/openscad.exe openscad-$VERSION + cp $TARGET/openscad.com openscad-$VERSION rm -f OpenSCAD-$VERSION.zip "$ZIP" $ZIPARGS OpenSCAD-$VERSION.zip openscad-$VERSION cd $OPENSCADDIR diff --git a/src/winconsole.c b/src/winconsole.c new file mode 100644 index 0000000..2180e19 --- /dev/null +++ b/src/winconsole.c @@ -0,0 +1,146 @@ +// enable easy piping under windows command line, using the 'devenv' method +// http://stackoverflow.com/questions/493536/can-one-executable-be-both-a-console-and-gui-app +// http://blogs.msdn.com/b/oldnewthing/archive/2009/01/01/9259142.aspx +// http://blogs.msdn.com/b/junfeng/archive/2004/02/06/68531.aspx +// http://www.i18nguy.com/unicode/c-unicode.html + +/* + +Based on inkscapec by Jos Hirth work at http://kaioa.com +and Nop Head's OpenSCAD_cl at github.com + +Zero-clause BSD-style license (DGAF) + +Redistribution and use in source and binary forms, with or without +modification, are permitted. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include <windows.h> +#include <stdio.h> +#include <tchar.h> +void HandleOutput(HANDLE hPipeRead); +DWORD WINAPI RedirThread(LPVOID lpvThreadParam); + +HANDLE hChildProcess=NULL; +HANDLE hStdIn=NULL; +BOOL bRunThread=TRUE; + +int main(int argc,char *argv[]){ + HANDLE hOutputReadTemp,hOutputRead,hOutputWrite; + HANDLE hInputWriteTemp,hInputRead,hInputWrite; + HANDLE hErrorWrite; + HANDLE hThread; + DWORD ThreadId; + SECURITY_ATTRIBUTES sa; + + sa.nLength=sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor=NULL; + sa.bInheritHandle=TRUE; + + int i; + wchar_t cmd[32000]; + wcscat( cmd,L"\0" ); + wcscat( cmd,L"openscad.exe" ); + int wargc; + LPWSTR *wargv; + wargv = CommandLineToArgvW(GetCommandLineW(), &wargc); + if ( !wargv ) { + printf(" error in CommandLineToArgvW\n"); + return 1; + } + for(i=1;i<argc;i++){ + wcscat( cmd, L" " ); + wcscat( cmd, wargv[i] ); + } + LocalFree( wargv ); + + CreatePipe(&hOutputReadTemp,&hOutputWrite,&sa,0); + DuplicateHandle(GetCurrentProcess(),hOutputWrite,GetCurrentProcess(),&hErrorWrite,0,TRUE,DUPLICATE_SAME_ACCESS); + CreatePipe(&hInputRead,&hInputWriteTemp,&sa,0); + DuplicateHandle(GetCurrentProcess(),hOutputReadTemp,GetCurrentProcess(),&hOutputRead,0,FALSE,DUPLICATE_SAME_ACCESS); + DuplicateHandle(GetCurrentProcess(),hInputWriteTemp,GetCurrentProcess(),&hInputWrite,0,FALSE,DUPLICATE_SAME_ACCESS); + CloseHandle(hOutputReadTemp); + CloseHandle(hInputWriteTemp); + + hStdIn=GetStdHandle(STD_INPUT_HANDLE); + + //- + PROCESS_INFORMATION pi; + STARTUPINFO si; + + ZeroMemory(&si,sizeof(STARTUPINFO)); + si.cb=sizeof(STARTUPINFO); + si.dwFlags=STARTF_USESTDHANDLES; + si.hStdOutput=hOutputWrite; + si.hStdInput=hInputRead; + si.hStdError=hErrorWrite; + + CreateProcess(NULL,cmd,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi); + + hChildProcess=pi.hProcess; + + CloseHandle(pi.hThread); + //- + + CloseHandle(hOutputWrite); + CloseHandle(hInputRead); + CloseHandle(hErrorWrite); + + hThread=CreateThread(NULL,0,RedirThread,(LPVOID)hInputWrite,0,&ThreadId); + + HandleOutput(hOutputRead); + + CloseHandle(hStdIn); + + bRunThread=FALSE; + + WaitForSingleObject(hThread,INFINITE); + CloseHandle(hOutputRead); + CloseHandle(hInputWrite); + + return 0; +} + +void HandleOutput(HANDLE hPipeRead){ + CHAR lpBuffer[256]; + DWORD nRead; + DWORD nWrote; + + while(TRUE){ + if(!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),&nRead,NULL)||!nRead) + if(GetLastError()==ERROR_BROKEN_PIPE) + break; + WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer,nRead,&nWrote,NULL); + } +} + +DWORD WINAPI RedirThread(LPVOID lpvThreadParam){ + CHAR buff[256]; + DWORD nRead,nWrote; + HANDLE hPipeWrite=(HANDLE)lpvThreadParam; + + while(bRunThread){ + ReadConsole(hStdIn,buff,1,&nRead,NULL); + + buff[nRead]='\0'; + + if(!WriteFile(hPipeWrite,buff,nRead,&nWrote,NULL)){ + if(GetLastError()==ERROR_NO_DATA) + break; + } + } + return 1; +} diff --git a/winconsole.pri b/winconsole.pri new file mode 100644 index 0000000..a3991ae --- /dev/null +++ b/winconsole.pri @@ -0,0 +1,28 @@ +# Windows console issues workaround stub. +# +# Usage: put at the end of .pro file, then run qmake CONFIG+=winconsole +# +# This attempts to solve the problem of piping OpenSCAD under windows +# command line (GUI mode programs in Windows dont allow this). We use +# the 'devenv' solution, which means building two binaries: +# openscad.exe, and openscad.com, the latter being a wrapper for the +# former. See src/winconsole.c for more details. +# +# Qmake doesn't like building two binaries in the same directory so we +# depend on release-common.sh to call qmake twice and package the file properly + +CONFIG(winconsole) { + TEMPLATE = app + TARGET = openscad_winconsole + FORMS = + HEADERS = + FLEXSOURCES = + BISONSOURCES = + RESOURCES = + SOURCES = src/winconsole.c + CONFIG += console # sets IMAGE_SUBSYSTEM_WINDOWS_CUI in binary + LIBS -= $$LIBS + RC_FILE -= $$RC_FILE + QMAKE_POST_LINK = cd $(DESTDIR) && mv openscad_winconsole.exe openscad.com +} + |