/*=========================================================================== 
 Copyright (C) 1993-2009 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifer   PCO
.PURPOSE     Takes care of opening and closing graphics devices
.AUTHOR      R.M. van Hees IPG-ESO Garching
.KEYWORDS    High level plot interface
.LANGUAGE    C
.COMMENTS    holds PCOPEN and PCCLOS
.ENVIRONment MIDAS and AGL
             #include <agl.h> 		Prototypes for AGL application programs
             #include <osparms.h>       Symbols used by the OS interfaces
             #include <plot_def.h>	Symbols used by the PLT interfaces
             #include <midas_def.h>	Prototypes for MIDAS interfaces

.VERSION     1.0  23-Sep-1993  FORTRAN --> C         RvH

 090630		last modif
------------------------------------------------------------*/
/*
 * Define _POSIX_SOURCE to indicate
 * that this is a POSIX program
 */
#define  _POSIX_SOURCE 1

/*
 * definition of the used functions in this module
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <idinumd.h>
#include <midas_def.h>

/*
 * define some macros and constants
 */
#include <osparms.h>
#include <plot_def.h>

#undef  FATAL
#define FATAL           1                              /* error status FATAL */

#define MAXDEV		10	      /* maximum number of different devices */
#define MAXLEN		80		    /* maximum length of device name */

/* The routine PCOPEN makes use of several static functions. 
 * They are used according to the following scheme:
 *
 *           graphic display        PCOPEN         image display
 *                                    |
 *                                  PCDEV
 *                                    |
 *                           <-------- ---------->
 *                    GRPCLP                       DISCLP
 *                                                   |
 *                                                 WC2PIX
 *                                                   |
 *                                    |            GETFRAME
 *                                  PCSET
 *                                    |
 *                                  PCTSET
 *                                    |
 *                                  PCWND
 */
                                  
/*
 * definition of struct dev, containing device name and AGL ID-number
 */
struct dev 
   { 
   char name[21];
   int  id;
   };

/*

*/

/*++++++++++++++++++++++++++++
.IDENTifer   PCDEV
.PURPOSE     get logical device name for current graphics window
             on both workstations and terminals
     input:   char *kname:  type of device
    output:   char *lname:  logical name of device
.RETURNS     
.COMMENTS    The length of the file AGL3CONFIG:agldevs.dat, also 
             defines the number of supported graphics devices. 
             This number should consist with the number of devices 
             declared in the file PLTDEV.INC
             static function also defined in low level routine GETDEV
------------------------------*/
#ifdef __STDC__
      static int PCDEV( char *kname, char *lname )
#else
      static int PCDEV( kname, lname )
      char *kname, *lname;
#endif

{
int  fid, found;
char devnam[84], *strtest;   

char *pldev = "AGL3CONFIG:agldevs.dat",
     *err_opn = "*** FATAL: PCDEV, Cannot open file with device definitions";


/* get rid of trailing blanks */

(void) strtok( kname, " " );
CGN_LOWSTR( kname );


/* read from AGLDEVS.dat */

if ( (fid = CGN_OPEN( pldev, READ )) == -1 ) SCETER( 1, err_opn );


/* keyword conversion or user input conversion */

if ( strncmp( kname+1, "_", 1 ) == 0 )
   strtest = kname+2;                                      /*full device name*/
else
   strtest = kname;                                      /*normal device name*/

found = FALSE;
while ( ! found && ( osaread( fid, devnam, MAXLEN )) >= 0 )
      { if ( ! (*devnam == '#') ) 
           { if ( ! strncmp( devnam, "unknown", 7 ) )
                { (void) strcpy( lname, "unknown" );
                  found = TRUE;
                }
             else
                { (void) strtok( devnam, ":");
                  if ( strcmp( strtest, devnam ) == 0 )
                     { (void) strcpy( lname, strtest );
                       found = TRUE;
                     }
                }
           }
      }

(void) osaclose(fid); 

if ( found == FALSE ) 
   {
   SCTPUT( "*** FATAL: PCDEV, Cannot find device definition" );
   return FATAL;
   }
else
   return ERR_NORMAL;
}

/*

*/

/*+++++++++++++++++++++++++++++++
.IDENTifer   GRPCLP
.PURPOSE     find and write viewport CLIP values, on graphics display
     input:   int   plmode :  plot mode
              char  *device:  name of plotting device
    output:   float *clpl  :  clip limits
.COMMENTS    static function
-------------------------------*/
#ifdef __STDC__
      static void GRPCLP( int plmode, char *device, float *clpl )
