/********************************************************************
This file is part of the abs 0.907 distribution.  abs is a spreadsheet
with graphical user interface.

Copyright (C) 1998-2001  André Bertin (Andre.Bertin@ping.be) 

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 if in the same spirit as version 2.

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 Mass Ave, Cambridge, MA 02139, USA.

Concact: abs@pi.be
         http://home.pi.be/bertin/abs.shtml

*********************************************************************/


























#include "worksheet.h"
#include "workbook.h"
#include "memory.h"
#include "newplot.h"
#include "main.h"
#include "callback.h"

extern int setcursor (int r, int c);

#define CW worksheet_getcolw
#define RH worksheet_getrowh


Worksheet *ActiveWorksheet;
extern void setscrollvlimit (int vmin, int vmax);
extern void setscrollhlimit (int vmin, int vmax);
extern void setscrollv (double v);
extern void setscrollh (double v);
extern void setzoomlabel (int z);
extern int rebuild_thumb ();



static int nworksheet = 1;

Worksheet *
newworksheet ()
{

  Worksheet *worksheet;
  Worksheet *tmp = ActiveWorksheet;

  if (ActiveWorkbook == NULL)
    return NULL;

  worksheet = (Worksheet *) absmalloc (sizeof (Worksheet), "newworksheet:worksheet ");

  if (worksheet == NULL)
    {
      fprintf (stderr, "worksheet not allocated!");
      return (Worksheet *) NULL;
    };

  ActiveWorksheet = worksheet;

  worksheet->nblin = NB_LINE;
  worksheet->nbcol = NB_COLUMN;

  worksheet->lh = NULL;
  worksheet->cw = NULL;
  worksheet->lhdim = -1;
  worksheet->cwdim = -1;

  worksheet->ll = 1;
  worksheet->cc = 1;
  worksheet->nbcell = 0;
  worksheet->nbgraph = 0;
  worksheet->nbdrawing = 0;
  worksheet->nbbutton = 0;
  worksheet->zoom = 100;

  worksheet->Graphs = NULL;
  worksheet->Drawings = NULL;
  worksheet->Buttons = NULL;

  worksheet->selection = newselection ();

  worksheet->defcell = newcell (-1, -1);
  worksheet->defcell->worksheet = worksheet;

  ActiveGraph = NULL;		
  ActiveDrawing = NULL;		
  ActiveButton = NULL;		

  worksheet->activegraph = NULL;
  worksheet->activedrawing = NULL;
  worksheet->activebutton = NULL;

  ActiveSelection = worksheet->selection;

  
  worksheet->objnum = nworksheet++;
  

  worksheet->array = NULL;
  worksheet->maxrow = -1;
  worksheet->_maxcol = 0;
  worksheet->maxcol = NULL;

  worksheet->workbook = ActiveWorkbook;
  worksheet->cur_r = 1;
  worksheet->cur_c = 1;
  ActiveCell = worksheet_getcell (worksheet, 1, 1, 1);
  worksheet->activecell = ActiveCell;
  worksheet_select_cell (ActiveWorksheet, ActiveCell);


  ActiveWorksheet = tmp;
  return worksheet;
}

int
freeworksheet (worksheet)
     Worksheet *worksheet;
{
  int i, j;

  if (worksheet == NULL)
    return 1;
  


  if (ActiveWorksheet == worksheet)
    {				
      for (i = 0; i < ActiveWorksheet->nbgraph; i++)
	deletegraphpixmap (ActiveWorksheet->Graphs[i]);
      ActiveWorksheet = NULL;
    }


  for (i = 0; i < worksheet->nbgraph; i++)
    freegraph (worksheet->Graphs[i]);
  for (i = 0; i < worksheet->nbdrawing; i++)
    freedrawing (worksheet->Drawings[i]);
  for (i = 0; i < worksheet->nbbutton; i++)
    freebutton (worksheet->Buttons[i]);

  freeselection (worksheet->selection);


  for (i = 1; i <= worksheet->maxrow; i++)	
    {
      for (j = 1; j <= worksheet->maxcol[i]; j++)
	freecell (worksheet->array[i][j]);
      if (worksheet->array[i] != NULL)
	absfree (worksheet->array[i], "freeworksheet:worksheet->array[i] ");
    }
  if (worksheet->maxrow > 0)
    {
      absfree (worksheet->array, "freeworksheet:worksheet->array ");
      absfree (worksheet->maxcol, "freeworksheet:worksheet->maxcol ");
    }

  freecell (worksheet->defcell);

  if (worksheet->cw != NULL)
    absfree (worksheet->cw, "freeworksheet:cw");
  if (worksheet->lh != NULL)
    absfree (worksheet->lh, "freeworksheet:lh");

  absfree (worksheet, "freeworksheet:worksheet ");

  return 0;
}

