/*
 *    pm.trm  --- inboard terminal driver for Presentation Manager
 *            --- after X-11 driver, by R.W.Fearick 31/1/92.
 *    v1.1 11/8/92 -- speed things up        
 */



#ifndef GOT_DRIVER_H
#include "driver.h"
#endif

#ifdef TERM_REGISTER
register_term(pm)
#endif

#ifdef TERM_PROTO
TERM_PUBLIC void PM_init __P((void));
TERM_PUBLIC void PM_reset __P((void));
TERM_PUBLIC void PM_text __P((void));
TERM_PUBLIC void PM_graphics __P((void));
TERM_PUBLIC void PM_linetype __P((int lt));
TERM_PUBLIC void PM_move __P((unsigned int x,unsigned int y));
TERM_PUBLIC void PM_vector __P((unsigned int x,unsigned int y));
TERM_PUBLIC int  PM_text_angle __P((int ta));
TERM_PUBLIC void PM_put_text __P((unsigned int x,unsigned int y,char *str));
TERM_PUBLIC int  PM_justify_text __P((enum JUSTIFY mode));
TERM_PUBLIC void PM_point __P((unsigned int x, unsigned int y, int number));
TERM_PUBLIC void PM_suspend __P((void));
TERM_PUBLIC void PM_resume __P((void));

/* define PM world coordinate limits */
#define PM_XMAX 4096
#define PM_YMAX 4096

/* approximations for typical font/screen sizes */

#define PM_VCHAR (PM_YMAX/30) 
#define PM_HCHAR (PM_XMAX/80) 
#define PM_VTIC (PM_YMAX/100)
#define PM_HTIC (PM_XMAX/150)
#endif

#ifdef TERM_BODY

#include <stdio.h>
#include <process.h>
#include <io.h>


/* 
   include all stuff from os2.h as GNUPLOT uses INT as an enum and
   this clashes with #defines in os2.h 
*/

typedef unsigned short USHORT;
typedef USHORT *PUSHORT;
typedef void *PVOID ;
typedef char *PCHAR ;

typedef long LONG;
typedef LONG *PLONG;

typedef unsigned long ULONG;
typedef ULONG *PULONG;
typedef struct
{
  ULONG  tib2_ultid;
  ULONG  tib2_ulpri;
  ULONG  tib2_version;
  USHORT tib2_usMCCount;
  USHORT tib2_fMCForceFlag;
} TIB2;
typedef TIB2 *PTIB2;

typedef struct
{
  PVOID tib_pexchain;
  PVOID tib_pstack;
  PVOID tib_pstacklimit;
  PTIB2 tib_ptib2;
  ULONG tib_version;
  ULONG tib_ordinal;
} TIB;
typedef TIB *PTIB;

typedef struct
{
  ULONG pib_ulpid;
  ULONG pib_ulppid;
  ULONG pib_hmte;
  PCHAR pib_pchcmd;
  PCHAR pib_pchenv;
  ULONG pib_flstatus;
  ULONG pib_ultype;
} PIB;
typedef PIB *PPIB;
typedef ULONG HEV;
typedef HEV *PHEV;

ULONG DosCreateEventSem (const char *, PHEV, ULONG, ULONG);
ULONG DosWaitEventSem (HEV, ULONG);
ULONG DosGetInfoBlocks (PTIB *, PPIB *);
ULONG DosSearchPath( ULONG, char*, char*, char*, ULONG ) ;


/* graphics commands */
#define SET_GRAPHICS    'G'
#define SET_TEXT        'E'
#define SET_LINE        'L'
#define SET_ANGLE       'A'
#define SET_JUSTIFY     'J'
#define SET_POINTMODE   'D'
#define GR_SUSPEND      'E' /*'s'*/
#define GR_RESUME       'r'
#define GR_MOVE         'M'
#define GR_DRAW         'V'
#define GR_RESET        'R'
#define GR_TEXT         'T'
#define GR_PAUSE        'P'
#define GR_HELP         'H'
#define PM_nopts 1

static char PM_path[256] = "" ;  /* path for pm program */
static int  PM_mode      = 0 ;   /* track mode to avoid redraw after hitting break */
static     HEV hev ;

static char PM_opts[PM_nopts][20] = {
   " "
   };
