/*===========================================================================
  Copyright (C) 1995-2005 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
===========================================================================*/

/* @(#)edtcommand.c	2.1.1.1 (ESO-IPG) 9/27/91 17:32:12 */
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TYPE        Module
.NAME        edtcommand.c
.LANGUAGE    C
.AUTHOR      J.D.Ponz  IPG-ESO Garching
.CATEGORY    table editor
.PURPOSE
             Command input on the dialogue window.
.RETURNS     error status.
.VERSION     1.0 25-Mar-1988   Implementation     JDP
.VERSION     1.1 16-Feb-1990   Be sure that cursoir correctly positionned. FO
				Cosmetic modifications.
.VERSION     1.2 30-Oct-1990   Default is Current Column
.VERSION     1.3 27-JUL-1992   correct bug, suggested by Vilspa People 
 051012		last modif

- ------------------------------------------------------------*/

#define DEBUG		0

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

#include <tw.h>				/* Window system	*/
#include <ok.h>				/* Just OK / NOK definitions */
#include <macrogen.h>			/* General purpose macros, e.g. MAX */

#include <tbldef.h>	
#include <tfmdef.h>	
#include <tbledt.h>	
#include <tblfmt.h>	
#include <str.h>			/* Basic String Manipulation */

#include <stdio.h>


static char vertical = RuleChar(_VERTICAL_);
static char test_buffer[80];
static char buffer[100] = "";
static char *buf_pos = buffer;

int   null;
char string [EDT_MAXCHA];

static char *GetWord(prompt)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Get next word from command. 
.RETURNS Pointer to next word. When asked for terminate, returns NULL
- --------------------------------------------------------------*/
	char *prompt;	/* IN: Prompt to issue if no text */
{
	char *p;

    if_not(*buf_pos)		/* There is nothing in the buffer. Prompt
				 	and get answer */
    {	buf_pos = buffer;	
    	RaiseWindow(dialogue_window);
    	ActiveWindow(dialogue_window);
	if (prompt)
        {   NewLine(dialogue_window);	Put(dialogue_window, prompt); }
     	if (Gets(dialogue_window, buffer, sizeof(buffer)) == _EOF_) 
		return((char *)0);
    }
    ClearError();

	/* Now buf_pos points to the first word.
         	Prepare buf_pos for the next call.
	 */
    
    buf_pos += strspan(buf_pos, _SPACE_);	/* Gobble leading spaces */
    p = buf_pos ;				/* To be returned */
    buf_pos += strscan(buf_pos, _SPACE_);	/* End of word	*/
    if (isspace(*buf_pos))			/* There is a continuation */
	*(buf_pos++) = '\0',
       	buf_pos += strspan(buf_pos, _SPACE_);	/* Gobble trailing spaces */

#if DEBUG
    sprintf(test_buffer, ".. <%s> == Next ,<%s>",p,buf_pos);
    ShowError(test_buffer);
#endif
    return(p);
}

/*==========================================================================*/
int edt_quit()
{
  edt_action = TERMINATE;
  edt_status = QUIT;

  return(NULLACTION);
}

int edt_exit()
{
  edt_action = TERMINATE;
  edt_status = EXIT;

  return(NULLACTION);
}

int edt_nextline()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE 
         Move cursor to next line.
.RETURNS
         Status
- --------------------------------------------------------------*/

