/*===========================================================================
  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
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE        Module
.NAME        tbcolumn.c
.LANGUAGE    C
.AUTHOR      IPG-ESO Garching
.CATEGORY    table utilities
.COMMENTS
Inplementation of the Midas commands:
 	CREATE/COLUMN
	p1 table name.
	p2 column name (must start with a colon...)
	p3 optional unit (within quotes)
	p4 data type with array size (e.g. {\tt R*4(12)})
	p5 optional format

 	DELETE/COLUMN
	p1 table name.
	p2 old column name (must start with a colon...)
	p3 optional new column name (must start with a colon...)
	p4 optional unit (within quotes)
	p5 optional new format

 	NAME/COLUMN
	p1 table name.
	p2 column name (must start with a colon...)

 	SET/REFCOLUMN
	p1 table name.
	p2 column name 




.VERSION 1.0 	25-Mar-1989   Definition     J.D. Ponz
.VERSION 1.1 	11-Dec-1989   modif to remove quotes in units M Peron
.VERSION 3.0 	05-Jul-1990   New version with column arrays   F.O.
.VERSION 3.1 	18-Dec-1990 FO: Check NAME/COL that name did NOT exist

 090708		last modif
------------------------------------------------------------*/

#include <tbldef.h>
#include <midas_def.h>
#include <proto_tbl.h>
#include <stdlib.h>

#define PARLEN 	80
#define COLS	16		/* max number of columns	*/
#define DELCOLS	100		/* max number of cols to delete in one go */

static  char table[PARLEN], column[PARLEN];

void sortcol(); 
int  strloc(), tbl_dectyp(), tbl_argc(), tbl_getarg();



int tbl_creacol()
/*++++++++++++++++++
.PURPOSE CREATE/COLUMN table_name :col_name "unit" data_type(array_size) format
.RETURNS Status
------------------*/
{
	int	argc, arg;
	int  	tid, ic, status, i, noelem, type, items;
	char	p3[3][PARLEN];		/* Parameters P3 to P5 	*/
	char	dform[5+TBL_FORLEN];	/* Default Format	*/
	char	*parm, *pform, *ptype, *punit;
  
                                                /* Which table ? 	*/
  tbl_getarg(1, PARLEN, table);
  tid = -1;
  status = TCTOPN(table,F_IO_MODE,&tid);
  if (status) 	return(status);

						/* Which column ? 	*/
  tbl_getarg(2, PARLEN, column);
  status = TCCSER(tid, column, &ic);
  if (status)	goto error;
  if (ic > 0) {
  	status = ERR_TBLCOL; 
	SCTPUT("**** Column already exists");
	goto error;
   }

					/* decode rest of parameters 	*/
  pform = punit = ptype = (char *)0;
  argc = tbl_argc();
  for (i=0; i < 3; i++) {
	arg = i+3;
  	if (arg <= argc) {
  		parm = p3[i];
  		tbl_getarg(arg, PARLEN, parm);
                if (parm[0] == '?') continue;
  		else if (parm[strloc(parm,'*')]) {	/* It's datatype */
			if (!ptype)	ptype = parm, parm = (char *)0;
  		}
  		else if (*parm == '"')		/* It's Unit	*/
			punit = parm, parm = (char *)0;
  		else {				/* Format	*/
			if ((!ptype) && (!parm[1]))
				ptype = parm, parm = (char *)0;
			else if (!pform)pform = parm, parm = (char *)0;
  		}
  		if (parm) {
  			SCTPUT ("**** Invalid Argument");
  			return (ERR_INPINV);
  		}
  	}
  }

						/* Take Defaults	*/
  if (!punit)	punit = "Unitless";
  if (!ptype)	ptype = "R*4";

						/* Examine DataType	*/
  status = tbl_dectyp(ptype, &type, &noelem, dform);
  if (status) goto error;
 	 
  if (!pform)	pform = dform;

  if (strchr(pform,'.') == 0)                    /* If format contains no . */   
  {
     if (strchr(pform,'E')!=0 || strchr(pform,'e')!=0 || strchr(pform,'D')!= 0)
     {   
       /* formats like E12 or D24 would cause problems, therefore use default */
       SCTPUT("WARNING:format will be set to default value!\n");
       pform = dform;
     } 
  }  
                                      /*add here control for column format*/
  if (strcmp(pform,"F10.7") == 0)
  {
     SCTPUT("WARNING: Column created with format F10.7");
     SCTPUT("F10.7 overlaps with data type range of float");
  } 

			/* finally create the column. Note that 
			   the : in front of label and quotes around unit 
			   are removed in TCCINI	 	*/
  if (type == D_C_FORMAT) {
       ptype += 2;
       items = atoi(ptype); 
       status = TCCINI(tid, type, noelem * items , pform, punit, column, &ic);
       if (noelem != 1) TCAPUT(tid,ic, noelem);
       }
  else status = TCCINI(tid, type, noelem , pform, punit, column, &ic);
 if (status == ERR_NORMAL) CGN_DSCUPD(tid,tid," "); 
 error:
 TCTCLO(tid);
 return (status);
}       

