/********************************************************************
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 "sheetdrawer.h"
#include "gr_interf.h"
#include "application.h"
#include "mainwin.h"
#include "finite_state.h"

#include "param.h"		

#include "callback.h"

extern int is_selecting ();	

#define AW ActiveWorksheet
#define CW worksheet_getcolw
#define LH worksheet_getrowh
#define SW worksheet_setcolw
#define SH worksheet_setrowh
#define Letext ActiveMainwin->commandline_obj->text
#define Drawarea ActiveMainwin->draw
#define linindex ActiveMainwin->linindex
#define colindex ActiveMainwin->colindex
#define corner ActiveMainwin->corner
#define toplevel ActiveMainwin->toplevel
#define Infoarea ActiveMainwin->info	
#define DrawAreaPixmap ActiveMainwin->DrawAreaPixmap
#define linpixmap ActiveMainwin->LinPixmap
#define colpixmap ActiveMainwin->ColPixmap
#define cornerpixmap ActiveMainwin->CornerPixmap

#define dpy ActiveMainwin->dpy
#define screen ActiveMainwin->screen
#define AMwin  ActiveMainwin->draw_window
#define Height ActiveMainwin->height
#define Width ActiveMainwin->width





int 
create_active_mainwin_pixmaps (int width, int height)
{				
  
  Height = height;
  Width = width;


  DrawAreaPixmap = createpixmap (Drawarea, width, height);
  setbackpix (Drawarea, DrawAreaPixmap);
  linpixmap = createpixmap (linindex, 40, height);
  colpixmap = createpixmap (colindex, width, 20);
  cornerpixmap = createpixmap (corner, 40, 20);
  setbackpix (linindex, linpixmap);
  setbackpix (colindex, colpixmap);
  setbackpix (corner, cornerpixmap);
  setbackpix (Drawarea, DrawAreaPixmap);

  return 0;
}

int
cb_resize (int width, int height)
{
  freepixmap (Drawarea, DrawAreaPixmap);
  freepixmap (linindex, linpixmap);
  freepixmap (colindex, colpixmap);

  Height = height - 20;
  Width = width - 40;


  DrawAreaPixmap = createpixmap (Drawarea, width - 40, height - 20);
  setbackpix (Drawarea, DrawAreaPixmap);

  linpixmap = createpixmap (linindex, 40, height - 20);
  colpixmap = createpixmap (colindex, width - 40, 20);

  setbackpix (linindex, linpixmap);
  setbackpix (colindex, colpixmap);
  xrepaint ("cb_resize");
  return 0;
}






int
xfit (int ii, int jj)
{
  int ret = 0;
  ret = xfitcolumn (ii, jj);
  if (!ret)
    ret = xfitline (ii, jj);
  return ret;
}

int
xfitcolumn (int ii, int jj)
{
  int cwidth;

  int font, fontw, fonts;
  char *name;
  Cell *cell;

  if (AW == NULL)
    return -1;
  if (ii < 0 || ii > AW->nblin || jj < 0 || jj > AW->nbcol)
    return -1;

  cell = (Cell *) applicationcell (ii, jj, -1);
  if (cell == NULL)
    return -1;
  name = cell_gettext (cell);
  if (name == NULL)
    return 0;
  if (strlen (name) < 1)
    return 0;

  font = cell_getfont (cell);
  fontw = cell_getfontw (cell);
  fonts = cell_getfonts (cell);

  cwidth = gettextw (name, strlen (name), font, fontw, fonts) + 2;

  if (CW (AW, jj + 1) - CW (AW, jj) < cwidth)
    {
      SW (AW, jj, cwidth);
    }
  return 0;
}

int
xfitline (int ii, int jj)
{
  int cheight;

  int font, fontw, fonts;
  char *name;
  Cell *cell;

  if (AW == NULL)
    return -1;
  if (ii < 0 || ii > AW->nblin || jj < 0 || jj > AW->nbcol)
    return -1;

  cell = (Cell *) applicationcell (ii, jj, -1);
  if (cell == NULL)
    return -1;

  name = cell_gettext (cell);
  if (name == NULL)
    return 0;
  if (strlen (name) < 1)
    return 0;

  font = cell_getfont (cell);
  fontw = cell_getfontw (cell);
  fonts = cell_getfonts (cell);

  cheight = gettexth (name, strlen (name), font, fontw, fonts) + 2;

  if (LH (AW, ii + 1) - LH (AW, ii) < cheight)
    {
      SW (AW, ii, cheight);
    }
  return 0;
}










static int numover = 0;

int
checkwidth (char *name, int width, Cell * cell, int r, int c, int type)
{
  int cwidth;
  int nchar;
  int i, j;
  int color, just, font, fontw, fonts;
  int delta;
  char *formula = NULL;
  Cell *cl;

  if (name == NULL)
    return width;
  nchar = strlen (name);
  if (nchar < 1)
    return width;

  color = cell_getfg (cell);
  just = cell_getjust (cell);
  font = cell_getfont (cell);
  fontw = cell_getfontw (cell);
  fonts = cell_getfonts (cell);

  cwidth = gettextw (name, nchar, font, fontw, fonts);
  if (type == 2 || type == 3)
    delta = CW (AW, c + 1 + numover) - CW (AW, c + 1);
  else
    delta = 0;


  if (cwidth > width - 2 + delta && (type != 2 && type != 3))	
    {

      i = r;
      j = c;
      cl = (Cell *) applicationcell (i, j + 1, -1);
      if (cl != NULL)
	formula = cell_getformula (cl);
      else
	formula = NULL;
      while (((cwidth > width - 2 + delta && formula == NULL) ||
	      (cwidth > width - 2 + delta && (type == 2 || type == 3))
	     ) &&
	     (width < 1000)
	)
	{
	  j++;
	  if (type == 2 || type == 3)
	    numover++;
	  delta = CW (AW, j + 1) - CW (AW, c + 1);
	  cl = (Cell *) applicationcell (i, j + 1, -1);
	  if (cl != NULL)
	    formula = cell_getformula (cl);
	  else
	    formula = NULL;
	}

    }

  return width + delta;

}

int
xdrawstring (char *name, int x, int y, int width, int widthmax, int height, int type, Cell * cell)
{
  int textx, texty;

  int cheight, cwidth;
  int nchar;
  int color, just, font, fontw, fonts;


  if (FS->l1 == StBatch || BatchMode)
    return 0;
  if (name == NULL)
    return 0;
  nchar = strlen (name);
  if (nchar < 1)
    return 0;

  font = cell_getfont (cell);
  fontw = cell_getfontw (cell);
  fonts = cell_getfonts (cell);

  cheight = gettexth (name, nchar, font, fontw, fonts);
  cwidth = gettextw (name, nchar, font, fontw, fonts);
  if (height < (cheight + 2))
    return width;


  while (cwidth > widthmax - 2 && nchar > 0)
    {
      nchar--;
      cwidth = gettextw (name, nchar, font, fontw, fonts);
    }
  if (nchar < 1)
    return 0;

  color = cell_getfg (cell);
  just = cell_getjust (cell);


  if (type == 3)
    just = 0;


  
  textx = x + 1;



  if (just == 1)
    textx = x + width / 2 - cwidth / 2;
  if (just == 2)
    textx = x + width - cwidth;
  if (textx < x + 1)
    textx = x + 1;
  texty = y + height / 2 + cheight / 2 + 1;
  
  setfont2 (color, font, fontw, fonts);
  drawstring (XtDisplay (Drawarea), DrawAreaPixmap, color, textx, texty, name, nchar, CW (AW, AW->cc), LH (AW, AW->ll));

  return 0;
}

int
xdrawrrect (int x, int y, int width, int height, int type, Cell * cell)
{

  int bg = cell_getbg (cell);
  int fg = cell_getfg (cell);
  if (FS->l1 == StBatch || BatchMode)
    return 0;

  if (bg < 0)
    bg = 0;
  if (fg < 0)
    fg = 5;
  switch (type)
    {
    case 0:
      {
	fillrectangle (dpy, DrawAreaPixmap, bg, x + 1, y + 1, width - 1, height - 1, CW (AW, AW->cc), LH (AW, AW->ll), 0);
	break;
      }
    case 4:
      {
	fillrectangle (dpy, DrawAreaPixmap, 2, x, y, width, height, CW (AW, AW->cc), LH (AW, AW->ll), 0);
	fillrectangle (dpy, DrawAreaPixmap, bg, x + 1, y + 1, width - 1, height - 1, CW (AW, AW->cc), LH (AW, AW->ll), 1);
	break;
      }
    case 7:
      {				
	fillrectangle (dpy, DrawAreaPixmap, 2, x, y, width, height, 0, 0, 0);
	fillrectangle (dpy, DrawAreaPixmap, bg, x + 1, y + 1, width - 1, height - 1, CW (AW, AW->cc), LH (AW, AW->ll), 0);
	break;
      }
    case 5:
      {
	if (bg != 0 && bg != 45)
	  fillrectangle (dpy, DrawAreaPixmap, bg, x + 1, y + 1, width - 1, height - 1, CW (AW, AW->cc), LH (AW, AW->ll), 5);
	break;
      }
    case 2:
      {
	fillrectangle (dpy, DrawAreaPixmap, bg, x + 2, y + 2, width - 3, height - 3, CW (AW, AW->cc), LH (AW, AW->ll), 0);
	break;
      }
    case 3:
      {
	fillrectangle (dpy, DrawAreaPixmap, bg, x + 2, y + 2, width - 3, height - 3, CW (AW, AW->cc), LH (AW, AW->ll), 0);
	break;
      }
    case 6:
      {
	fillrectangle (dpy, DrawAreaPixmap, bg, x + 2, y + 2, width - 3, height - 3, CW (AW, AW->cc), LH (AW, AW->ll), 0);
	break;
      }
    }


  if (cell_gettop (cell))
    {
      drawline (dpy, DrawAreaPixmap, fg, x, y, x + width, y, CW (AW, AW->cc), LH (AW, AW->ll));
    }
  if (cell_getbot (cell))
    {
      drawline (dpy, DrawAreaPixmap, fg, x + width, y + height, x, y + height, CW (AW, AW->cc), LH (AW, AW->ll));
    }
  if (cell_getrig (cell))
    {
      drawline (dpy, DrawAreaPixmap, fg, x + width, y, x + width, y + height, CW (AW, AW->cc), LH (AW, AW->ll));
    }
  if (cell_getlef (cell))
    {
      drawline (dpy, DrawAreaPixmap, fg, x, y, x, y + height, CW (AW, AW->cc), LH (AW, AW->ll));
    }
  return 0;
}

int
xdrawcursor (int pop, int selmove)
{
  int x1, x2, y1, y2;
  int i, j;
  int d = 4;
  if (ActiveWorksheet == NULL)
    return 0;
  if (ActiveCell == NULL)
    return 0;
  if (FS->l1 == StBatch || FS->l1 == 0 || BatchMode)
    return 0;



  i = ActiveWorksheet->cur_r;
  j = ActiveWorksheet->cur_c;


  x1 = CW (AW, j) - CW (AW, AW->cc);

  y1 = LH (AW, i) - LH (AW, AW->ll);

  x2 = CW (AW, j + 1) - CW (AW, AW->cc);
  y2 = LH (AW, i + 1) - LH (AW, AW->ll);










  if (is_selecting ())
    d = 0;
  setlineattributes (dpy, 1, 2, LineSolid, CapProjecting, JoinBevel);
  drawline (dpy, AMwin, 5, x1, y1, x2, y1, CW (AW, AW->cc), LH (AW, AW->ll));
  drawline (dpy, AMwin, 5, x2 + 1, y1, x2 + 1, y2 - d, CW (AW, AW->cc), LH (AW, AW->ll));
  drawline (dpy, AMwin, 5, x2 - d, y2 + 1, x1, y2 + 1, CW (AW, AW->cc), LH (AW, AW->ll));
  drawline (dpy, AMwin, 5, x1, y2 + 1, x1, y1, CW (AW, AW->cc), LH (AW, AW->ll));
  {
    if (!is_selecting ())
      {
	drawline (dpy, AMwin, 1, x2 - 1, y2 + 2, x2 + 2, y2 + 2, 0, 0);
	drawline (dpy, AMwin, 1, x2 + 2, y2 - 1, x2 + 2, y2 + 1, 0, 0);
      }
  }
  setlineattributes (dpy, 1, 1, LineSolid, CapButt, JoinBevel);

  return 0;
}


int
xdrawlincell (int i, int j, int color)
{
  char label[8];
  int height;
  int top;
  int act = 0;
  int zoom = AW->zoom;
  if (FS->l1 == StBatch || BatchMode)
    return 0;
  if (i <= 0)
    return -1;
  if (i > ActiveWorksheet->nblin)
    return -1;
  height = (LH (AW, i + 1) - LH (AW, i)) * zoom / 100 - 1;
  top = (LH (AW, i) - LH (AW, AW->ll)) * zoom / 100 + 1;
  sprintf (label, "%d", i);
  desactivate_zoom ();

/*haut */ drawline (XtDisplay (linindex), linpixmap, 0, 2, top, 38, top, 0, 0);

  if (AW != NULL)
    if (AW->cur_r == i)
      act = 1;

  fillrectangle (XtDisplay (linindex), linpixmap, 2, 2, top + 1, 37, height - 1, 0, 0, 0);

  if (act)
    {				
      drawline (XtDisplay (linindex), linpixmap, 1, 2, (top + height), 38, (top + height), 0, 0);
      /*bas-in */ drawline (XtDisplay (linindex), linpixmap, 3, 3, (top + height) - 1, 37, (top + height) - 1, 0, 0);
      /*gauch */ drawline (XtDisplay (linindex), linpixmap, 0, 2, 1 + top, 2, (top + height) - 1, 0, 0);
      /*droi */ drawline (XtDisplay (linindex), linpixmap, 1, 39, top, 39, (top + height), 0, 0);
      /*droi-in */ drawline (XtDisplay (linindex), linpixmap, 3, 38, top + 1, 38, (top + height) - 1, 0, 0);
      /*droi-in-top */ drawline (XtDisplay (linindex), linpixmap, 2, 38, top, 38, top, 0, 0);
    }
  else
    {				
      drawline (XtDisplay (linindex), linpixmap, 3, 2, (top + height), 38, (top + height), 0, 0);
      /*gauch */ drawline (XtDisplay (linindex), linpixmap, 2, 2, top + 1, 2, (top + height) - 1, 0, 0);
      /*droi */ drawline (XtDisplay (linindex), linpixmap, 3, 39, top, 39, (top + height), 0, 0);
    }
  reactivate_zoom ();

  setfont2 (0, 1, 0, 3);
  drawstring (XtDisplay (linindex), linpixmap, 1, 1 + 3 * 100 / zoom, (top + height - 4) * 100 / zoom, label, strlen (label), 0, 0);
  return 0;
}