{	int iend, status, k, i, ii, j, oldpos,dummy,len,mylen;
        char form[10],dums[EDT_MAXCHA];

  oldpos = cursor_pos[0];
  
  GetCursor(data_subwindow,cursor_pos);
                                        /* check boundaries */
  if (edt_row[cursor_pos[0]] >= edt_narow || 
      edt_row[cursor_pos[0]] <= 0 )
  {   status = ShowError("Bottom of the table");
      cursor_pos[0] = oldpos;
      CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);
      return(NULLACTION);
  }
  cursor_pos[0] = cursor_pos[0] + 1;
  if (cursor_pos[0] >= data_lines) {
     cursor_pos[0] = data_lines;
     iend = edt_row[edt_nr-1];
     if (iend >= edt_narow) 
        status = ShowError("Bottom of the table");
     else  {

            for (i=1; i<edt_nr; i++) 
            edt_row[i-1] = edt_row[i];
            ScrollUp(editor_window,1);
            iend    = iend + 1;
            edt_row[edt_nr-1] = iend;
            ed_pic(string,"00000009",iend);
            CursorTo(sequence_subwindow,data_lines,0);
            Put(sequence_subwindow,string);
            SetAttr(sequence_subwindow,_GRAPHICS_);
            Write(sequence_subwindow, &vertical, 1);
            SetAttr(sequence_subwindow,_NORMAL_);
            for (ii=0; ii<EDT_MAXCHA; ii++) string[ii] = ' ';
            mylen = 1;
            for (j=0; j < edt_nc; j++) {
                TCFGET(edt_tid,edt_column[j],form,&len,&dummy);
                TCERDC(edt_tid,iend,edt_column[j],dums,&null);
                if (!null)   strncpy(string+mylen,dums,strlen(dums));
                mylen += len+1;
                }
            string[mylen] = '\0';
            CursorTo(data_subwindow, cursor_pos[0],0);
            Puts(data_subwindow, string+1);
            SetAttr(data_subwindow,_GRAPHICS_);
            for (i=0; i<edt_nc; i++)
                {k = FMT[i].LAST;
                 CursorTo(data_subwindow,data_lines,k);
                 Write(data_subwindow, &vertical, 1);
                }
            SetAttr(data_subwindow,_NORMAL_);
            }
     }                              
 CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);
 
return (NULLACTION);     
}

int edt_prevline()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE 
         Move cursor to previous line.
.RETURNS
         Status
- --------------------------------------------------------------*/
{ int istart, status, i, ii, k, l, len, mylen, dummy ;
  char form[10], dums[EDT_MAXCHA];

GetCursor(data_subwindow,cursor_pos);
cursor_pos[0] = cursor_pos[0] - 1;
if (cursor_pos[0] < 0) {
    cursor_pos[0] = 0;
    istart = edt_row[0];
    if (istart <= 1) 
        status = ShowError("Top of the table");
    else  {
/*        for (i=edt_nr-1; i<=1; i--) edt_row[i] = edt_row[i-1]; MP 100491 */
        for (i=edt_nr-1; i>=1; i--) edt_row[i] = edt_row[i-1];
        ScrollDown(editor_window,1);
        istart  = istart - 1;
        edt_row[0] = istart;
        ed_pic(string,"00000009",edt_row[0]);
        CursorTo(sequence_subwindow,0,0);
        Put(sequence_subwindow,string);
        SetAttr(sequence_subwindow,_GRAPHICS_);
        Write(sequence_subwindow, &vertical, 1);
        SetAttr(sequence_subwindow,_NORMAL_);
        for (ii=0; ii<EDT_MAXCHA; ii++) string[ii] = ' ';
        mylen = 1;
        for (l=0; l<edt_nc;l++) {
             TCFGET(edt_tid,edt_column[l],form,&len,&dummy);
             TCERDC(edt_tid,istart,edt_column[l],dums,&null);
             if (!null)   strncpy(string+mylen,dums,strlen(dums));
             mylen += len+1;
        }
        string[mylen] = '\0';
        CursorTo(data_subwindow, 0,0);
        Puts(data_subwindow, string+1);
        SetAttr(data_subwindow,_GRAPHICS_);
        for (i=0; i<edt_nc; i++)
            {k = FMT[i].LAST;
             CursorTo(data_subwindow,0,k);
             Write(data_subwindow, &vertical, 1);
            }
        SetAttr(data_subwindow,_NORMAL_);
       }
   }                              
CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);

return(NULLACTION);
}

int edt_nextcol()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Move cursor to next column.
.RETURNS Status
- --------------------------------------------------------------*/
{	int status;

    GetCursor(data_subwindow,cursor_pos);
    thecol = compute_col();
    thecol = thecol + 1;
    if (thecol >= edt_nc) {
    	thecol = edt_nc-1;
    	if (edt_column[thecol] >= edt_ncol ) 
        status = ShowError("Limit of the table");
    	else {
            edt_format(NEXTCOL);
            edt_page(edt_tid);
            thecol = edt_nc-1;
	}
    } 
    cursor_pos[1] = FMT[thecol].FIRST;
    CursorTo(data_subwindow, cursor_pos[0], cursor_pos[1]);

    return (NULLACTION);
}

