/*===========================================================================
  Copyright (C) 1988-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
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE        Program
.NAME        idiserv
.LANGUAGE    C
.AUTHOR      K. Banse
             (very first version from M. Pucillo, Trieste Astronomical Obs.)
.CATEGORY    Image Display Interfaces. Workstation server
.COMMENTS
 The IDI workstation server allows application programs to
 access image display (virtual) devices without being concerned
 with their creation and maintenance.
 Errors are managed the same way as IDI errors.
.VERSION 
 871101:  definition - MPucillo - Trieste Astronomical Observatory
 881208:  rebuild on the basis of above - KB

 090903		last modif
------------------------------------------------------------*/ 

#include    <stdlib.h>
#include    <midas_def.h>
#include    <osyparms.h>
#include    <idi.h>
#include    <idifunct.h>
#include    <idistruct.h>
#include    <idiserver.h>
#include    <proto_idi.h>
#include    <proto_II.h>

extern int IISSIN_C();


static int     n_bytes = 0;      /* number of transmitted bytes  */
static int     func_code = 0;      /* function code                */

static unsigned char     *memdata;
static char    *memadr;

static char    datfilnam[MAXSTRLEN];
static char    *pipedir, unitnam[4], *charbuf, do_shad;

static  int    osxchan, curid;
static  int    fid, logid;
static int     np, outsize, paksize, mod4, pf;
static  int    shadow, paral, copyjob[MAX_DEV][MAX_DEV]; /* for shadow stuff */

static unsigned int   bytbuf;

/*

*/

int main(argc,argv)
int  argc;
char *argv[];

{
int    k, osxi, oldsxi, expo[2], mode, nmem, i;
int  servpid;
int  con_alw = 1, log_no = 0, dis_no = 0; 
static int osx_cod, first_bytes, jsecs, msecs;
/*
int  old_code = -99, ncount = -1, probid = -1, probcount;
*/

char   cbuf[4], record[84];
char   logfilnam[MAXSTRLEN];
char   *device;
static char    *servername[2] = { (char *)NULL, (char *)NULL };

void SetAutoCursor(), iismrmy(), iisdsnp();




SCSPRO("-1");
osscatch(SIGINT,SIG_IGN);	/* Ignore INT signals (Ctrl-C) */
SCECNT( "PUT", &con_alw, &log_no, &dis_no );

OSY_GETSYMB("DAZUNIT",unitnam,4);
unitnam[2] = '\0';

if (!(pipedir = getenv("MID_WORK")))
   { 
   (void) printf ("!! MID_WORK not defined !!\n");
   ospexit (1);
   }

for (i=0; i<MAX_DEV; i++) copyjob[i][0] = -1;

memset((char *)&serv_buf,0,sizeof(serv_buf));   /* init structures */
memset((char *)&serv_ret,0,sizeof(serv_ret));



/* create the file IDISERV in the very beginning  */

#ifndef pripri
(void) strcpy(datfilnam,pipedir);
(void) strcat(datfilnam,"IDISERV");
fid = osaopen(datfilnam,READ);
if (fid < 0)                            /* no file there yet */
   {
   fid = osaopen(datfilnam,WRITE);
   if (fid > 0)
      {
      cbuf[0] = unitnam[0];
      cbuf[1] = unitnam[1];
      cbuf[2] = '\0';
      np = osawrite(fid,cbuf,(int)strlen(cbuf));
      (void) osaclose(fid);
      }
   }
else                                    /* file IDISERV already there */
   (void) osaclose(fid);
#endif

#if vms
 jsecs = 0;
 msecs = 100;
 first_bytes = 4096;
 servername[0] = malloc((size_t)((int)strlen(unitnam)+(int)strlen("XW")+1));
 (void) sprintf(servername[0],"%s%s",unitnam,"XW");

#else
 first_bytes = BUFHEAD;
 jsecs = 1;
 msecs = 0;
 servername[0] = malloc((size_t)((int)strlen(pipedir)+(int)strlen("midas_xw")+
                        (int)strlen(unitnam)+1));
 (void) sprintf(servername[0],"%s%s%s",pipedir,"midas_xw",unitnam);
#endif 

oserror = 0;

/*  create new idiservXY.log file  */

(void) sprintf(logfilnam,"%s%s%s%s",pipedir,"idiserv",unitnam,".log");

logid = osaopen(logfilnam,WRITE);
if (logid > 0)
   {
#ifdef pripri
   (void) sprintf(record,"*** IDI Server %s in log mode *** ",servername[0]);
#else
   (void) sprintf(record,"*** IDI Server %s *** ",servername[0]);
#endif
   (void) osawrite(logid,record,(int)strlen(record));
   servpid = oshpid();			/* get pid of idiserver */
#if vms
   (void) sprintf(record,"%X",servpid);	/* we need pid in hexa ...  */
#else
   (void) sprintf(record,"%d",servpid);	/* and save it in idiserver.log  */
#endif
   (void) osawrite(logid,record,(int)strlen(record));
   (void) osaclose(logid);
   }


/* Open server channel for reading */

mode = LOCAL | IPC_READ;

osx_open:
if ((osxchan = osxopen(servername, mode)) == -1)
   {
   logid = osaopen(logfilnam,APPEND);
   if (logid > 0)
      {
      (void) sprintf(record,"idiserver,read channel: %s\n",servername[0]);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) sprintf(record,"error = %d",oserror);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) osaclose(logid);
      }
   else
      {
      (void) printf("idiserver,osxopen: %s\n",servername[0]);
      (void) printf("error = %d\n",oserror);
      }
   goto end_of_it;
   }
