Logo Search packages:      
Sourcecode: xaos version File versions  Download package

ui_helper.c

#include <config.h>
#ifndef _plan9_
#ifndef NO_MALLOC_H
#include <malloc.h>
#endif
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <errno.h>
#ifdef __EMX__
#include <float.h>
/*
   #ifndef M_PI
   #define M_PI 3.14159265358979323846
   #endif
 */
#endif
#else
#include <u.h>
#include <libc.h>
#include <ctype.h>
#endif
#include <fconfig.h>
#include <filter.h>
#include <ui_helper.h>
#include <plane.h>
#include "../include/timers.h"
#include <zoom.h>
#include <xmenu.h>
#include <xerror.h>
#include "autopilot.h"
#include "grlib.h"
#include "play.h"
#include <archaccel.h>

#ifdef HAVE_GETTEXT
#include <libintl.h>
#else
#define gettext(STRING) STRING
#endif

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#define WAITTIME  50000
#define WAITTIME1 200000
#define WAITTIME2 2000000
#define uih_palettechg(uih) if(!uih->recalculatemode&&uih->queue->palettechg!=NULL) uih->recalculatemode=UIH_PALETTEDRAW, uih->display=1
#include <misc-f.h>

static struct filter *uih_getinstance (CONST struct filteraction *a);
static void uih_destroyinstance (struct filter *f);
static int uih_require (struct filter *f, struct requirements *r);
static int uih_initialize (struct filter *f, struct initdata *i);
static CONST rgb_t uicolors[] = {
  {0, 0, 0},
  {255, 255, 255},
  {255, 65, 0},
  {64, 64, 64},
  {128, 128, 128},
  {128 + 64, 128 + 64, 128 + 64}
};
static CONST rgb_t uibwcolors[] = {
  {0, 0, 0},
  {255, 255, 255},
  {255, 255, 255},
  {255, 255, 255},
  {255, 255, 255},
  {255, 255, 255}
};

static CONST struct filteraction uih_filter = {
  "XaoS's user interface layer",
  "ui",
  0,
  uih_getinstance,
  uih_destroyinstance,
  NULL,
  uih_require,
  uih_initialize,
  convertupgeneric,
  convertdowngeneric,
  NULL
};

static uih_context *uih;
static int waitcount, waitcount1, waitcount2;

extern CONST struct filteraction interlace_filter, stereogram_filter,
  subwindow_filter, smalliter_filter, julia_filter, blur_filter, edge_filter,
  edge2_filter, rotate_filter, starfield_filter, truecolor_filter,
  fixedcolor_filter, bitmap_filter, emboss_filter, palette_filter,
  antialias_filter, threed_filter;

CONST struct filteraction *CONST uih_filters[MAXFILTERS] = {
  &edge_filter,
  &edge2_filter,
  &threed_filter,
  &starfield_filter,
  &stereogram_filter,
  &interlace_filter,
  &blur_filter,
  &emboss_filter,
  &palette_filter,
  &antialias_filter,
  &truecolor_filter,
  NULL
};

CONST int uih_nfilters = 11;

static void
uih_invalidatepos (uih_context * uih)
{
  uih->xcenterm = INT_MAX;
  uih->xcenterm = INT_MAX;
}
static void
uih_finishpalette (struct uih_context *uih)
{
  if (uih->image->palette->flags & UNFINISHED)
    {
      if (uih->image->palette->allocfinished != NULL)
      uih->image->palette->allocfinished (uih->image->palette);
      uih->image->palette->flags &= ~UNFINISHED;
    }
}

static void
uih_getcoord (uih_context * uih, int x, int y, number_t * xr, number_t * yr)
{
  uih->uifilter->action->convertdown (uih->uifilter, &x, &y);
  *xr =
    (((number_t)
      (uih->fcontext->rs.nc +
       (x) * ((uih->fcontext->rs.mc - uih->fcontext->rs.nc) /
            (number_t) uih->zengine->image->width))));
  *yr =
    (((number_t)
      (uih->fcontext->rs.ni +
       (y) * ((uih->fcontext->rs.mi - uih->fcontext->rs.ni) /
            (number_t) uih->zengine->image->height))));
  rotateback (*(uih->fcontext), *xr, *yr);
}

int
uih_enablefilter (uih_context * c, int n)
{
  if (c->filter[n] == NULL)
    {
      struct filter *f, *f1;
      int i, wascycling = 0;
      if (c->cycling)
      uih_cycling_off (c), wascycling = 1;
      f = uih_filters[n]->getinstance (uih_filters[n]);
      f1 = c->uifilter;
      if (c->fixedcolor != NULL)
      f1 = c->fixedcolor;
      for (i = MAXFILTERS - 1; i > n; i--)
      {
        if (c->filter[i])
          f1 = c->filter[i];
      }
      uih_newimage (c);
      insertfilter (f, f1);
      if (!initqueue (c->queue))
      {
        c->ddatalost = 1;
        removefilter (f);
        f->action->destroyinstance (f);
        if (!initqueue (c->queue))
          {
            x_fatalerror
            ("Fatal error. Can not continue - initialization of queue can not be performed eigher with or without filter");
          }
        if (wascycling)
          uih_cycling_on (c);
        if (!strcmp ("palette", uih_filters[n]->shortname))
          {
            uih_updatemenus (c, "palettef");
          }
        else
          {
            uih_updatemenus (c, uih_filters[n]->shortname);
          }
        return 0;
      }
      else
      c->filter[n] = f;
      if (wascycling)
      uih_cycling_on (c);
      if (!strcmp ("palette", uih_filters[n]->shortname))
      {
        uih_updatemenus (c, "palettef");
      }
      else
      {
        uih_updatemenus (c, uih_filters[n]->shortname);
      }
      return 1;
    }
  return 0;
}

void
uih_disablefilter (uih_context * c, int n)
{
  if (n == c->aliasnum)
    return;
  if (c->filter[n] != NULL)
    {
      int wascycling = 0;
      struct filter *f = c->filter[n];
      if (c->cycling)
      uih_cycling_off (c), wascycling = 1;
      uih_newimage (c);
      removefilter (f);
      if (!initqueue (c->queue))
      {
        struct filter *f1;
        int i;
        c->ddatalost = 1;
        f1 = c->uifilter;
        if (c->fixedcolor != NULL)
          f1 = c->fixedcolor;
        for (i = MAXFILTERS - 1; i > n; i--)
          {
            if (c->filter[i])
            f1 = c->filter[i];
          }
        insertfilter (f, f1);
        if (!initqueue (c->queue))
          {
            x_fatalerror ("Fatal error. Can not continue");
          }
      }
      else
      f->action->destroyinstance (f), c->filter[n] = NULL;
      if (wascycling)
      uih_cycling_on (c);
      if (!strcmp ("palette", uih_filters[n]->shortname))
      {
        uih_updatemenus (c, "palettef");
      }
      else
      {
        uih_updatemenus (c, uih_filters[n]->shortname);
      }
    }
}
int
uih_fastrotateenable (uih_context * c)
{
  int wascycling = 0;
  if (c->juliamode)
    uih_disablejulia (c);
  if (!c->fastrotate && !c->juliamode)
    {
      if (c->cycling)
      uih_cycling_off (c), wascycling = 1;
      c->rotatef = rotate_filter.getinstance (&rotate_filter);
      if (c->rotatef == NULL)
      goto end;
      uih_newimage (c);
      addfilter (c->rotatef, c->zengine);
      if (!initqueue (c->queue))
      goto end2;
      if (wascycling)
      uih_cycling_on (c);
      c->fastrotate = 1;
      return 1;
    }
  return 0;
end2:
  removefilter (c->rotatef);
  initqueue (c->queue);
  c->rotatef->action->destroyinstance (c->rotatef);
end:
  if (wascycling)
    uih_cycling_on (c);
  return 0;
}