int edt_shstat()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Show editor status
.RETURNS Status
- --------------------------------------------------------------*/
{ char *str;

  thecol = compute_col();

  GetCursor(data_subwindow,cursor_pos);
  if (edt_advance == TRUE) str = "ADVANCE";
  else                     str = "BACKUP";

        sprintf(test_buffer,
                "s (%d, %d), w (%d, %d), p (%d, %d), col: %d, %s",
                 data_lines,data_columns,edt_nr,edt_nc,
                 cursor_pos[0],cursor_pos[1],thecol, str);
	ShowError(test_buffer);
    	return (NULLACTION);
}

static int resetwindow() 
{
    if (edt_status != COMMAND) RemoveWindow(dialogue_window);
}

static int setwindow(prompt) 
	char *prompt;
{
    if (edt_status != COMMAND) ClearWindow(dialogue_window),
    	Put(dialogue_window, prompt );
    RaiseWindow(dialogue_window);
}

static int edt_getcol(ncols, acols, flags)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE  Get column number interactivelly, default is current column.
.RETURNS  How many columns where asked  / 0 for error
- ------------------------------------------------------------*/
	int   ncols;	/* IN: Maximal number of columns */
	int *acols;	/* OUT: Column values		 */
	int *flags;	/* OUT: Column flags (+/-1)	 */
{
   int  found, status;
   char *str, *p;

    str = GetWord(" Enter column :");
    if(!*str)	return(0);

    for (p = str; *p ==' '; p++) ;

    if (*p) {
	status = TCCSEL(edt_tid, p, ncols, acols, flags, &found);
	if (status)	found = 0, ShowError(TBL_eget());
    }
    else {	/* Current Column */
	found = 1;
	*acols = FMT[thecol].colno;
	*flags = 0;
    }

    return (found);
}

int edt_sort()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Sort Table  &&&&&& TO BE IMPLEMENTED *********
.RETURNS Status
- --------------------------------------------------------------*/
{       int column[6], fl[6];
 	char *str;
	int  nc;

    setwindow(" Sort table.");

    if (nc = edt_getcol(ITEMS(column), column, fl)) {
    	if (fl[0] == 0)  {
       		str = GetWord("Ascending/Descending ?");
          	fl[0] = (toupper(*str) == 'D' ? -1 : 1);
	}
	TCCSRT(edt_tid, nc, column, fl);
	edt_page(edt_tid);
    }
    resetwindow();
    return (NULLACTION);
}

int edt_prevcol()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Move cursor to previous column.
.RETURNS Status
- --------------------------------------------------------------*/
{int status;

GetCursor(data_subwindow,cursor_pos);
thecol = compute_col();
thecol = thecol - 1;
if (thecol < 0) {
    thecol = 0;
    if (edt_column[thecol] <= 1 ) 
        status = ShowError("Limit of the table");
    else {
        edt_format(PREVCOL);
        edt_page(edt_tid);
       }
   }
cursor_pos[1] = FMT[thecol].FIRST;
CursorTo(data_subwindow, cursor_pos[0], cursor_pos[1]);
return (NULLACTION);
}
int edt_tabular()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Move cursor to next field.
.RETURNS Status
- --------------------------------------------------------------*/
{int statusl;

GetCursor(data_subwindow,cursor_pos);
thecol = compute_col();

if (edt_advance == TRUE) thecol = thecol + 1;
else                     thecol = thecol - 1;

if (thecol >= 0 && thecol < edt_nc) 
   CursorTo(data_subwindow,cursor_pos[0],FMT[thecol].FIRST);
if (thecol < 0)     {edt_prevline(); 	edt_lastcol();}
if (thecol>=edt_nc) {edt_nextline(); 	edt_homecol();}

return (NULLACTION);
}

int edt_homecol()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Move cursor to home column.
.RETURNS Status
- --------------------------------------------------------------*/

