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

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

				main_refresh.c

Purpose:
	Refresh  the main  window  content.  This function  does the most
	important job from  the user's standpoint: draws something to the
	screen.  This function calls  the functions  which are  doing the
	most important job.

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, with information about the
	    atom occupying the given pixel.
	(7) The number of pixels in the main window free area.
	(8) The refreshI, used to check the  NearestAtomS associated with
	    a given pixel.  If refreshI is larger than  the corresponding
	    value stored in NearestAtomS,  the structure does not contain
	    fresh data, so the pixel may be redrawn without any checking.
	    If values are equal,  the check should be  made to see  which
	    atom is closer  to the observer:  the one which  is currently
	    processed, or the one which already occupies the pixel.

Output:
	(1) Image drawn to the main window.
	(2) Return value.

Return value:
	(1) Depends on  main window  drawing mode index.  If mode is zero 
	    the number of atoms which were drawn  will be returned.  Zero
	    is returned if there are no visible atoms.  Negative value is
	    never returned,  because the return type is size_t,  so it is
	    unsigned on most systems.

Notes:
	(1) The initial drawing destination is the hidden pixmap, and the
	    content of this pixmap is  copied  later to  the main window.

	(2) The human eye may discriminate  something like  25 images per 
	    second.  Thus,  if this  function executes  once in less than
	    40  milliseconds,  refreshing will be smooth for the user. It
	    will be quite smooth even if needs more time for one passage,
	    because drawing is done on hidden pixmap ("hidden frame").

	(3) In default mode  (structure drawing mode),  after  the loaded
	    objects are drawn,  a small legend is placed to  the top left
	    corner (system.xpm).

	(4) A macromolecular object is visible and should be projected if
	    if least  one atom  of  this object  is visible.  The atom is
	    visible  if it is  not  hidden  (user may decide to hide some
	    atoms) and if it  falls inside the slab.  This does  not mean
	    that this atom will be truly visible in the main window:  its	
	    projection  may be outside  the free area of the main window.
	    Note  that the term  visible applyes both to  the atoms which
	    are actually  visible and to  the atoms  which are  projected
	    outside of the main window free area!

	(5) Do not change the execution order of Slab_, ProjectAtoms_ and
	    Fading_ !

	(6) Note that atoms and bonds  are drawn  style by style.  In the
	    first step,  only atoms which have  style "1"  are drawn. All
	    other atoms are ignored in this step. In the next step, atoms
	    which have style "2" are drawn etc.  Another approach will be
	    to draw  atom by atom  and bond by bond,  choosing the proper
	    style. This may require a larger number of function calls and
	    repeated passing of certain parameters, reducing the speed of
	    execution.

	(7) Planes are drawn after atoms and bonds are drawn.

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

#include <stdio.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:=================================================*/

void		InformUser_ (GUIS *, char *);
int		RefreshPixmap_ (Display *, Pixmap, GC,
				unsigned int, unsigned int, unsigned long);
size_t		Slab_ (MolComplexS *, int);
size_t		ProjectAtoms_ (MolComplexS *, int, ConfigS *);
void		ProjectMembranes_ (MolComplexS *, int, ConfigS *);
void		ProjectPlanes_ (MolComplexS *, int, ConfigS *);
size_t		Fading_ (MolComplexS *, int, GUIS *);
void		ResetPositionFlag_ (MolComplexS *, int);
size_t		DrawAtomsStyle1_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawAtomsStyle2_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawAtomsStyle3_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawAtomsStyle4_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawAtomsStyle5_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawAtomsStyle6_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawAtomsStyle7_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawBondsStyle1_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawBondsStyle2_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawBondsStyle3_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawBondsStyle4_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawBondsStyle5_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawNiceBonds_ (MolComplexS *, int, ConfigS *, GUIS *,
				NearestAtomS *, size_t, unsigned int);
size_t		DrawSticks_ (MolComplexS *, int, ConfigS *, GUIS *,
			     NearestAtomS *, size_t, unsigned int);
size_t		DrawBackbone_ (MolComplexS *, int, ConfigS *, GUIS *,
			       NearestAtomS *, size_t, unsigned int);
int		DrawBalls_ (MolComplexS *, int, ConfigS *, GUIS *,
			    NearestAtomS *, size_t, unsigned int);
int		DrawBalls2_ (MolComplexS *, int, ConfigS *, GUIS *,
			     NearestAtomS *, size_t, unsigned int);
int		DrawBigSpheres_ (MolComplexS *, int, ConfigS *, GUIS *,
				 NearestAtomS *, size_t, unsigned int);