void
uih_fastrotatedisable (uih_context * c)
{
  if (c->fastrotate)
    {
      int wascycling = 0;
      uih_rotatemode (c, ROTATE_NONE);
      if (c->cycling)
      uih_cycling_off (c), wascycling = 1;
      c->fastrotate = 0;
      removefilter (c->rotatef);
      initqueue (c->queue);
      c->rotatef->action->destroyinstance (c->rotatef);
      uih_newimage (c);
      if (wascycling)
      uih_cycling_on (c);
    }
}
void
uih_rotate (struct uih_context *c, int n)
{
  if (!n)
    uih_fastrotate (c, 0);
  else
    {
      uih_fastrotate (c, 1);
      uih_rotatemode (c, n);
    }
}
static void
uih_fixedcolordisable (uih_context * c)
{
#ifdef SCONVERTORS
  if (c->fixedcolor != NULL)
    {
      int wascycling = 0;
      if (c->cycling)
      uih_cycling_off (c), wascycling = 1;
      initqueue (c->queue);
      removefilter (c->fixedcolor);
      initqueue (c->queue);
      c->fixedcolor->action->destroyinstance (c->fixedcolor);
      c->fixedcolor = NULL;
      uih_newimage (c);
      if (wascycling)
      uih_cycling_on (c);
    }
#endif
}
static int
uih_fixedcolorenable (uih_context * c)
{
#ifdef SCONVERTORS
  CONST struct filteraction *fa = NULL;
  int wascycling = 0;
  preallocpalette (c->palette);
  switch (c->image->palette->type)
    {
#ifdef SFIXEDCOLOR
    case FIXEDCOLOR:
      fa = &fixedcolor_filter;
      break;
#endif
#ifdef SBITMAPS
    case LBITMAP:
    case MBITMAP:
    case LIBITMAP:
    case MIBITMAP:
      fa = &bitmap_filter;
      break;
#endif
    default:
      x_fatalerror ("Unsupported image type. Recompile XaoS");
    }
  if (c->fixedcolor != NULL && c->fixedcolor->action != fa)
    uih_fixedcolordisable (c);
  if (c->fixedcolor == NULL)
    {
      if (c->cycling)
      uih_cycling_off (c), wascycling = 1;
      c->fixedcolor = fa->getinstance (fa);
      if (c->fixedcolor == NULL)
      goto end;
      uih_newimage (c);
      addfilter (c->fixedcolor, c->uifilter->previous);
      if (!initqueue (c->queue))
      goto end2;
      if (wascycling)
      uih_cycling_on (c);
      return 1;
    }
  return 0;
end2:
  removefilter (c->fixedcolor);
  c->fixedcolor->action->destroyinstance (c->fixedcolor);
  c->fixedcolor = NULL;
  initqueue (c->queue);
end:
  if (wascycling)
    uih_cycling_on (c);
  return 0;
#else
  x_fatalerror ("Fixed color not supported, please recompile XaoS");
  return 0;
#endif
}

int
uih_fastrotate (uih_context * c, int mode)
{
  if (mode)
    return (uih_fastrotateenable (c));
  uih_fastrotatedisable (c);
  return 1;
}

void
uih_angle (uih_context * c, number_t angle)
{
  if (angle != c->fcontext->angle)
    {
      if (!c->fastrotate)
      {
        c->fcontext->version++;
        uih_newimage (c);
      }
      c->fcontext->angle = angle;
      uih_animate_image (c);
    }
}
void
uih_rotatemode (uih_context * c, int mode)
{
  CONST char *names[] = {
    "norotate",
    "mouserotate",
    "controtate"
  };
  if (c->fastrotate)
    {
      if (c->rotatemode != mode)
      {
        c->rotatemode = mode;
        if (mode == ROTATE_CONTINUOUS)
          tl_reset_timer (c->doittimer);
        uih_updatemenus (c, names[mode]);
      }
    }
}

int
uih_enablejulia (uih_context * c)
{
  int wascycling = 0;
  if (!c->juliamode && c->fcontext->mandelbrot
      /*&&c->fcontext->currentformula->calculate_julia != NULL */ )
    {
      struct filter *addf = c->zengine;
      uih_newimage (c);
      if (c->fastrotate)
      uih_fastrotatedisable (c);
      if (c->cycling)
      uih_cycling_off (c), wascycling = 1;
      if (c->fcontext->currentformula->calculate_julia == NULL
        || c->fcontext->slowmode)
      c->julia = zoom_filter.getinstance (&zoom_filter);
      else
      c->julia = julia_filter.getinstance (&julia_filter);
      if (c->julia == NULL)
      goto end;

      c->subwindow = subwindow_filter.getinstance (&subwindow_filter);
      if (c->subwindow == NULL)
      goto end2;
      if (c->fcontext->currentformula->calculate_julia != NULL
        && !c->fcontext->slowmode)
      {
        c->smalliter = smalliter_filter.getinstance (&smalliter_filter);
        if (c->smalliter == NULL)
          goto end3;
      }
      else
      c->smalliter = NULL;
      addfilter (c->subwindow, addf);
      if (c->fcontext->currentformula->calculate_julia != NULL
        && !c->fcontext->slowmode)
      {
        addfilter (c->smalliter, addf);
      }
      addfilter (c->julia, addf);
      subwindow_setsecond (c->subwindow, addf);
      if (!initqueue (c->queue))
      goto end4;
      if (c->fcontext->currentformula->calculate_julia == NULL
        || c->fcontext->slowmode)
      c->juliamode = 2;
      else
      c->juliamode = 1;
      uih_updatemenus (c, "fastjulia");
      return 1;
    }
  uih_updatemenus (c, "fastjulia");
  return 0;
end4:;
  removefilter (c->subwindow);
  removefilter (c->julia);
  if (c->smalliter != NULL)
    removefilter (c->smalliter);
  initqueue (c->queue);
end3:;
  c->smalliter->action->destroyinstance (c->smalliter);
end2:;
  c->subwindow->action->destroyinstance (c->subwindow);
end:;
  c->julia->action->destroyinstance (c->julia);
  if (wascycling)
    uih_cycling_on (c);
  uih_updatemenus (c, "fastjulia");
  return 0;
}

void
uih_disablejulia (uih_context * c)
{
  int wascycling = 0;
  if (c->juliamode)
    {
      uih_newimage (c);
      c->fcontext->version++;
      if (c->cycling)
      uih_cycling_off (c), wascycling = 1;
      removefilter (c->subwindow);
      removefilter (c->julia);
      if (c->smalliter != NULL)
      removefilter (c->smalliter);
      initqueue (c->queue);
      if (c->smalliter != NULL)
      c->smalliter->action->destroyinstance (c->smalliter);
      c->subwindow->action->destroyinstance (c->subwindow);
      c->julia->action->destroyinstance (c->julia);
      if (wascycling)
      uih_cycling_on (c);
      c->juliamode = 0;
      uih_updatemenus (c, "fastjulia");
    }
}
int
uih_setjuliamode (uih_context * c, int mode)
{
  if (mode)
    return uih_enablejulia (c);
  uih_disablejulia (c);
  return 1;
}

void
uih_rotationspeed (uih_context * c, number_t speed)
{
  c->rotationspeed = speed;
}
static void
uih_cyclinghandler (void *userdata, int n)
{
  struct uih_context *uih = (struct uih_context *) userdata;
  int direct;
  if (uih->zengine->fractalc->palette != NULL &&
      uih->zengine->fractalc->palette->cyclecolors == NULL)
    return;
  direct = uih->direction * uih->cyclingdirection * n;
  if (direct > 0)
    direct %= uih->zengine->fractalc->palette->size - 1;
  else
    direct = -((-direct) % (uih->zengine->fractalc->palette->size - 1));
  if (direct)
    {
      uih->paletteshift += direct;
      while (uih->paletteshift < 0)
      uih->paletteshift += uih->zengine->fractalc->palette->size - 1;
      uih->paletteshift =
      uih->paletteshift % (uih->zengine->fractalc->palette->size - 1);
      uih->zengine->fractalc->palette->cyclecolors (uih->zengine->
                                        fractalc->palette,
                                        direct);
      if (uih->flags & UPDATE_AFTER_PALETTE
        && (!uih->play || !uih->nonfractalscreen))
      uih->display = 1;
      uih_palettechg (uih);
    }
}
void
uih_cycling_off (struct uih_context *c)
{
  if (c->cycling)
    {
      tl_free_timer (c->cyclingtimer);
      c->cycling = 0;
      uih_updatemenus (c, "cycling");
      uih_updatemenus (c, "rcycling");
    }
}
void
uih_display (struct uih_context *c)
{
  c->display = 1;
  c->nonfractalscreen = 0;
  if (c->clearscreen)
    c->clearscreen = 0;
  c->displaytext = 0;
  c->nletters = 0;
  c->display = 1;
  if (c->text[0] != NULL)
    free (c->text[0]), c->text[0] = NULL;
  if (c->text[1] != NULL)
    free (c->text[1]), c->text[1] = NULL;
  if (c->text[2] != NULL)
    free (c->text[2]), c->text[2] = NULL;
  if (c->play)
    uih_clear_lines (c);
}

void
uih_cycling_stop (struct uih_context *c)
{
  if (c->cycling && !c->stopped)
    {
      tl_remove_timer (c->cyclingtimer);
      c->stopped = 1;
    }
}
void
uih_cycling_continue (struct uih_context *c)
{
  if (c->cycling && c->stopped)
    {
      c->stopped = 0;
      tl_add_timer (syncgroup, c->cyclingtimer);
    }
}
void
uih_loadfile (struct uih_context *c, xio_constpath d)
{
  xio_file f;
  f = xio_ropen (d);
  if (f == NULL)
    {
#ifdef _plan9_
      uih_error (c, (char *) errstr);
#else
      uih_error (c, strerror (errno));
#endif
      return;
    }
  uih_load (c, f, d);
  return;
}