{

GetCursor(data_subwindow,cursor_pos);
CursorTo(data_subwindow,cursor_pos[0],FMT[0].FIRST);

return (NULLACTION);

}

int edt_lastcol()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Move cursor to last page columns.
.RETURNS Status
- --------------------------------------------------------------*/
{

GetCursor(data_subwindow,cursor_pos);
CursorTo(data_subwindow,cursor_pos[0],FMT[edt_nc-1].FIRST);

return (NULLACTION);
}

int edt_newpage()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Display new page.
.RETURNS Status
- --------------------------------------------------------------*/

{	int iend, istart, status, i, imax;

GetCursor(data_subwindow,cursor_pos);

/* iend   = edt_row[edt_nr]; */
iend   = edt_row[edt_nr-1];     /* Midas BUG corrected (IY) */

istart = edt_row[0];
if (edt_advance == TRUE) 
   {if (iend >= edt_narow)  {status = ShowError("Bottom of the table"); 
                             return (NULLACTION);}
    else                     istart = MIN(istart+edt_nr,edt_narow-edt_nr+1);
   }
else
   {if (istart <= 1)        {status = ShowError("Top of the table"); 
                             return (NULLACTION);}
    else                     istart = MAX(istart-edt_nr, 1);
   }
for (i=0; i < edt_nr; i++) edt_row[i] = imax = i+istart;
status = edt_page(edt_tid);
/* CursorHome(data_subwindow); */	/* Be sure cursor within table */
if (cursor_pos[0] > imax)	cursor_pos[0] = imax;
CursorTo(data_subwindow, cursor_pos[0], cursor_pos[1]);

return (NULLACTION);
}

int edt_toptbl()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Display top of the table.
.RETURNS Status
- --------------------------------------------------------------*/
{   int istart, i, status;

    GetCursor(data_subwindow,cursor_pos);
    istart = edt_row[0];
    if (istart <= 1)  status = ShowError("Top of the table");
    else
   { 	istart = 1;
	for (i=0; i < data_lines; i++) edt_row[i] = i+istart;
	cursor_pos[0] = 0;			/* FO: New pos on data_subwindow */
	CursorTo(data_subwindow, cursor_pos[0], cursor_pos[1]);
	status = edt_page(edt_tid);
   }

return (NULLACTION);
}

int edt_bottomtbl()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Display bottom of the table.
.RETURNS Status
- --------------------------------------------------------------*/
{  	int iend, istart, status, i, imax;

    GetCursor(data_subwindow,cursor_pos);
/*    iend = edt_row[edt_nr]; */
    iend = edt_row[edt_nr-1];   /* Midas BUG corrected (IY) */

    if (iend >= edt_narow)  status = ShowError("Bottom of the table");
    else {
	iend   = edt_narow;               /* mod. to alloc rows */ 
	istart = MAX(iend-data_lines+1, 1);
	for (i=0; i < data_lines; i++) edt_row[i] = imax = i+istart;
	status = edt_page(edt_tid);
					/* Be sure cursor within table */
	if (cursor_pos[0] > imax)	cursor_pos[0] = imax;
	CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);
    }
return (NULLACTION);
}

int edt_rightpage()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Display right page.
.RETURNS Status
- --------------------------------------------------------------*/
{	int status;

    GetCursor(data_subwindow,cursor_pos);
    if (edt_column[edt_nc-1] >= edt_ncol) 
	status = ShowError("The rightmost column is already displayed..."); 
    else {
	status = edt_format(RIGHTPAGE);
	status = edt_page(edt_tid);
	cursor_pos[1] = 0;		/* We're now at left (of rightpage!) */
	CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);
    }
    return (NULLACTION);
}

int edt_leftpage()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Displays left page.
.RETURNS Status
- --------------------------------------------------------------*/
{	int status;

    GetCursor(data_subwindow, cursor_pos);
    if (edt_column[0] <= 1) 
	status = ShowError("The leftmost column is already displayed..."); 
    else {
	status = edt_format(LEFTPAGE);
	status = edt_page(edt_tid);
	cursor_pos[1] = 0;	/* We're now at left (of leftpage!) */
	CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);
   }
    return (NULLACTION);
}