#else
      static void GRPCLP( plmode, device, clpl )
      char  *device; 
      int   plmode;
      float *clpl; 
#endif
{
int    actvals, xy, qdszy[2], knul, unit ;

float  aspect, xmxcl, maxcl[PLDIM2], devmm[PLDIM2], dval[PLDIM2], 
       frmwc[PLDIM2], frmcl[PLDIM2], frmmm[PLDIM2], 
       offset[PLDIM2], offusr[PLDIM2], scale[PLDIM3],
       scusr[PLDIM2], wndl[4];

char   frame[5], cmnd[21], text[81], *offcoo[2], *scacoo[2],
       *errmmoff[PLDIM2], *errscoff[PLDIM2], *errnooff[PLDIM2], 
       *errmmsca[PLDIM2], *errscsca[PLDIM2], *errnosca[PLDIM2],
       *errsiz[PLDIM2]; 

char *errtrm   = "*** FATAL: (GRPCLP) terminal unknown to system", 
     *errmin   = "           smallest possible scale:%13.6g units/mm",
     *errlarge = "           largest possible size: %6.1f mm";

errmmoff[0] = "*** FATAL: maximum offset in x: %6.1f mm";
errmmoff[1] = "*** FATAL: maximum offset in y: %6.1f mm";
errscoff[0] = "*** FATAL: maximum offset in x: %6d screen pixels";
errscoff[1] = "*** FATAL: maximum offset in y: %6d screen pixels";
errnooff[0] = "*** FATAL: norm. offset in x must be between 0 and 1";
errnooff[1] = "*** FATAL: norm. offset in y must be between 0 and 1";

errmmsca[0] = "*** FATAL: maximum axis size in x: %6.1f mm";
errmmsca[1] = "*** FATAL: maximum axis size in y: %6.1f mm";
errscsca[0] = "*** FATAL: maximum axis size in x: %6d screen pixels";
errscsca[1] = "*** FATAL: maximum axis size in y: %6d screen pixels";
errnosca[0] = "*** FATAL: norm.axis size in x must be between 0 and 1";
errnosca[1] = "*** FATAL: norm.axis size in y must be between 0 and 1";

errsiz[0]   = "*** FATAL: plot too large in x direction";
errsiz[1]   = "*** FATAL: plot too large in y direction";

PCKRDR( "XWNDL", 4, &actvals, wndl );
frmwc[0] = (float) fabs( *(wndl+1) - *wndl );
PCKRDR( "YWNDL", 4, &actvals, wndl );
frmwc[1] = (float) fabs( *(wndl+1) - *wndl );

for ( xy = 0; xy < PLDIM2; xy++ ) offcoo[xy] = osmmget(5);
for ( xy = 0; xy < PLDIM2; xy++ ) scacoo[xy] = osmmget(5);

/* 
 * get terminal characteristics, if failed exit
 */
if ( ( AG_RGET( "ASPE", &aspect ) != 1 ) || ( AG_RGET( "DEVD", dval ) != 2 ) )
   SCETER( 1, errtrm );
for ( xy = 0; xy < PLDIM2; xy++ ) devmm[xy] = 10 * dval[xy];

/*
 * determine scaling parameters
 */
(void) SCKGETC( "MID$CMND", 1, 20, &actvals, cmnd );
if ( plmode != 2 || strncmp( QUAL, "AXES", 4 ) == 0 )
   { clpl[0] = 0.15;
     clpl[1] = 0.95;
     clpl[2] = 0.1;
     clpl[3] = 0.95;
   }
else                                                   /* plot mode equals 2 */
   { clpl[0] = 0.15;
     clpl[1] = 0.8;
     clpl[2] = 0.1;
     clpl[3] = 0.95;
   }

/*
 * read the x and Y coordinate unit for x and y offset
 */
PCKRDR( "XOFF", 1, &actvals, offusr );
PCKRDR( "YOFF", 1, &actvals, offusr+1 );
PCKRDC( "CXOF", 4, &actvals, offcoo[0] );
PCKRDC( "CYOF", 4, &actvals, offcoo[1] );
PCKRDR( "OFFS", 2, &actvals, offset );

for ( xy = 0; xy < PLDIM2; xy++ )
/*
 * set offset in mm
 */
   if ( strncmp( offcoo[xy], "MM", 2 ) == 0 ) 
       { offset[xy] = MYMAX( offusr[xy], offset[xy] );
         if ( offset[xy] + 999  > PLT_EPS )
            { if ( offset[xy] > devmm[xy] )
                 { (void) sprintf( text, errmmoff[xy], devmm[xy] );
                  SCETER( 3, text);
                 }
              else 
                 { if ( xy == FOR_X )
                      clpl[0] = offset[0] / devmm[0];
                   else
                      clpl[2] = offset[1] / devmm[1];
                 }
            }
       }
/*
 * set offset in screen coordinates
 */
   else if ( strncmp( offcoo[xy], "SC", 2 ) == 0 ) 
       { (void) SCKRDI( "IDIDEV", 32, 2, &actvals, qdszy, &unit, &knul);
         if ( offset[xy] > qdszy[xy] )
            { (void) sprintf( text, errscoff[xy], qdszy[xy] );
              SCETER( 3, text);
            }
         else 
            {
            if ( xy == FOR_X )
	        clpl[0] = offset[0]/qdszy[0];
             else
	        clpl[2] = offset[1]/qdszy[1];
	    }
       }
/*
 * set offset in normlized coordinates
 */
   else if ( strncmp( offcoo[xy], "NO", 2 ) == 0 )                      
       { if ( offset[xy] < 0.0 || offset[xy] > 1.0 )
            { (void) strcpy(text, errnooff[xy]);
              SCETER( 3, text);
            }
         else 
            { if ( xy == FOR_X )
                 clpl[0] = offset[0];
              else
   	         clpl[2] = offset[1];
            }
       }

/* 
 * else we assume mm offset
 */
   else

       { offset[xy] = MYMAX( offusr[xy], offset[xy] );
         if ( offset[xy] + 999  > PLT_EPS )
            { if ( offset[xy] > devmm[xy] )
                 { (void) sprintf( text, errmmoff[xy], devmm[xy] );
                  SCETER( 3, text);
                 }
              else 
                 { if ( xy == FOR_X )
                      clpl[0] = offset[0] / devmm[0];
                   else
                      clpl[2] = offset[1] / devmm[1];
                 }
            }
       }

/*
 * X and Y scaling and position:
 */
PCKRDC( "FRAME", 4, &actvals, frame );
PCKRDR( "XSCA", 1, &actvals, scusr );
PCKRDR( "YSCA", 1, &actvals, scusr+1 );
PCKRDC( "CXSC", 4, &actvals, scacoo[0] );
PCKRDC( "CYSC", 4, &actvals, scacoo[1] );
PCKRDR( "SCAL", 3, &actvals, scale );

for ( xy = 0; xy < PLDIM2; xy++ )
/* 
 * scale via command line or preset
 */
    {if ( fabs( scale[xy] ) > PLT_EPS )
         { if ( ( strncmp( scacoo[xy], "MM", 2 ) == 0 ) 
               || ( scale[xy] < 0.0 ) )     /* scale in mm. or in neg. numbers*/ 
             { if ( fabs(scale[xy]) > devmm[xy] )
                   { (void) sprintf( text, errmmsca[xy], devmm[xy] );
                   SCETER( 3, text);
                   }
                else
 		   frmmm[xy] = (float) fabs( scale[xy]);       /*viewport size*/
	     }

           else if ( strncmp( scacoo[xy], "SC", 2 ) == 0 )    /*screen. coord.*/
             { (void) SCKRDI( "IDIDEV", 32, 2, &actvals, qdszy, &unit, &knul);
               if ( scale[xy] > qdszy[xy] )
                   { (void) sprintf( text, errscsca[xy], qdszy[xy] );
                   SCETER( 3, text);
                   }
                else 
	           frmmm[xy] = scale[xy]/qdszy[xy]*devmm[xy];  /*viewport size*/
  
             }

          else if ( strncmp( scacoo[xy], "NO", 2 ) == 0  )        /*norm.coord*/       
             { if ( scale[xy] < 0.0 || scale[xy] > 1.0 )
                  { (void) strcpy(text, errnosca[xy]);
                   SCETER( 3, text);
                  }
               else 
                   frmmm[xy] = scale[xy]*devmm[xy];                           

             }

          else                                           /*scale in wo per mm*/
             frmmm[xy] = fabs( frmwc[xy]/scale[xy] );
			 

          frmcl[xy] = (float) fabs(frmmm[xy]/devmm[xy]);   
	 }

/* 
 *scale via PLRGRAP
 */
      else if ( fabs( scusr[xy]) > PLT_EPS )
         { if ( scusr[xy] < 0.0 )                               /*scale in mm*/
              frmmm[xy] = (float) fabs( scusr[xy] );          /*viewport size*/
           else
              frmmm[xy] = frmwc[xy] / scusr[xy];             /*scale in wo/mm*/
           frmcl[xy] = (float) fabs( frmmm[xy] / devmm[xy]); /*norm.view size*/
         }

      else                                      /*no scale given; use default*/
         { if ( xy == FOR_X )
              { if ( strncmp( frame, "SQ", 2 ) == 0 )
                   { xmxcl = clpl[1];
                     clpl[1] = clpl[0] + aspect* (clpl[3] - clpl[2]);
                     if ( clpl[1] > xmxcl )
                        { clpl[1] = xmxcl;
                          clpl[2] = clpl[3]-(clpl[1]-clpl[0])/aspect;
                        }
                   }
                frmcl[xy]  = clpl[1] - clpl[0];
                frmmm[xy]  = devmm[xy] * frmcl[xy];
              }
           else
              { frmcl[xy]  = clpl[3] - clpl[2];
                frmmm[xy]  = devmm[xy] * frmcl[xy];
              }
         }

      if ( xy == FOR_X )
         maxcl[xy] = clpl[1] - clpl[0];
      else
         maxcl[xy] = clpl[3] - clpl[2];

/*
 * check the size 
 */
      if ( frmcl[xy] > maxcl[xy]+0.01 && 
           strncmp( device, "VERSATEC", 8 ) != 0 )
         { if ( scale[xy] < 0.0 )
              (void) sprintf( text, errlarge, maxcl[xy] * devmm[xy] );
           else
              (void) sprintf( text, errmin, frmwc[xy]/( maxcl[xy] * devmm[xy]));
           SCTPUT( errsiz[xy] );
           SCETER( 1, text );
         }
      else                                                     /* size is ok */
         { if ( xy == FOR_X )
              clpl[1] = clpl[0] + frmcl[xy];
           else
              { if ( fabs( offset[1] + 999 ) > PLT_EPS )
                   clpl[3] = clpl[2] + frmcl[xy];
                else
                   clpl[2] = clpl[3] - frmcl[xy];
              }
          }
    }

for ( xy = 0; xy < PLDIM2; xy++ ) 
    scale[xy] = (float) fabs( frmwc[xy]/frmmm[xy]);

PCKWRR( "SCAL", 2, scale );                                     /*store scale*/
PCKWRR( "CLPL", 4, clpl );                                /*store clip values*/

for ( xy = 0; xy < PLDIM2; xy++ ) osmmfree(offcoo[xy]);
for ( xy = 0; xy < PLDIM2; xy++ ) osmmfree(scacoo[xy]);

return;
}

