
static char const rcsid [] = "$Id: lend.c,v 1.1 1998/04/21 10:51:13 stojanov Exp $";


/*****************************************************************************/
/*                                                                           */
/* Program: lend (creation of the legend from plain format landmarks files)  */
/*                                                                           */
/* Author: Nikola Stojanovic                                                 */
/*                                                                           */
/* Revision:    16 MAR 97   Version 1.0                                      */
/*                                                                           */
/*                                                                           */
/*   Given a set of files containing motif match sites in the plain form     */
/* landmarks format, the program sorts the data and outputs the legend for   */
/* the match sites, as plain text or PostScript output                       */
/*                                                                           */
/*****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ntl.h"

/*****************************************************************************/
/*                                                                           */
/* Definitions section                                                       */
/*                                                                           */
/*****************************************************************************/


/*****************************************************************************/
/* Definitions of the constants of the program unit                          */
/*****************************************************************************/


#define TEXT_OUTPUT                    1
#define POSTSCRIPT_OUTPUT              2

#define DEFAULT_DIRECTORY              "."
#define DEFAULT_OUTPUT                 TEXT_OUTPUT

#define TFD_REFERENCE                  "g_ref.dat"
#define IMD_REFERENCE                  "referenc"
#define WIN_REFERENCE                  "w_ref.dat"

#define PORTRAIT                       1
#define LANDSCAPE                      2
#define DEFAULT_ORIENTATION            PORTRAIT

#define MAX_INT_LENGTH                 4
#define MIN_FONT                       4
#define MAX_FONT                       16
#define DEFAULT_FONT                   9

#define TFD_INIT                       50
#define IMD_INIT                       50
#define WIN_INIT                       50

#define PSX_TOPLEFT                    50
#define FIRST_PS_PORTRAIT              742
#define FIRST_PS_LANDSCAPE             562

#define PORTRAIT_LINES                 48
#define LANDSCAPE_LINES                38
#define PORTRAIT_FACTOR                10.0
#define LANDSCAPE_FACTOR               10.0

#define FONT                           "Helvetica"

#define PORTRAIT_ENDLINE               540
#define LANDSCAPE_ENDLINE              750

#define LEGEND_SHIFT                   40
#define LEGEND_HEIGHT                  12
#define HEADER_HEIGHT                  5

#define MEDIUM_CUTOFF                  7
#define WIDE_CUTOFF                    14
#define NARROW_SCALE                   0.5
#define MEDIUM_SCALE                   1.0
#define WIDE_SCALE                     1.0

#define PORTRAIT_DISTANCE_FACTOR       1.5
#define LANDSCAPE_DISTANCE_FACTOR      1.5

#define PORTRAIT_TAB_2                 150
#define PORTRAIT_TAB_3                 260
#define PORTRAIT_TAB_4                 410
#define LANDSCAPE_TAB_2                190
#define LANDSCAPE_TAB_3                340
#define LANDSCAPE_TAB_4                540

#define INNER_DIVIDE                   10


/*****************************************************************************/
/* Prototypes of locally used functions of the program unit                  */
/*****************************************************************************/


int lend_collect_data (strlist_ptr directories, strlist_ptr files,
                       plist_ptr *records);
int lend_process_records (strlist_ptr directories, plist_ptr records,
                          strlist_ptr input_files, char *tfd_file,
                          char *imd_file, char *win_file, int output,
                          int orientation, int size);
int lend_assign_references (strlist_ptr directories, plain_ptr sorted,
                            char *tfd_file, char *imd_file, char *win_file);
int lend_text_output (strlist_ptr sources, plist_ptr records);
int lend_postscript_output (strlist_ptr sources, plist_ptr records,
                            int orientation, int size);
void lend_postscript_string (char *output);
bool lend_is_integer (char *string, int *value);

/*****************************************************************************/
/*                                                                           */
/* Code section                                                              */
/*                                                                           */
/*****************************************************************************/


/*****************************************************************************/
/*                                                                           */
/* Procedure: main                                                           */
/*                                                                           */
/* "main" procedure of the program. Receives and analyses the command line   */
/*   parameters, sets the control variables of the program, checks their     */
/*   consistency and passes control to internal procedures which actually    */
/*   process the input data; returns 0 if everything is OK, non-zero status  */
/*   in case of any errors                                                   */