osxi = NOCONN;
expo[0] = -1;
expo[1] = -1;


/* we got the connection going, now only check, if we run in automatic
   cursor mode */

if (argc > 1) 
   SetAutoCursor(argv[1],pipedir);
else
   SetAutoCursor("N",pipedir);


/*  ---------------------  */
/*  here is the main loop  */
/*  ---------------------  */

/*
    for VMS we start a QIO without wait and check via the following osxinfo
    if the read finished and we got data 

    for Unix we check first via osxinfo if something is there and go into
    a read loop after that 
*/


osx_read:

do_shad = 'n';			/* default to NO shadowing */
paral = 0;			/* counter */
oserror = 0;

#if vms					/* VMS: QIO without wait */
osx_cod = osxread (osxchan,&serv_buf,first_bytes);
if (osx_cod != 0)
   {
   logid = osaopen(logfilnam,APPEND);
   if (logid > 0)
      {
      (void) sprintf(record,"idiserver,osxread: error = %d",oserror);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) sprintf(record,"retstat = %d, chan_id = %d, last command = %d\n",
              osx_cod,osxchan,func_code);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) osaclose(logid);
      }
   else
      {
      (void) printf
      ("osxread: error = %d, retstat = %d, chan_id = %d, last command = %d\n",
       oserror,osx_cod,osxchan,func_code);
      }
   (void) osxclose (osxchan);
   goto osx_open;
   }
#endif

osx_poll:

exposed(expo[0],expo[1]);		/* check for Expose events */

oldsxi = osxi;
osxi = osxinfo(osxchan,jsecs,msecs);	/* see, if something to read  (UNIX) */
if (osxi == NOCONN)			/* see, if read finished (VMS)       */
   {
#ifdef pripri
   if (oldsxi != osxi) printf("osxinfo: NOCONN\n");
#endif
   goto osx_poll;
   }
else if (osxi == NODATA)
   {
#ifdef pripri
   if (oldsxi != osxi) printf("osxinfo: NODATA\n");
#endif
   goto osx_poll;
   }
else 
   {
#ifdef pripri
   if (oldsxi != osxi) printf("osxinfo: DATARDY\n");
#endif
   }



/*  o.k., so read the stuff */

#if vms
#else
osx_cod = osxread (osxchan,(char *)&serv_buf,first_bytes);

if (osx_cod == -1)
   {
   logid = osaopen(logfilnam,APPEND);
   if (logid > 0)
      {
      sprintf(record,"idiserver,osxread: error = %d",oserror);
      osawrite(logid,record,(int)strlen(record));
      sprintf(record,"retstat = %d, chan_id = %d, last command = %d\n",
              osx_cod,osxchan,func_code);
      osawrite(logid,record,(int)strlen(record));
      osaclose(logid);
      }
   else
      {
      printf
      ("osxread: error = %d, retstat = %d, chan_id = %d, last command = %d\n",
       oserror,osx_cod,osxchan,func_code);
      }
   osxclose (osxchan);
   goto osx_open;
   }

