/* Copyright (C) 2000 Damir Zucic */

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

				read_fasta.c

Purpose:
	Read a single chain sequence from FASTA file. Return negative
	value if file is not in FASTA format.  The letters J, O and U
	are translated as UNK (unknown) residue, as well as letter X.

Input:
	(1) Pointer to RuntimeS structure.
	(2) Pointer to input file name.

Output:
	(1) Sequence stored to the sequence buffer.
	(2) Return value.

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

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

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

FILE		*OpenFileForReading_ (char *);
void		InitHyphob_ (RuntimeS *);

/*======read FASTA file (sequence in one letter code):=======================*/

int ReadFasta_ (RuntimeS *runtimeSP, char *file_nameP)
{

int		max_length;
char		lineA[STRINGSIZE];
FILE		*fileP;
int		line_length;
int		n;
int		lineI = 0;
char		*P;
int		columnI;
size_t		residueI = 0;
size_t		offset;

/* The maximal residue name length: */
max_length = RESNAMESIZE - 1;

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

/* 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 -1;
			}
		else
			{
			lineI++;
			continue;
			}
		}

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

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

	/* Parse line: */
	for (columnI = 0; columnI < line_length; columnI++)
		{
		/* Check is there enough place left in the buffer: */
		offset = max_length * residueI;
		if (offset > runtimeSP->sequence_buffer_size - 10 * max_length)
			{
			strcpy (runtimeSP->messageA, "Sequence too long!");
			runtimeSP->message_length =
					strlen (runtimeSP->messageA);
			fclose (fileP);
			return -2;
			}

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

		/* Pointer to  the position where */
		/* residue name should be copied: */
		P = runtimeSP->sequenceP + offset;

		/* Identify residue: */
		switch (n)
			{
			case 'A':
				strncpy (P, "ALA", max_length);
				break;

			case 'B':
				strncpy (P, "ASX", max_length);
				break;

			case 'C':
				strncpy (P, "CYS", max_length);
				break;

			case 'D':
				strncpy (P, "ASP", max_length);
				break;

			case 'E':
				strncpy (P, "GLU", max_length);
				break;

			case 'F':
				strncpy (P, "PHE", max_length);
				break;

			case 'G':
				strncpy (P, "GLY", max_length);
				break;

			case 'H':
				strncpy (P, "HIS", max_length);
				break;

			case 'I':
				strncpy (P, "ILE", max_length);
				break;

			case 'J':
				strncpy (P, "UNK", max_length);
				break;

			case 'K':
				strncpy (P, "LYS", max_length);
				break;

			case 'L':
				strncpy (P, "LEU", max_length);
				break;

			case 'M':
				strncpy (P, "MET", max_length);
				break;

			case 'N':
				strncpy (P, "ASN", max_length);
				break;

			case 'O':
				strncpy (P, "UNK", max_length);
				break;

			case 'P':
				strncpy (P, "PRO", max_length);
				break;

			case 'Q':
				strncpy (P, "GLN", max_length);
				break;

			case 'R':
				strncpy (P, "ARG", max_length);
				break;

			case 'S':
				strncpy (P, "SER", max_length);
				break;

			case 'T':
				strncpy (P, "THR", max_length);
				break;

			case 'U':
				strncpy (P, "UNK", max_length);
				break;

			case 'V':
				strncpy (P, "VAL", max_length);
				break;

			case 'W':
				strncpy (P, "TRP", max_length);
				break;

			case 'X':
				strncpy (P, "UNK", max_length);
				break;

			case 'Y':
				strncpy (P, "TYR", max_length);
				break;

			case 'Z':
				strncpy (P, "GLX", max_length);
				break;

			default:
				;
			}

		/* Update the residue index: */
		residueI++;
		}

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

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

/* Store the number of residues: */
runtimeSP->residuesN = residueI;

/* Reinitialize serial numbers: */
for (residueI = 0; residueI < runtimeSP->residuesN; residueI++)
	{
	*(runtimeSP->serialIP + residueI) = residueI + 1;
	}

/* Reinitialize disulfide flags: */
for (residueI = 0; residueI < runtimeSP->residuesN; residueI++)
	{
	*(runtimeSP->disulfideFP + residueI) = 0;
	}

/* Initialize hydrophobicity values: */
InitHyphob_ (runtimeSP);

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

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