int tbl_namecol()
/*++++++++++++++++++
.PURPOSE NAME/COLUMN table old_col_name [new_col_name] [unit] [format]
.RETURNS Status
------------------*/
{
	int	argc, arg;
	int  	tid, ic, jc, status;
	char	field[PARLEN];

                                                /* Which table ? 	*/
  tbl_getarg(1, PARLEN, table);
  tid = -1;
  if ((status = TCTOPN(table,F_IO_MODE,&tid)))	return(status);

						/* Which column ? 	*/
  tbl_getarg(2, PARLEN, column);
  status = TCCSER(tid, column, &ic);
  if (status)	goto error;
  if (ic <= 0) {
	status = ERR_TBLCOL; 
	SCTPUT("**** Can't rename this column");
	goto error;
   }

					/* decode rest of parameters 	*/
  argc = tbl_argc();
  for (arg = 3; (status == ERR_NORMAL) && (arg <= argc); arg++) {
	tbl_getarg(arg, PARLEN, field);
        if (field[0] == '?') continue;
  	else if (field[0] == ':')   {	/* Check Label Not Existing */
  		TCCSER(tid, field, &jc);
  		if (jc > 0) {
        		status = ERR_TBLCOL;
        		SCTPUT("**** Column already exists");
        		goto error;
   		}
		status = TCLPUT(tid,ic,field+1);
	}
  	else if (field[0] == '"') 	status = TCUPUT(tid,ic,field);
  	else 				status = TCFPUT(tid,ic,field);
  }

 if (status == ERR_NORMAL)  CGN_DSCUPD(tid,tid," ");
 error:
 TCTCLO(tid);

 return (status);
}       

int tbl_delcol()
/*++++++++++++++++++
.PURPOSE DELETE/COLUMN table old_col_name 
.RETURNS Status
------------------*/
{
	int  argc, arg, status, i;
	int tid, ic[DELCOLS], flag[DELCOLS], found, remaining_cols, ncol;
  
                                                /* Which table ? 	*/
  tbl_getarg(1, PARLEN, table);
  tid = -1;
  status = TCTOPN(table,F_IO_MODE,&tid);
  if (status)	return(status);

  argc = tbl_argc();
  ncol = 0;
  for (arg = 2; (status == ERR_NORMAL) && (arg <= argc); arg++) {
						/* Which column(s) ? 	*/
	tbl_getarg(arg, PARLEN, column);
	status = TCCSEL(tid, column, DELCOLS, &ic[ncol], flag, &found);	
	if (status != ERR_NORMAL) {
  	        status = ERR_TBLCOL; 
		SCTPUT("**** Column(s) not found");
		goto error;
	}
        ncol += found;
  }

  sortcol(ic,ncol);
  for (i = ncol-1; (status == ERR_NORMAL) && (i >= 0  ); i--)
     		status = TCCDEL(tid, ic[i], &remaining_cols);

 if (status == ERR_NORMAL)  CGN_DSCUPD(tid,tid," ");
 error:
 TCTCLO(tid);

 return (status);
}       

int tbl_setref()
/*++++++++++++++++++
.PURPOSE SET/REFCOLUMN table_name :col_name 
.RETURNS Status
------------------*/
{
  char 	table[PARLEN], column[PARLEN];
  int  	tid, ic;
  int	status;
                                                /* read parameters */
  tbl_getarg(1, PARLEN, table); 
  tbl_getarg(2, PARLEN, column); 

  tid = -1;
  status =  TCTOPN(table, F_IO_MODE , &tid);
  if (status) return(status);

  status = TCCSER(tid,column,&ic);
  if (status)	goto error;
  if (ic == -1) {
  	status = ERR_TBLCOL; 
	SCTPUT("Column not found");
	goto error;
  }

  status = TCKPUT(tid,ic);

 error:
 TCTCLO(tid);
 return (status);
}

void sortcol(v,n)
int v[];
int n;
{
  int gap, i, j, temp;
  for (gap = n/2; gap >  0; gap /=2)
    for (i = gap; i < n; i++)
     for (j=i-gap; j>=0 && v[j] > v[j+gap]; j-=gap) {
          temp = v[j];
          v[j] = v[j+gap];
          v[j+gap] = temp;
     }         
}
