[BACK]Return to pgnuplot.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot / win

Annotation of OpenXM_contrib/gnuplot/win/pgnuplot.c, Revision 1.1

1.1     ! maekawa     1: /*
        !             2:  * pgnuplot.c -- pipe stdin to wgnuplot
        !             3:  *
        !             4:  * Version 0.3 -- 30 Jun 1999
        !             5:  *
        !             6:  * This program is based on pgnuplot.c Copyright (C) 1999 Hans-Bernhard Broeker
        !             7:  * with substantial modifications Copyright (C) 1999 Craig R. Schardt.
        !             8:  *
        !             9:  * The code is released to the public domain.
        !            10:  *
        !            11:  */
        !            12:
        !            13: /* Comments from original pgnuplot.c */
        !            14: /*
        !            15:  * pgnuplot.c -- 'Pipe to gnuplot'  Version 990608
        !            16:  *
        !            17:  * A small program, to be compiled as a Win32 console mode application.
        !            18:  * (NB: will not work on 16bit Windows, not even with Win32s installed).
        !            19:  *
        !            20:  * This program will accept commands on STDIN, and pipe them to an
        !            21:  * active (or newly created) wgnuplot text window. Command line options
        !            22:  * are passed on to wgnuplot.
        !            23:  *
        !            24:  * Effectively, this means `pgnuplot' is an almost complete substitute
        !            25:  * for `wgnuplot', on the command line, with the added benefit that it
        !            26:  * does accept commands from redirected stdin. (Being a Windows GUI
        !            27:  * application, `wgnuplot' itself cannot read stdin at all.)
        !            28:  *
        !            29:  * Copyright (C) 1999 by Hans-Bernhard Broeker
        !            30:  *                       (broeker@physik.rwth-aachen.de)
        !            31:  * This file is in the public domain. It might become part of a future
        !            32:  * distribution of gnuplot.
        !            33:  *
        !            34:  * based on a program posted to comp.graphics.apps.gnuplot in May 1998 by
        !            35:  * jl Hamel <jlhamel@cea.fr>
        !            36:  *
        !            37:  * Changes relative to that original version:
        !            38:  * -- doesn't start a new wgnuplot if one already is running.
        !            39:  * -- doesn't end up in an endless loop if STDIN is not redirected.
        !            40:  *    (refuses to read from STDIN at all, in that case).
        !            41:  * -- doesn't stop the wgnuplot session at the end of
        !            42:  *    stdin, if it didn't start wgnuplot itself.
        !            43:  * -- avoids the usual buffer overrun problem with gets().
        !            44:  *
        !            45:  * For the record, I usually use MinGW32 to compile this, with a
        !            46:  * command line looking like this:
        !            47:  *
        !            48:  *     gcc -o pgnuplot.exe pgnuplot.c -luser32 -s
        !            49:  */
        !            50:
        !            51: /*     Modifications by Craig R. Schardt (17 Jun 1999)
        !            52:
        !            53:        Copyright (C) 1999 by Craig R. Schardt (craig@silica.mse.ufl.edu)
        !            54:
        !            55:        Major changes: (See the explanation below for more information)
        !            56:                + Always starts a new instance of wgnuplot.
        !            57:                + If stdin isn't redirected then start wgnuplot and give it focus.
        !            58:                + Uses CreateProcess() instead of WinExec() to start wgnuplot when stdin
        !            59:                  is redirected.
        !            60:
        !            61:        Other changes:
        !            62:                + New technique for building the command line to pass to wgnuplot.exe
        !            63:                  which is less complicated and seems to work more reliably than the old
        !            64:                  technique.
        !            65:                + Simplified message passing section of the code.
        !            66:                + All printf(...) statements are now fprintf(stderr,...) so that errors
        !            67:                  are sent to the console, even if stdout is redirected.
        !            68:
        !            69:        The previous version of pgnuplot would fail when more than one program
        !            70:        tried to access wgnuplot simultaneously or when one program tried to start
        !            71:        more than one wgnuplot session. Only a single instance of wgnuplot would be
        !            72:        started and all input would be sent to that instance. When two or more programs
        !            73:        tried to pipe input to wgnuplot, the two seperate input streams would be sent
        !            74:        to one wgnuplot window resulting in one very confused copy of wgnuplot. The only
        !            75:        way to avoid this problem was to change pgnuplot so that it would start a
        !            76:        new instance of wgnuplot every time.
        !            77:
        !            78:        Just starting a new instance of wgnuplot isn't enough. pgnuplot must also
        !            79:        make sure that the data on each stdin pipe is sent to the proper wgnuplot
        !            80:        instance. This is achieved by using CreateProcess() which returns a handle
        !            81:        to the newly created process. Once the process has initialized, it can be
        !            82:        searched for the text window and then data can be routed correctly. The search
        !            83:        is carried out by the EnumThreadWindows() call and the data passing is carried
        !            84:        out by a rewritten version of the original code. With these changes, pgnuplot
        !            85:        now behaves in a manner consistent with the behavior of gnuplot on UNIX
        !            86:        computers.
        !            87:
        !            88:        This program has been compiled using Microsoft Visual C++ 4.0 with the
        !            89:        following command line:
        !            90:
        !            91:                cl /O2 pgnuplot.c /link user32.lib
        !            92:
        !            93:        The resulting program has been tested on WinNT and Win98 both by calling
        !            94:        it directly from the command line with and without redirected input. The
        !            95:        program also works on WinNT with a modified version of Gnuplot.py (a script
        !            96:        for interactive control of Gnuplot from Python).
        !            97:
        !            98:        22 JUN 1999:
        !            99:        + Fixed command line code to behave properly when the first
        !           100:          item is quoted in the original command line.
        !           101:
        !           102:        29 JUN 1999:
        !           103:        + Added some code to print the command line. This is for testing
        !           104:          only and should be removed before the general release. To enable,
        !           105:          compile with SHOWCMDLINE defined.
        !           106:
        !           107:        30 JUN 1999:
        !           108:        + New function FindUnquotedSpace() which replaces the earlier technique for
        !           109:          finding the command line arguments to send on to wgnuplot. Prior to this
        !           110:          the arguments were assumed to start after argv[0], however argv[0] is not
        !           111:          set the same by all combinitaions of compiler, command processor, and OS.
        !           112:          The new method ignores argv completely and manually search the command line
        !           113:          string for the first space which isn't enclosed in double-quotes.
        !           114:
        !           115:   */
        !           116:
        !           117: #include <io.h>
        !           118: #include <conio.h>
        !           119: #include <fcntl.h>
        !           120: #include <stdio.h>
        !           121: #include <string.h>
        !           122: #include <stdlib.h>
        !           123: #include <windows.h>
        !           124:
        !           125: #ifndef _O_BINARY
        !           126: # define _O_BINARY O_BINARY
        !           127: #endif
        !           128: #if (__BORLANDC__ >= 0x450) /* about BCBuilder 1.0 */
        !           129: # define _setmode setmode
        !           130: #endif
        !           131:
        !           132: /* Customize this path if needed */
        !           133: #define PROGNAME "wgnuplot.exe"
        !           134: /* CRS: The value given above will work correctly as long as pgnuplot.exe
        !           135:  * is in the same directory as wgnuplot.exe or the directory containing
        !           136:  * wgnuplot.exe is included in the path. I would recommend placing the
        !           137:  * pgnuplot.exe executable in the same directory as wgnuplot.exe and
        !           138:  * leaving this definition alone.
        !           139:  */
        !           140:
        !           141: #define WINDOWNAME "gnuplot"
        !           142: #define PARENTCLASS "wgnuplot_parent"
        !           143: #define TEXTCLASS "wgnuplot_text"
        !           144: #define GRAPHWINDOW "gnuplot graph"
        !           145: #define GRAPHCLASS "wgnuplot_graph"
        !           146: #define BUFFER_SIZE 80
        !           147:
        !           148: /* GLOBAL Variables */
        !           149: HWND hwndParent = NULL;
        !           150: HWND hwndText = NULL;
        !           151:
        !           152: PROCESS_INFORMATION piProcInfo;
        !           153: STARTUPINFO         siStartInfo;
        !           154:
        !           155: /* CRS: Callback for the EnumThreadWindows function */
        !           156: BOOL CALLBACK cbGetTextWindow(HWND  hwnd, LPARAM  lParam )
        !           157: {
        !           158:        /* save the value of the parent window */
        !           159:        hwndParent = hwnd;
        !           160:        /* check to see if it has a child text window */
        !           161:        hwndText = FindWindowEx(hwnd, NULL, TEXTCLASS, NULL );
        !           162:
        !           163:        /* if the text window was found, stop looking */
        !           164:        return ( hwndText != NULL );
        !           165: }
        !           166:
        !           167: /* sends a string to the specified window */
        !           168: /* CRS: made this into a function call */
        !           169: void PostString(HWND hwnd, char *pc)
        !           170: {
        !           171:        while( *pc ){
        !           172:                PostMessage( hwnd, WM_CHAR, *pc, 1L );
        !           173:                /* CRS: should add a check of return code on PostMessage. If 0, the
        !           174:                   message que was full and the message wasn't posted. */
        !           175:                pc++;
        !           176:        }
        !           177: }
        !           178:
        !           179: /* FindUnquotedSpace(): Search a string for the first space not enclosed in quotes.
        !           180:  *   Returns a pointer to the space, or the empty string if no space is found.
        !           181:  *   -CRS 30061999
        !           182:  */
        !           183: char* FindUnquotedSpace( char *pc )
        !           184: {
        !           185:        while ( (*pc) && (*pc != ' ') && (*pc != '\t') ){
        !           186:                if ( *pc == '"' ){
        !           187:                        do {
        !           188:                                pc++;
        !           189:                        } while ( (pc[1]) && (*pc != '"') );
        !           190:                }
        !           191:                pc++;
        !           192:        }
        !           193:        return pc;
        !           194: }
        !           195:
        !           196: int main (int argc, char *argv[])
        !           197: {
        !           198:        char    psBuffer[BUFFER_SIZE];
        !           199:        char    psGnuplotCommandLine[MAX_PATH] = PROGNAME;
        !           200:        LPTSTR  psCmdLine;
        !           201:        BOOL    bSuccess;
        !           202:
        !           203:        /* HBB 19990325, to allow pgnuplot < script > output.gif */
        !           204:        _setmode(fileno(stdout), _O_BINARY);
        !           205:
        !           206:        /* CRS: create the new command line, passing all of the command
        !           207:         * line options to wgnuplot so that it can process them:
        !           208:         * first, get the command line,
        !           209:         * then move past the name of the program (e.g., 'pgnuplot'),
        !           210:         * finally, add what's left of the line onto the gnuplot command line. */
        !           211:        psCmdLine = GetCommandLine();
        !           212:
        !           213: #ifdef SHOWCMDLINE
        !           214:        fprintf(stderr,"CmdLine: %s\n", psCmdLine);
        !           215:        fprintf(stderr,"argv[0]: %s\n",argv[0]);
        !           216: #endif
        !           217:
        !           218:        /* CRS 30061999: Search for the first unquoted space. This should
        !           219:           separate the program name from the arguments. */
        !           220:        psCmdLine = FindUnquotedSpace( psCmdLine );
        !           221:
        !           222:        strncat(psGnuplotCommandLine, psCmdLine, MAX_PATH - strlen(psGnuplotCommandLine));
        !           223:
        !           224: #ifdef SHOWCMDLINE
        !           225:        fprintf(stderr,"Arguments: %s\n", psCmdLine);
        !           226:        fprintf(stderr,"GnuplotCommandLine: %s\n",psGnuplotCommandLine);
        !           227: #endif
        !           228:
        !           229:        /* CRS: if stdin isn't redirected then just launch wgnuplot normally
        !           230:         * and exit. */
        !           231:        if ( isatty(fileno(stdin)) ) {
        !           232:                if ( WinExec(psGnuplotCommandLine, SW_SHOWDEFAULT) > 31 ){
        !           233:                        exit(EXIT_SUCCESS);
        !           234:                }
        !           235:                fprintf(stderr,"ERROR %u: Couldn't execute: \"%s\"\n",
        !           236:                            GetLastError(), psGnuplotCommandLine);
        !           237:                exit(EXIT_FAILURE);
        !           238:        }
        !           239:
        !           240:        /* CRS: initialize the STARTUPINFO and call CreateProcess(). */
        !           241:        siStartInfo.cb = sizeof(STARTUPINFO);
        !           242:        siStartInfo.lpReserved = NULL;
        !           243:        siStartInfo.lpReserved2 = NULL;
        !           244:        siStartInfo.cbReserved2 = 0;
        !           245:        siStartInfo.lpDesktop = NULL;
        !           246:        siStartInfo.dwFlags = STARTF_USESHOWWINDOW;
        !           247:        siStartInfo.wShowWindow = SW_SHOWMINIMIZED;
        !           248:
        !           249:        bSuccess = CreateProcess(
        !           250:                        NULL,                   /* pointer to name of executable module   */
        !           251:                        psGnuplotCommandLine,   /* pointer to command line string         */
        !           252:                        NULL,                   /* pointer to process security attributes */
        !           253:                        NULL,                   /* pointer to thread security attributes  */
        !           254:                        FALSE,                  /* handle inheritance flag                */
        !           255:                        0,                      /* creation flags                         */
        !           256:                        NULL,                   /* pointer to new environment block       */
        !           257:                        NULL,                   /* pointer to current directory name      */
        !           258:                        &siStartInfo,           /* pointer to STARTUPINFO                 */
        !           259:                        &piProcInfo             /* pointer to PROCESS_INFORMATION         */
        !           260:                        );
        !           261:
        !           262:        /* if CreateProcess() failed, print a warning and exit. */
        !           263:        if ( ! bSuccess ) {
        !           264:                fprintf(stderr,"ERROR %u: Couldn't execute: \"%s\"\n",
        !           265:                                                GetLastError(), psGnuplotCommandLine);
        !           266:                exit(EXIT_FAILURE);
        !           267:        }
        !           268:
        !           269:        /* CRS: give gnuplot enough time to start (1 sec.) */
        !           270:        if ( WaitForInputIdle(piProcInfo.hProcess, 1000) ) {
        !           271:                fprintf(stderr, "Timeout: gnuplot is not ready\n");
        !           272:                exit(EXIT_FAILURE);
        !           273:        }
        !           274:
        !           275:        /* CRS: get the HWND of the parent window and text windows */
        !           276:        EnumThreadWindows(piProcInfo.dwThreadId, cbGetTextWindow, 0);
        !           277:
        !           278:        /* CRS: free the process and thread handles */
        !           279:        CloseHandle(piProcInfo.hProcess);
        !           280:        CloseHandle(piProcInfo.hThread);
        !           281:
        !           282:        if ( ! hwndParent || ! hwndText ) {
        !           283:        /* Still no gnuplot window? Problem! */
        !           284:                fprintf(stderr, "Can't find the gnuplot window");
        !           285:                exit(EXIT_FAILURE);
        !           286:        }
        !           287:
        !           288:        /* wait for commands on stdin, and pass them on to the wgnuplot text
        !           289:         * window */
        !           290:        while ( fgets(psBuffer, BUFFER_SIZE, stdin) != NULL ) {
        !           291:                PostString(hwndText, psBuffer);
        !           292:        }
        !           293:
        !           294:        /* exit gracefully */
        !           295:        /* CRS: Add a test to see if gnuplot is still running? */
        !           296:        PostString(hwndText, "\nexit\n");
        !           297:
        !           298:        return EXIT_SUCCESS;
        !           299: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>