void
uih_loadstr (struct uih_context *c, CONST char *data)
{
  xio_file f;
  f = xio_strropen (data);
  uih_load (c, f, "");
  return;
}

void
uih_playstr (struct uih_context *c, CONST char *data)
{
  xio_file f;
  f = xio_strropen (mystrdup (data));
  uih_replayenable (c, f, "", 1);
  return;
}

void
uih_recalculate (struct uih_context *c)
{
  c->fcontext->version++;
  uih_newimage (c);
}

void
uih_playfile (struct uih_context *c, xio_constpath d)
{
  xio_file f;
  if (c->play)
    uih_replaydisable (c);
  f = xio_ropen (d);
  if (f == NULL)
    {
#ifdef _plan9_
      uih_error (c, (char *) errstr);
#else
      uih_error (c, strerror (errno));
#endif
      return;
    }
  uih_replayenable (c, f, d, 1);
  return;
}

void
uih_playtutorial (struct uih_context *c, CONST char *name)
{
  xio_pathdata tmp;
  xio_file f = XIO_FAILED;

  f = xio_gettutorial (name, tmp);
  if (f == NULL)
    {
      uih_error (c, gettext ("Tutorial files not found. Reinstall XaoS"));
      return;
    }
  uih_replayenable (c, f, tmp, 1);
  if (c->passfunc != NULL)
    {
      c->passfunc (c, 1, gettext ("Preparing first image"), 0);
    }
}
void
uih_loadexample (struct uih_context *c)
{
  xio_pathdata name;
  xio_file f = xio_getrandomexample (name);
  c->errstring = NULL;
  if (f == NULL)
    {
      uih_error (c, gettext ("Could not open examples"));
      return;
    }
  uih_load (c, f, name);
  if (c->errstring == NULL)
    {
      char s[256];
      sprintf (s, gettext ("File %s loaded."), name);
      uih_message (c, s);
    }
}
void
uih_savepngfile (struct uih_context *c, xio_constpath d)
{
  CONST char *s;
  if (c->passfunc != NULL)
    {
      c->passfunc (c, 1, gettext ("Saving image..."), 0);
    }
  if (c->recalculatemode)
    {
      uih_newimage (c);
      uih_clearwindows (c);
      uih_do_fractal (c);
    }
  if (c->interrupt)
    {
      uih_message (c, gettext ("Save interrupted"));
      return;
    }
  c->errstring = NULL;
  s = uih_save (c, d);
  if (s != NULL)
    uih_error (c, s);
  if (c->errstring == NULL)
    {
      char s[256];
      sprintf (s, gettext ("File %s saved."), d);
      uih_message (c, s);
    }
}
void
uih_saveposfile (struct uih_context *c, xio_constpath d)
{
  xio_file f;
  c->errstring = NULL;
  f = xio_wopen (d);
  if (f == XIO_FAILED)
    {
      uih_error (c, gettext ("Can not open file"));
      return;
    }
  uih_save_possition (c, f, UIH_SAVEPOS);
  if (c->errstring == NULL)
    {
      char s[256];
      sprintf (s, gettext ("File %s saved."), d);
      uih_message (c, s);
    }
}
char *
uih_savepostostr (struct uih_context *c)
{
  xio_file f;
  c->errstring = NULL;
  f = xio_strwopen ();
  uih_save_possition (c, f, UIH_SAVEPOS);
  return (xio_getstring (f));
}

void
uih_saveundo (struct uih_context *c)
{
  xio_file f;
  if (c->play)
    return;
  c->errstring = NULL;
  if (c->undo.undos[c->undo.last])
    free (c->undo.undos[c->undo.last]);
  f = xio_strwopen ();
  uih_save_possition (c, f, UIH_SAVEPOS);
  c->undo.undos[c->undo.last] = xio_getstring (f);
  c->undo.last = (c->undo.last + 1) % UNDOLEVEL;
}

void
uih_undo (struct uih_context *c)
{
  xio_file f;
  int pos = c->undo.last - 2;
  if (pos < 0)
    pos = UNDOLEVEL + pos;
  if (c->undo.undos[pos])
    {
      f = xio_strropen (c->undo.undos[pos]);
      c->undo.undos[pos] = NULL;
      c->undo.last = pos;
      uih_load (c, f, "");
    }
}
void
uih_redo (struct uih_context *c)
{
  xio_file f;
  int pos = c->undo.last;
  if (c->undo.undos[pos])
    {
      f = xio_strropen (c->undo.undos[pos]);
      c->undo.undos[pos] = NULL;
      c->undo.last = pos;
      uih_load (c, f, "");
    }
}
extern xio_pathdata configfile;
void
uih_savecfg (struct uih_context *c)
{
  xio_file f;
  c->errstring = NULL;
  f = xio_wopen (configfile);
  if (f == XIO_FAILED)
    {
      uih_message (c, (char *) xio_errorstring ());
      return;
    }
  uih_save_possition (c, f, UIH_SAVEALL);
  if (c->errstring == NULL)
    {
      char s[256];
      sprintf (s, gettext ("File %s saved."), configfile);
      uih_message (c, s);
    }
}
void
uih_saveanimfile (struct uih_context *c, xio_constpath d)
{
  xio_file f;
  c->errstring = NULL;
  if (c->save)
    {
      uih_save_disable (c);
      uih_updatemenus (c, "record");
      return;
    }
  f = xio_wopen (d);
  if (f == XIO_FAILED)
    {
      uih_message (c, (char *) xio_errorstring ());
      return;
    }
  uih_save_enable (c, f, UIH_SAVEANIMATION);
  if (c->errstring == NULL)
    {
      char s[256];
      sprintf (s, gettext ("Recording to file %s enabled."), d);
      uih_message (c, s);
    }
  uih_updatemenus (c, "record");
}







CONST char *
uih_save (struct uih_context *c, xio_constpath filename)
{
  FILE *f;
  CONST char *r;
  uih_cycling_stop (c);
  uih_stoptimers (c);
  uih_clearwindows (c);
  f = fopen (filename, "wb");
  r = writepng (f, c->queue->saveimage);
  uih_cycling_continue (c);
  uih_resumetimers (c);
  return (r);
}

void
uih_setcycling (struct uih_context *c, int speed)
{
  c->cyclingspeed = speed;
  if (c->cyclingspeed < 0)
    c->direction = -1;
  else
    c->direction = 1;
  if (c->cycling)
    {
      if (c->cyclingspeed)
      tl_set_interval (c->cyclingtimer,
                   1000000 / c->cyclingspeed * c->direction);
      else
      tl_set_interval (c->cyclingtimer, 1000000 * 100);
    }
}
int
uih_cycling_on (struct uih_context *c)
{
  if (c->zengine->fractalc->palette != NULL &&
      c->zengine->fractalc->palette->cyclecolors != NULL)
    {
      c->cycling = 1;
      tl_update_time ();
      c->cyclingtimer = tl_create_timer ();
      uih_emulatetimers (c);
      uih_setcycling (c, c->cyclingspeed);
      tl_set_multihandler (c->cyclingtimer, uih_cyclinghandler, c);
      tl_add_timer (syncgroup, c->cyclingtimer);
    }
  else
    {
      uih_updatemenus (c, "cycling");
      uih_updatemenus (c, "rcycling");
      return 0;
    }
  uih_updatemenus (c, "cycling");
  uih_updatemenus (c, "rcycling");
  return 1;
}

int
uih_cycling (struct uih_context *uih, int mode)
{
  if (mode)
    return (uih_cycling_on (uih));
  uih_cycling_off (uih);
  return 1;
}



static void
uih_waitfunc (struct filter *f)
{
  int l;
  tl_process_group (syncgroup, NULL);
  l = tl_lookup_timer (uih->calculatetimer);
  if (uih->interrupt)
    f->interrupt = 1, uih->endtime = l;
  if (uih->interruptiblemode)
    {
      if (f->incalculation && !uih->starttime)
      uih->starttime = l;
      else if (uih->starttime && !f->incalculation && !uih->endtime)
      uih->endtime = l;
      if ((uih->maxtime && l > uih->maxtime && f->readyforinterrupt)
        || uih->interrupt)
      f->interrupt = 1, uih->endtime = l;
    }
  if ((l) > (waitcount + 1) * WAITTIME)
    {
      int display = 0;
      if (!uih->interruptiblemode && l > (waitcount1 + 1) * WAITTIME1)
      {
        display = 1;
        waitcount1 = l / WAITTIME1;
      }
      if (f->image == uih->image && !uih->interruptiblemode
        && l > (waitcount2 + 1) * WAITTIME2)
      {
        if (!uih->play)
          uih->display = 1, uih_finishpalette (uih), display = 1;
        waitcount2 = l / WAITTIME2;
      }
      if (uih->passfunc != NULL)
      {
        f->interrupt |=
          uih->passfunc (uih, display, f->pass,
                     (float) (f->max ? f->pos * 100.0 /
                            f->max : 100.0));
        uih->display = 0;
      }
      waitcount = l / WAITTIME;
    }
  uih_clearwindows (uih);
}