int		DrawBigSpheres2_ (MolComplexS *, int, ConfigS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
int		DrawSpacefill_ (MolComplexS *, int, ConfigS *, GUIS *,
				NearestAtomS *, size_t, unsigned int);
int		DrawSpacefill2_ (MolComplexS *, int, ConfigS *, GUIS *,
				 NearestAtomS *, size_t, unsigned int);
int		DrawCovalent_ (MolComplexS *, int, ConfigS *, GUIS *,
			       NearestAtomS *, size_t, unsigned int);
int		DrawCovalent2_ (MolComplexS *, int, ConfigS *, GUIS *,
				NearestAtomS *, size_t, unsigned int);
int		DrawSmall_ (MolComplexS *, int, ConfigS *, GUIS *,
			    NearestAtomS *, size_t, unsigned int);
int		DrawSmall2_ (MolComplexS *, int, ConfigS *, GUIS *,
			     NearestAtomS *, size_t, unsigned int);
int		DrawEditSymbol_ (MolComplexS *, int,
				 RuntimeS *, ConfigS *, GUIS *,
				 NearestAtomS *, size_t, unsigned int);
int		DrawMembranes_ (MolComplexS *, int, ConfigS *, GUIS *,
				NearestAtomS *, size_t, unsigned int);
int		DrawPlanes_ (MolComplexS *, int, ConfigS *, GUIS *,
			     NearestAtomS *, size_t, unsigned int);
size_t		DrawRamachandran_ (MolComplexS *, int,
				   RuntimeS *, ConfigS *, GUIS *,
				   NearestAtomS *, size_t, unsigned int);
size_t		WheelTopView_ (RuntimeS *, GUIS *,
			       NearestAtomS *, size_t, unsigned int);
size_t		WheelBottomView_ (RuntimeS *, GUIS *,
				  NearestAtomS *, size_t, unsigned int);
size_t		DrawVenn_ (RuntimeS *, GUIS *,
			   NearestAtomS *, size_t, unsigned int);
size_t		DrawPlots_ (RuntimeS *, GUIS *,
			    NearestAtomS *, size_t, unsigned int);
size_t		DrawComparison_ (RuntimeS *, GUIS *,
				 NearestAtomS *, size_t, unsigned int);
int		SmallRamachandran_ (MolComplexS *, RuntimeS *, GUIS *);
int		SmallOmega_ (MolComplexS *, RuntimeS *, GUIS *);
int		BlurMainWindow_ (RuntimeS *, GUIS *, NearestAtomS *, size_t);
size_t		DrawLabels_ (MolComplexS *, int, ConfigS *, GUIS *);
int		DrawTags_ (MolComplexS *, int, ConfigS *, GUIS *);
int		DrawTitles_ (RuntimeS *, GUIS *);
int		DrawSystem_ (GUIS *);
int		WriteHints_ (GUIS *);

/*======refresh the main window:=============================================*/

size_t MainRefresh_ (MolComplexS *mol_complexSP, int mol_complexesN,
		     RuntimeS *runtimeSP, ConfigS *configSP, GUIS *guiSP,
		     NearestAtomS *nearest_atomSP, size_t pixelsN,
		     unsigned int refreshI)
{
size_t			atoms_drawnN = 0;
size_t			pixelI;
NearestAtomS		*curr_pixelSP;
int			edit_modeI;

/* Check  the main window refresh flag:  if it is equal to  zero,  do not */
/* refresh the main window - just inform the user that refreshing is off: */
if (guiSP->main_window_refreshF == 0)
	{
	InformUser_ (guiSP, "Refreshing off!");
	return 0;
	}

/* Draw Ramachandran plot instead of structure, if requested: */
if (guiSP->main_window_modeI == 1)
	{
	return DrawRamachandran_ (mol_complexSP, mol_complexesN,
				  runtimeSP, configSP, guiSP,
				  nearest_atomSP, pixelsN, refreshI);
	}

/* Draw helical wheel instead of structure, if requested: */
else if (guiSP->main_window_modeI == 2)
	{
	/* Counterclockwise wheel: */
	if (runtimeSP->wheel_clockwiseF == 0)
		{
		return WheelTopView_ (runtimeSP, guiSP,
				      nearest_atomSP, pixelsN, refreshI);
		}
	else
		{
		return WheelBottomView_ (runtimeSP, guiSP,
					 nearest_atomSP, pixelsN, refreshI);
		}
	}

/* Draw Venn diagram instead of structure, if requested: */
else if (guiSP->main_window_modeI == 3)
	{
	return DrawVenn_ (runtimeSP, guiSP,
			  nearest_atomSP, pixelsN, refreshI);
	}

/* Draw hydrophobicity plots instead of structure, if requested: */
else if (guiSP->main_window_modeI == 4)
	{
	return DrawPlots_ (runtimeSP, guiSP,
			   nearest_atomSP, pixelsN, refreshI);
	}

/* Draw sequence comparison: */
else if (guiSP->main_window_modeI == 5)
	{
	return DrawComparison_ (runtimeSP, guiSP,
				nearest_atomSP, pixelsN, refreshI);
	}

/* If this point is reached,  structures should be drawn */
/* (default drawing mode, guiSP->main_window_modeI = 0). */

/*---------------------------------------------------------------------------*/

/* Refresh the hidden pixmap, where drawing will be done: */
RefreshPixmap_ (guiSP->displaySP,
		guiSP->main_hidden_pixmapID,
		guiSP->theGCA[0],
		guiSP->control_winS.x0, guiSP->input_winS.y0,
		guiSP->main_winS.bg_colorID);

/* If blur is on,  fill the colorID element of each */
/* NearestAtomS structure with background color ID: */
if (runtimeSP->blurF)
	{
	for (pixelI = 0; pixelI < pixelsN; pixelI++)
		{
		curr_pixelSP = nearest_atomSP + pixelI;
		curr_pixelSP->colorID = guiSP->main_winS.bg_colorID;
		}
	}

/*---------------------------------------------------------------------------*/

/* Check which atoms are inside slab: */
Slab_ (mol_complexSP, mol_complexesN);

/* Project atoms: */
ProjectAtoms_ (mol_complexSP, mol_complexesN, configSP);

/* Project all available membranes: */
ProjectMembranes_ (mol_complexSP, mol_complexesN, configSP);

/* Project all planes (even if not visible): */
ProjectPlanes_ (mol_complexSP, mol_complexesN, configSP);

/* Prepare  the left,  middle and  right color for each atom. */
/* These are the only colors required by fast drawing styles. */
Fading_ (mol_complexSP, mol_complexesN, guiSP);

/* Reset the position_changedF in each macromolecular complex: */
ResetPositionFlag_ (mol_complexSP, mol_complexesN);

/*------draw atoms (simple styles):------------------------------------------*/

atoms_drawnN += DrawAtomsStyle1_ (mol_complexSP, mol_complexesN,
				  configSP, guiSP,
				  nearest_atomSP, pixelsN, refreshI);

atoms_drawnN += DrawAtomsStyle2_ (mol_complexSP, mol_complexesN,
				  configSP, guiSP,
				  nearest_atomSP, pixelsN, refreshI);

atoms_drawnN += DrawAtomsStyle3_ (mol_complexSP, mol_complexesN,
				  configSP, guiSP,
				  nearest_atomSP, pixelsN, refreshI);

atoms_drawnN += DrawAtomsStyle4_ (mol_complexSP, mol_complexesN,
				  configSP, guiSP,
				  nearest_atomSP, pixelsN, refreshI);

atoms_drawnN += DrawAtomsStyle5_ (mol_complexSP, mol_complexesN,
				  configSP, guiSP,
				  nearest_atomSP, pixelsN, refreshI);

atoms_drawnN += DrawAtomsStyle6_ (mol_complexSP, mol_complexesN,
				  configSP, guiSP,
				  nearest_atomSP, pixelsN, refreshI);

atoms_drawnN += DrawAtomsStyle7_ (mol_complexSP, mol_complexesN,
				  configSP, guiSP,
				  nearest_atomSP, pixelsN, refreshI);

/*------draw bonds (simple styles):------------------------------------------*/

DrawBondsStyle1_ (mol_complexSP, mol_complexesN,
		  configSP, guiSP,
		  nearest_atomSP, pixelsN, refreshI);

DrawBondsStyle2_ (mol_complexSP, mol_complexesN,
		  configSP, guiSP,
		  nearest_atomSP, pixelsN, refreshI);

DrawBondsStyle3_ (mol_complexSP, mol_complexesN,
		  configSP, guiSP,
		  nearest_atomSP, pixelsN, refreshI);

DrawBondsStyle4_ (mol_complexSP, mol_complexesN,
		  configSP, guiSP,
		  nearest_atomSP, pixelsN, refreshI);

DrawBondsStyle5_ (mol_complexSP, mol_complexesN,
		  configSP, guiSP,
		  nearest_atomSP, pixelsN, refreshI);

/*------special drawing functions:-------------------------------------------*/

DrawBackbone_ (mol_complexSP, mol_complexesN,
	       configSP, guiSP,
	       nearest_atomSP, pixelsN, refreshI);

DrawBalls_ (mol_complexSP, mol_complexesN,
	    configSP, guiSP,
	    nearest_atomSP, pixelsN, refreshI);

DrawBalls2_ (mol_complexSP, mol_complexesN,
	     configSP, guiSP,
	     nearest_atomSP, pixelsN, refreshI);

DrawBigSpheres_ (mol_complexSP, mol_complexesN,
		 configSP, guiSP,
		 nearest_atomSP, pixelsN, refreshI);

DrawBigSpheres2_ (mol_complexSP, mol_complexesN,
		  configSP, guiSP,
		  nearest_atomSP, pixelsN, refreshI);

DrawSpacefill_ (mol_complexSP, mol_complexesN,
		configSP, guiSP,
		nearest_atomSP, pixelsN, refreshI);

DrawSpacefill2_ (mol_complexSP, mol_complexesN,
		 configSP, guiSP,
		 nearest_atomSP, pixelsN, refreshI);

DrawCovalent_ (mol_complexSP, mol_complexesN,
	       configSP, guiSP,
	       nearest_atomSP, pixelsN, refreshI);

DrawCovalent2_ (mol_complexSP, mol_complexesN,
		configSP, guiSP,
		nearest_atomSP, pixelsN, refreshI);

DrawSmall_ (mol_complexSP, mol_complexesN,
	    configSP, guiSP,
	    nearest_atomSP, pixelsN, refreshI);

DrawSmall2_ (mol_complexSP, mol_complexesN,
	     configSP, guiSP,
	     nearest_atomSP, pixelsN, refreshI);

DrawNiceBonds_ (mol_complexSP, mol_complexesN,
		configSP, guiSP,
		nearest_atomSP, pixelsN, refreshI);

DrawSticks_ (mol_complexSP, mol_complexesN,
	     configSP, guiSP,
	     nearest_atomSP, pixelsN, refreshI);

if (runtimeSP->edit_modeI != 0)
	{
	DrawEditSymbol_ (mol_complexSP, mol_complexesN,
			 runtimeSP, configSP, guiSP,
			 nearest_atomSP, pixelsN, refreshI);
	}

DrawMembranes_ (mol_complexSP, mol_complexesN,
		configSP, guiSP,
		nearest_atomSP, pixelsN, refreshI);

DrawPlanes_ (mol_complexSP, mol_complexesN,
	     configSP, guiSP,
	     nearest_atomSP, pixelsN, refreshI);

/*------auxiliary symbols and plots:-----------------------------------------*/

/* If editing dihedral angle phi or psi (or both), draw small Rama. */
/* plot for the first selected residue  to the bottom right corner: */
edit_modeI = runtimeSP->edit_modeI;
if ((edit_modeI == 2) || (edit_modeI == 3) || (edit_modeI == 5))
	{
	SmallRamachandran_ (mol_complexSP + runtimeSP->default_complexI,
			    runtimeSP, guiSP);
	}

/* If editing the omega angle, draw small */
/* omega plot to the bottom right corner: */
else if (edit_modeI == 4)
	{
	SmallOmega_ (mol_complexSP + runtimeSP->default_complexI,
		     runtimeSP, guiSP);
	}

/* Write some hints if there are no macromolecular complexes loaded: */
if (mol_complexesN == 0) WriteHints_ (guiSP);

/*---------------------------------------------------------------------------*/

/* Copy hidden pixmap to the main window: */
XCopyArea (guiSP->displaySP,
	   guiSP->main_hidden_pixmapID, guiSP->main_winS.ID,
	   guiSP->theGCA[0],
	   0, 0,
	   guiSP->main_win_free_area_width, guiSP->main_win_free_area_height,
	   0, 0);

/* Blur image if blur flag is equal to one: */
if (runtimeSP->blurF)
	{
	BlurMainWindow_ (runtimeSP, guiSP, nearest_atomSP, pixelsN);
	}

/*------labels, tags, titles and coordinate system hint:---------------------*/

DrawLabels_ (mol_complexSP, mol_complexesN, configSP, guiSP);

DrawTags_ (mol_complexSP, mol_complexesN, configSP, guiSP);

DrawTitles_ (runtimeSP, guiSP);

/* Put a small legend to the top left corner: */
/* (system.xpm, to explain the coord. system) */
if (configSP->show_coord_systemF) DrawSystem_ (guiSP);

/*---------------------------------------------------------------------------*/

return atoms_drawnN;
}

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


