/*===========================================================================
  Copyright (C) 1995-2009 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/* ++++++++++++++++++++++++++++++++++++++++++++++++++

.LANGUAGE: C
.AUTHOR:
  K. Banse                     ESO - Garching
.IDENTIFICATION
  functions  sexa2data, sexa2val, val2sexa, form_sexa, form1_sexa
             Convsng, Convcoo, XConvsng, XConvcoo
.KEYWORDS
  coordinates
.PURPOSE
  convert character coordinate string to real pixel no. of a BDF
.ALGORITHM
  the MIDAS standard for input of coordinates is:
  real number = world coordinate            or
  "@"integer number = pixel coordinate            or
  "<" = first pixel coordinate (= 1)            or
  ">" = last pixel coordinate

  the resulting pixel coordinates will be obtained according to these rules

.RETURNS
  return status, = 0 o.k., else not o.k.

.VERSIONS
  2.10		increase size of internal buffers
  3.00		changed from Fortran to C
  2.20	930923  take out end > begin_coord check in Cextrco

 090904			last modif
-------------------------------------------------- */

#include <midas_def.h>

#include <stdio.h>


#define MAXDIM  4		/* synchronize with wrldco.c */

static char subs[MAXDIM][30];

static int  noax, linflag, npixls[MAXDIM];

static double  starrt[MAXDIM], stepp[MAXDIM];

/*

*/

int sexa2data(ra,sexa_str,value,ihd,ihm,hs)
int  ra;		/* IN: 1, if RA (=> hours are in `sexa_str'),
			       0, if DEC (=> degrees) */
char *sexa_str;		/* IN: ab:cd:ef.gh  or cd:ef.gh  or ef.gh */
double  *value;		/* OUT: coord in decimal form (degrees) */
int  *ihd;		/* OUT: hours or degrees */
int  *ihm;		/* OUT: minutes */
double  *hs;		/* OUT: seconds 
			all 3 parms above are returned as absolute values! */

{
int  ix, iwa, minx;

float  rwa;

double  degs, mins, secs;

char  aux[40], *cptr;


degs = mins = 0.0;
cptr = sexa_str;                        /* point to beginning of string */

if (*cptr == '-') 
   {
   minx = 1;
   cptr ++;
   }
else
   minx = 0;

ix = CGN_INDEXC(cptr,':');
if (ix == 0) return (-1);

if (ix > 0)
   {
   (void) strncpy(aux,cptr,ix);
   aux[ix] = '\0';
   if (CGN_CNVT(aux,4,1,&iwa,&rwa,&degs) != 1) return (1);
   cptr += (ix+1);

   ix = CGN_INDEXC(cptr,':');
   if (ix < 1)
      {
      mins = degs;
      degs = 0.0;
      }
   else
      {
      (void) strncpy(aux,cptr,ix);
      aux[ix] = '\0';
      if (CGN_CNVT(aux,4,1,&iwa,&rwa,&mins) != 1) return (1);
      cptr += (ix+1);
      }
   }
if (CGN_CNVT(cptr,4,1,&iwa,&rwa,&secs) != 1) return (1);

*ihd = (int) degs;  *ihm = (int) mins;  *hs = secs;

degs += ((mins/60.) + (secs/3600.));
if (ra == 1) degs *= 15.0;

if (minx == 1)
   *value = -degs;
else
   *value = degs;

return (0);
}

/*

*/

int sexa2val(ra,sexa_str,value)
int  ra;		/* IN: 1, if RA (=> hours),
			       0, if DEC (=> degrees) */
char *sexa_str;		/* IN: ab:cd:ef.gh  or cd:ef.gh  or ef.gh */
double  *value;		/* OUT: coord in decimal form (degrees) */

{
int  ix, iwa, minx;

float  rwa;

double  degs, mins, secs;

char  aux[40], *cptr;



degs = mins = 0.0;
cptr = sexa_str;                        /* point to beginning of string */

if (*cptr == ':') return (-1);
if (*cptr == '-') 
   {
   minx = 1;
   cptr ++;
   }
else
   minx = 0;


ix = CGN_INDEXC(cptr,':');
if (ix > 0)
   {
   (void) strncpy(aux,cptr,ix);
   aux[ix] = '\0';
   if (CGN_CNVT(aux,4,1,&iwa,&rwa,&degs) != 1) return (1);
   cptr += (ix+1);

   ix = CGN_INDEXC(cptr,':');
   if (ix < 1)
      {
      mins = degs;
      degs = 0.0;
      }
   else
      {
      (void) strncpy(aux,cptr,ix);
      aux[ix] = '\0';
      if (CGN_CNVT(aux,4,1,&iwa,&rwa,&mins) != 1) return (1);
      cptr += (ix+1);
      }
   }

if (CGN_CNVT(cptr,4,1,&iwa,&rwa,&secs) != 1) return (1);

degs += ((mins/60.) + (secs/3600.));
if (ra == 1) degs *= 15.0;

if (minx == 1)
   *value = -degs;
else
   *value = degs;
return (0);
}