int main (int argc, char **argv)
{
 strlist_ptr input_files, data_directory, new_string, string_scan;
 int arg_count, output; bool output_set; plist_ptr records;
 bool tfd_set, imd_set, win_set; char *tfd_file, *imd_file, *win_file;
 bool size_set, orientation_set; int size, orientation;

 input_files = NULL;
 data_directory = (strlist_ptr) NTL0_ckalloc (sizeof (StrList_Struct));
 data_directory -> string = NTL0_strsave (DEFAULT_DIRECTORY);
 data_directory -> next = NULL;
 tfd_set = imd_set = win_set = FALSE;
 tfd_file = TFD_REFERENCE; imd_file = IMD_REFERENCE; win_file = WIN_REFERENCE;
 output_set = FALSE; output = DEFAULT_OUTPUT;
 size_set = orientation_set = FALSE;
 size = DEFAULT_FONT; orientation = DEFAULT_ORIENTATION;
 
 if (argc < 2) {                       /* Display instructions and terminate */
 
  fprintf (stderr, "usage: %s [<input_file>]+\n", argv [0]);
  fprintf (stderr, "            [-I <directory_path>]*\n");
  fprintf (stderr, "            [-f <tfd_reference_file>]\n");
  fprintf (stderr, "            [-m <imd_reference_file>]\n");
  fprintf (stderr, "            [-w <transfac_reference_file>]\n");
  fprintf (stderr, "            [-t | -g]\n");
  fprintf (stderr, "            [-p | -l]\n");
  fprintf (stderr, "            [-s <font_size>]\n");
  exit (1);
 }
 else {                           /* Some parameters provided - process them */
 
  /* Proceed to extract the command line parameters and create the settings  */
  
  arg_count = 1; while (arg_count < argc) {
 
   if (argv [arg_count] [0] != '-') {       /* Not an "-" option - file name */
    new_string = (strlist_ptr) NTL0_ckalloc (sizeof (StrList_Struct));
    new_string -> string = NTL0_strsave (argv [arg_count]);
    new_string -> next = input_files;
    input_files = new_string;
    arg_count++;
   }
   else if (!strcmp (argv [arg_count], "-I")) {        /* New "include" path */
    arg_count++;
    if (arg_count == argc) {
     fprintf (stderr, "Missing directory path for inclusion.\n"); exit (1);
    }
    else {
     new_string = (strlist_ptr) NTL0_ckalloc (sizeof (StrList_Struct));
     new_string -> string = NTL0_strsave (argv [arg_count]);
     new_string -> next = NULL;

     if (data_directory == NULL) data_directory = new_string;
     else {
      string_scan = data_directory;
      while (string_scan -> next != NULL) string_scan = string_scan -> next;
      string_scan -> next = new_string;
     }
     arg_count++;
    }
   }
   else if (!strcmp (argv [arg_count], "-f")) {        /* TFD reference file */
    arg_count++;
    if (arg_count == argc) {
     fprintf (stderr, "Missing name of TFD reference file.\n"); exit (1);
    }
    else if (tfd_set) {
     fprintf (stderr, "TFD reference file name already set.\n"); exit (1);
    }
    else {
     tfd_set = TRUE; tfd_file = NTL0_strsave (argv [arg_count]); arg_count++;
    }
   }
   else if (!strcmp (argv [arg_count], "-m")) {        /* IMD reference file */
    arg_count++;
    if (arg_count == argc) {
     fprintf (stderr, "Missing name of IMD reference file.\n"); exit (1);
    }
    else if (imd_set) {
     fprintf (stderr, "IMD reference file name already set.\n"); exit (1);
    }
    else {
     imd_set = TRUE; imd_file = NTL0_strsave (argv [arg_count]); arg_count++;
    }
   }
   else if (!strcmp (argv [arg_count], "-w")) {   /* TRANSFAC reference file */
    arg_count++;
    if (arg_count == argc) {
     fprintf (stderr, "Missing name of TRANSFAC reference file.\n"); exit (1);
    }
    else if (win_set) {
     fprintf (stderr, "TRANSFAC reference file name already set.\n"); exit (1);
    }
    else {
     win_set = TRUE; win_file = NTL0_strsave (argv [arg_count]); arg_count++;
    }
   }
   else if (!strcmp (argv [arg_count], "-t")) {       /* Text output request */
    if (output_set) {
     fprintf (stderr, "Output mode already set.\n"); exit (1);
    }
    else { output = TEXT_OUTPUT; output_set = TRUE; arg_count++; }
   }
   else if (!strcmp (argv [arg_count], "-g")) {  /* PostSript output request */
    if (output_set) {
     fprintf (stderr, "Output mode already set.\n"); exit (1);
    }
    else { output = POSTSCRIPT_OUTPUT; output_set = TRUE; arg_count++; }
   }
   else if (!strcmp (argv [arg_count], "-p")) {    /* "Portrait" orientation */
    if (orientation_set) {
     fprintf (stderr, "Output page orientation already set.\n"); exit (1);
    }
    else { orientation = PORTRAIT; orientation_set = TRUE; arg_count++; }
   }
   else if (!strcmp (argv [arg_count], "-l")) {   /* "Landscape" orientation */
    if (orientation_set) {
     fprintf (stderr, "Output page orientation already set.\n"); exit (1);
    }
    else { orientation = LANDSCAPE; orientation_set = TRUE; arg_count++; }
   }
   else if (!strcmp (argv [arg_count], "-s")) {         /* Font size request */
    arg_count++;
    if (arg_count == argc) {
     fprintf (stderr, "Missing size for output font.\n"); exit (1);
    }
    else if (size_set) {
     fprintf (stderr, "Font size for output already set.\n"); exit (1);
    }
    else if (!lend_is_integer (argv [arg_count], &size)) {
     fprintf (stderr, "Illegal value for font size (%s).\n", argv [arg_count]);
     exit (1);
    }
    else if (size < MIN_FONT) {
     fprintf (stderr,
              "WARNING: Requested font (%d) too small - set to min (%d).\n",
              size, MIN_FONT);
     size_set = TRUE; size = MIN_FONT; arg_count++;
    }
    else if (size > MAX_FONT) {
     fprintf (stderr,
              "WARNING: Requested font (%d) too large - set to max (%d).\n",
              size, MAX_FONT);
     size_set = TRUE; size = MAX_FONT; arg_count++;
    }
    else { size_set = TRUE; arg_count++; }
   }
   else {                                     /* Unknown command-line option */
    fprintf (stderr, "Illegal option (%s).\n", argv [arg_count]);
    fprintf (stderr, "usage: %s [<input_file>]+\n", argv [0]);
    fprintf (stderr, "            [-I <directory_path>]*\n");
    fprintf (stderr, "            [-f <tfd_reference_file>]\n");
    fprintf (stderr, "            [-m <imd_reference_file>]\n");
    fprintf (stderr, "            [-w <transfac_reference_file>]\n");
    fprintf (stderr, "            [-t | -g]\n");
    fprintf (stderr, "            [-p | -l]\n");
    fprintf (stderr, "            [-s <font_size>]\n");
    exit (1);
   }
  }
  /* Now check whether all necessary parameters have been provided           */

  if (input_files == NULL) {
   fprintf (stderr, "Must have at least one file to process.\n"); exit (1);
  }

  if ((output == TEXT_OUTPUT) && ((orientation_set) || (size_set))) {
   fprintf (stderr, "WARNING: PostScript settings ignored - text output.\n");
  }
  
  /* If everything is OK so far, proceed to collect data from the files      */

  if (lend_collect_data (data_directory, input_files, &records) < 0) exit (1);
  else if (lend_process_records (data_directory, records, input_files,
                                 tfd_file, imd_file, win_file,
                                 output, orientation, size) < 0)
   exit (1);
  else exit (0);
 }
}


/*****************************************************************************/
/*                                                                           */
/* Procedure: lend_collect_data                                              */
/*                                                                           */
/* Procedure loads the sequences from the specified plain format files and   */
/*   assembles them in a list of internal records for further processing;    */
/*   returns 0 if everything is OK, negative number otherwise                */

