/*-------------------------------------------------------------------------

                           N E X T R I C S
                           
   NeXus file writing for the four circle diffractometer TRICS at Sinq, PSI.
   
   This object uses the NXDICT-API. A further speciality is that objects
   which are constantly written are kept in  cache. This means, on 
   initialisation pointers to all relevant objects which have to be stored with
   a data frame are searched and kept in the objects data structure.
   
   copyright: see copyright.h
   
   Mark Koennecke, April 1998

   Revised: Mark Koennecke, October 2000
   Revised: Mark Koennecke, July 2001
----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "fortify.h"
#include "sics.h"
#include "sicsvar.h"
#include "motor.h"
#include "countdriv.h"
#include "counter.h"
#include "HistMem.h"
#include "danu.h"
#include "nxdict.h"
#include "nxutil.h"
#include "hkl.h"
#include "udpquieck.h"
#include "nextrics.h"
#include "nxscript.h"


#define DET1X 256  /* x -length of detector 1 */ 
#define DET1Y 128  /* y-length of detector 1 */
#define DET1XS -.78   /* pixel size in x of detector 1 */
#define DET1YS 1.486   /* pixel size in y of detector 1 */
#define DET1DESC "EMBL PSD"
#define DET2X 256 /* x -length of detector 1 */ 
#define DET2Y 128 /* y-length of detector 1 */
#define DET2XS -.78  /* pixel size in x of detector 1 */
#define DET2YS 1.486  /* pixel size in y of detector 1 */
#define DET2DESC "EMBL PSD"
#define DET3X 256  /* x -length of detector 1 */ 
#define DET3Y 128  /* y-length of detector 1 */
#define DET3XS -.78   /* pixel size in x of detector 1 */
#define DET3YS 1.486   /* pixel size in y of detector 1 */
#define DET3DESC "EMBL PSD"
#define DETAMAX 256 /* maximum length of pixelsize array */

/* histogram memory names */
#define HM1 "hm1"
#define HM2 "hm2"
#define HM3 "hm3"

/*
 offset variable names
*/
#define HM2OFF "hm2off"
#define HM3OFF "hm3off"
#define HM1OFF "hm1off"

/*
name of hkl object holding crystallographic information
*/
#define HKLNAME "hkl"

/*------------------------ the data structure ----------------------------*/
  typedef struct __NexTrics {
                              pObjectDescriptor pDes;
                              char *pCurrentFile;
                              char *pFileRoot;
                              pDataNumber pDanu;
                              NXdict pDict;
                              pHistMem pHistogram1, pHistogram2, pHistogram3;
                              int iFirst;
                              int iFrameNum;
                              pICallBack pCall;
                              float hm2Off, hm3Off, hm1off;
                              pHKL pCrystal;
                              int iHDF5;
                              pCounter pCount;
                            } NexTrics;

/* event type */
#define NEWFRAME 1166                              
/*----------------------------------------------------------------------*/
  pNexTrics CreateNexTrics(pDataNumber pNum, char *pRoot, char *pDict,
                           SicsInterp *pSics)
  {
    pNexTrics pNew = NULL;
    int iRet;
    CommandList *pCom = NULL;
    pSicsVariable pVar = NULL;
    
    /* allocate memory */
    pNew = (pNexTrics)malloc(sizeof(NexTrics));
    if(!pNew)
    {
      return NULL;
    }
    memset(pNew,0,sizeof(NexTrics));
    
    /* new object descriptor and callback interface */
    pNew->pDes = CreateDescriptor(HM1);
    pNew->pCall = CreateCallBackInterface();
    if(!pNew->pDes || !pNew->pCall)
    {
      free(pNew);
      return NULL;
    }    
    
    /* initialize dictionary */
    iRet = NXDinitfromfile(pDict,&pNew->pDict);
    if(iRet != NX_OK)
    {
       DeleteNexTrics(pNew);
       return NULL;
    }
    if(strstr(pDict,"5") != NULL)
    {
      pNew->iHDF5 = 1;
    }
    pNew->pFileRoot = strdup(pRoot);
    pNew->pDanu = pNum;
    
    /* find things in interpreter */
    pCom = FindCommand(pSics,HM1);
    if(pCom)
    {
       pNew->pHistogram1 = (pHistMem)pCom->pData;
    }
    else
    {
	pNew->pHistogram1 = NULL;
    }

    pCom = FindCommand(pSics,HM2);
    if(pCom)
    {
        pNew->pHistogram2 = (pHistMem)pCom->pData;
    }
    else
    {
        pNew->pHistogram2 = NULL;
    }
    pCom = FindCommand(pSics,HM3);
    if(pCom)
    {
        pNew->pHistogram3 = (pHistMem)pCom->pData;
    }
    else
    {
        pNew->pHistogram3 = NULL;
    }
    pCom = FindCommand(pSics,HKLNAME);
    if(pCom)
    {
      pNew->pCrystal = (pHKL)pCom->pData;
    }
    else
    {
      pNew->pCrystal = NULL;
    }
    pCom = FindCommand(pSics,"counter");
    if(pCom)
    {
      pNew->pCount = (pCounter)pCom->pData;
    }
    else
    {
      pNew->pCrystal = NULL;
    }
    pNew->iFirst = 1;
    pNew->iFrameNum = 0;
 
    pVar = FindVariable(pSics,HM1OFF);
    if(pVar)
    {
      pNew->hm1off = pVar->fVal;
    }
    else
    {
      pNew->hm1off = 0;
    }
    pVar = FindVariable(pSics,HM2OFF);
    if(pVar)
    {
      pNew->hm2Off = pVar->fVal;
    }
    else
    {
      pNew->hm2Off = +45.;
    }
    pVar = FindVariable(pSics,HM3OFF);
    if(pVar)
    {
      pNew->hm3Off = pVar->fVal;
    }
    else
    {
      pNew->hm3Off = 90.;
    }
    
    
    return pNew;
  }                         
