/* Copyright (C) 2000-2003 Damir Zucic */

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

				catch.c

Purpose:
	Execute catch (take) command: catch the specified macromolecular
	complex and release all others.  Set the new default  caught  ID
	and refresh the control window. Reset the group flag (RuntimeS).

Input:
	(1) Pointer to MolComplexS structure,  with macromol. complexes.
	(2) 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) The string which contains the macromol. complex identifier.

Output:
	(1) The catch flag (catchF) set for each macromolecular complex.
	(2) Return value.

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

Notes:
	(1) This command takes only  one argument.  If you want to catch
	    more than one macromolecular complex, use command group.

	(2) This function resets the edit mode index.

========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 *);
size_t		MainRefresh_ (MolComplexS *, int,
			      RuntimeS *, ConfigS *, GUIS *,
			      NearestAtomS *, size_t, unsigned int);
int		ControlRefresh_ (MolComplexS *, ConfigS *, GUIS *);

/*======execute catch command:===============================================*/

int Catch_ (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[SHORTSTRINGSIZE];
int		complexID;
int		mol_complexI;
MolComplexS	*curr_mol_complexSP;
int		job_doneF = 0;

/* Extract the macromolecular complex identifier: */
remainderP = ExtractToken_ (tokenA, SHORTSTRINGSIZE, stringP, " \t\n");
if (!remainderP)
	{
	strcpy (runtimeSP->messageA, "Complex identifier missing!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_NO_ID;
	}

/* Read the identifier (integer expected): */
if (sscanf (tokenA, "%d", &complexID) != 1)
	{
	strcpy (runtimeSP->messageA, "Bad macromolecular complex identifier!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_BAD_ID;
	}

/* Set the catchF and the group_memberF for the specified complex: */
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
	{
	/** Prepare the pointer to the current macromolecular complex: **/
	curr_mol_complexSP = mol_complexSP + mol_complexI;

	/** Check the number of atoms;  for bad **/
	/** and discarded complexes it is zero: **/
	if (curr_mol_complexSP->atomsN == 0) continue;

	/** If macromolecular complex is recognized: **/
	if (curr_mol_complexSP->mol_complexID == complexID)
		{
		/* Set the catchF to one: */
		curr_mol_complexSP->catchF = 1;

		/* Set the group_memberF to zero: */
		curr_mol_complexSP->group_memberF = 0;

		/* Set the flag which says that the complex was found: */
		job_doneF = 1;
		}
	}

/* If complex was not found, return negative value: */
if (job_doneF == 0)
	{
	strcpy (runtimeSP->messageA, "Bad complex identifier (out of range)!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_BAD_ID;
	}

/* If complex was found, set all other catch flags to zero: */
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
	{
	/** Prepare the pointer to the current macromolecular complex: **/
	curr_mol_complexSP = mol_complexSP + mol_complexI;

	/** For the specified complex,  do not reset the catch flag,  but **/
	/** use the complex index as the index of default caught complex: **/
	if (curr_mol_complexSP->mol_complexID == complexID)
		{
		runtimeSP->default_complexI = mol_complexI;
		continue;
		}

	/** For all other complexes, set the catch flag to zero: **/
	curr_mol_complexSP->catchF = 0;
	}

/* Default editing mode (0, no editing) does not */
/* require  redrawing.  Other modes  require it: */
if (runtimeSP->edit_modeI != 0)
	{
	/* Reset the edit mode index: */
	runtimeSP->edit_modeI = 0;

	/* 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);
	}

/* Don't forget to reset the group flag to zero. If some structures */
/* were grouped before,  the command  CATCH should break the group: */
runtimeSP->groupF = 0;

/* If some structures were involved in a formation of a */
/* group, restore the original rotation center vectors: */
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
	{
	/* Prepare the pointer to the current macromolecular complex: */
	curr_mol_complexSP = mol_complexSP + mol_complexI;

	/* Check was this complex a group member: */
	if (curr_mol_complexSP->group_memberF == 0) continue;

	/* If this point is reached, the current complex was a group member. */

	/* Restore the original rotation center vector: */
	curr_mol_complexSP->rotation_center_vectorS.x =
				curr_mol_complexSP->backup_vectorS.x;
	curr_mol_complexSP->rotation_center_vectorS.y =
				curr_mol_complexSP->backup_vectorS.y;
	curr_mol_complexSP->rotation_center_vectorS.z =
				curr_mol_complexSP->backup_vectorS.z;

	/* Reset the group_memberF: */
	curr_mol_complexSP->group_memberF = 0;
	}

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

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