/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifer   GETFRAME
.PURPOSE     Get name of frame displayed on current active display channel
    output:    char *frame
.RETURNS     0 = o.k., else nothing loaded into channel
.COMMENTS    static function, also defined in PLOTAXES
------------------------------------------------------------*/
#ifdef __STDC__
      static int GETFRAME( char *frame )
#else
      static int GETFRAME( frame )
      char *frame;
#endif

{
int iav;


/* get the name of the frame loaded in the current image display */

(void) SCKGETC("IDIMEMC",1,80,&iav,frame);

if (truelen(frame) == 0) 
   return 1;
else
   return ERR_NORMAL;
}

/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifer   WC2PIX
.PURPOSE     converts world coordinates to screen pixels
     input:   float *wcpix:  pixel in world coordimates
    output:   float *scpix:  pixel in screen coordinates
.COMMENTS    static function
------------------------------------------------------------*/
#ifdef __STDC__
      static void WC2PIX( float *wcpix, float *scpix )
#else
      static void WC2PIX( wcpix, scpix )
      float *wcpix, *scpix;
#endif
{
int     iac, imf, knul, qdszy, dzmemi[13], unit;
float   cx, cy, imgpix[2];
double  start[2], step[2];
char    frame[82];

char *err_fram  = "*** FATAL: no frame loaded in the display channel";

/*
 * get the name of the loaded frame and it's characteristics
 */
if ( GETFRAME( frame ) != 0 ) SCETER( 1, err_fram );
(void) SCFOPN( frame, D_R4_FORMAT, 0, F_IMA_TYPE, &imf );
(void) SCDRDD( imf, "START", 1, PLDIM2, &iac, start, &unit, &knul );
(void) SCDRDD( imf, "STEP" , 1, PLDIM2, &iac, step , &unit, &knul );
(void) SCFCLO( imf );

/*
 * get display parameters
 */
(void) SCKRDI( "IDIMEMI", 1, 13, &iac, dzmemi, &unit, &knul);
(void) SCKRDI( "IDIDEV", 3, 1, &iac, &qdszy, &unit, &knul);

/*
 * calculate image pixel
 */
imgpix[0] = (float) ((wcpix[0] - start[0])/step[0] + 1);
imgpix[1] = (float) ((wcpix[1] - start[1])/step[1] + 1);

/*
 * take care of one real pixel + scaling
 */
if ( SCALX < 0 ) 
   cx = - (imgpix[0] - (float) SFPX ) * (float) SCALX;
else
   cx =   (imgpix[0] - (float) SFPX ) / (float) SCALX;
cx += SSPX;

if ( SCALY < 0 ) 
   cy = - (imgpix[1] - (float) SFPY ) * (float) SCALY;
else
   cy =   (imgpix[1] - (float) SFPY ) / (float) SCALY;
cy += SSPY;

scpix[0] = ( cx - SCROLX ) * ZOOMX;
scpix[1] = ( cy - SCROLY ) * ZOOMY + qdszy - 1;

return;
}