int edt_resetpage()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Display first page.
.RETURNS Status
- --------------------------------------------------------------*/
{	int status;

    GetCursor(data_subwindow,cursor_pos);
    if (edt_column[0] <= 1) 
    	status = ShowError("Limit of the table");
    else {
	status = edt_format(FIRSTPAGE);
	status = edt_page(edt_tid);
	cursor_pos[1] = 0;		/* We're now at left (of leftpage!) */
	CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);
    }
    return (NULLACTION);
}

int edt_newsection()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Displays new section.
.RETURNS Status
- --------------------------------------------------------------*/
{int istart, iend, status, i, imax;

GetCursor(data_subwindow,cursor_pos);
istart = edt_row[0];
/* iend   = edt_row[edt_nr]; */
iend   = edt_row[edt_nr-1];     /* Midas BUG corrected (IY) */

if (edt_advance == TRUE) 
   {if (iend >= edt_narow) {status = ShowError("Bottom of the table"); 
                            return (NULLACTION);}
/*    istart = MIN(istart+edt_nr/2,edt_narow-edt_nr+1); */
    istart = MAX(istart - edt_nr/2, 1); /* BUG corrected. pMidas MIN!! (IY) */
   }
else                   
   {if (istart <= 1)       {status = ShowError("Top of the table"); 
                            return (NULLACTION);}
    istart = MIN(istart - edt_nr/2, 1);
   }
for (i=0; i < edt_nr; i++) edt_row[i] = imax = i+istart;
					/* Be sure cursor within table */
   if (cursor_pos[0] > imax)	cursor_pos[0] = imax;
status = edt_page(edt_tid);
CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);

return (NULLACTION);
}

int edt_screen()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Change screen mode.
.RETURNS Status
- --------------------------------------------------------------*/
{

#if 0		/* NOT AVAILABLE ================== */
    edt_close();
    if (edt_mode == TABULAR) edt_mode = ROW;
    else                     edt_mode = TABULAR;
    edt_init(edt_mode);
    edt_format(RESETPAGE);
    edt_page(edt_tid);
#else
    ShowError("Only TABULAR mode is available");
#endif

    return (NULLACTION);
}

int edt_command()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Execute command.
.RETURNS Status
- --------------------------------------------------------------*/

{  int status;
   char *p;


    ClearWindow(dialogue_window);
    buf_pos = buffer; *buf_pos = '\0'; 	/* Initialize: buffer empty */

    edt_action = NULLACTION;
    edt_status = COMMAND;
    while (p=GetWord(" Command: ")) 
    {  if (*p == 'h' ||*p == 'H') 
          {edt_help(); 
           continue;
          }
       if (*p == '\0')      break;
       if (tk_cexec(p) == -1) 
		ShowError("ERROR >> Command ambiguous or not defined");
       if (edt_action == TERMINATE) return(TERMINATE);
    }
    edt_status = NULLACTION; 
    RemoveWindow(dialogue_window);
    ClearError();
    return (edt_action);
}

void edt_getval(val, err)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Get value to search and error interactivelly.
- ------------------------------------------------------------*/
    double *val;              /* value to search */
    double *err;              /* error in the search */

 {       double atof(); 
  	 char *str;

    str = GetWord(" Enter value: ");
    *val = 0.;		/* Default */
    if(!str)	return;
    *val = atof(str);
    str = GetWord(" Enter error: ");
    *err = 0.;		/* Default */
    if(!str)	return;
    *err = atof(str);
}

void edt_getchar(val, start, end)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Get string to search.
- ------------------------------------------------------------*/
    char *val;              /* value to search */
    int  *start;            /* start string */
    int  *end;              /* end string */
 { 
  	 char *str;

    *val = '\0';
    str = GetWord(" Enter string: ");
    if(!str)	return;
    strcopy(val, str);
    str = GetWord(" Enter starting position of subfield: ");
    *start = 0;		/* Default */
    if(!str)	return;
    *start = atoi(str);
    str = GetWord(" Enter end position of subfield: ");
    *end = 0;		/* Default */
    if(!str)	return;
    *end = atoi(str);
}

int edt_find()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Find value in a column
- ------------------------------------------------------------*/


