/*--------------------------------------------------------------------------- F O U R T A B L E A SICS object which holds the variation of scan parameters for four circle reflection list measurements. copyright: see copyright.h Mark Koennecke, February 2005 ---------------------------------------------------------------------------*/ #include #include #include "sics.h" #include "fortify.h" #include "lld.h" #include #include "splitter.h" #include "fourtable.h" /*====================== table entry ===================================*/ typedef struct { double twoThetaEnd; char scanVar[30]; double step; int np; float preset; }FourTableEntry, *pFourTableEntry; /*==================== functions =======================================*/ int MakeFourCircleTable(){ return LLDcreate(sizeof(FourTableEntry)); } /*-----------------------------------------------------------------------*/ void DeleteFourCircleTable(int handle){ LLDdelete(handle); } /*------------------------------------------------------------------------*/ static void printList(int handle, SConnection *pCon){ FourTableEntry entry; char pBueffel[132]; int status, printed = 0; Tcl_DString list; Tcl_DStringInit(&list); status = LLDnodePtr2First(handle); while(status == 1) { LLDnodeDataTo(handle,&entry); snprintf(pBueffel,131,"%8.3f %10s %8.3f %d %8.3f\n", entry.twoThetaEnd, entry.scanVar,entry.step, entry.np,entry.preset); Tcl_DStringAppend(&list,pBueffel,-1); printed = 1; status = LLDnodePtr2Next(handle); } if(printed == 0){ Tcl_DStringAppend(&list,"table is empty",-1); } SCWrite(pCon,Tcl_DStringValue(&list), eValue); Tcl_DStringFree(&list); } /*--------------------------------------------------------------------- Make sure that the entry is added in a sorted way according to two_theta ----------------------------------------------------------------------*/ static void insertEntry(int list, FourTableEntry newEntry){ int status, count = 0, pos; FourTableEntry test; /* locate the last entry bigger then us */ status = LLDnodePtr2First(list); while(status == 1){ LLDnodeDataTo(list,&test); count++; if(test.twoThetaEnd == newEntry.twoThetaEnd){ LLDnodeDataFrom(list,&newEntry); return; } if(test.twoThetaEnd > newEntry.twoThetaEnd){ break; } status = LLDnodePtr2Next(list); } /* special case: empty list */ if(count == 0){ LLDnodeAppendFrom(list,&newEntry); return; } /* special case: append after last */ LLDnodePtr2Last(list); LLDnodeDataTo(list,&test); if(newEntry.twoThetaEnd > test.twoThetaEnd){ LLDnodeAppendFrom(list,&newEntry); return; } status = LLDnodePtr2First(list); pos = 0; while(status == 1){ LLDnodeDataTo(list,&test); pos++; if(pos == count){ LLDnodeInsertFrom(list,&newEntry); return; } status = LLDnodePtr2Next(list); } } /*-----------------------------------------------------------------------*/ static int addToList(int handle, SConnection *pCon, int argc, char *argv[]){ FourTableEntry entry; char pBueffel[132]; if(argc < 7){ SCWrite(pCon,"ERROR: not enough arguments to table add",eError); return 0; } if(isNumeric(argv[3])){ entry.twoThetaEnd = atof(argv[3]); } else { snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } strncpy(entry.scanVar,argv[4],29); strtolower(entry.scanVar); if(strcmp(entry.scanVar,"om") != 0 && strcmp(entry.scanVar,"o2t") != 0){ SCWrite(pCon,"ERROR: Invalied scan variable specified, only om, o2t allowed",eError); return 0; } if(isNumeric(argv[5])){ entry.step = atof(argv[5]); } else { snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[4]); SCWrite(pCon,pBueffel,eError); return 0; } if(isNumeric(argv[6])){ entry.np = atoi(argv[6]); } else { snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[6]); SCWrite(pCon,pBueffel,eError); return 0; } entry.preset = -1.0; if(argc > 7){ if(isNumeric(argv[7])){ entry.preset = atof(argv[7]); } } insertEntry(handle,entry); return 1; } /*-----------------------------------------------------------------------*/ static void delEntry(int handle, int index){ int count = 0, status; status = LLDnodePtr2First(handle); while(status == 1) { if(count == index){ LLDnodeDelete(handle); break; } else { count++; status = LLDnodePtr2Next(handle); } } } /*------------------------------------------------------------------------*/ int HandleFourCircleCommands(int *table, SConnection *pCon, int argc, char *argv[], int *err){ int handle; *err = 1; handle = *table; /* test if this is for us */ if(argc >= 3){ strtolower(argv[1]); if(strcmp(argv[1],"table") != 0){ return 0; } } else { return 0; } /* what are we supposed to do? */ strtolower(argv[2]); if(strcmp(argv[2],"clear") == 0){ if(!SCMatchRights(pCon,usUser)){ *err = 0; return 1; } LLDdelete(handle); handle = LLDcreate(sizeof(FourTableEntry)); *table = handle; SCparChange(pCon); SCSendOK(pCon); } else if (strcmp(argv[2],"list") == 0){ printList(handle,pCon); } else if(strcmp(argv[2],"add") == 0){ if(!SCMatchRights(pCon,usUser)){ *err = 0; return 1; } *err = addToList(handle,pCon,argc,argv); if(*err != 0) { SCparChange(pCon); SCSendOK(pCon); } } else if(strcmp(argv[2],"del") == 0){ if(!SCMatchRights(pCon,usUser)){ *err = 0; return 1; } if(argc < 4){ SCWrite(pCon,"ERROR: insufficnet number of arguments to table del",eError); *err = 0; } else { if(isNumeric(argv[3])){ delEntry(handle, atoi(argv[3])); SCparChange(pCon); SCSendOK(pCon); } else { SCWrite(pCon,"ERROR: bad argument: expected numeric argument to table del",eError); *err = 0; } } } else { SCWrite(pCon,"ERROR: subcommand to table not known",eError); *err = 0; } return 1; } /*-----------------------------------------------------------------------*/ static FourTableEntry findEntry(int handle, double two_theta){ int status; FourTableEntry entry; status = LLDnodePtr2First(handle); while(status == 1) { LLDnodeDataTo(handle,&entry); if(entry.twoThetaEnd > two_theta){ return entry; } status = LLDnodePtr2Next(handle); } strcpy(entry.scanVar,"NOT FOUND"); return entry; } /*------------------------------------------------------------------------*/ char *GetFourCircleScanVar(int handle, double two_theta){ FourTableEntry entry; entry = findEntry(handle,two_theta); return strdup(entry.scanVar); } /*------------------------------------------------------------------------*/ double GetFourCircleStep(int handle, double two_theta){ FourTableEntry entry; entry = findEntry(handle,two_theta); if(strcmp(entry.scanVar,"NOT FOUND") == 0){ return -999.99; } else { return entry.step; } } /*------------------------------------------------------------------------*/ float GetFourCirclePreset(int handle, double two_theta){ FourTableEntry entry; entry = findEntry(handle,two_theta); if(strcmp(entry.scanVar,"NOT FOUND") == 0){ return -999.99; } else { return entry.preset; } } /*------------------------------------------------------------------------*/ int GetFourCircleScanNP(int handle, double two_theta){ FourTableEntry entry; entry = findEntry(handle,two_theta); if(strcmp(entry.scanVar,"NOT FOUND") == 0){ return -999; } else { return entry.np; } } /*------------------------------------------------------------------------*/ int SaveFourCircleTable(int handle, char *objName, FILE *fd){ FourTableEntry entry; int status; fprintf(fd,"%s table clear\n",objName); status = LLDnodePtr2Last(handle); while(status != 0) { LLDnodeDataTo(handle,&entry); fprintf(fd,"%s table add %f %s %f %d %f\n",objName, entry.twoThetaEnd,entry.scanVar, entry.step,entry.np,entry.preset); status = LLDnodePtr2Prev(handle); } return 1; }