/*-------------------------------------------------------------------------*/
  void DeleteNexTrics(void *pData)
  {
     pNexTrics self = NULL;
     
     self = (pNexTrics)pData;
     if(!self)
        return;
        
     if(self->pDes)
        DeleteDescriptor(self->pDes);
        
     if(self->pCurrentFile)
         free(self->pCurrentFile);
         
     if(self->pFileRoot)
         free(self->pFileRoot);
       
     if(self->pDict)
        NXDclose(self->pDict,NULL);

     if(self->pCall)
        DeleteCallBackInterface(self->pCall);
        
     free(self);                 
  }  
/*---------------------- a neXus error handler ---------------------------*/
  static void SNError(void *pData, char *text)
  {
     SConnection *pCon;
     
     assert(pData);
     pCon = (SConnection *)pData;
     SCWrite(pCon,text,eError);
  }
/*--------------------------------------------------------------------------*/
  int NexTricsFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
                      int argc, char *argv[])
  {
        pNexTrics pNew = NULL;
        pDataNumber pDanu = NULL;
        CommandList *pCom;
        char pBueffel[512];
        int iRet;
        pDummy pDum;
        
        if(argc < 4)
        {
           SCWrite(pCon,
               "ERROR: Insufficient number of arguments to NexTricsFactory",eError);
           return 0;    
        }
        
        /* first item must be the name of a datanumber variable */
        pCom = FindCommand(pSics,argv[1]);
        if(pCom)
        {
          pDanu = (pDataNumber)pCom->pData;
        }
        if( (!pCom) || (!pDanu))
        {
           SCWrite(pCon,"ERROR: DataNumber object NOT found",eError);
           return 0;
        }
        pDum = (pDummy)pDanu;
        if(strcmp(pDum->pDescriptor->name,"DataNumber") != 0)
        {
          sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[1]);
          SCWrite(pCon,pBueffel,eError);
          return 0;
        }
        
        /* install an error handler */
       NXMSetError((void *)pCon,SNError); 
    
       pNew = CreateNexTrics(pDanu,argv[2],argv[3],pSics);
       if(!pNew)
       {
         SCWrite(pCon,"ERROR: cannot create nexTrics, invalid dictionary file",eError);
         SCWrite(pCon,"ERROR:  or system objects missing.",eError);
         return 0;
       }      
       
       /* create the command */
       iRet = AddCommand(pSics,"nxtrics",NexTricsAction,DeleteNexTrics,
                         pNew);
       if(!iRet)
       {
          SCWrite(pCon,"ERROR: duplicate command nxtrics not created",eError);
       }                  
       return iRet;
  }