int
worksheet_write (worksheet, fp)
     Worksheet *worksheet;
     FILE *fp;
{
  int i, j;
  char buf[10];
  double v;
  int dim;
  
  
  
  

  for (i = 0; i < worksheet->nbcol - 1; i++)
    {
      dim = CW (worksheet, i + 1) - CW (worksheet, i);
      if (dim != W_COL)
	{
	  coltoalpha (buf, i);
	  v = dim / 7.;
	  fprintf (fp, "Columns(\"%s\").ColumnWidth = %f\n", buf, v);
	}
    }

  for (i = 0; i < worksheet->nblin - 1; i++)
    {
      dim = RH (worksheet, i + 1) - RH (worksheet, i);
      if (dim != H_LIN)
	{
	  fprintf (fp, "Rows(\"%d\").RowHeight = %d\n", i, dim);
	}
    }


  for (i = 1; i <= worksheet->maxrow; i++)
    for (j = 1; j <= worksheet->maxcol[i]; j++)
      {
	if (worksheet->array[i][j] != NULL)
	  cell_write (worksheet->array[i][j], fp);
      }












  for (i = 0; i < worksheet->nbgraph; i++)
    graph_write (worksheet->Graphs[i], fp);
  for (i = 0; i < worksheet->nbdrawing; i++)
    drawing_write (worksheet->Drawings[i], fp);
  for (i = 0; i < worksheet->nbbutton; i++)
    button_write (worksheet->Buttons[i], fp);

  return 0;
}

int
worksheet_update (worksheet)
     Worksheet *worksheet;
{
  int i;
  

  for (i = 0; i < worksheet->nbgraph; i++)
    {
      ActiveGraph = worksheet->Graphs[i];
      plot (0);
    }
  

  
  
  
  
  return 0;
}






int
worksheet_find (worksheet, x, y)
     Worksheet *worksheet;
     int x, y;
{				
				
				
  return 0;
}

