/*===========================================================================
  Copyright (C) 1993-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 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding 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:
\begin{TeX}
\begin{enumerate}
\item {\tt GROUP/ROW} table incol outcol flag
\end{enumerate}
\end{TeX}

.VERSION  1.0   15-Mar-1993   Definition     M. Peron

 090831		last modif
----------------------------------------------------------*/
#include <atype.h>
#include <tbldef.h>
#include <tblsys.h>
#include <tblerr.h>
#include <midas_def.h>
#include <macrogen.h>
#include <proto_tbl.h>


#define issign(c)               ((c == '+') || (c == '-'))
#define PARLEN 80


extern int  tbl_hist();

void readtreei();
void readtreec();


 
struct treec {
     char name[256];    
     int *seqnum;
     int noelem;
     struct treec *left;
     struct treec *right;
};
struct treec *headc;
struct treei {
     int ival;    
     int *seqnum;
     int noelem;
     struct treei *left;
     struct treei *right;
};
struct treei *headi;
int tid,gnum,icol,ocol,ncol,incol[256];
int len;



int main()
{
int status,nrow;
int null, dummy;
int sel,dtype,ival;
int i,j;
char icolumn[PARLEN],ocolumn[PARLEN];
char form[1+TBL_FORLEN];
char intab[60], action[2];
char cval[256];
double dval;
struct treec *s1dtreec();
struct treei *s1dtreei();


SCSPRO("tbgroup");
SCKGETC("IN_A",1L,60L,&dummy,intab);
SCKGETC("INPUTC",1L,80L,&dummy,icolumn);
SCKGETC("OUTPUTC",1L,80L,&dummy,ocolumn);
SCKGETC("ACTION",1L,1L,&dummy,action);
status = TCTOPN(intab,F_IO_MODE,&tid);
if (status != ERR_NORMAL) {
      SCTPUT("Error opening input data table");
      SCSEPI();
}
TCIGET(tid,&ncol,&nrow,&dummy,&dummy,&dummy);
TCCSER(tid,icolumn,&icol);
if (icol <= 0) {
       SCTPUT("Input column not found");
       SCSEPI();  
     }
TCFGET(tid,icol,form,&len,&dtype);
TCCSER(tid,ocolumn,&ocol);
if (ocol <= 0) TCCINI(tid,D_I4_FORMAT,1,"I3"," ",ocolumn,&ocol);
gnum = 0;
if (dtype == D_C_FORMAT) {
 for (i=1; i<=nrow; i++) {
    TCSGET(tid,i,&sel);
    if (!sel) continue;
    TCERDC(tid,i,icol,cval,&null);
    if (null) continue;
    if (!headc) headc = s1dtreec(headc,headc,cval,i,nrow);
    else s1dtreec(headc,headc,cval,i,nrow,gnum);
    }
incol[0] = icol;
j=1;
 for (i=1; i<=ncol; i++) if (i != icol) {
        incol[j] = i;
        j++;
        } 
if (toupper(*action) == 'R')  readtreec(headc);
 }
else {
 for (i=1; i<=nrow; i++) {
    TCSGET(tid,i,&sel);
    if (!sel) continue;
    TCERDD(tid,i,icol,&dval,&null);
    ival = (int ) dval;
    if (null) continue;
    if (!headi) headi = s1dtreei(headi,headi,ival,i,nrow);
    else s1dtreei(headi,headi,ival,i,nrow,gnum);
    }
incol[0] = icol;
j=1;
 for (i=1; i<=ncol; i++) if (i != icol) {
        incol[j] = i;
        j++;
        } 

if (toupper(*action) == 'R') readtreei(headi);
 }

status = tbl_hist(tid);
SCSEPI();
return 0;
}

struct treec *s1dtreec(root,r,cval,row,nrow)
struct treec *root;
struct treec *r;
char cval[256];
int row,nrow;
{
if (!r) {
        r = (struct treec *)osmmget(sizeof(struct treec));
        r->left = (struct treec *)0;
        r->right = (struct treec *)0;
        strcpy(r->name,cval);
        r->seqnum = (int *) osmmget(sizeof(int)*nrow);
        gnum++;
        r->noelem = 1;
        r->seqnum[0] = gnum;
        r->seqnum[r->noelem] = row;
        if (!root) {
             TCEWRI(tid,row,ocol,r->seqnum);
             return r;
             }
        if (strcmp(cval,root->name) < 0) {
                    root->left = r;
                    TCEWRI(tid,row,ocol,r->seqnum);
                    }
        else if (strcmp(cval,root->name) > 0) {
                    root->right = r;
                    TCEWRI(tid,row,ocol,r->seqnum);
                    }
        else {
             root->noelem++ ;
             root->seqnum[root->noelem] = row;
             TCEWRI(tid,row,ocol,r->seqnum);
        }
        return r;
}
if  (strcmp(cval,r->name) < 0) s1dtreec(r,r->left,cval,row,nrow);
else if (strcmp(cval,r->name) > 0) s1dtreec(r,r->right,cval,row,nrow);
else {
     r->noelem++;
     r->seqnum[r->noelem] = row;
     TCEWRI(tid,row,ocol,r->seqnum);
     }
return r;
}        

void readtreec(head)
struct treec *head;
{
int i;
char line[256];
int nulls[256];
if (head->left) readtreec(head->left);
TCRRDC(tid,head->seqnum[1],ncol,incol,line,nulls);
SCTPUT(line);
oscfill(line,len+1,' ');
for (i=2; i<= head->noelem;i++){
        TCRRDC(tid,head->seqnum[i],ncol-1,&incol[1],line+len+1,nulls);
        SCTPUT(line);
        }
if (head->right) readtreec(head->right);
}



struct treei *s1dtreei(root,r,ival,row,nrow)
struct treei *root;
struct treei *r;
int ival;
int row,nrow;
{
if (!r) {
        r = (struct treei *)osmmget(sizeof(struct treei));
        r->left = (struct treei *)0;
        r->right = (struct treei *)0;
        r->ival = ival;
        r->seqnum = (int *) osmmget(sizeof(int)*nrow);
        gnum++;
        r->noelem = 1;
        r->seqnum[0] = gnum;
        r->seqnum[r->noelem] = row;
        if (!root) {
             TCEWRI(tid,row,ocol,r->seqnum);
             return r;
             }
        if (ival < root->ival ) {
                    root->left = r;
                    TCEWRI(tid,row,ocol,r->seqnum);
                    }
        else if (ival > root->ival) {
                    root->right = r;
                    TCEWRI(tid,row,ocol,r->seqnum);
                    }
        else {
             root->noelem++ ;
             root->seqnum[root->noelem] = row;
             TCEWRI(tid,row,ocol,r->seqnum);
        }
        return r;
}
if  (ival < r->ival) s1dtreei(r,r->left,ival,row,nrow);
else if (ival > r->ival) s1dtreei(r,r->right,ival,row,nrow);
else {
     r->noelem++;
     r->seqnum[r->noelem] = row;
     TCEWRI(tid,row,ocol,r->seqnum);
     }
return r;
}        



void readtreei(head)
struct treei *head;
{
int i;
char line[256];
int nulls[256];
if (head->left) readtreei(head->left);
TCRRDC(tid,head->seqnum[1],ncol,incol,line,nulls);
SCTPUT(line);
oscfill(line,len+1,' ');
for (i=2; i<= head->noelem;i++){
        TCRRDC(tid,head->seqnum[i],ncol-1,&incol[1],line+len+1,nulls);
        SCTPUT(line);
        }
if (head->right) readtreei(head->right);
}