/*-------------------------------------------------------------------------*/
  static int DumpData(pNexTrics self, SConnection *pCon, NXhandle hfil, 
                      int iFrameNum)
  {
     int iRet;
     char pBueffel[512];
     CounterMode eMode;
     HistInt lData[DET1X*DET1Y], i, lVal;
     int iVal,lBeam;
     float fVal, fTTheta, fTime = 0.;
     pMotor pMot;

     /* write motors */
     SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
                  "framechi","CHI");     
     SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
                  "framephi","PHI");     
     SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
                  "frameomega","OM");     
     /* 
      read two theta
     */
      pMot = FindMotor(pServ->pSics,"stt");
      if(!pMot)
      {
        sprintf(pBueffel,"WARNING: cannot find motor stt");
        SCWrite(pCon,pBueffel,eWarning);
        return 0;
      }  
      
      /* get the position */
      iRet = MotorGetSoftPosition(pMot,pCon,&fTTheta);


     /* write frame time */
     SNXFormatTime(pBueffel,512);
     iRet = NXDputalias(hfil,self->pDict,"etime",pBueffel);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: cannot write frame time",eError);
     }
     
     /* write counting parameters */
     if(self->pHistogram1 != NULL)
     {
        eMode = GetHistCountMode(self->pHistogram1);
        fVal = GetHistPreset(self->pHistogram1);
        lVal = GetHistMonitor(self->pHistogram1,1,pCon);
        lBeam = GetHistMonitor(self->pHistogram1,4,pCon);
     }
     if(self->pHistogram2 != NULL)
     {
        eMode = GetHistCountMode(self->pHistogram2);
        fVal = GetHistPreset(self->pHistogram2);
        lVal = GetHistMonitor(self->pHistogram2,1,pCon);
        lBeam = GetHistMonitor(self->pHistogram2,4,pCon);
     }
     if(self->pHistogram3 != NULL)
     {
        eMode = GetHistCountMode(self->pHistogram3);
        fVal = GetHistPreset(self->pHistogram3);
        lVal = GetHistMonitor(self->pHistogram3,1,pCon);
        lBeam = GetHistMonitor(self->pHistogram3,4,pCon);
     }
     if(self->pCount != NULL)
     {
       eMode = GetCounterMode(self->pCount);
       fVal = GetCounterPreset(self->pCount);
       lVal = GetMonitor(self->pCount,1,pCon);
       fTime = GetCountTime(self->pCount,pCon);
       lBeam = GetMonitor(self->pCount,4,pCon);
     }
     if(eMode == eTimer)
     {
       strcpy(pBueffel,"Timer");
     }
     else
     {
       strcpy(pBueffel,"Monitor");
     }
     NXDputalias(hfil,self->pDict,"framemode",pBueffel);     
     NXDputalias(hfil,self->pDict,"framepreset",&fVal);
     iVal = (int)lVal;
     NXDputalias(hfil,self->pDict,"framemonitor",&iVal);
     iVal = (int)lBeam;
     NXDputalias(hfil,self->pDict,"sinqmonitor",&iVal);
     NXDputalias(hfil,self->pDict,"cctime",&fTime);
     
     /* write detector1 histogram */
     if(self->pHistogram1 != NULL)
     {
	 strcpy(pBueffel,"detector1");
	 NXDupdate(self->pDict,"dnumber",pBueffel);
	 SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
		      "frametilt","DG1");     
	 GetHistogram(self->pHistogram1,pCon,0,0,DET1X*DET1Y,lData,
		      DET1X*DET1Y*sizeof(HistInt));
	 NXDputalias(hfil,self->pDict,"framecounts",lData);

	 /*
	 NXDopenalias(hfil,self->pDict,"framecounts");
	 NXputdata(hfil,lData);
	 NXsetdimname(hfil,0,"frame_x");
	 NXsetdimname(hfil,1,"frame_y");
	 NXclosedata(hfil);
	 */

	 fVal = fTTheta + self->hm1off;
	 NXDputalias(hfil,self->pDict,"frame2theta",&fVal);

	 /* the NXdata links */
	 NXDaliaslink(hfil,self->pDict,"frame","detectorx");
	 NXDaliaslink(hfil,self->pDict,"frame","detectory");
	 NXDaliaslink(hfil,self->pDict,"frame","framecounts");
     }
     /*
       do detector 2 histogram
     */     
     if(self->pHistogram2 != NULL)
     {
	 strcpy(pBueffel,"detector2");
	 NXDupdate(self->pDict,"dnumber",pBueffel);
         SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
                  "frametilt","DG2");     
	 GetHistogram(self->pHistogram2,pCon,0,0,DET2X*DET2Y,lData,
		      DET2X*DET2Y*sizeof(HistInt));
	 NXDputalias(hfil,self->pDict,"framecounts",lData);

         /* code for reducing object number  in HDF-4
	 NXDopenalias(hfil,self->pDict,"framecounts");
	 NXputdata(hfil,lData);
	 NXsetdimname(hfil,0,"frame_x");
	 NXsetdimname(hfil,1,"frame_y");
	 NXclosedata(hfil);
         */

         fVal = fTTheta + self->hm2Off;
         NXDputalias(hfil,self->pDict,"frame2theta",&fVal);

	 /* the NXdata links */
	 NXDaliaslink(hfil,self->pDict,"frame","detectorx");
	 NXDaliaslink(hfil,self->pDict,"frame","detectory");
	 NXDaliaslink(hfil,self->pDict,"frame","framecounts");
     }
     /*
       do detector 3 histogram
     */     
     if(self->pHistogram3 != NULL)
     {
	 strcpy(pBueffel,"detector3");
	 NXDupdate(self->pDict,"dnumber",pBueffel);
         SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
                  "frametilt","DG3");     
	 GetHistogram(self->pHistogram3,pCon,0,0,DET3X*DET3Y,lData,
		      DET3X*DET3Y*sizeof(HistInt));

	 NXDputalias(hfil,self->pDict,"framecounts",lData);

         /* code for reducing object numbers in HDF-4
	 NXDopenalias(hfil,self->pDict,"framecounts");
	 NXputdata(hfil,lData);
	 NXsetdimname(hfil,0,"frame_x");
	 NXsetdimname(hfil,1,"frame_y");
	 NXclosedata(hfil);
         */


         fVal = fTTheta + self->hm3Off;
         NXDputalias(hfil,self->pDict,"frame2theta",&fVal);

	 /* the NXdata links */
	 NXDaliaslink(hfil,self->pDict,"frame","detectorx");
	 NXDaliaslink(hfil,self->pDict,"frame","detectory");
	 NXDaliaslink(hfil,self->pDict,"frame","framecounts");
     }


     /* temperature */
     SNXSPutEVVar(hfil,self->pDict,"temperature",
                  pCon,
                  "frametemp",
                  "framestdev");   
     
     /* close and done */
     sprintf(pBueffel,"Frame %d succesfully written",iFrameNum-1);
     SCWrite(pCon,pBueffel,eStatus);
     
     return 1;
 }
