/*  Copyright 1997-2003: 
     Fred Hutchinson Cancer Research Center, Seattle, WA, USA */
/*      format_block.c                                    */

/* SP May 96' - modifications :
  Made the sequence names and start positions optional. If the fields 
  (windows) for these are totaly empty the program will give default values.
  Fixed spelling mistake and bug in message when a sequence is too short.
  SP July 19 96. 
     removed tags ('-') as suffixes to weight type and scale parameters
     when calling blweight. After this program was updated its behavoir
     changed.
  SP Aug 27 96.
     added fasta format reading from sequences box.
11/15/97 Moved home directory defs to homedir.h - but always executes from
	 btest anyway (??)
12/ 8/98 Execute logo.csh instead of logoscript.www.BFormatter
         Execute pssm.sh instead of PSSMscript.www
         Added btest_flag
 6/20/99 Increased sequence name length from 10 to 18
 2/ 8/00 Allow ACs of 7-10 chars
12/23/06 Increased sequence name length from 18 to 20
*/

/*===========================================================================*/
/* blimps stuff */
#define EXTERN

#include <blocksprogs.h>

#define BTEST_HOME   "/home/btest"
#define BLOCKS_HOME  "/home/blocks"

typedef struct {
    char *name;
    char *val;
} entry;

/* from util.c */
char *makeword(char *line, char stop);
char *fmakeword(FILE *f, char stop, int *len);
char x2c(char *what);
void unescape_url(char *url);
void plustospace(char *str);
 
entry entries[10000];

#define BLOCK_SEQUENCE_INCREASE_SIZE 50  /* default number of sequences to allocate */
#define MIN_BLOCK_LENGTH 3
#define MINAC 7
#define MAXAC 10

#define UNKNOWN_SEQ_NAME "unknown"
#define UNKNOWN_SEQ_POS 9999


#define TMP_SUBDIR   "/tmp"
#define BIN_SUBDIR   "/bin"
#define LOG_SUBDIR   "/log"

char extblock_stdout[LARGE_BUFF_LENGTH];
char Block_file[LARGE_BUFF_LENGTH];
char Block_fileNW[LARGE_BUFF_LENGTH];
char Blweight[LARGE_BUFF_LENGTH];
char Weight_type[LARGE_BUFF_LENGTH];
char Weight_scale[LARGE_BUFF_LENGTH];
char log_dir[LARGE_BUFF_LENGTH];
char log_file[LARGE_BUFF_LENGTH];
char error_file[LARGE_BUFF_LENGTH];
char tmp_dir[LARGE_BUFF_LENGTH];
char home_dir[LARGE_BUFF_LENGTH];
char buf[LARGE_BUFF_LENGTH];

int btest_flag;
int pid;

int no_seq_names, no_seq_pos ;

entry *ID_Ptr = NULL;
entry *AC_Ptr = NULL;
entry *MIN_DIST_Ptr = NULL;
entry *MAX_DIST_Ptr = NULL;
entry *DE_Ptr = NULL;
entry *MA_METH_Ptr = NULL;
entry *MA_WIDTH_Ptr = NULL;
entry *MA_SEQS_Ptr = NULL;
entry *SEQ_NAMES_Ptr = NULL;
entry *SEQ_POS_Ptr = NULL;
entry *SEQS_Ptr = NULL;

