// $Id: interf_aux.cc,v 1.1 1998/10/25 23:39:52 cthulhu Exp $

#include "tcl_interf.hh"

/**** Auxiliary functions for Find command ****/

char *strnstr(char *haystack,char *needle)
{
  char *aux_h=haystack,*aux_n=needle;

  for(;*aux_h!='\0';aux_h++)
    {
      if(toupper(*aux_h)==toupper(*aux_n))
	{
	  aux_n++;
	  if(*aux_n=='\0')
	    return(aux_h-strlen(needle)+1);
	}
      else
	aux_n=needle;
    }
  return(NULL);
}

char *strrep(char *destination,char *substring,char *replacement)
{
  char *ret,*end,*read_ptr;

  ret=(char *) malloc(strlen(destination)+strlen(replacement)-
		      strlen(substring)+1);
  ret=strcpy(ret,destination);
  read_ptr=strstr(ret,substring);
  end=(char *) malloc (strlen(read_ptr+strlen(substring))+1);
  end=strcpy(end,read_ptr+strlen(substring));
  strncpy(read_ptr,replacement,strlen(replacement));
  read_ptr+=strlen(replacement);
  strcpy(read_ptr,end);
  free(end);
  return(ret);
}  

char *strnrep(char *destination,char *substring,char *replacement)
{
  char *ret,*end,*read_ptr;

  ret=(char *) malloc(strlen(destination)+strlen(replacement)-
		      strlen(substring)+1);
  ret=strcpy(ret,destination);
  read_ptr=strnstr(ret,substring);
  end=(char *) malloc (strlen(read_ptr+strlen(substring))+1);
  end=strcpy(end,read_ptr+strlen(substring));
  strncpy(read_ptr,replacement,strlen(replacement));
  read_ptr+=strlen(replacement);
  strcpy(read_ptr,end);
  free(end);
  return(ret);
}  

