#ifndef UNSUPPORTED

/*  this two routines implements solid guessing. They are almost same. One
 *  caluclates lines, second rows.
 *
 *  The heruistic is as follows:
 *
 *  ---1------6------5-------  (vbuffu)
 *     |      |      |
 *  ===7======X======8=======  (vbuff1)
 *     |      |      |     
 *  ---2------3------4-------  (vbuffd)
 *  distdown  rx   distup
 *
 *  -- and | means calculated lines. == is current line, names are pointers to
 *  them. Note that naming is quite confusing, because it is same in lines and
 *  rows.
 *
 *  we do solid guessing as folows: 
 *  |distl-vbuff1| < range
 *  |distr-vbuff1| < range
 *  the distance of distup and distdown is not limited, because we already
 *  have exact enought guesses 3 and 6
 *
 *  points 1 2 3 4 5 6 8 must be the same (point 8 is not yet calculated)
 *
 */
static void
calcline (realloc_t * RESTRICT ry)
REGISTERS (3);
REGISTERS (3)
     static void calcline (realloc_t * RESTRICT ry)
{
  number_t y;
  int range = cfractalc.range;
  realloc_t *RESTRICT rx, *rend, *rend1, *ryl, *ryr;
  int distl, distr, distup, distdown;
  cpixel_t *RESTRICT vbuff, *RESTRICT vbuffu, *RESTRICT vbuffd;
  cpixeldata_t inset = (cpixeldata_t) cpalette.pixels[0];
  cpixeldata_t c;
  cppixel_t *vbuff1 = (cpixel_t **) cimage.currlines + (ry - czoomc.reallocy);
  assert (ry >= czoomc.reallocy);
  assert (ry < czoomc.reallocy + cimage.height);
  y = ry->possition;
  rend = ry - range - 1;
  if (czoomc.reallocy > rend)
    rend = czoomc.reallocy;
  for (ryl = ry - 1; rend <= ryl && ryl->dirty; ryl--);
  distl = (int) (ryl - ry);
  rend = ry + range;
  if (czoomc.reallocy + cimage.height < rend)
    rend = czoomc.reallocy + cimage.height;
  for (ryr = ry + 1; rend > ryr && ryr->dirty; ryr++);
  distr = (int) (ryr - ry);
  rend = czoomc.reallocy + cimage.height;
  if (ryr == czoomc.reallocy + cimage.height || ryl < czoomc.reallocy
      || ryr->dirty || ryl->dirty)
    {
      for (rx = czoomc.reallocx, vbuff = *vbuff1,
	   rend1 = czoomc.reallocx + cimage.width; rx < rend1; rx++)
	{
	  if (!rx->dirty)
	    {
	      STAT (tocalculate++);
	      p_set (vbuff,
		     (cpixeldata_t) calculate (rx->possition, y,
					       cfractalc.periodicity));
#ifdef DRAW
	      vga_setcolor (0xff0000);
	      vga_drawpixel (rx - czoomc.reallocx, ry - czoomc.reallocy);
#endif
	    }
	  p_inc (vbuff, 1);
	}
    }
  else
    {
      distup = INT_MAX / 2;
      distdown = 0;
      for (rx = czoomc.reallocx,
	   vbuff = vbuff1[0], vbuffu = vbuff1[distl], vbuffd = vbuff1[distr],
	   rend1 = czoomc.reallocx + cimage.width; rx < rend1; rx++)
	{
	  assert (rx < czoomc.reallocx + cimage.width);
	  assert (rx >= czoomc.reallocx);
	  if (!rx->dirty)
	    {
	      STAT (tocalculate++);
	      if (distdown <= 0)
		{
		  for (ryr = rx + 1; ryr < rend1 && ryr->dirty; ryr++);
		  distdown = (int) (ryr - rx);
		  if (ryr == rend1)
		    distdown = INT_MAX / 2;
		}
	      if (distdown < INT_MAX / 4 && distup < INT_MAX / 4 &&
		  (p_get (vbuffu) == (c = p_get (vbuffd)) &&
		   c == p_getp (vbuff, -distup) &&
		   c == p_getp (vbuffu, -distup) &&
		   c == p_getp (vbuffu, distdown) &&
		   c == p_getp (vbuffd, distdown) &&
		   c == p_getp (vbuffd, -distup)))
		{
		  p_set (vbuff, c);
		  STAT (avoided++);
		}
	      else
		{
		  if (cfractalc.periodicity &&
		      distdown < INT_MAX / 4 && distup < INT_MAX / 4 &&
		      (p_get (vbuffu) != inset &&
		       p_get (vbuffd) != inset &&
		       p_getp (vbuff, -distup) != inset &&
		       p_getp (vbuffu, -distup) != inset &&
		       p_getp (vbuffu, +distdown) != inset &&
		       p_getp (vbuffd, -distup) != inset &&
		       p_getp (vbuffd, +distdown) != inset))
		    p_set (vbuff,
			   (cpixeldata_t) calculate (rx->possition, y, 0));
		  else
		    p_set (vbuff,
			   (cpixeldata_t) calculate (rx->possition, y,
						     cfractalc.periodicity));
#ifdef DRAW
		  vga_setcolor (0xffffff);
		  vga_drawpixel (rx - czoomc.reallocx, ry - czoomc.reallocy);
#endif
		}
	      distup = 0;
	    }
	  p_inc (vbuff, 1);
	  p_inc (vbuffu, 1);
	  p_inc (vbuffd, 1);
	  distdown--;
	  distup++;
	}
    }
  ry->recalculate = 0;
  ry->dirty = 0;
}
static void
calccolumn (realloc_t * RESTRICT rx)
REGISTERS (3);
REGISTERS (3)
     static void calccolumn (realloc_t * RESTRICT rx)
{
  number_t x;
  int range = cfractalc.range;
  realloc_t *RESTRICT ry, *rend, *rend1, *rxl, *rxr;
  int pos, distl, distr, distup, distdown;
  cpixeldata_t c;
  cpixeldata_t inset = (cpixeldata_t) cpalette.pixels[0];
  cppixel_t *RESTRICT vbuff;
  pos = (int) (rx - czoomc.reallocx);
  assert (pos >= 0);
  assert (pos < cimage.width);
  rend = rx - range + 1;
  if (czoomc.reallocx > rend)
    rend = czoomc.reallocx;
  for (rxl = rx - 1; rend <= rxl && rxl->dirty; rxl--);
  distl = (int) (rx - rxl);
  rend = rx + range;
  if (czoomc.reallocx + cimage.width < rend)
    rend = czoomc.reallocx + cimage.width;
  for (rxr = rx + 1; rxr < rend && rxr->dirty; rxr++);
  distr = (int) (rxr - rx);
  x = rx->possition;
  rend = czoomc.reallocx + cimage.width;
  if (rxr >= czoomc.reallocx + cimage.width || rxl < czoomc.reallocx
      || rxr->dirty || rxl->dirty)
    {
      for (ry = czoomc.reallocy, vbuff =
	   (cppixel_t *) cimage.currlines, rend1 =
	   czoomc.reallocy + cimage.height; ry < rend1; ry++, vbuff++)
	{
	  if (!ry->dirty)
	    {
	      STAT (tocalculate++);
	      p_setp ((*vbuff), pos,
		      (cpixeldata_t) calculate (x, ry->possition,
						cfractalc.periodicity));
#ifdef DRAW
	      vga_setcolor (0xff0000);
	      vga_drawpixel (rx - czoomc.reallocx, ry - czoomc.reallocy);
#endif
	    }
	}
    }
  else
    {
      distl = pos - distl;
      distr = pos + distr;
      assert (distl >= 0);
      assert (distr < cimage.width);
      distup = INT_MAX / 2;
      distdown = 0;
      for (ry = czoomc.reallocy, vbuff =
	   (cppixel_t *) cimage.currlines, rend1 =
	   czoomc.reallocy + cimage.height; ry < rend1; ry++)
	{
	  /*if (ry->symto == -1) { */
	  assert (ry < czoomc.reallocy + cimage.height);
	  if (!ry->dirty)
	    {
	      STAT (tocalculate++);
	      if (distdown <= 0)
		{
		  for (rxr = ry + 1; rxr < rend1 && rxr->dirty; rxr++);
		  distdown = (int) (rxr - ry);
		  if (rxr == rend1)
		    distdown = INT_MAX / 2;
		}
	      if (distdown < INT_MAX / 4 && distup < INT_MAX / 4 &&
		  (p_getp (vbuff[0], distl) == (c = p_getp (vbuff[0], distr))
		   && p_getp (vbuff[-distup], distl) == c
		   && p_getp (vbuff[-distup], distr) == c
		   && p_getp (vbuff[-distup], pos) == c
		   && p_getp (vbuff[distdown], distr) == c
		   && p_getp (vbuff[distdown], distl) == c))
		{
		  STAT (avoided++);
		  p_setp (vbuff[0], pos, c);
		}
	      else
		{
		  if (cfractalc.periodicity &&
		      distdown < INT_MAX / 4 && distup < INT_MAX / 4 &&
		      (p_getp (vbuff[0], distl) != inset &&
		       p_getp (vbuff[0], distr) != inset &&
		       p_getp (vbuff[distdown], distr) != inset &&
		       p_getp (vbuff[distdown], distl) != inset &&
		       p_getp (vbuff[-distup], distl) != inset &&
		       p_getp (vbuff[-distup], pos) != inset &&
		       p_getp (vbuff[-distup], distr) != inset))
		    p_setp (vbuff[0], pos,
			    (cpixeldata_t) calculate (x, ry->possition, 0));
		  else
		    p_setp (vbuff[0], pos,
			    (cpixeldata_t) calculate (x, ry->possition,
						      cfractalc.periodicity));
#ifdef DRAW
		  vga_setcolor (0xffffff);
		  vga_drawpixel (rx - czoomc.reallocx, ry - czoomc.reallocy);
#endif
		}
	      distup = 0;
	    }
	  vbuff++;
	  distdown--;
	  distup++;
	}
    }
  rx->recalculate = 0;
  rx->dirty = 0;
}