/*--------------------------------------------------------------------------*/
  static int  WriteFirstFrame(pNexTrics self, SConnection *pCon)
  {
     char pBueffel[1024];
     NXhandle hfil;
     int iRet, iYear, i;
     pSicsVariable pVar;
     char *pText;
     CommandList *pCom = NULL;
     pHKL pCryst = NULL;
     float fVal, fPix[DETAMAX];
     float fHKL[3], fUB[9];
     
     iRet = NXopen(self->pCurrentFile,NXACC_RDWR,&hfil);
     if(iRet != NX_OK)
     {
       sprintf(pBueffel,"ERROR: cannot open %s",self->pCurrentFile);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }       
  
     /* make sure: first frame */
     NXDupdate(self->pDict,"framename","frame0000");
     self->iFrameNum = 0;

     /* title */
     pVar = NULL;
     pVar = FindVariable(pServ->pSics,"title");
     if(pVar)
     {
        pText = pVar->text;
     }
     else
     {
        SCWrite(pCon,"ERROR: Variable title not found ",eError);
        pText = pBueffel;
     }
     iRet = NXDputalias(hfil,self->pDict,"etitle",pText);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write title",eError);
     }
     
     /* start time */
     SNXFormatTime(pBueffel,1023);
     iRet = NXDputalias(hfil,self->pDict,"etime",pBueffel);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write start time",eError);
     }
     
     /* source info */
     strcpy(pBueffel,"SINQ at Paul Scherrer Institut, Villigen");
     iRet = NXDputalias(hfil,self->pDict,"sname",pBueffel);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write source name",eError);
     }
     strcpy(pBueffel,"Spallation Neutron Source");
     iRet = NXDputalias(hfil,self->pDict,"stype",pBueffel);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write source type",eError);
     }
     
     /* instrument name */
     strcpy(pBueffel,"TRICS at SINQ, Paul Scherrer Institut, Switzerland"); 
     iRet = NXDputalias(hfil,self->pDict,"iname0",pBueffel);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write instrument name",eError);
     }

     /* Collimator */
     SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
                  "cex1","cex1");     
     SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
                  "cex2","cex2");     
     
     
     /* Monochromator */
     pVar = NULL;
     strcpy(pBueffel,"UNKNOWN");
     pVar = FindVariable(pServ->pSics,"monodescription");
     if(pVar)
     {
        pText = pVar->text;
     }
     else
     {
        SCWrite(pCon,"ERROR: Variable monodescription not found ",eError);
        pText = pBueffel;
     }
     iRet = NXDputalias(hfil,self->pDict,"monodes",pText);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write monodescription",eError);
     }

     /* lambda */
     if(self->pCrystal != NULL)
     {
        GetLambda(self->pCrystal,&fVal);
        iRet = NXDputalias(hfil,self->pDict,"monolambda",&fVal);
        if(iRet != NX_OK)
        {
             SCWrite(pCon,"ERROR: failed to write lambda",eError);
        }
     }
     
     /* two theta */
     pVar = NULL;
     strcpy(pBueffel,"UNKNOWN");
     pVar = FindVariable(pServ->pSics,"mono2theta");
     if(pVar)
     {
        fVal = pVar->fVal;
     }
     else
     {
        SCWrite(pCon,"ERROR: Variable mono2theta not found ",eError);
        fVal = -2188.99;
     }
     iRet = NXDputalias(hfil,self->pDict,"mono2theta",&fVal);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write monochromator 2 Theta",eError);
     }
     /* theta, needs work when lift operational */
     SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict,
                  "monotheta","MUCA");     
     
     
     /* detector data 
        first set detector variables in dictionary 
        This is the first detector. 
     */
     if(self->pHistogram1 != NULL)
     {
	strcpy(pBueffel,"detector1");
	NXDupdate(self->pDict,"dnumber",pBueffel);
	sprintf(pBueffel,"%d",DET1X);
	NXDupdate(self->pDict,"framedim1",pBueffel);
	sprintf(pBueffel,"%d",DET1Y);
	NXDupdate(self->pDict,"framedim2",pBueffel);
	strcpy(pBueffel,DET1DESC);
	iRet = NXDputalias(hfil,self->pDict,"ddescription",pBueffel);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write detector1 description",eError);
	}
	for(i = 0; i < DET1X; i++)
	{
	  fPix[i] = i * DET1XS;
	}
	iRet = NXDputalias(hfil,self->pDict,"detectorx",fPix);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write detector1 x-axis description",eError);
	}
	for(i = 0; i < DET1Y; i++)
	{
	  fPix[i] = i * DET1YS;
	}
	iRet = NXDputalias(hfil,self->pDict,"detectory",fPix);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write detector1 y-axis description",eError);
	}
	pVar = NULL;
	pVar = FindVariable(pServ->pSics,"det1zerox");
	if(pVar)
	{
	   fVal = pVar->fVal;
	}
	else
	{
	   SCWrite(pCon,"ERROR: Variable detector x zero point not found ",eError);
	   fVal = -2188.99;
	}
	iRet = NXDputalias(hfil,self->pDict,"detzerox",&fVal);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write detecor x zero point",eError);
	}
	pVar = NULL;
	pVar = FindVariable(pServ->pSics,"det1zeroy");
	if(pVar)
	{
	   fVal = pVar->fVal;
	}
	else
	{
	   SCWrite(pCon,"ERROR: Variable detector y zero point not found ",eError);
	   fVal = -2188.99;
	}
	iRet = NXDputalias(hfil,self->pDict,"detzeroy",&fVal);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write detecor y zero point",eError);
	}
	pVar = NULL;
	pVar = FindVariable(pServ->pSics,"detdist1");
	if(pVar)
	{
	   fVal = pVar->fVal;
	}
	else
	{
	   SCWrite(pCon,"ERROR: Variable detector distance not found ",eError);
	   fVal = -2188.99;
	}
	iRet = NXDputalias(hfil,self->pDict,"detdist",&fVal);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write detecor y zero point",eError);
	}
	iRet = 1;
	iRet = NXDputalias(hfil,self->pDict,"detvalid",&iRet);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write frame validity",eError);
	}
     }
     /* 
       second frame, but only if present
     */
     if(self->pHistogram2 != NULL)
     {
        strcpy(pBueffel,"detector2");
        NXDupdate(self->pDict,"dnumber",pBueffel);
        sprintf(pBueffel,"%d",DET2X);
        NXDupdate(self->pDict,"framedim1",pBueffel);
        sprintf(pBueffel,"%d",DET2Y);
        NXDupdate(self->pDict,"framedim2",pBueffel);
        strcpy(pBueffel,DET2DESC);
        iRet = NXDputalias(hfil,self->pDict,"ddescription",pBueffel);
        if(iRet != NX_OK)
        {
          SCWrite(pCon,"ERROR: failed to write detector2 description",eError);
        }
        for(i = 0; i < DET2X; i++)
        {
           fPix[i] = i * DET2XS;
        }
        iRet = NXDputalias(hfil,self->pDict,"detectorx",fPix);
        if(iRet != NX_OK)
        {
            SCWrite(pCon,"ERROR: failed to write detector2 x-axis description",
                          eError);
        }
        for(i = 0; i < DET2Y; i++)
        {
           fPix[i] = i * DET2YS;
        }
        iRet = NXDputalias(hfil,self->pDict,"detectory",fPix);
        if(iRet != NX_OK)
        {
           SCWrite(pCon,"ERROR: failed to write detector1 y-axis description",
                   eError);
        }
        pVar = NULL;
        pVar = FindVariable(pServ->pSics,"det2zerox");
        if(pVar)
        {
           fVal = pVar->fVal;
        }
        else
        {
             SCWrite(pCon,"ERROR: Variable detector x zero point not found ",
                    eError);
             fVal = -2188.99;
        }
        iRet = NXDputalias(hfil,self->pDict,"detzerox",&fVal);
        if(iRet != NX_OK)
        {
           SCWrite(pCon,"ERROR: failed to write detecor x zero point",
           eError);
        }
        pVar = NULL;
        pVar = FindVariable(pServ->pSics,"det2zeroy");
        if(pVar)
        {
            fVal = pVar->fVal;
        }
        else
        {
            SCWrite(pCon,"ERROR: Variable detector2 y zero point not found ",
                    eError);
            fVal = -2188.99;
         }
         iRet = NXDputalias(hfil,self->pDict,"detzeroy",&fVal);
         if(iRet != NX_OK)
         {
             SCWrite(pCon,"ERROR: failed to write detecor y zero point",
                     eError);
         }
         pVar = NULL;
         pVar = FindVariable(pServ->pSics,"detdist2");
         if(pVar)
         {
            fVal = pVar->fVal;
         }
         else
         {
            SCWrite(pCon,"ERROR: Variable detector distance not found ",
                    eError);
            fVal = -2188.99;
         }
         iRet = NXDputalias(hfil,self->pDict,"detdist",&fVal);
         if(iRet != NX_OK)
         {
             SCWrite(pCon,"ERROR: failed to write detecor2 y distance",
                     eError);
         }
         iRet = 1;
         iRet = NXDputalias(hfil,self->pDict,"detvalid",&iRet);
         if(iRet != NX_OK)
         {
            SCWrite(pCon,"ERROR: failed to write frame validity",eError);
         }
     }     
     /* 
       third detector, but only if present
     */
     if(self->pHistogram3 != NULL)
     {
        strcpy(pBueffel,"detector3");
        NXDupdate(self->pDict,"dnumber",pBueffel);
        sprintf(pBueffel,"%d",DET3X);
        NXDupdate(self->pDict,"framedim1",pBueffel);
        sprintf(pBueffel,"%d",DET3Y);
        NXDupdate(self->pDict,"framedim2",pBueffel);
        strcpy(pBueffel,DET3DESC);
        iRet = NXDputalias(hfil,self->pDict,"ddescription",pBueffel);
        if(iRet != NX_OK)
        {
          SCWrite(pCon,"ERROR: failed to write detector3 description",eError);
        }
        for(i = 0; i < DET3X; i++)
        {
           fPix[i] = i * DET3XS;
        }
        iRet = NXDputalias(hfil,self->pDict,"detectorx",fPix);
        if(iRet != NX_OK)
        {
            SCWrite(pCon,"ERROR: failed to write detector2 x-axis description",
                          eError);
        }
        for(i = 0; i < DET3Y; i++)
        {
           fPix[i] = i * DET3YS;
        }
        iRet = NXDputalias(hfil,self->pDict,"detectory",fPix);
        if(iRet != NX_OK)
        {
           SCWrite(pCon,"ERROR: failed to write detector1 y-axis description",
                   eError);
        }
        pVar = NULL;
        pVar = FindVariable(pServ->pSics,"det3zerox");
        if(pVar)
        {
           fVal = pVar->fVal;
        }
        else
        {
             SCWrite(pCon,"ERROR: Variable detector 3 x zero point not found ",
                    eError);
             fVal = -2188.99;
        }
        iRet = NXDputalias(hfil,self->pDict,"detzerox",&fVal);
        if(iRet != NX_OK)
        {
           SCWrite(pCon,"ERROR: failed to write detecor x zero point",
           eError);
        }
        pVar = NULL;
        pVar = FindVariable(pServ->pSics,"det3zeroy");
        if(pVar)
        {
            fVal = pVar->fVal;
        }
        else
        {
            SCWrite(pCon,"ERROR: Variable detector 3 y zero point not found ",
                    eError);
            fVal = -2188.99;
         }
         iRet = NXDputalias(hfil,self->pDict,"detzeroy",&fVal);
         if(iRet != NX_OK)
         {
             SCWrite(pCon,"ERROR: failed to write detecor y zero point",
                     eError);
         }
         pVar = NULL;
         pVar = FindVariable(pServ->pSics,"detdist3");
         if(pVar)
         {
            fVal = pVar->fVal;
         }
         else
         {
            SCWrite(pCon,"ERROR: Variable detector 3 distance not found ",
                    eError);
            fVal = -2188.99;
         }
         iRet = NXDputalias(hfil,self->pDict,"detdist",&fVal);
         if(iRet != NX_OK)
         {
             SCWrite(pCon,"ERROR: failed to write detecor 3 y distance",
                     eError);
         }
         iRet = 1;
         iRet = NXDputalias(hfil,self->pDict,"detvalid",&iRet);
         if(iRet != NX_OK)
         {
            SCWrite(pCon,"ERROR: failed to write frame validity",eError);
         }
     }     
     
     /* do sample information */
     strcpy(pBueffel,"UNKNOWN");
     pVar = FindVariable(pServ->pSics,"sample");
     if(pVar)
     {
        pText = pVar->text;
     }
     else
     {
        SCWrite(pCon,"ERROR: Variable sample not found ",eError);
        pText = pBueffel;
     }
     iRet = NXDputalias(hfil,self->pDict,"samplename",pText);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write sample name",eError);
     }
     if(self->pCrystal != NULL)
     {
       GetUB(self->pCrystal,fUB);
       iRet = NXDputalias(hfil,self->pDict,"sampleub",fUB);
       if(iRet != NX_OK)
       {
	 SCWrite(pCon,"ERROR: failed to write sample UB",eError);
       }
       GetCurrentHKL(self->pCrystal,fHKL);
       iRet = NXDputalias(hfil,self->pDict,"samplehkl",fHKL);
       if(iRet != NX_OK)
       {
	 SCWrite(pCon,"ERROR: failed to write HKL",eError);
       }
     }
   
     /* put the frame number */
     iRet = 0;
     iRet = NXDputalias(hfil,self->pDict,"fnum",&iRet);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write initial frame number",eError);
     }

     /* write actual data */
     iRet = DumpData(self,pCon,hfil,1);

     /* put the frame number */
     iRet = 1;
     iRet = NXDputalias(hfil,self->pDict,"fnum",&iRet);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: failed to write initial frame number",eError);
     }
     self->iFrameNum = 1;
     InvokeCallBack(self->pCall, NEWFRAME,&(self->iFrameNum));  
     
     self->iFirst = 0;
     
     /* close the file and go */
     NXclose(&hfil);
     SendQuieck(QUIECK,self->pCurrentFile);
     return iRet;
  }  