int SearchCell(Sheet *sheet, Tcl_Interp *interp, char *search, char *replace,
	       int i, int j, int form, int vals, int exact, int whole)
{
  char *aux,*tmp;
  Cell *cell;

  if((cell=sheet->cellExists(i,j))!=NULL)
    switch(cell->type) 
      {
      case CODE_INTEGER:
	if((vals==1)&&(atoi(search)==cell->ivalue))
	  {
	    if(replace!=NULL)
	      {
		cell = sheet->cellSet(i,j,replace);
		if (cell->modified) 
		  sheet->recalc(cell);
	      }
	    sprintf(interp->result,"%d %d",i,j);
	    return(TCL_OK);
	  }
	break;
      case CODE_NUMBER:
	if((vals==1)&&(atof(search)==cell->value))
	  {
	    if(replace!=NULL)
	      {
		cell = sheet->cellSet(i,j,replace);
		if (cell->modified) 
		  sheet->recalc(cell);
	      }
	    sprintf(interp->result,"%d %d",i,j);
	    return(TCL_OK);
	  }
	break;
      case CODE_LABEL:
	if(vals==1)
	  {
	    if(whole==0)
	      {
		if((exact==1)&&((aux=strstr(cell->label,search))!=NULL))
		  {
		    if(replace!=NULL)
		      {
			tmp=strrep(cell->label+1,search,replace);
			sheet->cellSet(i,j,tmp);
			free(tmp);
			if(cell->modified)
			  sheet->recalc(cell);
		      }
		    sprintf(interp->result,"%d %d",i,j);
		    return(TCL_OK);
		  }
		if((exact==0)&&(strnstr(cell->label,search)!=NULL))
		  {
		    if(replace!=NULL)
		      {
			tmp=strnrep(cell->label+1,search,replace);
			sheet->cellSet(i,j,tmp);
			free(tmp);
			if(cell->modified)
			  sheet->recalc(cell);
		      }
		    sprintf(interp->result,"%d %d",i,j);
		    return(TCL_OK);
		  }
	      }
	    else if(whole==1)
	      {
		if((exact==1)&&(strcmp(cell->label+1,search)==0))
		  {
		    if(replace!=NULL)
		      {
			sheet->cellSet(i,j,replace);
			if(cell->modified)
			  sheet->recalc(cell);
		      }
		    sprintf(interp->result,"%d %d",i,j);
		    return(TCL_OK);
		  }
		if((exact==0)&&(strcasecmp(cell->label+1,search)==0))
		  {
		    if(replace!=NULL)
		      {
			sheet->cellSet(i,j,replace);
			if(cell->modified)
			  sheet->recalc(cell);
		      }
		    sprintf(interp->result,"%d %d",i,j);
		    return(TCL_OK);
		  }
	      }
	  }
	break;
      case CODE_BLANK:
	break;
      case CODE_FORMULA:
	if(form==1)
	  {
	    if(whole==0)
	      {
		if((exact==1)&&
		   (strstr(sheet->formula_string(cell),search)!=NULL))
		  {
		    if(replace!=NULL)
		      {
			tmp=strrep(cell->label+1,search,replace);
			sheet->cellSet(i,j,tmp);
			free(tmp);
			if(cell->modified)
			  sheet->recalc(cell);
		      }
		    sprintf(interp->result,"%d %d",i,j);
		    return(TCL_OK);
		  }
		if((exact==0)&&
		   (strnstr(sheet->formula_string(cell),search)!=NULL))
		  {
		    if(replace!=NULL)
		      {
			tmp=strnrep(cell->label+1,search,replace);
			sheet->cellSet(i,j,tmp);
			free(tmp);
			if(cell->modified)
			  sheet->recalc(cell);
		      }
		    sprintf(interp->result,"%d %d",i,j);
		    return(TCL_OK);
		  }
	      }
	    else if(whole==1)
	      {
		if((exact==1)&&(strcmp(sheet->formula_string(cell),search)==0))
		  {
		    if(replace!=NULL)
		      {
			sheet->cellSet(i,j,replace);
			if(cell->modified)
			  sheet->recalc(cell);
		      }
		    sprintf(interp->result,"%d %d",i,j);
		    return(TCL_OK);
		  }
		if((exact==0)&&
		   (strcasecmp(sheet->formula_string(cell),search)==0))
		  {
		    if(replace!=NULL)
		      {
			sheet->cellSet(i,j,replace);
			if(cell->modified)
			  sheet->recalc(cell);
		      }
		    sprintf(interp->result,"%d %d",i,j);
		    return(TCL_OK);
		  }
	      }
	  }
	break;
      default:
	internal_error();
      }
  return(-1);
}

/**** Auxiliary functions for PasteSpecial command ****/

void reverse(char *s)
{
  int c,i,j;

  for(i=0,j=strlen(s)-1;i<j;i++,j--)
    {
      c=s[i];
      s[i]=s[j];
      s[j]=c;
    }
}

#define MBIG 1000000000

char *itof(double n,char *s)
{
  int i;
  double sign;
  
  n*=MBIG;
  n=floor(n);
  if((sign=n)<0)
    n=-n;
  i=0;
  do 
    {
      s[i++]=(char) floor(fmod(n,10))+'0';
      if(i==9)
	s[i++]='.';
    } while((n/=10)>1);
  if(sign<0)
    s[i++]='-';
  s[i]='\0';
  reverse(s);
  return(s);
}

#undef MBIG

char *itoa(int n,char *s)
{
  int i,sign;

  if((sign=n)<0)
    n=-n;
  i=0;
  do 
    {
      s[i++]=n%10+'0';
    } while((n/=10)>0);
  if(sign<0)
    s[i++]='-';
  s[i]='\0';
  reverse(s);
  return(s);
}