void
uih_do_fractal (uih_context * c)
{
  int flags;
  int time;

  c->interrupt = 0;
  c->display = 0;
  uih = c;
  if (c->juliamode && !c->fcontext->mandelbrot)
    {
      uih_disablejulia (c);
    }
  if ((c->juliamode == 1
       && (c->fcontext->currentformula->calculate_julia == NULL
         || c->fcontext->slowmode)) || (c->juliamode == 2
                                && c->fcontext->
                                currentformula->calculate_julia !=
                                NULL && !c->fcontext->slowmode))
    {
      uih_disablejulia (c);
      uih_enablejulia (c);
      c->fcontext->version++;
    }

  tl_update_time ();
  if (c->recalculatemode < c->fastmode && c->emulator == NULL
      && !c->fixedstep)
    c->interruptiblemode = 1;
  else
    c->interruptiblemode = 0;
  if (!c->interruptiblemode && c->recalculatemode > UIH_ANIMATION)
    {
      if (c->longwait != NULL)
      c->longwait (c);
      uih_stoptimers (c);
    }

  tl_update_time ();
  tl_reset_timer (c->calculatetimer);
  c->starttime = 0;
  c->endtime = 0;
  waitcount = tl_lookup_timer (c->calculatetimer) / WAITTIME + 2;
  waitcount1 = tl_lookup_timer (c->calculatetimer) / WAITTIME1 + 1;
  waitcount2 = tl_lookup_timer (c->calculatetimer) / WAITTIME2 + 1;
#ifdef _UNDEFINED_
  waitcount = 2;
  waitcount1 = 1;
  waitcount2 = 1;
#endif
  c->incalculation = 1;

  if (!(c->flags & ROTATE_INSIDE_CALCULATION))
    uih_cycling_stop (c);

  time = tl_lookup_timer (c->doittimer);
  if (c->rotatemode == ROTATE_CONTINUOUS)
    {
      c->fcontext->angle += c->rotationspeed * time / 1000000.0;
    }

  tl_reset_timer (c->doittimer);
  c->indofractal = 1;
  if (c->recalculatemode < UIH_PALETTEDRAW)
    {
      if (c->queue->palettechg != NULL)
      flags =
        c->queue->palettechg->action->doit (c->queue->palettechg,
                                    PALETTEONLY, 0);
      else
      flags = CHANGED;
    }
  else
    flags =
      c->uifilter->previous->action->doit (c->uifilter->previous,
                                 c->interruptiblemode ?
                                 INTERRUPTIBLE : 0, time);
  c->indofractal = 0;

  if (!(c->flags & ROTATE_INSIDE_CALCULATION))
    uih_cycling_continue (c);

  c->dirty = 0;
  if (c->inanimation)
    c->inanimation--;
  c->ddatalost = 0;
  c->recalculatemode = 0;

  if (flags & ANIMATION)
    c->fastanimation = 1;
  else
    c->fastanimation = 0;
  if (c->emulator)
    c->inanimation = 1;
  if (flags & (ANIMATION | UNCOMPLETTE)
      || (c->rotatemode == ROTATE_CONTINUOUS))
    {
      tl_resume_timer (c->doittimer);
      c->uncomplette = 1;
      c->inanimation = 2;
      if (flags & UNCOMPLETTE)
      c->recalculatemode = UIH_ANIMATION;
      else
      c->recalculatemode = UIH_FILTERANIMATION;
      c->display = 1;
    }
  else
    {
      tl_stop_timer (c->doittimer);
      c->uncomplette = 0;
    }
  if ((flags & CHANGED) && (!c->play || !c->nonfractalscreen))
    {
      c->display = 1;
      if (flags & INEXACT)
      c->dirty = 1;
    }
  else
    c->incalculation = 0;
  uih_callcomplette (c);
  if (c->autopilot)
    c->inanimation = 1;
}

void
uih_prepare_image (uih_context * c)
{
  if (c->play)
    uih_update_lines (c);
  if (c->display)
    {
      uih_clearwindows (c);
      xprepareimage (c->image);
      if (uih_needrecalculate (c))
      uih_do_fractal (c);
    }
}
void
uih_callcomplette (uih_context * c)
{
  if (!c->uncomplette && !c->display && !c->recalculatemode && !c->inanimation
      && c->complettehandler != NULL)
    {
      c->complettehandler (c->handlerdata);
    }
}
void
uih_setcomplettehandler (uih_context * c, void (h) (void *), void *d)
{
  c->complettehandler = h;
  c->handlerdata = d;
}

void
uih_letterspersec (uih_context * c, int n)
{
  if (n < 1)
    n = 1;
  c->letterspersec = n;
}

double
uih_displayed (uih_context * c)
{
  int drawingtime;
  uih_finishpalette (c);
  if (c->indofractal)
    return 0;                 /*image is currently calculating */
  if (c->recalculatemode)
    c->display = 1;
  else
    c->display = 0;
  tl_update_time ();
  uih_resumetimers (c);
  c->nonfractalscreen = 0;
  c->nletters = 0;
  if (c->incalculation)
    {
      c->incalculation = 0;
      drawingtime = tl_lookup_timer (c->calculatetimer);
      if (c->emulator)
      drawingtime = 0;
      if (c->lasttime == -1
        || (drawingtime && c->lasttime
            && (drawingtime / c->lasttime < 0.2
              || drawingtime / c->lasttime > 4)))
      c->lasttime = drawingtime;
      c->lasttime = (c->lasttime * 30 + drawingtime) / 31;
      c->lastspeed = c->lasttime ? 1000000.0 / c->lasttime : 100.0;
      if (c->interruptiblemode)
      {
        int i;
        int time1, time;
        time1 = drawingtime;
        time1 -= c->endtime;
        time = (drawingtime - c->endtime) + c->starttime;
        if (c->times[0][0] == -1)
          {
            for (i = 0; i < AVRGSIZE; i++)
            c->times[0][i] = time, c->times[1][i] = time1;
            c->count[0] = time * AVRGSIZE, c->count[1] = time1 * AVRGSIZE;
          }
        c->timespos = (c->timespos + 1) % AVRGSIZE;
        c->count[0] += time - c->times[0][c->timespos];
        c->count[1] += time1 - c->times[1][c->timespos];
        c->times[0][c->timespos] = time;
        c->times[1][c->timespos] = time1;
        c->maxtime = (c->count[0] * 5) / AVRGSIZE;
        if (c->step || c->pressed
            || (c->play
              && (c->playc->morph || c->playc->morphangle
                  || c->playc->morphjulia || c->playc->lines.morphing))
            || (c->rotatemode == ROTATE_CONTINUOUS) || c->fastanimation)
          {
            if (c->maxtime > 1000000 / 25)
            c->maxtime = c->count[0] * 3 / AVRGSIZE;
            if (c->maxtime > 1000000 / 15)
            c->maxtime = 1000000 / 15;
          }
        else
          {
            c->maxtime = 1000000 / 3;
          }
        if (c->maxtime < 1000000 / 30)
          c->maxtime = 1000000 / 30;
        c->maxtime -= c->count[1] / AVRGSIZE;
        if (c->maxtime < c->starttime + 10000)
          c->maxtime = c->starttime + 10000;
      }
    }
  uih_callcomplette (c);
  return (c->lastspeed);
}

void
uih_text (uih_context * c, CONST char *text)
{
  int i, l;
  c->display = 1;
  if (c->text[c->ytextpos])
    free (c->text[c->ytextpos]);
  c->textpos[c->ytextpos] = c->xtextpos;
  c->textcolor[c->ytextpos] = c->color;
  c->displaytext |= 1 << c->ytextpos;
  c->text[c->ytextpos] = mystrdup (text);
  l = (int) strlen (text);
  c->todisplayletters = 0;
  for (i = 0; i < l; i++)
    {
      if (isalnum (text[i]))
      c->todisplayletters++;
      if (text[i] == '-')
      c->todisplayletters += 3;
      if (text[i] == '.')
      c->todisplayletters += 2;
    }
  c->step = 0;
}

void
uih_clearscreen (uih_context * c)
{
  c->clearscreen = 1;
  if (c->save)
    c->savec->clearscreen = 1;
  if (c->displaytext)
    c->displaytext = 0;
  if (c->text[0] != NULL)
    free (c->text[0]), c->text[0] = NULL;
  if (c->text[1] != NULL)
    free (c->text[1]), c->text[1] = NULL;
  if (c->text[2] != NULL)
    free (c->text[2]), c->text[2] = NULL;
  c->nletters = 0;
  c->display = 1;
  if (c->play)
    uih_clear_lines (c);
}

