/* Copyright (C) 2000, 2001 Damir Zucic */

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

				select.c

Purpose:
	Execute  select  command.  Select  the specified  atoms  in all
	caught  macromolecular  complexes.  Three  selection modes  are
	available:  0 = overwrite,  1 = restrict,  2 = expand  previous
        selection.

Input:
	(1) Pointer to MolComplexS structure.
	(2) Number of macromolecular complexes.
	(3) Pointer to RuntimeS structure.
	(4) Pointer to ConfigS structure.
	(5) Pointer to GUIS structure.
	(6) Pointer to NearestAtomS structure.
	(7) The number of pixels in the main window free area.
	(8) Pointer to refreshI.
	(9) The selection string.
       (10) Selection mode index.

Output:
	(1) Selection flag changed for some or all atoms.
	(2) Return value.

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

Notes:
	(1) 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 *);
long		FullSelect_ (MolComplexS *, int, char *, int);
long		SelectElement_ (MolComplexS *, int, char *, int);
long		SelectAtoms_ (MolComplexS *, int, RuntimeS *, char *, int);
long		SpecialSelect_ (MolComplexS *, int, RuntimeS *, char *, int);
long		QuickSelect_ (MolComplexS *, int, char *, int);
size_t		MainRefresh_ (MolComplexS *, int,
			      RuntimeS *, ConfigS *, GUIS *,
			      NearestAtomS *, size_t, unsigned int);
int		ControlRefresh_ (MolComplexS *, ConfigS *, GUIS *);

/*======execute select command:==============================================*/

int Select_ (MolComplexS *mol_complexSP, int mol_complexesN,
	     RuntimeS *runtimeSP, ConfigS *configSP, GUIS *guiSP,
	     NearestAtomS *nearest_atomSP, size_t pixelsN,
	     unsigned int *refreshIP,
	     char *stringP, int selection_modeI)
{
char		*remainderP;
char		tokenA[STRINGSIZE];
long		selected_atomsN;

/* The second token should contain  the selection */
/* criteria; it is called "the selection string": */
remainderP = ExtractToken_ (tokenA, STRINGSIZE, stringP, "\n\0");
if (!remainderP)
	{
	strcpy (runtimeSP->messageA, "Selection criteria missing!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_SELECT;
	}

/* First try with the function which expects precise selection */
/* criteria;  the string is expected to contain three slashes: */
selected_atomsN = FullSelect_ (mol_complexSP, mol_complexesN,
			       tokenA, selection_modeI);

/* If the first attempt failed, try to intepret the command */
/* as the request to select the specified chemical element: */
if (selected_atomsN == -1)
	{
	selected_atomsN = SelectElement_ (mol_complexSP, mol_complexesN,
					  tokenA, selection_modeI);
	}

/* Try to interpret the command as the request to select */
/* the atom  which  has  the  specified  serial  number: */
if (selected_atomsN == -1)
	{
	selected_atomsN = SelectAtoms_ (mol_complexSP, mol_complexesN,
					runtimeSP, tokenA, selection_modeI);
	}

/* If  all previous functions  were unable  to interpret the */
/* selection string try with the special selection function: */
if (selected_atomsN == -1)
	{
	selected_atomsN = SpecialSelect_ (mol_complexSP, mol_complexesN,
					  runtimeSP, tokenA, selection_modeI);
	}

/* The last attempt - try with the "quick" selection: */
if (selected_atomsN == -1)
	{
	selected_atomsN = QuickSelect_ (mol_complexSP, mol_complexesN,
					tokenA, selection_modeI);
	}

/* Write the number of selected atoms to the input window: */
if (selected_atomsN >= 0)
	{
	sprintf (runtimeSP->messageA,
		 "%ld atom(s) selected", selected_atomsN);
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	}

/* If all selection functions failed, prepare error message: */
else
	{
	strcpy (runtimeSP->messageA, "Selection failed!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return ERROR_SELECT;
	}

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

	/* Reset edit_single_bondF flag: */
	runtimeSP->edit_single_bondF = 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);
	}

/* If this point is reached, everything worked fine: */
return COMMAND_SELECT;
}

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