int
xdrawcolcell (int i, int j, int color)
{
  char label[4];
  int width;
  int left;
  int act = 0;
  int zoom = AW->zoom;
  if (FS->l1 == StBatch || BatchMode)
    return 0;
  if (j <= 0)
    return -1;
  if (j > ActiveWorksheet->nbcol)
    return -1;
  width = CW (AW, j + 1) - CW (AW, j);
  left = CW (AW, j) - CW (AW, AW->cc);
  
  if (j <= 26)
    {
      label[0] = 'A' + j - 1;
      label[1] = '\0';
    }
  else
    {
      label[0] = 'A' + (j - 1) / 26 - 1;
      label[1] = 'A' + j - 26 * ((j - 1) / 26) - 1;
      label[2] = '\0';
    }


  if (AW != NULL)
    if (AW->cur_c == j)
      act = 1;

  desactivate_zoom ();
  fillrectangle (XtDisplay (colindex), colpixmap, 2, left * zoom / 100 + 1, 2, width * zoom / 100 - 1, 17, 0, 0, 0);

  if (act)
    {
      drawline (XtDisplay (colindex), colpixmap, 0, left * zoom / 100 + 1, 2, left * zoom / 100 + 1, 19, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 1, (left + width) * zoom / 100, 2, (left + width) * zoom / 100, 19, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 1, left * zoom / 100 + 1, 19, (left + width) * zoom / 100 - 1, 19, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 0, left * zoom / 100 + 1, 2, (left + width) * zoom / 100 - 1, 2, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 3, left * zoom / 100 + 1, 18, (left + width) * zoom / 100 - 1, 18, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 2, left * zoom / 100 + 1, 18, left * zoom / 100 + 1, 18, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 3, (left + width) * zoom / 100 - 1, 3, (left + width) * zoom / 100 - 1, 18, 0, 0);
    }
  else
    {
      drawline (XtDisplay (colindex), colpixmap, 0, left * zoom / 100 + 1, 2, left * zoom / 100 + 1, 19, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 3, (left + width) * zoom / 100, 2, (left + width) * zoom / 100, 19, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 3, left * zoom / 100 + 1, 19, (left + width) * zoom / 100 - 1, 19, 0, 0);
      drawline (XtDisplay (colindex), colpixmap, 2, left * zoom / 100 + 2, 2, (left + width) * zoom / 100 - 1, 2, 0, 0);
    }
  reactivate_zoom ();

  setfont2 (0, 1, 0, 3);
  drawstring (XtDisplay (colindex), colpixmap, 1, left + width / 2 - 5, 15 * 100 / zoom, label, strlen (label), 0, 0);
  return 0;
}