void
uih_settextpos (uih_context * c, int x, int y)
{
  CONST char *names1[] = {
    "ytextposup",
    "ytextposmiddle",
    "ytextposbottom",
  };
  CONST char *names2[] = {
    "xtextposleft",
    "xtextposcenter",
    "xtextposright",
  };
  c->xtextpos = x;
  c->ytextpos = y;
  uih_updatemenus (c, names1[y]);
  uih_updatemenus (c, names2[x]);
}


/*timming routines */

void
uih_tbreak (uih_context * c)
{
  c->tbreak = 1;
}

void
uih_emulatetimers (uih_context * c)
{
  if (c->emulator == NULL)
    return;
  tl_emulate_timer (c->maintimer, c->emulator);
  tl_emulate_timer (c->doittimer, c->emulator);
  if (c->autopilot)
    tl_emulate_timer (c->autopilottimer, c->emulator);
  if (c->cycling)
    {
      tl_emulate_timer (c->cyclingtimer, c->emulator);
    }
  if (c->play)
    {
      tl_emulate_timer (c->playc->timer, c->emulator);
    }
  if (c->save)
    {
      tl_emulate_timer (c->savec->timer, c->emulator);
      tl_emulate_timer (c->savec->synctimer, c->emulator);
    }
}
static void
uih_unemulatetimers (uih_context * c)
{
  tl_unemulate_timer (c->maintimer);
  tl_unemulate_timer (c->doittimer);
  if (c->autopilot)
    tl_unemulate_timer (c->autopilottimer);
  if (c->cycling)
    tl_unemulate_timer (c->cyclingtimer);
  if (c->play)
    {
      tl_unemulate_timer (c->playc->timer);
    }
  if (c->save)
    {
      tl_unemulate_timer (c->savec->timer);
      tl_unemulate_timer (c->savec->synctimer);
    }
}
void
uih_constantframetime (uih_context * c, int time)
{
  if (c->emulator == NULL)
    c->emulator = tl_create_emulator ();
  c->emulatedframetime = time;
  uih_emulatetimers (c);
}

void
uih_noconstantframetime (uih_context * c)
{
  if (c->emulator == NULL)
    return;
  uih_unemulatetimers (c);
  tl_free_emulator (c->emulator);
  c->emulator = NULL;
}

void
uih_stoptimers (uih_context * c)
{
  if (!c->stoppedtimers)
    {
      c->stoppedtimers = 1;
      c->display = 1;
      tl_stop_timer (c->maintimer);
      tl_stop_timer (c->doittimer);
      if (c->autopilot)
      tl_stop_timer (c->autopilottimer);
      if (c->play)
      {
        tl_stop_timer (c->playc->timer);
        if (c->cycling)
          tl_stop_timer (c->cyclingtimer);
      }
      if (c->save)
      {
        tl_stop_timer (c->savec->timer);
        tl_stop_timer (c->savec->synctimer);
        if (c->cycling)
          tl_stop_timer (c->cyclingtimer);
      }
    }
}
void
uih_slowdowntimers (uih_context * c, int time)
{
  tl_slowdown_timer (c->maintimer, time);
  if (c->autopilot)
    tl_slowdown_timer (c->autopilottimer, time);
  if (c->play)
    {
      tl_slowdown_timer (c->playc->timer, time);
      if (c->cycling)
      tl_slowdown_timer (c->cyclingtimer, time);
    }
  if (c->save)
    {
      tl_slowdown_timer (c->savec->timer, time);
      tl_slowdown_timer (c->savec->synctimer, time);
      if (c->cycling)
      tl_slowdown_timer (c->cyclingtimer, time);
    }
}
void
uih_resumetimers (uih_context * c)
{
  if (c->stoppedtimers)
    {
      c->stoppedtimers = 0;
      tl_resume_timer (c->maintimer);
      if (c->cycling)
      tl_resume_timer (c->cyclingtimer);
      if (c->autopilot)
      tl_resume_timer (c->autopilottimer);
      if (c->play)
      {
        tl_resume_timer (c->playc->timer);
      }
      if (c->save)
      {
        tl_resume_timer (c->savec->timer);
        tl_resume_timer (c->savec->synctimer);
      }
    }
}

/*autopilot implementation */

static void
uih_changed (void)
{
  uih_newimage (uih);
}

static void
uih_autopilothandler (void *uih1, int n)
{
  uih = (uih_context *) uih1;
  do_autopilot (uih, &uih->autopilotx, &uih->autopiloty,
            &uih->autopilotbuttons, uih_changed, n);
}
static INLINE void
uih_zoom (uih_context * uih)
{
  uih->step += uih->speedup * 2 * uih->mul;
  if (uih->step > uih->maxstep)
    uih->step = uih->maxstep;
  else if (uih->step < -uih->maxstep)
    uih->step = -uih->maxstep;
}
static INLINE void
uih_unzoom (uih_context * uih)
{
  uih->step -= uih->speedup * 2 * uih->mul;
  if (uih->step > uih->maxstep)
    uih->step = uih->maxstep;
  else if (uih->step < -uih->maxstep)
    uih->step = -uih->maxstep;
}
static INLINE void
uih_slowdown (uih_context * uih)
{
  if (uih->step > 0)
    {
      if (uih->step < uih->speedup * uih->mul)
      uih->step = 0;
      else
      uih->step -= uih->speedup * uih->mul;
    }
  else if (uih->step < 0)
    {
      if (uih->step > -uih->speedup * uih->mul)
      uih->step = 0;
      else
      uih->step += uih->speedup * uih->mul;
    }
}
static INLINE void
uih_zoomupdate (uih_context * uih)
{
  number_t x;
  number_t y;
  number_t mmul = pow ((double) (1 - uih->step), (double) uih->mul);
  number_t mc = uih->fcontext->s.cr - uih->fcontext->s.rr / 2;
  number_t nc = uih->fcontext->s.cr + uih->fcontext->s.rr / 2;
  number_t mi = uih->fcontext->s.ci - uih->fcontext->s.ri / 2;
  number_t ni = uih->fcontext->s.ci + uih->fcontext->s.ri / 2;
  x = uih->xcenter, y = uih->ycenter;
  mc = x + (mc - x) * (mmul);
  nc = x + (nc - x) * (mmul);
  mi = y + (mi - y) * (mmul);
  ni = y + (ni - y) * (mmul);
  uih->fcontext->s.rr = nc - mc;
  uih->fcontext->s.ri = ni - mi;
  uih->fcontext->s.cr = (nc + mc) / 2;
  uih->fcontext->s.ci = (ni + mi) / 2;
  uih_animate_image (uih);
}


/*main uih loop */