if (osx_cod < first_bytes) goto osx_poll;
#endif
                                             /*   current_id =  buf.ident; */
func_code = serv_buf.code_id;
n_bytes = serv_buf.nobyt - BUFHEAD;    /*  get remaining bytes  */

/*
oooooooooooooooooooooo

if (ncount == -1)
   {
   probid = osaopen("IDI_problems",WRITE);
   probcount = 0;
   ncount = 0;
   old_code = serv_buf.code_id;
 
   OSY_ASCTIM(record);
   (void) strcat(record," - start of logging...");
   (void) osawrite(probid,record,(int)strlen(record));
   }
 
if (old_code != serv_buf.code_id)
   {
   if (ncount > 1)
      {
      sprintf(record,"code: %d * %d",old_code,ncount);
      printf("code: %d * %d\n",old_code,ncount);
      }
   else
      {
      sprintf(record,"code: %d",old_code);
      printf("code: %d \n",old_code);
      }
   (void) osawrite(probid,record,(int)strlen(record));
   probcount ++;
   if (probcount > 10)
      {
      (void) osaclose(probid);
      probid = osaopen("IDI_problems",APPEND);
      probcount = 0;
      }
 
   old_code = serv_buf.code_id;
   ncount = 1;
   }
else
   ncount++;
 
if (serv_buf.code_id == EXIT_CODE)
   {
   sprintf(record,"code: %d * %d",old_code,ncount);
   (void) osawrite(probid,record,(int)strlen(record));
   }

oooooooooooooooooooooo
*/


/* if EXIT, close output channel + die  */

if (serv_buf.code_id == EXIT_CODE)
   goto end_of_it;
              

/* here all other commands ... */
 
#if vms
#else
osx_cod = osxread(osxchan,(char *)&serv_buf.data,n_bytes);
if (osx_cod == -1)
   {
   logid = osaopen(logfilnam,APPEND);
   if (logid > 0)
      {
      (void) sprintf(record,"idiserver,osxread: error = %d",oserror);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) sprintf(record,"retstat = %d, chan_id = %d, last command = %d\n",
              osx_cod,osxchan,func_code);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) osaclose(logid);
      }
   else
      {
      (void) printf
      ("osxread: error = %d, retstat = %d, chan_id = %d, last command = %d\n",
       oserror,osx_cod,osxchan,func_code);
      }
   func_code = EXIT_CODE;        /* Error during osx read */
   goto end_of_it;
   }
#endif


   
if (serv_buf.code_id == DOPN_CODE) 				/* IIDOPN */
   {
   device = (char *) (&serv_buf.data.in[0]);
   serv_ret.code = IIDOPN_C (device , &serv_ret.data.in[0]);
   if ((serv_ret.code != ENTRYFND) && (serv_ret.code != II_SUCCESS))
      shadow = -1;
   else
      {
      i = serv_ret.data.in[0];			/* returned ididev id. */
      shadow = ididev[i].shadow[0];
      copyjob[i][0] = shadow;
      }
   k = 1;
   while (shadow != -1)
      {
      ididev[shadow].opened = 1;             /* open `shadow' the fast way */
      loc_zero(shadow);
      shadow = ididev[i].shadow[k];		/* get next candidate */
      copyjob[i][k++] = shadow;
      }
   paksize = RET_SIZE + 4;
   goto case_end;
   }
              
else if (serv_buf.code_id == DDEL_CODE)                          /* IIDDEL */
   {
   device = (char *) (&serv_buf.data.in[0]);
   serv_ret.code = IIDDEL_C(device,&serv_ret.data.in[0],&serv_ret.data.in[1],
                       &serv_ret.data.in[2]);
   paksize = RET_SIZE + 12;
   goto case_end;
   }
          
curid = serv_buf.data.in[0];			/* current display id */
shadow = copyjob[curid][0];		/* 1st element in copyjob[i] */