{int column, ctemp, row, next, len, dtype, nb, iend, istart, i;
 char form[20], msg[80];

    GetCursor(data_subwindow,cursor_pos);
    thecol = compute_col();
    column = edt_column[thecol];
    row    = edt_row[cursor_pos[0]];
    ctemp  = cursor_pos[1];

    sprintf(msg," Search value. Column %d, starting row %d ",column,row);

    setwindow(msg);

    TCFGET(edt_tid, column, form, &len, &dtype);
    if (dtype == D_C_FORMAT)
       {edt_getchar(edt_csearch,&edt_cstart,&edt_cend);
        if (edt_csearch[0] == '\0') goto error;
        nb    = edt_cend - edt_cstart + 1;
        TCESRC(edt_tid, column, edt_csearch, edt_cstart, nb, row, &next);
       }
    else
       {edt_getval(&edt_vsearch,&edt_esearch);
        TCESRD(edt_tid, column, edt_vsearch, edt_esearch, row, &next);
       }

    if (next > 0) 
       {sprintf(msg," Value found at row %d ",next);
        ShowError(msg);
        row = next;
        if (row < edt_row[0] || row > edt_row[edt_nr-1]) /* outside */
/*           {iend    = MIN(row+data_lines/2, edt_nrow); */
           {iend    = MIN(row+data_lines/2, edt_narow); /* mod. to alloc.rows */
            istart  = MAX(1, iend-data_lines+1);
            for (i=0; i<data_lines; i++) edt_row[i] = i+istart;
            edt_page(edt_tid);
           }
        cursor_pos[0] = row - edt_row[0];
        cursor_pos[1] = ctemp;
        CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);
       }
     else     ShowError(" Value not found");
    
error:
    resetwindow();
    return (NULLACTION);
}

void edt_getrow(relative, row)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Get row number interactivelly;
		row number can be absolute or relative (+/-).
- ------------------------------------------------------------*/
   int *relative;             /* relative positioning */
   int *row;                  /* row number */

 { 
  	 char *str, *p;

    str = GetWord(" Enter row: ");
    *row = 1;		/* Default */
    if(!str)	return;

    if (*str == '-' || *str == '+') 
       *relative = TRUE;
    else 
       *relative = FALSE;

    *row = atoi(str);
}

int edt_findrow()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Search row 
- ------------------------------------------------------------*/


{ int  relative, row, iend, istart, i, status;

    GetCursor(data_subwindow,cursor_pos);
    setwindow(" Search Table Row.");

    edt_getrow(&relative,&row);   
    if (row == 0)
       {resetwindow();
        return (NULLACTION);
       }
    if (relative) row = edt_row[cursor_pos[0]] + row;
    
    if (row < edt_row[0] || row > edt_row[edt_nr-1]) /* outside the page */
/*       {iend   = MIN(row + data_lines/2, edt_nrow);  mod. to alloc. rows */
       {iend   = MIN(row + data_lines/2, edt_narow);
        istart = MAX(1, iend-data_lines+1);
        for (i=0; i< data_lines; i++) edt_row[i] = i+istart;
        status = edt_page(edt_tid);
       }
    cursor_pos[0] = row - edt_row[0];
    CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);

    resetwindow();
    return (NULLACTION);
}

int edt_fndnxt()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE Find next value in a column
- ------------------------------------------------------------*/

{int column, ctemp, row, next, len, dtype, nb, iend, istart, i;
 char form[20], msg[80];

    GetCursor(data_subwindow,cursor_pos);
    thecol = compute_col();
    column = edt_column[thecol];
    row    = edt_row[cursor_pos[0]];
    ctemp  = cursor_pos[1];

    TCFGET(edt_tid, column, form, &len, &dtype);
    if (dtype == D_C_FORMAT)
       {nb    = edt_cend - edt_cstart + 1;
        TCESRC(edt_tid, column, edt_csearch, edt_cstart, nb, row, &next);
       }
    else TCESRD(edt_tid, column, edt_vsearch, edt_esearch, row, &next);

    if (next > 0) 
       {sprintf(msg," Value found at row %d ",next);
        ShowError(msg);
        row = next;
        if (row < edt_row[0] || row > edt_row[edt_nr-1]) /* outside */
/*           {iend    = MIN(row+data_lines/2, edt_nrow);  mod. to alloc.rows */
           {iend    = MIN(row+data_lines/2, edt_narow);
            istart  = MAX(1, iend-data_lines+1);
            for (i=0; i<data_lines; i++) edt_row[i] = i+istart;
            edt_page(edt_tid);
           }
        cursor_pos[0] = row - edt_row[0];
        cursor_pos[1] = ctemp;
        CursorTo(data_subwindow,cursor_pos[0],cursor_pos[1]);
       }
     else
         ShowError(" Value not found");
    
    resetwindow();
    return (NULLACTION);
}