int
uih_update (uih_context * c, int mousex, int mousey, int mousebuttons)
{
  int inmovement = 0;
  int slowdown = 1;
  int time;
  uih = c;

  if (!mousebuttons && uih->lastbuttons)
    uih_saveundo (c);
  uih->lastbuttons = mousebuttons;
  if (c->incalculation)
    return 0;
  if (c->emulator != NULL)
    tl_elpased (c->emulator, c->emulatedframetime);

  if (mousebuttons == (BUTTON1 | BUTTON3))
    mousebuttons = BUTTON2;
  tl_process_group (syncgroup, NULL);     /*First we need to update timming */
  tl_update_time ();
  time = tl_lookup_timer (c->maintimer);
  if (c->autopilot)
    {                   /*now handle autopilot */
      tl_process_group (c->autopilotgroup, NULL);
    }
  if (!c->inanimation)
    time = 0;
  if (time > 2000000)
    {
      uih_slowdowntimers (uih, time - 2000000);
      time = 2000000;
    }
  if (c->inanimation)
    c->inanimation--;
  tl_reset_timer (c->maintimer);
  c->mul = (double) time / FRAMETIME;
  if (c->fixedstep)
    c->mul = 0.3;
  if (c->tbreak)
    c->mul = 1, c->tbreak--;
  if (c->mul == 0)
    c->mul = 0.00000001;
  if (c->play)
    {
      uih_playupdate (c);
      if (!c->play)
      {
        c->inanimation = 2;
        return 1;
      }
      if (c->playc->lines.morphing) /*inmovement=1, c->display=1; */
      uih_update_lines (c);
      if (c->step)
      uih_zoomupdate (c), inmovement = 1;
      switch (c->zoomactive)
      {
      case 1:
        uih_zoom (c), inmovement = 1;
        break;
      case -1:
        uih_unzoom (c), inmovement = 1;
        break;
      default:
        uih_slowdown (c);
      }
      if (c->playc->morph)
      {
        int timer = tl_lookup_timer (c->playc->timer) - c->playc->starttime;
        number_t mmul = /*(tl_lookup_timer (c->playc->timer) - c->playc->starttime) / (number_t) (c->playc->frametime - c->playc->starttime); */
          MORPHVALUE (timer, c->playc->frametime - c->playc->starttime,
                  c->playc->morphtimes[0], c->playc->morphtimes[1]);
        number_t srr, drr;
        number_t mmul1;
        if (c->playc->source.rr * c->fcontext->windowwidth >
            c->playc->source.ri * c->fcontext->windowheight)
          srr = c->playc->source.rr;
        else
          srr = c->playc->source.ri;
        if (c->playc->destination.rr * c->fcontext->windowwidth >
            c->playc->destination.ri * c->fcontext->windowheight)
          drr = c->playc->destination.rr;
        else
          drr = c->playc->destination.ri;
        if (srr == drr)
          mmul1 = mmul;
        else
          mmul1 =
            (exp (log (srr) + ((log (drr) - log (srr)) * mmul)) -
             srr) / (drr - srr);
        if (mmul1 > 1)
          mmul1 = 1;
        if (mmul1 < 0)
          mmul1 = 0;
        inmovement = 1;
        c->fcontext->s.rr =
          c->playc->source.rr + (c->playc->destination.rr -
                           c->playc->source.rr) * mmul1;
        c->fcontext->s.ri =
          c->playc->source.ri + (c->playc->destination.ri -
                           c->playc->source.ri) * mmul1;
        c->fcontext->s.cr =
          c->playc->source.cr + (c->playc->destination.cr -
                           c->playc->source.cr) * mmul1;
        c->fcontext->s.ci =
          c->playc->source.ci + (c->playc->destination.ci -
                           c->playc->source.ci) * mmul1;
        uih_animate_image (c);
      }
      if (c->playc->morphjulia)
      {
        int timer = tl_lookup_timer (c->playc->timer) - c->playc->starttime;
        number_t mmul = /*(tl_lookup_timer (c->playc->timer) - c->playc->starttime) / (number_t) (c->playc->frametime - c->playc->starttime); */
          MORPHVALUE (timer, c->playc->frametime - c->playc->starttime,
                  c->playc->morphjuliatimes[0],
                  c->playc->morphjuliatimes[1]);
        uih_setjuliaseed (uih,
                      c->playc->sr + (c->playc->dr -
                                  c->playc->sr) * mmul,
                      c->fcontext->pim =
                      c->playc->si + (c->playc->di -
                                  c->playc->si) * mmul);
        inmovement = 1;
      }
      if (c->playc->morphangle)
      {
        int timer = tl_lookup_timer (c->playc->timer) - c->playc->starttime;
        number_t mmul = /*(tl_lookup_timer (c->playc->timer) - c->playc->starttime) / (number_t) (c->playc->frametime - c->playc->starttime); */
          MORPHVALUE (timer, c->playc->frametime - c->playc->starttime,
                  c->playc->morphangletimes[0],
                  c->playc->morphangletimes[1]);
        uih_angle (uih,
                 c->playc->srcangle + (c->playc->destangle -
                                 c->playc->srcangle) * mmul);
        inmovement = 1;
      }
    }
  else
    {
      if (!c->juliamode)
      {
        if (c->autopilot)
          {             /*now handle autopilot */
            mousex = c->autopilotx;
            mousey = c->autopiloty;
            mousebuttons = c->autopilotbuttons;
            inmovement = 1;
          }
        if (c->step)
          {
            number_t x;
            number_t y;
            if (mousex != c->xcenterm || mousey != c->ycenterm)
            {
              c->xcenterm = mousex;
              c->ycenterm = mousey;
              uih_getcoord (uih, mousex, mousey, &x, &y);
              c->xcenter = x;
              c->ycenter = y;
            }
            uih_zoomupdate (c), inmovement = 1;
          }
        c->zoomactive = 0;
        if (c->rotatemode != ROTATE_MOUSE)
          switch (mousebuttons)
            {                 /*process buttons */
            case BUTTON1:
            c->zoomactive = 1;
            inmovement = 1;
            break;
            case BUTTON3:
            c->zoomactive = -1;
            inmovement = 1;
            break;
            }
        uih_saveframe (c);
        if (c->rotatemode != ROTATE_MOUSE)
          {
            c->rotatepressed = 0;
            switch (mousebuttons)
            {           /*process buttons */
            case BUTTON1:
              uih_zoom (c), slowdown = 0;
              break;
            case BUTTON3:
              uih_unzoom (c), slowdown = 0;
              break;
            case BUTTON2:
              {
                number_t x, y;
                uih_getcoord (uih, mousex, mousey, &x, &y);
                if (c->pressed && (c->oldx != x || c->oldy != y))
                  {
                  c->fcontext->s.cr -= x - c->oldx;
                  c->fcontext->s.ci -= y - c->oldy;
                  uih_animate_image (c);
                  c->moved = 1;
                  }
                c->pressed = 1;
                c->speed = 0;
                update_view (c->fcontext);
                uih_getcoord (uih, mousex, mousey, &c->oldx, &c->oldy);
              }
              break;
            }
          }
        else
          {
            if (mousebuttons & BUTTON1)
            {
              number_t x, y;
              number_t angle;

              x = (mousex - c->image->width / 2) * c->image->pixelwidth;
              y = (mousey - c->image->height / 2) * c->image->pixelheight;
              angle = -atan2 (x, y) * 180 / M_PI;
              if (c->rotatepressed)
                {
                  uih_angle (uih,
                         c->fcontext->angle + angle - c->oldangle);
                }
              c->rotatepressed = 1;
              c->oldangle = angle;
            }
            else
            c->rotatepressed = 0;
          }
        if (!(mousebuttons & BUTTON2))
          c->pressed = 0;
        if (slowdown)
          uih_slowdown (c);
      }
      else
      {
        if (mousebuttons & BUTTON1)
          {
            number_t x, x1 = c->fcontext->pre;
            number_t y, y1 = c->fcontext->pim;
            c->zoomactive = 0;
            uih_getcoord (uih, mousex, mousey, &x, &y);
            c->fcontext->pre = x;
            c->fcontext->pim = y;
            uih_saveframe (c);
            c->pressed = 1;
            recalculate (c->fcontext->plane, &c->fcontext->pre,
                     &c->fcontext->pim);
            if (c->fcontext->pre != x1 || c->fcontext->pim != y1)
            {
              uih_animate_image (c);
            }
          }
        else
          c->pressed = 0;
      }
    }
  if (!inmovement)
    uih_tbreak (c);
  if (c->uncomplette)
    inmovement = 1;
  if (!c->recalculatemode && !c->display)
    uih_finishpalette (c);
  if (!inmovement)
    uih_callcomplette (c);
  if (c->inanimation < inmovement * 2)
    c->inanimation = inmovement * 2;
  return (inmovement * 2);
}

/*actions that can be used be user interface */

void
uih_autopilot_on (uih_context * c)
{
  if (!c->autopilot)
    {
      clean_autopilot (c);
      uih_autopilothandler (c, 1);
      tl_update_time ();
      uih_resumetimers (c);
      c->autopilottimer = tl_create_timer ();
      c->autopilotgroup = tl_create_group ();
      tl_set_multihandler (c->autopilottimer, uih_autopilothandler, c);
      tl_set_interval (c->autopilottimer, 1000000 / 25);
      tl_reset_timer (c->autopilottimer);
      tl_add_timer (c->autopilotgroup, c->autopilottimer);
      tl_update_time ();
      c->autopilot = 1;
      uih_emulatetimers (c);
      uih_updatemenus (c, "autopilot");
    }
}
void
uih_autopilot_off (uih_context * c)
{
  if (c->autopilot)
    {
      tl_remove_timer (c->autopilottimer);
      tl_free_timer (c->autopilottimer);
      tl_free_group (c->autopilotgroup);
      c->autopilot = 0;
      uih_updatemenus (c, "autopilot");
    }
}
void
uih_mkdefaultpalette (uih_context * c)
{
  if (c->zengine->fractalc->palette == NULL)
    return;
  uih_cycling_stop (c);
  if (mkdefaultpalette (c->zengine->fractalc->palette) != 0)
    {
      uih_newimage (c);
    }
  uih_palettechg (c);
  c->paletteshift = 0;
  c->manualpaletteshift = 0;
  c->palettechanged = 1;
  c->palettetype = 0;
  uih_finishpalette (c);
  uih_cycling_continue (c);
}

void
uih_mkpalette (uih_context * c)
{
  int seed;
  int alg = rand () % PALGORITHMS;
  if (c->zengine->fractalc->palette == NULL)
    return;
  uih_cycling_stop (c);
  if (mkpalette (c->zengine->fractalc->palette, seed = rand (), alg) != 0)
    {
      uih_newimage (c);
    }
  uih_palettechg (c);
  c->paletteshift = 0;
  c->manualpaletteshift = 0;
  c->paletteseed = seed;
  uih_finishpalette (c);
  c->palettechanged = 1;
  c->palettetype = alg + 1;
  uih_cycling_continue (c);
}