void join_formulas_op_all(Sheet *sheet, Cell *from,Cell *to,int op,int inv,
			  int all)
{
  char *aux_s,aux_tmp[40],*aux_s1;

  if((inv==1)&&((from->type==CODE_LABEL)||(from->type==CODE_BLANK)))
    {
      if(all==1)
	*to=*from;
      else
	{
	  to->type=from->type;
	  to->value=from->value;
	  to->ivalue=from->ivalue;
	  if(from->type==CODE_LABEL)
	    {
	      to->label=new char[strlen(from->label)+1];
	      to->label=strcpy(to->label,from->label);
	    }
	}
      return;
    }
  if(from->type==CODE_FORMULA)
    {
      aux_s=new char[strlen(sheet->formula_string(from))+
		    strlen(sheet->formula_string(to))+5];
      aux_s1=sheet->formula_string(to);
      aux_s[0]='=';
      aux_s[1]='\0';
      aux_s=strcat(aux_s,aux_s1);
      switch(op)
	{
	case(PASTE_ADD):
	  aux_s=strcat(aux_s,"+");
	  break;
	case(PASTE_SUB):
	  aux_s=strcat(aux_s,"-");
	  break;
	case(PASTE_MUL):
	  aux_s=strcat(aux_s,"*");
	  break;
	case(PASTE_DIV):
	  aux_s=strcat(aux_s,"/");
	  break;
	default:
	  internal_error();
	  break;
	}
      aux_s1=sheet->formula_string(from);
      aux_s=strcat(aux_s,aux_s1);
      if(all==1)
	*to=*from;
      to=sheet->cellSet(to->col,to->row,aux_s);
      if (to->modified) {
	sheet->recalc(to);
      }
      return;
    }
  if(from->type==CODE_INTEGER)
    {
      aux_s1=sheet->formula_string(to);
      aux_s=new char[strlen(aux_s1)+25];
      itoa(from->ivalue,aux_tmp);
      aux_s[0]='=';
      aux_s[1]='\0';
      aux_s=(inv==1 ? strcat(aux_s,aux_s1) : strcat(aux_s,aux_tmp));
      switch(op)
	{
	case(PASTE_ADD):
	  aux_s=strcat(aux_s,"+");
	  break;
	case(PASTE_SUB):
	  aux_s=strcat(aux_s,"-");
	  break;
	case(PASTE_MUL):
	  aux_s=strcat(aux_s,"*");
	  break;
	case(PASTE_DIV):
	  aux_s=strcat(aux_s,"/");
	  break;
	default:
	  internal_error();
	  break;
	}
      aux_s=(inv==1 ? strcat(aux_s,aux_tmp) : strcat(aux_s,aux_s1));
      if(inv==1)
	{
	  if(all==1)
	    *to=*from;
	  to=sheet->cellSet(to->col,to->row,aux_s);
	  if (to->modified) {
	    sheet->recalc(to);
	  }
	}
      else
	{
	  if(all==1)
	    *from=*to;
	  from=sheet->cellSet(from->col,from->row,aux_s);
	  if (from->modified) {
	    sheet->recalc(to);
	  }
	}
      return;
    }
  if(from->type==CODE_NUMBER)
    {
      aux_s1=sheet->formula_string(to);
      aux_s=new char[strlen(aux_s1)+45];
      itof(from->value,aux_tmp);
      aux_s[0]='=';
      aux_s[1]='\0';
      aux_s=(inv==1 ? strcat(aux_s,aux_s1) : strcat(aux_s,aux_tmp));
      switch(op)
	{
	case(PASTE_ADD):
	  aux_s=strcat(aux_s,"+");
	  break;
	case(PASTE_SUB):
	  aux_s=strcat(aux_s,"-");
	  break;
	case(PASTE_MUL):
	  aux_s=strcat(aux_s,"*");
	  break;
	case(PASTE_DIV):
	  aux_s=strcat(aux_s,"/");
	  break;
	default:
	  internal_error();
	  break;
	}
      aux_s=(inv==1 ? strcat(aux_s,aux_tmp) : strcat(aux_s,aux_s1));
      if(inv==1)
	{
	  if(all==1)
	    *to=*from;
	  to=sheet->cellSet(to->col,to->row,aux_s);
	  if (to->modified) {
	    sheet->recalc(to);
	  }
	}
      else
	{
	  if(all==1)
	    *from=*to;
	  from=sheet->cellSet(from->col,from->row,aux_s);
	  if (from->modified) {
	    sheet->recalc(to);
	  }
	}
      return;
    }
  internal_error();
}

