349 lines
8.6 KiB
C
349 lines
8.6 KiB
C
/*---------------------------------------------------------------------------
|
|
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 <stdlib.h>
|
|
#include <assert.h>
|
|
#include "sics.h"
|
|
#include "fortify.h"
|
|
#include "lld.h"
|
|
#include <tcl.h>
|
|
#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;
|
|
}
|