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

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

				init_runtime.c

Purpose:
	Initialize some runtime data and allocate required memory.

Input:
	(1) Pointer to RuntimeS structure.
	(2) Pointer to ConfigS structure.

Output:
	(1) Runtime parameters initialized.
	(2) Return value.

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

Notes:
	(1) The buffers exposed_atom1IP and exposed_atom2IP will be
	    allocated only if docking is required. Otherwise, there
	    is no need to allocate these buffers. The allocation is
	    done in a function which creates docking window.

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

#include <stdio.h>

#include <stdlib.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		ErrorMessage_ (char *, char *, char *,
			       char *, char *, char *, char *);
FILE		*OpenTemplateFile_ (void);
int		ReadTemplateFile_ (RuntimeS *, FILE *, ConfigS *);

/*======initialize runtime:==================================================*/

int InitRuntime_ (RuntimeS *runtimeSP, ConfigS *configSP)
{
size_t		char_size;
size_t		int_size, double_size;
size_t		atom_struct_size;
size_t		beta_cell_size;
size_t		elementsN;
int		i;
double		d;
int		width;
FILE		*template_fileP;

/* Initialize the click_modeI: */
runtimeSP->click_modeI = 0;

/* Initialize the edit_modeI: */
runtimeSP->edit_modeI = 0;

/* Initialize edit_single_bondF flag: */
runtimeSP->edit_single_bondF = 0;

/* Default caught macromolecular complex: */
runtimeSP->default_complexI = 0;

/* Initialize the scriptF (0 = interactive mode, 1 = script mode): */
runtimeSP->scriptF = 0;

/* Initialize the pauseF (0 = do not stop execution, 1 = pause): */
runtimeSP->pauseF = 0;

/* Initialize the rama_selectionF: */
runtimeSP->rama_selectionF = 0;

/* Initialize the wheel_clockwiseF: */
runtimeSP->wheel_clockwiseF = 0;

/* Initialize the groupF: */
runtimeSP->groupF = 0;

/* Size of a single character: */
char_size = sizeof (char);

/* Size of integer: */
int_size = sizeof (int);

/* Size of double: */
double_size = sizeof (double);

/* Size of AtomS: */
atom_struct_size = sizeof (AtomS);

/* Size of BetaCellS: */
beta_cell_size = sizeof (BetaCellS);

/* Allocate memory for command strings (the history buffer): */
elementsN = MAXCOMMSTRINGS * COMMSTRINGSIZE;
runtimeSP->commandsP = (char *) calloc (elementsN, char_size);
if (runtimeSP->commandsP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for command strings!\n",
		"", "", "");
	return -1;
	}

/* Initialize next_commandI, old_commandI and highest_commandI: */
runtimeSP->next_commandI    =  0;
runtimeSP->old_commandI     =  0;
runtimeSP->highest_commandI = -1;

/* Initialize the carriage (keyboard cursor) position: */
runtimeSP->carriage_position = 0;

/* Zero initialize the curr_commandA: */
runtimeSP->curr_commandA[0] = '\0';

/* Initialize the length of the current command and carriage position: */
runtimeSP->command_length = 0;
runtimeSP->carriage_position = 0;

/* Zero initialize the messageA: */
runtimeSP->messageA[0] = '\0';

/* Initialize the length of the message: */
runtimeSP->message_length = 0;

/* Allocate memory for titles: */
elementsN = MAXTITLES * TITLESTRINGSIZE;
runtimeSP->titlesP = (char *) calloc (elementsN, char_size);
if (runtimeSP->titlesP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for title strings!\n",
		"", "", "");
	return -2;
	}

/* All titles are initially hidden: */
for (i = 0; i < MAXTITLES; i++) runtimeSP->title_hiddenF[i] = 1;

/* Initialize positions of titles: */
for (i = 0; i < MAXTITLES; i++)
	{
	runtimeSP->title_screen_x[i] = 10;
	runtimeSP->title_screen_y[i] = 10;
	}

/* Initialize the size of the sequence buffer: */
runtimeSP->sequence_buffer_size = MAXRESIDUES * (RESNAMESIZE - 1);

/* Initialize the number of residues in the sequence buffer: */
runtimeSP->residuesN = 0;

/* Allocate the sequence buffer: */
elementsN = runtimeSP->sequence_buffer_size;
runtimeSP->sequenceP = (char *) calloc (elementsN, char_size);
if (runtimeSP->sequenceP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate the sequence buffer!\n",
		"", "", "");
	return -3;
	}

