/*--------------------------------------------------------------------------- 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 && strstr(entry.scanVar, "o2t") == NULL) { 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; }