Index: vcdiff.c =================================================================== --- vcdiff.c (revision 2263) +++ vcdiff.c (working copy) @@ -36,6 +36,30 @@ #include "project.h" #include "pluginmacros.h" +#ifdef G_OS_WIN32 +#include +#include + +#define BUFSIZE 4096 + +struct _geany_win32_spawn +{ + HANDLE hChildStdinRd; + HANDLE hChildStdinWr; + HANDLE hChildStdoutRd; + HANDLE hChildStdoutWr; + HANDLE hInputFile; + HANDLE hStdout; +}; +typedef struct _geany_win32_spawn geany_win32_spawn; + +gboolean geany_w32_spawn_sync(gchar *cmdline, gchar *dir, gchar **stdoutput); +BOOL CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline, TCHAR *dir); +VOID ReadFromPipe(geany_win32_spawn *gw_spawn, HANDLE hTempFile); +VOID ErrorExit(LPSTR); +#endif + + PluginFields *plugin_fields; GeanyData *geany_data; @@ -307,17 +331,24 @@ 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); +#ifdef G_OS_WIN32 + TCHAR buffer[MAX_PATH]=TEXT(""); + TCHAR cmdline[MAX_PATH] = TEXT(""); + TCHAR* lpPart[MAX_PATH]={NULL}; + DWORD retval=0; +#else + gint exit_code; +#endif + if (!argv) { if (env) @@ -334,6 +365,30 @@ dir = g_path_get_dirname(filename); } +#ifdef G_OS_WIN32 + retval = SearchPath(NULL, + argv[0], ".exe", MAX_PATH, buffer, lpPart); + + sprintf(cmdline,"\"%s\" %s %s", buffer, argv[1], argv[2]); + + if (geany_w32_spawn_sync(cmdline, dir, &std_output)) + { + p_dialogs->show_msgbox(1, "AFTER **********************\n%s.", std_output); + if (NZV(std_output)) + { + text = std_output; + } + else + { + p_ui->set_statusbar(FALSE, _("No changes were made.")); + } + } + else + { + p_ui->set_statusbar(FALSE, _("Something went really wrong.")); + } + +#else if (g_spawn_sync(dir, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL, &std_output, &std_error, &exit_code, NULL)) { // CVS dump stuff to stderr when diff nested dirs @@ -356,6 +411,7 @@ p_ui->set_statusbar(FALSE, _("Something went really wrong.")); } +#endif g_free(dir); g_free(std_error); g_strfreev(env); @@ -530,3 +586,214 @@ // remove the menu item added in init() gtk_widget_destroy(plugin_fields->menu_item); } + +#ifdef G_OS_WIN32 +gboolean geany_w32_spawn_sync(gchar *cmdline, gchar *dir, gchar **std_output) +{ + SECURITY_ATTRIBUTES saAttr; + BOOL fSuccess; + geany_win32_spawn gw_spawn; + + /* Temp file */ + DWORD dwBufSize=BUFSIZE; + UINT uRetVal; + TCHAR szTempName[BUFSIZE]; + TCHAR lpPathBuffer[BUFSIZE]; + DWORD dwRetVal; + HANDLE hTempFile; + DWORD output_size; + gchar *output_result = NULL; + + /* Get the temp path. */ + dwRetVal = GetTempPath(dwBufSize, /* length of the buffer*/ + lpPathBuffer); /* buffer for path */ + + if (dwRetVal > dwBufSize || (dwRetVal == 0)) + { + printf ("GetTempPath failed (%d)\n", GetLastError()); + return FALSE; + } + + /* Create a temporary file. */ + uRetVal = GetTempFileName(lpPathBuffer, /* directory for tmp files */ + TEXT("NEW"), /* temp file name prefix */ + 0, /* create unique name */ + szTempName); /* buffer for name */ + if (uRetVal == 0) + { + printf ("GetTempFileName failed (%d)\n", GetLastError()); + return FALSE; + } + + /* Create the new file to write the upper-case version to. */ + 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) + { + printf("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. */ + gw_spawn.hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + + /* Create a pipe for the child process's STDOUT. */ + if (! CreatePipe(&(gw_spawn.hChildStdoutRd), &(gw_spawn.hChildStdoutWr), &saAttr, 0)) + { + ErrorExit("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 STDIN. */ + if (! CreatePipe(&(gw_spawn.hChildStdinRd), &(gw_spawn.hChildStdinWr), &saAttr, 0)) + { + ErrorExit("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) + { + ErrorExit("Create process failed with"); + return FALSE; + } + + /* Read from pipe that is the standard output for child process. */ + ReadFromPipe(&gw_spawn, hTempFile); + + output_size = GetFileSize(hTempFile, NULL); + DWORD dwRead; + + output_result = g_malloc(sizeof(gchar*) * (output_size+1)); + if (!output_result) + { + ErrorExit("Alloc failed"); + return FALSE; + } + + SetFilePointer(hTempFile,0, NULL, FILE_BEGIN); + if( !ReadFile(hTempFile, output_result, output_size, &dwRead, + NULL) || dwRead == 0) + { + ErrorExit("Cannot read tempfile"); + return FALSE; + } + + fSuccess = CloseHandle (hTempFile); + + if (!fSuccess) + { + printf ("CloseHandle failed (%d)\n", GetLastError()); + return (8); + } + +#ifdef GW_WIN32_DEBUG + fSuccess = MoveFileEx(szTempName, + TEXT("c:\\geany_build\\out.txt"), + MOVEFILE_REPLACE_EXISTING); +#endif + + if (!fSuccess) + { + printf ("MoveFileEx failed (%d)\n", GetLastError()); + return FALSE; + } + *std_output = output_result; + 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->hChildStdoutWr; + 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) + { + ErrorExit("CreateProcess failed\n"); + return FALSE; + } + else + { + CloseHandle(piProcInfo.hProcess); + CloseHandle(piProcInfo.hThread); + return bFuncRetn; + } + return FALSE; +} + +VOID ReadFromPipe(geany_win32_spawn *gw_spawn, HANDLE hTempFile) +{ + DWORD dwRead, dwWritten; + CHAR chBuf[BUFSIZE]; + + /* Close the write end of the pipe before reading from the + read end of the pipe. */ + + if (!CloseHandle(gw_spawn->hChildStdoutWr)) + { + ErrorExit("Closing handle failed"); + return; + } + + /* Read output from the child process, and write to parent's STDOUT. */ + for (;;) + { + if( !ReadFile(gw_spawn->hChildStdoutRd, chBuf, BUFSIZE, &dwRead, + NULL) || dwRead == 0) break; + if (!WriteFile(hTempFile, chBuf, dwRead, &dwWritten, NULL)) + break; + } +#ifdef GW_WIN32_DEBUG + MessageBox(NULL, chBuf, "VCDiff Output", MB_ICONWARNING); +#endif +} + +VOID ErrorExit (LPSTR lpszMessage) +{ + p_dialogs->show_msgbox(1, _("%s."), lpszMessage); +} +#endif +