/*-------------------------------------------------------------------------*/
  static int ContinueFile(pNexTrics self, SConnection *pCon)
  {
     int iFrameNum, iRet;
     char pBueffel[1024];
     float fVal;
     NXhandle hfil;
     
     assert(self);
     assert(pCon);
     assert(self->iFirst == 0);
     
     /* let's start by opening the file*/
     iRet = NXopen(self->pCurrentFile,NXACC_RDWR,&hfil); 
     if(iRet != NX_OK)
     {
       sprintf(pBueffel,"ERROR: cannot reopen %s, NO data written",
               self->pCurrentFile);
       SCWrite(pCon,pBueffel,eError);  
       return 0;      
     }
     
     /* read the frame number, set the framename for further reading, 
        increment and write back again
     */
     iRet = NXDgetalias(hfil,self->pDict,"fnum",&iFrameNum);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"EERROR: cannot read old framenumber, NO data written",eError);
       return 0;
     }
     sprintf(pBueffel,"frame%4.4d", iFrameNum);
     NXDupdate(self->pDict,"framename",pBueffel);
     iFrameNum++;
     self->iFrameNum++;
     InvokeCallBack(self->pCall, NEWFRAME,&(self->iFrameNum));  
     iRet = NXDputalias(hfil,self->pDict,"fnum",&iFrameNum);
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"ERROR: cannot write new framenumber, NO data written",eError);
       return 0;
     }

     /* put in links to duplicates: entry */
     iRet = NXDaliaslink(hfil,self->pDict,"entry","etitle0");  
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"WARNING: cannot link against title",eWarning);
     }
     
     /* links to instrument */
     iRet = NXDaliaslink(hfil,self->pDict,"inst0","iname0");  
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"WARNING: cannot link against instrument name",eWarning);
     }
     iRet = NXDaliaslink(hfil,self->pDict,"inst0","source0");  
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"WARNING: cannot link against source group",eWarning);
     }
     iRet = NXDaliaslink(hfil,self->pDict,"inst0","mono0");  
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"WARNING: cannot link against monochromator group",
	       eWarning);
     }
     iRet = NXDaliaslink(hfil,self->pDict,"inst0","coll0");  
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"WARNING: cannot link against collimator group",
	       eWarning);
     }


     
     /*    
       links in detector group 
       detector 1
       */
     if(self->pHistogram1 != NULL)
     {
	strcpy(pBueffel,"detector1");
	NXDupdate(self->pDict,"dnumber",pBueffel);
	iRet = NXDaliaslink(hfil,self->pDict,"det1","ddescription");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector description",eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detectorx");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector x-axis",eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detectory");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector y-axis",eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detzerox");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector x zero ",eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detzeroy");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector y zero",eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detdist");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector distance",
                 eWarning);
	}
	iRet = 1;
	iRet = NXDputalias(hfil,self->pDict,"detvalid",&iRet);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write frame validity",eError);
	}
     }
     /*
      links in detector group, detector 2
     */
     if(self->pHistogram2)
     {
	strcpy(pBueffel,"detector2");
	NXDupdate(self->pDict,"dnumber",pBueffel);
	iRet = NXDaliaslink(hfil,self->pDict,"det1","ddescription");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector description",
                       eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detectorx");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector x-axis",
                  eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detectory");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector y-axis",
                  eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detzerox");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector x zero ",
                 eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detzeroy");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector y zero",
                  eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detdist");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector distance",
                  eWarning);
	}
	iRet = 1;
	iRet = NXDputalias(hfil,self->pDict,"detvalid",&iRet);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write frame validity",eError);
	}
     }     

     /*
      links in detector group, detector 3
     */
     if(self->pHistogram3)
     {
	strcpy(pBueffel,"detector3");
	NXDupdate(self->pDict,"dnumber",pBueffel);
	iRet = NXDaliaslink(hfil,self->pDict,"det1","ddescription");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector description",
                       eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detectorx");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector x-axis",
                  eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detectory");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector y-axis",
                  eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detzerox");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector x zero ",
                 eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detzeroy");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector y zero",
                  eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"det1","detdist");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against detector distance",
                  eWarning);
	}
	iRet = 1;
	iRet = NXDputalias(hfil,self->pDict,"detvalid",&iRet);
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"ERROR: failed to write frame validity",eError);
	}
     }     

     
     /* links in sample group */
     iRet = NXDaliaslink(hfil,self->pDict,"samplev","samplename");  
     if(iRet != NX_OK)
     {
       SCWrite(pCon,"WARNING: cannot link against sample name",eWarning);
     }
     if(self->pCrystal != NULL)
     {
	iRet = NXDaliaslink(hfil,self->pDict,"samplev","sampleub");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against sample UB",eWarning);
	}
	iRet = NXDaliaslink(hfil,self->pDict,"samplev","samplehkl");  
	if(iRet != NX_OK)
	{
	  SCWrite(pCon,"WARNING: cannot link against sample HKL",eWarning);
	}
     }
     
     /* write actual data */
     iRet = DumpData(self,pCon,hfil,iFrameNum);

     /* close the file and go */
     NXclose(&hfil);
     SendQuieck(QUIECK,self->pCurrentFile);
     return iRet;
  
  }