/*

*/

void val2sexa(ra,value,hdegs,hmins,hsecs,minflg)
int  ra;		/* IN: 1, if Ra (=> hours),
			       0, if DEC (=> degrees) */
double  value;		/* IN: coord in decimal form (degrees) */
int  *hdegs;		/* OUT: hours/degrees (depends on `ra' */
int  *hmins;		/* OUT: minutes */
double  *hsecs;		/* OUT: seconds 
		           all 3 parms above are returned as absolute values! */
int  *minflg;		/* = 1 if value was negative, else = 0 */

{
int imins, idegs;

double  degs, rdegs, mins, secs;


if (value < 0.0)
   {
   *minflg = 1;
   value = -value;
   }
else
   *minflg = 0;

if (ra == 1)
   degs = value / 15.0;
else
   degs = value;

idegs = (int) degs;
rdegs = (double)idegs;
if (rdegs > degs)
   {
   idegs --;
   rdegs--;
   }


secs = (degs - rdegs) * 3600.0;

mins = secs / 60.0;
imins = (int) mins;
if ((double)imins > mins) imins --;		/* take care of rounding... */
secs -= (double) (imins*60);

*hdegs = idegs;
*hmins = imins;
*hsecs = secs;
}

/*

*/

void form_sexa(ra,value,sexa_str)
int  ra;		/* IN: 1, if Ra (=> hours),
			       0, if DEC (=> degrees) */
double  value;		/* IN: coord in decimal form (degrees) */
char *sexa_str;		/* OUT: ab:cd:ef.gh  */

{
int minx, imins, idegs;

double  secs;

char  *cptr;


val2sexa(ra,value,&idegs,&imins,&secs,&minx);

cptr = sexa_str;
if (minx == 1) *cptr++ = '-';
(void) sprintf(cptr,"%d:%d:%2.2f",idegs,imins,secs);
}

/*

*/

int move_sxdc(direc,ra,in_str,out_str)
int  direc;		/* IN: > 0, if from sexa -> dec string,
			       < 0, if from dec -> sexa string */
int  ra;		/* IN: 1, if RA (=> hours),
			       0, if DEC (=> degrees) */
char *in_str;		/* IN: ab:cd:ef.gh or cd:ef.gh or ef.gh <-> xy.zzzzz */
char *out_str;		/* OUT: opposite of `in_str' */

{
int  stat;

double value;


if (direc > 0)
   {
   stat = sexa2val(ra,in_str,&value);
   if (stat == 0)
      (void) sprintf(out_str,"%10.8g",value);
   }

else
   {
   int  iwa;
   float rwa;

   stat = CGN_CNVT(in_str,4,1,&iwa,&rwa,&value);
   if (stat == 1) 
      {
      form_sexa(ra,value,out_str);
      stat = 0;		/* to have common return status */
      }
   else
      stat = -1;
   }

return stat;
}

/*

*/

void form1_sexa(ihd,ihm,hs,sexa_str)
int  ihd;		/* IN: hours or degrees */
int  ihm;		/* IN: minutes */
double  hs;		/* IN: seconds */
char *sexa_str;		/* OUT: ab:cd:ef.gh  or cd:ef.gh  or ef.gh */

{
int minx;

double  value;

char  *cptr;


minx = 0;
if (ihd < 0)				/* get absolute values */
   {
   minx = 1;
   ihd = -ihd;
   }
if (ihm < 0)
   {
   minx = 1;
   ihm = -ihm;
   }
if (hs < 0.0)
   {
   minx = 1;
   hs = -hs;
   }

value = (double) (ihd*3600 + ihm*60);
value += hs;				/* value in seconds */

cptr = sexa_str;
if (minx == 1) *cptr++ = '-';
   
form_sexa(0,value,cptr);		/* pass always positive value */
}

/*

*/

