/*===========================================================================
  Copyright (C) 1989-2012 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        tbread.c
.LANGUAGE    C
.AUTHOR      IPG-ESO Garching
.CATEGORY    table utilities
.COMMENTS       This module implements the following Midas commands:
 READ/TABLE} table column_selection line_selection format_file

.VERSION  1.0 	25-Mar-1989   Definition     J.D. Ponz
.VERSION  1.1 	09-Jun-1990   Include option Format file M.Peron
.VERSION  3.0 	05-Jul-1990   New version with column arrays   F.O.
.VERSION  3.1   04-Apr-1991   New version for PRINT with format file M.P
.VERSION  3.2   27-Jul-1992   doesn't take care of width of screen, 

 120130		last modif
------------------------------------------------------------*/

#include <tbldef.h>
#include <midas_def.h>
#include <osterm.h>		/* To know the width of Terminal */
#include <macrogen.h>
#include <proto_tbl.h>

#include <str.h>		/* String Handling Functions	 */
#include <stdio.h>
#include <stdlib.h>


#define PARLEN 	80

/* COLS, EDCOLS from 256 -> 3200		081016  */

#define COLS	3200		/* Max number of Columns */
#define EDCOLS	3200		/* Max number of Edited Columns */

#define RANGES	256		/* Max number of Ranges	 */
#define STRINGLEN 256
#define MAXCHAR 4096



static char action[2];

extern char *osmmget(), *osmmexp(), *osmsg();
extern int  tbl_decfmt(), tbl_getarg(), tbl_argc(), tbl_readf(), tbl_reado();