case_front:
paksize = RET_SIZE;

switch (serv_buf.code_id)
   {
   case MSMV_CODE : 				/* IIMSMV */
   do_shad = 'y';
   serv_ret.code = IIMSMV_C (serv_buf.data.in[0],&serv_buf.data.in[3],
                        serv_buf.data.in[1],serv_buf.data.in[2]);
   break;
              
   case ZWSC_CODE : 				/* IIZWSC */
   do_shad = 'y';
   serv_ret.code = IIZWSC_C (serv_buf.data.in[0],&serv_buf.data.in[4],
                            serv_buf.data.in[1],serv_buf.data.in[2],
                            serv_buf.data.in[3]);
   break;
              
   case ZRSZ_CODE : 				/* IIZRSZ */
   serv_ret.code = IIZRSZ_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             &serv_ret.data.in[0],&serv_ret.data.in[1],
                             &serv_ret.data.in[2]);
   paksize += 12;
   break;
              
   case ZWSZ_CODE : 				/* IIZWSZ */
   do_shad = 'y';
   serv_ret.code = IIZWSZ_C (serv_buf.data.in[0],serv_buf.data.in[1],
			     serv_buf.data.in[2],serv_buf.data.in[3],
			     serv_buf.data.in[4]);
   break;
              
   case DSDP_CODE : 				/* IIDSDP */
   nmem = serv_buf.data.in[1];
   serv_ret.code = IIDSDP_C (serv_buf.data.in[0],&serv_buf.data.in[2],
                             serv_buf.data.in[1],&serv_buf.data.in[2+nmem],
                             &serv_buf.data.in[2+2*nmem]);
   break;
              
   case MWMY_CODE :				/* IIMWMY */
   do_shad = 'y';
   serv_ret.code = IIMWMY_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             (unsigned char *) &serv_buf.data.in[7],
                             serv_buf.data.in[2],serv_buf.data.in[3] ,
                             serv_buf.data.in[4],serv_buf.data.in[5] ,
                             serv_buf.data.in[6]);
   break;
              
   case MCMY_CODE : 				/* IIMCMY */
   do_shad = 'y';
   serv_ret.code = IIMCMY_C (serv_buf.data.in[0],&serv_buf.data.in[3],
                             serv_buf.data.in[1],serv_buf.data.in[2]);
   break;
              
   case MCPV_CODE :                             /* IIMCPV */
   do_shad = 'y';
   serv_ret.code = IIMCPV_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             &serv_buf.data.in[2],
                             serv_buf.data.in[4],serv_buf.data.in[5],
                             &serv_buf.data.in[6],
                             &serv_buf.data.in[8],serv_buf.data.in[10]);
   break;

   case MRMY_CODE :				/* IIMRMY */
   iismrmy ();
 
   break;
              
   case MSTW_CODE : 				/* IIMSTW */
   do_shad = 'y';
   serv_ret.code = IIMSTW_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4],serv_buf.data.in[5],
                             serv_buf.data.in[6],serv_buf.data.in[7]);
   break;
              
   case GPLY_CODE :                          /* IIGPLY */
   do_shad = 'y';
   np = serv_buf.data.in[2];
   serv_ret.code = IIGPLY_C (serv_buf.data.in[0], serv_buf.data.in[1],
                             &serv_buf.data.in[5], &serv_buf.data.in[5+np], 
                             serv_buf.data.in[2], serv_buf.data.in[3],
                             serv_buf.data.in[4]);
   break;
              
   case GTXT_CODE : 				/* IIGTXT */
   do_shad = 'y';
   charbuf = (char *)(&serv_buf.data.in[8]);
   serv_ret.code = IIGTXT_C (serv_buf.data.in[0],serv_buf.data.in[1],charbuf,
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4],serv_buf.data.in[5],
                             serv_buf.data.in[6],serv_buf.data.in[7]);
   break;
              
   case GCPY_CODE : 				/* IIGCPY */
   do_shad = 'y';
   serv_ret.code = IIGCPY_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2]);
   break;
              
   case LWIT_CODE : 				/* IILWIT */
   do_shad = 'y';
   serv_ret.code = IILWIT_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4],&serv_buf.data.fl[5]);
   break;
              
   case LRIT_CODE : 				/* IILRIT */
   serv_ret.code = IILRIT_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4],&serv_ret.data.fl[0]);
   paksize += (serv_buf.data.in[4] * 4);
   break;
             
   case LWLT_CODE : 				/* IILWLT */
   do_shad = 'y';
   serv_ret.code = IILWLT_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             &serv_buf.data.fl[4]);
   break;
              
   case LRLT_CODE : 				/* IILRLT */
   serv_ret.code = IILRLT_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             &serv_ret.data.fl[0]);
   paksize += (3 * serv_buf.data.in[3] * 4);
   break;
              
   case CINC_CODE : 				/* IICINC */
   do_shad = 'y';
   serv_ret.code = IICINC_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4],serv_buf.data.in[5],
                             serv_buf.data.in[6]);
   break;
              
   case CSCV_CODE : 				/* IICSCV */
   do_shad = 'y';
   serv_ret.code = IICSCV_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2]);
   break;
              
   case CRCP_CODE : 				/* IICRCP */
   serv_ret.code = IICRCP_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],&serv_ret.data.in[0],
                             &serv_ret.data.in[1],&serv_ret.data.in[2]);
   paksize += 12;
   break;
              
   case CWCP_CODE : 				/* IICWCP */
   serv_ret.code = IICWCP_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4]);
   break;
              
   case RINR_CODE : 				/* IIRINR */
   do_shad = 'y';
   serv_ret.code = IIRINR_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4],serv_buf.data.in[5],
                             serv_buf.data.in[6],&serv_ret.data.in[0]);
   paksize += 4;
   break;
              
   case RRRI_CODE : 				/* IIRRRI */
   serv_ret.code = IIRRRI_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],&serv_ret.data.in[0],
                             &serv_ret.data.in[1],&serv_ret.data.in[2],
                             &serv_ret.data.in[3],&serv_ret.data.in[4]);
   paksize += 20;
   break;
              
   case RWRI_CODE : 				/* IIRWRI */
   serv_ret.code = IIRWRI_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4],serv_buf.data.in[5],
                             serv_buf.data.in[6]);
   break;
              
   case RSRV_CODE : 				/* IIRSRV */
   do_shad = 'y';
   serv_ret.code = IIRSRV_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2]);
   break;

   case CINR_CODE :                             /* IICINR */
   do_shad = 'y';
   serv_ret.code = IICINR_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],serv_buf.data.in[3],
                             serv_buf.data.in[4],serv_buf.data.in[5],
                             serv_buf.data.in[6],serv_buf.data.in[7],
                             &serv_ret.data.in[0]);
   paksize += 4;
   break;

   case CRRI_CODE :                             /* IICRRI */
   serv_ret.code = IICRRI_C (serv_buf.data.in[0],serv_buf.data.in[1],
			     serv_buf.data.in[2],&serv_ret.data.in[0],
			     &serv_ret.data.in[1],&serv_ret.data.in[2],
                             &serv_ret.data.in[3],&serv_ret.data.in[4],
			     &serv_ret.data.in[5]);
   paksize += 24;
   break;

   case CWRI_CODE :                             /* IICWRI */
   serv_ret.code = IICWRI_C (serv_buf.data.in[0],serv_buf.data.in[1],
			     serv_buf.data.in[2],serv_buf.data.in[3],
			     serv_buf.data.in[4],serv_buf.data.in[5],
                             serv_buf.data.in[6],serv_buf.data.in[7]);
   break;
              
   case IENI_CODE : 				/* IIIENI */
   serv_ret.code = IIIENI_C (serv_buf.data.in[0],serv_buf.data.in[1],
			     serv_buf.data.in[2],serv_buf.data.in[3],
			     serv_buf.data.in[4],serv_buf.data.in[5],
                             serv_buf.data.in[6]);
   break;
              
   case IEIW_CODE : 				/* IIIEIW */
   serv_ret.code = IIIEIW_C (serv_buf.data.in[0],&serv_ret.data.in[0]);
   paksize += (MAX_TRG * 4);
   break;
              
   case ISTI_CODE : 				/* IIISTI */
   serv_ret.code = IIISTI_C (serv_buf.data.in[0]);
   break;
              
   case IGSE_CODE : 				/* IIIGSE */
   charbuf = (char *)(&serv_ret.data.in[1]);
   serv_ret.code = IIIGSE_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             charbuf,&serv_ret.data.in[0]);
   paksize += (4 + 80);
   break;

   case IGCE_CODE : 				/* IIIGCE */
   charbuf = (char *)(&serv_ret.data.in[0]);
   serv_ret.code = IIIGCE_C (serv_buf.data.in[0],serv_buf.data.in[1],charbuf);
   paksize += 4;
   break;

   case IGLD_CODE : 				/* IIIGLD */
   serv_ret.code = IIIGLD_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             &serv_ret.data.in[0],&serv_ret.data.in[1]);
   paksize += 8;
   break;
              
   case DSNP_CODE :				/* IIDSNP */
   do_shad = 'y';
   iisdsnp();
   break;
              
   case MBLM_CODE : 				/* IIMBLM */
   do_shad = 'y';
   serv_ret.code = IIMBLM_C (serv_buf.data.in[0],&serv_buf.data.in[2],
                             serv_buf.data.in[1],&serv_buf.data.fl[20]);
   break;
              
   case LSBV_CODE : 				/* IILSBV */
   do_shad = 'y';
   serv_ret.code = IILSBV_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2]);
   break;
              
   case DCLO_CODE : 				/* IIDCLO */
   do_shad = 'y';
   serv_ret.code = IIDCLO_C (serv_buf.data.in[0]);
   break;
              
   case DRST_CODE : 				/* IIDRST */
   do_shad = 'y';
   serv_ret.code = IIDRST_C(serv_buf.data.in[0]);
   break;
              
   case DICO_CODE : 				/* IIDRST */
   do_shad = 'y';
   serv_ret.code = IIDICO_C(serv_buf.data.in[0],serv_buf.data.in[1]);
   break;
              
   case DQDV_CODE : 				/* IIDQDV */
   serv_ret.code = IIDQDV_C(serv_buf.data.in[0],&serv_ret.data.in[0],
			    &serv_ret.data.in[1],&serv_ret.data.in[2],
			    &serv_ret.data.in[3],&serv_ret.data.in[4],
                            &serv_ret.data.in[5],&serv_ret.data.in[6]);
   paksize += 28;
   break;
              
   case DQCI_CODE : 				/* IIDQCI */
   serv_ret.code = IIDQCI_C(serv_buf.data.in[0],serv_buf.data.in[1],
			    serv_buf.data.in[2],&serv_ret.data.in[1],
			    &serv_ret.data.in[0]);
   paksize += (4 + (4*serv_buf.data.in[2]));
   break;
              
   case DQCR_CODE : 				/* IIDQCR */
   serv_ret.code = IIDQCR_C (serv_buf.data.in[0],serv_buf.data.in[1],
			     serv_buf.data.in[2],&serv_ret.data.fl[1],
			     &serv_ret.data.in[0]);
   paksize += (4 + (4*serv_buf.data.in[2]));
   break;
              
   case DQDC_CODE : 				/* IIDQDC */
   nmem = serv_buf.data.in[3];
   serv_ret.code = IIDQDC_C (serv_buf.data.in[0],serv_buf.data.in[1],
			     serv_buf.data.in[2],serv_buf.data.in[3],
			     &serv_ret.data.in[0],&serv_ret.data.in[2],
                             &serv_ret.data.in[2+nmem],
			     &serv_ret.data.in[2+2*nmem],
                             &serv_ret.data.in[2+3*nmem],
			     &serv_ret.data.in[2+4*nmem],
                             &serv_ret.data.in[1]);
   paksize += (8 + (4 * nmem * 5));
   break;
              
   case EGDB_CODE : 				/* IIEGDB */
   serv_ret.code = IIEGDB_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],
                             (char *)(&serv_ret.data.in[0]),
                             &serv_ret.data.in[20],
			     (float *) &serv_ret.data.in[40]);
   paksize += (80 + (20 + 8)*4);
   break;

   case ESDB_CODE :                             /* IIESDB */
   serv_ret.code = IIESDB_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             serv_buf.data.in[2],
                             (char *)(&serv_buf.data.in[3]),
                             &serv_buf.data.in[23],
			     (float *) &serv_buf.data.in[40]);
   break;
              
   case ZWZM_CODE : 				/* IIZWZM */
   do_shad = 'y';
   serv_ret.code = IIZWZM_C (serv_buf.data.in[0],&serv_buf.data.in[3],
                             serv_buf.data.in[1],serv_buf.data.in[2]);
   break;
              
   case DSSS_CODE :				/* IIDSSS */
   do_shad = 'y';
   serv_ret.code = 0;
   break; 
        
   case MCPY_CODE : 				/* IIMCPY */
   do_shad = 'y';
   serv_ret.code = IIMCPY_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             &serv_buf.data.in[2],
                             serv_buf.data.in[4],serv_buf.data.in[5],
                             &serv_buf.data.in[6],
                             &serv_buf.data.in[8],serv_buf.data.in[10]);
   break;
              
              
   case XWIM_CODE :                             /* IIXWIM */
   do_shad = 'y';
   serv_ret.code = XWIMG(serv_buf.data.in[0],serv_buf.data.in[1],
                         (char *)(&serv_buf.data.in[2]),&serv_buf.data.in[25],
                         serv_buf.data.in[39],
                         &serv_buf.data.in[40],&serv_buf.data.in[42],
                         &serv_buf.data.fl[46],&serv_buf.data.in[48]);
   break;

   case SSIN_CODE :                             /* IISSIN */
   serv_ret.code = IISSIN_C (serv_buf.data.in[0],serv_buf.data.in[1],
                             (char *)(&serv_buf.data.in[2]));
   break;


   default        :               /* Error in code : close connection */
   logid = osaopen(logfilnam,APPEND);
   if (logid > 0)
      {
      (void) sprintf
             (record,"idiserver: invalid IDI code %d ...",serv_buf.code_id);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) osaclose(logid);
      }
   else
      (void) printf("invalid IDI code %d ...\n",serv_buf.code_id);
   goto end_of_it;
   }
 