static int Convsng(pixels)
			/* the static strings `subs' are used for input */
int    *pixels; 	/* OUT: frame pixels */

{
int    stat, flgpix[6], k, n, iwa;

float  rr;

double  dd1[MAXDIM], dd2[MAXDIM];

char  errbuf[80], pixlab[3];


for (n=0; n<noax; n++)
   {
   flgpix[n] = 1;

   if (subs[n][0] == '<')				/* handle "<" format */
      {
      pixels[n] = 0;					/* C indexing... */
      dd1[n] = starrt[n];
      }
       
   else if (subs[n][0] == '>')				/* handle ">" format */
      pixels[n] = npixls[n] - 1;			/* C indexing... */
 
   else if ((subs[n][0] == 'C') || (subs[n][0] == 'c'))	/* "Center" */
      {
      if (npixls[n] > 1)
         pixels[n] = (npixls[n] / 2) - 1;
      else
         pixels[n] = 0;
      }
 
   else if (subs[n][0] == '@')				/* handle "@" format */
      {
      k = CGN_CNVT(&subs[n][1],1,1,&iwa,&rr,&dd1[n]);
      if (k > 0) 
         {
         pixels[n] = iwa - 1;	/* coord. string in Fortran notation */
         if (iwa == 1) dd1[n] = starrt[n];
         }
      else
         return (-3);
      }
   else
      { 			/*  here we have world coordinates */
      k = CGN_INDEXC(subs[n],':');
      if (k > 0)		/* test, if sexagesimal string */
         {
         if (n == 0) 
            k = 1;		/* x-coord is always RA */
         else
            k = 0;
         stat = sexa2val(k,subs[n],&dd1[n]);
         if (stat != 0) return (-3);
         }
      else
         {
         k = CGN_CNVT(subs[n],4,1,&iwa,&rr,&dd1[n]);
         if (k < 1) return (-3);
         }
      flgpix[n] = -1;		/* remember it */
      }
   }


if (linflag == 0)			/* we have non-linear coord_sys */
   {
   for (n=0; n<noax; n++)
      {
      if (flgpix[n] < 0) 
         {				/* no mixed coord input possible! */
         for (k=0; k<noax; k++)
            {
            if (flgpix[k] > 0) 
               {
               if (k != 2)		/* 3rd dimension */
                  {
                  (void) sprintf(errbuf,
"Warning: non-linear WCS - mixed coordinate input might cause problems...");
                  SCTPUT(errbuf);
                  }

               dd1[k] = starrt[k] + (pixels[k]*stepp[k]);  /* approximate .. */
               }
            }

         if (noax < 3) dd1[2] = starrt[2];	/* take care of art. cubes */
         if (fp2wc(-1,0,dd1,dd2) != 0)		/* convert wc -> fp */
            return (-3);

         for (k=0; k<noax; k++)
            {
            if (flgpix[k] < 0)
               pixels[k] = CGN_NINT((float)dd2[k]) - 1;	/* C indexing... */
            }
         break;
         }
      }
   }
else
   {
   for (n=0; n<noax; n++)
      {
      if (flgpix[n] < 0)	
         {				/* mixed coord input possible */
         for (k=0; k<noax; k++)
            {
            if (flgpix[k] > 0) 
               dd1[k] = starrt[k] + (pixels[k]*stepp[k]);  /* approximate .. */
            }
      
         if (noax < 3) dd1[2] = starrt[2];	/* take care of art. cubes */
         if (fp2wc(-1,0,dd1,dd2) != 0)		/* convert wc -> fp */
            return (-3);

         for (k=0; k<noax; k++)
            {
            if (flgpix[k] < 0)
               pixels[k] = CGN_NINT((float)dd2[k]) - 1;	/* C indexing... */
            }
         break;
         }
      }
   }


for (n=0; n<noax; n++)
   {
   if ( (pixels[n] >= npixls[n]) || (pixels[n] < 0) )
      {
      pixlab[0] = 'x';  pixlab[1] = 'y'; pixlab[2] = 'z';
      (void) sprintf(errbuf,"%c-pixel outside valid range ...",pixlab[n]);
      SCTPUT(errbuf);
      return (-1);
      }
   }
return (0);
}

/*

*/
int Convcoo(twocoord,imno,string,pixdim,subdim,sublo,subhi)

int  twocoord;		/* IN: 0 for single coord, 1 for interval */
int  imno;		/* IN: image no.
                              if > -1, valid imno + init conversion scheme
                              if < 0, use previous values */