Cell *
worksheet_getcell (worksheet, r, c, new)
     Worksheet *worksheet;
     int r, c, new;
{
  int i;
  Cell *cell;
  Cell *ret;

  worksheet->defcell->r = r;
  worksheet->defcell->c = c;
  cell = worksheet->defcell;


  if (worksheet == NULL)
    return NULL;

  if (r < 0 || r > NB_LINE)
    return worksheet->defcell;
  if (c < 0 || c > NB_COLUMN)
    return worksheet->defcell;
  if (r == 0 && c == 0)
    return worksheet->defcell;

  if (new < 0)
    {
      ret = NULL, new = 0;
    }
  else
    ret = worksheet->defcell;

  if (r < 0 || c < 0 || r > worksheet->nblin || c > worksheet->nbcol)
    return ret;

  if (r > worksheet->maxrow)
    {
      if (!new)
	return ret;

      
      worksheet->array = (Cell ***) absrealloc (worksheet->array, sizeof (Cell **) * (r + 1), "worksheet_getcell:worksheet->array ");
      worksheet->maxcol = (int *) absrealloc (worksheet->maxcol, sizeof (int) * (r + 1), "worksheet_getcell:worksheet->maxcol ");

      for (i = worksheet->maxrow + 1; i <= r; i++)
	{
	  worksheet->maxcol[i] = 0;
	  worksheet->array[i] = NULL;
	}

      
      worksheet->array[r] =
	(Cell **) absrealloc (worksheet->array[r], sizeof (Cell *) * (c + 1), "worksheet_getcell:worksheet->array[r] ");
      for (i = 0; i <= c; i++)
	worksheet->array[r][i] = NULL;

      
      worksheet->maxrow = r;
      if (c > worksheet->_maxcol)
	worksheet->_maxcol = c;
      worksheet->maxcol[r] = c;

      worksheet->array[r][c] = newcell (r, c);
      worksheet->array[r][c]->worksheet = worksheet;

      return worksheet->array[r][c];
    }
  else if (c > worksheet->maxcol[r])
    {
      if (!new)
	return ret;

      worksheet->array[r] =
	(Cell **) absrealloc (worksheet->array[r], sizeof (Cell *) * (c + 1), "worksheet_getcell:worksheet->array[r] ");
      for (i = worksheet->maxcol[r] + 1; i <= c; i++)
	worksheet->array[r][i] = NULL;
      worksheet->maxcol[r] = c;
      if (c > worksheet->_maxcol)
	worksheet->_maxcol = c;
      {
	worksheet->array[r][c] = newcell (r, c);
	worksheet->array[r][c]->worksheet = worksheet;
      }
      return worksheet->array[r][c];
    }


  else if (worksheet->array[r][c] == NULL)
    {
      if (!new)
	return ret;
      worksheet->array[r][c] = newcell (r, c);
      worksheet->array[r][c]->worksheet = worksheet;

      return worksheet->array[r][c];
    }

  return worksheet->array[r][c];

}

int
worksheet_delcell (worksheet, r, c)
     Worksheet *worksheet;
     int r, c;
{
  Cell *cell = worksheet_getcell (worksheet, r, c, -1);
  if (cell == NULL)
    return 1;

  if (cell->familly->numpar > 0)
    cell_isnew (cell);


  if (cell->familly->numchi > 0)
    cell_setformula (cell, "");
  else
    {
      worksheet->array[r][c] = NULL;
      freecell (cell);
    }
  return 0;
}

Graph *
worksheet_newgraph (worksheet)
     Worksheet *worksheet;
{
  worksheet->Graphs = (Graph **) absrealloc (worksheet->Graphs, sizeof (Graph *) * (worksheet->nbgraph + 1), "worksheet_newgraph:worksheet->Graphs ");
  worksheet->Graphs[worksheet->nbgraph] = newgraph ();
  worksheet->activegraph = worksheet->Graphs[worksheet->nbgraph];
  worksheet->nbgraph++;
  worksheet->activegraph->worksheet = worksheet;
  if (worksheet == ActiveWorksheet)
    {
      creategraphpixmap (worksheet->activegraph);
      doplot (worksheet->activegraph);
      ActiveGraph = worksheet->activegraph;
    }

  return worksheet->Graphs[worksheet->nbgraph - 1];
}

Graph *
worksheet_newgraph1 (Worksheet * worksheet, Graph * graph)
{
  worksheet->Graphs = (Graph **) absrealloc (worksheet->Graphs, sizeof (Graph *) * (worksheet->nbgraph + 1), "worksheet_newgraph:worksheet->Graphs ");
  worksheet->Graphs[worksheet->nbgraph] = newgraph1 (graph);
  worksheet->activegraph = worksheet->Graphs[worksheet->nbgraph];
  worksheet->nbgraph++;
  worksheet->activegraph->worksheet = worksheet;
  if (worksheet == ActiveWorksheet)
    {
      creategraphpixmap (worksheet->activegraph);
      doplot (worksheet->activegraph);
      ActiveGraph = worksheet->activegraph;
    }
  return worksheet->Graphs[worksheet->nbgraph - 1];
}