int
xdrawcell (int i, int j, int type, int noclear)
{
  Cell *cell = (Cell *) applicationcell (i, j, -1);
  return xdrawcell2 (cell, type, noclear);
}



int
xdrawcell2 (Cell * cell, int type, int noclear)
{
  int left, top, width, widthmax, height;
  char *buf = NULL;
  int i, j;


  if (FS->l1 == StBatch || FS->l1 == 0)
    return 0;

  if (cell == NULL)
    return -1;

  i = cell->r;
  j = cell->c;

  if (type == 2)
    numover = 0;

  if (cell == NULL && (type == 4 || type == 5))
    return 0;

  if (type == DRAW_FORCED)
    numover = 0;

  width = CW (AW, j + 1) - CW (AW, j);
  left = CW (AW, j) - CW (AW, AW->cc);
  height = LH (AW, i + 1) - LH (AW, i);
  top = LH (AW, i) - LH (AW, AW->ll);

  if (cell != NULL)
    buf = (char *) cell_gettext (cell);

  if (type == 2 && cell != NULL)	
    buf = (char *) cell_getformula (cell);

  if (type == 3)		
    {
      buf = (char *) GetEntryString (Letext);
    }

  widthmax = width;
  if (buf != NULL)
    {
      if (type == 3 || type == 2 || (cell_getrig (cell) == 0))
	widthmax = checkwidth (buf, width, cell, i, j, type);
      if (type == 2)
	{
	  left += 2;
	  top += 2;
	  width -= 4;
	  height -= 4;
	}

    }
  xdrawrrect (left, top, widthmax, height, type, cell);

  if (buf != NULL)
    xdrawstring (buf, left, top, width, widthmax, height, type, cell);

  if (!noclear)			
    cleararea (dpy, AMwin, left, top, widthmax + 1, height + 1, False);

  return 0;
}