char *string;		/* IN: coord string in the format:
                               either [c1,c2,c3] or c1,c2,c3
			       and [c1,c2,c3:d1,d2,d3] or  c1,c2,c3:d1,d2,d3 */
int  pixdim;		/* IN: max. no. of axes wanted in subframe (1,2,3) */

int  *subdim;		/* OUT: dimension of subframe */
int  *sublo;		/* OUT: low pixels for `twocoord' = 1,
			        the pixels for `twocoord' = 0 */
int  *subhi;		/* OUT: high pixels for `twocoord' = 1 */

{
int  bracket, begin, k, n, ls, off, newsep;

char subst[80];



if (pixdim > MAXDIM)
   {
   SCTPUT("only MAXDIM dimensions supported...");
   return (3);
   }

if (string[0] == '[') 
   bracket = 1;
else
   bracket = 0;


/* test imno + initialize conversion, if a valid image no. */

if (imno > -1) 
   {
   double  dd1[MAXDIM], dd2[MAXDIM];
   int  stat, iav, uni, nulo;

   stat = fp2wc(0,imno,dd1,dd2);	/* prepare wc -> fp conversion */
   if (stat > 0) return (stat);		/* initialization gave problems */

   linflag = stat;			/* save linear coord_sys flag */
   (void) SCDRDI(imno,"NPIX",1,MAXDIM,&iav,npixls,&uni,&nulo);
   starrt[2] = 0.0;			/* to have a value ... */
   (void) SCDRDD(imno,"START",1,MAXDIM,&iav,starrt,&uni,&nulo);
   (void) SCDRDD(imno,"STEP",1,MAXDIM,&iav,stepp,&uni,&nulo);
   }


/*  get substring with start coordinates */


if (twocoord == 0)
   {
   (void) strcpy(subst,&string[bracket]);
   if (bracket > 0) 
      {
      k = CGN_INDEXC(subst,']');
      if (k >= 0)
          {
	  subst[k] = '\0';
          }
      }
   else
      {
      register int nr;

      for (nr=(int)strlen(subst)-1; nr>0; nr--)
         {
         if (subst[nr] != ' ')
            {
            subst[nr+1] = '\0';
            break;
            }
         }
      }
   }						/* subst = c1,c2,c3  */

else
   {
   k = CGN_INDEXS(string,"..");
   if (k < 1) 
      {
      newsep = 1;
      k = CGN_INDEXC(string,':');
      }
   else
      newsep = 2;

   if (k < 1)
      {
      SCTPUT("invalid coord. interval ...");
      return (5);
      }

   ls = k - bracket;
   (void) strncpy(subst,&string[bracket],ls);
   subst[ls] = '\0';				/* subst = c1,c2,c3  */
   begin = k + newsep;				/* point to end coords */
   }


/*  isolate start coords + determine dimension of subframe */

for (n=0; n<pixdim; n++)                /* init output params first */
   {
   sublo[n] = 0;
   subhi[n] = 0;
   }

noax = 0;
off = 0;
for (n=0; n<pixdim; n++)
   {
   k = CGN_EXTRSS(subst,(int)strlen(subst),',',&off,subs[n],30);
   if (k > 0)
      noax = n + 1;
   else
      break;
   }
*subdim = noax;
if (noax == 0) goto sect_9000;


k = Convsng(sublo);
if (k != 0) goto sect_9090;

if (twocoord == 0) return (0);			/* was only one coord_pair */


/*  for coord-interval, isolate substring with end coordinates */

if (bracket > 0)
   {
   ls = CGN_EXTRSS(string,156,']',&begin,subst,78);
   if (ls < 1) goto sect_9000;                       /* wrong syntax... */
   }
else
   ls = CGN_COPY(subst,&string[begin]);

off = 0;

for (n=0; n<noax; n++)
   {
   k = CGN_EXTRSS(subst,ls,',',&off,subs[n],30);
   if (k < 1) goto sect_9000;                       /* wrong syntax... */
   }

k = Convsng(subhi);
if (k != 0) goto sect_9090;

for (n=0; n<noax; n++)
   {
   if (sublo[n] > subhi[n])
      {
      SCTPUT("interval start > end => empty coordinate interval ...");
      return (4);
      }
   }

return (0);

sect_9000:
SCTPUT("invalid syntax in coordinate string...");
return (1);

sect_9090:
return (2);
}