/*

*/

/*++++++++++++++++++++++++++++++
.IDENTifer   DISCLP
.PURPOSE     find and write viewport CLIP values, on image display
     output:  float *clpl  :  clip limits
.COMMENTS    static function
--------------------------------*/
#ifdef __STDC__
      static void DISCLP( float *clpl )
#else
      static void DISCLP( clpl )
      float *clpl;
#endif
{
int    actvals, imf, knul, unit, xy, scale[PLDIM2], scrpx[PLDIM2];

float  frmmm[PLDIM2], frmpx[PLDIM2], offmm[PLDIM2], wcpix1[PLDIM2],
       wndl[8], scpix1[PLDIM2], scpix2[PLDIM2], wcpix2[PLDIM2];
double step[2];
char   frame[82];

char   *err_fram  = "*** FATAL: no frame loaded in the display channel";

/*
 * get the name of the loaded frame and it's characteristics
 */
if ( GETFRAME( frame ) != 0 ) SCETER( 1, err_fram );
(void) SCFOPN( frame, D_R4_FORMAT, 0, F_IMA_TYPE, &imf );
(void) SCDRDD( imf, "STEP" , 1, PLDIM2, &actvals, step , &unit, &knul );
(void) SCFCLO( imf );

/*
 * get display parameters
 */
(void) SCKRDI( "IDIDEV", 2, 2, &actvals, scrpx, &unit, &knul);
(void) SCKRDI( "IDIMEMI", 8, 2, &actvals, scale, &unit, &knul);

/*
 * do pixel convertion
 */
PCKRDR( "XWNDL", 2, &actvals, wndl );
PCKRDR( "YWNDL", 2, &actvals, wndl+2 );
/*
wcpix1[0] = (float) (wndl[0] + step[0]/2.0);
wcpix1[1] = (float) (wndl[2] + step[1]/2.0);
wcpix2[0] = (float) (wndl[1] + step[0]/2.0);
wcpix2[1] = (float) (wndl[3] + step[1]/2.0);
*/

wcpix1[0] = (float) (wndl[0]);
wcpix1[1] = (float) (wndl[2]);
wcpix2[0] = (float) (wndl[1]);
wcpix2[1] = (float) (wndl[3]);

WC2PIX( wcpix1, scpix1 );
WC2PIX( wcpix2, scpix2 );

/*
 * make the box 1/2 pixel larger
 */
if (scale[0] < 0.0)
   {
   scpix1[0] -= 0.5 * scale[0];
   scpix2[0] -= 0.5 * scale[0];
   }
if (scale[1] < 0.0)
   { 
   scpix1[1] -= 0.5 * scale[1];
   scpix2[1] -= 0.5 * scale[1];
   }

/* 
 * get terminal characteristics
 */
for ( xy = 0; xy < PLDIM2; xy++ ) 
    { frmpx[xy] = (float) fabs((double)  scpix2[xy] - scpix1[xy] ) + 1;
      frmmm[xy] = frmpx[xy] / scrpx[xy];
      offmm[xy] = scpix1[xy] / scrpx[xy];
    }
/*
 * set the clip coordinates
 */
clpl[0] = MYMAX( offmm[0], 0.0 );
clpl[1] = MYMIN( offmm[0] + (float) fabs((double) frmmm[0] ), 1.0 );
clpl[2] = MYMAX( offmm[1], 0.0 );
clpl[3] = MYMIN( offmm[1] + (float) fabs((double) frmmm[1] ), 1.0 );

PCKWRR( "CLPL", 4, clpl );                               /*store clip values*/
}