/*--------------------------------------------------------------------------*/
  int StartFile(pNexTrics self, SConnection *pCon)
  {
     char pBueffel[1024];
     NXhandle hfil;
     int iRet, iYear, i;
     pSicsVariable pVar;
     char *pText;
     CommandList *pCom = NULL;
     pHKL pCryst = NULL;
     float fVal, fPix[DETAMAX];
     
     /* make a filename and open it */
     if(self->pCurrentFile)
        free(self->pCurrentFile);
     
     pText = makeFilename(pServ->pSics,pCon);
     changeExtension(pText,"hdf");
     if(pText == NULL)
     {
       return 0;
     }
     self->pCurrentFile = strdup(pText);   
     if(self->iHDF5)
     {
       iRet = NXopen(self->pCurrentFile,NXACC_CREATE5,&hfil);
     }
     else
     {
       iRet = NXopen(self->pCurrentFile,NXACC_CREATE,&hfil);
     }
     if(iRet != NX_OK)
     {
       sprintf(pBueffel,"ERROR: cannot open %s",self->pCurrentFile);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }       
  
     /* tell user what we are doing */
     sprintf(pBueffel,"Initialising file %s ......", self->pCurrentFile);
     SCWrite(pCon,pBueffel,eWarning);
     
     
     /* Write header data */
     SNXSPutGlobals(hfil,self->pCurrentFile,
                    "TRICS at SinQ, Paul Scherrer Institut, Switzerland",
                    pCon);

     self->iFirst = 1;
     self->iFrameNum = 0;
     InvokeCallBack(self->pCall, NEWFRAME,&(self->iFrameNum));  
     
     /* close the file and go */
     NXclose(&hfil);
     return 1;
  }  