void join_formulas_op_val(Cell *from,Cell *to,int op)
{
  char *aux_s,aux_tmp[20];

  if((from->type==CODE_LABEL)||(from->type==CODE_BLANK))
    {
      to->type=from->type;
      to->value=from->value;
      to->ivalue=from->ivalue;
      to->label=from->label;
      return;
    }
  if(from->type==CODE_FORMULA)
    {
      from->type=CODE_NUMBER;
      from->value=from->formula->value;
    }
  if(from->type==CODE_INTEGER)
    {
      aux_s=new char[strlen(from->formula->formula)+20];
      aux_s=strncpy(aux_s,to->formula->formula,
		    strlen(to->formula->formula));
      switch(op)
	{
	case(PASTE_ADD):
	  aux_s=strncat(aux_s,"+",1);
	  break;
	case(PASTE_SUB):
	  aux_s=strncat(aux_s,"-",1);
	  break;
	case(PASTE_MUL):
	  aux_s=strncat(aux_s,"*",1);
	  break;
	case(PASTE_DIV):
	  aux_s=strncat(aux_s,"/",1);
	  break;
	default:
	  internal_error();
	  break;
	}
      itoa(from->ivalue,aux_tmp);
      aux_s=strcat(aux_s,aux_tmp);
      to->type=from->type;
      to->value=from->value;
      to->ivalue=from->ivalue;
      to->label=from->label;
      to->formula=&(Formula(strlen(aux_s),aux_s));
      free(aux_s);
    }
  if(from->type==CODE_NUMBER)
    {
      aux_s=new char[strlen(from->formula->formula)+20];
      aux_s=strncpy(aux_s,to->formula->formula,
		    strlen(to->formula->formula));
      switch(op)
	{
	case(PASTE_ADD):
	  aux_s=strncat(aux_s,"+",1);
	  break;
	case(PASTE_SUB):
	  aux_s=strncat(aux_s,"-",1);
	  break;
	case(PASTE_MUL):
	  aux_s=strncat(aux_s,"*",1);
	  break;
	case(PASTE_DIV):
	  aux_s=strncat(aux_s,"/",1);
	  break;
	default:
	  internal_error();
	  break;
	}
      itof(from->ivalue,aux_tmp);
      aux_s=strcat(aux_s,aux_tmp);
      to->type=from->type;
      to->value=from->value;
      to->ivalue=from->ivalue;
      to->label=from->label;
      to->formula=&(Formula(strlen(aux_s),aux_s));
      free(aux_s);
    }
}