/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifer   PCWND
.PURPOSE     Set the plot window in world coordinates
   input:     float *wcfram  plot window limits in world coordinated

.COMMENTS    static function, also defined as low level plot interface
------------------------------------------------------------*/
#ifdef __STDC__
      static void PCWND( float *wcfram )
#else
      static void PCWND( wcfram )
      float *wcfram;
#endif
{
float  wndl[4];

/*
 * copy input array because we are going to change it
 */
wndl[0] = wcfram[0];
wndl[1] = wcfram[1];
wndl[2] = wcfram[4];
wndl[3] = wcfram[5];

/*
 * set the window
 */
if ( wcfram[3] <= -2.0 )                                /* logarithmic x-axis*/
   { wndl[0] = exp( wcfram[0] );
     wndl[1] = exp( wcfram[1] );
   }
else if ( wcfram[3] < 0.0 )
   { wndl[0] = pow( 10.0, wcfram[0] );
     wndl[1] = pow( 10.0, wcfram[1] );
   }

if ( wcfram[7] <= -2.0 )                                /* logarithmic y-axis*/
   { wndl[2] = exp( wcfram[4] );
     wndl[3] = exp( wcfram[5] );
   }
else if ( wcfram[7] < 0.0 )
   { wndl[2] = pow( 10.0, wcfram[4] );
     wndl[3] = pow( 10.0, wcfram[5] );
   }
/* 
 *define window
 */
AG_WDEF( wndl[0], wndl[1], wndl[2], wndl[3] );
AG_SSET( "liny" );
AG_SSET( "linx" );
if ( wcfram[3] < 0 ) AG_SSET( "logx" );
if ( wcfram[7] < 0 ) AG_SSET( "logy" );

return;
}