/* if we have a shadow, do same operation again */

case_end:
if ((shadow != -1) && (do_shad == 'y'))
   {
   serv_buf.data.in[0] = shadow;
   shadow = copyjob[curid][++paral];
   goto case_front;
   }

osx_cod = osxwrite(osxchan,(char *)&serv_ret,paksize);
#if vms
if (osx_cod != 0)
#else
if (osx_cod == -1)
#endif
   {
   logid = osaopen(logfilnam,APPEND);
   if (logid > 0)
      {
      (void) sprintf(record,"idiserver,osxwrite: error = %d",oserror);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) sprintf(record,"retstat = %d, chan_id = %d, last command = %d\n",
              osx_cod,osxchan,func_code);
      (void) osawrite(logid,record,(int)strlen(record));
      (void) osaclose(logid);
      }
   else
      {
      (void) printf
      ("osxwrite: error = %d, retstat = %d, chan_id = %d, command = %d\n",
       oserror,osx_cod,osxchan,func_code);
       goto end_of_it;
      }
#ifdef vms
   goto end_of_it;
#endif
   }

goto osx_read;


end_of_it:
if (record_cursor_fid > 0) (void) osaclose(record_cursor_fid);
osxclose (osxchan);


/* delete file MID_WORK:IDISERV if we created it */