int edt_creacol()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE 	Create  column
- ------------------------------------------------------------*/
{
  int column, status, type, alen;
  char label[20], format[10];
  char *answer;
  static char unit[17] = "unitless";

    setwindow(" Create column.");

    edt_getlabel(label, sizeof(label));   

    if (label[0] == '\0') {
      	ShowError("Missing label");
  	resetwindow();
       	return (NULLACTION);
    }
       
    answer = GetWord(" Enter data type: ");
    if (!*answer) {
        strcpy(format,"E12.6");
        type= 10;
        alen = 1;
        }
    else {
        if (status = tbl_dectyp(answer, &type, &alen, format)) {
	ShowError("Bad datatype");
  	resetwindow();
       	return (NULLACTION);
        }
    }

    answer = GetWord(" Enter Format: ");
    if (! answer)	return (NULLACTION);
    if (*answer)	strncopy (format, sizeof(format), answer);

    status = TCCINI(edt_tid, type, alen, format, unit, label, &column);
    if (status == ERR_NORMAL) {
       	edt_ncol = edt_ncol + 1;
        edt_format(RESETPAGE);
        edt_page(edt_tid);
    }
    else ShowError(TBL_eget());
    resetwindow();


    return (NULLACTION);

}

int edt_delcol()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Delete column
- ------------------------------------------------------------*/


{  int column, flag, status, ncol;

    setwindow(" Delete column.");

    if (edt_getcol(1, &column, &flag) == 1){    
	status = TCCDEL(edt_tid, column, &ncol);
	if (status == ERR_NORMAL) {
		edt_ncol = edt_ncol - 1;
		if (edt_displayed(column)) {
			edt_format(RESETPAGE);
			edt_page(edt_tid);
		}
	}
	else ShowError("Error deleting the column");
    } 
    resetwindow();
    return (NULLACTION);
}

int edt_chgfmt()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Change format in a column
- ------------------------------------------------------------*/

{  int column, flag, status;
   char *answer;
   char format[10];


    setwindow(" Change format in a column.");

    if (edt_getcol(1, &column, &flag) == 1)  {
    	answer = GetWord(" Enter Format: ");
    	if (!*answer)       return (NULLACTION);

        status = TCFPUT(edt_tid, column, answer);
        if (status == ERR_NORMAL) {
     		if (edt_displayed(column)) {
              		edt_format(RESETPAGE);
               		edt_page(edt_tid);
         	} 
  	}
        else ShowError(TBL_eget());;
    } 

    resetwindow();
    return (NULLACTION);
}

int edt_showtable()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	show table
- ------------------------------------------------------------*/

{  char line[80];

   sprintf(line,"Cols: %d, Rows: %d, Alloc. rows: %d, Alloc. words/rec: %d",
           edt_ncol, edt_nrow, edt_narow, edt_nacol);
   ShowError(line);
   return (NULLACTION);
}

int edt_adv()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Advance
- ------------------------------------------------------------*/
{  
   edt_advance = TRUE;
   return (NULLACTION);
}

int edt_backup()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Backup
- ------------------------------------------------------------*/
{ 
   edt_advance = FALSE;
   return (NULLACTION);
}

int edt_line()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	New line
- ------------------------------------------------------------*/
{  thecol = compute_col();
   if (thecol == 0)
      {if (edt_advance == TRUE) edt_nextline();
       else             edt_prevline();
      }
   else
       edt_homecol();
  
   return (NULLACTION);
}