/*Basic inicialization routines */

static void
uih_alloctables (uih_context * c)
{
  c->zengine = zoom_filter.getinstance (&zoom_filter);
  if (c->zengine == NULL)
    return;
  c->fcontext =
    make_fractalc (0, c->image->pixelwidth * c->image->width,
               c->image->pixelheight * c->image->height);
  uih_updatemenus (c, "periodicity") uih_updatemenus (c,
                                          "in0")
    uih_updatemenus (c, "int0") uih_updatemenus (c,
                                     "out0") uih_updatemenus (c,
                                                        "outt0")
    uih_updatemenus (c, "plane0") uih_updatemenus (c, "guess3") uih = c;
  c->uifilter = uih_filter.getinstance (&uih_filter);
  c->queue = create_queue (c->uifilter);
  insertfilter (c->zengine, c->uifilter);
}
static int
uih_initqueue (uih_context * c)
{
  return (initqueue (c->queue));
}

void
uih_setmaxstep (uih_context * c, number_t p)
{
  c->maxstep = p;
}

void
uih_setspeedup (uih_context * c, number_t p)
{
  c->speedup = p;
}

void
uih_setmaxiter (uih_context * c, int maxiter)
{
  if (maxiter < 1)
    maxiter = 1;
  if (maxiter > 2000000)
    maxiter = 2000000;
  if (c->fcontext->maxiter != (unsigned int) maxiter)
    {
      c->fcontext->maxiter = maxiter;
      c->fcontext->version++;
      uih_newimage (c);
    }
}

void
uih_setbailout (uih_context * c, number_t bailout)
{
  if (bailout < 0)
    bailout = 0;
  if (c->fcontext->bailout != (number_t) bailout)
    {
      c->fcontext->bailout = bailout;
      c->fcontext->version++;
      uih_newimage (c);
    }
}

void
uih_setincoloringmode (uih_context * c, int mode)
{
  if (mode < 0)
    mode = rand () % INCOLORING;
  if (mode > INCOLORING)
    mode = INCOLORING;
  if (c->fcontext->incoloringmode != mode)
    {
      char str[10];
      c->fcontext->incoloringmode = mode;
      c->fcontext->version++;
      uih_newimage (c);
      sprintf (str, "in%i", mode);
      uih_updatemenus (c, str);
    }
}
void
uih_setintcolor (uih_context * c, int mode)
{
  if (mode < 0)
    mode = rand () % TCOLOR;
  if (mode > TCOLOR)
    mode = TCOLOR;
  if (c->fcontext->intcolor != mode)
    {
      char str[10];
      c->fcontext->intcolor = mode;
      if (c->fcontext->incoloringmode == 10)
      {
        c->fcontext->version++;
        uih_newimage (c);
      }
      sprintf (str, "int%i", mode);
      uih_updatemenus (c, str);
    }
}
void
uih_setouttcolor (uih_context * c, int mode)
{
  if (mode < 0)
    mode = rand () % TCOLOR;
  if (mode > TCOLOR)
    mode = TCOLOR;
  if (c->fcontext->outtcolor != mode)
    {
      char str[10];
      c->fcontext->outtcolor = mode;
      if (c->fcontext->coloringmode == 10)
      {
        c->fcontext->version++;
        uih_newimage (c);
      }
      sprintf (str, "outt%i", mode);
      uih_updatemenus (c, str);
    }
}
void
uih_setperbutation (uih_context * c, number_t zre, number_t zim)
{
  if (c->fcontext->bre != zre || c->fcontext->bim != zim)
    {
      c->fcontext->bre = zre;
      c->fcontext->bim = zim;
      if (c->fcontext->mandelbrot)
      {
        c->fcontext->version++;
        uih_newimage (c);
      }
      uih_updatemenus (c, "uiperturbation");
    }
}
void
uih_perbutation (uih_context * c, int mousex, int mousey)
{
  number_t r, i;
  uih_getcoord (c, mousex, mousey, &r, &i);
  uih_setperbutation (c, r, i);
}

void
uih_setjuliaseed (uih_context * c, number_t zre, number_t zim)
{
  if (c->fcontext->pre != zre || c->fcontext->pim != zim)
    {
      c->fcontext->pre = zre;
      c->fcontext->pim = zim;
      if (c->juliamode)
      {
        uih_animate_image (c);
      }
      else
      {
        if (!c->fcontext->mandelbrot)
          {
            c->fcontext->version++;
            if (c->playc && c->playc->morphjulia)
            uih_animate_image (c);
            else
            uih_newimage (c);
          }
      }
    }
}
void
uih_setfastmode (uih_context * c, int mode)
{
  CONST char *names[] = {
    "nodynamic",
    "nodynamic",
    "dynamicanimation",
    "dynamicnew",
    "dynamicnew"
  };
  if (mode < 0)
    mode = 0;
  c->fastmode = mode;
  uih_updatemenus (c, names[mode]);
}

void
uih_setoutcoloringmode (uih_context * c, int mode)
{
  if (mode < 0)
    mode = rand () % OUTCOLORING;
  if (mode > OUTCOLORING)
    mode = OUTCOLORING - 1;
  if (c->fcontext->coloringmode != mode)
    {
      char str[10];
      c->fcontext->coloringmode = mode;
      c->fcontext->version++;
      uih_newimage (c);
      sprintf (str, "out%i", mode);
      uih_updatemenus (c, str);
    }
}
void
uih_setplane (uih_context * c, int mode)
{
  int i;

  if (mode < 0)
    mode = 0;
  for (i = 0; planename[i] != NULL; i++);
  if (mode >= i)
    mode = i - 1;
  if (mode < 0)
    mode = rand () % i;
  uih_invalidatepos (c);
  if (c->fcontext->plane != mode)
    {
      char str[10];
      c->fcontext->plane = mode;
      c->fcontext->version++;
      uih_newimage (c);
      sprintf (str, "plane%i", mode);
      uih_updatemenus (c, str);
    }
}
void
uih_screentofractalcoord (uih_context * c, int mousex, int mousey,
                    number_t * re, number_t * im)
{
  uih_getcoord (c, mousex, mousey, re, im);
  recalculate (c->fcontext->plane, re, im);
}

void
uih_setmandelbrot (uih_context * c, int mode, int mousex, int mousey)
{
  if (mode < 0)
    mode = 0;
  if (mode > 1)
    mode = 1;
  if (c->fcontext->mandelbrot != mode)
    {
      c->fcontext->mandelbrot = mode;
      if (c->fcontext->mandelbrot == 0 && !c->juliamode)
      {
        uih_getcoord (c, mousex, mousey, &c->fcontext->pre,
                  &c->fcontext->pim);
        recalculate (c->fcontext->plane, &c->fcontext->pre,
                   &c->fcontext->pim);
      }
      else
      uih_disablejulia (c);
      c->fcontext->version++;
      uih_newimage (c);
      uih_updatemenus (c, "uimandelbrot");
    }
}
void
uih_setguessing (uih_context * c, int range)
{
  char str[10];
  c->fcontext->range = range;
  if (range <= 1)
    {
      uih_updatemenus (c, "noguess");
    }
  else if (range > 8)
    {
      uih_updatemenus (c, "guessall");
    }
  else
    {
      sprintf (str, "guess%i", range);
      uih_updatemenus (c, str);
    }
}
void
uih_setperiodicity (uih_context * c, int periodicity)
{
  c->fcontext->periodicity = periodicity;
  uih_updatemenus (c, "periodicity");
}

void
uih_interrupt (uih_context * c)
{
  if (c->incalculation)
    c->interrupt = 1;
}

void
uih_stopzooming (uih_context * c)
{
  c->speed = 0;
}

