/* Copyright (C) 2000 Damir Zucic */

/*=============================================================================

				comm_rotate.c

Purpose:
	Execute rotate command. Rotate all caught macromolecular complexes
	for a given angle around a given axis.

Input:
	(1) Pointer to MolComplexS structure, with macromol. complexes.
	(2) The number of macromolecular complexes.
	(3) Pointer to RuntimeS structure, with some runtime data.
	(4) Pointer to ConfigS structure, with configuration data.
	(5) Pointer to GUIS structure, with GUI data.
	(6) Pointer to NearestAtomS structure.
	(7) The number of pixels in the main window free area.
	(8) Pointer to refreshI.
	(9) String which contains  the rotation axis name and the rotation
	    angle.

Output:
	(1) Atoms rotated.
	(2) Return value.

Return value:
	(1) Positive (command) code on success.
	(2) Negative (error) code on failure.

========includes:============================================================*/

#include <stdio.h>

#include <string.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "commands.h"
#include "typedefs.h"

/*======function prototypes:=================================================*/

char		*ExtractToken_ (char *, int, char *, char *);
int		Rotate_ (MolComplexS *, int,
			 RuntimeS *, ConfigS *, double, int);
size_t		MainRefresh_ (MolComplexS *, int,
			      RuntimeS *, ConfigS *, GUIS *,
			      NearestAtomS *, size_t, unsigned int);
int		ControlRefresh_ (MolComplexS *, ConfigS *, GUIS *);
int		DockingRefresh_ (RuntimeS *, GUIS *);

/*======execute rotate command:==============================================*/

int CommandRotate_ (MolComplexS *mol_complexSP, int mol_complexesN,
		    RuntimeS *runtimeSP, ConfigS *configSP, GUIS *guiSP,
		    NearestAtomS *nearest_atomSP, size_t pixelsN,
		    unsigned int *refreshIP, char *stringP)
{
char		*remainderP;
char		tokenA[STRINGSIZE];
int		axisID;
double		rotation_angle;

/* Extract axis name: */
remainderP = ExtractToken_ (tokenA, STRINGSIZE, stringP, " \t\n");
if (!remainderP)
	{
	strcpy (runtimeSP->messageA, "Axis specification missing!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_NO_AXIS;
	}

/* Identify the axis: */
if      (strcmp (tokenA, "X") == 0) axisID = 1;
else if (strcmp (tokenA, "Y") == 0) axisID = 2;
else if (strcmp (tokenA, "Z") == 0) axisID = 3;
else
	{
	strcpy (runtimeSP->messageA,
		"Bad axis (only x, y and z are available)!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_BAD_AXIS;
	}

/* Extract the token which contains the rotation angle: */
remainderP = ExtractToken_ (tokenA, STRINGSIZE, remainderP, " \t\n");
if (!remainderP)
	{
	strcpy (runtimeSP->messageA, "Rotation angle missing!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_NO_ANGLE;
	}

/* Extract the rotation angle: */
if (sscanf (tokenA, "%lf", &rotation_angle) != 1)
	{
	strcpy (runtimeSP->messageA, "Rotation angle specification is bad!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_NO_ANGLE;
	}

/* Convert degrees to radians: */
rotation_angle *= DEG_TO_RAD;

/* Rotate all caught macromolecular complexes: */
Rotate_ (mol_complexSP, mol_complexesN,
	 runtimeSP, configSP, rotation_angle, axisID);

/* Refresh the main window: */
(*refreshIP)++;
MainRefresh_ (mol_complexSP, mol_complexesN, runtimeSP, configSP, guiSP,
	      nearest_atomSP, pixelsN, *refreshIP);

/* Refresh the control window: */
ControlRefresh_ (mol_complexSP + runtimeSP->default_complexI, configSP, guiSP);

/* Refresh docking window, if docking is switched on: */
if (guiSP->dockingF) DockingRefresh_ (runtimeSP, guiSP);

/* Return positive value on success: */
return COMMAND_ROTATE;
}

/*===========================================================================*/


