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

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

				select_element.c

Purpose:
	Try to interpret the selection string as the request to select the
	the specified chemical element.  There are  three selection modes:
	0 = overwrite,  1 = restrict,  2 = expand the previous  selection.
	This function expects that the second token in the command line is
	the keyword  ELEMENT  (short version is ELE).  If it is not found,
	the function will return negative value.

Input:
	(1) Pointer to MolComplexS structure, with macromol. complexes.
	(2) Number of macromolecular complexes.
	(3) The selection string.
	(4) Selection mode index  (0 = overwr., 1 = restrict, 2 = expand).

Output:
	(1) The flag selectedF will be equal to one for selected atoms and
	    equal to zero for all other atoms.
	(2) Return value.

Return value:
	(1) The number of  selected atoms,  if selection  is done  in this
	    function.
	(2) Negative value on failure.

Notes:
	(1) The standard chemical  symbols should  be used  to specify the
	    chemical elements.  In addition  to well known  elements,  two
	    imaginary elements were added: jellium (J) and quarkonium (Q).
	    Jellium  is inert - it is never  involved in  chemical  bonds.
	    Quarkonium  binds to neighboring atoms in the list of Q atoms,
	    i.e. to quarkonium  atoms  which have  adjacent  atomic serial
	    numbers.  The actual distance  between quarkonium atoms is not
	    important.  Quarkonium may be used  for polygonal lines in 3D.
	    J and Q were introduced  to adapt garlic  for visualization of
	    medical data.

========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 "typedefs.h"

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

char		*ExtractToken_ (char *, int, char *, char *);

/*======select the specified chemical element:===============================*/

long SelectElement_ (MolComplexS *mol_complexSP, int mol_complexesN,
		     char *stringP, int selection_modeI)
{
long		selected_atomsN = 0; 
char		*remainderP;
char		tokenA[STRINGSIZE];
int		mol_complexI;
MolComplexS	*curr_mol_complexSP;
size_t		atomsN, atomI;
AtomS		*curr_atomSP;
char		*P;
char		chemical_symbolA[20];
int		elementF;

/* Extract the first token and check it (look for substring ELE): */
remainderP = ExtractToken_ (tokenA, STRINGSIZE, stringP, " \t\n");
if (!strstr (tokenA, "ELE")) return (long) -1;

/* Try to extract one more token (chemical symbol expected): */
remainderP = ExtractToken_ (tokenA, STRINGSIZE, remainderP, " \t\n");
if (!remainderP) return (long) -2;

/* Check every macromolecular complex: */
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
	{
	/* Pointer to the current macromolecular complex: */
	curr_mol_complexSP = mol_complexSP + mol_complexI;

	/* Check is the current macromolecular complex caught: */
	if (curr_mol_complexSP->catchF == 0) continue;

	/* Number of atoms in a macromolecular complex: */
	atomsN = curr_mol_complexSP->atomsN;

	/* Scan all atoms in the current complex: */
	for (atomI = 0; atomI < atomsN; atomI++)
		{
		/* Pointer to the current atom: */
		curr_atomSP = curr_mol_complexSP->atomSP + atomI;

		/* Extract the chemical symbol of the current atom: */
		P = curr_atomSP->raw_atomS.chemical_symbolA;
		remainderP = ExtractToken_ (chemical_symbolA, 20, P, " \t");
		if (!remainderP) continue;

		/* Check the chemical symbol: */
		elementF = 0;
		if (strcmp (chemical_symbolA, tokenA) == 0) elementF = 1;

		/* Set the selection flag for the current atom: */
		switch (selection_modeI)
			{
			/* Overwrite the previous selection: */
			case 0:
				curr_atomSP->selectedF = elementF;
				break;

			/* Restrict the previous selection: */
			case 1:
				curr_atomSP->selectedF &= elementF;
				break;

			/* Expand the previous selection: */
			case 2:
				curr_atomSP->selectedF |= elementF;
				break;

			default:
				;
			}

		/* Check the selection flag; increase */
		/* the count if flag is equal to one: */
		if (curr_atomSP->selectedF) selected_atomsN++;
		}

	/* Update the position_changedF (some atoms may have bad color): */
	curr_mol_complexSP->position_changedF = 1;
	}

/* Return the number of selected atoms: */
return selected_atomsN;
}

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