static int i0;
static int j0;
static int li;
static int lj;

int 
initselectbox (int _i0, int _j0)
{
  i0 = _i0;
  j0 = _j0;
  drawselectbox (i0, j0, i0, j0);
  li = i0;
  lj = j0;
  return 0;
}


int 
extendselectbox (int i, int j)
{
  int di = i - li;
  int dj = j - lj;
  if (!(di) && !(dj))
    return -1;
  set_visible (i, j);
  copypix ("extendselectbox");
  drawselectbox (i0, j0, i, j);
  return 0;
}

int 
drawselectbox (int i1, int j1, int i2, int j2)
{
  int x1, y1, x2, y2;
  double fact = 100.0 / AW->zoom;
  if (i2 >= i1 && j2 >= j1)
    {
      i2++;
      j2++;
    }
  if (i2 < i1 && j2 >= j1)
    {
      j2++;
      i1++;
    }
  if (i2 >= i1 && j2 < j1)
    {
      i2++;
      j1++;
    }
  if (i2 < i1 && j2 < j1)
    {
      i1++;
      j1++;
    }
  ijtoxy (i1, j1, &x1, &y1);
  ijtoxy (i2, j2, &x2, &y2);

  if (x1 < 0)
    x1 = 0;
  if (x2 < 0)
    x2 = 0;
  if (y1 < 0)
    y1 = 0;
  if (y2 < 0)
    y2 = 0;
  if (x1 > Width * fact)
    x1 = Width * fact;
  if (x2 > Width * fact)
    x2 = Width * fact;
  if (y1 > Height * fact)
    y1 = Height * fact;
  if (y2 > Height * fact)
    y2 = Height * fact;

  setlineattributes (dpy, 1, 3, LineDoubleDash, CapButt, JoinBevel);
  drawline (dpy, AMwin, 1, x1, y1, x2, y1, 0, 0);
  drawline (dpy, AMwin, 1, x2, y1, x2, y2 - 4, 0, 0);
  drawline (dpy, AMwin, 1, x2 - 4, y2, x1, y2, 0, 0);
  drawline (dpy, AMwin, 1, x1, y2, x1, y1, 0, 0);
  setlineattributes (dpy, 1, 3, LineSolid, CapButt, JoinBevel);
  drawline (dpy, AMwin, 1, x2 - 2, y2 + 2, x2 + 2, y2 + 2, 0, 0);
  drawline (dpy, AMwin, 1, x2 + 2, y2 - 2, x2 + 2, y2 + 4, 0, 0);
  setlineattributes (dpy, 1, 1, LineSolid, CapButt, JoinBevel);

  return 0;
}