int edt_dell()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Delete line
- ------------------------------------------------------------*/
{  ShowError("DELETE LINE not yet implemented");
   return (NULLACTION);
}

int edt_undell()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Undelete line
- ------------------------------------------------------------*/
{  ShowError("UNDELETE LINE not yet implemented");
   return (NULLACTION);
}

int edt_delw()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Delete Word
- ------------------------------------------------------------*/
{  ShowError("DELETE ENTRY not yet implemented");
   return (NULLACTION);
}

int edt_undelw()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Undelete word
- ------------------------------------------------------------*/
{  ShowError("UNDELETE ENTRY not yet implemented");
   return (NULLACTION);
}

int edt_delc()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Delete character
- ------------------------------------------------------------*/
{  ShowError("DELETE character not yet implemented");
   return (NULLACTION);
}

int edt_undelc()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Undelete character
- ------------------------------------------------------------*/
{  ShowError("UNDELETE CHAR not yet implemented");
   return (NULLACTION);
}

int edt_badkey()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Bad Key
- ------------------------------------------------------------*/
{  ShowError("ERROR >>> Bad Key ");
   return (NULLACTION);
}

int edt_noaction()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	None
- ------------------------------------------------------------*/
{
   return (NULLACTION);
}

edt_getlabel(label, size)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	Get column label interactivelly.
- ------------------------------------------------------------*/
 char *label;
 int  size; 	/* IN: Size of format buffer */

{	char *str, *p;

    str = GetWord(" Enter label :");
    *label = '\0';
    if(!str)	return 0;

    for (p = str; *p ==' ' || *p ==':' || *p =='#'; p++) ;

    strncopy(label, size, p);

    return 0;
}

int edt_displayed(column)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE	True if column is displayed, false otherwise
- ------------------------------------------------------------*/
 int column;

{int i;

    for (i=0; i<edt_nc; i++) if (edt_column[i] == column) return (TRUE);    

    return (FALSE);
}

int edt_addrow()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PURPOSE        Add a given number of rows at a given position of the table
- ----------------------------------------------------------*/
{
  int irow,nrow,i,phform;
  char *str;
  int status;
  setwindow(" Add row");
  status = TCDGET(edt_tid,&phform);
  if (phform == F_RECORD) {
        status = ShowError("Function not available for RECORD Tables");
        return(NULLACTION);
   }
  str = GetWord("Enter position:");
  if (!*str) return(NULLACTION);
  irow = atoi(str);
  str = GetWord("Enter number of rows:");
  if (!*str) return(NULLACTION);
  nrow = atoi(str);
  status = TBL_ADDROW(edt_tid,irow,nrow);
    if (status == ERR_NORMAL) {
        edt_nrow = edt_nrow + nrow;
        edt_narow = edt_nrow;
        edt_nr = MIN(edt_nrow,data_lines);
        for (i=0; i<edt_nr; i++) edt_row[i] = i+1;
        edt_format(RESETPAGE);
        edt_page(edt_tid);
    }
    else if (status == ERR_TBLROW) {
        status = ShowError("Error in Row Position");
        return(NULLACTION);
        }

  }	
int edt_delrow()
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PURPOSE        delete  one or several rows at a given position of the table
- ----------------------------------------------------------*/
{
  int irow,nrow;
  char *str;
  int status,phform;
  setwindow(" Del row");
  status = TCDGET(edt_tid,&phform);
  if (phform == F_RECORD) {
        status = ShowError("Function not available for RECORD Tables ");
        return(NULLACTION);
   }
  str = GetWord("Enter position:");
  if (!*str) return(NULLACTION);
  irow = atoi(str);
  str = GetWord("Enter number of rows:");
  if (!*str) return(NULLACTION);
  nrow = atoi(str);
  status = TBL_DELROW(edt_tid,irow,nrow);
    if (status == ERR_NORMAL) {
       edt_nrow = edt_nrow - nrow;
       edt_nr = edt_nr - nrow;
       edt_narow = edt_nrow;
       edt_format(RESETPAGE);
       edt_page(edt_tid);
     }
    else if (status == ERR_TBLROW) {
        status = ShowError("Error in Row Position");
        return(NULLACTION);
        }
 }