static int indelgraph = 0;
int
worksheet_delgraph (Worksheet * worksheet, Graph * graph)
{
  int i, found = 0;
  if (indelgraph)
    return 0;			
  indelgraph = 1;

  if (ActiveWorksheet == worksheet)
    {				
      for (i = 0; i < ActiveWorksheet->nbgraph; i++)
	{
	  if (graph == ActiveWorksheet->Graphs[i])
	    deletegraphpixmap (ActiveWorksheet->Graphs[i]);
	}
    }

  i = 0;
  while (i < worksheet->nbgraph && found == 0)
    {
      if (graph == worksheet->Graphs[i])
	found = 1;
      i++;
    }
  if (found == 0)
    return -1;

  found = i - 1;
  for (i = found; i < worksheet->nbgraph - 1; i++)
    {
      worksheet->Graphs[i] = worksheet->Graphs[i + 1];
    }
  worksheet->nbgraph--;

  if (worksheet->nbgraph > 0)
    {
      worksheet->Graphs = (Graph **) absrealloc (worksheet->Graphs, sizeof (Graph *) * (worksheet->nbgraph + 1), "worksheet_newgraph:worksheet->Graphs ");
    }
  else
    {
      absfree (worksheet->Graphs, "worksheet_delgraph:worksheet->Graphs ");
      worksheet->Graphs = NULL;
    }

  freegraph (graph);

  indelgraph = 0;
  return 0;

}




Drawing *
worksheet_newdrawing (worksheet)
     Worksheet *worksheet;
{
  fprintf (stderr, "newdrawing worksheet->nbdrawing %d\n", worksheet->nbdrawing);
  worksheet->Drawings = (Drawing **) absrealloc (worksheet->Drawings, sizeof (Drawing *) * (worksheet->nbdrawing + 1), "worksheet_newdrawing:worksheet->Drawings ");
  worksheet->Drawings[worksheet->nbdrawing] = newdrawing ();
  worksheet->activedrawing = worksheet->Drawings[worksheet->nbdrawing];
  worksheet->activedrawing->worksheet = worksheet;
  worksheet->nbdrawing++;
  return worksheet->Drawings[worksheet->nbdrawing - 1];
}

Drawing *
worksheet_newdrawing1 (Worksheet * worksheet, Drawing * drawing)
{
  fprintf (stderr, "newdrawing1 worksheet->nbdrawing %d\n", worksheet->nbdrawing);
  worksheet->Drawings = (Drawing **) absrealloc (worksheet->Drawings, sizeof (Drawing *) * (worksheet->nbdrawing + 1), "worksheet_newdrawing:worksheet->Drawings ");
  worksheet->Drawings[worksheet->nbdrawing] = newdrawing1 (drawing);
  worksheet->activedrawing = worksheet->Drawings[worksheet->nbdrawing];
  worksheet->activedrawing->worksheet = worksheet;
  worksheet->nbdrawing++;
  return worksheet->Drawings[worksheet->nbdrawing - 1];
}


static int indeldrawing = 0;

int
worksheet_deldrawing (Worksheet * worksheet, Drawing * drawing)
{
  int i, found = 0;

  fprintf (stderr, "indeldrawing %d, worksheet->nbdrawing %d\n", indeldrawing, worksheet->nbdrawing);

  if (indeldrawing)
    return 0;
  indeldrawing = 1;

  i = 0;
  while (i < worksheet->nbdrawing && found == 0)
    {
      if (drawing == worksheet->Drawings[i])
	found = 1;
      i++;
    }
  if (found == 0)
    {
      indeldrawing = 0;
      fprintf (stderr, "drawing not found! \n");
      return -1;
    }

  fprintf (stderr, "drawing found at position %d\n", i - 1);

  found = i - 1;

  for (i = found; i < worksheet->nbdrawing - 1; i++)
    {
      fprintf (stderr, "moving drawing %d to pos %d\n", i + 1, i);
      worksheet->Drawings[i] = worksheet->Drawings[i + 1];
    }
  worksheet->nbdrawing--;

  fprintf (stderr, "NOW worksheet->nbdrawing %d\n", worksheet->nbdrawing);

  if (worksheet->nbdrawing > 0)
    {
      worksheet->Drawings = (Drawing **) absrealloc (worksheet->Drawings, sizeof (Drawing *) * (worksheet->nbdrawing + 1), "worksheet_deldrawing:worksheet->Drawings ");
    }
  else
    {
      absfree (worksheet->Drawings, "worksheet_deldrawing:worksheet->Drawings ");
      worksheet->Drawings = NULL;
      worksheet->nbdrawing = 0;
    }

  freedrawing (drawing);

  indeldrawing = 0;

  return 0;

}