void paste_cell(Sheet *sheet,Cell *from,Cell *to,int what, int how)
{
  short aux_i;
  double aux_d;
  char *aux_s,aux_tmp[20];

  switch(what)
    {
    case(PASTE_ALL):
      switch(how)
	{
	case(PASTE_NONE):
	  *to=*from;
	  break;
	case(PASTE_ADD):
	case(PASTE_SUB):
	case(PASTE_MUL):
	case(PASTE_DIV):
	  if((to->type==CODE_BLANK) || (to->type==CODE_LABEL))
	    {
	      *to=*from;
	      break;
	    }
	  if(to->type==CODE_FORMULA)
	    {
	      join_formulas_op_all(sheet,from,to,how,1,1);
	      break;
	    }
	  if(from->type==CODE_FORMULA)
	    {
	      join_formulas_op_all(sheet,to,from,how,0,1);
	      break;
	    }
	  if((to->type==CODE_INTEGER) && (from->type==CODE_INTEGER))
	    {
	      aux_i=to->ivalue;
	      *to=*from;
	      if(how==PASTE_ADD)
		to->ivalue=aux_i+to->ivalue;
	      if(how==PASTE_SUB)
		to->ivalue=aux_i-to->ivalue;
	      if(how==PASTE_MUL)
		to->ivalue=aux_i*to->ivalue;
	      if(how==PASTE_DIV)
		to->ivalue=aux_i/to->ivalue;
	      break;
	    }
	  if(to->type==CODE_INTEGER)
	    {
	      aux_d=to->ivalue;
	      to->value=to->ivalue;
	    }
	  else
	    aux_d=to->value;
	  *to=*from;
	  to->value=to->ivalue;
	  to->type=CODE_NUMBER;
	  if(how==PASTE_ADD)
	    to->value=aux_d+to->value;
	  if(how==PASTE_SUB)
	    to->value=aux_d-to->value;
	  if(how==PASTE_MUL)
	    to->value=aux_d*to->value;
	  if(how==PASTE_DIV)
	    to->value=aux_d/to->value;
	  break;
	default:
	  internal_error();
	  break;
	}
      break;
    case(PASTE_FORMULAS):
      switch(how)
	{
	case(PASTE_NONE):
	  to->type=from->type;
	  to->value=from->value;
	  to->ivalue=from->ivalue;
	  if(from->type==CODE_LABEL)
	    {
	      to->label=new char[strlen(from->label)+1];
	      to->label=strcpy(to->label,from->label);
	    }
	  if(from->type==CODE_FORMULA)
	    to->formula=new Formula(*from->formula);
	  break;
	case(PASTE_ADD):
	case(PASTE_SUB):
	case(PASTE_MUL):
	case(PASTE_DIV):
	  if((to->type==CODE_BLANK) || (to->type==CODE_LABEL))
	    {
	      to->type=from->type;
	      to->value=from->value;
	      to->ivalue=from->ivalue;
	      if(from->type==CODE_LABEL)
		{
		  to->label=new char[strlen(from->label)+1];
		  to->label=strcpy(to->label,from->label);
		}
	      if(from->type==CODE_FORMULA)
		to->formula=new Formula(*from->formula);
	      break;
	    }
	  if(to->type==CODE_FORMULA)
	    {
	      join_formulas_op_all(sheet,from,to,how,1,1);
	      break;
	    }
	  if(from->type==CODE_FORMULA)
	    {
	      join_formulas_op_all(sheet,to,from,how,0,1);
	      break;
	    }
	  if((to->type==CODE_INTEGER) && (from->type==CODE_INTEGER))
	    {
	      aux_i=to->ivalue;
	      to->ivalue=from->ivalue;
	      if(how==PASTE_ADD)
		to->ivalue=aux_i+to->ivalue;
	      if(how==PASTE_SUB)
		to->ivalue=aux_i-to->ivalue;
	      if(how==PASTE_MUL)
		to->ivalue=aux_i*to->ivalue;
	      if(how==PASTE_DIV)
		to->ivalue=aux_i/to->ivalue;
	      break;
	    }
	  if(to->type==CODE_INTEGER)
	    {
	      aux_d=to->ivalue;
	      to->value=to->ivalue;
	    }
	  else
	    aux_d=to->value;
	  if(from->type==CODE_INTEGER)
	    to->value=from->ivalue;
	  else
	    to->value=from->value;
	  to->type=CODE_NUMBER;
	  if(how==PASTE_ADD)
	    to->value=aux_d+to->value;
	  if(how==PASTE_SUB)
	    to->value=aux_d-to->value;
	  if(how==PASTE_MUL)
	    to->value=aux_d*to->value;
	  if(how==PASTE_DIV)
	    to->value=aux_d/to->value;
	  break;
	default:
	  internal_error();
	  break;
	}
      break;
    case(PASTE_VALUES):
      switch(how)
	{
	case(PASTE_NONE):
	  to->type=from->type;
	  to->value=from->value;
	  to->ivalue=from->ivalue;
	  if(from->type==CODE_LABEL)
	    {
	      to->label=new char[strlen(from->label)+1];
	      to->label=strcpy(to->label,from->label);
	    }
	  if(from->type==CODE_FORMULA)
	    {
	      to->type=CODE_NUMBER;
	      to->value=from->formula->value;
	    }
	  break;
	case(PASTE_ADD):
	case(PASTE_SUB):
	case(PASTE_MUL):
	case(PASTE_DIV):
	  if((to->type==CODE_BLANK) || (to->type==CODE_LABEL))
	    {
	      to->type=from->type;
	      to->value=from->value;
	      to->ivalue=from->ivalue;
	      if(from->type==CODE_LABEL)
		{
		  to->label=new char[strlen(from->label)+1];
		  to->label=strcpy(to->label,from->label);
		}
	      if(from->type==CODE_FORMULA)
		{
		  to->type=CODE_NUMBER;
		  to->value=from->formula->value;
		}
	      break;
	    }
	  if((from->type==CODE_LABEL)||(from->type==CODE_BLANK))
	    {
	      to->type=from->type;
	      if(from->type==CODE_LABEL)
		{
		  to->label=new char[strlen(from->label)+1];
		  to->label=strcpy(to->label,from->label);
		}
	      break;
	    }
	  if(from->type==CODE_FORMULA)
	    {
	      if(to->type==CODE_INTEGER)
		aux_d=to->ivalue;
	      else if(to->type==CODE_FORMULA)
		aux_d=to->formula->value;
	      else
		aux_d=to->value;
	      to->type=CODE_NUMBER;
	      if(how==PASTE_ADD)
		to->value=aux_d+from->formula->value;
	      if(how==PASTE_SUB)
		to->value=aux_d-from->formula->value;
	      if(how==PASTE_MUL)
		to->value=aux_d*from->formula->value;
	      if(how==PASTE_DIV)
		to->value=aux_d/from->formula->value;
	      break;
	    }
	  if(to->type==CODE_FORMULA)
	    {
	      if(from->type==CODE_INTEGER)
		aux_d=from->ivalue;
	      else
		aux_d=from->value;
	      to->type=CODE_NUMBER;
	      to->value=to->formula->value;
	      if(how==PASTE_ADD)
		to->value=aux_d+to->value;
	      if(how==PASTE_SUB)
		to->value=aux_d-to->value;
	      if(how==PASTE_MUL)
		to->value=aux_d*to->value;
	      if(how==PASTE_DIV)
		to->value=aux_d/to->value;
	      break;
	    }
	  if((to->type==CODE_INTEGER) && (from->type==CODE_INTEGER))
	    {
	      aux_i=to->ivalue;
	      to->ivalue=from->ivalue;
	      if(how==PASTE_ADD)
		to->ivalue=aux_i+to->ivalue;
	      if(how==PASTE_SUB)
		to->ivalue=aux_i-to->ivalue;
	      if(how==PASTE_MUL)
		to->ivalue=aux_i*to->ivalue;
	      if(how==PASTE_DIV)
		to->ivalue=aux_i/to->ivalue;
	      break;
	    }
	  if(to->type==CODE_INTEGER)
	    {
	      aux_d=to->ivalue;
	      to->value=to->ivalue;
	    }
	  else
	    aux_d=to->value;
	  if(from->type==CODE_INTEGER)
	    to->value=from->ivalue;
	  else
	    to->value=from->value;
	  to->type=CODE_NUMBER;
	  if(how==PASTE_ADD)
	    to->value=aux_d+to->value;
	  if(how==PASTE_SUB)
	    to->value=aux_d-to->value;
	  if(how==PASTE_MUL)
	    to->value=aux_d*to->value;
	  if(how==PASTE_DIV)
	    to->value=aux_d/to->value;
	  break;
	default:
	  internal_error();
	  break;
	}
      break;
    case(PASTE_FORMATS):
      to->format=from->format;
      break;
    default:
      internal_error();
      break;
    }
}