static int PM_optarg[PM_nopts] = { 
   0
   };

FILE *fopen();
static FILE *PM_pipe=NULL;
#if 0
static char PM_command[1024]= "gnuplot_PM -name gnuplot";
#endif

int  PM_pause __P((char *str));
void PM_setup( void ) ;


TERM_PUBLIC void PM_init() 
    { 
    static char buffer[1024] ;
    int pid ;
    int rc ;
    PPIB pib ;
    PTIB tib ;
    char semname[32] ;
    char pipename[32] ;
    char tempname[32] ;
    if( PM_pipe == NULL ) {
        strcpy( tempname, "gpXXXXXX" ) ;
        if( mktemp( tempname ) == NULL ) {
            fprintf( stderr, "Temp name failure !\n" ) ;
            abort() ;   
            }
        strcpy( semname, "\\sem32\\" ) ;
        strcpy( pipename, "\\pipe\\" ) ;
        strcat( semname, tempname ) ;
        strcat( pipename, tempname ) ;
        strcat( PM_path, "\\gnupmdrv.exe" ) ;
        rc = access( PM_path, 0 ) ;
            /* find exe file */ 
  
        if( rc != 0 ) 
            rc = DosSearchPath( 0x0002, /* search GNUPLOT environment */
                                "GNUPLOT",
                                "gnupmdrv.exe",
                                PM_path,
                                256 ) ; 

        if( rc != 0 ) 
            rc = DosSearchPath( 0x0003,  /* then try current directory & path */
                                "PATH",
                                "gnupmdrv.exe",
                                PM_path,
                                256 ) ; 
        if( rc != 0 ) {
            fprintf( stderr, "Can't find gnupmdrv.exe !\n" ) ;
            abort() ;   
            }
                            
        rc = DosCreateEventSem( semname, &hev, 1, 0 ) ;
        if( rc != 0 ) {
            fprintf( stderr, "Can't create semaphore !\n" ) ;
            abort() ;   
            }
        pid=spawnl( P_SESSION|P_DEFAULT, PM_path, "GnuplotPM", tempname, NULL ) ;
      /*  pid=spawnl( P_SESSION|P_DEFAULT, "ipmd", "GnuplotPM", PM_path, tempname, NULL ) ;*/
        if( rc == -1 ) {
            fprintf( stderr, "Can't spawn gnupmdrv.exe !\n" ) ;
            abort() ;   
            }

        DosGetInfoBlocks( &tib, &pib ) ;
        DosWaitEventSem( hev, 10000 ) ;        
        PM_pipe = fopen( pipename, "r+b" ) ; 
        if( PM_pipe == NULL ) {
            fprintf( stderr, "Can't open pipe to gnupmdrv.exe !\n" ) ;
            abort() ;   
            }
        setvbuf( PM_pipe, buffer, _IOFBF, 1024 ) ;
        pid = pib->pib_ulpid ;
        fwrite( &pid, 1, 4, PM_pipe ) ;
        fflush( PM_pipe ) ;
        }
    }

TERM_PUBLIC void PM_reset() {
        putc( GR_RESET, PM_pipe); 
        fflush(PM_pipe);
        }

TERM_PUBLIC void PM_suspend() {
        putc( GR_SUSPEND, PM_pipe); 
        fflush(PM_pipe);
        }

TERM_PUBLIC void PM_resume() {
        putc( GR_RESUME, PM_pipe); 
        fflush(PM_pipe);
        }

TERM_PUBLIC void PM_text() 
    {
    fflush(PM_pipe);
    if( PM_mode != SET_TEXT ) { 
        putc( SET_TEXT, PM_pipe); 
        fflush(PM_pipe);
        }
    PM_mode = SET_TEXT ;
    }

TERM_PUBLIC void PM_graphics() 
    { 
    putc( SET_GRAPHICS, PM_pipe); 
    PM_mode = SET_GRAPHICS ;
    }

TERM_PUBLIC void PM_move(unsigned int x, unsigned int y) 
    { 
    putc( GR_MOVE, PM_pipe ) ;
    fwrite( &x, sizeof(int), 1, PM_pipe ) ;
    fwrite( &y, sizeof(int), 1, PM_pipe ) ;
    }