Button *
worksheet_newbutton (worksheet)
     Worksheet *worksheet;
{
  worksheet->Buttons = (Button **) absrealloc (worksheet->Buttons, sizeof (Button *) * (worksheet->nbbutton + 1), "worksheet_newbutton:worksheet->Buttons ");
  worksheet->Buttons[worksheet->nbbutton] = newbutton ();
  worksheet->activebutton = worksheet->Buttons[worksheet->nbbutton];
  worksheet->nbbutton++;
  return worksheet->Buttons[worksheet->nbbutton - 1];
}

extern int repaint_activesheet (char *message);

Worksheet *
ActivateWorksheet (worksheet)
     Worksheet *worksheet;
{
  int i;

  if (worksheet == NULL)
    return NULL;

  if (ActiveWorksheet != worksheet && ActiveWorksheet != NULL)
    {				
      for (i = 0; i < ActiveWorksheet->nbgraph; i++)
	deletegraphpixmap (ActiveWorksheet->Graphs[i]);
    }

  ActiveWorksheet = worksheet;
  worksheet->workbook->activeworksheet = worksheet;
  
  ActiveCell = worksheet->activecell;
  ActiveGraph = worksheet->activegraph;
  ActiveDrawing = worksheet->activedrawing;
  ActiveButton = worksheet->activebutton;
  ActiveSelection = worksheet->selection;



  for (i = 0; i < worksheet->nbgraph; i++)
    {
      creategraphpixmap (worksheet->Graphs[i]);
      doplot (worksheet->Graphs[i]);
    }

  
  cb_setzoom (worksheet->zoom);
  setzoomlabel (worksheet->zoom);
  setscrollvlimit (1, worksheet->nblin);
  setscrollhlimit (1, worksheet->nbcol);
  setscrollv ((double) worksheet->ll);
  setscrollh ((double) worksheet->cc);

  if (worksheet->workbook == ActiveWorkbook)
    {
      repaint_activesheet ("ActivateWorksheet");
      rebuild_thumb ();
    }
  
  setcursor (ActiveWorksheet->cur_r, ActiveWorksheet->cur_c);

  return ActiveWorksheet;
}

Chart *
worksheet_getchart (worksheet, n)
     Worksheet *worksheet;
     int n;
{
  if (n > 0 && n < worksheet->nbgraph)
    return worksheet->Graphs[n];
  return NULL;
}

Graph *
worksheet_addchart (worksheet, args, n)
     Worksheet *worksheet;
     int *args;
     int n;
{
  worksheet->Graphs = (Graph **) absrealloc (worksheet->Graphs, sizeof (Graph *) * (worksheet->nbgraph + 1), "worksheet_newgraph:worksheet->Graphs ");
  worksheet->Graphs[worksheet->nbgraph] = newgraph ();
  worksheet->activegraph = worksheet->Graphs[worksheet->nbgraph];
  worksheet->nbgraph++;
  worksheet->activegraph->worksheet = worksheet;



  if (n == 4)
    {
      worksheet->activegraph->x = args[0];
      worksheet->activegraph->y = args[1];
      worksheet->activegraph->w = args[2];
      worksheet->activegraph->h = args[3];
    }
  else
    {
      worksheet->activegraph->x = 30;
      worksheet->activegraph->y = 30;
      worksheet->activegraph->w = 80;
      worksheet->activegraph->h = 50;
    }

  if (worksheet == ActiveWorksheet)
    {
      creategraphpixmap (worksheet->activegraph);
      doplot (worksheet->activegraph);
      ActiveGraph = worksheet->activegraph;
    }
  return worksheet->activegraph;
}

