/* Copyright (C) 2001 Damir Zucic */

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

				load_sec_structure.c

Purpose:
	Load secondary structure from a file.

Input:
	(1) Pointer to RuntimeS structure.

Output:
	(1) Secondary structure stored to the main sec. str. buffer.
	(2) Return value.

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

Notes:
	(1) The file which contains  the secondary structure  should be
	    written in a sort of FASTA format (one letter code, but the
	    first character in title line is '>').  The lines beginning
	    with # are treated as comments. Empty lines are ignored.

	(2) The original  command string  is used  because the copy was
	    converted to uppercase. File names are case sensitive!

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

#include <stdio.h>

#include <string.h>
#include <ctype.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 *);
FILE		*OpenFileForReading_ (char *);

/*======load secondary structure from file:==================================*/

int LoadSecondaryStructure_ (RuntimeS *runtimeSP)
{
int		i;
char		lineA[STRINGSIZE];
char		*remainderP;
char		tokenA[STRINGSIZE];
FILE		*fileP;
int		line_length;
int		n;
int		lineI = 0;
char		*P;
int		code;
int		columnI;
size_t		codeI = 0;

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

/* Copy the original command string: */
strncpy (lineA, runtimeSP->curr_commandA, STRINGSIZE - 1);
lineA[STRINGSIZE - 1] = '\0';

/* Skip two tokens: */
remainderP = ExtractToken_ (tokenA, STRINGSIZE, lineA, " \t\n");
if (!remainderP) return -1;
remainderP = ExtractToken_ (tokenA, STRINGSIZE, remainderP, " \t\n");
if (!remainderP) return -2;

/* The third token should contain the file name: */
remainderP = ExtractToken_ (tokenA, STRINGSIZE, remainderP, " \t\n");
if (!remainderP)
	{
	strcpy (runtimeSP->messageA, "File name missing!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return -3;
	}

/* Try to open file: */
fileP = OpenFileForReading_ (tokenA);
if (fileP == NULL)
	{
	strcpy (runtimeSP->messageA, "Failed to open file!");
	runtimeSP->message_length = strlen (runtimeSP->messageA);
	return -4;
	}

/* Read file, line by line: */
while (fgets (lineA, STRINGSIZE, fileP))
	{
	/* Remove the trailing newline: */
	line_length = strlen (lineA);
	n = line_length - 1;
	if (line_length > 0)
		{
		if (lineA[n] == '\n') lineA[n] = '\0';
		line_length--;
		}

	/* Empty lines are ignored: */
	if (line_length == 0) continue;

	/* Lines beginning with # are treated as comments: */
	if (lineA[0] == '#') continue;

	/* If the first character of the first useful line is */
	/* not '>', input file format is not FASTA compliant. */
	/* If it is, the line contains a protein description. */
	if (lineI == 0)
		{
		if (lineA[0] != '>')
			{
			fclose (fileP);
			return -5;
			}
		else
			{
			lineI++;
			continue;
			}
		}

	/* If the first character of  a line  which is not  the first useful */
	/* line is '>', this signals another structure. Break from the loop: */
	else
		{
		if (lineA[0] == '>') break;
		}

	/* Convert to uppercase: */
	P = lineA;
	while ((code = *P++) != '\0') *(P - 1) = toupper (code);

	/* Parse line: */
	for (columnI = 0; columnI < line_length; columnI++)
		{
		/* Check is there enough place left in the buffer: */
		if (codeI > MAXRESIDUES - 10)
			{
			strcpy (runtimeSP->messageA,
				"Secondary structure too long!");
			runtimeSP->message_length =
					strlen (runtimeSP->messageA);
			fclose (fileP);
			return -6;
			}

		/* The current character: */
		code = lineA[columnI];

		/* Identify residue: */
		switch (code)
			{
			/* Valid codes: */
			case 'C':
			case 'E':
			case 'G':
			case 'H':
			case 'T':
				break;

			/* Separators: */
			case ' ':
			case ',':
			case '\t':
				continue;
				break;

			/* Bad codes: */
			default:
				sprintf (runtimeSP->messageA,
					 "Bad code found in input file!");
				strcat (runtimeSP->messageA,
					" Valid codes: C E G H T.");
				runtimeSP->message_length =
					strlen (runtimeSP->messageA);
				return -7;
			}

		/* Store the secondary structure code: */
		P = runtimeSP->sec_structureP + codeI;
		*P = code;

		/* Increment the counter: */
		codeI++;
		}

	/* Update the line index (only useful lines are counted): */
	lineI++;
	}

/* Close file: */
fclose (fileP);

/* Store the number of secondary structure codes: */
runtimeSP->sec_structure_length = codeI;

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

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