/*-------------------------------------------------------------------------*/
  int ReopenFile(pNexTrics self, char *filename)
  {
     char pBueffel[1024];
     NXhandle hfil;
     int iRet, iFrameNum;
     
     assert(self);
     
     /* concat with data root and check for existence */
     sprintf(pBueffel,"%s/%s",self->pFileRoot,filename);
     iRet = NXopen(pBueffel,NXACC_RDWR,&hfil);
     if(iRet != NX_OK)
     {
       return 0;
     }
     else
     {
       if(self->pCurrentFile)
            free(self->pCurrentFile);
       self->pCurrentFile = strdup(pBueffel);     
     }

     /* check the framenumber, if already data written */
     iRet = NXDgetalias(hfil,self->pDict,"fnum",&iFrameNum);
     if(iRet != NX_OK)
     {
       self->iFirst = 1;
     }
     else
     {
       self->iFirst = 0;
     }
     self->iFrameNum = iFrameNum;
     InvokeCallBack(self->pCall, NEWFRAME,&(self->iFrameNum));  
     return 1;
  }
/*--------------------------------------------------------------------------*/
  int DumpFrame(pNexTrics self, SConnection *pCon)
  {
     int iRet;
     
     assert(self);
     assert(pCon);
     
     if(self->iFirst == 1)
     {
        iRet = WriteFirstFrame(self,pCon);
     }
     else
     {
       iRet = ContinueFile(self,pCon);
     }     

     return iRet;     
  }  
/*-------------------------------------------------------------------------*/
  static int FrameInterest(int iEvent, void *pEvent, void *pUser)
  {
     SConnection *pCon = NULL;
     int *iFrame;
     char pBueffel[512];
     
     if(iEvent != NEWFRAME)
     {
       return 0;
     }
     
     pCon = (SConnection *)pUser;
     iFrame  = (int *)pEvent;
     assert(pCon);
     sprintf(pBueffel,"framenumber = %d",*iFrame);
     SCWrite(pCon,pBueffel,eWarning);
     return 1;        
  }  