int lend_collect_data (strlist_ptr directories, strlist_ptr files,
                       plist_ptr *records)
{
 errind report; char *new_path; strlist_ptr current_path, file_scan;
 plain_ptr sequences; plist_ptr new_record;
 
 *records = NULL;

 for (file_scan = files; file_scan != NULL; file_scan = file_scan -> next) {

  if ((directories == NULL) || ((file_scan -> string) [0] == '/') ||
      ((file_scan -> string) [0] == '~')) {
   if ((report = NTL2_Load_Plain (file_scan -> string, &sequences)) != NULL) {
    fprintf (stderr, "Can't open sequences file '%s' (%s).\n",
                     file_scan -> string, report -> message);
    return -1;
   }
   else if (sequences == NULL) {        /* File found, but nothing retrieved */
    fprintf (stderr, "WARNING: Empty file '%s'.\n", file_scan -> string);
   }
  }
  else {                    /* Directory path(s) provided, try them in order */
   current_path = directories; sequences = NULL;
   while ((sequences == NULL) && (current_path != NULL)) {
    new_path = NTL0_ckalloc ((strlen (current_path -> string) + 2 +
                              strlen (file_scan -> string)) * sizeof (char));
    strcpy (new_path, current_path -> string);
    if ((file_scan -> string) [0] != '/') strcat (new_path, "/");
    strcat (new_path, file_scan -> string);
    
    if ((report = NTL2_Load_Plain (new_path, &sequences)) != NULL) {
     sequences = NULL; current_path = current_path -> next;
    }
    free (new_path);
   }
   if (report != NULL) {                       /* File not found on any path */
    fprintf (stderr, "Can't open sequences file '%s' (%s).\n",
                     file_scan -> string, report -> message);
    return -2;
   }
   else if (sequences == NULL) {       /* File found, but nothing retrieved */
    fprintf (stderr, "WARNING: Empty file '%s'.\n", file_scan -> string);
   }
  }
  new_record = (plist_ptr) NTL0_ckalloc (sizeof (Plist_Struct));
  new_record -> lines = sequences;
  new_record -> from = 0;
  new_record -> to = 0;
  new_record -> start_count = 0;
  new_record -> stop_count = 0;
  new_record -> consensus = NULL;
  new_record -> next = *records;
  *records = new_record;
 }
 return 0;
}


/*****************************************************************************/
/*                                                                           */
/* Procedure: lend_process_records                                           */
/*                                                                           */
/* Procedure rearranges (sorts, and then merges overlaps) the received       */
/*   lists of records, gets the full reference citations for them and        */
/*   displays them in the specified format; returns a negative number if     */
/*   any errors were encountered in the process, 0 otherwise                 */

int lend_process_records (strlist_ptr directories, plist_ptr records,
                          strlist_ptr input_files, char *tfd_file,
                          char *imd_file, char *win_file, int output,
                          int orientation, int size)
{
 errind erret; plain_ptr sorted; plist_ptr merged;

 /* Sort and flatten all line records contained in the input list first      */
 
 if ((erret = NTL1_Sort_Plain (&records, &sorted)) != NULL) {
  fprintf (stderr, "Can't merge the lists (%s).\n", erret -> message);
  return -11;
 }
 /* Assign the full reference text to the records in the flattened list      */

 if (lend_assign_references (directories, sorted,
                             tfd_file, imd_file, win_file) < 0) return -12;

 /* Merge the overlapping data into blocks of their own - separate blocks    */

 if ((erret = NTL1_Compress_Plain (&sorted, &merged)) != NULL) {
  fprintf (stderr, "Can't compress overlaps (%s).\n", erret -> message);
  return -12;
 }
 /* Proceed to output the data, in the requested format                      */

 if (output == TEXT_OUTPUT)
  return lend_text_output (input_files, merged);
 else return lend_postscript_output (input_files, merged, orientation, size);
}


/*****************************************************************************/
/*                                                                           */
/* Procedure: lend_assign_references                                         */
/*                                                                           */
/* Procedure gets the full reference citation data for the received list of  */
/*   records, retrieved from the specified files and in accordance with the  */
/*   reference codes contained in the records; returns a negative number if  */
/*   any errors were encountered in the process, 0 otherwise                 */