int
xytoij (int x, int y, int *i, int *j)
{
  int jj = 0;
  int x1, x2, y1, y2;
  x += CW (AW, AW->cc);
  y += LH (AW, AW->ll);
  get_visible (&x1, &x2, &y1, &y2);
  while (x > CW (AW, jj))
    {
      jj++;
    }
  *j = jj - 1;
  jj = 0;
  while (y > LH (AW, jj))
    {
      jj++;
    }
  *i = jj - 1;

  if (*i < 1)
    *i = 1;
  if (*j < 1)
    *j = 1;
  if (*i > AW->nblin - 1)
    *i = AW->nblin - 1;
  if (*j > AW->nbcol - 1)
    *j = AW->nbcol - 1;

  if (x < x1 + CW (AW, 1))
    *j = 1;
  if (y < y1 + LH (AW, 1))
    *i = 1;

  return 1;
}

int
ijtoxy (int i, int j, int *x, int *y)
{
  if (AW == NULL)
    return -1;


  *x = CW (AW, j);
  *y = LH (AW, i);

  *x -= CW (AW, AW->cc);
  *y -= LH (AW, AW->ll);

  return 1;
}

int
absijtoxy (int i, int j, int *x, int *y)
{
  if (AW == NULL)
    return -1;


  *x = CW (AW, j);
  *y = LH (AW, i);

  
  
  
  
  return 1;
}