int
uih_updateimage (uih_context * c, struct image *image)
{
  /*exit(); */
  c->image = image;
  c->palette = image->palette;
  c->queue->isinitialized = 0;
  c->ddatalost = 1;
  fractalc_resize_to (c->fcontext, c->image->pixelwidth * c->image->width,
                  c->image->pixelheight * c->image->height);
  c->display = 1;
  c->palette->ncells = sizeof (uicolors) / sizeof (rgb_t);
  c->palette->prergb = uicolors;
  if (c->palette->type & BITMAPS)
    c->palette->prergb = uibwcolors;
  c->inanimation = 2;
  uih_newimage (c);
  if (image->palette->type & (FIXEDCOLOR | BITMAPS))
    uih_fixedcolorenable (c);
  else
    uih_fixedcolordisable (c);
  return (uih_initqueue (c));
}
static void
uih_getcscreensizes (struct uih_context *uih, int *x, int *y, int *w, int *h,
                 void *data)
{
  *x = 0;
  *y = 0;
  if (uih->clearscreen)
    *w = uih->image->width, *h = uih->image->height;
  else
    *w = *h = 0;
}
static void
uih_drawcscreen (struct uih_context *uih, void *data)
{
  if (uih->clearscreen)
    clear_image (uih->image);
}
struct uih_context *
uih_mkcontext (int flags, struct image *image,
             int (*passfunc) (struct uih_context *, int, CONST char *,
                        float),
             void (*longwait) (struct uih_context *),
             void (*upd) (struct uih_context *, CONST char *))
{
  uih_context *uih;
  uih = (uih_context *) calloc (sizeof (*uih), 1);    /*setup parameters */
  uih->updatemenus = upd;
  uih->autopilot = 0;
  uih->flags = flags;
  uih->image = image;
  uih->playstring = NULL;
  uih->palette = image->palette;
  uih->menuroot = "root";
  uih->palette->ncells = sizeof (uicolors) / sizeof (rgb_t);
  uih->palette->prergb = uicolors;
  if (uih->palette->type & BITMAPS)
    {
      uih->palette->prergb = uibwcolors;
    }
  uih->speed = 0;
  uih->step = 0;
  uih->color = 0;
  uih->speedup = STEP;
  uih->maxstep = MAXSTEP;
  uih->lasttime = -1;
  uih->recalculatemode = UIH_NEW_IMAGE;
  uih->display = 1;
  uih->fastmode = 2;
  uih_updatemenus (uih, "dynamicanimation");
  uih->aliasnum = -1;
  uih->direction = 1;
  uih->cyclingdirection = 1;
  uih->cyclingspeed = ROTATIONSPEED;
  uih->ddatalost = 1;
  uih->xtextpos = 1;
  uih_updatemenus (uih, "xtextleft");
  uih->complettehandler = 0;
  uih->ytextpos = 1;
  uih_updatemenus (uih, "ytextup");
  uih->display = 0;
  uih->errstring = NULL;
  uih->rotatemode = 0;
  uih_updatemenus (uih, "norotate");
  uih->rotationspeed = 10;
  uih->longwait = longwait;
  uih->passfunc = passfunc;
  uih->nletters = 0;
  uih->letterspersec = 15;
  uih->maintimer = tl_create_timer ();
  uih->calculatetimer = tl_create_timer ();
  uih->doittimer = tl_create_timer ();
  tl_update_time ();
  tl_reset_timer (uih->maintimer);
  tl_reset_timer (uih->calculatetimer);
  tl_stop_timer (uih->doittimer);
  tl_reset_timer (uih->doittimer);
  uih_alloctables (uih);
  uih_initqueue (uih);        /*FIXME return value should not be ignored */
  if (image->palette->type & (FIXEDCOLOR | BITMAPS))
    uih_fixedcolorenable (uih);
  uih_mkdefaultpalette (uih);
  uih_stoptimers (uih);
  clean_autopilot (uih);
  uih_newimage (uih);
  uih->cscreenwindow =
    uih_registerw (uih, uih_getcscreensizes, uih_drawcscreen, 0,
               NONTRANSPARENTW);
  uih_initmessages (uih);
  uih_inittext (uih);
  uih_emulatetimers (uih);
  uih_setformula (uih, 0);
  uih_saveundo (uih);
  return (uih);
}

void
uih_savepalette (uih_context * c)
{
  if (c->palette2 != NULL)
    destroypalette (c->palette2);
  if (c->zengine->fractalc->palette != NULL)
    c->palette2 = clonepalette (c->zengine->fractalc->palette);
}

void
uih_restorepalette (uih_context * uih)
{
  if (uih->palette2 != NULL)
    {
      if (uih->zengine->fractalc->palette != NULL)
      restorepalette (uih->zengine->fractalc->palette, uih->palette2);
      destroypalette (uih->palette2);
    }
  uih->palette2 = NULL;
  uih_finishpalette (uih);
}

void
uih_setformula (uih_context * c, int num)
{
  set_formula (c->fcontext, num);
  uih_newimage (c);
  uih_updatemenus (c, "uimandelbrot");
  uih_updatemenus (c, "uiperturbation");
  uih_updatemenus (c, c->fcontext->currentformula->shortname);
}

void
uih_initstate (struct uih_context *uih)
{
  int i;
  int ver = uih->fcontext->version;
  uih->step = 0;
  uih->speedup = STEP;
  uih->maxstep = MAXSTEP;
  uih_fastrotatedisable (uih);
  uih_disablejulia (uih);
  uih->color = 0;
  uih_cycling_off (uih);
  for (i = 0; i < uih_nfilters; i++)
    uih_disablefilter (uih, i);
  uih_setperbutation (uih, 0, 0);
  set_formula (uih->fcontext, 0);
  uih_setperiodicity (uih, 1);
  uih_setmaxiter (uih, 170);
  uih_setbailout (uih, 4);
  uih_setincoloringmode (uih, 0);
  uih_setoutcoloringmode (uih, 0);
  uih_setcycling (uih, 30);
  uih_display (uih);
  uih_setfastmode (uih, 2);
  uih_setintcolor (uih, 0);
  uih_setouttcolor (uih, 0);
  uih_setplane (uih, 0);
  uih_setguessing (uih, 3);
  uih_angle (uih, 0);
  uih_rotatemode (uih, 0);
  uih_rotationspeed (uih, 10);
  uih->xtextpos = 1;
  uih->ytextpos = 1;
  if (uih->playc)
    {
      uih->playc->morphtimes[0] = 0;
      uih->playc->morphtimes[1] = 0;
      uih->playc->morphjuliatimes[0] = 0;
      uih->playc->morphjuliatimes[1] = 0;
      uih->playc->morphangletimes[0] = 0;
      uih->playc->morphangletimes[1] = 0;
      uih->playc->morphlinetimes[0] = 0;
      uih->playc->morphlinetimes[1] = 0;
    }
  if (mkdefaultpalette (uih->zengine->fractalc->palette) != 0
      || uih->recalculatemode || uih->fcontext->version != ver)
    {
      uih_newimage (uih);
    }
}


void
uih_freecontext (uih_context * c)
{
  struct filter *f;
  int i;
  if (c->emulator != NULL)
    uih_noconstantframetime (c);
  for (i = 0; i < UNDOLEVEL; i++)
    if (c->undo.undos[i])
      free (c->undo.undos[i]), c->undo.undos[i] = 0;
  while (c->queue->first)
    {
      f = c->queue->first;
      removefilter (c->queue->first);
      f->action->destroyinstance (f);
    }
  uih_destroymessages (c);
  uih_destroytext (c);
  uih_removew (c, c->cscreenwindow);
  free (c->queue);
  free_fractalc (c->fcontext);
  free (c);
}
static struct filter *
uih_getinstance (CONST struct filteraction *a)
{
  struct filter *f = createfilter (a);
  f->data = uih;
  f->name = "XaoS's user interface layer";
  return (f);
}
static void
uih_destroyinstance (struct filter *f)
{
  struct uih_context *c = (struct uih_context *) f->data;
  if (c->autopilot)
    uih_autopilot_off (c);
  if (c->cycling)
    uih_cycling_off (c);
  tl_free_timer (c->maintimer);
  tl_free_timer (c->calculatetimer);
  tl_free_timer (c->doittimer);
  if (c->save)
    uih_save_disable (c);
  if (c->play)
    uih_replaydisable (c);
  free (f);
}
static int wascycling;
static int
uih_require (struct filter *f, struct requirements *r)
{
  struct uih_context *uih;
  uih = (struct uih_context *) f->data;
  f->req = *r;
  uih_clearwindows (uih);
  if (uih->cycling)
    uih_cycling_off (uih), wascycling = 1;
  if (!(r->supportedmask & uih->image->palette->type))
    return 0;
  /*FIXME something should be done here :) */
  return (1);
}

static int
uih_initialize (struct filter *f, struct initdata *i)
{
  struct uih_context *uih;
  int returnval;
  uih = (struct uih_context *) f->data;
  f->queue->saveimage = uih->image;
  i->fractalc = uih->fcontext;
  uih_setfont (uih);
  tl_update_time ();
  f->image = uih->image;
  f->wait_function = uih_waitfunc;
  uih->times[0][0] = -1;
  i->image = uih->image;
  f->fractalc = i->fractalc;
  f->image->palette->flags |= FINISHLATER;
  i->fractalc->palette = uih->image->palette;
  i->wait_function = uih_waitfunc;
  /*FIXME datalost should be handled in better way */
  if (uih->ddatalost)
    i->flags |= DATALOST;
  uih->tbreak = 2;
  uih_invalidatepos (uih);
  clean_autopilot (uih);
  returnval = f->previous->action->initialize (f->previous, i);
  if (wascycling)
    uih_cycling_on (uih), wascycling = 0;
  return returnval;
}

Generated by  Doxygen 1.6.0   Back to index