// -*- C++ -*-
#ifdef GNUPLOT_ONLY_INCLUDES

#include <io.h>
#include <fcntl.h>
#include <windows.h> 
#include <malloc.h> // alloca()


#else

// the next is "stolen" from the popen implementation of Python
// my own try to write this didn't work, maybe the docs of MSDN
// are not specific enough

static FILE* 
win32_error(const char*, void *){
    return NULL;
}

static int
_PyPopenCreateProcess(char *cmdstring,
		      HANDLE hStdin,
		      HANDLE hStdout,
		      HANDLE hStderr)
{
    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
    char *s1,*s2, *s3 = " /c ";
    const char *szConsoleSpawn = "w9xpopen.exe \"";
    int i;
    int x;
 
    if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) {
	s1 = (char *)_alloca(i);
	if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
	    return x;
	if (GetVersion() < 0x80000000) {
	    /*
	     * NT/2000
	     */
	    x = i + strlen(s3) + strlen(cmdstring) + 1;
	    s2 = (char *)_alloca(x);
	    ZeroMemory(s2, x);
	    sprintf(s2, "%s%s%s", s1, s3, cmdstring);
	}
	else {
	    /*
	     * Oh gag, we're on Win9x. Use the workaround listed in
	     * KB: Q150956
	     */
	    char modulepath[256];
	    GetModuleFileName(NULL, modulepath, sizeof(modulepath));
	    for (i = x = 0; modulepath[i]; i++)
		if (modulepath[i] == '\\')
		    x = i+1;
	    modulepath[x] = '\0';
	    x = i + strlen(s3) + strlen(cmdstring) + 1 +
		strlen(modulepath) + 
		strlen(szConsoleSpawn) + 1;
	    s2 = (char *)_alloca(x);
	    ZeroMemory(s2, x);
	    sprintf(
		s2,
		"%s%s%s%s%s\"",
		modulepath,
		szConsoleSpawn,
		s1,
		s3,
		cmdstring);
	}
    }

    /* Could be an else here to try cmd.exe / command.com in the path
       Now we'll just error out.. */
    else
	return -1;
  
    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
    siStartInfo.cb = sizeof(STARTUPINFO);
    siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    siStartInfo.hStdInput = hStdin;
    siStartInfo.hStdOutput = hStdout;
    siStartInfo.hStdError = hStderr;
    siStartInfo.wShowWindow = SW_HIDE;

    if (CreateProcess(NULL,
		      s2,
		      NULL,
		      NULL,
		      TRUE,
		      CREATE_NEW_CONSOLE,
		      NULL,
		      NULL,
		      &siStartInfo,
		      &piProcInfo) ) {
	/* Close the handles now so anyone waiting is woken. */
	CloseHandle(piProcInfo.hProcess);
	CloseHandle(piProcInfo.hThread);
	return TRUE;
    }
    return FALSE;
}


static FILE* 
OpenPipe(char *cmdstring, int mode)
{
    HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
	hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup,
	hChildStderrRdDup; /* hChildStdoutWrDup; */
	  
    SECURITY_ATTRIBUTES saAttr;
    BOOL fSuccess;
    int fd1, fd2, fd3;
    FILE *f1, *f2, *f3;

    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;

    if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
	return win32_error("CreatePipe", NULL);

    /* Create new output read handle and the input write handle. Set
     * the inheritance properties to FALSE. Otherwise, the child inherits
     * the these handles; resulting in non-closeable handles to the pipes
     * being created. */
    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
			       GetCurrentProcess(), &hChildStdinWrDup, 0,
			       FALSE,
			       DUPLICATE_SAME_ACCESS);
    if (!fSuccess)
	return win32_error("DuplicateHandle", NULL);

    /* Close the inheritable version of ChildStdin
       that we're using. */
    CloseHandle(hChildStdinWr);

    if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
	return win32_error("CreatePipe", NULL);

    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
			       GetCurrentProcess(), &hChildStdoutRdDup, 0,
			       FALSE,
			       DUPLICATE_SAME_ACCESS);
    if (!fSuccess)
	return win32_error("DuplicateHandle", NULL);

    /* Close the inheritable version of ChildStdout
       that we're using. */
    CloseHandle(hChildStdoutRd);

    if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
	return win32_error("CreatePipe", NULL);
    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStderrRd,
			       GetCurrentProcess(), &hChildStderrRdDup, 0,
			       FALSE,
			       DUPLICATE_SAME_ACCESS);
    if (!fSuccess)
	return win32_error("DuplicateHandle", NULL);
    /* Close the inheritable version of ChildStdErr that we're using. */
    CloseHandle(hChildStderrRd);
		 	  
    /* Case for writing to child Stdin in text mode. */
    fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
    f1 = _fdopen(fd1, "w");
    /* We don't care about these pipes anymore, so close them. */
    CloseHandle(hChildStdoutRdDup);
    CloseHandle(hChildStderrRdDup);

/*
// Case for writing to child Stdin in binary mode.
fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
f1 = _fdopen(fd1, "wb");
// We don't care about these pipes anymore, so close them.
CloseHandle(hChildStdoutRdDup);
CloseHandle(hChildStderrRdDup);
*/	
	
    if (!_PyPopenCreateProcess(cmdstring,
			       hChildStdinRd,
			       hChildStdoutWr,
			       hChildStderrWr))
	return win32_error("CreateProcess", NULL);

    /* Child is launched. Close the parents copy of those pipe
     * handles that only the child should have open.  You need to
     * make sure that no handles to the write end of the output pipe
     * are maintained in this process or else the pipe will not close
     * when the child process exits and the ReadFile will hang. */

    if (!CloseHandle(hChildStdinRd))
	return win32_error("CloseHandle", NULL);
	  
    if (!CloseHandle(hChildStdoutWr))
	return win32_error("CloseHandle", NULL);
 
    if (!CloseHandle(hChildStderrWr))
	return win32_error("CloseHandle", NULL);

    return f1;
}

static FILE* OpenGnuplot(void){
    return OpenPipe("g:\\gp373w32\\pgnuplot.exe",_O_WRONLY | _O_TEXT);
}
static void CloseGnuplot(FILE* pipe){
    fclose(pipe);
}
#endif