Drawing *
worksheet_addshape (worksheet, args, n)
     Worksheet *worksheet;
     int *args;
     int n;
{
  if (worksheet == NULL)
    return NULL;
  if (n != 5 && n != 4)
    return NULL;

  worksheet->Drawings = (Drawing **) absrealloc (worksheet->Drawings, sizeof (Drawing *) * (worksheet->nbdrawing + 1)
				,"worksheet_addshape:worksheet->Drawings ");
  worksheet->Drawings[worksheet->nbdrawing] = (Drawing *) newdrawing ();
  worksheet->activedrawing = worksheet->Drawings[worksheet->nbdrawing];
  worksheet->nbdrawing++;


  if (n == 5)
    {
      worksheet->activedrawing->type = args[0];
      worksheet->activedrawing->x1 = args[1];
      worksheet->activedrawing->y1 = args[2];
      worksheet->activedrawing->x2 = args[3];
      worksheet->activedrawing->y2 = args[4];
    }
  if (n == 4)
    {
      worksheet->activedrawing->type = 0;
      worksheet->activedrawing->x1 = args[0];
      worksheet->activedrawing->y1 = args[1];
      worksheet->activedrawing->x2 = args[2];
      worksheet->activedrawing->y2 = args[3];
    }


  ActiveDrawing = worksheet->activedrawing;
  return ActiveDrawing;
}

Button *
worksheet_addbutton (worksheet, args, n)
     Worksheet *worksheet;
     int *args;
     int n;
{
  worksheet->Buttons = (Button **) absrealloc (worksheet->Buttons, sizeof (Button *) * (worksheet->nbbutton + 1), "worksheet_addbutton:worksheet->Buttons ");
  worksheet->Buttons[worksheet->nbbutton] = (Button *) newbutton ();
  worksheet->activebutton = worksheet->Buttons[worksheet->nbbutton];
  worksheet->nbbutton++;

  worksheet->activebutton->x1 = args[0];
  worksheet->activebutton->y1 = args[1];
  worksheet->activebutton->x2 = args[2] + args[0];
  worksheet->activebutton->y2 = args[3] + args[1];

  ActiveButton = worksheet->activebutton;
  return ActiveButton;
}



int
worksheet_setcolw (worksheet, col, w)
     Worksheet *worksheet;
     int col;
     double w;
{
  int i;
  int dw;
  int dim = worksheet->cwdim;

  col++;
  if (col <= 0)
    return -1;


  if (col > dim)
    {
      worksheet->cw = (int *) absrealloc (worksheet->cw, sizeof (int) * (col + 1), "worksheet_setcolw:cw");
      if (dim == -1)
	{
	  worksheet->cw[0] = -W_COL;
	  dim = 0;
	}
      for (i = dim + 1; i <= col; i++)
	worksheet->cw[i] = worksheet->cw[i - 1] + W_COL;
      worksheet->cwdim = col;
    }

  dw = w - (worksheet->cw[col] - worksheet->cw[col - 1]);
  for (i = col; i <= worksheet->cwdim; i++)
    worksheet->cw[i] += dw;

  return 0;
}

int
worksheet_setrowh (worksheet, lin, h)
     Worksheet *worksheet;
     int lin;
     double h;
{
  int i;
  int dh;
  int dim = worksheet->lhdim;
  lin++;
  if (lin <= 0)
    return -1;

  if (lin > dim)
    {
      worksheet->lh = (int *) absrealloc (worksheet->lh, sizeof (int) * (lin + 1), "worksheet_setrowh:lh");
      if (dim == -1)
	{
	  worksheet->lh[0] = -H_LIN;
	  dim = 0;
	}
      for (i = dim + 1; i <= lin; i++)
	worksheet->lh[i] = worksheet->lh[i - 1] + H_LIN;
      worksheet->lhdim = lin;
    }

  dh = h - (worksheet->lh[lin] - worksheet->lh[lin - 1]);
  for (i = lin; i <= worksheet->lhdim; i++)
    worksheet->lh[i] += dh;
  return 0;
}