int lend_assign_references (strlist_ptr directories, plain_ptr sorted,
                            char *tfd_file, char *imd_file, char *win_file)
{
 char **tfd_refs, **imd_refs, **win_refs;
 char **tfd_codes, **imd_codes, **win_codes;
 char **tfd_strings, **imd_strings; strlist_ptr *win_strings;
 int tfd_size, tfd_num, imd_size, imd_num, win_size, win_num, index;
 plain_ptr scan; bool found;
 errind errstat; strlist_ptr current_path; char *new_path;

 /* Loop to expand the reference information for all listed records          */

 tfd_refs = (char **) NTL0_ckalloc (TFD_INIT * sizeof (char *));
 tfd_size = TFD_INIT; tfd_num = 0;
 imd_refs = (char **) NTL0_ckalloc (IMD_INIT * sizeof (char *));
 imd_size = IMD_INIT; imd_num = 0;
 win_refs = (char **) NTL0_ckalloc (WIN_INIT * sizeof (char *));
 win_size = WIN_INIT; win_num = 0;

 for (scan = sorted; scan != NULL; scan = scan -> next) {
  if (scan -> database != NULL) {
   if (!strcmp (scan -> database, "TFD")) {
    found = FALSE; index = 0; while ((!found) && (index < tfd_num)) {
     if (!strcmp (tfd_refs [index], scan -> reference)) found = TRUE;
     else index++;
    }
    if (!found) {
     tfd_num++; if (tfd_num >= tfd_size) {
      tfd_size *= 2;
      tfd_refs = (char **) NTL0_ckrealloc ((char *) tfd_refs,
					   tfd_size * sizeof (char *));
     }
     tfd_refs [tfd_num - 1] = NTL0_strsave (scan -> reference);
    }
   }
   else if (!strcmp (scan -> database, "IMD")) {
    found = FALSE; index = 0; while ((!found) && (index < imd_num)) {
     if (!strcmp (imd_refs [index], scan -> reference)) found = TRUE;
     else index++;
    }
    if (!found) {
     imd_num++; if (imd_num >= imd_size) {
      imd_size *= 2;
      imd_refs = (char **) NTL0_ckrealloc ((char *) imd_refs,
					   imd_size * sizeof (char *));
     }
     imd_refs [imd_num - 1] = NTL0_strsave (scan -> reference);
    }
   }
   else if (!strcmp (scan -> database, "WIN")) {
    found = FALSE; index = 0; while ((!found) && (index < win_num)) {
     if (!strcmp (win_refs [index], scan -> reference)) found = TRUE;
     else index++;
    }
    if (!found) {
     win_num++; if (win_num >= win_size) {
      win_size *= 2;
      win_refs = (char **) NTL0_ckrealloc ((char *) win_refs,
					   win_size * sizeof (char *));
     }
     win_refs [win_num - 1] = NTL0_strsave (scan -> reference);
    }
   }
  }
 }
 if (tfd_num > 0) {
  tfd_codes = (char **) NTL0_ckalloc (tfd_num * sizeof (char *));
  for (index = 0; index < tfd_num; index++)
   tfd_codes [index] = tfd_refs [index];  
  free (tfd_refs);
  tfd_strings = (char **) NTL0_ckalloc (tfd_num * sizeof (char *));
  
  if ((directories == NULL) || (tfd_file [0] == '/') || (tfd_file [0] == '~'))
  {
   if ((errstat = NTL2_Read_TFDreferences (tfd_file, tfd_num, tfd_codes,
                                           tfd_strings)) != NULL) {
    fprintf (stderr, "Can't open references file '%s' (%s).\n",
                     tfd_file, errstat -> message);
    return -21;
   }
  }
  else {                    /* Directory path(s) provided, try them in order */
   current_path = directories; found = FALSE;
   while ((!found) && (current_path != NULL)) {
    new_path = NTL0_ckalloc ((strlen (current_path -> string) +
                              strlen (tfd_file) + 2) * sizeof (char));
    strcpy (new_path, current_path -> string);
    if (tfd_file [0] != '/') strcat (new_path, "/");
    strcat (new_path, tfd_file);
    
    if ((errstat = NTL2_Read_TFDreferences (new_path, tfd_num, tfd_codes,
                                            tfd_strings)) != NULL) {
     current_path = current_path -> next;
    }
    else found = TRUE;
    free (new_path);
   }
   if (errstat != NULL) {                      /* File not found on any path */
    fprintf (stderr, "Can't open references file '%s' (%s).\n",
                     tfd_file, errstat -> message);
    return -22;
   }
  }
 }
 else { tfd_codes = NULL; tfd_strings = NULL; }

 if (imd_num > 0) {
  imd_codes = (char **) NTL0_ckalloc (imd_num * sizeof (char *));
  for (index = 0; index < imd_num; index++)
   imd_codes [index] = imd_refs [index];  
  free (imd_refs);
  imd_strings = (char **) NTL0_ckalloc (imd_num * sizeof (char *));
  
  if ((directories == NULL) || (imd_file [0] == '/') || (imd_file [0] == '~'))
  {
   if ((errstat = NTL2_Read_IMDreferences (imd_file, imd_num, imd_codes,
                                           imd_strings)) != NULL) {
    fprintf (stderr, "Can't open references file '%s' (%s).\n",
                     imd_file, errstat -> message);
    return -23;
   }
  }
  else {                    /* Directory path(s) provided, try them in order */
   current_path = directories; found = FALSE;
   while ((!found) && (current_path != NULL)) {
    new_path = NTL0_ckalloc ((strlen (current_path -> string) +
                              strlen (imd_file) + 2) * sizeof (char));
    strcpy (new_path, current_path -> string);
    if (imd_file [0] != '/') strcat (new_path, "/");
    strcat (new_path, imd_file);
    
    if ((errstat = NTL2_Read_IMDreferences (new_path, imd_num, imd_codes,
                                            imd_strings)) != NULL) {
     current_path = current_path -> next;
    }
    else found = TRUE;
    free (new_path);
   }
   if (errstat != NULL) {                      /* File not found on any path */
    fprintf (stderr, "Can't open references file '%s' (%s).\n",
                     imd_file, errstat -> message);
    return -24;
   }
  }
 }
 else { imd_codes = NULL; imd_strings = NULL; }

 if (win_num > 0) {
  win_codes = (char **) NTL0_ckalloc (win_num * sizeof (char *));
  for (index = 0; index < win_num; index++)
   win_codes [index] = win_refs [index];  
  free (win_refs);
  win_strings = (strlist_ptr *) NTL0_ckalloc (win_num * sizeof (strlist_ptr));
  
  if ((directories == NULL) || (win_file [0] == '/') || (win_file [0] == '~'))
  {
   if ((errstat = NTL2_Read_TRANSFAC_References (win_file, win_num, win_codes,
                                                 win_strings)) != NULL) {
    fprintf (stderr, "Can't open references file '%s' (%s).\n",
                     win_file, errstat -> message);
    return -25;
   }
  }
  else {                    /* Directory path(s) provided, try them in order */
   current_path = directories; found = FALSE;
   while ((!found) && (current_path != NULL)) {
    new_path = NTL0_ckalloc ((strlen (current_path -> string) +
                              strlen (win_file) + 2) * sizeof (char));
    strcpy (new_path, current_path -> string);
    if (win_file [0] != '/') strcat (new_path, "/");
    strcat (new_path, win_file);
    
    if ((errstat = NTL2_Read_TRANSFAC_References (new_path, win_num, win_codes,
                                                  win_strings)) != NULL) {
     current_path = current_path -> next;
    }
    else found = TRUE;
    free (new_path);
   }
   if (errstat != NULL) {                      /* File not found on any path */
    fprintf (stderr, "Can't open references file '%s' (%s).\n",
                     win_file, errstat -> message);
    return -26;
   }
  }
 }
 else { win_codes = NULL; win_strings = NULL; }

 for (scan = sorted; scan != NULL; scan = scan -> next) {
  if (scan -> database != NULL) {
   if (!strcmp (scan -> database, "TFD")) {
    found = FALSE; index = 0; while ((!found) && (index < tfd_num)) {
     if (!strcmp (tfd_codes [index], scan -> reference)) found = TRUE;
     else index++;
    }
    if (!found) {
     fprintf (stderr, "TFD reference '%s' not found in sorted list.\n",
                      scan -> reference);
     return -27;
    }
    else {
     scan -> full_ref = (strlist_ptr) NTL0_ckalloc (sizeof (StrList_Struct));
     (scan -> full_ref) -> string = tfd_strings [index];
     (scan -> full_ref) -> next = NULL;
    }
   }
   else if (!strcmp (scan -> database, "IMD")) {
    found = FALSE; index = 0; while ((!found) && (index < imd_num)) {
     if (!strcmp (imd_codes [index], scan -> reference)) found = TRUE;
     else index++;
    }
    if (!found) {
     fprintf (stderr, "IMD reference '%s' not found in sorted list.\n",
                      scan -> reference);
     return -27;
    }
    else {
     scan -> full_ref = (strlist_ptr) NTL0_ckalloc (sizeof (StrList_Struct));
     (scan -> full_ref) -> string = imd_strings [index];
     (scan -> full_ref) -> next = NULL;
    }
   }
   else if (!strcmp (scan -> database, "WIN")) {
    found = FALSE; index = 0; while ((!found) && (index < win_num)) {
     if (!strcmp (win_codes [index], scan -> reference)) found = TRUE;
     else index++;
    }
    if (!found) {
     fprintf (stderr, "TRANSFAC reference '%s' not found in sorted list.\n",
                      scan -> reference);
     return -27;
    }
    else scan -> full_ref = win_strings [index];
   }
  }
 }
 for (index = 0; index < tfd_num; index++) free (tfd_codes [index]);
 if (tfd_codes != NULL) free (tfd_codes);
 if (tfd_strings != NULL) free (tfd_strings);
 for (index = 0; index < imd_num; index++) free (imd_codes [index]);
 if (imd_codes != NULL) free (imd_codes);
 if (imd_strings != NULL) free (imd_strings);
 for (index = 0; index < win_num; index++) free (win_codes [index]);
 if (win_codes != NULL) free (win_codes);
 if (win_strings != NULL) free (win_strings);

 return 0;
}