void read_startup_info()
{
  int i;
  char *script, *ptr;
  FILE *logdate, *curr_year_month;

  script = getenv("SCRIPT_NAME");

  btest_flag = 0;
  ptr = getenv("BLOCKS_HOME");
  if (ptr != NULL)
  {
     sprintf(home_dir, "%s", ptr);
  }
  else
  {
     if (strstr(script, "btest")) {
       sprintf(home_dir, "%s", BTEST_HOME);
       btest_flag = 1;
     }
     else if (strstr(script, "blocks")) {
       sprintf(home_dir, "%s", BLOCKS_HOME);
     }
     else {
    /* problems, raise an error */
    /* this is the only way I know how to get mosaic to raise an error. */
       printf(0);
       exit(1);
     }
   }

  pid = getpid();
  curr_year_month = popen("date '+%y%m'", "r");
  logdate = popen("date \"+%y%m%d\"", "r");

  sprintf(extblock_stdout, "%s%s/extblock_stdout", home_dir, BIN_SUBDIR);
  sprintf(Blweight, "%s%s/blweight", home_dir, BIN_SUBDIR);
  sprintf(Block_fileNW, "%s%s/%d.blk.NW.temp", home_dir, TMP_SUBDIR, pid);
  sprintf(Block_file, "%s%s/%d.blk", home_dir, TMP_SUBDIR, pid);
  sprintf(Weight_type, "P");
  sprintf(Weight_scale, "M");
  fgets(buf, LARGE_BUFF_LENGTH, curr_year_month);
  remove_trailing_whitespace(buf);
  sprintf(log_dir, "%s%s/%s", home_dir, LOG_SUBDIR, buf);
  fgets(buf, LARGE_BUFF_LENGTH, logdate);
  remove_trailing_whitespace(buf);
  sprintf(tmp_dir, "%s%s", home_dir, TMP_SUBDIR);

  pclose(curr_year_month);
  pclose(logdate);
}   /*  end of read_startup_info */


int parse()
{
/* parse the input */

  register int i,num_entries=0;
  char *entry_string;
  int cl;

  /* check that there is something to use. */
  entry_string = getenv("QUERY_STRING");

/*
  if (entry_string == NULL) 
     {
     printf("No query information to decode.\n");
     exit(1);
     }
*/

  /* parse the query string into individual entries */

  cl = atoi(getenv("CONTENT_LENGTH"));

  for(i=0;cl && (!feof(stdin));i++) 
     {
     num_entries=i;
     entries[i].val = fmakeword(stdin,'&', &cl);
     plustospace(entries[i].val);
     unescape_url(entries[i].val);
     entries[i].name = makeword(entries[i].val,'=');

     if (!strncmp(entries[i].name, "ID", 14)) 
        {
	ID_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "AC", 14)) 
        {
	AC_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "MIN_DIST", 14)) 
        {
	MIN_DIST_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "MAX_DIST", 14)) 
        {
	MAX_DIST_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "DE", 14)) 
        {
	DE_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "MA_METH", 14)) 
        {
	MA_METH_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "MA_WIDTH", 14)) 
        {
	MA_WIDTH_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "MA_SEQS", 14)) 
        {
	MA_SEQS_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "SEQ_NAMES", 14)) 
        {
	SEQ_NAMES_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "SEQ_POS", 14)) 
        {
	SEQ_POS_Ptr = &entries[i]; 
        }

     if (!strncmp(entries[i].name, "SEQS", 14)) 
        {
	SEQS_Ptr = &entries[i]; 
        }

    }


  return num_entries;
} /*  end of parse */


void clean_temp_files()
{
/* weighted block file won't be deleted so it can be used to make a logo */
  sprintf(buf, "rm -f %s%s/%d*temp", home_dir, TMP_SUBDIR, pid); 
  system(buf);
}

/* 
 * resize_block_sequences
 *   Increases the memory for the storage of the sequences of a block.
 *   Parameter:
 *     Block *block: the block to resize
 *   Error codes: none
 */

static void resize_block_sequences(block)
     Block *block;
{
  int i;
  void *tmp_ptr;		/* don't want to ruin pointer in case there */
				/* is a repeated realloc call */

  /* announce info */
  sprintf(ErrorBuffer, 
	  "Allocating more space for sequences in block %s.\n",
	  block->number);
/*  ErrorReport(INFO_ERR_LVL); */ /* turned off SP */

  /* get more space */
  block->max_sequences += BLOCK_SEQUENCE_INCREASE_SIZE;
  
  CheckMem(
	   tmp_ptr = 
	   (Sequence *) realloc(block->sequences,
				sizeof(Sequence) *
				block->max_sequences)
	   );
  block->sequences = (Sequence *) tmp_ptr;
  
  CheckMem(
	   tmp_ptr = 
	   (Residue *) realloc(block->sequences[0].sequence,
			       sizeof(Residue) *
			       block->width *
			       block->max_sequences)
	   );
  block->sequences[0].sequence = (Residue *) tmp_ptr;

  CheckMem(
	   tmp_ptr = 
	   (Residue **) realloc(block->residues,
				sizeof(Residue *) *
				block->max_sequences)
	   );
  block->residues = (Residue **) tmp_ptr;
  
  /* re-initialize sequences and residues, same data, just different place */
  for(i=0; i<block->max_sequences; i++) {
    block->sequences[i].length = block->width;
    block->sequences[i].sequence = 
      &(block->sequences[0].sequence[i * block->width]);
    block->residues[i] = 
      &(block->sequences[0].sequence[i * block->width]);
  }
}