(void) strcpy(datfilnam,pipedir);
(void) strcat(datfilnam,"IDISERV");
fid = osaopen(datfilnam,READ);
if (fid > 0)                            /* no file there yet */
   {
   cbuf[0] = '\0';
   np = osaread(fid,cbuf,4);
   (void) osaclose(fid);
   if ((cbuf[0] == unitnam[0]) && (cbuf[1] == unitnam[1]))
      (void) osfdelete(datfilnam);
   }


return SCSEPI();

}

/*

*/

/* **************************************************************** */
/*                   here come the subroutines                      */
/* **************************************************************** */

void iismrmy ()
 
{
np = serv_buf.data.in[2];
pf = serv_buf.data.in[6];

mod4 = np % pf;				/* take care of packing */
if (mod4 == 0)
   outsize = np / pf;
else
   outsize = (np/pf) + 1;		/* outsize = no. of 4byte integers */

bytbuf = outsize * 4;			/* back to bytes */

if (outsize > MAXINTBUF)
   {
   memadr = osmmget(bytbuf);
   memdata = (unsigned char *) memadr;
   }
else
   memdata = (unsigned char *) &serv_ret.data.in[0];

serv_ret.code = IIMRMY_C (serv_buf.data.in[0], serv_buf.data.in[1],
                          serv_buf.data.in[2], serv_buf.data.in[3], 
                          serv_buf.data.in[4], serv_buf.data.in[5],
                          serv_buf.data.in[6], serv_buf.data.in[7],
                          memdata);


if (outsize > MAXINTBUF)
   {					/* build data file name */
   (void) sprintf(datfilnam,"%sx11%s.xmy",pipedir,unitnam);
   fid = osdopen(datfilnam,WRITE);
   if (fid < 0)
      {
      (void) printf ("No internal data file %s\n",datfilnam);
      return;
      }

   np = osdwrite(fid,memadr,bytbuf);
   if (np != bytbuf)
      {
      (void) printf ("Error writing file %s\n",datfilnam);
      osdclose(fid);
      free(memadr);
      return;
      }
   
   bytbuf = 0;
   np = osdclose(fid);
   if (np < 0)
      {
      (void) printf("problems in osdclose, oserror = %d\n",oserror);
      oserror = 0;
      }
   free(memadr);
   }

paksize = RET_SIZE + bytbuf;
}