/**** Auxiliary functions for SortCells command ****/

int CompareStrings(char *str1,char *str2)
{
  int i,size=MIN(strlen(str1),strlen(str2));
  
  for(i=0;i<size;i++)
    {
      if(str1[i]<str2[i])
	return((sort_dir==1 ? -1 : 1));
      if(str1[i]>str2[i])
	return((sort_dir==1 ? 1 : -1));
    }
  if(strlen(str1)==strlen(str2))
    return(0);
  if(strlen(str1)<strlen(str2))
    return((sort_dir==1 ? -1 : 1));
  return((sort_dir==1 ? 1 : -1));
}

int CompareCells(const void *val1,const void *val2)
{
  Cell *cell1,*cell2;

  cell1=((SortList*) val1)->val;
  cell2=((SortList*) val2)->val;

  if((cell1->type==CODE_LABEL)||(cell2->type==CODE_LABEL))
    {
      if(cell1->type==CODE_LABEL)
	{
	  if(cell2->type==CODE_LABEL)
	    return(CompareStrings(cell1->label,cell2->label));
	  else
	    return((sort_dir==1 ? -1 : 1));
	}
      return((sort_dir==1 ? 1 : -1));
    }
  if((cell1->type==CODE_BLANK)||(cell2->type==CODE_BLANK))
    {
      if(cell1->type==CODE_BLANK)
	{
	  if(cell2->type==CODE_BLANK)
	    return(0);
	  else
	    return((sort_dir==1 ? 1 : -1));
	}
      return((sort_dir==1 ? -1 : 1));
    }
  switch(cell1->type)
    {
    case CODE_INTEGER:
    case CODE_NUMBER:
    case CODE_FORMULA:
      if(!VALUE_DIFFERENT(cell1->getValueAsDouble(),
			  cell2->getValueAsDouble()))
	return(0);
      if(cell1->getValueAsDouble()<cell2->getValueAsDouble())
	return((sort_dir==1 ? -1 : 1));
      return((sort_dir==1 ? 1 : -1));
      break;
    case CODE_LABEL:
    case CODE_BLANK:
    default:
      internal_error();
      break;
    }
}