void make_block()
{
  FILE  *bfp ;
  Block *block ;
  char  string[LARGE_BUFF_LENGTH], string2[SMALL_BUFF_LENGTH] ;
  char  chr, end_chr, *ptr ;
  int   stringlen, i, seqs_start, j, k, rc ;
  Sequence *sequence_pointer ;
  Residue  *residue_pointer ;
  Boolean is_fasta = FALSE, seq_header = FALSE ;

  /* check that obligatory fields have something */

/* Note if sequence names and start positions not supplied */
  if (SEQ_NAMES_Ptr->val[0] == NULL) no_seq_names = 1 ;
  else                               no_seq_names = 0 ; 

  if (SEQ_POS_Ptr->val[0] == NULL) no_seq_pos = 1 ;
  else                             no_seq_pos = 0 ; 

  if (SEQS_Ptr->val[0] == NULL) 
    {
      printf("<H1>Error</H1>\n");
      printf("No sequences specified.<P>\n");
      exit(0);
    }

                                                /* allocate space for block */
    CheckMem(block = (Block *) malloc(sizeof(Block))) ;

        /* if first non blank char is '>' the sequences are in FASTA format */
    for (seqs_start=0; 
         (chr = SEQS_Ptr->val[seqs_start]) != '\0' && 
         chr != '>' && isspace(chr);
         seqs_start++) ;
    if (chr == '>') 
       {
       is_fasta = TRUE ;
       seqs_start++ ;                                          /* skip '>' */
       }
    else            
       {
       is_fasta = FALSE ;
       seqs_start = 0 ;
       }

                  /* get length of first sequence to use as alignment width */
    if (is_fasta)
       {
                                         /* find begining of first sequence */
       for (ptr=strchr(SEQS_Ptr->val, '>'); *ptr != '\n' && *ptr != '\0';
            ptr++) ;
       if (*ptr == '\0')
          {
          printf("<H1>Error</H1>\n");
          printf("No sequences specified.<P>\n");
          exit(0);
          }
       else
	  {
          ptr++ ;
          end_chr = '>' ;
          seq_header = TRUE ;

          if (!(no_seq_names))
	     {
             printf("<H2>Warning</H2>\n");
             printf("Sequence names box is used and the alignment is in FASTA format.<BR>\n") ;
             printf("Sequence names will be taken from the alignment<BR>\n") ;
             printf("(first word in the sequence header lines -<BR>\n") ;
             printf("'><B>seq_name</B> 123 aa example protein').<P>\n") ;
             }
	  }
       }
    else
       {
       ptr = SEQS_Ptr->val ;           
       end_chr = '\n' ;
       seq_header = FALSE ;
       }


    for(block->width = 0;
        *ptr != end_chr && *ptr != '\0'; ptr++)
      if (isalpha(*ptr) || *ptr == '-') block->width++ ;

    if (block->width > LARGE_BUFF_LENGTH)
       {
       printf("<H1>Error</H1>\n");
       printf("Judging by the first sequence length (%d) the alignment is too long. The maximal length is %d.<P>\n", 
              block->width, LARGE_BUFF_LENGTH);
       exit(0);
       }

    if (block->width < MIN_BLOCK_LENGTH)
       {
       printf("<H1>Error</H1>\n");
       printf("Judging by the first sequence length (%d) the alignment is too short. The minimal length is %d.<P>\n", 
              block->width, MIN_BLOCK_LENGTH);
       exit(0);
       }

    if (MA_WIDTH_Ptr->val[0] != NULL && 
        block->width != atoi (MA_WIDTH_Ptr->val))
       {
       printf("<H2>Warning</H2>\n");
       printf("The alignment width you gave (%s) is different than the first sequence length (%d).<P>\n", 
              MA_WIDTH_Ptr->val, block->width);
       }


                                            /* allocate memory for sequences*/

   block->num_clusters = block->max_clusters = 1 ; 
                                 /* since number of sequences not known yet */
   block->max_sequences = BLOCK_SEQUENCE_INCREASE_SIZE ;


                                         /* allocate space for the clusters */
   CheckMem(block->clusters = (Cluster *) 
                             calloc(block->max_clusters, sizeof(Cluster))) ;

                          /* following part adapted from 
                             blimps procedure read_block_body by Bill Alford */

         /* allocate space for all the Sequences of the block sequence array */
         CheckMem(
             sequence_pointer = 
                  (Sequence *) 
		  calloc(block->max_sequences,sizeof(Sequence))) ;

	                             /* initialize the block sequences array */
	 block->sequences = sequence_pointer ;

	                                  /* allocate space for all residues */
	 CheckMem(
             residue_pointer = 
                 (Residue *) 
                 calloc(block->width * block->max_sequences, 
			sizeof(Residue))) ;

	                                /* initialize the residues 2-d array */
	 CheckMem(
             block->residues = 
               (Residue **) calloc(block->max_sequences, sizeof(Residue *))) ;

	                                /* initialize sequences and residues */
         for(j=0; j<block->max_sequences; j++) 
            {
	    sequence_pointer[j].length = block->width;
	    sequence_pointer[j].sequence =
 		              &(residue_pointer[j * block->width]) ;
	    block->residues[j] = 
                              &(residue_pointer[j * block->width]) ;
	    }

 /* get block sequence data */
 /* sequences */
 
    stringlen = (int) strlen(SEQS_Ptr->val) ;

    block->num_sequences = 0;
    j = 0 ;

             /* go along the string containing all the sequence-window data */
    for (i=seqs_start; i<=stringlen; i++)
      if (seq_header)
	 {
                                                            /* skip blanks */
         for(; isspace(SEQS_Ptr->val[i]) && SEQS_Ptr->val[i] != '/n' && 
               SEQS_Ptr->val[i] != '/0'; i++) ;
         if (SEQS_Ptr->val[i] == '/n')      /* no name is found in line */
             sprintf(block->sequences[block->num_sequences].name, 
                     "%s%d", UNKNOWN_SEQ_NAME, block->num_sequences+1) ;
         else
                        /* copy first 20 chars or until a space is reached */
         for(k=0; !(isspace(SEQS_Ptr->val[i])) && k<20 &&
                  SEQS_Ptr->val[i] != '/n' ; i++, k++) 
            block->sequences[block->num_sequences].name[k] = SEQS_Ptr->val[i];

                                                            /* end string */
         block->sequences[block->num_sequences].name[k] = '\0' ;

                                   /* move along until the end of the line */
         for(; SEQS_Ptr->val[i] != '\n' && SEQS_Ptr->val[i] != '\0'; i++) ;
                          /* if end of string reached - sequence is missing */
         if (SEQS_Ptr->val[i] != '\n')
	    {
            printf("<H1>Error</H1>\n");
            printf("Sequence %d not found.<P>\n", block->num_sequences+1) ;
            exit(0);            
            }

         seq_header = FALSE ;
         }
                      /* else-if end of sequence-string reached process it */
/* end of sequence is end of string OR the end-character (eol or >) + 
   checking that the end-chararcter is precede by an eol for fasta seqs */
      else if (SEQS_Ptr->val[i] == '\0' ||
          (SEQS_Ptr->val[i] == end_chr && 
           (!(is_fasta) || SEQS_Ptr->val[i-1] == '\n')) )
	 {
         if (j==0)
            {
                              /* skip until end of string or no space char */
            while(isspace(SEQS_Ptr->val[i]) && SEQS_Ptr->val[i] != '\0') ;
 /* if we are the end-of-string this is just an extra line beyond the seqs */
            if (SEQS_Ptr->val[i] == '\0') break ;
            else
               {
               printf("<H1>Error</H1>\n");
               printf("Sequence %d not found.<P>\n", 
                      block->num_sequences+1) ;
               exit(0);
	       }
            }
         string[j] = '\0' ;

         if (block->max_sequences <= block->num_sequences+1) 
            resize_block_sequences(block) ;

	                                            /* process the sequence */

    /* next part adopted from blimps  procedure next_cluster by Bill Alford */
                     /* read the sequence from the string into the Sequence */

         rc = read_sequence(&(block->sequences[block->num_sequences]), 
                            AA_SEQ, 0, string) ; 
				   /* the Sequence, sequence type, starting */
   				   /* position, string with the sequence    */

                                      /* check to see if there was an error */
         if (rc < 0) 
            {
                      /* Error, more residues in the sequence than expected */
            printf("<H2>Warning</H2>\n");
            printf("Error reading sequence %d. %d more residues in the sequence than the expected %d.<P>\n",
                   block->num_sequences+1, -rc, 
                   block->sequences[block->num_sequences].length) ;
            }
         else if (rc < block->sequences[block->num_sequences].length) 
            {
            if (rc < MIN_BLOCK_LENGTH)
               {
               printf("<H1>Error</H1>\n");
               printf("Sequence (%d) is too short (%d). The minimal length is %d.<P>\n", 
                      block->num_sequences+1, rc, MIN_BLOCK_LENGTH);
               exit(0);
	       }

          /* Error, not enough residues for the sequence, filling with gaps */
            printf("<H2>Warning</H2>\n");
            printf("Error reading sequence %d. It is shorter (%d) than the apparent alignment length. Padding the end of the sequence with gaps.<P>\n",
                   block->num_sequences+1, rc);

                                                       /* filling with gaps */
    	    for(j=rc; j<block->sequences[block->num_sequences].length; j++) 
	       block->sequences[block->num_sequences].sequence[j] = 
                                                                 aa_atob['-'];
	    }
         else if (rc > block->sequences[block->num_sequences].length) 
            {
              /* BIG Error, an undocumented return value from read_sequence */
            printf("<H1>Error</H1>\n");
            printf("Error reading sequence %d.<P>\n", block->num_sequences+1);
            exit(0);            
            } /* else, ret_value == seq.length, OK */

                 /* sequences have no weights give all equal weights of 100 */
         block->sequences[block->num_sequences].weight =  100.0 ;

 /* if this is fasta format and it is not the last seq next is a seq header */
         if (is_fasta && SEQS_Ptr->val[i] != '\0') seq_header = TRUE ;

         j = 0 ;
         block->num_sequences++ ;         
         }
      else         /* if end of seq not reached add char to sequence string */
	 {
         string[j++] = SEQS_Ptr->val[i] ;
         }

 /* sequence names */

    if (! (is_fasta)) /* in fasta format sequence names given with sequences*/
    if (no_seq_names) 
       for (i=0; i<block->num_sequences; i++) 
          sprintf(block->sequences[i].name, "%s%d", UNKNOWN_SEQ_NAME, i+1) ;
    else 
       {
       stringlen = (int) strlen(SEQ_NAMES_Ptr->val) ;

/* if the string doesn't end with eol, put one there instead of 
   end-of-string */
       if (SEQ_NAMES_Ptr->val[stringlen-1] != '\n') 
          SEQ_NAMES_Ptr->val[stringlen] = '\n' ;       

       k = 0;
       j = 0 ;

       for (i=0; i<=stringlen; i++)
         if (SEQ_NAMES_Ptr->val[i] != '\n') 
	    {
            if (!isspace(SEQ_NAMES_Ptr->val[i]))
               string[j++] = SEQ_NAMES_Ptr->val[i] ;
            }
         else
	    {
         /* check if this is an "extra" name (with no sequence to attach to) */
            if (k == block->num_sequences) break ;

            if (j==0)
               {
               printf("<H1>Error</H1>\n");
               printf("No name found for sequence %d.<P>\n", 
                      k+1) ;
               exit(0);
               }

            string[j] = '\0' ;

            if (block->max_sequences <= k) 
               resize_block_sequences(block) ;

                                       /* copy up to first 20 chars of name */
            strncpy(block->sequences[k].name,string,20) ;

            j = 0 ;
            k++ ;         
	    }

                        /* check that number of sequence names is equal to 
                                                       number of sequences */
       if (k != block->num_sequences)
          {
          if (k < block->num_sequences) printf("<H1>Error</H1>\n");
          else                          printf("<H2>Warning</H2>\n");
          printf("Number of sequence names (%d) is different than number of sequences (%d).<P>\n", 
                 k, block->num_sequences) ;
          if (k < block->num_sequences) exit(0);
          }
       }


 /* sequence positions */
 
    if (no_seq_pos) for (i=0; i<block->num_sequences; i++) 
       block->sequences[i].position = UNKNOWN_SEQ_POS ;
    else
       {
       stringlen = (int) strlen(SEQ_POS_Ptr->val) ;

/* if the string doesn't end with eol, put one there instead of 
   end-of-string */
       if (SEQ_POS_Ptr->val[stringlen-1] != '\n') 
          SEQ_POS_Ptr->val[stringlen] = '\n' ;       

       k = 0;
       j = 0 ;

       for (i=0; i<=stringlen; i++)
         if (SEQ_POS_Ptr->val[i] != '\n') 
	    {
            if (isalnum(SEQ_POS_Ptr->val[i]))
                string[j++] = SEQ_POS_Ptr->val[i] ;
            }
         else
	    {
  /* check if this is an "extra" position (with no sequence to attach to) */
            if (k == block->num_sequences) break ;

            if (j==0)
               {
               printf("<H1>Error</H1>\n");
               printf("No start position found for sequence %d.<P>\n", 
                      k+1) ;
               exit(0);
               }
            string[j] = '\0' ;

            if (block->max_sequences <= k+1) resize_block_sequences(block) ;

            block->sequences[k].position = atoi(string) ;

            j = 0 ;
            k++ ;         
	    }

                /* check that number of sequence start positions is equal to 
                   number of sequences */
       if (k != block->num_sequences)
          {
          if (k < block->num_sequences) printf("<H1>Error</H1>\n");
          else                          printf("<H2>Warning</H2>\n");
          printf("Number of sequence start positions (%d) is different than number of sequences (%d).<P>\n", 
                 k, block->num_sequences) ;
          if (k < block->num_sequences) exit(0);
          }
       }

                       /* check that actual number of sequences is equal to 
                          what the user gave */
    if (MA_SEQS_Ptr->val[0] != NULL && 
        block->num_sequences != atoi (MA_SEQS_Ptr->val))
       {
       printf("<H2>Warning</H2>\n");
       printf("The number of sequences you gave (%s) is different from the number found (%d).<P>\n", 
              MA_SEQS_Ptr->val, block->num_sequences);
       }

          /* assign the sequences to the cluster (space has been allocated) */

    block->clusters[0].num_sequences = block->num_sequences ;

    block->clusters[0].sequences = &(block->sequences[0]) ;

 /* get block header data */

    if (ID_Ptr->val[0] == NULL) 
       strcpy(block->id, "None") ;
    else
       strncpy(block->id,ID_Ptr->val, SMALL_BUFF_LENGTH) ;

    strcat(block->id, "; BLOCK") ;


    if (AC_Ptr->val[0] == NULL) 
    {
       strncpy(block->number, block->sequences[0].name, MAXAC) ;
    }
    else
    { strcpy(block->number,AC_Ptr->val) ;   }
    block->number[MAXAC] = '\0';
    if (strlen(block->number) < MINAC)
    {
       for (i=strlen(block->number); i< MINAC; i++) block->number[i] = 'x';
       block->number[MINAC] = '\0';
    }
    for (i=0; i<strlen(block->number); i++)
    {
       if (!isalnum(block->number[i])) block->number[i] = 'x';
    }

    strcpy(block->ac,block->number) ;

    if (MIN_DIST_Ptr->val[0] == NULL) 
       {
       j = 10000 ;
       for(i=0; i<block->num_sequences; i++) 
         if (block->sequences[i].position < j) j = block->sequences[i].position ;
       }
    else j = atoi(MIN_DIST_Ptr->val) ;

    sprintf(block->ac, "%s; distance from previous block = (%d",
            block->ac, j) ;


    if (MAX_DIST_Ptr->val[0] == NULL) 
       {
       j = 0 ;
       for(i=0; i<block->num_sequences; i++) 
         if (block->sequences[i].position > j) j = block->sequences[i].position ;
       }
    else j = atoi(MAX_DIST_Ptr->val) ;

    sprintf(block->ac, "%s,%d)",
            block->ac, j) ;
  
    if (DE_Ptr->val[0] == NULL) 
       strcpy(block->de, "None") ;
    else
       strncpy(block->de,DE_Ptr->val, SMALL_BUFF_LENGTH) ;

    if (MA_METH_Ptr->val[0] != NULL) 
       strncpy(block->bl,MA_METH_Ptr->val, SMALL_BUFF_LENGTH-25) ;
    else
       strcpy(block->bl,"Method unspecified") ;

    sprintf(block->bl, "%s; width=%d; seqs=%d;",
            block->bl, block->width, block->num_sequences) ;

    block->motif[0] = '\0';
    block->percentile = 0 ;
    block->strength = 0 ;

    /* open up the block file to write to */
    bfp = fopen(Block_fileNW, "w");

    output_block(block, bfp) ;
      
    free_block(block) ;
    fclose(bfp);
      
} 
  