int
xytoclotherij (int x, int y, int *i, int *j)
{
  int jj = 0;
  x += CW (AW, AW->cc);
  y += LH (AW, AW->ll);
  while (x > CW (AW, jj))
    {
      jj++;
    }
  *j = jj - 1;
  if (CW (AW, jj) - x < x - CW (AW, jj - 1))
    *j = jj;
  jj = 0;
  while (y > LH (AW, jj))
    {
      jj++;
    }
  *i = jj - 1;
  if (LH (AW, jj) - y < y - LH (AW, jj - 1))
    *i = jj;

  if (*i < 1)
    *i = 1;
  if (*j < 1)
    *j = 1;
  if (*i > AW->nblin - 1)
    *i = AW->nblin - 1;
  if (*j > AW->nbcol - 1)
    *j = AW->nbcol - 1;
  
  return 1;
}




int
get_visible (int *x1, int *x2, int *y1, int *y2)
{
  *x1 = CW (AW, AW->cc);
  *y1 = LH (AW, AW->ll);
  *x2 = *x1 + Width * 100 / AW->zoom;
  *y2 = *y1 + Height * 100 / AW->zoom;
  return 0;
}

int
get_visible_cells (int *i1, int *j1, int *i2, int *j2)
{
  *i1 = AW->ll;
  *j1 = AW->cc;
  *i2 = *i1;
  *j2 = *j1;

  while (LH (AW, *i2) < LH (AW, AW->ll) + Height * 100 / AW->zoom && *i2 < AW->nblin)
    {
      (*i2)++;
    }

  while (CW (AW, *j2) < CW (AW, AW->cc) + Width * 100 / AW->zoom && *j2 < AW->nbcol)
    {
      (*j2)++;
    }
  return 0;
}