/*

*/

/* **************************************************************** */

void iisdsnp ()
 
{
np = serv_buf.data.in[2];
pf = serv_buf.data.in[6];

mod4 = np % pf;				/* take care of packing */
if (mod4 == 0)
   outsize = np / pf;
else
   outsize = (np/pf) + 1;		/* outsize = no. of 4byte integers */

bytbuf = outsize * 4;			/* back to bytes */

if (outsize > MAXINTBUF)
   {
   memadr = osmmget(bytbuf);
   memdata = (unsigned char *) memadr;
   }
else
   memdata = (unsigned char *) &serv_ret.data.in[0];

serv_ret.code = IIDSNP_C(serv_buf.data.in[0],serv_buf.data.in[1],
                         serv_buf.data.in[2],serv_buf.data.in[3],
                         serv_buf.data.in[4],serv_buf.data.in[5],
                         serv_buf.data.in[6],memdata);


if (outsize > MAXINTBUF)
   {						/* build data file name */
   (void) sprintf(datfilnam,"%sx11%s.xmy",pipedir,unitnam); 
   fid = osdopen(datfilnam,WRITE);
   if (fid < 0)
      {
      (void) printf ("No internal data file %s\n",datfilnam);
      return;
      }

   np = osdwrite(fid,memadr,bytbuf);
   if (np != bytbuf)
      {
      (void) printf ("Error writing file %s\n",datfilnam);
      osdclose(fid);
      free(memadr);
      return;
      }
  
   bytbuf = 0;
   np = osdclose(fid);
   if (np < 0)
      {
      (void) printf("problems in osdclose, oserror = %d\n",oserror);
      oserror = 0;
      }
   free(memadr);
   }

paksize = RET_SIZE + bytbuf;
}

/*

*/

/* **************************************************************** */
/*                   set up things for Auto_Cursor                  */
/* **************************************************************** */

void SetAutoCursor(cc,midw)
char  *cc;			/* IN: AutoFlag, if = A we have automatic
					 cursor input from file 
					 $MID_WORK/cursor.automatic */
char  *midw;			/* IN: MID_WORK directory */

{
char  cursor_file[80];


auto_cursor_fid = -1;
record_cursor_fid = -1;

(void) strcpy(cursor_file,midw);
if (*cc == '1') 
   {
   (void) strcat(cursor_file,"/cursor.automatic");
   auto_cursor_fid = osaopen(cursor_file,READ);
   }

else if (*cc == '2') 
   {
   (void) strcat(cursor_file,"/cursor.recorded");
   record_cursor_fid = osaopen(cursor_file,WRITE);
   }
}