/* Initialize the size of the pattern buffer: */
runtimeSP->pattern_buffer_size = MAX_RES_IN_PATT * (RESNAMESIZE - 1);

/* Initialize the number of residues in the pattern buffer: */
runtimeSP->residues_in_patternN = 0; 

/* Initialize the pattern tolerance: */
runtimeSP->pattern_tolerance = 0;

/* Allocate the pattern buffer: */
elementsN = runtimeSP->pattern_buffer_size;
runtimeSP->patternP = (char *) calloc (elementsN, char_size);
if (runtimeSP->patternP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate the pattern buffer!\n",
		"", "", "");
	return -4;
	}

/* Initialize the array with the number of residues per set: */
for (i = 0; i < MAX_PATT_LENGTH; i++)
	{
	runtimeSP->namesNA[i] = 0;
	}

/* Allocate the secondary structure buffer: */
elementsN = MAXRESIDUES;
runtimeSP->sec_structureP = (char *) calloc (elementsN, char_size);
if (runtimeSP->sec_structureP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate the secondary structure buffer!\n",
		"", "", "");
	return -5;
	}

/* Fill the buffer with the code for extended conformation: */
runtimeSP->sec_structure_length = MAXRESIDUES;
for (i = 0; i < MAXRESIDUES; i++) *(runtimeSP->sec_structureP + i) = 'E';

/* Allocate memory for disulfide flags (see typedefs.h): */
elementsN = MAXRESIDUES;
runtimeSP->disulfideFP = (int *) calloc (elementsN, int_size);
if (runtimeSP->disulfideFP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for disulfide flags!\n",
		"", "", "");
	return -6;
	}

/* Allocate memory for serial numbers: */
elementsN = MAXRESIDUES;
runtimeSP->serialIP = (int *) calloc (elementsN, int_size);
if (runtimeSP->serialIP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for residue serial numbers!\n",
		"", "", "");
	return -7;
	}

/* Allocate memory for numeric residue codes: */
elementsN = MAXRESIDUES;
runtimeSP->residue_codeIP = (int *) calloc (elementsN, int_size);
if (runtimeSP->residue_codeIP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for numeric residue codes!\n",
		"", "", "");
	return -8;
	}

/* Allocate memory for hydrophobicity values: */
elementsN = MAXRESIDUES;
runtimeSP->hydrophobicityP = (double *) calloc (elementsN, double_size);
if (runtimeSP->hydrophobicityP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for hydrophobicity values!\n",
		"", "", "");
	return -9;
	}

/* Allocate memory for average hydrophobicity: */
elementsN = MAXRESIDUES;
runtimeSP->average_hydrophobicityP = (double *) calloc (elementsN, double_size);
if (runtimeSP->average_hydrophobicityP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for average hydrophobicity!\n",
		"", "", "");
	return -10;
	}

/* Allocate memory for weighted hydrophobicity: */
elementsN = MAXRESIDUES;
runtimeSP->weighted_hydrophobicityP =
				(double *) calloc (elementsN, double_size);
if (runtimeSP->weighted_hydrophobicityP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for weighted hydrophobicity!\n",
		"", "", "");
	return -11;
	}

/* Allocate memory for hydrophobic moment: */
elementsN = MAXRESIDUES;
runtimeSP->hydrophobic_momentP = (double *) calloc (elementsN, double_size);
if (runtimeSP->hydrophobic_momentP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for hydrophobic moment!\n",
		"", "", "");
	return -12;
	}

/* Allocate memory for sided hydrophobicity (two buffers): */
elementsN = MAXRESIDUES;
runtimeSP->larger_sided_hyphobP = (double *) calloc (elementsN, double_size);
if (runtimeSP->larger_sided_hyphobP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
	    "Failed to allocate memory for larger sided hydrophobicity!\n",
	    "", "", "");
	return -13;
	}
runtimeSP->smaller_sided_hyphobP = (double *) calloc (elementsN, double_size);
if (runtimeSP->smaller_sided_hyphobP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
	    "Failed to allocate memory for smaller sided hydrophobicity!\n",
	    "", "", "");
	return -14;
	}

/* Allocate memory for hydrophobicity function F1: */
elementsN = MAXRESIDUES;
runtimeSP->function1P = (double *) calloc (elementsN, double_size);
if (runtimeSP->function1P == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for function F1!\n",
		"", "", "");
	return -15;
	}