int
resizegra ()
{
  Graph *gr;
  gr = (Graph *) getlastgra ();
  freepixmap (Drawarea, gr->pixmap);
  gr->pixmap = createpixmap (Drawarea,
			     gr->w * gr->zoom / 100, gr->h * gr->zoom / 100);
  fillrectangle (dpy, gr->pixmap, 0, 0, 0, gr->w, gr->h, 0, 0, 0);
  return 0;
}

int
redrawbt (Button * btn)
{
  int x1, x2, y1, y2;

  x1 = btn->x1 - CW (AW, AW->cc);
  y1 = btn->y1 - LH (AW, AW->ll);
  x2 = btn->x2 - CW (AW, AW->cc);
  y2 = btn->y2 - LH (AW, AW->ll);
  drawbuttonup (dpy, DrawAreaPixmap, x1, y1, x2, y2, button_getlabel (btn), CW (AW, AW->cc), LH (AW, AW->ll));
  return 0;
}

int
redrawbtdown (Button * btn)
{
  int x1, x2, y1, y2;
  char *label;

  x1 = btn->x1 - CW (AW, AW->cc);
  y1 = btn->y1 - LH (AW, AW->ll);
  x2 = btn->x2 - CW (AW, AW->cc);
  y2 = btn->y2 - LH (AW, AW->ll);

  drawline (dpy, DrawAreaPixmap, 2, x1, y1, x2 - 1, y1, CW (AW, AW->cc), LH (AW, AW->ll));
  drawline (dpy, DrawAreaPixmap, 2, x1, y1, x1, y2, CW (AW, AW->cc), LH (AW, AW->ll));

  drawline (dpy, DrawAreaPixmap, 1, x1 + 1, y1 + 1, x2 - 1, y1 + 1, CW (AW, AW->cc), LH (AW, AW->ll));
  drawline (dpy, DrawAreaPixmap, 1, x1 + 1, y1 + 2, x1 + 1, y2 - 1, CW (AW, AW->cc), LH (AW, AW->ll));

  drawline (dpy, DrawAreaPixmap, 1, x2, y1, x2, y2, CW (AW, AW->cc), LH (AW, AW->ll));
  drawline (dpy, DrawAreaPixmap, 1, x1, y2, x2, y2, CW (AW, AW->cc), LH (AW, AW->ll));
  drawline (dpy, DrawAreaPixmap, 0, x2 - 1, y1, x2 - 1, y2 - 1, CW (AW, AW->cc), LH (AW, AW->ll));
  drawline (dpy, DrawAreaPixmap, 0, x1 + 1, y2 - 1, x2 - 1, y2 - 1, CW (AW, AW->cc), LH (AW, AW->ll));
  fillrectangle (dpy, DrawAreaPixmap, 2, x1 + 2, y1 + 2, x2 - x1 - 3, y2 - y1 - 3, CW (AW, AW->cc), LH (AW, AW->ll), 1);
  label = button_getlabel (btn);
  drawstring (dpy, DrawAreaPixmap, 1, x1 + 10, (y1 + y2) / 2, label, strlen (label), CW (AW, AW->cc), LH (AW, AW->ll));
  return 0;
}

