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

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

			    full_colors.c

Purpose:
	This function  handles the precise  color definitions.  The input
	string is expected  at least three tokens,  specifying three near
	and three far colors. The keyword old may be used to leave any of
	the old  colors  unchanged.  See  the table below  for mapping of
	tokens.  If  six colors  are  defined,  there  will be  two color
	surfaces; nine colors define three color surfaces etc.

Input:
	(1) Pointer to MolComplexS structure.
	(2) Number of macromolecular complexes.
	(3) Pointer to GUIS structure, with GUI data.
	(4) String with six colors.

Output:
	(1) Return value.

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

Notes:
	(1) Mapping tokens to colors:

	    ==================
	    | token | color  |
	    ==================
	    |   1   | left   |
	    |   2   | middle |
	    |   3   | right  |
	    ==================

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

#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 *);
int		IsOld_ (char *);
int		ParseColor_ (RGBS *, unsigned long *, GUIS *, char *, char *);

/*======full color specifications:===========================================*/

int FullColors_ (MolComplexS *mol_complexSP, int mol_complexesN,
		 GUIS *guiSP, char *stringP)
{
char			*remainderP;
char			tokenA[SHORTSTRINGSIZE];
int			tokensN = 0;
int			surfacesN, surfaceI;
size_t			rgb_struct_size;
RGBS			rgbS;
unsigned long		dummyID;
static ColorSchemeS	color_schemeS;
int			leftF[MAXCOLORSURFACES];
int			middleF[MAXCOLORSURFACES];
int			rightF[MAXCOLORSURFACES];
int			mol_complexI;
MolComplexS		*curr_mol_complexSP;
size_t			atomsN, atomI;
AtomS			*curr_atomSP;

/* Skip the first token: */
remainderP = ExtractToken_ (tokenA, SHORTSTRINGSIZE, stringP, " \t,;");
if (remainderP == NULL) return -1;

/* Count tokens: */
while ((remainderP = ExtractToken_ (tokenA, SHORTSTRINGSIZE,
				    remainderP, " \t,;")) != NULL) tokensN++;

/* Check the number of tokens: */
if (tokensN == 0) return -2;
if ((tokensN % 3) != 0) return -3;

/* Prepare the number of surfaces: */
surfacesN = tokensN / 3;
if (surfacesN > MAXCOLORSURFACES) return -4;

/*------extract and parse colors:--------------------------------------------*/

/* Skip the first token: */
remainderP = ExtractToken_ (tokenA, SHORTSTRINGSIZE, stringP, " \t,;");
if (remainderP == NULL) return -5;

/* The size of RGBS structure: */
rgb_struct_size = sizeof (RGBS); 

/* Parse all tokens: */
for (surfaceI = 0; surfaceI < surfacesN; surfaceI++)
	{
	/** Left color: **/
	remainderP = ExtractToken_ (tokenA, SHORTSTRINGSIZE,
				    remainderP, " \t,;");
	if (remainderP == NULL) return -6;
	if (IsOld_ (tokenA)) leftF[surfaceI] = 0;
	else
		{
		leftF[surfaceI] = 1;
		ParseColor_ (&rgbS, &dummyID, guiSP, tokenA, "white");
		memcpy (color_schemeS.left_rgbSA + surfaceI,
			&rgbS, rgb_struct_size);
		}

	/** Middle color: **/
	remainderP = ExtractToken_ (tokenA, SHORTSTRINGSIZE,
				    remainderP, " \t,;");
	if (remainderP == NULL) return -7;
	if (IsOld_ (tokenA)) middleF[surfaceI] = 0;
	else
		{
		middleF[surfaceI] = 1;
		ParseColor_ (&rgbS, &dummyID, guiSP, tokenA, "gray");
		memcpy (color_schemeS.middle_rgbSA + surfaceI,
			&rgbS, rgb_struct_size);
		}

	/** Right color: **/
	remainderP = ExtractToken_ (tokenA, SHORTSTRINGSIZE,
				    remainderP, " \t,;");
	if (remainderP == NULL) return -8;
	if (IsOld_ (tokenA)) rightF[surfaceI] = 0;
	else
		{
		rightF[surfaceI] = 1;
		ParseColor_ (&rgbS, &dummyID, guiSP, tokenA, "black");
		memcpy (color_schemeS.right_rgbSA + surfaceI,
			&rgbS, rgb_struct_size);
		}
	}

/*------assign colors to selected atoms:-------------------------------------*/

/* Scan 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;

		/** Check is atom selected: **/
		if (curr_atomSP->selectedF == 0) continue;

		/** Set the number of color surfaces: **/
		curr_atomSP->surfacesN = surfacesN;

		/** Copy the color specifications: **/
		for (surfaceI = 0; surfaceI < surfacesN; surfaceI++)
			{
			/*** Left color: ***/
			if (leftF[surfaceI])
				{
				memcpy (curr_atomSP->left_rgbSA  + surfaceI,
					color_schemeS.left_rgbSA + surfaceI,
					rgb_struct_size);
				}

			/*** Middle color: ***/
			if (middleF[surfaceI])
				{
				memcpy (curr_atomSP->middle_rgbSA  + surfaceI,
					color_schemeS.middle_rgbSA + surfaceI,
					rgb_struct_size);
				}

			/*** Right color: ***/
			if (rightF[surfaceI])
				{
				memcpy (curr_atomSP->right_rgbSA  + surfaceI,
					color_schemeS.right_rgbSA + surfaceI,
					rgb_struct_size);
				}
			}
		}

	/* Reset the position_changedF: */
	curr_mol_complexSP->position_changedF = 1;
	}

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

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