double
worksheet_getcolw (worksheet, col)
     Worksheet *worksheet;
     int col;
{
  int dim;

  if (col < 0)
    return 0.0;

  dim = worksheet->cwdim;

  if (dim == -1)
    {
      return (col - 1) * W_COL;
    }

  if (col > dim)
    {
      return (worksheet->cw[dim] + (col - dim) * W_COL);
    }
  return worksheet->cw[col];
}

double
worksheet_getrowh (worksheet, lin)
     Worksheet *worksheet;
     int lin;
{
  int dim;
  dim = worksheet->lhdim;

  if (lin < 0)
    return 0.0;

  if (dim == -1)
    {
      return (lin - 1) * H_LIN;
    }

  if (lin > dim)
    {
      return (worksheet->lh[dim] + (lin - dim) * H_LIN);
    }

  return worksheet->lh[lin];
}


int
worksheet_setname (Worksheet * worksheet, char *name)
{
  int len = 0;
  int i, j, k;
  Cell *cell;
  char oldname[30];
  if (name == NULL)
    return -1;
  len = strlen (name);
  if (len < 1)
    return -1;
  if (len > 30)
    {
      name[29] = '\0';
      len = 30;
    }
  
  strcpy (oldname, worksheet->Name);
  strcpy (worksheet->Name, name);
  worksheet->Name[29] = '\0';
  rebuild_thumb ();



  for (i = 1; i <= worksheet->maxrow; i++)
    for (j = 1; j <= worksheet->maxcol[i]; j++)
      {
	cell = worksheet->array[i][j];
	if (cell != NULL)
	  {
	    if (cell->familly != NULL)
	      for (k = 0; k < cell->familly->numchi; k++)
		{		
		  cell_chgwksname (cell->familly->childlist[k], oldname, name);
		}
	  }
      }
  return 0;
}

int 
worksheet_calculate (Worksheet * worksheet)
{
  int i, j;
  for (i = 1; i <= worksheet->maxrow; i++)
    for (j = 1; j <= worksheet->maxcol[i]; j++)
      {
	if (worksheet->array[i][j] != NULL)
	  cell_calculate (worksheet->array[i][j]);
      }
  if (worksheet == ActiveWorksheet)
    repaint_activesheet ("worksheet_calculate");
  return 0;
}

int 
worksheet_printout (Worksheet * worksheet)
{

  return 0;
}

int 
worksheet_setcursor (Worksheet * worksheet, int row, int column)
{
  Cell *cell;
  if (worksheet == NULL)
    return -1;
  worksheet->cur_r = row;
  worksheet->cur_c = column;

  if (worksheet->cur_r < 1)
    worksheet->cur_r = 1;
  else if (worksheet->cur_r > worksheet->nblin)
    worksheet->cur_r = worksheet->nblin;

  if (worksheet->cur_c < 1)
    worksheet->cur_c = 1;
  else if (worksheet->cur_c > worksheet->nbcol)
    worksheet->cur_c = worksheet->nbcol;

  cell = worksheet_getcell (worksheet, worksheet->cur_r, worksheet->cur_c, 0);
  if (cell != ActiveCell)
    cell_activate (cell);

  return 0;
}

int 
worksheet_movecursor (Worksheet * worksheet, int drow, int dcolumn)
{
  if (worksheet == NULL)
    return -1;
  return worksheet_setcursor (worksheet, worksheet->cur_r + drow, worksheet->cur_c + dcolumn);

  return 0;
}

#include "object.h"

int
worksheet_select_cell (Worksheet * w, Cell * c)
{
  if (w == NULL || c == NULL)
    return -1;
  worksheet_select_range (w, c->r, c->c, c->r, c->c);
  worksheet_setcursor (w, c->r, c->c);
  return 0;
}

int
worksheet_select_range (Worksheet * w, int i1, int j1, int i2, int j2)
{
  Range *range;
  obj o;
  selection_reset (w->selection);
  range = newrange2 (i1, j1, i2, j2);

  o.rec.s = (char *) range;
  o.type = name2type ("RANGE");
  selection_addobj (w->selection, o);
  
  return 0;
}