/* Allocate memory for hydrophobicity function F2: */
elementsN = MAXRESIDUES;
runtimeSP->function2P = (double *) calloc (elementsN, double_size);
if (runtimeSP->function2P == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for function F2!\n",
		"", "", "");
	return -16;
	}

/* Allocate memory for hydrophobicity function F3: */
elementsN = MAXRESIDUES;
runtimeSP->function3P = (double *) calloc (elementsN, double_size);
if (runtimeSP->function3P == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for function F3!\n",
		"", "", "");
	return -17;
	}

/* Allocate memory for hydrophobicity function F4: */
elementsN = MAXRESIDUES;
runtimeSP->function4P = (double *) calloc (elementsN, double_size);
if (runtimeSP->function4P == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for function F4!\n",
		"", "", "");
	return -18;
	}

/* Allocate memory for hydrophobicity function F5: */
elementsN = MAXRESIDUES;
runtimeSP->function5P = (double *) calloc (elementsN, double_size);
if (runtimeSP->function5P == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for function F5!\n",
		"", "", "");
	return -19;
	}

/* Allocate memory for hydrophobicity function F6: */
elementsN = MAXRESIDUES;
runtimeSP->function6P = (double *) calloc (elementsN, double_size);
if (runtimeSP->function6P == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for function F6!\n",
		"", "", "");
	return -20;
	}

/* Allocate memory for hydrophobicity function F7: */
elementsN = MAXRESIDUES;
runtimeSP->function7P = (double *) calloc (elementsN, double_size);
if (runtimeSP->function7P == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory for function F7!\n",
		"", "", "");
	return -21;
	}

/* Allocate memory for auxiliary integers: */
elementsN = MAXRESIDUES;
runtimeSP->auxiliaryIP = (int *) calloc (elementsN, int_size);
if (runtimeSP->auxiliaryIP == NULL)
        {
        ErrorMessage_ ("garlic", "InitRuntime_", "",
                "Failed to allocate memory",
                " for auxiliary integers!\n",
                "", "");
        return -22;
        }

/* Allocate memory for auxiliary double values: */
elementsN = MAXRESIDUES;
runtimeSP->aux_doubleP = (double *) calloc (elementsN, double_size);
if (runtimeSP->aux_doubleP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory",
		" for auxiliary double values!\n",
		"", "");
	return -23;
	}

/* Initialize the number of residues in the reference sequence buffer: */
runtimeSP->reference_residuesN = 0;

/* Allocate the reference sequence buffer: */
elementsN = runtimeSP->sequence_buffer_size;
runtimeSP->reference_sequenceP = (char *) calloc (elementsN, char_size);
if (runtimeSP->reference_sequenceP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate the reference sequence buffer!\n",
		"", "", "");
	return -24;
	}

/* Initialize the reference secondary structure length: */
runtimeSP->reference_sec_str_length = 0;

/* Allocate the reference secondary structure buffer: */
elementsN = MAXRESIDUES;
runtimeSP->reference_sec_structureP = (char *) calloc (elementsN, char_size);
if (runtimeSP->reference_sec_structureP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate",
		" the reference secondary structure buffer!\n",
		"", "");
	return -25;
	}

/* Allocate memory for reference serial numbers: */
elementsN = MAXRESIDUES;
runtimeSP->reference_serialIP = (int *) calloc (elementsN, int_size);
if (runtimeSP->reference_serialIP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory",
		" for reference residue serial numbers!\n",
		"", "");
	return -26;
	}

/* Allocate memory for reference numeric residue codes: */
elementsN = MAXRESIDUES;
runtimeSP->reference_residue_codeIP =
			(int *) calloc (elementsN, int_size);
if (runtimeSP->reference_residue_codeIP == NULL)
        {
        ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory",
		" for reference numeric residue codes!\n",
		"", "");
        return -27;
        }

/* Allocate memory for reference hydrophobicity values: */
elementsN = MAXRESIDUES;
runtimeSP->reference_hydrophobicityP =
				(double *) calloc (elementsN, double_size);
if (runtimeSP->reference_hydrophobicityP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		"Failed to allocate memory",
		" for reference hydrophobicity values!\n",
		"", "");
	return -28;
	}

/* Initialize the zoom factor: */
runtimeSP->zoom_factor = 2;