int
redrawdr (Drawing * dr)
{
  int centerx, centery, width, height, a1 = 0, a2 = 0;
  int pi = 90 * 64;
  int x1, x2, y1, y2;

  x1 = dr->x1 - CW (AW, AW->cc);
  y1 = dr->y1 - LH (AW, AW->ll);
  x2 = dr->x2 - CW (AW, AW->cc);
  y2 = dr->y2 - LH (AW, AW->ll);


  switch (dr->type)
    {

    case LINE:
      {
	drawline (dpy, DrawAreaPixmap, 1, x1, y1, x2, y2, CW (AW, AW->cc), LH (AW, AW->ll));
	break;
      }
    case RECT:
      {
	drawline (dpy, DrawAreaPixmap, 1, x1, y1, x2, y1, CW (AW, AW->cc), LH (AW, AW->ll));
	drawline (dpy, DrawAreaPixmap, 1, x2, y1, x2, y2, CW (AW, AW->cc), LH (AW, AW->ll));
	drawline (dpy, DrawAreaPixmap, 1, x2, y2, x1, y2, CW (AW, AW->cc), LH (AW, AW->ll));
	drawline (dpy, DrawAreaPixmap, 1, x1, y2, x1, y1, CW (AW, AW->cc), LH (AW, AW->ll));
	break;
      }
    case ARC:
      {
	centerx = x1;
	centery = y1;
	width = 2 * abs (x1 - x2);
	height = 2 * abs (y1 - y2);

	if (x1 <= x2 && y1 <= y2)
	  {
	    a1 = 0;
	    a2 = pi;
	    centery += height / 2;
	  }
	if (x1 >= x2 && y1 <= y2)
	  {
	    a1 = -pi;
	    a2 = pi;
	    centerx -= width / 2;
	  }
	if (x1 >= x2 && y1 >= y2)
	  {
	    a1 = 2 * pi;
	    a2 = pi;
	    centery -= height / 2;
	  }
	if (x1 <= x2 && y1 >= y2)
	  {
	    a1 = pi;
	    a2 = pi;
	    centerx += width / 2;
	  }
	drawarc
	  (dpy, DrawAreaPixmap, 1, centerx - width / 2, centery - height / 2, width, height, a1, a2, CW (AW, AW->cc), LH (AW, AW->ll));
	break;
      }
    case CIRCLE:
      {
	centerx = (x1 + x2) / 2;
	centery = (y1 + y2) / 2;
	width = abs (x1 - x2);
	height = abs (y1 - y2);
	drawarc
	  (dpy, DrawAreaPixmap, 1, centerx - width / 2, centery - height / 2, width, height, 0, 360 * 64,
	   CW (AW, AW->cc), LH (AW, AW->ll));
	break;
      }
    }
  return 0;
}



Pixmap
createpixmapforgraph (Graph * gr)
{
  gr->pixmap = createpixmap (Drawarea, gr->w, gr->h);
  fillrectangle (dpy, gr->pixmap, 0, 0, 0, gr->w, gr->h, 0, 0, 0);
  return gr->pixmap;

}

Pixmap
getpixmap (Graph * gr, int *x, int *y, int *w, int *h)
{
  *x = gr->x;			
  *y = gr->y;

  *w = gr->w;
  *h = gr->h;
  return gr->pixmap;
}