/*

*/
static int XConvsng(pixels)
                        /* the static strings `subs' are used for input */
float  *pixels;         /* OUT: frame pixels */

{
int    stat, flgpix[6], k, n, iwa;

float  rr;

double  dd1[MAXDIM], dd2[MAXDIM];

char  errbuf[80], pixlab[3];


for (n=0; n<noax; n++)
   {
   flgpix[n] = 1;

   if (subs[n][0] == '<')                               /* handle "<" format */
      {
      pixels[n] = 0.0;                                    /* C indexing... */
      dd1[n] = starrt[n];
      }

   else if (subs[n][0] == '>')                          /* handle ">" format */
      pixels[n] = npixls[n] - 1.0;			/* C indexing... */

   else if ((subs[n][0] == 'C') || (subs[n][0] == 'c')) /* "Center" */
      {
      if (npixls[n] > 1)
         pixels[n] = (npixls[n]/2) - 1.0;
      else
         pixels[n] = 0.0;
      }

   else if (subs[n][0] == '@')                          /* handle "@" format */
      {
      k = CGN_CNVT(&subs[n][1],2,1,&iwa,&rr,&dd1[n]);
      if (k > 0)
         {
         pixels[n] = rr - 1.0;		/* coord. string in Fortran notation */
         if (CGN_NINT(rr) == 1) dd1[n] = starrt[n];
         }
      else
         return (-3);
      }
   else
      {                         /*  here we have world coordinates */
      k = CGN_INDEXC(subs[n],':');
      if (k > 0)                /* test, if sexagesimal string */
         {
         if (n == 0)
            k = 1;              /* x-coord is always RA */
         else
            k = 0;
         stat = sexa2val(k,subs[n],&dd1[n]);
         if (stat != 0) return (-3);
         }
      else
         {
         k = CGN_CNVT(subs[n],4,1,&iwa,&rr,&dd1[n]);
         if (k < 1) return (-3);
         }
      flgpix[n] = -1;           /* remember it */
      }
   }


if (linflag == 0)                       /* we have non-linear coord_sys */
   {
   for (n=0; n<noax; n++)
      {
      if (flgpix[n] < 0)
         {                              /* no mixed coord input possible! */
         for (k=0; k<noax; k++)
            {
            if (flgpix[k] > 0)
               {
               if (k != 2)              /* 3rd dimension */
                  {
                  (void) sprintf(errbuf,
"Warning: non-linear WCS - mixed coordinate input might cause problems...");
                  SCTPUT(errbuf);
                  }

               dd1[k] = starrt[k] + (pixels[k]*stepp[k]);  /* approximate .. */
               }
            }

         if (noax < 3) dd1[2] = starrt[2];      /* take care of art. cubes */
         if (fp2wc(-1,0,dd1,dd2) != 0)          /* convert wc -> fp */
            return (-3);

         for (k=0; k<noax; k++)
            {
            if (flgpix[k] < 0)
               pixels[k] = (float)dd2[k] - 1.0;		/* C indexing... */
            }
         break;
         }
      }
   }
else
   {
   for (n=0; n<noax; n++)
      {
      if (flgpix[n] < 0)
         {                              /* mixed coord input possible */
         for (k=0; k<noax; k++)
            {
            if (flgpix[k] > 0)
               dd1[k] = starrt[k] + (pixels[k]*stepp[k]);  /* approximate .. */
            }

         if (noax < 3) dd1[2] = starrt[2];      /* take care of art. cubes */
         if (fp2wc(-1,0,dd1,dd2) != 0)          /* convert wc -> fp */
            return (-3);

         for (k=0; k<noax; k++)
            {
            if (flgpix[k] < 0)
               pixels[k] = (float)dd2[k] - 1.0;		/* C indexing... */
            }
         break;
         }
      }
   }


for (n=0; n<noax; n++)
   {
   if ( (pixels[n] >= npixls[n]) || (pixels[n] < 0.0) )
      {
      pixlab[0] = 'x';  pixlab[1] = 'y'; pixlab[2] = 'z';
      (void) sprintf(errbuf,"%c-pixel outside valid range ...",pixlab[n]);
      SCTPUT(errbuf);
      return (-1);
      }
   }
return (0);
}

/*

*/

int XConvcoo(twocoord,imno,string,pixdim,subdim,sublo,subhi)

int  twocoord;          /* IN: 0 for single coord, 1 for interval */
int  imno;              /* IN: image no.
                              if > -1, valid imno + init conversion scheme
                              if < 0, use previous values */