int
worksheet_select_graph (Worksheet * w, Graph * c)
{
  obj o;
  if (w == NULL)
    return -1;
  selection_reset (w->selection);
  if (c == NULL)
    return 0;

  o.rec.s = (char *) c;
  o.type = name2type ("CHART");
  selection_addobj (w->selection, o);
  return 0;
}

int
worksheet_select_drawing (Worksheet * w, Drawing * d)
{
  obj o;
  if (w == NULL || d == NULL)
    return -1;
  selection_reset (w->selection);
  o.rec.s = (char *) d;
  o.type = name2type ("SHAPES");
  selection_addobj (w->selection, o);
  return 0;
}

int
worksheet_select_button (Worksheet * w, Button * b)
{
  obj o;
  if (w == NULL || b == NULL)
    return -1;
  selection_reset (w->selection);
  o.rec.s = (char *) b;
  o.type = name2type ("BUTTON");
  selection_addobj (w->selection, o);
  return 0;
}






static int r = 0;
static int c = 0;
static int pl = 0;
static Range *ran = NULL;

Cell *
worksheet_selection_cells (Worksheet * w)
{
  obj o;
  int rangetype = name2type ("RANGE");

  if (ran == NULL)
    {
      o.type = 0;
      while (o.type != rangetype)
	{
	  o = selection_getobjects (w->selection);
	  if (o.type < 0)
	    return NULL;
	}
      selection_resetget (w->selection);

      ran = (Range *) o.rec.s;
      if (ran == NULL)
	return NULL;
      if (ran->nplage == 0)
	return NULL;
      pl = 0;
      c = ran->plage[pl].c1 - 1;
      r = ran->plage[pl].r1;
    }

  c++;
  if (c > ran->plage[pl].c2)
    {
      c = ran->plage[pl].c1;
      r++;
      if (r > ran->plage[pl].r2)
	{
	  pl++;
	  if (pl >= ran->nplage)
	    {
	      pl = 0;
	      ran = NULL;
	      return NULL;
	    }
	  else
	    {
	      c = ran->plage[pl].c1;
	      r = ran->plage[pl].r1;
	    }
	}
    }
  
  
  return worksheet_getcell (w, r, c, 1);


}





int
worksheet_cell_coord (Worksheet * w, Cell * c, int *x1, int *y1, int *x2, int *y2)
{
  if (c == NULL)
    {
      *x1 = 0;
      *x2 = 0;
      *y1 = 0;
      *y2 = 0;
      return -1;
    }
  return worksheet_rc_coord (w, c->r, c->c, x1, y1, x2, y2);
}

#define CW worksheet_getcolw
#define LH worksheet_getrowh

int 
worksheet_rc_coord (Worksheet * w, int r, int c, int *x1, int *y1, int *x2, int *y2)
{
  if (w == NULL || r < 0 || c < 0 || r > w->nblin || c > w->nbcol)
    {
      *x1 = 0;
      *x2 = 0;
      *y1 = 0;
      *y2 = 0;
      return -1;
    }

  *x1 = (CW (w, c) - CW (w, w->cc)) * w->zoom / 100;
  *y1 = (LH (w, r) - LH (w, w->ll)) * w->zoom / 100;
  *x2 = (CW (w, c + 1) - CW (w, w->cc)) * w->zoom / 100;
  *y2 = (LH (w, r + 1) - LH (w, w->ll)) * w->zoom / 100;

  return 0;
}

Graph *
worksheet_getchart_at (Worksheet * w, int x, int y)
{
  int i;
  int x1, x2, y1, y2;
  Graph *chart;

  for (i = 0; i < w->nbgraph; i++)
    {
      chart = w->Graphs[i];
      x1 = chart->x * w->zoom / 100;
      y1 = chart->y * w->zoom / 100;
      x2 = (chart->x + chart->w) * w->zoom / 100;
      y2 = (chart->y + chart->h) * w->zoom / 100;

      if (x1 < x && y1 < y && x2 > x && y2 > y)
	{			
	  return chart;
	}
    }
  return NULL;
}