SortList *BuildSortColumnVector(Sheet *sheet,SortList *list,Range rng,short *i)
{
  Ref aux;
  Cell *cell;
  short end,j,act_col;
  SortList *cur,*act;

  Range_iter ref(rng);
  for(ref.first(aux),*i=0,act_col=aux.col-1;!ref.last();ref.next(aux))
    {
      if(aux.col!=act_col)
	{
	  ++act_col;
	  cell=sheet->cellFind(aux.col,aux.row);
	  list[*i].val=new Cell;
	  list[*i].val->loadvalue(*cell);
	  if (cell->type == CODE_FORMULA)
	    sheet->manipulateReferences(cell,REMOVE_REFERENCES);
	  list[*i].next=NULL;
	  act=&list[*i];
	  (*i)++;
	}
      else
	{
	  cell=sheet->cellFind(aux.col,aux.row);
	  act->next=new SortList;
	  act=act->next;
	  act->next=NULL;
	  act->val=new Cell;
	  act->val->loadvalue(*cell);
	  if(cell->type==CODE_FORMULA)
	    sheet->manipulateReferences(cell,REMOVE_REFERENCES);
	}
    }
  return(list);
}

SortList *BuildSortRowVector(Sheet *sheet,SortList *list,Range rng,short *i)
{
  Ref aux;
  Cell *cell;
  int num_elems;
  short end,j;
  SortList *cur,*act;

  Range_iter ref(rng);
  for(ref.first(aux),end=aux.col,*i=0;
      aux.col==end && !ref.last();
      ref.next(aux),(*i)++)
    {
      cell = sheet->cellFind(aux.col,aux.row);
      list[*i].val=new Cell;
      list[*i].val->loadvalue(*cell);
      if (cell->type == CODE_FORMULA)
	sheet->manipulateReferences(cell,REMOVE_REFERENCES);
      list[*i].next=NULL;
    }
  num_elems=*i;
  while(!ref.last())
    {
      cell=sheet->cellFind(aux.col,aux.row);
      j=num_elems%(*i);
      if((act=list[j].next)==NULL)
	act=&list[j];
      else
	while(act->next!=NULL)
	  act=act->next; /* optimize by adding a pointer to last element ? */
      cur=new SortList;
      cur->val=new Cell;
      cur->val->loadvalue(*cell);
      if (cell->type == CODE_FORMULA)
	sheet->manipulateReferences(cell,REMOVE_REFERENCES);
      cur->next=NULL;
      act->next=cur;
      ++num_elems;
      ref.next(aux);
    }
  return(list);
}

SortList *RearrangeSortColumn(Sheet *sheet,SortList *list,Range rng,short *i,
			      array<Cell*> *to_calc)
{
  Ref aux;
  short j,act_col;
  Cell *cell;
  SortList *act,*cur;

  Range_iter ref(rng);
  for(ref.first(aux),act_col=aux.col-1;!ref.last();ref.next(aux))
    {
      cell=sheet->cellFind(aux.col,aux.row);
      if(act_col!=aux.col)
	{
	  ++act_col;
	  j=aux.col-rng.start.col;
	  cell->loadvalue(*(list[j].val));
	  if (cell->type == CODE_FORMULA)
	    sheet->manipulateReferences(cell,INSERT_REFERENCES);
	  *to_calc += cell;
	  sheet->display(cell);
	  delete list[j].val;
	  act=list[j].next;
	}
      else
	{
	  cur=act->next;
	  cell->loadvalue(*(act->val));
	  if (cell->type == CODE_FORMULA)
	    sheet->manipulateReferences(cell,INSERT_REFERENCES);
	  *to_calc += cell;
	  sheet->display(cell);
	  delete act->val;
	  delete act;
	  act=cur;
	}
    }
  return(list);
}