char *string;           /* IN: coord string in the format:
                               either [c1,c2,c3] or c1,c2,c3
                               and [c1,c2,c3:d1,d2,d3] or  c1,c2,c3:d1,d2,d3 */
int  pixdim;            /* IN: max. no. of axes wanted in subframe (1,2,3) */

int  *subdim;           /* OUT: dimension of subframe */
float  *sublo;		/* OUT: low pixels for `twocoord' = 1,
                                the pixels for `twocoord' = 0 */
float  *subhi;		/* OUT: high pixels for `twocoord' = 1 */

{
int  bracket, begin, k, n, ls, off, newsep;

char subst[80];



if (pixdim > MAXDIM)
   {
   SCTPUT("only MAXDIM dimensions supported...");
   return (3);
   }

if (string[0] == '[')
   bracket = 1;
else
   bracket = 0;


/* test imno + initialize conversion, if a valid image no. */

if (imno > -1)
   {
   double  dd1[MAXDIM], dd2[MAXDIM];
   int  stat, iav, uni, nulo;

   stat = fp2wc(0,imno,dd1,dd2);        /* prepare wc -> fp conversion */
   if (stat > 0) return (stat);         /* initialization gave problems */

   linflag = stat;                      /* save linear coord_sys flag */
   (void) SCDRDI(imno,"NPIX",1,MAXDIM,&iav,npixls,&uni,&nulo);
   starrt[2] = 0.0;                     /* to have a value ... */
   (void) SCDRDD(imno,"START",1,MAXDIM,&iav,starrt,&uni,&nulo);
   (void) SCDRDD(imno,"STEP",1,MAXDIM,&iav,stepp,&uni,&nulo);
   }


/*  get substring with start coordinates */


if (twocoord == 0)
   {
   (void) strcpy(subst,&string[bracket]);
   if (bracket > 0)
      {
      k = CGN_INDEXC(subst,']');
      subst[k] = '\0';
      }
   else
      {
      register int nr;

      for (nr=(int)strlen(subst)-1; nr>0; nr--)
         {
         if (subst[nr] != ' ')
            {
            subst[nr+1] = '\0';
            break;
            }
         }
      }
   }                                            /* subst = c1,c2,c3  */

else
   {
   k = CGN_INDEXS(string,"..");
   if (k < 1)
      {
      newsep = 1;
      k = CGN_INDEXC(string,':');
      }
   else
      newsep = 2;

   if (k < 1)
      {
      SCTPUT("invalid coord. interval ...");
      return (5);
      }

   ls = k - bracket;
   (void) strncpy(subst,&string[bracket],ls);
   subst[ls] = '\0';                            /* subst = c1,c2,c3  */
   begin = k + newsep;                          /* point to end coords */
   }


/*  isolate start coords + determine dimension of subframe */

for (n=0; n<pixdim; n++)                /* init output params first */
   {
   sublo[n] = 0.0;
   subhi[n] = 0.0;
   }

noax = 0;
off = 0;
for (n=0; n<pixdim; n++)
   {
   k = CGN_EXTRSS(subst,(int)strlen(subst),',',&off,subs[n],30);
   if (k > 0)
      noax = n + 1;
   else
      break;
   }
*subdim = noax;
if (noax == 0) goto sect_9000;


k = XConvsng(sublo);
if (k != 0) goto sect_9090;

if (twocoord == 0) return (0);                  /* was only one coord_pair */


/*  for coord-interval, isolate substring with end coordinates */

if (bracket > 0)
   {
   ls = CGN_EXTRSS(string,156,']',&begin,subst,78);
   if (ls < 1) goto sect_9000;                       /* wrong syntax... */
   }
else
   ls = CGN_COPY(subst,&string[begin]);

off = 0;

for (n=0; n<noax; n++)
   {
   k = CGN_EXTRSS(subst,ls,',',&off,subs[n],30);
   if (k < 1) goto sect_9000;                       /* wrong syntax... */
   }

k = XConvsng(subhi);
if (k != 0) goto sect_9090;

for (n=0; n<noax; n++)
   {
   if (sublo[n] > subhi[n])
      {
      SCTPUT("interval start > end => empty coordinate interval ...");
      return (4);
      }
   }

return (0);

sect_9000:
SCTPUT("invalid syntax in coordinate string...");
return (1);

sect_9090:
return (2);
}


