JPRED-2 Add alscript to the Git repository
[jpred.git] / sources / alscript / src / alps.c
diff --git a/sources/alscript/src/alps.c b/sources/alscript/src/alps.c
new file mode 100644 (file)
index 0000000..74bc0ee
--- /dev/null
@@ -0,0 +1,3853 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "array.h"
+#include "gjutil.h"
+#include "version.h"
+
+/****************************************************************************
+
+   ALPS - Main routines for ALSCRIPT alignment formatting tool
+
+   Copyright:  Geoffrey J. Barton (1992,1993,1997)
+
+   email: geoff@ebi.ac.uk
+
+All use of this program  must cite:  Barton, G. J. (1993), ALSCRIPT: A Tool to
+Format Multiple Sequence Alignments, Protein Engineering, Volume 6, No. 1, 
+pp. 37-40.
+
+  Please see README file for details of limitations of use.
+
+  $Id: alps.c,v 1.3 1998/09/17 17:34:26 geoff Exp $
+  $Log: alps.c,v $
+  Revision 1.3  1998/09/17 17:34:26  geoff
+  Add the new README file and the LICENSE and RELEASE_NOTES
+
+  Revision 1.2  1998/09/17 16:54:58  geoff
+  Check consistency with archive
+
+
+****************************************************************************
+
+   Main routine for ALSCRIPT - formally called ALPS
+
+   alps:  11th June 1992.
+   Author: G. J. Barton
+
+   This file contains a set of subroutines that provide for flexible
+formatting of multiple sequence alignments in PostScript at
+publication quality.
+
+11-18th June 1992:
+
+1.  Modified getbloc.c to Agetbloc.c.  Agetbloc reads all characters
+(ie not just legal amino acid codes) from an AMPS blocfile format
+multiple alignment file.
+
+2.  Wrote basic page scaling features to allow arbitrary page
+dimensions to be defined and to allow all x,y locations to be defined
+in terms of characters of the chosen pointsize.  The number of
+residues per line and hence number of pages is determined by the
+pointsize.  The page is divided into four areas.  (a) The main region
+for plotting out the amino acid sequences. (b) A region to the left of
+a for plotting sequence identifier codes - the width of this region is
+set by variable Cidwidth.  (c) A region above region a, and (d) a
+region below a.  Regions c and d are initially set to zero size.
+Routine ALReserveSpace() allows a selected number of lines to be
+reserved above or below for plotting.
+
+3.  Routines ALOutID and ALOutSeq written and multi-page plotting of
+the sequences sorted out.  Still limited to one page in the vertical
+direction - toyed with the idea of writing single page PostScript and
+using PostScript to modify clipping boundaries like in the Poster demo
+program in the CookBook.
+
+4.  Experiment with simple boxing facility - ALDrawSimpleBox().  This
+routine is incompatible with multi-page output since page breaks are
+unpredictable.
+
+5.  Develop sophisticated (!) boxing facility - defines boxes in terms
+of TOP BOTTOM LEFT and RIGHT lines that may be defined around each
+character routine ALLineRes() implements this feature.  The details of
+TOP etc for each character are stored in the unsigned char array
+"lines".  This uses the rightmost four bits to encode LEFT RIGHT etc.
+Thus a line to the LEFT line is coded by decimal 1 (0001 binary), a
+full box by decimal 15 (1111 binary).  ALBoxRes and ALBoxRegion
+written to allow boxing of arbitrary regions.  
+
+6.  The y coordinate sent to the low level ALLineRes routine 
+refers directly to the index to the lines array.  If you want to work in 
+residue coordinate space, you need to flip the y coordinate before 
+writing to the lines array (also the fill array).  Routines ALSurroundChars
+and ALFillChars do this directly.  Routines ALBoxRegion and ALFilRegion
+make use of the Yindx array which does the flip in a much cleaner and more
+elegant way.  If I'd thought of it at the
+time, I would have used this in ALSurroundChars and ALFillChars as well!
+
+7.  Now add capability to split alignments vertically as well as horizontally.
+There is now no limit on pointsize or number/length of sequences 
+(in principle!).  Next move on the page layout front will be to allow 
+multiple blocks on a single page - this would permit alignments of a 
+few sequences, or small fonts to make better use of paper!
+
+8.  We now have most of the subroutines working OK.  So time to tidy up the 
+input.  Add simple command parser to main programme - this is in two steps, 
+step 1 reads the basic page layout commands, step 2 reads the boxing/shading
+font changing commands - Oh yes, added the font changing option as well.
+
+Current commands as follows:
+Commands are delimited by space, comma, or tab. Newline signals the end of a 
+command.  Unless otherwise stated, units are in characters of the default pointsize.
+For a full list see the file "alscript.doc".
+
+step 1 commands:
+
+BLOCK_FILE <input filename>           %The name of the alignment file to format
+OUTPUT_FILE <file>                    %must have this near the beginning
+LANDSCAPE                             %Longest side horizontal
+PORTRAIT                              %             vertical
+POINTSIZE  <float>                    %Pointsize for page calculations and character spacing/default size.
+IDENT_WIDTH <integer>                 %Width allocated to identifiers.
+NUMBER_SEQS  1 || 0                   %1=number identifiers, 0= no numbers (default).
+DEFINE_FONT <font number integer> <font name> <pointsize>  %define a font to be referred to as font number.
+e.g.
+  DEFINE_FONT 0 Helvetica 10          %font 0 is Helvetica at 10 point
+  DEFINE_FONT 4 Times-Roman DEFAULT   %font 4 is Times-Roman at the default pointsize.
+SETUP                                 %signals end of step 1 commands.
+
+step 2 commands:
+
+RESERVE_SPACE_TOP <integer>           %make space at the top of the alignment 
+RESERVE_SPACE_BOTTOM <integer>        %                  bottom  DOES NOT WORK.
+SURROUND_CHARS <chars> <start_res> <start_seq> <end_res> <end_seq> 
+                                      %surround (box) the characters chars within the ranges specified 
+e.g.
+  SURROUND_CHARS PG 1 7 20 12         %surround P and G characters from residues 1 to 20 of sequences 7 to 12.
+  SURROUND_CHARS DEKHR ALL            %surround D and E and K and R characters for the whole alignment.
+
+SHADE_CHARS <chars> <start_res> <start_seq> <end_res> <end_seq> <grey>
+                                      %similar syntax to SURROUND_CHARS with the addition of a grey value
+                                      % 0 = black, 1 = white.  Note that shading is done before outputing the
+                                      % alignment.
+e.g.
+  SHADE_CHARS PG 1 7 20 12 0.5        % shade P and G in the range shown with a grey value of 0.5
+  SHADE_CHARS ILV ALL 0               % shade all  I and L and V in black.
+
+FONT_CHARS <chars> <start_res> <start_seq> <end_res> <end_seq> <fontnumber>
+                                      %same syntax as SHADE_CHARS, only give the font number in place of grey.
+                                      %font numbers must first be defined with the DEFINE_FONT command above.
+FONT_RESIDUE sx sy font               %allows setting of font for one residue (use with TEXT command)
+
+BOX_REGION <start_res> <start_seq> <end_res> <end_seq>
+                                      %draw a rectangular box around the characters within the defined range.
+SHADE_REGION <start_res> <start_seq> <end_res> <end_seq> <grey>
+                                      %shade the region by the chosed grey value.
+
+9.  Add option to place arbitrary text string at a character location.
+e.g
+  TEXT 1 7 "SIGNAL PEPTIDE"           %puts this text at sequence position 1 7.
+                                      %to change fonts use the FONT_RESIDUE or FONT_REGION commands.
+10. Add option to change fonts of identifiers.
+ID_FONT <sequence> <font>
+e.g. 
+  ID_FONT 3 1                         %sets font to 1 for sequence identifier 3
+  ID_FONT ALL 7                       %uses font 7 for all identifiers
+
+19th June 1992:
+Still fiddling - must get back to some real work soon.
+Split alps away from the scanps program.  Now have a separate main() for the routine.
+
+Add options to redefine all defaults:  e.g. MAXslen (maximum sequence
+length etc.) Add arbitrary line drawing options:  eg. LINE TOP 20 15 50
+draws a line along the top of the characters from residue 20 to 50 or
+sequence 15. Think about adding the option to change line thickness at
+different parts of the plot. Decide not to implement that option right
+now. Add option to include dummy sequences (ADD_SEQ)
+
+Check the programme compiles on the 386 PC.  It does!
+Write documentation and brief report of the programme.
+
+22nd June 1992:  Get back to some real work!
+
+19th October:  Add SILENT_MODE Command and carriage returns to all .PS print statements.
+21st October:  Add VERTICAL_SPACING command and ability to output multiple blocks per page.
+15th November: Add pipe options to alscript.c  Tidy up file handling.
+
+6th December:  Add Colour options.
+18th Jan 1993: Tidy up citations:  modify Inverse chars to allow reversion.
+1 March 1993:  Fix bug in colour option.  Pass use_colour to ALDrawLines routine to 
+               specify black for line colour.  Previously, this was drawn in white
+               if coloured shading had been specified on the same characters.
+2 March 1993:  Fix bug in colour option to output identifiers in black, not white!
+9 March 1993:  Add NO_NUMBERS option to avoid printing residue numbers.
+24 March 1993: Add mask features.
+
+11 March 1994: At PERI - Add special text features - preliminary version only.
+               This permits strands and helices to be plotted as cylinders and arrows.
+               Special text features also permit triangles and circles etc etc. through
+               use of text command.
+
+23 May 1995: Numerous changes and additions over the last year - these
+include the option to colour backgrounds differently, ommission of
+idents on second and subsequent lines, helix, strand and other special
+characters, relative numbering, error checking of ranges on input,
+bounding box, screening, conservation colouring...
+
+
+*/
+
+#define TOKENS "\" ,\n\t"        /* standard command token delimiters */
+#define POINT 72               /* Work in points throughout */
+#define C_ID_WIDTH 10          /* Default width for writing id's (in characters) */
+#define DEF_POINTSIZE 10.0      
+#define X_OFFSET 40            /* offset for bottom lh corner of page (points) */
+#define Y_OFFSET 30
+#define DEF_YPOS 0             /* default first printinf position (character units) */
+#define LINE_WIDTH_FACTOR 0.05 /* Multiply pointsize by this to get linewidth */
+#define MAX_ADD_SEQ 10        /* Maximum number of ADD_SEQ commands allowed */
+
+/*#define MAX_S 10.5             max and min page side in inches */
+/*#define MIN_S 6.5  */
+/*#define MAXSIDE (MAX_S * POINT)   Default Max and min dimensions of paper */
+/*#define MINSIDE (MIN_S * POINT) */
+
+#define SCREENSIZE 120           /* define default size for screen */
+
+
+int width = 0;                 /* max width and height of drawing area */
+int height = 0;
+char *tokens = TOKENS;
+
+float MAXside = 10.5 * POINT;     /* values to hold Max and min page side in points */
+float MINside = 6.5 * POINT;
+
+int xoff = X_OFFSET;
+int yoff = Y_OFFSET;
+
+int Cidwidth = C_ID_WIDTH;     /* width of id region in characters (left of sequence block)*/
+int Cseqwidth;                 /* width of sequence region in characters */
+int Cwidth;                    /* width/height of page in characters */
+int Cheight;
+int Xspace;                    /* spacing between characters in X */
+int Yspace;                    /* spacing between characters in Y */
+float XspaceFactor = 0.2;          /* extra bit to add to horizontal character spacing */
+float YspaceFactor = 0.0;          /* extra bit to add to vertical character spacing */
+float XshiftFactor = 0.12;          /* *pointsize gives the shift for vertical lines */
+float YshiftFactor = 0.12;          /*                                horizontal lines */
+
+int CseqTop = 0;
+int CseqVoffset = 0;           /* vertical offset for sequence block (characters)*/
+int CtopSpace =0;              /* extra space above sequence block (characters) */
+int CbottomSpace = 0;          /*   "     "   below    "       "         "      */
+int Csheet = 1;                /* number of vertical splits in sequence block */
+
+int TVspace = 0;               /* total vertical space reserved (characters)*/
+
+float Xshift = 0;     /* offsets for drawing box lines */
+float Yshift = 0;
+float LineWidthFactor = LINE_WIDTH_FACTOR;
+
+float pointsize = DEF_POINTSIZE;
+int npage;
+
+int Vspacing = 0;               /* vertical spacing in characters between blocks on a page */
+
+
+enum Orientations{
+  LANDSCAPE,
+  PORTRAIT
+};
+
+enum Spaces{
+  TOP,
+  BOTTOM
+};
+
+struct addseq {
+       int pos;
+       int num;
+};
+
+/* bit masks for the lines array */
+unsigned char LINE_LEFT = 1; /* mask for line at left of char */
+unsigned char LINE_RIGHT= 2; /*                  right        */
+unsigned char LINE_TOP  = 4; /*                  top          */
+unsigned char LINE_BOTTOM=8; /*                  bottom       */
+void ALOutId(struct seqdat *,int,unsigned char *colour,
+            unsigned char *,int,int,int,int, FILE *);
+void ALOutSeq(struct seqdat *,unsigned char **,
+             char ***,
+             unsigned char **,int ,unsigned char **,
+             unsigned char **text_colour,
+             unsigned char background_colour,
+             int ,int ,int ,int ,FILE *);
+void PSPutText(int,int,char *,FILE *);
+void PSPutChar(int,int,char,FILE *);
+void PSShowPage(FILE *);
+void ALSetFont(char *,int,FILE *);
+void ALCheckSinglePage(int ,int ,int );
+void ALSetPageLimits(void);
+void PSSetOrientation(int, FILE *);
+void PSPreamble(FILE *,int, int*, int screensize);
+void PSLandscape(FILE *);
+void PSPortrait(FILE *);
+void PSSetupPage(int,int,FILE *);
+void ALReserveSpace(int, int);
+void ALReportInfo(int, FILE *);
+char **ALCreateNumbers(int,int,int,int);
+char *ALCreateTicks(int,int,int);
+void ALOutTicks(char *,int,int,int,int,FILE *);
+void ALOutNumbers(char **,int,int,int,int,FILE *);
+void PSDrawBox(float,float,float,float,float,FILE *);
+void ALSimpleBox(int,int,int,int,float,FILE *);
+void PSline(float,float,float,float,FILE *);
+void ALLineChar(unsigned char **,int,int,unsigned char);
+void ALLineRes(unsigned char **,int,int,unsigned char);
+void ALDrawLines(unsigned char **,int,
+                unsigned char **left_line_colour,
+                unsigned char **right_line_colour,
+                unsigned char **top_line_colour,
+                unsigned char **bottom_line_colour,
+                int,int,int,int,int,int,FILE *);
+void ALBoxRes(unsigned char **,int,int);
+void ALDrawFills(signed char **,int ,unsigned char **, 
+                int,int ,int,int ,int ,int, FILE *);
+void ALFilRes(signed char **,int,int,float);
+void ALBoxRegion(unsigned char **,int,int,int,int,int *);
+void ALFilRegion(signed char **,int ,int,int,int , int *,float);
+void ALSurroundChars(struct seqdat *,unsigned char **,int,int,int,int,int,char *);
+void ALShadeChars(struct seqdat *,signed char **,
+                 int ,int,int,int,int,char *,float);
+void ALDefineFont(int,char *,float,FILE *);
+void echo(char *);
+void ALGetFourInt(int *,int *,int *,int *);
+void ALGetThreeInt(int *,int *,int *);
+void ALGetTwoInt(int *,int *);
+void ALFontChars(struct seqdat *,unsigned char **,
+                int,int,int,int,char *,unsigned char);
+void ALFontRegion(unsigned char **,int,int,int,int,unsigned char);
+void PSSetFont(unsigned char,FILE *);
+void ALDoLine(unsigned char **,int,int,int,int,int *);
+void ALSubChars(struct seqdat *,int,int,int,int,char,char);
+char ALChekSpace(const char *);
+void PSSetGrey(float,FILE *);
+void ALInverseChars(struct seqdat *,unsigned char **,int,int,int,int,char *);
+int Agetbloc(FILE *,struct seqdat *,int *);
+void ALDefineColour(int,char *coltype, float,float,float,FILE *);
+void ALSColChars(struct seqdat *,unsigned char **,
+                int,int,int,int,int,char *,unsigned char);
+void ALColourChars(struct seqdat *,unsigned char **,
+                  int ,int,int,int,char *,unsigned char);
+void ALColRes(unsigned char **,int ,int , int );
+void PSSetColour(unsigned char,FILE *);
+void ALColRegion(unsigned char **,int,int,int,int,int *,unsigned char);
+void ALColRRegion(unsigned char **,int,int,int,int,unsigned char);
+void ckdd(struct seqdat *, int);
+int Ifound(struct seqdat *,int,int,char *,int);
+void ALSColMask(unsigned char **,unsigned char **,
+               int, int, int, int,int, unsigned char);
+void ALInverseMask(unsigned char **,unsigned char **,int, int, int, int);
+void ALFontMask(unsigned char **,unsigned char **,int, int, int, int,unsigned char);
+void ALShadeMask(unsigned char **,signed char **,int,int,int,int,int *, float);
+void ALGetAllRange(int *, int *, int *, int *,int ,int );
+void ALid_mask(unsigned char **,struct seqdat *,int, int, int, int, int, char *, char *);
+void ALfre_mask(unsigned char **mask,struct seqdat *,int, int, int, int, char *, char *);
+int Ifound(struct seqdat *,int,int,char *,int);
+void ALagree_mask(unsigned char **,struct seqdat *,int,int,int,int,int);
+void ALnot_mask(unsigned char **,int, int, int, int);
+void ALsub_mask(unsigned char **,struct seqdat *,int, int, int, int, char);
+void ALMask(unsigned char **,int, int, int, int);
+void ALConsMask(unsigned char **mask,
+int sx,int sy,int ex,int ey,int *consval,int conscut);
+void ALColourMask(unsigned char **,unsigned char **,int,int,int,int,unsigned char);
+void ALSurroundMask(unsigned char **,struct seqdat *,unsigned char **,int,int,int,int,int);
+int save_pir(struct seqdat *,int,FILE *);
+void ALDrawHorizLine(
+                    float Xpos,       /* bottom left hand corner of character posn */
+                    float Ypos,       /* */
+                    float Xspace,     /* horizontal width of character position */
+                    float Yspace,     /* vertical height of character position */
+                    float width_fac,FILE *outf);  /* proportion of vertical height that the line will fill */
+void ALDrawRightArrow(float Xpos,float Ypos, float Xspace, 
+                     float Yspace, float width_fac,FILE *outf);
+void ALDrawLeftArrow(float Xpos,float Ypos, float Xspace, 
+                    float Yspace, float width_fac,FILE *outf);
+void ALDrawUpArrow(float Xpos,float Ypos, float Xspace, 
+                  float Yspace, float width_fac,FILE *outf);
+void ALDrawDownArrow(float Xpos,float Ypos, float Xspace, 
+                    float Yspace, float width_fac,FILE *outf);
+void ALDrawCircle(float Xpos,float Ypos, float Xspace, 
+                 float Yspace, float width_fac,FILE *outf);
+void ALDrawPseudoEllipse(float Xpos,float Ypos, float Xspace, 
+                        float Yspace, float width_fac,
+                        FILE *outf);
+void ALDrawLeftSemiEnd(float Xpos,float Ypos, float Xspace, 
+                      float Yspace, float width_fac,FILE *outf);
+void ALDrawRightSemiEnd(float Xpos,float Ypos, float Xspace, 
+                       float Yspace, float width_fac,FILE *outf);
+void ALDrawRightHalfHorizLine(float Xpos,float Ypos,float Xspace,
+                             float Yspace,float width_fac,FILE *outf);
+void ALDrawLeftHalfHorizLine(float Xpos,float Ypos,float Xspace,float 
+                            Yspace,float width_fac,FILE *outf);
+void PSmoveto(float x,float y,FILE *outf);
+void PSlineto(float x,float y,FILE *outf);
+void PSPutSpecialText(float Xpos,float Ypos,float Xspace,
+                     float Yspace,char *text,unsigned char current_col,
+                     unsigned char background_colour,
+                     float YspaceFactor,FILE *outf);
+void PSstroke(FILE *outf);
+void PSnewpath(FILE *outf);
+void ALColourBackground(FILE *outf,int colour,int *background_region);
+void ALCheckLegalRange(int sx,int sy, int ex, int ey, int xmin, int ymin, int xmax, int ymax);
+void ALMakeCoilText(int sx, int sy, int ex, char ***texts);
+void ALMakeStrandText(int sx, int sy, int ex, char ***texts);
+void ALMakeHelixText(int sx, int sy, int ex, char ***texts);
+int ALrel(char *pos,int *relnum);
+int GJindex(char *str,char c);
+float mzcons(unsigned char *pos,int n);
+int *ALCalCons(struct seqdat *bloc,
+               int sx,int sy,int ex,int ey,int *ret_val,int len);
+int save_msf(struct seqdat *bloc,int nseq,FILE *msff);
+
+int alps(char *command_file,int silent, int pipe, int singlepage)
+{  
+  FILE *cf,*inf,*outf,*pirf,*msff;
+  char *buff;
+  char *token;
+  char *charstring;
+  struct seqdat *bloc;
+  struct seqdat *temp;
+  int orientation;
+  extern int MAXtlen,MAXnbloc;
+  extern int MAXilen,precis,MAXslen;
+  int nseq;
+  int start_aa;
+  int start_seq;
+  int i,j,k;
+  int totalpage;
+  char **numbers;
+  char *ticks;
+  unsigned char **lines;
+#ifdef VAX
+ char **fills;
+#else
+  signed char **fills;
+#endif
+  unsigned char **fonts;
+  unsigned char *idfonts;
+  unsigned char **inverse;
+  char ***texts;
+  int *Yindx;
+  int number_seqs = 0;
+
+  int Xtemp,Ytemp;
+  int sx,sy,ex,ey;
+
+  int fnum;
+  char *fname;
+  float fpoint;
+  int rowsiz;
+
+  char oldchar,newchar;
+  
+  struct seqdat *addbloc;
+  struct addseq *adds;
+  int nadds;
+  int natot;
+  int l;
+  int do_ticks = 0;
+  int number_int = 10;
+  int pirsave = 0;
+  int msfsave = 0;
+
+  int nbp,nspage;  /*counter and total for number of blocks per page */
+  int lastY;
+  int nbpage;
+
+  /* bounding_box - allows explicit fiddling with the bounding_box */
+  int *bounding_box;
+
+  /* colours */
+  float red,green,blue;
+  unsigned char **s_colour;       /*colour number for shading */
+  unsigned char **c_colour;       /*colour number for characters */
+  /* new 4th Oct 1994 */
+  unsigned char *id_colour;          /*colour for identifiers */
+  unsigned char **left_line_colour;  /*colours for lines */ 
+  unsigned char **right_line_colour;   
+  unsigned char **top_line_colour;   
+  unsigned char **bottom_line_colour;   
+  unsigned char **text_colour;       /*colour for text */
+  char *colname;
+
+  int background_colour = 99;        /*set background to white */
+  int *background_region;            /* use this to set the region for background colouring */
+
+  int number_colour = 100;           /* colour for numbers along top of plot */
+  /* end new */
+  char *tstring;
+
+  int use_colour;                 /* flag set if the define_colour command is seen */
+  int res_numbers;
+
+  int msl;
+
+  /* min and max ranges in the sequence alignment */
+  int xmin, ymin, xmax, ymax;
+
+  /* masking variables */
+  unsigned char **mask;
+  char *illegal;
+  char *legal;
+  int id_cut;
+
+  /* screen size variable - for printer screen */
+  int screensize = SCREENSIZE;
+
+  /* set up relative numbering - allows commands to follow
+     a specific sequence numbering 
+     firstres defines the number of the first residue */
+  int relative_seq = 0;
+  int firstres = 0;
+  int i1;
+  int *relnum;
+  /* temp relnum */
+  int *trelnum;
+
+  /* flag for idents */
+  int id_only_on_first = 0;
+  int tempCseqwidth;
+  int tempCidwidth;
+
+  /* conservation values */
+  int *consval;     /* array */
+  int conscut;      /* cutoff */
+
+  /* counter for add_seq errors */
+  int adderr;
+    
+  /* file streams */
+  extern FILE *std_in, *std_out, *std_err;
+
+  /* By default read and write to stdin and stdout */
+  outf = std_out;
+  inf = std_in;
+
+
+  /* default is no colour */
+  use_colour = 0;
+
+  /* if set, residue numbers are output */
+  res_numbers = 1;
+
+
+
+  /* set the bounding box to default values for portrait A4*/
+  bounding_box = (int *) GJmalloc(sizeof(int) * 4);
+  bounding_box[0] = 0;
+  bounding_box[1] = 0;
+  bounding_box[2] = 590;
+  bounding_box[3] = 826;
+
+  /* set the background colour region equal to the default bounding box */
+  background_region = (int *) GJmalloc(sizeof(int) * 4);
+  background_region[0] = 0;
+  background_region[1] = 0;
+  background_region[2] = 590;
+  background_region[3] = 826;
+
+  /* initialise the mask */
+  mask = NULL;
+  illegal = NULL;
+  legal = NULL;
+
+  adds = (struct addseq *) malloc(sizeof(struct addseq) * (MAX_ADD_SEQ+1));
+  nadds = 0;
+  
+
+  fname = (char *) malloc(sizeof(char)*MAXtlen);
+
+  buff = (char *) malloc(MAXtlen * sizeof(char));
+  if(buff == NULL)error("No Space for buff",1);
+
+  if((cf = fopen(command_file,"r")) == NULL){
+       error("Cannot open ALSCRIPT command file",0);
+       return 0;
+  }
+  
+  /* 
+    This is a little inelegant at the moment - when I get the generalized 
+    parser finished this could be cleaned up substantially
+  */
+
+  /* main loop to read commands */
+  if(pipe){
+    /* Alscript is being used as a pipe so write preamble to std_out */
+    outf = std_out;
+    PSPreamble(outf,singlepage,bounding_box,screensize);
+  }
+    
+  if(!silent)fprintf(std_err,"Starting ALSCRIPT\n");
+
+  while(buff = fgets(buff,MAXtlen,cf)){
+    if(!silent)echo(buff);
+    if(buff == NULL) continue;
+    token = strtok(buff,TOKENS);
+    if(token == NULL) continue;
+    token = GJstoup(token);    
+    if(*token == '#'){
+      if(!silent)echo("Comment\n");
+    }else if(strcmp(token,"SILENT_MODE")==0){
+        if(!silent){
+         silent=1;
+       }else{
+         silent=0;
+       }
+    }else if(strcmp(token,"MAX_INPUT_LEN")==0){
+      if(!silent) fprintf(std_err,"Max input len was:\t%d\n",MAXtlen);
+      token = strtok(NULL,TOKENS);
+      MAXtlen = atoi(token);
+      if(!silent)fprintf(std_err,"Max input len now:\t%d\n",MAXtlen);
+    }else if(strcmp(token,"MAX_NSEQ")==0){
+      if(!silent)fprintf(std_err,"Max No. of sequences was:\t%d\n",MAXnbloc);
+      token = strtok(NULL,TOKENS);
+      MAXnbloc = atoi(token);
+      MAXtlen = MAXnbloc;
+      fprintf(std_err,"Max No. of sequences now:\t%d\n",MAXnbloc);
+    }else if(strcmp(token,"MAX_ILEN")==0){
+      if(!silent)fprintf(std_err,"Max Identifier length was:\t%d\n",MAXilen);
+      token = strtok(NULL,TOKENS);
+      MAXilen = atoi(token);
+      if(!silent)fprintf(std_err,"Max Identifier length now:\t%d\n",MAXilen);
+    }else if(strcmp(token,"PRECISION")==0){
+      token = strtok(NULL,TOKENS);
+      precis = atoi(token);
+    }else if(strcmp(token,"MAX_SEQ_LEN")==0){
+      if(!silent)fprintf(std_err,"Max Sequence Length was:\t%d\n",MAXslen);
+      token = strtok(NULL,TOKENS);
+      MAXslen = atoi(token);
+      if(!silent)fprintf(std_err,"Max Sequence Length now:\t%d\n",MAXslen);
+    }else if(strcmp(token,"X_OFFSET")==0){
+      if(!silent)fprintf(std_err,"X offset was:\t%d\n",xoff);
+      token = strtok(NULL,TOKENS);
+      xoff = atoi(token);
+      if(!silent)fprintf(std_err,"X offset now:\t%d\n",xoff);
+    }else if(strcmp(token,"Y_OFFSET")==0){
+      if(!silent)fprintf(std_err,"Y offset was:\t%d\n",yoff);
+      token = strtok(NULL,TOKENS);
+      yoff = atoi(token);
+      if(!silent)fprintf(std_err,"Y offset now:\t%d\n",yoff);
+    }else if(strcmp(token,"MAX_SIDE")==0){
+      if(!silent)fprintf(std_err,"Longest page side was:\t%.2f inches\n",MAXside/POINT);
+      token = strtok(NULL,TOKENS);
+      MAXside = POINT * atof(token);
+      if(!silent)fprintf(std_err,"Longest page side now:\t%.2f inches\n",MAXside/POINT);
+    }else if(strcmp(token,"MIN_SIDE")==0){
+      if(!silent)fprintf(std_err,"Shortest page side was:\t%.2f inches\n",MINside/POINT);
+      token = strtok(NULL,TOKENS);
+      MINside = POINT * atof(token);
+      if(!silent)fprintf(std_err,"Shortest page side now:\t%.2f inches\n",MINside/POINT);
+    }else if(strcmp(token,"LINE_WIDTH_FACTOR")==0){
+      if(!silent)fprintf(std_err,"Line width multiplication factor was:\t%f\n",LineWidthFactor);
+      token = strtok(NULL,TOKENS);
+      LineWidthFactor = atof(token);
+      if(!silent)fprintf(std_err,"Line width multiplication factor now:\t%f\n",LineWidthFactor);
+    }else if(strcmp(token,"SCREENSIZE")==0){
+      if(!silent)fprintf(std_err,"Screensize was:\t%d\n",screensize);
+      token = strtok(NULL,TOKENS);
+      screensize = atoi(token);
+      if(!silent)fprintf(std_err,"Screensize now:\t%d\n",screensize);
+    }else if(strcmp(token,"BLOCK_FILE") == 0){
+      token = strtok(NULL,TOKENS);
+      if(!pipe){
+        inf = fopen(token,"r");
+        if(inf == NULL)error("Cannot open BLOCK_FILE\n",1);
+      }
+    }else if(strcmp(token,"OUTPUT_FILE")==0){
+      token = strtok(NULL,TOKENS);
+      if(!pipe){
+        outf = fopen(token,"w");
+        if(outf == NULL)error("Cannot open OUTPUT_FILE\n",1);
+        PSPreamble(outf,singlepage,bounding_box,screensize);
+      }
+    }else if(strcmp(token,"PIR_SAVE")==0){
+      token = strtok(NULL,TOKENS);
+      pirf = fopen(token,"w");
+      if(pirf == NULL)error("Cannot open PIR_SAVE file\n",1);
+      pirsave = 1;
+    }else if(strcmp(token,"MSF_SAVE")==0){
+      token = strtok(NULL,TOKENS);
+      msff = fopen(token,"w");
+      if(msff == NULL)error("Cannot open MSF_SAVE file\n",1);
+      msfsave = 1;
+    }else if(strcmp(token,"LANDSCAPE")==0){
+      orientation = LANDSCAPE;
+    }else if(strcmp(token,"PORTRAIT")==0){
+      orientation = PORTRAIT;
+
+    }else if(strcmp(token,"POINTSIZE")==0){
+      token = strtok(NULL,TOKENS);
+      pointsize = atof(token);
+    }else if(strcmp(token,"IDENT_WIDTH")==0){
+      token = strtok(NULL,TOKENS);
+      Cidwidth = atoi(token);
+      if(Cidwidth > MAXilen)error("INCREASE MAX_ID_LEN value",1);
+    }else if(strcmp(token,"NUMBER_SEQS")==0){
+      number_seqs=1;
+    }else if(strcmp(token,"X_SPACE_FACTOR")==0){
+      if(!silent)fprintf(std_err,"Was:\t%.2f\n",XspaceFactor);
+      token = strtok(NULL,TOKENS);
+      XspaceFactor = atof(token);
+      if(!silent)fprintf(std_err,"Now Is:\t%.2f\n",XspaceFactor);
+    }else if(strcmp(token,"Y_SPACE_FACTOR")==0){
+      if(!silent)fprintf(std_err,"Was:\t%.2f\n",YspaceFactor);
+      token = strtok(NULL,TOKENS);
+      YspaceFactor = atof(token);
+    }else if(strcmp(token,"X_SHIFT_FACTOR")==0){
+      if(!silent)fprintf(std_err,"Was:\t%.2f\n",XshiftFactor);
+      token = strtok(NULL,TOKENS);
+      XshiftFactor = atof(token);
+      if(!silent)fprintf(std_err,"Now Is:\t%.2f\n",XshiftFactor);
+    }else if(strcmp(token,"Y_SHIFT_FACTOR")==0){
+      if(!silent)fprintf(std_err,"Was:\t%.2f\n",YshiftFactor);
+      token = strtok(NULL,TOKENS);
+      YshiftFactor = atof(token);
+      if(!silent)fprintf(std_err,"Now Is:\t%.2f\n",YshiftFactor);
+    }else if(strcmp(token,"VERTICAL_SPACING")==0){
+      if(!silent)fprintf(std_err,"Was:\t%d\n",Vspacing);
+      token = strtok(NULL,TOKENS);
+      Vspacing = (int) atol(token);
+      if(!silent)fprintf(std_err,"Now Is:\t%d\n",Vspacing);
+    }else if(strcmp(token,"DEFINE_FONT")==0){
+      token = strtok(NULL,TOKENS);
+      fnum = atoi(token);                      /* font number */
+      token = strtok(NULL,TOKENS);           /* font name */
+      fname = strcpy(fname,token);
+      token = strtok(NULL,TOKENS);
+      if(strcmp(token,"DEFAULT")==0){
+       fpoint = pointsize;
+      }else if(strcmp(token,"REL")==0){
+       token = strtok(NULL,TOKENS);
+       fpoint = pointsize * atof(token);
+      }else{
+       fpoint = atof(token);
+      }
+      ALDefineFont(fnum,fname,fpoint,outf);
+    }else if(strcmp(token,"DEFINE_COLOUR")==0 || strcmp(token,"DEFINE_COLOR")==0){
+       /* new style 
+          define_colour <colour_number | colour type> colour_name r g b <colour_number> */
+       /* e.g. define_colour 1 1.0 1.0 1.0
+               (same as before)
+               define_colour rgb red 1.0 0.0 0.0 7
+               (define an rgb colour (red,green,blue),colour_number)
+               define_colour hsb red 1.0 0.0 0.0 9
+               (define an hsb colour (hue,sat,bright),colour_number)
+           currently can use either hsb OR rgb, but not mix them
+        */
+      use_colour = 1;
+      token = strtok(NULL,TOKENS);
+      tstring = GJstoupper(token);
+      if(strcmp(tstring,"RGB")==0 || strcmp(tstring,"HSB")==0){
+         token = strtok(NULL,TOKENS);
+         colname = GJstrdup(token);
+         token = strtok(NULL,TOKENS);
+         red = atof(token);
+         token = strtok(NULL,TOKENS);
+         green = atof(token);
+         token = strtok(NULL,TOKENS);
+         blue = atof(token);
+         token = strtok(NULL,TOKENS);
+         fnum = atoi(token);
+      }else{
+         fnum = atoi(token);                      /* colour number */
+         token = strtok(NULL,TOKENS);
+         red = atof(token);
+         token = strtok(NULL,TOKENS);
+         green = atof(token);
+         token = strtok(NULL,TOKENS);
+         blue = atof(token);
+
+      }
+      /* for now just ignore the colour name - we'll allow use of this later */
+      ALDefineColour(fnum,tstring,red,green,blue,outf);
+      GJfree(tstring);
+    }else if(strcmp(token,"ADD_SEQ")==0){
+      token = strtok(NULL,TOKENS);
+      adds[nadds].pos = atoi(token);
+      token = strtok(NULL,TOKENS);
+      adds[nadds].num = atoi(token);
+      ++nadds;
+    }else if(strcmp(token,"DO_TICKS")==0){
+      do_ticks=1;
+    }else if(strcmp(token,"NUMBER_INT")==0){
+      token = strtok(NULL,TOKENS);
+      number_int = atoi(token);
+      if(!silent)fprintf(std_err,"Sequence Numbering interval now:\t%d\n",number_int);
+    }else if(strcmp(token,"NO_NUMBERS")==0){
+      res_numbers = 0;
+    }else if(strcmp(token,"NUMBER_COLOUR")==0){
+       token = strtok(NULL,TOKENS);
+       number_colour = atoi(token);
+    }else if(strcmp(token,"SINGLE_PAGE")==0){
+      /* if this is set, then alscript assumes a single page - 
+        just adds a bounding box for now*/
+      if(!silent)fprintf(std_err,"Single page was: %d\n",singlepage);
+      singlepage = 1;
+      if(!silent)fprintf(std_err,"Single page now: %d\n",singlepage);
+    }else if(strcmp(token,"BOUNDING_BOX")==0){
+      ALGetFourInt(&bounding_box[0],&bounding_box[1],
+                  &bounding_box[2],&bounding_box[3]);
+      if(!silent){
+       fprintf(std_err,"Bounding box set to: %d %d %d %d\n",
+               bounding_box[0],bounding_box[1],
+               bounding_box[2],bounding_box[3]);
+      }
+    }else if(strcmp(token,"BACKGROUND_REGION") == 0){
+       /* set the region of the background to colour */
+       ALGetFourInt(&background_region[0],&background_region[1],
+                    &background_region[2],&background_region[3]);
+      if(!silent){
+       fprintf(std_err,"Background region set to: %d %d %d %d\n",
+               background_region[0],background_region[1],
+               background_region[2],background_region[3]);
+      }
+    }else if(strcmp(token,"ID_ONLY_ON_FIRST_LINE")==0){
+       /* flag to indicate identifiers only on first line!*/
+       id_only_on_first = 1;
+    }else if(strcmp(token,"BACKGROUND_COLOUR") ==0){
+       /* set the colour for background defined by background_region */
+       token = strtok(NULL,TOKENS);
+       background_colour = atoi(token);
+    }else if(strcmp(token,"SETUP")==0){
+      if(!silent)fprintf(std_err,"Initial Commands read - Establishing basic settings\n");
+      break;
+    }else{
+      fprintf(std_err,"%s",buff);
+      error("Unrecognised Step 1 command",1);
+
+    }
+  }
+
+  if(outf == std_out){
+    if(!silent)fprintf(std_err,"Output file undefined - will write to stdout\n");
+  }
+
+  
+  if(inf == std_in){
+    if(!silent)fprintf(std_err,"Block file undefined - will read from stdin\n");
+  }
+  
+  bloc = (struct seqdat *) malloc(sizeof(struct seqdat) * MAXnbloc);
+  mcheck((char *) bloc,"Cannot get space for bloc");
+  if(!Agetbloc(inf,bloc,&nseq))error("Cannot read bloc file",1);
+
+  ckdd(bloc,nseq);
+
+  if(pirsave){
+    if(!save_pir(bloc,nseq,pirf))error("Cannot write to pirf file",1);
+    exit(0);
+  }
+
+  if(msfsave){
+    if(!save_msf(bloc,nseq,msff))error("Cannot write to msf file",1);
+    exit(0);
+  }
+
+  /* Initialise relnum to 1..n*/
+  /*  relnum = (int *) GJmalloc(sizeof(int) * MAXslen); */
+  /*  for(i=1;i<MAXslen;++i){ */
+  /*      relnum[i]=i;     */
+  /*  }  */
+
+  /* Initialise relnum to 1..n*/
+  /* 29 July 1998 - allocate relnum to MAXslen *2.  with pointer in the middle */
+
+  trelnum = (int *) GJmalloc(sizeof(int) * MAXslen * 2);
+  for(i=1;i<(MAXslen +1);++i){
+      trelnum[i]=0;
+  }
+  relnum = &trelnum[MAXslen];
+  for(i=1;i<MAXslen;++i){
+    relnum[i] = i;
+  }
+
+  /* do a check of the adds array to make sure there are no out of bounds
+     requests
+     */
+  adderr = 0;
+  for(i=0;i<nadds;++i){
+    if(adds[i].pos > nseq){
+      ++adderr;
+      fprintf(std_err,"Error in ADD_SEQ request: %d %d\n",adds[i].pos,adds[i].num);
+      fprintf(std_err,"%d is greater than the number of sequences in the block file(%d)\n",adds[i].pos,nseq);
+      fprintf(std_err,"Please see the manual for help on using ADD_SEQ\n");
+    }
+  }
+  if(adderr > 0){
+    fprintf(std_err,"%d ADD_SEQ errors - exiting\n",adderr);
+    exit(-1);
+  }
+
+
+  if(nadds > 0){
+     if(!silent)fprintf(std_err,"Making extra space for %d additions\n",nadds);
+     natot = 0;
+     for(i=0;i<nadds;++i){
+       natot += adds[i].num;
+     }
+     if(!silent)fprintf(std_err,"Total of %d extra sequences\n",natot);
+     addbloc = (struct seqdat *) malloc(sizeof(struct seqdat) *(nseq+natot+1));
+     i = 0;
+     j = 0;
+     k = 0;
+     while(i < nseq+1){
+       if(k < nadds && i==adds[k].pos){
+         /* reserve space for the new sequences and set to blank*/
+         for(l=0;l<adds[k].num;++l){
+            ++j;
+            addbloc[j].id = (char *) malloc(sizeof(char) * MAXilen);
+            addbloc[j].id = GJstrblank(addbloc[j].id,MAXilen);
+            addbloc[j].seq = (char *) malloc(sizeof(char) * (bloc[1].slen+1));
+            addbloc[j].seq = GJstrblank(addbloc[j].seq,bloc[1].slen+1);
+         }
+         ++k;
+       }else{
+         /* just copy the pointers to the bloc sequences */
+         ++i;
+         ++j;
+         if(i<nseq+1){
+           addbloc[j].id = bloc[i].id;
+           addbloc[j].title = bloc[i].title;
+           addbloc[j].seq = bloc[i].seq;
+         }
+       }
+     }
+     addbloc[1].slen = bloc[1].slen;
+     temp = bloc;
+     bloc = addbloc;
+     addbloc = temp;
+     nseq += natot;
+     if(!silent)fprintf(std_err,"Total number of sequences now: %d\n",nseq);
+  }
+  msl = bloc[1].slen-2;  /* maximum sequence length defined */
+
+  xmin = 1;  ymin = 1; xmax = msl+1; ymax = nseq;
+
+  PSSetupPage(orientation,1,outf);
+  ALSetPageLimits();  
+
+  CtopSpace = 2;    /* set top 2 lines for numbers */
+
+  /* now set up the bounding box and background 
+     based on current values of xoff, yoff, width and height 
+     these can be overridden by step 2 commands
+
+  bounding_box[0] = 0;
+  bounding_box[1] = 0;
+  bounding_box[2] = width;
+  bounding_box[3] = height;
+  */
+
+  /* set the background colour region equal to the default bounding box
+  background_region[0] = bounding_box[0];
+  background_region[1] = bounding_box[1];
+  background_region[2] = bounding_box[2];
+  background_region[3] = bounding_box[3];
+  */
+
+  if(background_colour != 99)ALColourBackground(outf,background_colour,background_region);
+
+  
+
+/*  TVspace = nseq;*/
+/*  ALReserveSpace(TOP,2);*/
+
+  
+  /* allocate to +1 size to allow indexing from 1...max */
+  /* lines array - stored info on where to draw lines */
+  lines = uchararr(bloc[1].slen+1,nseq+1);
+  if(lines == NULL)error("No space for lines array\n",1);
+  GJUCinit(lines,bloc[1].slen+1,nseq+1,0);
+
+  /* array holds grey value for each character fill*/
+  fills = chararr(bloc[1].slen+1,nseq+1);
+  if(fills == NULL)error("No space for fills array\n",1);
+  GJCinit(fills,bloc[1].slen+1,nseq+1,-1);
+
+  /* allocate to +1 size to allow indexing from 1...max */
+  /* fonts array - stores a number representing the font to use for each residue */
+  /* default font is font 0 */
+  fonts = uchararr(bloc[1].slen+1,nseq+1);
+  if(fonts == NULL)error("No space for fonts array\n",1);
+  GJUCinit(fonts,bloc[1].slen+1,nseq+1,0);
+
+  /* inverse indicates whether the the text at i j should be printed in white */
+  inverse = uchararr(bloc[1].slen+1,nseq+1);
+  if(inverse == NULL)error("No space for inverse array\n",1);
+  GJUCinit(inverse,bloc[1].slen+1,nseq+1,0);
+
+  /* colour arrays - define the colour to use for shading and lettering */
+  /* default colour numbers are 99 for white and 100 for black */
+  s_colour = uchararr(bloc[1].slen+1,nseq+1);       /* shading colour */
+  if(s_colour == NULL)error("No space for s_colour array\n",1);
+  GJUCinit(s_colour,bloc[1].slen+1,nseq+1,background_colour);
+  c_colour = uchararr(bloc[1].slen+1,nseq+1);       /* character colour */
+  if(c_colour == NULL)error("No space for c_colour array\n",1);
+  GJUCinit(c_colour,bloc[1].slen+1,nseq+1,100);
+  left_line_colour = uchararr(bloc[1].slen+1,nseq+1);       /* left line colour */
+  if(left_line_colour == NULL)error("No space for left_line_colour array\n",1);
+  GJUCinit(left_line_colour,bloc[1].slen+1,nseq+1,100);
+  right_line_colour = uchararr(bloc[1].slen+1,nseq+1);       /* right line colour */
+  if(right_line_colour == NULL)error("No space for right_line_colour array\n",1);
+  GJUCinit(right_line_colour,bloc[1].slen+1,nseq+1,100);
+  top_line_colour = uchararr(bloc[1].slen+1,nseq+1);       /* top line colour */
+  if(top_line_colour == NULL)error("No space for top_line_colour array\n",1);
+  GJUCinit(top_line_colour,bloc[1].slen+1,nseq+1,100);
+  bottom_line_colour = uchararr(bloc[1].slen+1,nseq+1);       /* bottom line colour */
+  if(bottom_line_colour == NULL)error("No space for bottom_line_colour array\n",1);
+  GJUCinit(bottom_line_colour,bloc[1].slen+1,nseq+1,100);
+  text_colour = uchararr(bloc[1].slen+1,nseq+1);       /* text colour */
+  if(text_colour == NULL)error("No space for text_colour array\n",1);
+  GJUCinit(text_colour,bloc[1].slen+1,nseq+1,100);
+
+  /* holds font information for each identifier */
+  idfonts = (unsigned char *) malloc(sizeof(unsigned char) * nseq+1);
+  for(i=0;i<nseq+1;++i){
+    idfonts[i]= (unsigned char) 0;
+  }
+  /* holds colour information for each identifier */
+  id_colour = (unsigned char *) GJmalloc(sizeof(unsigned char) * nseq+1);
+  for(i=0;i<nseq+1;++i){
+    id_colour[i]= (unsigned char) 100;
+  }
+  /* holds conservation values */
+  consval = (int *) GJmalloc(sizeof(int) * bloc[1].slen);
+  GJIinit(consval,bloc[1].slen,0);
+
+
+  /* array holds pointers to text strings at each [i][j] point*/
+  texts = (char ***) malloc(sizeof(char **) * (bloc[1].slen+1));
+  rowsiz = sizeof(char *) * (nseq + 1);
+  for(k=0;k<bloc[1].slen+1;++k){
+    texts[k] = (char **) malloc(rowsiz);
+    for(i=0;i<(nseq+1);++i){
+      texts[k][i]=NULL;
+    }
+  }
+  
+  Yindx = (int *) malloc(sizeof(int)*(nseq+1));
+  for(i=1,j=nseq;i<nseq+1;++i,--j){
+    Yindx[i] = j;
+  }
+
+  numbers = ALCreateNumbers(0,number_int,bloc[1].slen,4);
+  ticks = ALCreateTicks(0,number_int,bloc[1].slen);
+  CseqTop = nseq;
+
+  while(buff = fgets(buff,MAXtlen,cf)){
+    if(buff == NULL) break;
+    if(!silent)echo(buff);
+    token = strtok(buff,TOKENS);
+    if(token == NULL) break;
+    token = GJstoup(token);
+    if(*token == '#'){
+      if(!silent)echo("Comment\n");
+    }else if(strcmp(token,"SILENT_MODE")==0){
+        if(!silent){
+         silent=1;
+       }else{
+         silent=0;
+       }
+/* This block has moved to the MODE 1 section
+    }else if(strcmp(token,"BOUNDING_BOX")==0){
+      ALGetFourInt(&bounding_box[0],&bounding_box[1],
+                  &bounding_box[2],&bounding_box[3]);
+
+    }else if(strcmp(token,"BACKGROUND_REGION") == 0){
+       set the region of the background to colour 
+       ALGetFourInt(&background_region[0],&background_region[1],
+                    &background_region[2],&background_region[3]);
+*/
+    }else if(strcmp(token,"RESERVE_SPACE_TOP")==0){
+      token = strtok(NULL,TOKENS);
+      ALReserveSpace(TOP,atoi(token));
+    }else if(strcmp(token,"RESERVE_SPACE_BOTTOM")==0){
+      token = strtok(NULL,TOKENS);
+      ALReserveSpace(BOTTOM,atoi(token));
+      CseqTop = nseq + CbottomSpace;
+    }else if(strcmp(token,"SURROUND_CHARS")==0){
+      token = strtok(NULL,TOKENS);
+      charstring = token;
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      ALSurroundChars(bloc,lines,relnum[sx],sy,relnum[ex],ey,nseq,charstring);
+    }else if(strcmp(token,"SHADE_CHARS")==0){
+      token = strtok(NULL,TOKENS);
+      charstring = token;
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALShadeChars(bloc,fills,relnum[sx],sy,relnum[ex],ey,nseq,charstring,(float)atof(token));
+    }else if(strcmp(token,"FONT_CHARS")==0){
+      token = strtok(NULL,TOKENS);
+      charstring = token;
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALFontChars(bloc,fonts,relnum[sx],sy,relnum[ex],ey,charstring,atoi(token));
+    }else if(strcmp(token,"CCOL_CHARS")==0){  /* colour characters */
+      if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+      token = strtok(NULL,TOKENS);
+      charstring = token;
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALColourChars(bloc,c_colour,relnum[sx],sy,relnum[ex],ey,charstring,atoi(token));
+    }else if(strcmp(token,"SCOL_CHARS")==0){  /* colour character backgrounds */
+      if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+      token = strtok(NULL,TOKENS);
+      charstring = token;
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALSColChars(bloc,s_colour,relnum[sx],sy,relnum[ex],ey,nseq,charstring,(unsigned char) atoi(token));
+    }else if(strcmp(token,"INVERSE_CHARS")==0){
+      token = strtok(NULL,TOKENS);
+      charstring = token;
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      ALInverseChars(bloc,inverse,relnum[sx],sy,relnum[ex],ey,charstring);
+    }else if(strcmp(token,"SUB_CHARS")==0){
+       token = strtok(NULL,TOKENS);
+       if(strcmp(token,"ALL")==0){
+         token = strtok(NULL,TOKENS);
+         oldchar = ALChekSpace(token);
+         token = strtok(NULL,TOKENS);
+         newchar = ALChekSpace(token); 
+         ALSubChars(bloc,1,1,bloc[1].slen-1,nseq,oldchar,newchar);
+       }else{
+         sx = atoi(token);
+         ALGetThreeInt(&sy,&ex,&ey);
+         token = strtok(NULL,TOKENS);
+         oldchar = ALChekSpace(token);
+         token = strtok(NULL,TOKENS);
+         newchar = ALChekSpace(token);
+         ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+         ALSubChars(bloc,relnum[sx],sy,relnum[ex],ey,oldchar,newchar);
+       }
+    }else if(strcmp(token,"SUB_ID")==0){
+       token = strtok(NULL,"\"");
+       sx = atoi(token);
+       token = strtok(NULL,"\"");
+        ALCheckLegalRange(xmin,1,xmax,sx,xmin,ymin,xmax,ymax);
+       bloc[sx].id = (char *) realloc(bloc[sx].id,sizeof(char)*(strlen(token)+1));
+       bloc[sx].id = strcpy(bloc[sx].id,token);
+    }else if(strcmp(token,"FONT_REGION")==0){
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      token = strtok(NULL,TOKENS);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      ALFontRegion(fonts,relnum[sx],sy,relnum[ex],ey,atoi(token));
+    }else if(strcmp(token,"FONT_RESIDUE")==0){
+      token = strtok(NULL,TOKENS);
+      sx = atoi(token);
+      token=strtok(NULL,TOKENS);
+      sy = atoi(token);
+      token=strtok(NULL,TOKENS);
+      ALCheckLegalRange(relnum[sx],sy,relnum[sx],sy,xmin,ymin,xmax,ymax);
+      ALFontRegion(fonts,relnum[sx],sy,relnum[sx],sy,atoi(token));
+    }else if(strcmp(token,"LINE")==0){
+      token = strtok(NULL,TOKENS);
+      if(strcmp(token,"TOP")==0){
+       ALGetThreeInt(&sx,&sy,&ex);
+        if(ex > bloc[1].slen-1) ex = bloc[1].slen-1;
+        ALCheckLegalRange(relnum[sx],sy,relnum[ex],sy,xmin,ymin,xmax,ymax);
+       ALDoLine(lines,relnum[sx],sy,relnum[ex],LINE_TOP,Yindx);
+      }else if(strcmp(token,"BOTTOM")==0){
+       ALGetThreeInt(&sx,&sy,&ex);     
+        ALCheckLegalRange(relnum[sx],sy,relnum[ex],sy,xmin,ymin,xmax,ymax);
+        if(ex > bloc[1].slen-1) ex = bloc[1].slen-1;
+       ALDoLine(lines,relnum[sx],sy,relnum[ex],LINE_BOTTOM,Yindx);
+      }else if(strcmp(token,"LEFT")==0){
+       ALGetThreeInt(&sx,&sy,&ey);     
+        ALCheckLegalRange(relnum[sx],sy,relnum[sx],ey,xmin,ymin,xmax,ymax);
+        if(ey > nseq) ey = nseq;
+       ALDoLine(lines,relnum[sx],sy,ey,LINE_LEFT,Yindx);
+      }else if(strcmp(token,"RIGHT")==0){
+       ALGetThreeInt(&sx,&sy,&ey);     
+        ALCheckLegalRange(relnum[sx],sy,relnum[sx],ey,xmin,ymin,xmax,ymax);
+        if(ey > nseq) ey = nseq;
+       ALDoLine(lines,relnum[sx],sy,ey,LINE_RIGHT,Yindx);
+      }else{
+       error("Illegal LINE command\n",1);
+      }
+    }else if(strcmp(token,"BOX_REGION")==0){
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      ALBoxRegion(lines,relnum[sx],sy,relnum[ex],ey,Yindx);
+    }else if(strcmp(token,"SHADE_REGION")==0){
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALFilRegion(fills,relnum[sx],sy,relnum[ex],ey,Yindx,(float)atof(token));
+    }else if(strcmp(token,"SHADE_RES")==0){
+      ALGetTwoInt(&sx,&sy);
+      ALCheckLegalRange(relnum[sx],sy,relnum[sx],sy,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALFilRegion(fills,relnum[sx],sy,relnum[sx],sy,Yindx,(float)atof(token));
+    }else if(strcmp(token,"COLOUR_REGION")==0 || strcmp(token,"COLOR_REGION")==0){
+      if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALColRegion(s_colour,relnum[sx],sy,relnum[ex],ey,Yindx,(unsigned char) atoi(token));
+    }else if(strcmp(token,"COLOUR_TEXT_REGION")==0 || strcmp(token,"COLOR_TEXT_REGION")==0){
+      if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALColRRegion(text_colour,relnum[sx],sy,relnum[ex],ey,(unsigned char) atoi(token));
+    }else if(strcmp(token,"COLOUR_RES")==0 || strcmp(token,"COLOR_RES")==0){
+      if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+      ALGetTwoInt(&sx,&sy);
+      ALCheckLegalRange(relnum[sx],sy,relnum[sx],sy,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALColRRegion(s_colour,relnum[sx],sy,relnum[sx],sy,(unsigned char) atoi(token));
+    }else if(strcmp(token,"CCOLOUR_REGION")==0 || strcmp(token,"CCOLOR_REGION")==0){
+      if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALColRRegion(c_colour,relnum[sx],sy,relnum[ex],ey,(unsigned char) atoi(token));
+    }else if(strcmp(token,"COLOUR_LINE_REGION")==0 || strcmp(token,"COLOR_LINE_REGION")==0){
+      if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+      ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+      ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+      token = strtok(NULL,TOKENS);
+      ALColRegion(left_line_colour,relnum[sx],sy,relnum[ex],ey,Yindx,(unsigned char) atoi(token));
+      ALColRegion(right_line_colour,relnum[sx],sy,relnum[ex],ey,Yindx,(unsigned char) atoi(token));
+      ALColRegion(top_line_colour,relnum[sx],sy,relnum[ex],ey,Yindx,(unsigned char) atoi(token));
+      ALColRegion(bottom_line_colour,relnum[sx],sy,relnum[ex],ey,Yindx,(unsigned char) atoi(token));
+    }else if(strcmp(token,"CCOLOUR_RES")==0 || strcmp(token,"CCOLOR_RES")==0){
+      if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+      ALGetTwoInt(&sx,&sy);
+      token = strtok(NULL,TOKENS);
+      ALCheckLegalRange(relnum[sx],sy,relnum[sx],sy,xmin,ymin,xmax,ymax);
+      ALColRRegion(c_colour,relnum[sx],sy,relnum[sx],sy,(unsigned char) atoi(token));
+     }else if(strcmp(token,"MASK")==0){
+        /* mask commands */
+        token = strtok(NULL,TOKENS);
+        if(strcmp(token,"SETUP")==0){
+            if(mask == NULL){
+                mask = uchararr(bloc[1].slen+1,nseq+1);
+                GJUCinit(mask,bloc[1].slen+1,nseq+1,0);
+            }else{
+                GJUCinit(mask,bloc[1].slen+1,nseq+1,0);
+           }
+       }else if(strcmp(token,"RESET")==0){
+            GJUCinit(mask,bloc[1].slen+1,nseq+1,0);
+        }else if(strcmp(token,"LEGAL")==0){
+            /* get the legal character list */
+            token = strtok(NULL,TOKENS);
+            if(legal != NULL) GJfree(legal);
+            legal = GJstrdup(token);
+            if(!silent)fprintf(stderr,"legal:%s\n",legal);
+        }else if(strcmp(token,"ILLEGAL")==0){
+            /* get the illegal character list */
+            token = strtok(NULL,TOKENS);
+            if(illegal != NULL) GJfree(illegal);
+            illegal = GJstrdup(token);
+            if(!silent)fprintf(stderr,"illegal:%s:\n",illegal);
+        }else if(strcmp(token,"ID")==0){
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            token = strtok(NULL,TOKENS);
+            id_cut = atoi(token);
+            if(id_cut < (int) ( ( ((float) (ey-sy+1) / 2.0) + 0.6))){
+                error("ID cutoff must be > half the number of sequences",1);
+            }
+            ALid_mask(mask,bloc,relnum[sx],sy,relnum[ex],ey,id_cut,legal,illegal);
+        }else if(strcmp(token,"AGREE")==0){
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            token= strtok(NULL,TOKENS);
+            ALagree_mask(mask,bloc,relnum[sx],sy,relnum[ex],ey,atoi(token));
+        }else if(strcmp(token,"FRE")==0){
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            ALfre_mask(mask,bloc,relnum[sx],sy,relnum[ex],ey,legal,illegal);
+        }else if(strcmp(token,"NOT")==0){
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            ALnot_mask(mask,relnum[sx],sy,relnum[ex],ey);
+        }else if(strcmp(token,"SUB")==0){
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            token=strtok(NULL,TOKENS);
+            ALsub_mask(mask,bloc,relnum[sx],sy,relnum[ex],ey,token[0]);
+        }else if(strcmp(token,"REGION")==0){
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            ALMask(mask,relnum[sx],sy,relnum[ex],ey);
+        }else if(strcmp(token,"CONSERVATION")==0){
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+           token=strtok(NULL,TOKENS);
+           conscut = atoi(token);
+           if(!silent)fprintf(std_err,"Conservation Cutoff:%d\n",conscut);
+            ALConsMask(mask,relnum[sx],sy,relnum[ex],ey,consval,conscut);
+        }else if(strcmp(token,"BOX")==0){
+            /* box the masked residues - ie surround them*/
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            ALSurroundMask(mask,bloc,lines,relnum[sx],sy,relnum[ex],ey,nseq);
+        }else if(strcmp(token,"SHADE")==0){
+            /* shade the masked residues - */
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            token = strtok(NULL,TOKENS);
+            ALShadeMask(mask,fills,relnum[sx],sy,relnum[ex],ey,Yindx,(float)atof(token));
+        }else if(strcmp(token,"FONT")==0){
+            /* set the font of the masked residues - */
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            token = strtok(NULL,TOKENS);
+            ALFontMask(mask,fonts,relnum[sx],sy,relnum[ex],ey,(unsigned char) atoi(token));
+        }else if(strcmp(token,"INVERSE")==0){
+            /* invert the masked residues - */
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            token = strtok(NULL,TOKENS);
+            ALInverseMask(mask,inverse,relnum[sx],sy,relnum[ex],ey);
+        }else if(strcmp(token,"SCOL")==0){
+            if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            token = strtok(NULL,TOKENS);
+            ALSColMask(mask,s_colour,relnum[sx],sy,relnum[ex],ey,nseq,(unsigned char) atoi(token));
+        }else if(strcmp(token,"CCOL")==0){
+            if(!use_colour)error("You must use the DEFINE_COLOUR command first",1);
+            ALGetAllRange(&sx,&sy,&ex,&ey,xmax,nseq);
+           ALCheckLegalRange(relnum[sx],sy,relnum[ex],ey,xmin,ymin,xmax,ymax);
+            token = strtok(NULL,TOKENS);
+            ALColourMask(mask,c_colour,relnum[sx],sy,relnum[ex],ey,(unsigned char) atoi(token));
+       }else{
+           error("Unrecognised MASK qualifier\n",1);
+       }
+    }else if(strcmp(token,"TEXT")==0){
+      token=strtok(NULL,TOKENS);
+      sx = atoi(token);
+      token=strtok(NULL,"\"");
+      sy = atoi(token);
+      token=strtok(NULL,"\"");
+      ALCheckLegalRange(relnum[sx],sy,relnum[sx],sy,xmin,ymin,xmax,ymax);
+      texts[relnum[sx]][sy] = (char *) malloc(sizeof(char)*(strlen(token)+1));
+      texts[relnum[sx]][sy] = (char *) strcpy(texts[relnum[sx]][sy],token);
+    }else if(strcmp(token,"NUMBERS")==0){
+        error("Numbers not implemented",1);
+    }else if(strcmp(token,"ID_FONT")==0){
+      token = strtok(NULL,TOKENS);
+      if(strcmp(token,"ALL")==0){
+       token = strtok(NULL,TOKENS);
+       for(i=1;i<nseq+1;++i)idfonts[i]= (unsigned char) atoi(token);
+      }else{
+       sx = atoi(token);
+       token = strtok(NULL,TOKENS);
+       ALCheckLegalRange(xmin,ymin,xmax,sx,xmin,ymin,xmax,ymax);
+       idfonts[sx] = atoi(token);
+      }
+    }else if(strcmp(token,"ID_COLOUR")==0){
+      token = strtok(NULL,TOKENS);
+      if(strcmp(token,"ALL")==0){
+       token = strtok(NULL,TOKENS);
+       for(i=1;i<nseq+1;++i)id_colour[i]= (unsigned char) atoi(token);
+      }else{
+       sx = atoi(token);
+       ALCheckLegalRange(xmin,ymin,xmax,sx,xmin,ymin,xmax,ymax);
+       token = strtok(NULL,TOKENS);
+       id_colour[sx] = atoi(token);
+      }
+    }else if(strcmp(token,"HELIX")==0){
+       ALGetThreeInt(&sx,&sy,&ex);
+        ALCheckLegalRange(relnum[sx],sy,relnum[ex],sy,xmin,ymin,xmax,ymax);
+       ALMakeHelixText(relnum[sx],sy,relnum[ex],texts);
+    }else if(strcmp(token,"STRAND")==0){
+       ALGetThreeInt(&sx,&sy,&ex);
+        ALCheckLegalRange(relnum[sx],sy,relnum[ex],sy,xmin,ymin,xmax,ymax);
+       ALMakeStrandText(relnum[sx],sy,relnum[ex],texts);
+    }else if(strcmp(token,"COIL")==0){
+       ALGetThreeInt(&sx,&sy,&ex);
+        ALCheckLegalRange(relnum[sx],sy,relnum[ex],sy,xmin,ymin,xmax,ymax);
+       ALMakeCoilText(relnum[sx],sy,relnum[ex],texts);
+    }else if(strcmp(token,"CALCONS")==0){
+       /* calculate conservation for the range */
+       ALGetFourInt(&sx,&sy,&ex,&ey);
+        ALCheckLegalRange(relnum[sx],relnum[sy],relnum[ex],relnum[ey],xmin,ymin,xmax,ymax);
+       consval = ALCalCons(bloc,relnum[sx],relnum[sy],relnum[ex],relnum[ey],
+                        consval,bloc[1].slen);
+/*     fprintf(std_err,"Conservation Values\n"); */
+/*     for(k=1;k<bloc[1].slen-1;++k){*/
+/*         fprintf(std_err,"%d:%d\n",k,consval[k]);*/
+/*     }*/
+    }else if(strcmp(token,"RELATIVE_TO")==0){
+       token = strtok(NULL,TOKENS);
+       relative_seq = atoi(token);
+       fprintf(stderr,"RELATIVE SEQ %d\n",relative_seq);
+       fprintf(stderr,"bloc[relative_seq].slen+1] %d\n",
+               bloc[relative_seq].slen+1);
+       token = strtok(NULL,TOKENS);
+       if(token != NULL){
+           /* there is a first residue definition */
+           firstres = atoi(token);
+           fprintf(stderr,"First position is number: %d\n",firstres);
+       }else{
+           firstres = 1;
+       }
+       if(relative_seq != 0){
+           k= firstres - 1;
+           for(i=1;i<bloc[1].slen+1;++i){
+               /* for now assume all gaps are blanks */
+               if(bloc[relative_seq].seq[i] != ' '){
+                   ++k;
+                   relnum[k] = i;
+               }
+           }
+           /* increase the max allowed X value to the max of xmax and k */
+           /* leave the minimum value at 1 since otherwise we will not be able to mix
+              absolute and relative numbers without the Check routine skwawking */
+           if(k > xmax ) xmax = k;
+       }else{
+           for(i=1;i<bloc[1].slen+1;++i){
+               relnum[i] = i;
+           }
+       }
+    }else{
+      fprintf(std_err,"%s",buff);
+      error("Unrecognised Step 2 command\n",1);
+    }
+  }
+  if(!silent){
+    ALReportInfo(nseq,std_err);
+  }
+  ALCheckSinglePage(nseq,bloc[1].slen,silent);
+
+  start_aa = 1;
+  totalpage = npage * Csheet;
+
+  /* get how many blocks of sequence we can fit per page */
+  nspage = Cheight/(nseq+CtopSpace+Vspacing);
+  if(nspage < 1){
+    nspage = 1;
+  }
+  nbp = 0;
+
+  if(!silent)fprintf(std_err,"Will write a maximum of %d blocks of sequence per page\n",nspage);
+  if(!silent)fprintf(std_err,"Background region: %d %d %d %d\n",
+                    background_region[0],
+                    background_region[1],
+                    background_region[2],
+                    background_region[3]);
+  if(!silent && singlepage)fprintf(std_err,"Bounding box: %d %d %d %d\n",
+                    bounding_box[0],
+                    bounding_box[1],
+                    bounding_box[2],
+                    bounding_box[3]);
+
+  /* MARKER */
+
+  if((Cwidth - Cidwidth > 0)){
+    if(!silent)fprintf(std_err,"Saving  (%d) Pages to file\n",totalpage/nspage);
+  }else{
+    fprintf(std_err,"This pointsize is too large to print even a single character on the page\n");
+    fprintf(std_err,"Try a smaller pointsize - or\n");
+    fprintf(std_err,"Try reducing the Identifier width\n");
+    fprintf(std_err,"Increase the paper size\n");
+    fprintf(std_err,"You could do some PostScrip-ery to print partial characters\n");
+    fprintf(std_err,"After creating an alignment on a single page - see the CookBook\n");
+    exit(1);
+  }
+  lastY = 0;
+  nbpage = 0;
+  k = 0;
+  start_seq = 1;
+  while(k < totalpage){
+    start_aa = 1;
+    Ytemp = start_seq+Cheight-CtopSpace - 1;
+    if(Ytemp > nseq) Ytemp = nseq;
+    for(i=0;i<npage;++i){
+
+      if(nspage > 1){        /* more than one block per page */
+/*       fprintf(stderr,"nbp nspage %d %d\n",nbp,nspage);*/
+         if(k>0 && nbp == 0){ /* if not the first page, then setup page*/
+           PSSetupPage(orientation,nbpage+1,outf);
+           if(background_colour != 99){
+               ALColourBackground(outf,background_colour,background_region);
+           }
+         }
+         if(nbp>0){
+           /* if this is not the first block on the page, then */
+           /* translate the block of alignment back to origin  */
+           fprintf(outf,"%d %d translate\n",0,-lastY);
+         }
+         /* get new position for drawing and translate to this posn*/
+         lastY = Yspace*( Cheight-(nseq+CtopSpace)*(nbp+1) - (nbp*Vspacing) );
+         fprintf(outf,"%d %d translate\n",0,lastY);
+      }else{
+       if(k>0)PSSetupPage(orientation,k+1,outf);
+       if(background_colour != 99){
+           ALColourBackground(outf,background_colour,background_region);
+       }
+      }
+      if(id_only_on_first == 1 && nbp > 0 ){
+         /* save the Cseqwidth, then reset it to Cwidth - also set Cidwidth to 0*/
+         tempCseqwidth = Cseqwidth;
+         tempCidwidth = Cidwidth;
+         Cseqwidth = Cwidth;
+         Cidwidth = 0;
+      }
+
+      Xtemp = start_aa+Cseqwidth-1;
+      if(Xtemp > bloc[1].slen) Xtemp = bloc[1].slen;
+
+      fprintf(outf,"2 setlinecap\n");
+      fprintf(outf," %.2f setlinewidth\n",LineWidthFactor*pointsize);
+
+      ALDrawFills(fills,use_colour,s_colour,start_aa,nseq-Ytemp+1,Xtemp,nseq-start_seq+1,Cidwidth,CseqVoffset,outf);
+      ALDrawLines(lines,use_colour,
+                left_line_colour,
+                right_line_colour,
+                top_line_colour,
+                bottom_line_colour,
+                start_aa,nseq-Ytemp+1,Xtemp,nseq-start_seq+1,Cidwidth,CseqVoffset,outf);
+      if(!(id_only_on_first == 1 && (nbp > 0 || k > 0))){
+         /* don't output ID string if this is not the first block on the first page*/
+         ALOutId(bloc,use_colour,
+             id_colour,idfonts,start_seq,Ytemp,CseqVoffset,number_seqs,outf);
+      }
+      ALOutSeq(bloc,fonts,texts,inverse,use_colour,c_colour,
+              text_colour,background_colour,start_seq,Ytemp,start_aa,CseqVoffset,outf);
+      
+      if(res_numbers){
+       if(use_colour)PSSetColour(number_colour,outf);
+        if(do_ticks){
+          ALOutTicks(ticks,start_aa,Cidwidth,Ytemp-start_seq+1,bloc[1].slen,outf);
+          ALOutNumbers(numbers,start_aa,Cidwidth,Ytemp-start_seq+2,bloc[1].slen,outf);
+        }else{
+          ALOutNumbers(numbers,start_aa,Cidwidth,Ytemp-start_seq+1,bloc[1].slen,outf);
+        }
+      }
+      start_aa += Cseqwidth;
+
+      if(nspage > 1){
+       ++nbp;
+       if(nbp == nspage || k == totalpage-1){  /* put showpage command for page or last page */
+         PSShowPage(outf);
+         nbp = 0;
+         ++nbpage;
+       }
+      }else{
+       PSShowPage(outf);
+      }
+      ++k;
+    }
+    start_seq = Ytemp + 1;
+    if(id_only_on_first == 1 && nbp > 0){
+       /* reset the values - not strictly necessary */
+       Cseqwidth = tempCseqwidth;
+       Cidwidth = tempCidwidth;
+    }
+  }
+  return 1;
+}
+
+void ALShadeChars(struct seqdat *bloc,
+signed char **fill,
+int start_x,int start_y,int end_x,int end_y,
+int maxY,
+char *charlist,
+float grey)
+
+/* shade residues in charlist by grey value */
+
+{
+  int i,j,jpos;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y,jpos=(maxY-start_y+1);j<end_y+1;++j,--jpos){
+       if(strchr(charlist,bloc[j].seq[i])!=NULL){
+        ALFilRes(fill,i,jpos,grey);
+       }
+     }
+   }
+}
+void ALSColChars(struct seqdat *bloc,unsigned char **colour,int start_x,
+int start_y,int end_x,int end_y,int maxY,char *charlist,unsigned char colnum)
+
+/* colour residue backgrounds in charlist by colnum value */
+
+{
+  int i,j,jpos;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y,jpos=(maxY-start_y+1);j<end_y+1;++j,--jpos){
+       if(strchr(charlist,bloc[j].seq[i])!=NULL){
+        ALColRes(colour,i,jpos,colnum);
+       }
+     }
+   }
+}
+
+void ALSColMask(unsigned char **mask,unsigned char **colour,
+                int start_x,int start_y,int end_x,int end_y,int maxY,
+               unsigned char colnum)
+
+/* colour residue backgrounds in mask by colnum value */
+
+{
+  int i,j,jpos;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y,jpos=(maxY-start_y+1);j<end_y+1;++j,--jpos){
+       if(mask[i][j]==1){
+        ALColRes(colour,i,jpos,colnum);
+       }
+     }
+   }
+}
+void ALInverseChars(struct seqdat *bloc,unsigned char **inverse,
+                   int start_x,int start_y,int end_x,int end_y,char *charlist)
+
+/* Invert the characters within the range */
+/* 18/Jan/93:  Allow inverted chars to be reverted */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+       if(strchr(charlist,bloc[j].seq[i])!=NULL){
+                if(inverse[i][j] == 1){
+                       inverse[i][j] = (unsigned char) 0;
+                }else{
+               inverse[i][j] = (unsigned char ) 1;
+        }
+       }
+     }
+   }
+}
+void ALInverseMask(unsigned char **mask,unsigned char **inverse,
+                  int start_x,int start_y,int end_x,int end_y)
+/* Invert the characters within the range of the mask*/
+/* 18/Jan/93:  Allow inverted chars to be reverted */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+       if(mask[i][j]){
+                if(inverse[i][j] == 1){
+                       inverse[i][j] = (unsigned char) 0;
+                }else{
+               inverse[i][j] = (unsigned char ) 1;
+        }
+       }
+     }
+   }
+}
+
+void ALFontChars(struct seqdat *bloc,unsigned char **fonts,
+                int start_x,int start_y,int end_x,int end_y,char *charlist,unsigned char fontnum)
+
+/* set the characters within the range to the fontnum */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+       if(strchr(charlist,bloc[j].seq[i])!=NULL){
+        fonts[i][j] = fontnum;
+       }
+     }
+   }
+}
+void ALFontRegion(unsigned char **fonts,
+                 int start_x,int start_y,int end_x,int end_y,
+                 unsigned char fontnum)
+/* set the characters within the range to the fontnum */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+        fonts[i][j] = fontnum;
+     }
+   }
+}
+void ALFontMask(unsigned char **mask,unsigned char **fonts,
+               int start_x,int start_y,int end_x,int end_y,
+               unsigned char fontnum)
+
+/* set the characters within the range to the fontnum */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+        if(mask[i][j]==1){
+        fonts[i][j] = fontnum;
+       }
+     }
+   }
+}
+
+void ALColourChars(struct seqdat *bloc,unsigned char **colour,
+                  int start_x,int start_y,int end_x,int end_y,
+                  char *charlist,unsigned char colournum)
+
+/* set the characters within the range to the colour defined by colournum */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+       if(strchr(charlist,bloc[j].seq[i])!=NULL){
+        colour[i][j] = colournum;
+       }
+     }
+   }
+}
+void ALColourRegion(unsigned char **colour,
+                   int start_x,int start_y,int end_x,int end_y,
+                   unsigned char colournum)
+
+/* set the characters within the range to the colournum */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+        colour[i][j] = colournum;
+     }
+   }
+}
+
+void ALColourMask(unsigned char **mask,unsigned char **colour,
+                 int start_x,int start_y,int end_x,int end_y,
+                 unsigned char colournum)
+
+/* set the characters within the range to the colournum */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+        if(mask[i][j] == 1){
+        colour[i][j] = colournum;
+       }
+     }
+   }
+}
+
+  
+void ALSubChars(struct seqdat *bloc,
+               int start_x,int start_y,int end_x,int end_y,
+               char oldchar,char newchar)
+
+/* substitute oldchar for newchar at each position in bloc */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+        if(bloc[j].seq[i] == oldchar) bloc[j].seq[i] = newchar;
+     }
+   }
+}
+
+
+void ALSurroundChars(struct seqdat *bloc,unsigned char **lines,
+                    int start_x,int start_y,int end_x,int end_y,
+                    int maxY,char *charlist)
+
+/* 
+within the range of start_x etc.  Draw lines such that every character that
+is present within charlist is surrounded by a box.
+*/
+{
+  int i,j,jpos;
+  char above,below,left,right;
+  
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y,jpos=(maxY-start_y+1);j<end_y+1;++j,--jpos){
+      if(strchr(charlist,bloc[j].seq[i]) != NULL){
+/*     fprintf(std_err,"%d %d %c %c\n",i,j,bloc[j].seq[i]*/
+       if(j == end_y){
+         below = '!';
+       }else{
+         below = bloc[j+1].seq[i];
+       }
+       if(j == start_y){
+         above = '!';
+       }else{
+         above = bloc[j-1].seq[i];
+       }
+       if(i == start_x){
+         left = '!';
+       }else{
+         left  = bloc[j].seq[i-1];
+       }
+       if(i == end_x){
+         right = '!';
+       }else{
+         right = bloc[j].seq[i+1];
+       }
+
+       if(strchr(charlist,above)== NULL){
+         ALLineRes(lines,i,jpos,LINE_TOP);
+       }
+       if(strchr(charlist,below)== NULL){
+         ALLineRes(lines,i,jpos,LINE_BOTTOM);
+       }
+       if(strchr(charlist,left)==NULL){
+         ALLineRes(lines,i,jpos,LINE_LEFT);
+       }
+       if(strchr(charlist,right)==NULL){
+         ALLineRes(lines,i,jpos,LINE_RIGHT);
+       }
+      }
+    }
+  }
+}
+void ALSurroundMask(unsigned char **mask,struct seqdat *bloc,unsigned char **lines,
+                   int start_x,int start_y,int end_x,int end_y,
+                   int maxY)
+/* 
+within the range of start_x etc.  Draw lines such that every
+masked position is isolated from every non-masked position
+*/
+{
+  int i,j,jpos;
+  char above,below,left,right;
+
+/*  fprintf(stdout,"ALSurroundMask: %d %d %d %d\n",start_x,start_y,end_x,end_y);*/
+  
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y,jpos=(maxY-start_y+1);j<end_y+1;++j,--jpos){
+        if(mask[i][j] == 1){
+/*     fprintf(std_err,"%d %d %c %c\n",i,j,bloc[j].seq[i]*/
+       if(j == end_y){
+         below = 0;
+       }else{
+         below = mask[i][j+1];
+       }
+       if(j == start_y){
+         above = 0;
+       }else{
+         above = mask[i][j-1];
+       }
+       if(i == start_x){
+         left = 0;
+       }else{
+         left  = mask[i-1][j];
+       }
+       if(i == end_x){
+         right = 0;
+       }else{
+         right = mask[i+1][j];
+       }
+       /*
+       fprintf(stdout,"IN ALSurroundMask\n");
+       fprintf(stdout,"%d %d (%d %d %d %d)\n",i,j,above,below,left,right);
+       */
+
+       if(mask[i][j] != above){
+         ALLineRes(lines,i,jpos,LINE_TOP);
+       }
+       if(mask[i][j] != below){
+         ALLineRes(lines,i,jpos,LINE_BOTTOM);
+       }
+       if(mask[i][j] != left){
+         ALLineRes(lines,i,jpos,LINE_LEFT);
+       }
+       if(mask[i][j] != right){
+         ALLineRes(lines,i,jpos,LINE_RIGHT);
+       }
+       }
+     }
+  }
+}
+
+void ALFilRegion(signed char **fill,
+                int start_x,int start_y,int end_x,int end_y,
+                int *Yindx,float grey)
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+    for(j=start_y;j<end_y+1;++j){
+      ALFilRes(fill,i,Yindx[j],grey);
+    }
+  }
+}
+
+void ALShadeMask(unsigned char **mask,signed char **fill,
+                int start_x,int start_y,int end_x,int end_y,int *Yindx,
+                float grey)
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+    for(j=start_y;j<end_y+1;++j){
+        if(mask[i][j]==1){
+            ALFilRes(fill,i,Yindx[j],grey);
+        }
+    }
+  }
+}
+
+
+void ALColRegion(unsigned char **colour,
+                int start_x,int start_y,int end_x,int end_y,
+                int *Yindx,unsigned char colnum)
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+    for(j=start_y;j<end_y+1;++j){
+      ALColRes(colour,i,Yindx[j],colnum);
+    }
+  }
+}
+
+void ALColRRegion(unsigned char **colour,
+                int start_x,int start_y,int end_x,int end_y,
+                unsigned char colnum)
+/* version of ALColRegion that is indexed by characters rather than position */
+/* 18/1/1995 */
+
+{
+  int i,j;
+  for(i=start_x;i<end_x+1;++i){
+     for(j=start_y;j<end_y+1;++j){
+        colour[i][j] = colnum;
+     }
+   }
+}
+
+void ALBoxRegion(unsigned char **lines,
+                int start_x,int start_y,int end_x,int end_y,
+                int *Yindx)
+{
+  int i;
+  for(i=start_x;i<end_x+1;++i){
+    ALLineRes(lines,i,Yindx[end_y],LINE_BOTTOM);
+    ALLineRes(lines,i,Yindx[start_y],LINE_TOP);
+  }
+  for(i=start_y;i<end_y+1;++i){
+    ALLineRes(lines,start_x,Yindx[i],LINE_LEFT);
+    ALLineRes(lines,end_x,Yindx[i],LINE_RIGHT);
+  }
+}
+void ALDoLine(unsigned char **lines,
+             int start_x,int start_y,int end,
+             int type,int *Yindx)
+{
+  int i;
+  if(type == LINE_TOP || type == LINE_BOTTOM){
+    for(i=start_x;i<end+1;++i){
+      ALLineRes(lines,i,Yindx[start_y],type);
+    }
+  }else{
+    for(i=start_y;i<end+1;++i){
+      ALLineRes(lines,start_x,Yindx[i],type);
+
+
+    }
+  }
+}
+
+void ALDrawFills(signed char **fill,int use_colour,unsigned char **colour,
+                int start_x,int start_y,int end_x,int end_y,int XOffset,int YOffset,FILE *outf)
+
+/* for values of fill >= 0  draw box and fill in with grey value */
+/* 6/12/92:  add colour option */
+{
+  int i,j;
+  extern int precis;
+
+  XOffset *= Xspace;
+  YOffset *= Yspace;
+  
+  for(i=end_x;i>(start_x-1);--i){
+    for(j=end_y;j>(start_y-1);--j){
+      if((int) fill[i][j] >=  0 || use_colour){
+
+/*
+Revise to use ML function 27th Oct 1992
+       fprintf(outf," newpath\n");
+       fprintf(outf,"%.2f %.2f moveto \n",(float)(i-start_x)*Xspace-Xshift+XOffset,
+                                        (float)(j-start_y+1)*Yspace-Yshift+YOffset);
+       fprintf(outf,"%.2f %.2f lineto \n",(float)(i-start_x)*Xspace-Xshift+XOffset,
+                                        (float)(j-start_y+0)*Yspace-Yshift+YOffset);
+       fprintf(outf,"%.2f %.2f lineto \n",(float)(i-start_x+1)*Xspace-Xshift+XOffset,
+                                        (float)(j-start_y+0)*Yspace-Yshift+YOffset);
+        fprintf(outf,"%.2f %.2f lineto \n",(float)(i-start_x+1)*Xspace-Xshift+XOffset,
+                                        (float)(j-start_y+1)*Yspace-Yshift+YOffset);
+       fprintf(outf,"%.2f %.2f lineto \n",(float)(i-start_x)*Xspace-Xshift+XOffset,
+                                        (float)(j-start_y+1)*Yspace-Yshift+YOffset);
+       fprintf(outf,"closepath %.2f setgray fill 0 setgray \n",(float)fill[i][j]/(float)precis);
+*/
+       fprintf(outf," newpath\n");
+       fprintf(outf,"%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f ML\n",
+               (float)(i-start_x)*Xspace-Xshift+XOffset,
+              (float)(j-start_y+1)*Yspace-Yshift+YOffset,
+              (float)(i-start_x)*Xspace-Xshift+XOffset,
+              (float)(j-start_y+0)*Yspace-Yshift+YOffset,
+              (float)(i-start_x+1)*Xspace-Xshift+XOffset,
+              (float)(j-start_y+0)*Yspace-Yshift+YOffset,
+               (float)(i-start_x+1)*Xspace-Xshift+XOffset,
+              (float)(j-start_y+1)*Yspace-Yshift+YOffset,
+              (float)(i-start_x)*Xspace-Xshift+XOffset,
+              (float)(j-start_y+1)*Yspace-Yshift+YOffset);
+       if(use_colour && fill[i][j] < 0){
+           /* 6/1/1995 - only set colour if grey is not set */
+           /* set to colour number */
+           fprintf(outf,"closepath  C%-d  fill \n",colour[i][j]);
+       }else{
+           fprintf(outf,"closepath %.2f setgray fill 0 setgray \n",(float)fill[i][j]/(float)precis);
+       }
+      }
+    }
+  }
+}
+
+void ALFilRes(signed char **fill,int i,int j,float grey)
+
+{
+  extern int precis;
+/*  ALBoxRes(lines,i,j); 
+  fill[i+Cidwidth][j+CseqVoffset] = grey * precis;
+*/
+  fill[i][j] = grey * precis;
+}
+
+void ALColRes(unsigned char **colour,int i,int j,int colnum)
+
+{
+  colour[i][j] = colnum;
+}
+  
+
+void ALBoxRes(unsigned char **lines,int i,int j)
+
+{
+  ALLineRes(lines,i,j,LINE_TOP);
+  ALLineRes(lines,i,j,LINE_BOTTOM);
+  ALLineRes(lines,i,j,LINE_LEFT);
+  ALLineRes(lines,i,j,LINE_RIGHT);
+}
+
+
+void ALLineRes(
+unsigned char **lines,
+int i,int j,
+unsigned char value)
+{
+/*
+  i = i + Cidwidth;
+  j = j + CseqVoffset;
+*/
+  ALLineChar(lines,i,j,value);
+}
+
+void ALLineChar(unsigned char **lines,int i,int j,unsigned char value)
+
+{
+  lines[i][j] = lines[i][j] | value;
+}
+
+void ALDrawLines(unsigned char **lines,int use_colour,
+                unsigned char **left_line_colour,
+                unsigned char **right_line_colour,
+                unsigned char **top_line_colour,
+                unsigned char **bottom_line_colour,
+                int start_x,int start_y,int end_x,int end_y,
+                int XOffset,int YOffset,FILE *outf)
+
+/* draw the lines that are indicated by the lines array in the range of the
+array indicated by start_x etc
+*/
+{
+  int i,j;
+  XOffset *= Xspace;
+  YOffset *= Yspace;
+
+/*  
+  if(use_colour){
+    fprintf(outf,"C100\n");
+  }
+*/
+  
+  for(i=end_x;i>(start_x-1);--i){
+    for(j=end_y;j>(start_y-1);--j){
+      if(lines[i][j] != 0){
+       if((LINE_LEFT & lines[i][j]) == LINE_LEFT){
+         PSSetColour(left_line_colour[i][j],outf);
+         PSline((float)(i-start_x)*Xspace-Xshift+XOffset,
+                (float)(j-start_y+1)*Yspace-Yshift+YOffset,
+                (float)(i-start_x)*Xspace-Xshift+XOffset,
+                (float)(j-start_y+0)*Yspace-Yshift+YOffset,outf);
+       }
+       if((LINE_RIGHT & lines[i][j]) == LINE_RIGHT){
+         PSSetColour(right_line_colour[i][j],outf);
+         PSline((float)(i-start_x+1)*Xspace-Xshift+XOffset,
+                (float)(j-start_y+1)*Yspace-Yshift+YOffset,
+                (float)(i-start_x+1)*Xspace-Xshift+XOffset,
+                (float)(j-start_y+0)*Yspace-Yshift+YOffset,outf);
+       }
+       if((LINE_TOP & lines[i][j]) == LINE_TOP){
+         PSSetColour(top_line_colour[i][j],outf);
+         PSline((float)(i-start_x)*Xspace-Xshift+XOffset,
+                (float)(j-start_y+1)*Yspace-Yshift+YOffset,
+                (float)(i-start_x+1)*Xspace-Xshift+XOffset,
+                (float)(j-start_y+1)*Yspace-Yshift+YOffset,outf);
+       }
+       if((LINE_BOTTOM & lines[i][j]) == LINE_BOTTOM){
+         PSSetColour(bottom_line_colour[i][j],outf);
+         PSline((float)(i-start_x)*Xspace-Xshift+XOffset,
+                (float)(j-start_y+0)*Yspace-Yshift+YOffset,
+                (float)(i-start_x+1)*Xspace-Xshift+XOffset,
+                (float)(j-start_y+0)*Yspace-Yshift+YOffset,outf);
+       }
+      }
+    }
+  }
+  /*
+  if(use_colour){
+    fprintf(outf,"C99\n");
+  }
+  */
+}
+
+void PSline(float x1,float y1,float x2,float y2,FILE *outf)
+
+{
+  fprintf(outf,"%.2f %.2f %.2f %.2f L\n ",x1,y1,x2,y2);
+}
+
+
+
+void ALSimpleBox(int x1,int y1,int x2,int y2,float pfactor,    /* multiply pointsize by this to get linewidth */         
+                FILE *outf)
+
+/* draw a box to include character coordinates x1,y1 to x2,y2 */
+/* x1 < x2 y1< y2 */
+{
+  float lshift = Xspace/6;
+  float rshift = Xspace - lshift;
+  
+  x1 *= Xspace; 
+  y1 *= Yspace;
+  x2 *= Xspace;
+  y2 *= Yspace;
+
+  x1 -= lshift;
+  x2 += rshift;
+  y1 -= lshift;
+
+  PSDrawBox((float)x1,(float)y1,(float)x2,(float)y2,pfactor,outf);
+}
+
+void PSDrawBox(float x1,float y1,float x2,float y2,float pfactor,FILE *out)
+
+{
+  fprintf(out,"%f setlinewidth\n ",pointsize*pfactor);
+  fprintf(out,"%f %f moveto %f %f lineto %f %f lineto %f %f lineto %f %f lineto closepath stroke\n",
+               x1,y1,x2,y1,x2,y2,x1,y2,x1,y1);
+}
+
+void ALOutTicks(char *array,int start_aa,int xpos,int ypos,int len,FILE *out)
+
+{
+  int right;
+  int j;
+  
+  xpos *= Xspace;
+  ypos *= Yspace;
+
+  right = start_aa + Cseqwidth;
+  if(right > len)right = len;
+  for(j=start_aa;j<right;j++){
+    if(array[j] != '\0'){
+      PSPutChar(xpos,ypos,array[j],out);
+    }
+    xpos +=  Xspace;
+  }
+}
+
+void ALOutNumbers(char **array,int start_aa,int xpos,int ypos,int len,FILE *out)
+
+{
+  int right;
+  int j;
+  
+  xpos *= Xspace;
+  ypos *= Yspace;
+
+  right = start_aa + Cseqwidth;
+  if(right > len)right = len;
+  for(j=start_aa;j<right;j++){
+    if(array[j][0] != '\0'){
+      PSPutText(xpos,ypos,array[j],out);
+    }
+    xpos +=  Xspace;
+  }
+}
+
+char *ALCreateTicks(int start, int interval, int len)
+
+/* create ticks at the desired interval starting with residue start */
+{
+  int i;
+  char *temp;
+  temp = (char *) malloc(sizeof(char) * len);
+  /* first set all ticks to '\0' */
+  for(i=0;i<len;++i){
+    temp[i]='\0';
+  }
+  for(i=0;i<len;i+=interval){
+    temp[i] = '|';
+  }
+  temp[0]='\0';
+  temp[1]='|';
+  return temp;
+}
+
+
+
+char **ALCreateNumbers(int start,int interval,int nres,int nwidth)
+
+/* create character array of numbers from start to nres at interval*/
+{
+  int i;
+  char **temp;
+  temp = (char **) malloc(nres*sizeof(char *));
+  for(i=0;i<nres;++i){
+    temp[i] = (char *) malloc(sizeof(char) *nwidth);
+    temp[i][0]='\0';
+  }
+  for(i=start;i<nres;i+=interval){
+    if(i==0){
+      sprintf(temp[i+1],"%-d",i+1);      
+    }else{
+      sprintf(temp[i],"%-d",i);
+    }
+  }
+
+  return temp;
+}
+  
+char **ALCreateNum2(
+int nstart,     /* starting number */
+int ninterval,  /* interval for numbers */
+int nend,       /* end of number range */
+int nres,       /* total length of sequence */
+int xstart,     /* starting location for writing numbers */
+int nwidth)     /* width of the number string */
+
+/* create character array of numbers from start to nres at interval*/
+{
+  int i,xp;
+  char **temp;
+  temp = (char **) malloc(nres*sizeof(char *));
+  for(i=0;i<nres;++i){
+    temp[i] = (char *) malloc(sizeof(char) *nwidth);
+    temp[i][0]='\0';
+  }
+  xp = xstart;
+  for(i=nstart;i<nend;i+=ninterval){
+    if(i==0){
+      sprintf(temp[xp+1],"%-d",i+1);      
+    }else{
+      sprintf(temp[xp],"%-d",i);
+    }
+    xp += ninterval;
+  }
+
+  return temp;
+}
+
+void ALReportInfo(int nseq,FILE *out)
+
+{
+  fprintf(out,"Number of Sequences: %d\n",nseq);
+  fprintf(out,"Total Vertical Space per page: %d\n",Cheight);
+}
+
+void ALReserveSpace(int location,int nspace)
+
+{
+  extern int TVspace,CseqVoffset;
+
+  switch(location){
+  case TOP:
+    TVspace += nspace;
+    CtopSpace +=nspace;
+    break;
+  case BOTTOM:
+    TVspace += nspace;
+    CseqVoffset += nspace;
+    CbottomSpace += nspace;
+    break;
+  }
+}
+
+void PSSetupPage(int orientation,int npage,FILE *outf)
+
+{
+  fprintf(outf,"%%%%Page: ? %d\n",npage);
+  PSSetOrientation(orientation,outf);
+  PSSetFont(0,outf);    /* set default font for document */
+}
+
+void ALOutSeq(struct seqdat *bloc,unsigned char **fonts,char ***texts,unsigned char **inverse,
+             int use_colour,
+             unsigned char **colour,
+             unsigned char **text_colour,
+             unsigned char background_colour,
+             int start_seq,int end_seq,int start_aa,int ypos,FILE *outf)
+
+{
+  extern int Xspace,Yspace;
+  extern int Cidwidth;
+
+  int i,j;
+  int xpos;
+  unsigned char current_col;
+
+  int right;
+
+  ypos *= Yspace;
+
+  current_col = background_colour;
+
+  right = start_aa + Cseqwidth;
+  if(right > bloc[1].slen-1)right = bloc[1].slen;
+  
+  for(i=end_seq;i>(start_seq-1);--i){
+    xpos = Cidwidth * Xspace;
+    for(j=start_aa;j<right;++j){
+      if(texts[j][i] != NULL || bloc[i].seq[j] != ' '){
+       if(fonts[j][i]!=0)PSSetFont(fonts[j][i],outf);
+       if(inverse[j][i] != 0)PSSetGrey(1,outf);
+       if(use_colour && colour[j][i] != current_col){
+           PSSetColour(colour[j][i],outf);
+           current_col = colour[j][i];
+       } 
+       if(bloc[i].seq[j] != ' '){
+         PSPutChar(xpos,ypos,bloc[i].seq[j],outf);
+       }
+       if(texts[j][i] != NULL){
+           if(text_colour[j][i] != current_col){
+               PSSetColour(text_colour[j][i],outf);
+               current_col = text_colour[j][i];
+           }
+         if(texts[j][i][0] == '@'){
+           PSPutSpecialText(xpos,ypos,Xspace,Yspace,texts[j][i],
+                            text_colour[j][i],background_colour,0.9,outf);
+         }else{
+           PSPutText(xpos,ypos,texts[j][i],outf);
+         }
+       }
+       if(inverse[j][i] != 0)PSSetGrey(0,outf);
+       if(fonts[j][i]!=0)PSSetFont(0,outf);
+      }
+      xpos += Xspace;
+    }
+    ypos += Yspace;
+  }
+/*
+  if(use_colour){
+       PSSetColour(100,outf);
+  }
+*/
+}
+
+
+void ALOutId(struct seqdat *bloc,int use_colour,
+            unsigned char *colour,
+            unsigned char *fonts,
+            int start_seq,int end_seq,int ypos,int numbers,
+             FILE *outf)
+
+{
+  extern int MAXilen;
+  extern int Xspace,Yspace;
+  int i;
+  int xpos;
+  char *temp;
+
+  xpos = 0;
+  ypos *= Yspace;
+  temp = (char *) malloc(sizeof(char) * (MAXilen + 5));
+
+
+  for(i=end_seq;i>(start_seq-1);--i){
+    if(use_colour)PSSetColour(colour[i],outf);
+    if(fonts[i] != 0)PSSetFont(fonts[i],outf);
+    if(numbers){
+      sprintf(temp,"%4d:%s",i,bloc[i].id);
+    }else{
+      sprintf(temp,"%s",bloc[i].id);
+    }
+    PSPutText(xpos,ypos,temp,outf);
+    ypos += Yspace;
+    if(fonts[i] != 0)PSSetFont(0,outf);
+  }
+  free((char *) temp);
+
+}
+
+void PSPutText(int x,int y,char *text,FILE *outf)
+
+{
+  fprintf(outf," %d %d moveto (%s) show \n",x,y,text);
+}
+
+void PSPutChar(int x,int y,char c,FILE *outf)
+
+{
+  /* fprintf(outf," %d %d moveto (%c) show \n",x,y,c);*/
+  fprintf(outf,"(%c) %d %d P\n",c,x,y);
+}
+
+void PSShowPage(FILE *outf)
+
+{
+  fprintf(outf,"showpage\n");
+}
+
+void ALSetFont(char *font,int point,FILE *outf)
+
+{
+  fprintf(outf,"/%s findfont %d scalefont setfont\n",font,point);
+}
+
+void PSSetFont(unsigned char number,FILE *outf)
+
+{
+  fprintf(outf,"F%-d\n ",number);
+}
+
+void PSSetColour(unsigned char number,FILE *outf)
+
+{
+  fprintf(outf,"C%-d\n ",number);
+}
+
+void ALDefineFont(int number,char *font,float point,FILE *outf)
+
+/* define a PostScript function called /Fnumber which selects the 
+font at point pointsize */
+{
+  fprintf(outf,"/F%-d {/%s findfont %.2f scalefont setfont } def\n",
+         number,font,point);
+}
+
+void ALDefineColour(int number,char *type,float red,float green,float blue,FILE *outf)
+
+/* define a PostScript function called /Cnumber which selects the 
+colour defined by red,green, blue intensities
+
+new addition - if type is equal to "HSB" then define an hsb colour using red, green blue as
+the hue saturation and brightness. 
+*/
+{
+    if(strcmp(type,"HSB")==0){
+       /* set an HSB colour */
+       fprintf(outf,"/C%-d {%f %f %f sethsbcolor } def\n", number,red,green,blue);
+    }else{
+       /* set an RGB colour */
+       fprintf(outf,"/C%-d {%f %f %f setrgbcolor } def\n", number,red,green,blue);
+    }
+}
+
+void ALCheckSinglePage(int nseq,int len,int silent)
+
+{
+  extern FILE *std_err;
+  Csheet = 1;
+
+
+  if(Cheight-CtopSpace < nseq){
+    if(!silent)fprintf(std_err,"Not enough height to print all sequences on a single page at this pointsize\n");
+    if(!silent)fprintf(std_err,"Pointsize: %.2f\n",pointsize);
+    if(!silent)fprintf(std_err,"Need a pointsize of < : %.2f\n",(float) height/(nseq+ CtopSpace));
+    Csheet = nseq/(Cheight-CtopSpace) + 1;
+    if(!silent)fprintf(std_err,"Will split alignment into %d segments\n",Csheet);
+  }
+  
+  npage = len/(Cwidth - Cidwidth)  + 1;
+}
+
+
+void ALSetPageLimits(void)
+/* Use the current width height and pointsize values to calculate:
+   Cwidth
+   Cheight
+   Xspace
+   Yspace
+*/
+{
+
+  Xspace = pointsize + pointsize * XspaceFactor;
+  Yspace = pointsize + pointsize * YspaceFactor;
+
+  Cwidth = width/Xspace;
+  Cheight = height/Yspace;
+
+  Cseqwidth = Cwidth - Cidwidth;
+
+  Xshift = Xspace * XshiftFactor;
+  Yshift = Yspace * YshiftFactor;
+}
+
+void PSSetOrientation(int orientation,FILE *outf)
+
+{
+  switch(orientation){
+  case LANDSCAPE:
+    PSLandscape(outf);
+    break;
+  case PORTRAIT:
+    PSPortrait(outf);
+    break;
+  default:
+    PSPortrait(outf);
+  }
+}
+
+void PSPreamble(FILE *out,int singlepage,int *b_box,int screensize)
+{
+  char *Alscript_Version = ALSCRIPT_VERSION;
+  fprintf(out,"%%!PS-Adobe-2.0\n");
+  fprintf(out,"%%%%Creator: %s\n",Alscript_Version);
+  fprintf(out,"%%%%Title: Alscript Output\n");
+  fprintf(out,"%% Barto,n G. J. (1993)\n");
+  fprintf(out,"%% ALSCRIPT - A Tool to format multiple sequence alignments\n");
+  fprintf(out,"%% Protein Engineering, 6, 37-40\n");
+  fprintf(out,"%%\n");
+  if(singlepage == 1){
+        fprintf(out,"%%%%BoundingBox: %d %d %d %d\n",
+               b_box[0],b_box[1],b_box[2],b_box[3]);
+  }
+  fprintf(out,"/P {moveto show} def\n");
+  fprintf(out,"/L {moveto lineto stroke} def\n");
+  fprintf(out,
+  "/ML {moveto lineto lineto lineto lineto} def\n");
+  fprintf(out,"2 setlinecap\n");                 /* projecting line caps */
+  ALDefineColour(99,"RGB",1.0,1.0,1.0,out);  /* white */
+  ALDefineColour(100,"RGB",0.0,0.0,0.0,out);  /* black */
+  /* modify the screening - suggested by Michael D. Baron */
+  fprintf(out,"%d currentscreen 3 -1 roll pop setscreen\n",screensize);
+
+}
+
+void PSLandscape(FILE *out)
+
+{
+  width = MAXside;
+  height = MINside;
+
+  fprintf(out,"%d %d translate\n",xoff+height,yoff);
+  fprintf(out,"90 rotate\n");  
+
+}
+
+void PSPortrait(FILE *out)
+
+{
+  width = MINside;
+  height = MAXside;
+  fprintf(out,"%d %d translate\n",xoff,yoff);
+}
+
+
+void echo(char *s)
+
+{
+  extern FILE *std_err;
+  fprintf(std_err,"%s",s);
+}
+
+void ALGetFourInt(int *sx,int *sy,int *ex,int *ey)
+
+{
+char *token;
+
+       token = strtok(NULL,TOKENS);
+       *sx = atoi(token);
+       token = strtok(NULL,TOKENS);
+       *sy = atoi(token);
+       token = strtok(NULL,TOKENS);
+       *ex = atoi(token);
+       token = strtok(NULL,TOKENS);
+       *ey = atoi(token);
+}
+void ALGetThreeInt(int *sy,int *ex,int *ey)
+
+{
+char *token;
+
+       token = strtok(NULL,TOKENS);
+       *sy = atoi(token);
+       token = strtok(NULL,TOKENS);
+       *ex = atoi(token);
+       token = strtok(NULL,TOKENS);
+       *ey = atoi(token);
+}
+void ALGetTwoInt(int *sy,int *ex)
+
+{
+char *token;
+
+       token = strtok(NULL,TOKENS);
+       *sy = atoi(token);
+       token = strtok(NULL,TOKENS);
+       *ex = atoi(token);
+}
+
+char ALChekSpace(const char *token)
+{
+  if(strcmp(token,"SPACE") == 0){
+    return ' ';
+  }else{
+    return token[0];
+  }
+}
+
+void PSSetGrey(float grey,FILE *outf)
+{
+  fprintf(outf," %.2f setgray\n",grey);
+}
+
+int save_pir(struct seqdat *bloc,int nseq,FILE *pirf)
+
+{
+  int i,j;
+  int count;
+
+
+   for(i=1;i<(nseq+1);++i){
+    fprintf(pirf,">P1;%s\n",bloc[i].id);
+    fprintf(pirf,"%s\n",bloc[i].title);
+    count=0;
+    for(j=1;j<bloc[i].slen;++j){
+      ++count;
+      /* convert spaces to dashes */
+      if(bloc[i].seq[j] == ' ')bloc[i].seq[j] = '.';
+      fputc(bloc[i].seq[j],pirf);
+      if(count==50){
+       count=0;
+       fprintf(pirf,"\n");
+      }
+    }
+    fprintf(pirf,"*\n");
+  }
+  return 1;
+}
+
+int save_msf(struct seqdat *bloc,int nseq,FILE *msff)
+
+{
+  int i,j,s,e;
+  int count;
+
+  fprintf(msff,"\njunk.msf  MSF: %d  Type: P  January 01, 1776  12:00  Check: 7110 ..\n\n",bloc[1].slen-1);
+
+   for(i=1;i<(nseq+1);++i){
+     fprintf(msff,"Name: %20s Len: %7d  Check:    0  Weight:  1.00\n",
+            bloc[i].id,bloc[1].slen-1);
+   }
+   fprintf(msff,"\n//\n\n\n");
+
+
+   s = 1; 
+
+   while(s < bloc[1].slen){
+       e = s + 50;
+       if(e > bloc[1].slen) e = bloc[1].slen;
+       
+       for(i=1;i<(nseq+1);++i){
+          fprintf(msff,"%10s ",bloc[i].id);
+          for(j=s;j<e;++j){
+             if(bloc[i].seq[j] == ' ')bloc[i].seq[j]='.';
+              fputc(bloc[i].seq[j],msff);
+          }
+          fprintf(msff,"\n");
+       }
+       s += 50;
+       fprintf(msff,"\n\n");
+   }
+   return 1;
+}
+  
+
+void ALGetAllRange(int *sx, int *sy, int *ex, int *ey,int dex,int dey)
+/* checks the next token if it is ALL then return box around whole alignment
+   else return box according to the integers found
+*/
+{
+    char *token;
+    
+    token = strtok(NULL,TOKENS);
+    
+    if(strcmp(token,"ALL")==0){
+                *sx = 1;
+                *sy = 1;
+                *ex = dex;
+                *ey = dey;
+    }else{
+                *sx = atoi(token);
+                       ALGetThreeInt(sy,ex,ey);
+    }
+    if(*ex > dex) *ex = dex;
+    if(*ey > dey) *ey = dey;
+}
+
+void ALid_mask(
+unsigned char **mask,
+struct seqdat *bloc,
+int sx,int sy,int ex,int ey,
+int id_cut,
+char *legal,
+char *illegal)
+
+{
+    int i,j,k,iseen;
+    char fchar;
+    char *seen;   /* array of characters that are seen at this position */
+    int *freq;    /* array of frequencies of the characters */
+    int nc;       /* number of different character types at this position */
+    int ns;
+    int mc;       /* maximum character present */
+    int imc;      /* location of max character */
+
+    ns = ey - sy + 1;
+    nc = 0;
+
+    seen = (char *) GJmalloc(sizeof(char) *ns);
+    freq = (int *)  GJmalloc(sizeof(int) *ns);
+
+    for(i=0;i<ns;++i){
+        freq[i] = 0;
+        seen[i] = '\0';
+    }
+
+/*    fprintf(stdout,"In ALidmask\n");*/
+    
+    for(i=sx;i<(ex+1);++i){
+        /* for each position get the list of characters seen and their frequencies */
+        for(j=sy;j<(ey+1);++j){
+            iseen = Ifound(bloc,i,j,seen,nc);
+            if(iseen >= 0){
+                ++freq[iseen];
+            }else{
+                seen[nc] = bloc[j].seq[i];
+                ++freq[nc];
+                ++nc;
+            }
+        }
+        /*
+        for(k=0;k<nc;++k)fprintf(stdout,"%c ",seen[k]);
+        for(k=0;k<nc;++k)fprintf(stdout,"%d ",freq[k]);
+        fprintf(stdout,"\n");
+        */
+        /* find the most frequent character that is legal and not illegal*/
+        mc = 0;
+        for(k=0;k<nc;++k){
+            if(legal != NULL && illegal != NULL){
+                if(  strchr(legal,seen[k]) != NULL
+                  && strchr(illegal,seen[k]) == NULL
+                  && freq[k] > mc){
+                  mc = freq[k];
+                  imc = k;
+                  }
+            }else if(legal != NULL){
+                if(  strchr(legal,seen[k]) != NULL
+                  && freq[k] > mc){ 
+                  mc = freq[k];
+                  imc = k;
+                  }
+            }else if(illegal != NULL){
+                if(  strchr(illegal,seen[k]) == NULL
+                  && freq[k] > mc){
+                  mc = freq[k];
+                  imc = k;
+                  }
+            }else{
+                if(freq[k] > mc){
+                     mc = freq[k];
+                     imc = k;
+                }
+            }
+       }
+       if(mc >= id_cut){
+           /* only select the character if it is >= id_cut */
+           fchar = seen[imc];
+/*         fprintf(stdout,"At %d %c\n",i,fchar);*/
+            for(j=sy;j<(ey+1);++j){
+                if(bloc[j].seq[i] == fchar){
+                    mask[i][j] = 1;
+/*                    fprintf(stdout,"%d %d \n",i,j);*/
+               }
+           }
+        }
+        for(j=0;j<ns;++j){
+           freq[j] = 0;
+           seen[j] = '\0';
+       }
+       nc = 0;
+    }
+    GJfree(seen);
+    GJfree(freq);
+}
+
+void ALfre_mask(
+unsigned char **mask,
+struct seqdat *bloc,
+int sx,int sy,int ex,int ey,
+char *legal,
+char *illegal)
+
+{
+    int i,j,k,iseen;
+    char fchar;
+    char *seen;   /* array of characters that are seen at this position */
+    int *freq;    /* array of frequencies of the characters */
+    int nc;       /* number of different character types at this position */
+    int ns;
+    int mc;       /* maximum character present */
+    int imc;      /* location of max character */
+
+    ns = ey - sy + 1;
+    nc = 0;
+
+    seen = (char *) GJmalloc(sizeof(char) *ns);
+    freq = (int *)  GJmalloc(sizeof(int) *ns);
+
+    for(i=0;i<ns;++i){
+        freq[i] = 0;
+        seen[i] = '\0';
+    }
+
+/*    fprintf(stdout,"In ALidmask\n");*/
+    
+    for(i=sx;i<(ex+1);++i){
+        /* for each position get the list of characters seen and their frequencies */
+        for(j=sy;j<(ey+1);++j){
+            iseen = Ifound(bloc,i,j,seen,nc);
+            if(iseen >= 0){
+                ++freq[iseen];
+            }else{
+                seen[nc] = bloc[j].seq[i];
+                ++freq[nc];
+                ++nc;
+            }
+        }
+/*        for(k=0;k<nc;++k)fprintf(stdout,"%c ",seen[k]);
+        for(k=0;k<nc;++k)fprintf(stdout,"%d ",freq[k]);
+        fprintf(stdout,"\n");
+*/
+        /* find the most frequent character that is legal and not illegal*/
+        mc = 0;
+        for(k=0;k<nc;++k){
+            if(legal != NULL && illegal != NULL){
+                if(  strchr(legal,seen[k]) != NULL
+                  && strchr(illegal,seen[k]) == NULL
+                  && freq[k] > mc){
+                  mc = freq[k];
+                  imc = k;
+                  }
+            }else if(legal != NULL){
+                if(  strchr(legal,seen[k]) != NULL
+                  && freq[k] > mc){ 
+                  mc = freq[k];
+                  imc = k;
+                  }
+            }else if(illegal != NULL){
+                if(  strchr(illegal,seen[k]) == NULL
+                  && freq[k] > mc){
+                  mc = freq[k];
+                  imc = k;
+                  }
+            }else{
+                if(freq[k] > mc){
+                     mc = freq[k];
+                     imc = k;
+                }
+            }
+       }
+        fchar = seen[imc];
+/*         fprintf(stdout,"At %d %c\n",i,fchar);*/
+            for(j=sy;j<(ey+1);++j){
+                if(bloc[j].seq[i] == fchar){
+                    mask[i][j] = 1;
+/*                    fprintf(stdout,"%d %d \n",i,j);*/
+               }
+           }
+
+        for(j=0;j<ns;++j){
+           freq[j] = 0;
+           seen[j] = '\0';
+       }
+       nc = 0;
+    }
+    GJfree(seen);
+    GJfree(freq);
+}
+int Ifound(struct seqdat *bloc,
+int i,int j,
+char *seen,
+int nc)
+{
+    int k;
+    
+    if(nc > 0){
+       for(k=0;k<nc;++k){
+             if(bloc[j].seq[i] == seen[k]){
+                return k;
+             }
+       }
+    }
+    return -1;
+}
+void ALagree_mask(
+unsigned char **mask,
+struct seqdat *bloc,
+int sx,int sy,int ex,int ey,
+int ns)
+
+{
+    int i,j;
+
+    for(i=sx;i<(ex+1);++i){
+        /* for each position mask the characters that are identical to sequence ns */
+        for(j=sy;j<(ey+1);++j){
+            if(bloc[j].seq[i] == bloc[ns].seq[i]){
+                mask[i][j] = 1;
+            }
+        }
+    }
+}
+
+void ALnot_mask(
+unsigned char **mask,
+int sx,int sy,int ex,int ey)
+
+{
+    int i,j;
+
+    for(i=sx;i<(ex+1);++i){
+        /* NOT on each mask element ie 1 goes to 0, 0 to 1 */
+        for(j=sy;j<(ey+1);++j){
+            if(mask[i][j]==1){
+                mask[i][j]=0;
+            }else if(mask[i][j]==0){
+                mask[i][j]=1;
+            }
+        }
+    }
+}
+                    
+
+void ALsub_mask(unsigned char **mask,struct seqdat *bloc,
+               int sx,int sy,int ex,int ey,char cchar)
+
+{
+    int i,j;
+
+    for(i=sx;i<(ex+1);++i){
+        /* substitute all characters in the mask for cchar */
+        for(j=sy;j<(ey+1);++j){
+            if(mask[i][j]==1){
+                bloc[j].seq[i] = cchar;
+            }
+        }
+    }
+}
+
+void ALMask(unsigned char **mask,
+int sx,int sy,int ex,int ey)
+
+{
+    int i,j;
+
+    for(i=sx;i<(ex+1);++i){
+        /* substitute all characters in the mask for cchar */
+        for(j=sy;j<(ey+1);++j){
+            mask[i][j] = 1;
+        }
+    }
+}
+
+void ALConsMask(unsigned char **mask,
+int sx,int sy,int ex,int ey,int *consval,int conscut)
+
+{
+    int i,j;
+
+    for(i=sx;i<(ex+1);++i){
+        /* set mask at all positions that are >= conscut in the consval array */
+        for(j=sy;j<(ey+1);++j){
+           if(consval[i] >= conscut){
+               mask[i][j] = 1;
+           }
+        }
+    }
+}
+
+
+void ALDrawHorizLine(
+                    float Xpos,       /* bottom left hand corner of character posn */
+                    float Ypos,       /* */
+                    float Xspace,     /* horizontal width of character position */
+                    float Yspace,     /* vertical height of character position */
+                    float width_fac,FILE *outf)  /* proportion of vertical height that the line will fill */
+
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+
+  /* width_fac defines the width of the line in terms of the height of the characters */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  fprintf(outf,"%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f ML\n",
+         Xpos,ymid-hline_w,
+         xright,ymid-hline_w,
+         xright,ymid+hline_w,
+         Xpos,ymid+hline_w,
+         Xpos,ymid-hline_w,outf);
+} 
+
+void ALDrawRightArrow(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+
+  /* width_fac defines the width of the Arrow in terms of the height of the characters */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSmoveto(Xpos,Ypos,outf);
+  PSlineto(xright,ymid,outf);
+  PSlineto(Xpos,ytop,outf);
+  PSlineto(Xpos,Ypos,outf);
+
+}
+
+void ALDrawLeftArrow(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+
+  /* width_fac defines the width of the Arrow in terms of the height of the characters */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSmoveto(xright,Ypos,outf);
+  PSlineto(xright,ytop,outf);
+  PSlineto(Xpos,ymid,outf);
+  PSlineto(xright,Ypos,outf);
+} 
+
+
+void ALDrawUpArrow(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;   /* horizontal mid point */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSmoveto(Xpos,Ypos,outf);
+  PSlineto(xright,Ypos,outf);
+  PSlineto(xmid,ytop,outf);
+  PSlineto(Xpos,Ypos,outf);
+} 
+
+void ALDrawDownArrow(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;   /* horizontal mid point */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSmoveto(Xpos,ytop,outf);
+  PSlineto(xright,ytop,outf);
+  PSlineto(xmid,Ypos,outf);
+  PSlineto(Xpos,ytop,outf);
+} 
+
+/* Draw a small up arrow. mok 980917 */
+void ALDrawSmallUpArrow(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float xmid;
+  float x,y;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;        /* horizontal mid point */
+
+  PSmoveto(xmid, ytop, outf);
+  x = Xpos + (xright-Xpos)/5.0;   y = Ypos + 2.0*(ytop-Ypos)/3.0;
+  PSlineto(x,y,outf);
+  x = Xpos + 2.0*(xright-Xpos)/5.0;
+  PSlineto(x, y, outf);
+  PSlineto (x, Ypos, outf);
+  x = Xpos + 3.0*(xright-Xpos)/5.0;
+  PSlineto (x, Ypos, outf);
+  PSlineto(x, y, outf);
+  x = Xpos + 4.0*(xright-Xpos)/5.0;
+  PSlineto(x, y, outf);
+  PSlineto(xmid, ytop, outf);
+} 
+
+/* Draw a small down arrow. mok 980917 */
+void ALDrawSmallDownArrow(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float xmid;
+  float x,y;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;        /* horizontal mid point */
+
+  PSmoveto(xmid, Ypos, outf);
+  x = Xpos + 4.0*(xright-Xpos)/5.0;   y = Ypos + (ytop-Ypos)/3.0;
+  PSlineto(x,y,outf);
+  x = Xpos + 3.0*(xright-Xpos)/5.0;
+  PSlineto(x, y, outf);
+  PSlineto (x, ytop, outf);
+  x = Xpos + 2.0*(xright-Xpos)/5.0;
+  PSlineto (x, ytop, outf);
+  PSlineto(x, y, outf);
+  x = Xpos + (xright-Xpos)/5.0;
+  PSlineto(x, y, outf);
+  PSlineto(xmid, Ypos, outf);
+} 
+
+void ALDrawCircle(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;   /* horizontal mid point */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSnewpath(outf);
+
+  fprintf(outf,"%.2f %.2f %.2f %d %d arc\n",xmid,ymid,(ytop - Ypos)*0.5,0,360);
+
+} 
+
+/* Draw a diamond. mok 980917 */
+void ALDrawDiamond(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;        /* horizontal mid point */
+
+  PSmoveto(Xpos, ymid, outf);
+  PSlineto(xmid, ytop, outf);
+  PSlineto(xright, ymid, outf);
+  PSlineto(xmid, Ypos, outf);
+  PSlineto(Xpos, ymid, outf);
+} 
+
+/* Draw a bar. mok 980917 */
+void ALDrawBar(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright;
+  float y1, y2;
+  
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+
+  y1 = Ypos + 2.0*(Ypos+Yspace)/5.0;
+  y2 = Ypos + 3.0*(Ypos+Yspace)/5.0;
+
+  PSmoveto(Xpos, y1, outf);
+  PSlineto(xright, y1, outf);
+  PSlineto(xright, y2, outf);
+  PSlineto(Xpos, y2, outf);
+  PSlineto(Xpos, y1, outf);
+} 
+
+void ALDrawPseudoEllipse(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,
+                        FILE *outf)
+
+{
+  /* draws a pseudo ellipse in the box bounded by Xpos,Ypos, Xpos+Xspace, Ypos+Yspace */
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+  float xefact = 0.2;   /* this shifts the guide points by 0.2 towards the axis */
+                       /* should not really be hard wired */
+  float yefact = 0.0;
+
+  float xbit,ybit;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;   /* horizontal mid point */
+  xbit = Xspace * xefact;
+  ybit = Yspace * yefact;
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSnewpath(outf);
+
+  PSmoveto(xmid,Ypos,outf);
+  
+  fprintf(outf,"%.2f %.2f %.2f %.2f %.2f %.2f curveto\n",
+         Xpos+xbit,Ypos+ybit,Xpos+xbit,ytop-ybit,xmid,ytop);
+  fprintf(outf,"%.2f %.2f %.2f %.2f %.2f %.2f curveto\n",
+         xright-xbit,ytop-ybit,xright-xbit,Ypos+ybit,xmid,Ypos);
+} 
+
+void ALDrawLeftSemiEnd(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;   /* horizontal mid point */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSnewpath(outf);
+
+  fprintf(outf,"%.2f %.2f %.2f %d %d arc\n",xmid,ymid,(ytop - Ypos) *0.5,270,90);
+
+  PSlineto(xright,ytop,outf);
+  PSlineto(xright,Ypos,outf);
+  PSlineto(xmid,Ypos,outf);
+  
+} 
+void ALDrawRightSemiEnd(float Xpos,float Ypos, float Xspace, float Yspace, float width_fac,FILE *outf)
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;   /* horizontal mid point */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSnewpath(outf);
+  fprintf(outf,"%f %f %f %d %d arc\n",xmid,ymid,(ytop - Ypos) *0.5,90,270);
+
+  PSlineto(Xpos,Ypos,outf);
+  PSlineto(Xpos,ytop,outf);
+  PSlineto(xmid,ytop,outf);
+} 
+void ALDrawRightHalfHorizLine(
+                    float Xpos,       /* bottom left hand corner of character posn */
+                    float Ypos,       /* */
+                    float Xspace,     /* horizontal width of character position */
+                    float Yspace,     /* vertical height of character position */
+                    float width_fac, FILE *outf)  /* proportion of vertical height that the line will fill */
+
+/* draw line from midpoint to right of position */
+
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;   /* horizontal mid point */
+
+  /* width_fac defines the width of the line in terms of the height of the characters */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSmoveto(xmid,ymid-hline_w,outf);
+  PSlineto(xmid,ymid+hline_w,outf);
+  PSlineto(xright,ymid+hline_w,outf);
+  PSlineto(xright,ymid-hline_w,outf);
+  PSlineto(xmid,ymid-hline_w,outf);
+} 
+
+void ALDrawLeftHalfHorizLine(
+                    float Xpos,       /* bottom left hand corner of character posn */
+                    float Ypos,       /* */
+                    float Xspace,     /* horizontal width of character position */
+                    float Yspace,     /* vertical height of character position */
+                    float width_fac, FILE *outf)  /* proportion of vertical height that the line will fill */
+
+/* draw line from midpoint to left of position */
+
+{
+  float xright,ytop;
+  float ymid;
+  float hline_w;
+  float xmid;
+
+  xright = Xpos + Xspace;       /* right hand edge of character (lhe of next character) */
+  ytop = Ypos + Yspace;         /* top edge of character */
+  ymid = (ytop + Ypos) * 0.5;   /* vertical mid point */
+  xmid = (xright + Xpos) * 0.5;   /* horizontal mid point */
+
+  /* width_fac defines the width of the line in terms of the height of the characters */
+
+  hline_w = 0.5 * (width_fac * (ytop - Ypos));
+
+  PSmoveto(xmid,ymid-hline_w,outf);
+  PSlineto(xmid,ymid+hline_w,outf);
+  PSlineto(Xpos,ymid+hline_w,outf);
+  PSlineto(Xpos,ymid-hline_w,outf);
+  PSlineto(xmid,ymid-hline_w,outf);
+} 
+
+void PSmoveto(float x,float y,FILE *outf)
+{
+  fprintf(outf,"%.2f %.2f moveto\n",x,y);
+}
+void PSlineto(float x,float y,FILE *outf)
+{
+  fprintf(outf,"%.2f %.2f lineto\n",x,y);
+}
+void PSPutSpecialText(float Xpos,float Ypos,float Xspace,float Yspace,char *text,
+                     unsigned char current_col,
+                     unsigned char background_colour,float YspaceFactor,FILE *outf)
+/* Handle the special text characters */
+{
+
+  Yspace *= YspaceFactor;  /* shrink the Y axis a little to avoid clashes.*/
+
+
+  if(strcmp(text,"@horizline") == 0){
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fhorizline") == 0){
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@thickhorizline") == 0){
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fthickhorizline") == 0){
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    PSstroke(outf);
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@thinhorizline") == 0){
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,0.1,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fthinhorizline") == 0){
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,0.1,outf);
+    PSstroke(outf);
+    ALDrawHorizLine(Xpos,Ypos,Xspace,Yspace,0.1,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@rightarrow") == 0){
+    ALDrawRightArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@frightarrow") == 0){
+/*    ALDrawRightArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);*/
+/* temporary change to the right arrow width 20/1/1995*/
+    ALDrawRightArrow(Xpos,Ypos,(Xspace*0.7),Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawRightArrow(Xpos,Ypos,(Xspace*0.7),Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@leftarrow") == 0){
+    ALDrawLeftArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fleftarrow") == 0){
+    ALDrawLeftArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawLeftArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@uparrow") == 0){
+    ALDrawUpArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fuparrow") == 0){
+    ALDrawUpArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawUpArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@suparrow") == 0){
+    ALDrawSmallUpArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fsuparrow") == 0){
+    ALDrawSmallUpArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawSmallUpArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@downarrow") == 0){
+    ALDrawDownArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fdownarrow") == 0){
+    ALDrawDownArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawDownArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@sdownarrow") == 0){
+    ALDrawSmallDownArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fsdownarrow") == 0){
+    ALDrawSmallDownArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawSmallDownArrow(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@circle") == 0){
+    ALDrawCircle(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fcircle") == 0){
+    ALDrawCircle(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawCircle(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@diamond") == 0){
+    ALDrawDiamond(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fdiamond") == 0){
+    ALDrawDiamond(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawDiamond(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@bar") == 0){
+    ALDrawBar(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fbar") == 0){
+    ALDrawBar(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawBar(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@leftsemiend") == 0){
+    ALDrawLeftSemiEnd(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@fleftsemiend") == 0){
+    ALDrawLeftSemiEnd(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawLeftSemiEnd(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@rightsemiend") == 0){
+    ALDrawRightSemiEnd(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+  }else if(strcmp(text,"@frightsemiend") == 0){
+    ALDrawRightSemiEnd(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+    ALDrawRightSemiEnd(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+  }else if(strcmp(text,"@lefthelixend") == 0){
+
+    ALDrawRightHalfHorizLine(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    PSstroke(outf);
+    ALDrawRightHalfHorizLine(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+    ALDrawPseudoEllipse(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",background_colour);
+
+    ALDrawLeftHalfHorizLine(Xpos,Ypos,Xspace,Yspace,0.1,outf);
+    PSstroke(outf);
+    ALDrawLeftHalfHorizLine(Xpos,Ypos,Xspace,Yspace,0.1,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+    ALDrawPseudoEllipse(Xpos,Ypos,Xspace,Yspace,0.5,outf);
+    PSstroke(outf);
+
+  }else if(strcmp(text,"@righthelixend") == 0){
+
+    ALDrawLeftHalfHorizLine(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    PSstroke(outf);
+    ALDrawLeftHalfHorizLine(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+    ALDrawPseudoEllipse(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    PSstroke(outf);
+    ALDrawPseudoEllipse(Xpos,Ypos,Xspace,Yspace,1.0,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+    ALDrawRightHalfHorizLine(Xpos,Ypos,Xspace,Yspace,0.1,outf);
+    PSstroke(outf);
+    ALDrawRightHalfHorizLine(Xpos,Ypos,Xspace,Yspace,0.1,outf);
+    fprintf(outf,"closepath \n C%-d \n fill \n",current_col);
+
+
+  }else{
+    fprintf(stderr,"Error:  Unrecognised special character: %s\n",text);
+    error(" ",1);
+  }
+}
+
+void PSstroke(FILE *outf)
+{
+  fprintf(outf,"stroke\n");
+}
+
+void PSnewpath(FILE *outf)
+{
+  fprintf(outf,"newpath\n");
+}
+
+void ALColourBackground(FILE *outf,int colour, int *b_region)
+{
+    int x1,y1,x2,y2;
+    x1 = b_region[0];
+    x2 = b_region[2];
+    y1 = b_region[1];
+    y2 = b_region[3];
+
+   fprintf(outf,"%d %d moveto %d %d lineto %d %d lineto %d %d lineto %d %d lineto closepath\n",
+               x1,y1,x2,y1,x2,y2,x1,y2,x1,y1);
+   fprintf(outf," C%-d \n fill \n",colour);
+   /* reset the colour to white */
+   /*   fprintf(outf," C99\n");*/
+}
+
+void ALCheckLegalRange(int sx,int sy, int ex, int ey, int xmin, int ymin, int xmax, int ymax)
+/* check if sx, sy, ex, ey are within the limits given by xmin, ymin, xmax, ymax */
+{
+    extern FILE *std_err;
+    if(   sx >= xmin && sx <= xmax
+       && sy >= ymin && sy <= ymax
+       && ex <= xmax && ex >= xmin
+       && ey <= ymax && ey >= ymin){
+       return;
+    }else{
+       fprintf(std_err,"\n\nALSCRIPT COMMAND FILE ERROR:\n");
+       fprintf(std_err,"Maximum legal range:\n");
+       fprintf(std_err,"From position %d of sequence %d to position %d of sequence %d\n",
+               xmin,ymin,xmax,ymax);
+
+       fprintf(std_err,"Your range:\n");
+       fprintf(std_err,"From position %d of sequence %d to position %d of sequence %d\n",
+               sx,sy,ex,ey);
+
+       GJerror("Range too big for alignment - try again!");
+       exit(0);
+    }
+}
+
+void ALMakeHelixText(int sx, int sy, int ex, char ***texts)
+{
+    int i;
+    texts[sx][sy] = GJstrdup("@lefthelixend");
+    texts[ex][sy] = GJstrdup("@righthelixend");
+    for(i=sx+1;i<ex;++i){
+       texts[i][sy] = GJstrdup("@fthickhorizline");
+    }
+}
+
+void ALMakeStrandText(int sx, int sy, int ex, char ***texts)
+{
+    int i;
+    texts[ex][sy] = GJstrdup("@frightarrow");
+    for(i=sx;i<ex;++i){
+       texts[i][sy] = GJstrdup("@fhorizline");
+    }
+}
+
+void ALMakeCoilText(int sx, int sy, int ex, char ***texts)
+{
+    int i;
+    for(i=sx;i<ex+1;++i){
+       texts[i][sy] = GJstrdup("@fthinhorizline");
+    }
+}
+
+int ALrel(char *pos,int *relnum)
+/* ALrel: parses a string that defines a position in a sequence.  This can
+have the form
+
+to indicate position 10          10
+to indicate three before 10      10-3
+to indicate five after 10        10+5
+
+The routine looks up the relative number in *relnum before adding or
+subtracting numbers, the end result is therefore relative to the current 
+alignment position.
+
+It should be easy to extend this routine for the relative movement to
+apply to positions in another sequence rather than alignment
+coordinates.  (e.g. 10+5:73  might mean 5 after the current position in sequence 73).
+*/
+
+{
+     int i;
+     int len;
+     char *token;
+     int ipos,ioff;  /* position and offset */
+     extern FILE *std_in,*std_out,*std_err;
+
+     len = strlen(pos);
+     ioff = 0;
+     ipos = 0;
+
+     
+     if(strchr(pos,'+') != NULL){
+        token = strtok(pos,"+");
+        if(strlen(token)== 0){
+            error("Error decoding position",1);
+            fprintf(std_err,"Offending string is: %s\n",pos);
+        }else{
+            ipos = atoi(token);
+        }
+        token = strtok(NULL,"\0");
+        if(strlen(token)== 0){
+            error("Error decoding position",1);
+            fprintf(std_err,"Offending string is: %s\n",pos);
+        }else{
+            ioff = atoi(token);
+        }
+        return (relnum[ipos] + ioff);
+     }else if(strchr(pos,'-') != NULL){
+        token = strtok(pos,"-");
+        if(strlen(token)== 0){
+            error("Error decoding position",1);
+            fprintf(std_err,"Offending string is: %s\n",pos);
+        }else{
+            ipos = atoi(token);
+        }
+        token = strtok(NULL,"\0");
+        if(strlen(token)== 0){
+            error("Error decoding position",1);
+            fprintf(std_err,"Offending string is: %s\n",pos);
+        }else{
+            ioff = atoi(token);
+        }
+        return (relnum[ipos] - ioff);
+     }else{
+        ipos = atoi(pos);
+        return relnum[ipos];
+     }
+}
+
+int *ALCalCons(struct seqdat *bloc,
+               int sx,int sy,int ex,int ey,int *ret_val,int len)
+
+/* Calculate conservation for an alignment - this can be just a segment of an alignment */
+/* bloc = the alignment bloc */
+/* sx,sy,ex,ey = the positions over which to calculate the conservation */
+/* conscut = conservation number cutoff ( an integer 0 - 10) */
+/* ret_val = a pointer to an integer array to store the results of the calculation */
+/* len = the length of the array ret_val - this must be the same as the alignment length */
+
+{
+    int i,j,tlen,k;
+    char *temp;
+    char *temp2;
+    float tval;
+    int gcount;
+
+    tlen = ey -sy + 1;
+    temp = GJstrcreate(tlen+1,NULL);
+    if(ret_val == NULL){
+       ret_val = (int *) GJmalloc(sizeof(int) * len);
+    }
+
+    for(i=sx;i<(ex+1);++i){
+        /* calculate conservation at each position */
+       k = 0;
+        for(j=sy;j<(ey+1);++j){
+           temp[k] = bloc[j].seq[i];
+           ++k;
+       }
+       temp2 = GJstoupper(temp);
+       /* check for all gap columns */
+       gcount = 0;
+       for(j=0;j<tlen;++j){
+           if(temp2[j] == ' ') ++gcount;
+       }
+       if(gcount == tlen){
+           tval = 0.0;
+       }else{
+           tval = mzcons((unsigned char *)temp2,tlen);
+       }
+/*     fprintf(stderr,"In calcons: i:%d tlen:%d temp:%s tval:%f\n",i,tlen,temp,tval);*/
+       ret_val[i] = 10 * tval;
+       GJfree(temp2);
+    }
+    GJfree(temp);
+    return ret_val;
+}
+
+float mzcons(unsigned char *pos,int n)
+/* calculate conservation value according to Zvelebil et al for a set
+   of amino acids and gaps stored in string pos of length n
+   translated from the fortran mzcons.f 6/3/1995
+*/
+
+{
+    /* --  conmat contains a table like that shown in the JMB paper
+       order of amino acids is GAP,ARNDCQEGHILKMFPSTWYVBZX
+    */
+    static char *acids = " ARNDCQEGHILKMFPSTWYVBZX";
+    static int conmat[24][10] = {
+       {1,1,1,1,1,1,1,1,1,1},  /*  */
+       {1,0,0,0,0,1,1,0,0,0},  /*A */
+       {0,1,0,1,1,0,0,0,0,0},  /*R */ 
+       {0,0,0,1,0,1,0,0,0,0},  /*N */
+       {0,0,1,1,1,1,0,0,0,0},  /*D */ 
+       {1,0,0,0,0,1,0,0,0,0},  /*C */ 
+       {0,0,0,1,0,0,0,0,0,0},  /*Q */
+       {0,0,1,1,1,0,0,0,0,0},  /*E */
+       {1,0,0,0,0,1,1,0,0,0},  /*G */
+       {1,1,0,1,1,0,0,0,1,0},  /*H */
+       {1,0,0,0,0,0,0,1,0,0},  /*I */
+       {1,0,0,0,0,0,0,1,0,0},  /*L */
+       {1,1,0,1,1,0,0,0,0,0},  /*K */
+       {1,0,0,0,0,0,0,0,0,0},  /*M */
+       {1,0,0,0,0,0,0,0,1,0},  /*F */
+       {0,0,0,0,0,1,0,0,0,1},  /*P */
+       {0,0,0,1,0,1,1,0,0,0},  /*S */
+       {1,0,0,1,0,1,0,0,0,0},  /*T */
+       {1,0,0,1,0,0,0,0,1,0},  /*W */
+       {1,0,0,1,0,0,0,0,1,0},  /*Y */
+       {1,0,0,0,0,1,0,1,0,0},  /*V */
+       {0,0,0,1,0,0,0,0,0,0},  /*B */
+       {0,0,0,1,0,0,0,0,0,0},  /*Z */
+       {1,1,1,1,1,1,1,1,1,1}   /*X */
+    };
+
+    int concnt,it,i,j,k,l,tcnt,ibseq;
+    int nide;
+    float con;
+    unsigned char facid;
+
+    concnt = 0;
+    for(j=0;j<10;++j){
+       /*found: outer loop over properties
+       set IT to the value of the first amino acid*/
+       it = conmat[GJindex(acids,pos[0])][j];
+       /*loop over remaining acids, if a difference occurs then
+        set tcnt to 1*/
+        tcnt = 0;
+        for(k=1;k<n;++k){
+           if(it != conmat[GJindex(acids,pos[k])][j]){
+                tcnt = 1;
+          }
+       }
+       /*add tcnt to concnt*/
+        concnt += tcnt;
+    }
+    /* check for total identity at this position*/
+    facid = pos[0];
+    nide = 0;
+    for(k=1;k<n;++k){
+       if(facid == pos[k]){
+             ++nide;
+       }
+    }
+
+    /*calculate the conservation*/
+    if(concnt == 10){
+      con = 0.0;
+    }else if(concnt == 0){
+       if(nide == (n-1)){
+           /*total identity*/
+            con = 1.0;
+       }else{
+            /*not identity, but same properties*/
+              con = 0.9;
+       }
+    }else{
+        con = 0.9 - 0.1 * concnt;
+    }
+    return con;
+}
+
+
+int GJindex(char *str,char c)
+{
+    char *t;
+    t = strchr(str,c);
+    if(t == NULL) return -1;
+    return (int) (t - str);
+}
+