int tbl_read()
/*++++++++++++++++++
.PURPOSE READ/TABLE table [columns_selection] [rows_selection] [format-file]  
.RETURNS Status
------------------*/
{
  char table[PARLEN], msg[100];
  char *formfile;
  int  kuni;

  int  icol[COLS], fcol[COLS], lrange[RANGES], urange[RANGES], found;
  int 	status, tid, ncol, nr,log1[12],log2;
  int 	nctable, nrtable, nsc, nar, npar, nac;
  int   dummy, nch;
  int 	i, j, check_sel, header;
  

  i = 1; ncol = nr = 0; 
  header = 1;
  nch = 0;
  formfile = (char *)0;
						/* read parameters */
  npar = tbl_argc();
  status = tbl_getarg(1, PARLEN, table);

  tid = -1;				/* get table information */
  status = TCTOPN(table,F_I_MODE,&tid);
  if (status) return(status);
  status = TCIGET(tid,&nctable,&nrtable,&nsc,&nac,&nar);
  if (status) goto error;

  if (nctable > COLS)
  	{
  	nctable = COLS;
	}


  for (i=2; i<=npar; i++) 
  	{
  	tbl_getarg(i, PARLEN, msg);
        if (i==8 && msg[strloc(msg,' ')])
		{
		msg[strloc(msg,' ')] = '\0';
		SCTPUT ("***Warning*** Command Line truncated to 8 parameters");
		SCTPUT("Check Help  READ/TABLE for more info"); 
		}

 	switch (msg[0]) 
		{
	  case ':': case '#': 			/* it is a new column 	*/
   		if ((status = TCCSEL(tid, msg, COLS-ncol, 
   			&icol[ncol], &fcol[ncol], &found)))
			{
			goto error;
			}
   		ncol += found;
          	break;
	  case '@':				/* it is range definition */
   		if ((status = TCRSEL(tid, msg, RANGES-nr,  
   			&lrange[nr], &urange[nr], &found)))
			{
			goto error;
			}
   		if ( (nr == 1) && (found == 1) && (lrange[0] == urange[0]) &&
   		     (lrange[1] == urange[1]))	/* Backwards compatibility */
		     	{
   		     	urange[0] = lrange[1];
			}
   		else 
			nr += found;
                for (j=0; j<nr; j++)  
                	{
                	if (lrange[j]<1 || lrange[j]>nar || 
                      		urange[j]<1 || urange[j]>nar) 
                      	   { 
                      	   status = ERR_TBLROW;
       			   sprintf (msg, "Row selection outside range[1..%d]",nar);
              		   SCTPUT(msg);
                      	   break;
                      	   }
                 	}
         	break;
          case '?': break;
          case 'N': case 'n':
                if ( (!msg[1]))
			{
                     	header = 0;
                     	break;
                 	}
	  default: 				/* Assume a Format File	  */
                if (isdigit(msg[0])) 
			{
			nch = atol(msg);
			} 
		else if (formfile)	 
			{
			sprintf (msg, "****Format file is: %s", formfile);
     			SCTPUT(msg); 
			status = ERR_FILBAD;
			}
         	else  
			{
                  	formfile = strsave(msg);
                        
			if (osfsize(osfsupply(formfile,".fmt")) <0 ) 
			     {
                              sprintf(msg,"  Error opening Format file: %s",
                           	formfile);
                              SCTPUT(msg);
                              TCTCLO(tid);
                              SCSEPI(); 
                             }
                      	}
         	break;
		}
  	} 
	
  if (status != ERR_NORMAL)	goto error;

  if (ncol == 0) 
  	{ 				/* default columns to all */
	ncol = nctable;
	for (i=0; i<ncol; i++) 
		{
		icol[i] = i+1;
		}
  	}

  if (nr == 0)
  	{  				/* default range */
	nr = 1;
	lrange[0] = 1;
	urange[0] = nrtable;
	check_sel = 1;
	}
  else	
  	{
	check_sel = 0;
	}

  if (header) 
  	{
  	sprintf(msg,"  Table : %s \n",table);
  	SCTPUT(msg);
  	}    
					/* Get Terminal Characteristics */
  

  SCKRDC("ACTION",1,1,2,&dummy,action,&kuni,&dummy);
  SCKRDI("LOG",1,12,&dummy,log1,&kuni,&dummy);
  if ((action[0] == 'P') || (action[0] == 'p'))  
  	{
  	log2 = 0;
  	SCKWRI("LOG",&log2,9,1,&kuni);
	log2 = 1;
	SCKWRI("LOG",&log2,4,1,&kuni);
	}
  else 
  	{
	nch = log1[9];
	}
  if (formfile )
  	{
        tbl_readf(tid,formfile,nr,lrange,urange,header,check_sel,nch);	
        }
  else 
  	{
     	if (nch == 0)
		{ 
		nch = 80;
		}
 	SCKWRI("LOG",&nch,10,1,&kuni);
	tbl_reado(tid,nr,icol,ncol,lrange,urange,header,check_sel,nch);	
	}
  SCKWRI("LOG",&log1[3],4,1,&kuni); 
  SCKWRI("LOG",&log1[8],9,1,&kuni); 
  SCKWRI("LOG",&log1[9],10,1,&kuni); 

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


/* If format file is given tbl_read() calls: 
   tbl_readf(tid,formfile,nr,lrange,urange,header,check_sel,width)
                                           */
int tbl_readf(tid,formfile,nr,lrange,urange,header,check_sel,width)	
int tid,nr,check_sel,header;
int lrange[RANGES],urange[RANGES],width;
char *formfile;

{
char form[TBL_FORLEN+1], unit[TBL_UNILEN+1], label[1+TBL_LABLEN];
char buf[MAXCHAR],value[STRINGLEN];
char title[STRINGLEN], line[STRINGLEN];

int kuni;
int found,dtype,nulls[EDCOLS],icol[COLS],sel;
int fid,status,i1,i2,i,j,k,l,upos[COLS],lpos[COLS];
int ncol,m;

status = 0;

  for (i=0; i<COLS; i++)
  	{
        upos[i] = 0;
        lpos[i] = 0;
  	}
  for (i=0; i<=STRINGLEN; i++) 
  	{
	value[i] = '\0';
	}
  fid =  osaopen(osfsupply(formfile, ".fmt"), F_I_MODE);
  	
  if (fid < 0)	
	{
	SCTPUT (osmsg());
	status = ERR_FILBAD;
	goto error;
  	}
  i = 0;
  while (status == ERR_NORMAL) 
	{
        if (osaread (fid, buf, sizeof(buf)) < 0)
		{
		break;
		}
        tbl_decfmt(buf, &i1,&i2, &dtype, &found, form, unit, label);
        if (dtype) 
		{
                lpos[i] = i1; upos[i] = i2; 
		status = TCCSER (tid, label, &icol[i]);
		TCFPUT (tid, icol[i], form);
                i++;
             	}
        }
   ncol = i;
   width = MAX(80,upos[ncol-1]+1);
   SCKWRI("LOG",&width,10,1,&kuni); 

   if (header) 
	{
	for (i=0 ; i<ncol; i++) 
		{
             	TCLGET(tid,icol[i],label);
             	for (k=0; k<lpos[0]-1;k++) 
			{
			title[k]=' ';
			}
           	m = MIN (lpos[i]+strlen(label)-1,upos[i]);
             	j=0;
             	for (k=lpos[i]-1; k<m; k++ ) 	
			{
			title[k] = label[j++];
			}
             	for (k=m; k<=lpos[i+1]-1; k++) 
			{
			title[k] =  ' '; 
			}
        	}
       	title[upos[ncol-1]] = '\0';
        SCTPUT(title);

        for (i=0 ; i<ncol; i++) 
		{
             	for (k=0; k<lpos[0]-1;k++) 
			{
			title[k]=' ';
			}
             	for (k=lpos[i]-1; k<upos[i]; k++ ) 
			{
			title[k] = '-';
			}
             	for (k=m; k<=lpos[i+1]-1; k++) 
			{
			title[k] =  ' '; 
			}
        	}
        title[upos[ncol-1]] = '\0';
        SCTPUT(title);
        }

   for (j = 0; j < nr; j++) 
	{
	for (i=lrange[j]; i<=urange[j]; i++) 
		{
		if (check_sel)	
			{
			TCSGET(tid,i,&sel);
			}
		else	
			{
			sel = 1;
			}
                if (sel) 
			{
                        for (l=0; l < lpos[0]-1;l++) line[l]= ' ' ;
                        for (k=0; k < ncol; k++) 
				{
                             	TCRRDC(tid,i,1,&icol[k],value,nulls);
                             	m = MIN (lpos[k]+strlen(value)-2,upos[k]);
                             	for (l=lpos[k]-1;l<m   ;l++) 
                              		{
					line[l] = value[l-lpos[k]+2];
                             		}
				for (l=m;l<=lpos[k+1]-1;l++)  
					{
					line[l] = ' ';
                               		}
				}		
			for (l=upos[ncol-1];l<width;l++) 
				{
				line[l] = ' '; 
				} 
                        line[width] = '\0';
                	SCTPUT(line);
                	oscfill(line,width,' ');
                        }
         	}
         }

   if (header) 
	{
	SCTPUT(title);
	}
   if (status)
	{
	SCTPUT (buf);
	}
   osaclose(fid);
  	
   error:
   osmmfree(formfile);
   return (status);
   }


/* If no format file is given tbl_read() calls: 
   tbl_reado(tid,nr,icol,ncol,lrange,urange,header,check_sel,width)
                                           				*/
int tbl_reado(tid,nr,icol,ncol,lrange,urange,header,check_sel,width)
int icol[COLS],lrange[RANGES],urange[RANGES],width;
int tid,ncol,nr,check_sel,header;
{
char form[TBL_FORLEN+1], label[1+TBL_LABLEN];
char keyname[16];

int outcol[EDCOLS],colen[EDCOLS],nulls[EDCOLS],isarr[EDCOLS];
int dtype,sel,kuni;
int i,j,k,ic,nc,ibase,len,status;
int kk;


/* check if here from COPY/TBROW command */

if (action[1] == 'c')
   {
   int  kel, kbe;
   char  kty[8];

   SCKGETC("Q1",1,15,&i,keyname);	/* name of destination key */
   SCKFND(keyname,kty,&kel,&kbe);	/* check its type and size */
   if (kty[0] != 'C')
      SCETER(33,"Error: Destination keyword must be of type char!");
   width = kel*kbe;
   }

status = 0;
/* old version led to overflow of string 'title' ...	KB 100922
char *line, *title;
int  last_alloc;
title = line =  (char *)0;
line  = osmmget (1 + width);
title = osmmget (1 + width);

last_alloc = 1 + width;
*/

ic  = 0;
isarr[0] = 0;			/* sequence is no array column */

while (ic < ncol) 
   {
   char title[2*STRINGLEN], *line;

   line = title + STRINGLEN;
   outcol[0] = 0;
   TCFGET(tid, 0, form, colen, &dtype);
   ibase     = 1 + colen[0];

   for (nc=1; (nc<EDCOLS) && (ic<ncol); nc++, ic++) 
      {
      ++ibase;
      TCFGET(tid, icol[ic], form, &len, &dtype);
      TCBGET(tid, icol[ic], &dtype, &i, &k);
/*
printf("column #%d > form = %s, len = %d, type = %d\n",icol[ic],form,len,dtype);
*/

      if ((dtype != D_C_FORMAT) && (i > 1)) 
         isarr[nc] = 1;				/* array column */
      else
         isarr[nc] = 0;
      if ((ibase + len) >= width) break;

      outcol[nc] = icol[ic];
      colen[nc]  = len;
      ibase += len;
      }

   if (nc < 2) 
      {
      outcol[nc] = icol[ic];
      colen[nc]  = len;
      nc++, ic++;
      ibase += len;
      /* only expand memory if needed - only needed in old version
      if (ibase > (last_alloc-2))
         {
         last_alloc = ibase + 2;
	 line = osmmexp(line, ibase+2);
	 title = osmmexp(title, ibase+2); 
         }
      */
      }

   k = 0;		/* Edit Titles	*/
   if (header) 
      { 
      for (i=0; i < nc; i++) 
         {
         TCLGET(tid, outcol[i], label);      /*Reads column label*/
	 title[k++] = ' ';
         if (isarr[i] == 1)
            kk = 20;			/* array column */
         else
            kk = colen[i];
							
	 for (j=0; label[j] && (j < kk); j++)   
	    {
	    title[k++] = label[j];
	    }
         if (isarr[i] == 1)
            (void) strcpy(title+k," (array col)");
         else
            {
	    for (;   j < kk; j++)	
	       {    
	       title[k++] = ' ';
	       }
            title[k] = '\0';           
	    }
         if (k > STRINGLEN) 		/* we hope overflowing chars. */
            {				/* end up in following string line... */
            break;
            }
	 }
      SCTPUT(title);         /* display title on terminal screen */
	
      k = 0;	
      for (i=0; i < nc; i++) 
         {
         title[k++] = ' ';
         if (isarr[i] == 1)
            kk = 20;			/* array column */
         else
            kk = colen[i];
         for (j = kk; --j >= 0; )	
            {
            title[k++] = '-';
            }
         }
      if (k > STRINGLEN) 		/* we hope overflowing chars. */
         {				/* end up in following string line... */
         k = STRINGLEN - 1;
         }
      title[k] = '\0';           
      SCTPUT(title);         /* displays separating dashed line on screen */
      }
		
   /* list table values */

   for (j=0; j<nr; j++)
      {
      for (i=lrange[j]; i<=urange[j]; i++) 
         {
         if (check_sel)	
            {
            TCSGET(tid,i,&sel);     /*reads row selection flag*/
            }
	 else		
	    {
	    sel = 1;
	    }

         if (sel) 
            {			/*reads table row as character string */
	    oscfill(line,width,' ');
            TCRRDC(tid,i, nc, outcol, line, nulls); 
	    SCTPUT(line); 
            if (action[1] == 'c') 
               {
               len = (int)strlen(line);
               if (len > width) len = width;
               SCKWRC(keyname,1,line,1,len,&kuni);
               SCKWRI("OUTPUTI",&len,1,1,&kuni);
	       }
	    }
         }
      }

   if (header) 
      {
      SCTPUT(title);               /*plots again dashed lines*/
      }         
   }

/* osmmfree(title); 
   osmmfree(line); */

return(status);
}       