/*****************************************************************************/
/*                                                                           */
/* Procedure: lend_text_output                                               */
/*                                                                           */
/* Procedure outputs the received records in the plain text format; returns  */
/*   a negative number if there were any errors, 0 otherwise                 */

int lend_text_output (strlist_ptr sources, plist_ptr records)
{
 strlist_ptr source_scan, win_scan;
 plist_ptr data_scan; plain_ptr lines; int count;

 printf ("\nData retrieved from file records:  ");
 for (source_scan = sources;
      source_scan != NULL; source_scan = source_scan -> next) {
  printf ("%s", source_scan -> string);
  if (source_scan -> next != NULL) printf (", "); else printf ("\n\n\n");
 }
 printf (
   "__________________________________________________________________\n\n\n");

 data_scan = records; count = 1; while (data_scan != NULL) {
  if ((data_scan -> start_count > 0) && (data_scan -> stop_count > 0)) {
   if (data_scan -> start_count == data_scan -> stop_count) {
    printf ("Record number:  %d\n", data_scan -> start_count);
   }
   else {
    printf ("Records number:  %d  through  %d\n",
            data_scan -> start_count, data_scan -> stop_count);
   }
  }
  else {
   printf ("Record count:  %d\n", count);
  }
  printf ("  Position:  ");
  if ((data_scan -> from != 0) && (data_scan -> to != 0)) {
   printf ("%ld - %ld\n", data_scan -> from, data_scan -> to);
  }
  else if (data_scan -> from != 0) {
   printf ("from %ld\n", data_scan -> from);
  }
  else if (data_scan -> to != 0) {
   printf ("through %ld\n", data_scan -> to);
  }
  else {
   printf ("unknown\n");
  }
  if ((data_scan -> from != 0) && (data_scan -> to != 0) &&
      (data_scan -> from < data_scan -> to)) {
   printf ("  Consensus:  ");
   if (data_scan -> consensus != NULL) {
    printf ("%s\n", data_scan -> consensus);
   }
   else {
    printf ("unknown\n");
   }
  }
  printf ("\n");
  lines = data_scan -> lines; while (lines != NULL) {
   if (lines -> text != NULL)
    printf ("  %3d)   From:  %ld     To:  %ld       Sequence:  %s\n\n",
            count, lines -> start, lines -> stop, lines -> text);
   else
    printf ("  %3d)   From:  %ld     To:  %ld       Sequence unknown\n\n",
            count, lines -> start, lines -> stop);
   if (lines -> database != NULL) {
    if (!strcmp (lines -> database, "TFD")) {
     printf ("          Site name:  ");
     if (lines -> site == NULL) printf ("missing");
     else printf ("%s", lines -> site);
     printf ("          Binding factor:  ");
     if (lines -> binding == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> binding);
     printf ("          Matched motif:  ");
     if (lines -> matched == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> matched);
     printf ("\n         Motif found in Transcription Factor Database, file: ");
     if (lines -> file == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> file);
     if (lines -> strand == LITERAL_CODE)
      printf ("         Motif matched directly.\n");
     else if (lines -> strand == INVERSE_CODE)
      printf ("         Motif matched in inverse complement.\n");
     else if (lines -> strand == BOTH_STRAND_CODE)
      printf ("         Motif matched in both strands.\n");
     else if (lines -> strand == TRUNCATED_LITERAL_CODE)
      printf ("         Motif matched partially, directly.\n");
     else if (lines -> strand == TRUNCATED_INVERSE_CODE)
      printf ("         Motif matched partially, in inverse complement.\n");
     printf ("\n         Reference:                                     ");
     if (lines -> reference == NULL) printf ("missing\n");
     else {
      printf ("%s\n\n                      %s\n",
              lines -> reference, (lines -> full_ref) -> string);
     }
    }
    else if (!strcmp (lines -> database, "IMD")) {
     printf ("          Matrix name:  ");
     if (lines -> binding == NULL) printf ("missing");
     else printf ("%s", lines -> binding);
     printf ("          Consensus:  ");
     if (lines -> site == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> site);
     printf ("          Relative score of matrix matching:  ");
     if (lines -> matched == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> matched);
     printf ("\n         Motif found in Information Matrix Database, file: ");
     if (lines -> file == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> file);
     if (lines -> strand == LITERAL_CODE)
      printf ("         Motif matched directly.\n");
     else if (lines -> strand == INVERSE_CODE)
      printf ("         Motif matched in inverse complement.\n");
     else if (lines -> strand == BOTH_STRAND_CODE)
      printf ("         Motif matched in both strands.\n");
     else if (lines -> strand == TRUNCATED_LITERAL_CODE)
      printf ("         Motif matched partially, directly.\n");
     else if (lines -> strand == TRUNCATED_INVERSE_CODE)
      printf ("         Motif matched partially, in inverse complement.\n");
     printf ("\n         Reference:                                     ");
     if (lines -> reference == NULL) printf ("missing\n");
     else {
      printf ("%s\n\n                      %s\n",
              lines -> reference, (lines -> full_ref) -> string);
     }
    }
    else if (!strcmp (lines -> database, "WIN")) {
     printf ("          Site name:  ");
     if (lines -> site == NULL) printf ("missing");
     else printf ("%s", lines -> site);
     printf ("          Binding factor:  ");
     if (lines -> binding == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> binding);
     printf ("          Matched motif:  ");
     if (lines -> matched == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> matched);
     printf ("\n         Motif found in TRANSFAC (Wingender) database, file: ");
     if (lines -> file == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> file);
     if (lines -> strand == LITERAL_CODE)
      printf ("         Motif matched directly.\n");
     else if (lines -> strand == INVERSE_CODE)
      printf ("         Motif matched in inverse complement.\n");
     else if (lines -> strand == BOTH_STRAND_CODE)
      printf ("         Motif matched in both strands.\n");
     else if (lines -> strand == TRUNCATED_LITERAL_CODE)
      printf ("         Motif matched partially, directly.\n");
     else if (lines -> strand == TRUNCATED_INVERSE_CODE)
      printf ("         Motif matched partially, in inverse complement.\n");
     printf ("\n         References:                                    ");
     if (lines -> reference == NULL) printf ("missing\n");
     else {
      printf ("%s\n\n", lines -> reference);
      for (win_scan = lines -> full_ref;
           win_scan != NULL; win_scan = win_scan -> next) {
       printf ("                      %s\n", win_scan -> string);
      }
     }
    }
    else {
     printf ("          Database containing the record:  %s",
             lines -> database);
     printf ("          Site name:  ");
     if (lines -> site == NULL) printf ("missing");
     else printf ("%s", lines -> site);
     printf ("          Binding factor:  ");
     if (lines -> binding == NULL) printf ("missing\n");
     else printf ("%s\n", lines -> binding);
     printf ("          Details for the site unknown.\n");
    }
   }
   else {
    if (lines -> c_range != NULL)
     printf ("          This site represents a range of lines:  %s\n",
             lines -> c_range);
    else
     printf ("          Details for the site unknown.\n");
   }
   printf ("\n"); count++;

   if (lines -> next != NULL) {
    printf (
    "   --------------------------------------------------------------------");
    printf ("\n\n");
   }
   lines = lines -> next;
  }
  printf (
  "_________________________________________________________________________");
  printf ("\n\n\n");

  data_scan = data_scan -> next;
 }
 return 0;
}

   
/*****************************************************************************/
/*                                                                           */
/* Procedure: lend_postscript_output                                         */
/*                                                                           */
/* Procedure outputs the received records in the PostScript format, in       */
/*   accordance with the specified settings; returns negative number if      */
/*   there were any errors, 0 otherwise                                      */

