Index: makefile.win32 =================================================================== --- makefile.win32 (revision 2263) +++ makefile.win32 (working copy) @@ -16,15 +16,16 @@ CXX = g++ CP = copy RM = del +MAKE = c:\MinGW\bin\mingw32-make.exe -include localwin32.mk # Note: && is needed after cd because each line is executed in a different # shell. (cd .. is just for clarity). all: check-tools config.h - cd tagmanager && make -f makefile.win32 && cd .. - cd scintilla && make -f makefile.win32 && cd .. - cd plugins && make -f makefile.win32 && cd .. - cd src && make -f makefile.win32 && cd .. + cd tagmanager && $(MAKE) -f makefile.win32 && cd .. + cd scintilla && $(MAKE) -f makefile.win32 && cd .. + cd plugins && $(MAKE) -f makefile.win32 && cd .. + cd src && $(MAKE) -f makefile.win32 && cd .. # first check the required tools are installed check-tools: @@ -43,7 +44,7 @@ -$(RM) geany_private.res geany.exe clean: deps - cd tagmanager && make -f makefile.win32 clean && cd .. - cd scintilla && make -f makefile.win32 clean && cd .. - cd plugins && make -f makefile.win32 clean && cd .. - cd src && make -f makefile.win32 clean && cd .. + cd tagmanager && $(MAKE) -f makefile.win32 clean && cd .. + cd scintilla && $(MAKE) -f makefile.win32 clean && cd .. + cd plugins && $(MAKE) -f makefile.win32 clean && cd .. + cd src && $(MAKE) -f makefile.win32 clean && cd .. Index: plugins/vcdiff.c =================================================================== --- plugins/vcdiff.c (revision 2263) +++ plugins/vcdiff.c (working copy) @@ -36,6 +36,11 @@ #include "project.h" #include "pluginmacros.h" +#ifdef G_OS_WIN32 +#include +#include +#endif + PluginFields *plugin_fields; GeanyData *geany_data; @@ -167,7 +172,6 @@ return ret; } - static void* find_cmd_env(gint cmd_type, gboolean cmd, const gchar* filename) { guint i; @@ -186,7 +190,7 @@ } -static void* get_cmd_env(gint cmd_type, gboolean cmd, const gchar* filename) +static void* get_cmd_env(gint cmd_type, gboolean cmd, const gchar* filename, int *size) { int i; gint len = 0; @@ -234,6 +238,9 @@ else ret[i] = g_strdup(argv[i]); } + + *size = len; + g_free(dir); g_free(base_filename); return ret; @@ -307,16 +314,16 @@ g_free(filename); } - static gchar *make_diff(const gchar *filename, gint cmd) { gchar *std_output = NULL; gchar *std_error = NULL; - gint exit_code; gchar *text = NULL; gchar *dir; - gchar **env = get_cmd_env(cmd, FALSE, filename); - gchar **argv = get_cmd_env(cmd, TRUE, filename); + gint argc = 0; + gchar **env = get_cmd_env(cmd, FALSE, filename, &argc); + gchar **argv = get_cmd_env(cmd, TRUE, filename, &argc); + gint exit_code = 0; if (!argv) { @@ -334,9 +341,10 @@ dir = g_path_get_dirname(filename); } - if (g_spawn_sync(dir, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL, &std_output, &std_error, &exit_code, NULL)) + if (p_utils->utils_spawn_sync(dir, (const gchar **) argv, (const gchar **) env, G_SPAWN_SEARCH_PATH, + NULL, NULL, &std_output, &std_error, &exit_code)) { - // CVS dump stuff to stderr when diff nested dirs + /* CVS dump stuff to stderr when diff nested dirs*/ if (strcmp(argv[0], "cvs") != 0 && NZV(std_error)) { p_dialogs->show_msgbox(1, @@ -345,17 +353,22 @@ else if (NZV(std_output)) { text = std_output; - } + } else { p_ui->set_statusbar(FALSE, _("No changes were made.")); } + + if (NZV(std_error)) + { + p_dialogs->show_msgbox(1, "VCDIFF command sent errors:\n%s\n.", std_error); + } } else { - p_ui->set_statusbar(FALSE, - _("Something went really wrong.")); + p_ui->set_statusbar(FALSE, _("Something went really wrong.")); } + g_free(dir); g_free(std_error); g_strfreev(env); Index: src/plugindata.h =================================================================== --- src/plugindata.h (revision 2263) +++ src/plugindata.h (working copy) @@ -241,6 +241,12 @@ const gint default_value); gchar* (*get_setting_string) (GKeyFile *config, const gchar *section, const gchar *key, const gchar *default_value); + gboolean (*utils_spawn_sync) (const gchar *dir, const gchar **argv, + const gchar **env,GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, gpointer user_data, + gchar **std_out, gchar **std_err, gint *exit_status); + gboolean (*utils_spawn_async) (const gchar *cmdline, const gchar *dir, + gchar **std_out, gchar **std_err); } UtilsFuncs; Index: src/plugins.c =================================================================== --- src/plugins.c (revision 2263) +++ src/plugins.c (working copy) @@ -153,7 +153,9 @@ &utils_mkdir, &utils_get_setting_boolean, &utils_get_setting_integer, - &utils_get_setting_string + &utils_get_setting_string, + &utils_spawn_sync, + NULL, }; static UIUtilsFuncs uiutils_funcs = { Index: src/utils.c =================================================================== --- src/utils.c (revision 2263) +++ src/utils.c (working copy) @@ -56,7 +56,6 @@ #include "utils.h" - void utils_start_browser(const gchar *uri) { #ifdef G_OS_WIN32 @@ -1792,4 +1791,34 @@ return NULL; } +const gboolean utils_spawn_sync(const gchar *dir, const gchar **argv, + const gchar **env, GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, gpointer user_data, + gchar **std_out, gchar **std_err, gint *exit_status) +{ + gboolean result; + g_return_val_if_fail (argv != NULL, FALSE); + g_return_val_if_fail (std_out == NULL || + !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE); + g_return_val_if_fail (std_err == NULL || + !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE); + + if (std_out) + { + *std_out = NULL; + } + + if (std_err) + { + *std_err = NULL; + } + +#ifdef G_OS_WIN32 + result = geany_w32_spawn_sync(dir, argv, env, flags, std_out, std_err, exit_status); +#else + result = g_spawn_sync(dir, argv, env, flags, NULL, NULL, std_out, std_err, exit_status, NULL)); +#endif + + return result; +} Index: src/utils.h =================================================================== --- src/utils.h (revision 2263) +++ src/utils.h (working copy) @@ -146,4 +146,15 @@ gint utils_is_file_writeable(const gchar *locale_filename); + +const gboolean utils_spawn_sync(const gchar *dir, const gchar **argv, + const gchar **env, GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, gpointer user_data, + gchar **std_out, gchar **std_err, gint *exit_status); + +const gboolean utils_spawn_sync(const gchar *dir, const gchar **argv, + const gchar **env, GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, gpointer user_data, + gchar **std_out, gchar **std_err, gint *exit_status); + #endif Index: src/win32.c =================================================================== --- src/win32.c (revision 2263) +++ src/win32.c (working copy) @@ -54,8 +54,30 @@ #include "dialogs.h" #include "filetypes.h" +#define BUFSIZE 4096 +struct _geany_win32_spawn +{ + HANDLE hChildStdinRd; + HANDLE hChildStdinWr; + HANDLE hChildStdoutRd; + HANDLE hChildStdoutWr; + HANDLE hChildStderrRd; + HANDLE hChildStderrWr; + HANDLE hInputFile; + HANDLE hStdout; + HANDLE hStderr; +}; +typedef struct _geany_win32_spawn geany_win32_spawn; + +gboolean GetContentFromHandle(HANDLE hFile, gchar **content); +HANDLE getTempFileHandle(); +gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, TCHAR *dir); +VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile); +VOID ErrorExit(LPSTR); + + static gchar *get_file_filters() { gchar *string; @@ -700,7 +722,6 @@ return folder; } - gchar *win32_get_hostname() { gchar hostname[100]; @@ -712,4 +733,288 @@ return g_strdup("localhost"); } +gboolean geany_w32_spawn_sync( const gchar *dir, const gchar **argv, + const gchar **env, GSpawnFlags flags, + gchar **std_out, gchar **std_err, gchar *exit_status) +{ + TCHAR buffer[MAX_PATH]=TEXT(""); + TCHAR cmdline[MAX_PATH] = TEXT(""); + TCHAR* lpPart[MAX_PATH]={NULL}; + DWORD retval=0; + gint argc = 0, i; + gint cmdpos=0; + + SECURITY_ATTRIBUTES saAttr; + BOOL fSuccess; + geany_win32_spawn gw_spawn; + + /* Temp file */ + HANDLE hStdoutTempFile = NULL; + HANDLE hStderrTempFile = NULL; + + gchar *stdout_content = NULL; + gchar *stderr_content = NULL; + + while (argv[argc]) + { + ++argc; + } + g_return_val_if_fail (std_out == NULL || + !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE); + g_return_val_if_fail (std_err == NULL || + !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE); + + if (flags & G_SPAWN_SEARCH_PATH) + { + retval = SearchPath(NULL, + argv[0], ".exe", MAX_PATH, buffer, lpPart); + sprintf(cmdline, "\"%s\"", buffer); + cmdpos = 1; + } + + for (i = cmdpos; i < argc; i++) { + sprintf(cmdline, "%s %s", cmdline, argv[i]); + /*MessageBox(NULL, cmdline, cmdline, MB_OK);*/ + } + + if (std_err) { + hStderrTempFile = getTempFileHandle(); + if (hStderrTempFile == INVALID_HANDLE_VALUE) + { + fprintf(stderr, "Second CreateFile failed (%d)\n", GetLastError()); + return FALSE; + } + } + + if (std_out) { + hStdoutTempFile = getTempFileHandle(); + if (hStdoutTempFile == INVALID_HANDLE_VALUE) + { + fprintf(stderr, "Second CreateFile failed (%d)\n", GetLastError()); + return FALSE; + } + } + + /* Set the bInheritHandle flag so pipe handles are inherited. */ + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + + /* Get the handle to the current STDOUT and STDERR. */ + gw_spawn.hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + gw_spawn.hStderr = GetStdHandle(STD_ERROR_HANDLE); + + + /* Create a pipe for the child process's STDOUT. */ + if (!CreatePipe(&(gw_spawn.hChildStdoutRd), &(gw_spawn.hChildStdoutWr), &saAttr, 0)) + { + fprintf(stderr, "Stdout pipe creation failed\n"); + return FALSE; + } + + /* Ensure that the read handle to the child process's pipe for STDOUT is not inherited.*/ + SetHandleInformation(gw_spawn.hChildStdoutRd, HANDLE_FLAG_INHERIT, 0); + + + /* Create a pipe for the child process's STDERR. */ + if (!CreatePipe(&(gw_spawn.hChildStderrRd), &(gw_spawn.hChildStderrWr), &saAttr, 0)) + { + fprintf(stderr, "Stdout pipe creation failed\n"); + return FALSE; + } + + /* Ensure that the read handle to the child process's pipe for STDOUT is not inherited.*/ + SetHandleInformation(gw_spawn.hChildStderrRd, HANDLE_FLAG_INHERIT, 0); + + + /* Create a pipe for the child process's STDIN. */ + if (!CreatePipe(&(gw_spawn.hChildStdinRd), &(gw_spawn.hChildStdinWr), &saAttr, 0)) + { + fprintf(stderr, "Stdin pipe creation failed\n"); + return FALSE; + } + + /* Ensure that the write handle to the child process's pipe for STDIN is not inherited. */ + SetHandleInformation(gw_spawn.hChildStdinWr, HANDLE_FLAG_INHERIT, 0); + + + /* Now create the child process. */ + fSuccess = CreateChildProcess(&gw_spawn, cmdline, dir); + if (!fSuccess) + { + fprintf(stderr, "Create process failed with"); + return FALSE; + } + + /* Read from pipe that is the standard output for child process. */ + if (std_out) + { + ReadFromPipe(gw_spawn.hChildStdoutRd, gw_spawn.hChildStdoutWr, hStdoutTempFile); + GetContentFromHandle(hStdoutTempFile, &stdout_content); + *std_out = stdout_content; + } + + if (std_err) + { + ReadFromPipe(gw_spawn.hChildStderrRd, gw_spawn.hChildStderrWr, hStderrTempFile); + GetContentFromHandle(hStderrTempFile, &stderr_content); + *std_err = stderr_content; + } + + return TRUE; +} + +gboolean GetContentFromHandle(HANDLE hFile, gchar **content) +{ + DWORD filesize; + gchar * buffer; + DWORD dwRead; + + filesize = GetFileSize(hFile, NULL); + if (filesize<1) { + *content = NULL; + return TRUE; + } + + buffer = g_malloc(sizeof(gchar*) * (filesize+1)); + if (!buffer) + { + fprintf(stderr, "Alloc failed"); + return FALSE; + } + + SetFilePointer(hFile,0, NULL, FILE_BEGIN); + if( !ReadFile(hFile, buffer, filesize, &dwRead, + NULL) || dwRead == 0) + { + fprintf(stderr, "Cannot read tempfile"); + return FALSE; + } + + if (!CloseHandle (hFile)) + { + fprintf(stderr, "CloseHandle failed (%d)\n", GetLastError()); + g_free(buffer); + *content = NULL; + return FALSE; + } + *content = buffer; + return TRUE; +} + +gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, TCHAR *dir) +{ + PROCESS_INFORMATION piProcInfo; + STARTUPINFO siStartInfo; + BOOL bFuncRetn = FALSE; + + /* Set up members of the PROCESS_INFORMATION structure. */ + ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); + + /* Set up members of the STARTUPINFO structure.*/ + ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); + + siStartInfo.cb = sizeof(STARTUPINFO); + siStartInfo.hStdError = gw_spawn->hChildStderrWr; + siStartInfo.hStdOutput = gw_spawn->hChildStdoutWr; + siStartInfo.hStdInput = gw_spawn->hChildStdinRd; + siStartInfo.dwFlags |= STARTF_USESTDHANDLES; + + /* Create the child process. */ + bFuncRetn = CreateProcess(NULL, + szCmdline, /* command line */ + NULL, /* process security attributes */ + NULL, /* primary thread security attributes */ + TRUE, /* handles are inherited */ + CREATE_NO_WINDOW, /* creation flags */ + NULL, /* use parent's environment */ + dir, /* use parent's current directory */ + &siStartInfo, /* STARTUPINFO pointer */ + &piProcInfo); /* receives PROCESS_INFORMATION */ + + if (bFuncRetn == 0) + { + fprintf(stderr, "CreateProcess failed\n"); + return FALSE; + } + else + { + CloseHandle(piProcInfo.hProcess); + CloseHandle(piProcInfo.hThread); + return bFuncRetn; + } + return FALSE; +} + +VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile) +{ + DWORD dwRead, dwWritten; + CHAR chBuf[BUFSIZE]; + + /* Close the write end of the pipe before reading from the + read end of the pipe. */ + if (!CloseHandle(hWrite)) + { + fprintf(stderr, "Closing handle failed"); + return; + } + + /* Read output from the child process, and write to parent's STDOUT. */ + for (;;) + { + if( !ReadFile(hRead, chBuf, BUFSIZE, &dwRead, + NULL) || dwRead == 0) break; + + if (!WriteFile(hFile, chBuf, dwRead, &dwWritten, NULL)) + break; + } +} + + +HANDLE getTempFileHandle() +{ + /* Temp file */ + DWORD dwBufSize=BUFSIZE; + UINT uRetVal; + TCHAR szTempName[BUFSIZE]; + TCHAR lpPathBuffer[BUFSIZE]; + DWORD dwRetVal; + HANDLE hTempFile; + + /* Get the temp path. */ + dwRetVal = GetTempPath(dwBufSize, /* length of the buffer*/ + lpPathBuffer); /* buffer for path */ + + if (dwRetVal > dwBufSize || (dwRetVal == 0)) + { + fprintf(stderr, "GetTempPath failed (%d)\n", GetLastError()); + return NULL; + } + + /* Create a temporary file for STDOUT. */ + uRetVal = GetTempFileName(lpPathBuffer, /* directory for tmp files */ + TEXT("GEANY_VCDIFF_"), /* temp file name prefix */ + 0, /* create unique name */ + szTempName); /* buffer for name */ + if (uRetVal == 0) + { + fprintf(stderr, "GetTempFileName failed (%d)\n", GetLastError()); + return NULL; + } + + hTempFile = CreateFile((LPTSTR) szTempName, /* file name */ + GENERIC_READ | GENERIC_WRITE, /* open r-w */ + 0, /* do not share */ + NULL, /* default security */ + CREATE_ALWAYS, /* overwrite existing */ + FILE_ATTRIBUTE_NORMAL,/* normal file */ + NULL); /* no template */ + + if (hTempFile == INVALID_HANDLE_VALUE) + { + fprintf(stderr, "Second CreateFile failed (%d)\n", GetLastError()); + return NULL; + } + return hTempFile; +} #endif Index: src/win32.h =================================================================== --- src/win32.h (revision 2263) +++ src/win32.h (working copy) @@ -23,8 +23,6 @@ #ifdef G_OS_WIN32 - - void win32_show_pref_file_dialog(GtkEntry *item); gboolean win32_show_file_dialog(gboolean file_open, const gchar *initial_dir); @@ -61,4 +59,8 @@ gchar *win32_get_hostname(); +gboolean geany_w32_spawn_sync( const gchar *dir, const gchar **argv, + const gchar **env, GSpawnFlags flags, + gchar **std_out, gchar **std_err, gchar *exit_status); + #endif