/*

*/

/*++++++++++++++++++++++++++++++
.IDENTifer   PCSET
.PURPOSE     does a complete setup of the plot parameters and AGL
.COMMENTS    static function
-------------------------------*/
#ifdef __STDC__
      static void PCSET( void )
#else
      static void PCSET()
#endif
{
int    actvals, color, font, ltype, lwidth, twidth, ncol;
float  wcfram[8];
char   clmod[5], text[81];

/*
 * set character font
 */
PCKRDI( "FONT", 1, &actvals, &font );
(void) sprintf( text, "font=%1d", font );
AG_SSET( text );

/* 
 * set line style
 */
PCKRDI( "LTYPE", 1, &actvals, &ltype );
if ( ltype > 0 )
   { (void) sprintf( text, "lstyl=%1d", ltype - 1 );
     AG_SSET( text );
   }
/*
 * set line width
 */
PCKRDI( "LWIDTH", 1, &actvals, &lwidth );
(void) sprintf( text, "lwidt=%1d", lwidth - 1 );
AG_SSET( text );

/*
 * set line width for text
 */
PCKRDI( "TWIDTH", 1, &actvals, &twidth );
(void) sprintf( text, "twidt=%1d", twidth );
AG_SSET( text );

/*
 * determine character and symbol sizes for the MIDAS layout
 */
PCTSET();

/*
 * set color
 */
(void) AG_IGET( "ncol", &ncol);
PCKRDI( "COLOR", 1, &actvals, &color );
if ( ncol == 1 && color > 1 ) color = 1;
(void) sprintf( text, "color=%1d", color );
AG_SSET( text );

/*
 * color mode
 */
PCKRDC( "COLMODE", 4, &actvals, clmod );
if ( strncmp( clmod, "X", 1 ) == 0 )
   AG_SSET( "mode=Xor" );
else
   AG_SSET( "mode=Sub" );
/*
 * do a complete "manual" setting, which gives a default frame!!
 */
PCKRDR( "XWNDL", 4, &actvals, wcfram );
PCKRDR( "YWNDL", 4, &actvals, wcfram+FOR_Y );
PCWND( wcfram );

return;
}

/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifier  PCOPEN
.PURPOSE     Sets up the graphic device according to plot mode
      input:  char *devnam:  name of device to be activated
              char *plname:  name of meta file
              int  access :  access mode: -1 = cursor,
                                           1 = over plot,
                                           0 = new plot.
  in/output:  int  *plmode: plot mode: 0 = no axis & no info,
                                       1 = draw axes & some info,
                                       2 = draw axes & full info, 
                                      -1 take value from keyword PMODE