TERM_PUBLIC void PM_vector(unsigned int x, unsigned int y)
    { 
    putc( GR_DRAW, PM_pipe ) ;
    fwrite( &x, sizeof(int), 1, PM_pipe ) ;
    fwrite( &y, sizeof(int), 1, PM_pipe ) ;
    }

TERM_PUBLIC void PM_linetype(int lt)
    { 
    putc( SET_LINE, PM_pipe ) ;
    fwrite( &lt, sizeof(int), 1, PM_pipe ) ;
    }

TERM_PUBLIC int PM_text_angle( int ta)
    { 
    putc( SET_ANGLE, PM_pipe ) ;
    fwrite( &ta, sizeof(int), 1, PM_pipe ) ;
    return(TRUE) ; 
    }

TERM_PUBLIC void PM_put_text(unsigned int x, unsigned int y, char *str) 
    {
    int len ;
    putc( GR_TEXT, PM_pipe ) ;
    fwrite( &x, sizeof(int), 1, PM_pipe ) ;
    fwrite( &y, sizeof(int), 1, PM_pipe ) ;
    len = strlen( str ) + 1 ;
    fwrite( &len, sizeof(int), 1, PM_pipe ) ;
    fwrite( str, 1, len, PM_pipe ) ;
    for( len=sizeof(int)-len%sizeof(int); len > 0 ; len-- )  /* pad rest of int with zeros */
        putc( '\0', PM_pipe ) ;
    }

TERM_PUBLIC int PM_justify_text( enum JUSTIFY mode ) 
    {
    putc( SET_JUSTIFY, PM_pipe ) ;
    fwrite( &mode, sizeof(int), 1, PM_pipe ) ;
    return(TRUE);
    }

TERM_PUBLIC void PM_point( unsigned int x, unsigned int y, int number )
/*
** tell the driver we are plotting a point so it can decide whether to
** use colour or not
*/
    {
    int mode ;
    mode=1 ;
    putc( SET_POINTMODE, PM_pipe ) ;
    fwrite( &mode, sizeof(int), 1, PM_pipe ) ;
    do_point( x, y, number ) ;
    mode = 0 ;
    putc( SET_POINTMODE, PM_pipe ) ;
    fwrite( &mode, sizeof(int), 1, PM_pipe ) ;
    }

void PM_setup( void )
/*
** Initial terminal setup
*/
    {
    if( PM_path[0]=='\0' ) _getcwd2( PM_path, 256 ) ;
    }

int PM_pause( char *str )
/*
** pause - using message box on PM screen
*/
    {
    int len, cbR, rc ;
    unsigned long ul ;
    char buf[256] ;
    char *bp ;

    if( PM_pipe == NULL ) return 2 ;
    bp=buf ;
    putc( GR_PAUSE, PM_pipe ) ;
    len = strlen( str ) + 1 ;
    fwrite( &len, sizeof(int), 1, PM_pipe ) ;
    fwrite( str, 1, len, PM_pipe ) ;
    for( rc=sizeof(int)-len%sizeof(int); rc > 0 ; rc-- )  /* pad rest of int with zeros */
        putc( '\0', PM_pipe ) ;
    fflush(PM_pipe ) ;
    rc=DosRead( fileno(PM_pipe), &len, sizeof(int), &cbR ) ;
    return len ;
    }

#endif

#ifdef TERM_TABLE
TERM_TABLE_START(pm_driver)
    "pm", "OS/2 Presentation Manager", 
           PM_XMAX, PM_YMAX, PM_VCHAR, PM_HCHAR,
           PM_VTIC, PM_HTIC, options_null, PM_init, PM_reset,
           PM_text, null_scale, PM_graphics, PM_move, PM_vector,
           PM_linetype, PM_put_text, PM_text_angle,
           PM_justify_text, PM_point, do_arrow, set_font_null,
           null_set_pointsize, 0, PM_suspend, PM_resume
TERM_TABLE_END(pm_driver)

#undef LAST_TERM
#define LAST_TERM pm_driver
#endif

/*
 * NAME: pm
 *
 * OPTIONS: none 
 *
 * SUPPORTS: OS/2 Presentation Manager
 *
 * Further Info: none
 *
 * NOTE: Roger Fearick (the author of this file) and Stefan A. Deutscher
 *	 are both quite often seen at c.g.a.g and should know a lot
 *	 more about this terminal.
 */