void weight_block()
{

  sprintf(buf, "%s %s %s %s %s > /dev/null", 
         Blweight, Block_fileNW, Block_file, Weight_type, Weight_scale); 

  if (system(buf)) 
    {
    printf("<H1>Error</H1>\n");
    printf("An error occured weighting the block.\n");
    printf("Please try again at a later time.\n");
    printf("If it fails again contact the maintainer of these pages\n");
    printf("and describe what caused the problem with an example.<P>\n");

    clean_temp_files() ;

    exit(0);
    }
}


void display_output()
{

  FILE  *bfp ;
  Block *block;

  printf("<TITLE>Block Formatter output</TITLE>\n");
  printf("<H1>Block Formatter output</H1>\n");

  printf("Sequences weighted by") ;
  switch (Weight_type[0])
     {
     case 'P' :
        printf(" position-based weights") ;
        break ;
     case 'V' :
        printf(" Voronoi weights") ;
        break ;
     case 'A' :
        printf(" Vingron & Argos weights") ;
        break ;
     case 'C' :
        printf(" %% clustering") ;
        break ;
     }

   printf(". The weights were scaled to 1-100, 100 having most weight.<HR>\n") ;

   if (btest_flag)
   {
      printf("[<A HREF=\"/btest-bin/logo.csh?%s+gif\">block logo</A>",
          Block_file) ;
      printf(" (GIF image)]") ;
      printf(" [<A HREF=\"/btest-bin/pssm.sh?%s\">block PSSM</A>",
          Block_file) ;
      printf(" (<A HREF=\"/btest/help/PSSM_def.html\">what is a PSSM</A>)]") ;
   }
   else
   {
      printf("[<A HREF=\"/blocks-bin/logo.csh?%s+gif\">block logo</A>",
          Block_file) ;
      printf(" (GIF image)]") ;
      printf(" [<A HREF=\"/blocks-bin/pssm.sh?%s\">block PSSM</A>",
          Block_file) ;
      printf(" (<A HREF=\"/blocks/help/PSSM_def.html\">what is a PSSM</A>)]") ;
   }

   printf("<HR>\n") ;

    /* open up the block file */
   bfp = fopen(Block_file, "r");

   block = read_a_block(bfp) ;

   printf("<PRE>");
   output_block(block, stdout) ;
   printf("</PRE>");

   free_block(block) ;
   fclose(bfp);

}


void main(int argc, char *argv[]) {

  printf("Content-type: text/html\n\n\n");


  if(strcmp(getenv("REQUEST_METHOD"),"POST")) {
    printf("This script should be referenced with a METHOD of POST.\n");
    printf("If you don't understand this, see this ");
    printf("<A HREF=\"http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/fill-out-forms/overview.html\">forms overview</A>.%c",10);

    printf("<P>What could have happened is that you just reloaded this page rather than redoing the search.\n");

    printf("<P>If you use NETSCAPE it has a tendency to try to reload a page when you go back to it.  This may be why you have this error.\n");

    exit(1);
  }

  if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) {
    printf("This script can only be used to decode form results. \n");
    exit(1);
  }

  /*    Set file permissions to "rw-rw----"     */
  system("umask 006");

  read_startup_info();

  parse();

  make_block();
  
  weight_block();
  
  display_output(); 

  clean_temp_files() ;

  exit(0) ;
}