SortList *RearrangeSortRow(Sheet *sheet,SortList *list,Range rng,short *i,
			   array<Cell*> *to_calc)
{
  short j,k;
  Cell *cell;
  SortList *act,*cur;

  (*i)--;
  for(j=0;j<=(*i);j++)
    {
      cell=sheet->cellFind(rng.start.col,rng.start.row+j);
      cell->loadvalue(*(list[j].val));
      if (cell->type == CODE_FORMULA)
	sheet->manipulateReferences(cell,INSERT_REFERENCES);
      *to_calc += cell;
      delete list[j].val;
      sheet->display(cell);
      act=list[j].next;
      for(k=1;act!=NULL;k++)
	{
	  cell=sheet->cellFind(rng.start.col+k,rng.start.row+j);
	  cell->loadvalue(*(act->val));
	  if (cell->type == CODE_FORMULA)
	    sheet->manipulateReferences(cell,INSERT_REFERENCES);
	  *to_calc += cell;
	  delete act->val;
	  sheet->display(cell);
	  cur=act;
	  act=act->next;
	  delete cur;
	}
    }
  return(list);
}

SortList *SwapKeyValue(SortList *list,short i,short Key)
{
  short j,k;
  Cell *cell;
  SortList *act,*cur;

  cell=new Cell;
  for(j=0;j<i;j++)
    {
      act=&list[j];
      for(k=0;k!=Key;k++)
	act=act->next;
      cell->loadvalue(*(act->val));
      act->val->loadvalue(*(list[j].val));
      list[j].val->loadvalue(*cell);
    }
  delete cell;
  return(list);
}

/**** Auxiliary functions for SetFormat command ****/

void ApplyCRFormat(Sheet *sheet, short col_or_row, int index, 
		   CR_Formats format, Format *fmt)
{
  int col=0,row=0;
  Cell *cell;
  array<Cell *> to_display;
  
  if(col_or_row==0)
    col=index;
  else
    row=index;

  while((col_or_row==0 ? row : col) <= 
	((col_or_row==0 ? sheet->max_row_used : sheet->max_col_used)))
    {
      if(sheet->cellExists(col, row))
	{
	  cell=sheet->cellFind(col,row);
	  to_display+=cell;
	  switch(format)
	    {
	    case FORMAT:
	      cell->format.form=fmt->form;
	      break;
	    case ALIGNMENT:
	      cell->format.alignment=fmt->alignment;
	      break;
	    case FONT_FAMILY:
	      cell->format.font.family=fmt->font.family;
	      break;
	    case SIZE:
	      cell->format.font.size=fmt->font.size;
	      break;
	    case ITALICS:
	      cell->format.font.italics=fmt->font.italics;
	      break;
	    case BOLD:
	      cell->format.font.bold=fmt->font.bold;
	      break;
	    case TOP:
	      cell->format.borders.top=fmt->borders.top;
	      break;
	    case BOTTOM:
	      cell->format.borders.bottom=fmt->borders.bottom;
	      break;
	    case LEFT:
	      cell->format.borders.left=fmt->borders.left;
	      break;
	    case RIGHT:
	      cell->format.borders.right=fmt->borders.right;
	      break;
	    case BG:
	      cell->format.bg.filllevel=fmt->bg.filllevel;
	      break;
	    case -1:
	      cell->format=*fmt;
	      break;
	    default:
	      internal_error();
	      break;
	    }
	}
      if(col_or_row==0)
	++row;
      else
	++col;
    }
  sheet->display(to_display);
}

// $Log: interf_aux.cc,v $
// Revision 1.1  1998/10/25 23:39:52  cthulhu
// Initial revision
//