.COMMENTS    PCOPEN activates a given device, or the current (by MIDAS) 
             defined device if no device name is given. A given device has
             to be present in the AGLDEVS.dat file.

             PCOPEN does not open or append to a meta file if PLNAME
             equals "NO"ne. If no name or a file name (without ".plt" 
             extention) is given PCOPEN will open or append to a meta file
             (see access mode). Default for the name of the meta file is 
             the name of the activated device extended with MIDAS session 
             number with extention ".plt".

             PCOPEN reads the MIDAS graphics keywords, opens this device
             (on graphics or image display) according to the MIDAS settings.
             The coordinate box have to be defined BEFORE PCOPEN !!! 
             Use the MIDAS routine PCKWRR, with parameters: XWNDL and YWNDL.
------------------------------------------------------------*/
void PCOPEN( devnam, plname, access, plmode )
char *devnam, *plname;
int  access, *plmode; 

{
int   actvals, amode, bcolor, iac, idev, meta, newdev, pmode;
float ocount, rdef, clpl[4];
char  *pntr, session[3], debug[5], erase[5], action[9], cmnd[21], 
      device[21], dname[21], plmeta[81], text[81];

static int    nrdev = 0;
static struct dev  devtbl[MAXDEV];
      
char *errpmode = "*** FATAL: PCOPEN, unknown plot mode ...",
     *errdev   = "*** FATAL: PCOPEN, unknown or unavailable device",
     *errhlp   = "                   use HELP [printers]",
     *errmxdev = "*** FATAL: PCOPEN, too many different devices opened (> 4)",
     *errplt   = "*** FATAL: PCOPEN, no graphics device ==> No CURSOR",
     *errnopl  = "*** FATAL: PCOPEN, no existing plot file to append",
     *errnoex  = "*** FATAL: PCOPEN, no existing plot for graphics cursor";
/*
 * initialize device and meta-file name
 */
*device = *plmeta = '\0';
(void) strncat( device, devnam, 20 );
(void) strncat( plmeta, plname, 80 );
(void) SCKGETC( "MID$SESS", 11, 2, &iac, session );
PCKRDR( "OCOUNT", 1, &actvals, &ocount );

/*
 * Check plot mode
 */
if ( *plmode == -1 )                             /* plmode = -1 => use PMODE */
   { PCKRDI( "PMODE", 1, &actvals, &pmode );
     *plmode = pmode;
   }
/*
 * and check its value
 */
if ( *plmode < 0 && *plmode > 2 ) SCETER( 2, errpmode );

/*
 * debug mode
 */
PCKRDC( "DEBUG", 4, &actvals, debug );
if ( strncmp( debug, "ON", 2 ) == 0 )
   AG_SSET( "msgw;debu=1;errf=aglerr.log" );
else
   AG_SSET( "msgn;debu=0" );

/*
 * get device name
 */
if ( truelen( device ) == 0 )                        /* a device name given? */
   (void) SCKGETC( "MID$PLOT", 1, 20, &iac, device );

if ( PCDEV( device, dname ) != ERR_NORMAL || 
     strncmp( dname, "unknown", 7 ) == 0 )
   { SCTPUT( errdev );
     SCETER( 3, errhlp );
   }

newdev = TRUE;
if ( nrdev == 0 )                               /* are there devices opened? */
   { nrdev = 1;
     idev = 0;
     (void) strcpy( devtbl[idev].name, dname );
   }
else
   { for ( idev = 0; idev < nrdev; idev++ )
         if ( strcmp( dname, devtbl[idev].name ) == 0 ) break;

     if ( idev == nrdev )                                        /*new device*/
        { if ( ++nrdev > MAXDEV ) SCETER( 4, errmxdev );
          (void) strcpy( devtbl[idev].name, dname );
        }
     else
        newdev = FALSE;
   }
/*
 * set the access mode according to plot, overplot and cursor command
 */
(void) SCKGETC( "MID$CMND", 1, 20, &iac, cmnd );
if ( access == -1 )                              /*reserved for cursor*/
   { if ( strncmp( dname,"graph",5 ) != 0 && strncmp( dname,"image",5 ) != 0 )
        SCETER( 4, errplt );
     amode = -1;
   }
else if ( access == 1 )                                    /*overplot command*/
   { if ( strncmp( QUAL, "AX", 2 ) == 0 )                              /*axes*/
        amode = 2;
     else if ( strncmp( COMM, "LAB", 3 ) == 0 )              /*label graphics*/
        amode = 3;
     else                                                              /*data*/
        amode = 4;
   }
else                                                           /*plot command*/
   { PCKRDC( "CLEAR", 4, &actvals, erase );
     if ( strncmp( QUAL, "AX", 2 ) == 0 )                              /*axes*/
        { if ( strncmp( erase, "ON", 2 ) == 0 || ocount < 1)
             amode = 1;                                               /*erase*/
          else 
             amode = 2;                                            /*no erase*/
        }
     else                                                     /*data plotting*/
        { if ( strncmp( erase, "ON", 2 ) == 0 || ocount < 1)
             amode = 5;                                               /*erase*/
          else                                                     
             amode = 6;                                            /*no erase*/
        }
   }
/* 
 * get the plot file
 */
meta = FALSE;                                        /* default: no meta file*/
if ( amode > 0 )
   { if ( strncmp( plmeta, "no", 2 ) != 0 )
        { meta = TRUE;
          if ( amode == 1 || amode == 5 )                      /*new plotfile*/
             { if ( truelen( plmeta ) == 0 )            /*called with no name*/
                  { (void) strcpy( plmeta, dname );
                    if ( (pntr = strchr( plmeta, '.' )) == NULL )
                       (void) strcat( plmeta, session );
                    else
                       (void) strcpy( pntr, session );                       
                  }
               if ( (pntr = strchr( plmeta, '.' )) == NULL )
                  (void) strcat( plmeta, ".plt" );
               else
                  (void) strcpy( pntr, ".plt" );
               PCKWRC( "PLNAM", plmeta );
               ocount = 0.0;
             }
          else                                                /*overplot mode*/
             { PCKRDC( "PLNAM", 80, &actvals, plmeta );
               if ( ocount == 0.0 ) SCETER( 5, errnopl );
             }
        }
   }
/*
 * define default viewport setting
 */
clpl[0] = clpl[2] = 0.0;
clpl[1] = clpl[3] = 1.0;
/*
 * open viewport for device
 */
switch (amode)
   { case 1:                                     /*PLOT AXES*/
     case 5:                                     /*PLOT DATA erase*/
         (void) strcat( dname, ":" );
         break;
     case -1:                                    /*GET GCURSOR*/
         if ( ocount == 0.0 ) SCETER( 6, errnoex );           /*none existing*/
         PCKRDR( "CLPL", 4, &actvals, clpl );
     case 3:                                     /*LABEL GRAPH*/
         if ( ocount == 0.0 ) break;
     case 2:                                     /*OVER AXES*/
     case 4:                                     /*OVER DATA*/
     case 6:                                     /*PLOT DATA no-erase*/
         (void) strcat( dname, "/n:" );
         (void) strcat( plmeta, "/a" );
         break;
   }
if ( newdev ) 
    devtbl[idev].id = AG_VDEF( dname, 
                              clpl[0], clpl[1], clpl[2], clpl[3], 0., 0. );
else
   AG_VSEL( devtbl[idev].id );

if ( meta ) 
   { AG_MCLS();                            /* close the still open meta file */
     AG_MOPN( plmeta );                                    /* and open a new */
   }

if ( amode > 0 )
   { if ( amode == 3 || amode == 4 )
        PCKRDR( "CLPL", 4, &actvals, clpl );
     else
        { if ( ! newdev )
             { PCKWRR( "SCALES", 0, &rdef );
               PCKWRR( "OFFSET", 0, &rdef );
             }          
          (void) SCKGETC( "ACTION", 1, 4, &iac, action );
          if ( strncmp( action, "DISP", 4 ) == 0 )
             DISCLP( clpl );
          else
             GRPCLP( *plmode, device, clpl );
        }
     ocount += 1;
     PCKWRR( "OCOUNT", 1, &ocount );
   }
else
   PCKRDR( "CLPL", 4, &actvals, clpl );

AG_CDEF( clpl[0], clpl[1], clpl[2], clpl[3] );

if ( amode == 1 || amode == 5 )
   { PCKRDI( "BCOLOR", 1, &actvals, &bcolor );
     (void) sprintf( text, "back=%1d", bcolor );
     AG_SSET( text );
   }
PCSET();

return;
}

/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifer   PCCLOS
.PURPOSE     Close plot file, and terminate graphic operations
------------------------------------------------------------*/
void PCCLOS()
{
/*
 * terminate orderly the AGL operations
 */
AG_CLS();

return;
}