/* Initialize  the sequence offsets.  Some  sequences */
/* are long,  so they  will not fit into main window. */
/* This may also happen if large zoom factor is used. */
runtimeSP->sequence_offset = 0;
runtimeSP->reference_offset = 0;

/* Initialize the segment width and the minimal */
/* score  (used when comparing  two sequences): */
runtimeSP->segment_width = SEGMENT_WIDTH;
runtimeSP->minimal_score = MINIMAL_SCORE;

/* Initialize the hydrophobicity scale index (default: Eisenberg scale, 2): */
runtimeSP->hydrophobicity_scaleI = 2;

/* Initialize the helix step angle, in degrees: */
runtimeSP->helix_step_angle = 100.0;

/* Initialize the arc (extent) angle, in degrees: */
runtimeSP->arc_angle = 10.0;

/* Initialize the sphere radius: */
runtimeSP->sphere_radius = 8.0;

/* Initialize the sliding window width: */
runtimeSP->sliding_window_width = 11;

/* Initialize flags related to hydrophobicity functions: */
runtimeSP->average_hydrophobicityF  = 0;
runtimeSP->weighted_hydrophobicityF = 0;
runtimeSP->hydrophobic_momentF      = 0;
runtimeSP->sided_hydrophobicityF    = 0;
runtimeSP->function1F		    = 0;
runtimeSP->function2F		    = 0;
runtimeSP->function3F		    = 0;
runtimeSP->function4F		    = 0;
runtimeSP->function5F		    = 0;
runtimeSP->function6F		    = 0;
runtimeSP->function7F		    = 0;

/* Initialize range indices: */
runtimeSP->range_startI = 0;
runtimeSP->range_endI   = 0;

/* Initialize docking area width and docking cell width: */
runtimeSP->docking_area_width = DOCKING_AREA_WIDTH;
runtimeSP->docking_cell_width = DOCKING_CELL_WIDTH;

/* Initialize  the number of cells  across */
/* docking area; this number must be even. */
d = DOCKING_AREA_WIDTH / DOCKING_CELL_WIDTH;
width = (int) d;
if (width % 2) width++;
runtimeSP->docking_matrix_width = width;

/* Allocate the storage  for template atoms.  These atoms  will be */
/* used to create peptides, replace residues, insert residues etc. */
elementsN = MAXTEMPLATEATOMS;
runtimeSP->template_atomSP = (AtomS *) calloc (elementsN, atom_struct_size);
if (runtimeSP->template_atomSP == NULL)
        {
        ErrorMessage_ ("garlic", "InitRuntime_", "",
                "Failed to allocate memory for template atoms!\n",
                "", "", "");
	runtimeSP->max_template_atomsN = 0;
        return -29;
        }
else runtimeSP->max_template_atomsN = MAXTEMPLATEATOMS;

/* Try to open the file residues.pdb, which should contain the */
/* residue templates .  The first directory  to be searched is */
/* the current working directory, the second is  $HOME/garlic, */
/* the fourth is  /usr/local/lib/garlic and the last directory */
/* to be searched for  residues.pdb  file is  /usr/lib/garlic. */
if ((template_fileP = OpenTemplateFile_ ()) == NULL)
	{
	runtimeSP->template_atomsN = 0;
	runtimeSP->template_residuesN = 0;
	}

/* Read the template file: */
else 
	{
	ReadTemplateFile_ (runtimeSP, template_fileP, configSP);
	fclose (template_fileP);
	}

/* Reset the blur flag: */
runtimeSP->blurF = 0;

/* Initialize the size of blur rectangle: */
runtimeSP->blur_width  = configSP->blur_default_width;
runtimeSP->blur_height = configSP->blur_default_height;

/* Allocate the storage for  the array of beta cells on */
/* the surface of the auxiliary cylinder. This cylinder */
/* is used to find position and  orientation of bilayer */
/* membrane  with respect to  the beta  barel  protein. */
runtimeSP->beta_cellsN = BETA_CELLS_ALONG_AXIS * BETA_CELLS_IN_RING;
elementsN = runtimeSP->beta_cellsN;
runtimeSP->beta_cellSP = (BetaCellS *) calloc (elementsN, beta_cell_size);
if (runtimeSP->beta_cellSP == NULL)
	{
	ErrorMessage_ ("garlic", "InitRuntime_", "",
		       "Failed to allocate memory for beta cells!\n",
		       "", "", "");
	return -30;
	}

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

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