/*-------------------------------------------------------------------------
  NexusGetFrame opens a TRICS NeXus file and retrieves a frame for the
  specified detector from it. This is a special feature for the 
  status display.
  ---------------------------------------------------------------------------*/
  static int NexusGetFrame(SConnection *pCon, pNexTrics self, 
                           int iDetector, int iFrame)
  {
      char pBueffel[132];
      int iRet;
      NXhandle hfil;
      HistInt *lData = NULL;

      /* do a few range checks */
      if(iDetector < 1 || iDetector > 3)
      {
	sprintf(pBueffel,"ERROR: unknown detector %d requested",iDetector);
        return 0; 
      }
      if(iFrame < 0 || iFrame >= self->iFrameNum)
      {
	sprintf(pBueffel,"ERROR: frame %d not yet written",iDetector);
        return 0; 
      }

      /* open file */
      iRet = NXopen(self->pCurrentFile,NXACC_READ,&hfil);
      if(iRet != NX_OK)
      {
        sprintf(pBueffel,"ERROR: cannot open %s",self->pCurrentFile);
        SCWrite(pCon,pBueffel,eError);
        return 0;
      }       

      /* open groups */
      sprintf(pBueffel,"frame%4.4d",iFrame);
      iRet = NXopengroup(hfil,pBueffel,"NXentry");
      if(iRet != NX_OK)
      {
	  sprintf(pBueffel,"ERROR: frame %d not found in %s",iFrame, 
		  self->pCurrentFile);
          SCWrite(pCon,pBueffel,eError);
          NXclose(&hfil);
          return 0;
      }
      sprintf(pBueffel,"detector%1.1d",iDetector);
      iRet = NXopengroup(hfil,pBueffel,"NXdata");
      if(iRet != NX_OK)
      {
	  sprintf(pBueffel,"ERROR: detector %d not found in %s",iFrame, 
		  self->pCurrentFile);
          SCWrite(pCon,pBueffel,eError);
          NXclose(&hfil);
          return 0;
      }
      iRet = NXopendata(hfil,"counts");
      if(iRet != NX_OK)
      {
          SCWrite(pCon,"ERROR: no counts found, file corrupted",eError);
          NXclose(&hfil);
          return 0;
      }

      /* read data */
      lData = (HistInt *)malloc(DET1X*DET1Y*sizeof(HistInt));
      if(!lData)
      {
	SCWrite(pCon,"ERROR: out of memory in NexusGetFrame",eError);
        NXclose(&hfil);
        return 0;
      }   
      memset(lData,0,DET1X*DET1Y*sizeof(HistInt));
      iRet = NXgetdata(hfil,lData);
      if(iRet != NX_OK)
      {
          SCWrite(pCon,"ERROR: failed to read data",eError);
          NXclose(&hfil);
          return 0;
      }

      /* send it */
      sprintf(pBueffel,"detector%1.1d",iDetector);
      SCWriteZipped(pCon,pBueffel,lData,DET1X*DET1Y*sizeof(HistInt));

      /* clean up */
      NXclose(&hfil);
      free(lData);
      return 1;
  } 
/*---------------------------------------------------------------------------*/
  int NexTricsAction(SConnection *pCon, SicsInterp *pSics, void *pData,
                     int argc, char *argv[])
  {
      pNexTrics self;
      char pBueffel[1024];
      int iRet, iDet, iFrame;
      long lID;
      
      self = (pNexTrics)pData;
      assert(self);
      assert(pCon);
      
      /* check for subcommands */
      if(argc < 2)
      {
        sprintf(pBueffel,"ERROR: no subcommand found for %s",argv[0]);
        SCWrite(pCon,pBueffel,eError);
        return 0;
      }

       /* install an error handler */
       NXMSetError((void *)pCon,SNError); 
      
      strtolower(argv[1]);
      if(strcmp(argv[1],"start") == 0)
      {
         if(!SCMatchRights(pCon,usUser))
         {
           return 0;
         }
         iRet = StartFile(self,pCon);
         if(iRet)
         {
           SCSendOK(pCon);
         }
         return iRet;
      }
      else if(strcmp(argv[1],"file") == 0)
      {
        sprintf(pBueffel,"Currently writing to: %s",self->pCurrentFile);
        SCWrite(pCon,pBueffel,eValue);
        return 1; 
      }
      else if(strcmp(argv[1],"oldframe") == 0)
      {
        if(argc < 4)
	{
	  SCWrite(pCon,"ERROR: insufficient number of arguments to oldframe",
          eError);
          return 0;
        }
        iDet = atoi(argv[2]);
        iFrame = atoi(argv[3]);
        iRet = NexusGetFrame(pCon,self,iDet, iFrame);
        return 1; 
      }
      else if(strcmp(argv[1],"interest") == 0)
      {
        lID = RegisterCallback(self->pCall, NEWFRAME, FrameInterest,
                                                    pCon, NULL);
        SCRegister(pCon,pSics, self->pCall,lID);
        SCSendOK(pCon);
        return 1; 
      }
      else if(strcmp(argv[1],"framenum") == 0)
      {
        sprintf(pBueffel,"framenumber = %d",self->iFrameNum);
        SCWrite(pCon,pBueffel,eValue);
        return 1; 
      }
      else if(strcmp(argv[1],"dumpframe") == 0)
      {
         if(!SCMatchRights(pCon,usUser))
         {
           return 0;
         }
         iRet = DumpFrame(self,pCon);
         if(iRet)
         {
           SCSendOK(pCon);
         }
         return iRet;
      }
      else if(strcmp(argv[1],"reopen") == 0)
      {
         if(!SCMatchRights(pCon,usUser))
         {
           return 0;
         }
         if(argc < 3)
         {
           SCWrite(pCon,"ERROR: expected filename as parameter for reopen",eError);
           return 0;
         }
         iRet = ReopenFile(self,argv[2]);
         if(iRet)
         {
           SCSendOK(pCon);
         }
         return iRet;
      }
      sprintf(pBueffel,"ERROR: subcommand %s not recognized",argv[1]);
      SCWrite(pCon,pBueffel,eError);
      return 0;
  }                                                                   