static /*INLINE */ void
dosymetry2 (void /*@unused@ */ *data, struct taskinfo /*@unused@ */ *task,
	    int r1, int r2)
{
  cpixel_t **vbuff = (cpixel_t **) cimage.currlines;
  realloc_t *rx, *rend;
  cpixel_t **vend = (cpixel_t **) cimage.currlines + cimage.height;
  for (rx = czoomc.reallocx + r1, rend = czoomc.reallocx + r2; rx < rend;
       rx++)
    {
      assert (rx->symto >= 0 || rx->symto == -1);
      if (rx->symto >= 0)
	{
	  assert (rx->symto < cimage.width);
	  if (!czoomc.reallocx[rx->symto].dirty)
	    {
	      int pos = (int) (rx - czoomc.reallocx);
	      int pos1 = rx->symto;
	      vbuff = (cpixel_t **) cimage.currlines;
	      for (; vbuff < vend; vbuff++)
		p_copy (vbuff[0], pos, vbuff[0], pos1);
	      rx->dirty = 0;
	    }
	}
    }
}

#ifndef USE_i386ASM
/*
 * Fill - bitmap depended part.
 *
 * This function is called, when calculation was interrupted because of
 * timeout. It fills uncalculated rows by nearest one
 *
 * This function is very time critical in higher resultions I am shooting
 * for.
 */
#ifndef __GNUC__
#undef bpp1
#endif
#ifndef __i386__
#undef bpp1
#endif
#undef bpp1

static INLINE void
fillline (int line)
{
  register unsigned char *RESTRICT vbuff = cimage.currlines[line];
  CONST struct filltable *RESTRICT table = (struct filltable *) tmpdata;
  while (table->length)
    {
      register cpixeldata_t s = p_get ((cpixel_t *) (vbuff + table->from));
      register cpixel_t *vcurr = (cpixel_t *) (vbuff + table->to);
#ifdef bpp1
      memset (vcurr, s, table->length);
#else
      register cpixel_t *vend = (cpixel_t *) (vbuff + table->end);
      while (vcurr < vend)
	{
	  p_set (vcurr, s);
	  p_inc (vcurr, 1);
	}
#endif
      table++;
    }
}
#endif
#endif
#undef dosymetry2
#undef calcline
#undef calccolumn
#undef fillline
#undef rend