int lend_postscript_output (strlist_ptr sources, plist_ptr records,
                            int orientation, int size)
{
 strlist_ptr source_scan, win_scan; plist_ptr data_scan; plain_ptr lines;
 int top_x, top_y, x, x_detail, y, line_distance, endline, page_lines;
 int legend_lines, pages, count; float thickness; int x_d2, x_d3, x_d4;
 float scale;

 /* Initialize the parameters controlling the PostScript output              */
 
 thickness = 0.05 * size;
 if (size < MEDIUM_CUTOFF) scale = NARROW_SCALE;
 else if (size < WIDE_CUTOFF) scale = MEDIUM_SCALE;
 else scale = WIDE_SCALE;

 if (orientation == LANDSCAPE) {
  top_x = PSX_TOPLEFT;
  top_y = FIRST_PS_LANDSCAPE;
  line_distance = (int) (LANDSCAPE_DISTANCE_FACTOR * size);
  endline = (int) (LANDSCAPE_ENDLINE * scale);
  x_detail = top_x + (int) (LEGEND_SHIFT * scale);
  x_d2 = top_x + (int) (LANDSCAPE_TAB_2 * scale);
  x_d3 = top_x + (int) (LANDSCAPE_TAB_3 * scale);
  x_d4 = top_x + (int) (LANDSCAPE_TAB_4 * scale);
  legend_lines = (int) (LANDSCAPE_LINES * LANDSCAPE_FACTOR / size);
 }
 else {
  top_x = PSX_TOPLEFT;
  top_y = FIRST_PS_PORTRAIT;
  line_distance = (int) (PORTRAIT_DISTANCE_FACTOR * size);
  endline = (int) (PORTRAIT_ENDLINE * scale);
  x_detail = top_x + (int) (LEGEND_SHIFT * scale);
  x_d2 = top_x + (int) (PORTRAIT_TAB_2 * scale);
  x_d3 = top_x + (int) (PORTRAIT_TAB_3 * scale);
  x_d4 = top_x + (int) (PORTRAIT_TAB_4 * scale);
  legend_lines = (int) (PORTRAIT_LINES * PORTRAIT_FACTOR / size);
 }

 /* Proceed to output pages of PostScript text                                */

 printf ("%%!PS-Adobe-1.0\n");
 printf ("%%%%Creator: legend-utility\n");
 printf ("%%%%Pages: (atend)\n");
 printf ("%%%%EndComments\n\n");

 printf ("%%%%EndProlog\n\n");
 
 printf ("%%%%Page: 1 1\n\n"); pages = 1;
 printf ("gsave\n\n");

 if (orientation == LANDSCAPE) {
  printf ("612 0 translate\n90 rotate\n\n");
  printf ("%f setlinewidth\n\n", thickness);
 }

 /* Place the informational header at the top of the PostScript output       */
 
 x = top_x; y = top_y; page_lines = 0;
 printf ("%d %d moveto\n", top_x, top_y);
 printf ("/%s findfont %d scalefont setfont\n", FONT, size + 2);
 printf ("(Data retrieved from file records:  ) show\n");
 printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size + 2);
 printf ("(");
 for (source_scan = sources;
      source_scan != NULL; source_scan = source_scan -> next) {
  printf ("%s", source_scan -> string);
  if (source_scan -> next != NULL) printf (", "); else printf (") show\n\n");
 }
 printf ("/%s findfont %d scalefont setfont\n", FONT, size);
 page_lines = 3; y -= (3 * line_distance);
 printf ("newpath\n");
 printf ("%f setlinewidth\n", 2 * thickness);
 printf ("%d %d moveto\n", x, y + line_distance / 4);
 printf ("%d %d lineto\n", endline, y + line_distance / 4);
 printf ("%f setlinewidth\n", thickness);
 printf ("stroke\n\n");
 page_lines += 2; y -= (2 * line_distance);

 /* Loop for all areas of overlap recorded, to list all contained records    */
 
 data_scan = records; count = 1; while (data_scan != NULL) {
  if (page_lines + LEGEND_HEIGHT + HEADER_HEIGHT > legend_lines) {
   page_lines = 0; y = top_y;

   pages++;
   printf ("grestore\n\nshowpage\n\n");

   printf ("%%%%Page: %d %d\n\n", pages, pages);
   printf ("gsave\n\n");

   if (orientation == LANDSCAPE) {
    printf ("612 0 translate\n90 rotate\n\n");
    printf ("%f setlinewidth\n\n", thickness);
   }
  }
  printf ("/%s findfont %d scalefont setfont\n", FONT, size);
  printf ("%d %d moveto\n", x, y);
  if ((data_scan -> start_count > 0) && (data_scan -> stop_count > 0)) {
   if (data_scan -> start_count == data_scan -> stop_count) {
    printf ("(Record number:  ) show\n");
    printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
    printf ("(%d) show\n", data_scan -> start_count);
   }
   else {
    printf ("(Records number:  ) show\n");
    printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
    printf ("(%d) show\n", data_scan -> start_count);
    printf ("/%s findfont %d scalefont setfont\n", FONT, size);
    printf ("(  through  ) show\n");
    printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
    printf ("(%d) show\n", data_scan -> stop_count);
   }
  }
  else {
   printf ("Record count:  ) show\n");
   printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
   printf ("(%d) show\n", count);
  }
  page_lines += 1; y -= (1 * line_distance);
  
  printf ("/%s findfont %d scalefont setfont\n", FONT, size);
  printf ("%d %d moveto\n", x + INNER_DIVIDE, y);
  printf ("(Position:  ) show\n");
  printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
  if ((data_scan -> from != 0) && (data_scan -> to != 0)) {
   printf ("(%ld - %ld) show\n", data_scan -> from, data_scan -> to);
  }
  else if (data_scan -> from != 0) {
   printf ("(from %ld) show\n", data_scan -> from);
  }
  else if (data_scan -> to != 0) {
   printf ("(through %ld) show\n", data_scan -> to);
  }
  else {
   printf ("(unknown) show\n");
  }
  page_lines += 1; y -= (1 * line_distance);
  
  if ((data_scan -> from != 0) && (data_scan -> to != 0) &&
      (data_scan -> from < data_scan -> to)) {
   printf ("/%s findfont %d scalefont setfont\n", FONT, size);
   printf ("%d %d moveto\n", x + INNER_DIVIDE, y);
   printf ("(Consensus:  ) show\n");
   printf ("/%s-Bold findfont %d scalefont setfont\n", "Courier", size);
   if (data_scan -> consensus != NULL) {
    printf ("(%s) show\n", data_scan -> consensus);
   }
   else {
    printf ("(unknown) show\n");
   }
  }
  page_lines += 2; y -= (2 * line_distance);

  /* Loop for all individual records contained in the overlap area - display */
  
  lines = data_scan -> lines; while (lines != NULL) {

   /* Keep the output of the records as long as they fit on a page           */
   
   while ((lines != NULL) && (page_lines + LEGEND_HEIGHT < legend_lines))
   {
    printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
    printf ("%d %d moveto\n", x, y);
    printf ("(  %3d\\)) show\n", count);
    printf ("/%s findfont %d scalefont setfont\n", FONT, size);
    printf ("%d %d moveto\n", x_detail, y);
    printf ("(From:  ) show\n");
    printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
    printf ("(%ld) show\n", lines -> start);
    printf ("/%s findfont %d scalefont setfont\n", FONT, size);
    printf ("%d %d moveto\n", x_d2, y);
    printf ("(To:  ) show\n");
    printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
    printf ("(%ld) show\n", lines -> stop);
    printf ("/%s findfont %d scalefont setfont\n", FONT, size);
    printf ("%d %d moveto\n", x_d3, y);
    printf ("(Sequence:  ) show\n");
    printf ("/%s-Bold findfont %d scalefont setfont\n", "Courier", size);
    if (lines -> text != NULL)
     printf ("(%s) show\n", lines -> text);
    else printf ("(unknown) show\n");
    page_lines += 1; y -= (1 * line_distance);

    /* Show different data depending on the database they belong to          */
    
    printf ("/%s findfont %d scalefont setfont\n", FONT, size);
    printf ("%d %d moveto\n", x_detail, y);
    if (lines -> database != NULL) {
     if (!strcmp (lines -> database, "TFD")) {    /* Transcription Factor Db */
      printf ("(Site name:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> site == NULL) printf ("(missing) show\n");
      else lend_postscript_string (lines -> site);
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_d3, y);
      printf ("(Binding factor:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> binding == NULL) printf ("(missing) show\n");
      else lend_postscript_string (lines -> binding);
      page_lines += 1; y -= (1 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Matched motif:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", "Courier", size);
      if (lines -> matched == NULL) printf ("(missing) show\n");
      else printf ("(%s) show\n", lines -> matched);
      page_lines += 2; y -= (2 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Motif found in ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      printf ("(Transcription Factor Database) show\n");
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("(, file: ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> file == NULL) printf ("(missing) show\n");
      else printf ("(%s) show\n", lines -> file);
      page_lines += 1; y -= (1 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Motif matched ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> strand == LITERAL_CODE) {
       printf ("(directly) show\n");
      }
      else if (lines -> strand == INVERSE_CODE) {
       printf ("(in inverse complement) show\n");
      }
      else if (lines -> strand == BOTH_STRAND_CODE) {
       printf ("(in both strands) show\n");
      }
      else if (lines -> strand == TRUNCATED_LITERAL_CODE) {
       printf ("(partially, directly) show\n");
      }
      else if (lines -> strand == TRUNCATED_INVERSE_CODE) {
       printf ("(partially, in inverse complement) show\n");
      }
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("(.) show\n");
      page_lines += 2; y -= (2 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Reference:) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_d4, y);
      if (lines -> reference == NULL) printf ("(missing) show\n");
      else {
       printf ("(%s) show\n", lines -> reference);
       page_lines += 2; y -= (2 * line_distance);
      
       printf ("/%s findfont %d scalefont setfont\n", "Times-Roman", size);
       printf ("%d %d moveto\n", x_d2, y);
       printf ("(%s) show\n",
               (lines -> full_ref) -> string);
      }
     }
     else if (!strcmp (lines -> database, "IMD")) { /* Information Matrix Db */
      printf ("(Matrix name:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> binding == NULL) printf ("(missing) show\n");
      else lend_postscript_string (lines -> binding);
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_d3, y);
      printf ("(Consensus:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", "Courier", size);
      if (lines -> site == NULL) printf ("(missing) show\n");
      else printf ("(%s) show\n", lines -> site);
      page_lines += 1; y -= (1 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Relative score of matrix matching:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> matched == NULL) printf ("(missing) show\n");
      else printf ("(%s) show\n", lines -> matched);
      page_lines += 2; y -= (2 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Motif found in ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      printf ("(Information Matrix Database) show\n");
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("(, file: ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> file == NULL) printf ("(missing) show\n");
      else printf ("(%s) show\n", lines -> file);
      page_lines += 1; y -= (1 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Motif matched ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> strand == LITERAL_CODE) {
       printf ("(directly) show\n");
      }
      else if (lines -> strand == INVERSE_CODE) {
       printf ("(in inverse complement) show\n");
      }
      else if (lines -> strand == BOTH_STRAND_CODE) {
       printf ("(in both strands) show\n");
      }
      else if (lines -> strand == TRUNCATED_LITERAL_CODE) {
       printf ("(partially, directly) show\n");
      }
      else if (lines -> strand == TRUNCATED_INVERSE_CODE) {
       printf ("(partially, in inverse complement) show\n");
      }
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("(.) show\n");
      page_lines += 2; y -= (2 * line_distance);
     
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Reference:) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_d4, y);
      if (lines -> reference == NULL) printf ("(missing) show\n");
      else {
       printf ("(%s) show\n", lines -> reference);
       page_lines += 2; y -= (2 * line_distance);
      
       printf ("/%s findfont %d scalefont setfont\n", "Times-Roman", size);
       printf ("%d %d moveto\n", x_d2, y);
       printf ("(%s) show\n",
               (lines -> full_ref) -> string);
      }
     }
     else if (!strcmp (lines -> database, "WIN")) {     /* TRANSFAC database */
      printf ("(Site name:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> site == NULL) printf ("(missing) show\n");
      else lend_postscript_string (lines -> site);
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_d3, y);
      printf ("(Binding factor:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> binding == NULL) printf ("(missing) show\n");
      else lend_postscript_string (lines -> binding);
      page_lines += 1; y -= (1 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Matched motif:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", "Courier", size);
      if (lines -> matched == NULL) printf ("(missing) show\n");
      else printf ("(%s) show\n", lines -> matched);
      page_lines += 2; y -= (2 * line_distance);
      
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Motif found in ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      printf ("(TRANSFAC \\(Wingender\\) database) show\n");
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("(, file: ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> file == NULL) printf ("(missing) show\n");
      else printf ("(%s) show\n", lines -> file);
      page_lines += 1; y -= (1 * line_distance);
     
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Motif matched ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> strand == LITERAL_CODE) {
       printf ("(directly) show\n");
      }
      else if (lines -> strand == INVERSE_CODE) {
       printf ("(in inverse complement) show\n");
      }
      else if (lines -> strand == BOTH_STRAND_CODE) {
       printf ("(in both strands) show\n");
      }
      else if (lines -> strand == TRUNCATED_LITERAL_CODE) {
       printf ("(partially, directly) show\n");
      }
      else if (lines -> strand == TRUNCATED_INVERSE_CODE) {
       printf ("(partially, in inverse complement) show\n");
      }
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("(.) show\n");
      page_lines += 2; y -= (2 * line_distance);
     
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(References:) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_d4, y);
      if (lines -> reference == NULL) printf ("(missing) show\n");
      else {
       printf ("(%s) show\n", lines -> reference);
       page_lines += 2; y -= (2 * line_distance);
      
       printf ("/%s findfont %d scalefont setfont\n", "Times-Roman", size);
       for (win_scan = lines -> full_ref;
            win_scan != NULL; win_scan = win_scan -> next) {
        printf ("%d %d moveto\n", x_d2, y);
        printf ("(%s) show\n", win_scan -> string);
        page_lines += 1; y -= (1 * line_distance);
       }
      }
     }
     else {               /* Database specified, but with unknown identifier */
     
      printf ("(Database containing the record:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      printf ("(%s) show\n", lines -> database);
      page_lines += 1; y -= (1 * line_distance);
     
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Site name:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> site == NULL) printf ("(missing) show\n");
      else lend_postscript_string (lines -> site);
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_d2, y);
      printf ("(Binding factor:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      if (lines -> binding == NULL) printf ("(missing) show\n");
      else lend_postscript_string (lines -> binding);
      page_lines += 1; y -= (1 * line_distance);
     
      printf ("/%s findfont %d scalefont setfont\n", FONT, size);
      printf ("%d %d moveto\n", x_detail, y);
      printf ("(Details for the site unknown.) show\n");
      page_lines += 1; y -= (1 * line_distance);
     }
    }
    else {               /* No originating database provided for the records */
    
     if (lines -> c_range != NULL) {
      printf ("(This site represents a range of lines:  ) show\n");
      printf ("/%s-Bold findfont %d scalefont setfont\n", FONT, size);
      printf ("(%s) show\n", lines -> c_range);
     }
     else printf ("(Details for the site unknown.) show\n");
     page_lines += 1; y -= (1 * line_distance);
    }
    page_lines += 2; y -= (2 * line_distance);
    count++;
   
    if (lines -> next != NULL) {          /* Separate the individual records */
     printf ("newpath\n");
     printf ("%f setlinewidth\n", thickness);
     printf ("%d %d moveto\n", x + INNER_DIVIDE, y + line_distance / 4);
     printf ("%d %d lineto\n",
             endline, y + line_distance / 4);
     printf ("stroke\n\n");
     page_lines += 2; y -= (2 * line_distance);
    }
    lines = lines -> next;
   }
   if (lines != NULL) {                  /* If end of page, start a new one */
    page_lines = 0; y = top_y;
    
    pages++;
    printf ("grestore\n\nshowpage\n\n");

    printf ("%%%%Page: %d %d\n\n", pages, pages);
    printf ("gsave\n\n");
    
    if (orientation == LANDSCAPE) {
     printf ("612 0 translate\n90 rotate\n\n");
     printf ("%f setlinewidth\n\n", thickness);
    }
   }
  }
  /* Separate the area of overlaps (before proceeding to the next one)       */

  printf ("newpath\n");
  printf ("%f setlinewidth\n", 2 * thickness);
  printf ("%d %d moveto\n", x, y + line_distance / 4);
  printf ("%d %d lineto\n", endline, y + line_distance / 4);
  printf ("%f setlinewidth\n", thickness);
  printf ("stroke\n\n");
  page_lines += 2; y -= (2 * line_distance);
  
  data_scan = data_scan -> next;
 }
 printf ("grestore\n\nshowpage\n\n");              /* Conclude the last page */
 
 printf ("\n%%%%Trailer\n");
 printf ("%%%%Pages: %d\n\n", pages);
 return 0;
}


/*****************************************************************************/
/*                                                                           */
/* Procedure: lend_postscript_string                                         */
/*                                                                           */
/* Procedure outputs the received string as PostScript "show" command,       */
/*   accomodating the contained parenthesis, if any                          */

void lend_postscript_string (char *output)
{
 int out_len, index;

 printf ("(");
 out_len = strlen (output); for (index = 0; index < out_len; index++) {
  if ((output [index] != '(') && (output [index] != ')') &&
      (output [index] != '\n'))
   printf ("%c", output [index]);
  else if ((output [index] == '(') || (output [index] == ')'))
   printf ("%c%c", '\\', output [index]);
 }
 printf (") show\n");
}


/*****************************************************************************/
/*                                                                           */
/* Procedure: lend_is_integer                                                */
/*                                                                           */
/* Procedure determines whether the input string represents an integer       */
/*   number, as interpreted by this program, and places its value into a     */
/*   reference parameter; returns TRUE if a correct number has been          */
/*   extracted, FALSE otherwise                                              */

bool lend_is_integer (char *string, int *value)
{
 int index;
 
 if ((string [0] < '1') || (string [0] > '9')) return FALSE;
 *value = (int) (string [0] - '0');
 index = 1; while (string [index] != '\0') {
  if ((string [index] < '0') || (string [index] > '9')) return FALSE;
  *value = (*value) * 10 + (int) (string [index] - '0');
  index++; if (index > MAX_INT_LENGTH) return FALSE;
 }
 return TRUE;
}


