Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/ui-hlp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui-hlp')
-rw-r--r--src/ui-hlp/Makefile.in47
-rw-r--r--src/ui-hlp/autod.c112
-rw-r--r--src/ui-hlp/autopilot.c214
-rw-r--r--src/ui-hlp/autopilot.h33
-rw-r--r--src/ui-hlp/menu.c1678
-rw-r--r--src/ui-hlp/messg.c145
-rw-r--r--src/ui-hlp/play.c946
-rw-r--r--src/ui-hlp/play.h50
-rw-r--r--src/ui-hlp/playtext.c174
-rw-r--r--src/ui-hlp/render.c664
-rw-r--r--src/ui-hlp/save.c704
-rw-r--r--src/ui-hlp/ui-hlp.pri12
-rw-r--r--src/ui-hlp/ui_helper.c2303
-rw-r--r--src/ui-hlp/wstack.c528
14 files changed, 7610 insertions, 0 deletions
diff --git a/src/ui-hlp/Makefile.in b/src/ui-hlp/Makefile.in
new file mode 100644
index 0000000..6e8c830
--- /dev/null
+++ b/src/ui-hlp/Makefile.in
@@ -0,0 +1,47 @@
+CC = @CC@
+CFLAGS = @CFLAGS@
+LIBS = @LIBS@ -lm
+LFLAGS = @LDFLAGS@
+AR = @AR@
+RANLIB = @RANLIB@
+
+SRCS = autopilot.c \
+ ui_helper.c \
+ menu.c \
+ play.c \
+ messg.c \
+ render.c \
+ playtext.c \
+ save.c \
+ wstack.c
+
+OBJS = $(SRCS:.c=.o)
+
+TLIB = ../lib/libui-hlp.a
+
+
+all: $(TLIB)
+
+$(TLIB):$(OBJS)
+ rm -f $@
+ $(AR) rc $@ $(OBJS)
+ $(RANLIB) $@
+
+clean:
+ rm -f $(TLIB)
+ rm -f *.[oas]
+ rm -f *~
+ rm -f core
+
+distclean:clean
+ rm Makefile
+
+#dep:
+# rm -f .depend
+# make .depend
+#
+#.depend:
+# echo '# Program dependencies' >.depend
+# gcc -I svgalib $(DEFINES) -MM $(patsubst %.o,%.c,$(OBJS)) >>.depend
+#
+#include .depend
diff --git a/src/ui-hlp/autod.c b/src/ui-hlp/autod.c
new file mode 100644
index 0000000..2d66816
--- /dev/null
+++ b/src/ui-hlp/autod.c
@@ -0,0 +1,112 @@
+#ifndef UNSUPPORTED
+static INLINE int
+look1(uih_context * context, int x, int y, int range, int max)
+{
+ register cpixel_t *vbuff;
+ register int i, j, c = 0;
+ if (range < context->zengine->image->width / 2)
+ if (x < 0 || x > context->zengine->image->width ||
+ y < 0 || y > context->zengine->image->height)
+ return 0;
+ do {
+ max--;
+ c = 0;
+ if (range > context->zengine->image->width / 2)
+ context->x1 =
+ rand() % (context->zengine->image->width - 2 * LOOKSIZE -
+ 1) + LOOKSIZE, context->y1 =
+ rand() % (context->zengine->image->height - 2 * LOOKSIZE -
+ 1) + LOOKSIZE;
+ else {
+ context->x1 = rand() % range - (range >> 1) + x;
+ context->y1 = rand() % range - (range >> 1) + y;
+ if (context->x1 < LOOKSIZE)
+ context->x1 = LOOKSIZE;
+ if (context->y1 < LOOKSIZE)
+ context->y1 = LOOKSIZE;
+ if (context->x1 >
+ context->zengine->image->width - 2 - LOOKSIZE)
+ context->x1 =
+ context->zengine->image->width - 2 - LOOKSIZE;
+ if (context->y1 >
+ context->zengine->image->height - 2 - LOOKSIZE)
+ context->y1 =
+ context->zengine->image->height - 2 - LOOKSIZE;
+ }
+ for (j = context->y1 - LOOKSIZE; j <= context->y1 + LOOKSIZE; j++) {
+ vbuff = (cpixel_t *) context->zengine->image->currlines[j];
+ for (i = context->x1 - LOOKSIZE; i <= context->x1 + LOOKSIZE;
+ i++)
+ if (InSet(p_getp(vbuff, i)))
+ c++;
+ }
+ }
+ while ((c == 0 || c > LOOKSIZE * LOOKSIZE) && max > 0);
+ if (max > 0) {
+ context->c1 = BUTTON1, context->interlevel = 1;
+ return 1;
+ }
+ return (0);
+}
+
+static INLINE int
+look2(uih_context * context, int x, int y, int range, int max)
+{
+ register cpixel_t *vbuff, *vbuff2;
+ register int i, j, i1, j1, c = 0;
+ if (range < context->zengine->image->width / 2)
+ if (x < 0 || x > context->zengine->image->width ||
+ y < 0 || y > context->zengine->image->height)
+ return 0;
+ do {
+ max--;
+ c = 0;
+
+ if (range > context->zengine->image->width / 2)
+ context->x1 =
+ rand() % (context->zengine->image->width - 2 * LOOKSIZE -
+ 1) + LOOKSIZE, context->y1 =
+ rand() % (context->zengine->image->height - 2 * LOOKSIZE -
+ 1) + LOOKSIZE;
+ else {
+ context->x1 = rand() % range - (range >> 1) + x;
+ context->y1 = rand() % range - (range >> 1) + y;
+ if (context->x1 < LOOKSIZE)
+ context->x1 = LOOKSIZE;
+ if (context->y1 < LOOKSIZE)
+ context->y1 = LOOKSIZE;
+ if (context->x1 >
+ context->zengine->image->width - 2 - LOOKSIZE)
+ context->x1 =
+ context->zengine->image->width - 2 - LOOKSIZE;
+ if (context->y1 >
+ context->zengine->image->height - 2 - LOOKSIZE)
+ context->y1 =
+ context->zengine->image->height - 2 - LOOKSIZE;
+ }
+
+ for (j = context->y1 - LOOKSIZE; j < context->y1 + LOOKSIZE; j++) {
+ vbuff = (cpixel_t *) context->zengine->image->currlines[j];
+ for (i = context->x1 - LOOKSIZE; i <= context->x1 + LOOKSIZE;
+ i++)
+ for (j1 = j + 1; j1 < context->y1 + LOOKSIZE; j1++) {
+ vbuff2 =
+ (cpixel_t *) context->zengine->image->
+ currlines[j1];
+ for (i1 = i + 1; i1 < context->x1 + LOOKSIZE; i1++)
+ if (p_getp(vbuff, i) == p_getp(vbuff2, i1))
+ c++;
+ }
+ }
+
+ }
+ while ((c > LOOKSIZE * LOOKSIZE / 2) && max > 0);
+ if (max > 0) {
+ context->c1 = BUTTON1, context->interlevel = 2;
+ return 1;
+ }
+ return 0;
+}
+#endif
+#undef look1
+#undef look2
diff --git a/src/ui-hlp/autopilot.c b/src/ui-hlp/autopilot.c
new file mode 100644
index 0000000..5f28879
--- /dev/null
+++ b/src/ui-hlp/autopilot.c
@@ -0,0 +1,214 @@
+
+/*
+ * XaoS, a fast portable realtime fractal zoomer
+ * Copyright (C) 1996,1997 by
+ *
+ * Jan Hubicka (hubicka@paru.cas.cz)
+ * Thomas Marsh (tmarsh@austin.ibm.com)
+ *
+ * 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.
+ *
+ * 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.
+ */
+#ifdef _plan9_
+#include <u.h>
+#include <libc.h>
+#else
+#ifdef __MINGW32__
+#include <float.h>
+#define isnan _isnan
+#endif /* __MINGW32__ */
+#include <stdlib.h>
+#include <math.h>
+#include <config.h>
+#include <assert.h>
+#include <limits.h>
+#endif
+#include <fconfig.h>
+#define SLARGEITER
+#include <filter.h>
+#include <zoom.h>
+#include "autopilot.h"
+#include <ui_helper.h>
+#define MINCOUNT 5
+#define InSet(i) (i==context->image->palette->pixels[0])
+/*Include bitmap depended part first */
+
+#include <c256.h>
+#define look1 look18
+#define look2 look28
+#include "autod.c"
+
+#include <hicolor.h>
+#define look1 look116
+#define look2 look216
+#include "autod.c"
+
+#include <true24.h>
+#define look1 look124
+#define look2 look224
+#include "autod.c"
+
+#include <truecolor.h>
+#define look1 look132
+#define look2 look232
+#include "autod.c"
+
+void clean_autopilot(uih_context * context)
+{
+ context->minsize = 1000;
+ context->maxsize = 0;
+ context->autime = 0;
+ context->minlong = 0;
+ context->x1 = INT_MAX;
+ context->y1 = INT_MAX;
+ context->autopilotversion = context->fcontext->version;
+}
+
+static void again(uih_context * context)
+{
+ context->fcontext->s = context->fcontext->currentformula->v;
+ context->fcontext->version++;
+ clean_autopilot(context);
+}
+
+void
+do_autopilot(uih_context * context, int *x, int *y, int *controls,
+ void (*changed) (void), int times)
+{
+ int c = 0;
+ volatile number_t step =
+ (context->fcontext->rs.mc -
+ context->fcontext->rs.nc) / context->zengine->image->width / 10;
+ volatile number_t pos = context->fcontext->rs.mc;
+ volatile number_t pos1 = context->fcontext->rs.mc;
+ volatile number_t ystep =
+ (context->fcontext->rs.mi -
+ context->fcontext->rs.ni) / context->zengine->image->height / 10;
+ volatile number_t ypos = context->fcontext->rs.mi;
+ volatile number_t ypos1 = context->fcontext->rs.mi;
+ pos += step; /*out of precisity check */
+ ypos += ystep;
+ pos1 -= step; /*out of precisity check */
+ ypos1 -= ystep;
+ *x = context->x1;
+ *y = context->y1;
+ uih_clearwindows(context);
+ context->zengine->action->convertup(context->zengine, x, y);
+ if ((context->minlong > MINCOUNT && context->c1 == BUTTON3) ||
+ !(pos > context->fcontext->rs.mc) ||
+ !(ypos > context->fcontext->rs.mi) ||
+ (pos1 >= context->fcontext->rs.mc) ||
+ (ypos1 >= context->fcontext->rs.mi) ||
+ context->fcontext->rs.mc - context->fcontext->rs.nc > 100.0 ||
+ isnan(pos) || isnan(ypos) || isnan(context->fcontext->s.cr) ||
+ isnan(context->fcontext->s.ci) ||
+ isnan(context->fcontext->s.rr - context->fcontext->s.ri) ||
+ context->fcontext->s.rr == 0 ||
+ context->fcontext->s.ri == 0 ||
+ isnan(context->fcontext->rs.mc - context->fcontext->rs.mi) ||
+ isnan(context->fcontext->rs.nc - context->fcontext->rs.ni)) {
+ again(context);
+ changed();
+ }
+ /*Are we waiting for better qualitty? */
+ if (!context->c1 && context->zengine->flags & UNCOMPLETTE) {
+ return;
+ }
+ assert(changed != NULL);
+ if (context->fcontext->version != context->autopilotversion)
+ clean_autopilot(context);
+ if (context->fcontext->rs.mc - context->fcontext->rs.nc <
+ context->minsize) {
+ context->minsize =
+ context->fcontext->rs.mc - context->fcontext->rs.nc;
+ context->minlong = 0;
+ } /*Oscilating prevention */
+ if (context->fcontext->rs.mc - context->fcontext->rs.nc >
+ context->maxsize) {
+ context->minsize =
+ context->fcontext->rs.mc - context->fcontext->rs.nc;
+ context->maxsize =
+ context->fcontext->rs.mc - context->fcontext->rs.nc;
+ context->minlong = 0;
+ }
+ if (context->autime <= 0) {
+ context->minlong++;
+ context->autime = rand() % MAXTIME;
+ if (context->zengine->flags & LOWQUALITY) {
+ context->c1 = 0;
+ } else {
+ switch (context->zengine->image->bytesperpixel) {
+ case 1:
+ c = look18(context, *x, *y, RANGE1, NGUESSES);
+ if (!c)
+ c = look28(context, *x, *y, RANGE1, NGUESSES);
+ if (!(rand() % 30))
+ c = 0;
+ if (!c)
+ c = look18(context, *x, *y, 10000, NGUESSES1);
+ if (!c)
+ c = look18(context, *x, *y, 10000, NGUESSES2);
+ break;
+#ifdef SUPPORT16
+ case 2:
+ c = look116(context, *x, *y, RANGE1, NGUESSES);
+ if (!c)
+ c = look216(context, *x, *y, RANGE1, NGUESSES);
+ if (!(rand() % 30))
+ c = 0;
+ if (!c)
+ c = look116(context, *x, *y, 10000, NGUESSES1);
+ if (!c)
+ c = look216(context, *x, *y, 10000, NGUESSES1);
+ break;
+#endif
+#ifdef STRUECOLOR24
+ case 3:
+ c = look124(context, *x, *y, RANGE1, NGUESSES);
+ if (!c)
+ c = look224(context, *x, *y, RANGE1, NGUESSES);
+ if (!(rand() % 30))
+ c = 0;
+ if (!c)
+ c = look124(context, *x, *y, 10000, NGUESSES1);
+ if (!c)
+ c = look224(context, *x, *y, 10000, NGUESSES1);
+ break;
+#endif
+ case 4:
+ c = look132(context, *x, *y, RANGE1, NGUESSES);
+ if (!c)
+ c = look232(context, *x, *y, RANGE1, NGUESSES);
+ if (!(rand() % 30))
+ c = 0;
+ if (!c)
+ c = look132(context, *x, *y, 10000, NGUESSES1);
+ if (!c)
+ c = look232(context, *x, *y, 10000, NGUESSES1);
+ }
+ if (!c) {
+ if ((context->zengine->flags & UNCOMPLETTE)) {
+ context->c1 = 0;
+ } else
+ context->c1 = BUTTON3, context->autime >>= 1;
+ }
+ }
+ }
+ context->autime -= times;
+ *x = context->x1;
+ *y = context->y1;
+ context->zengine->action->convertup(context->zengine, x, y);
+/* printf("%i %i\n",*x,*y); */
+ *controls = context->c1;
+}
diff --git a/src/ui-hlp/autopilot.h b/src/ui-hlp/autopilot.h
new file mode 100644
index 0000000..98a3794
--- /dev/null
+++ b/src/ui-hlp/autopilot.h
@@ -0,0 +1,33 @@
+
+/*
+ * XaoS, a fast portable realtime fractal zoomer
+ * Copyright (C) 1996,1997 by
+ *
+ * Jan Hubicka (hubicka@paru.cas.cz)
+ * Thomas Marsh (tmarsh@austin.ibm.com)
+ *
+ * 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.
+ *
+ * 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.
+ */
+#ifndef AUTOPILOT_H
+#define AUTOPILOT_H
+
+#include <config.h>
+#include <ui_helper.h>
+
+void do_autopilot(uih_context *, int *, int *, int *, void (*)(void),
+ int times);
+void clean_autopilot(uih_context *);
+
+#endif
diff --git a/src/ui-hlp/menu.c b/src/ui-hlp/menu.c
new file mode 100644
index 0000000..4980efc
--- /dev/null
+++ b/src/ui-hlp/menu.c
@@ -0,0 +1,1678 @@
+#ifndef _plan9_
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#else
+#include <u.h>
+#include <libc.h>
+#endif
+
+#include <aconfig.h>
+#include <filter.h>
+#include <fconfig.h>
+#include <formulas.h>
+#include <ui_helper.h>
+#include <plane.h>
+#include <xmenu.h>
+#include "play.h"
+#ifdef HAVE_GETTEXT
+#include <libintl.h>
+#else
+#define gettext(STRING) STRING
+#endif
+
+#define LANG(name,name2) MENUSTRING("lang", NULL, name,name2,0, (void (*) (struct uih_context *c, char *))uih_loadcatalog, name2)
+#define TUTOR(name1,name2,name3) MENUSTRING(name1, NULL, name2,name3,MENUFLAG_INTERRUPT|UI,uih_playtutorial,name3)
+#define LANG_I(name,name2) MENUSTRING_I("lang", NULL, name,name2,0, (void (*) (struct uih_context *c, char *))uih_loadcatalog, name2)
+#define TUTOR_I(name1,name2,name3) MENUSTRING_I(name1, NULL, name2,name3,MENUFLAG_INTERRUPT|UI,uih_playtutorial,name3)
+
+CONST static char *CONST morphstypes[] = {
+ "view",
+ "julia",
+ "angle",
+ "line"
+};
+
+static CONST char *CONST imgtypes[] = {
+ "Truecolor",
+ "256 colors",
+ NULL
+};
+
+static CONST char *CONST yesno[] = {
+ "No",
+ "Yes",
+ NULL
+};
+
+CONST static char *CONST lineposs[] = {
+ "screen",
+ "scaled",
+ "fractal",
+ NULL
+};
+
+CONST char *CONST uih_colornames[] = {
+ "white",
+ "black",
+ "red",
+ NULL
+};
+
+/* Registering internationalized dialogs.
+ *
+ * The method we are internationalizing dialogs is similar to
+ * menu i18n. The original version of XaoS (without i18n)
+ * contained lots of static variables. Each row of a variable
+ * (which is a structure) contains a widget of a dialog.
+ * The last row contains NULL and 0 values to show
+ * that the dialog does not contain any other widgets.
+ *
+ * Here we are using a huge static variable which contains
+ * all widget from all dialogs. We copy each dialog after
+ * each other into this huge array. The original static
+ * variables will now be pointers pointing to the first
+ * row of the widget data from the appropriate line
+ * of the huge array.
+ *
+ * Note that in the first version there are only 2
+ * internationalized text, the rest will be "converted"
+ * continously (as I have enough time :-).
+ *
+ * Zoltan Kovacs <kovzol@math.u-szeged.hu>, 2003-01-05
+ */
+
+#define MAX_MENUDIALOGS_I18N 100
+#define Register(variable) variable = & menudialogs_i18n[no_menudialogs_i18n]
+static menudialog menudialogs_i18n[MAX_MENUDIALOGS_I18N];
+//static int no_menudialogs_i18n;
+
+static menudialog *uih_perturbationdialog, *uih_juliadialog,
+ *uih_smoothmorphdialog, *uih_renderdialog, *uih_viewdialog,
+ *uih_linedialog, *uih_colordialog, *uih_rotationdialog,
+ *uih_lettersdialog, *uih_iterdialog, *dtextparam, *dcommand,
+ *loaddialog, *playdialog, *saveimgdialog, *saveposdialog,
+ *uih_formuladialog, *uih_plviewdialog, *uih_coorddialog,
+ *uih_angledialog, *uih_autorotatedialog, *uih_fastrotatedialog,
+ *uih_filterdialog, *uih_shiftdialog, *uih_speeddialog, *printdialog,
+ *uih_bailoutdialog, *saveanimdialog, *uih_juliamodedialog,
+ *uih_textposdialog, *uih_fastmodedialog, *uih_timedialog,
+ *uih_numdialog, *uih_fpdialog, *palettedialog, *uih_cyclingdialog
+#ifdef SFFE_USING
+, *uih_sffedialog, *uih_sffeinitdialog
+#endif
+;
+
+extern char *xtextposnames[];
+extern char *ytextposnames[];
+
+
+void uih_registermenudialogs_i18n(void)
+{
+ int no_menudialogs_i18n = 0;
+
+/*
+ * The original code was:
+
+static menudialog uih_perturbationdialog[] = {
+ DIALOGCOORD ("Perturbation:", 0, 0),
+ {NULL}
+
+};
+
+ * Now first the static variable have to be registered (1),
+ * the widget must be inserted into the huge array (2),
+ * and the last row shows that no more widget comes (3).
+ */
+
+ Register(uih_perturbationdialog); // (1)
+ DIALOGCOORD_I(gettext("Perturbation:"), 0, 0); // (2)
+ NULL_I(); // (3)
+
+ Register(uih_juliadialog);
+ DIALOGCOORD_I(gettext("Julia-seed:"), 0, 0);
+ NULL_I();
+
+ Register(uih_smoothmorphdialog);
+ DIALOGCHOICE_I(gettext("Morphing type:"), morphstypes, 0);
+ DIALOGINT_I(gettext("Startuptime:"), 0);
+ DIALOGINT_I(gettext("Stoptime:"), 0);
+ NULL_I();
+
+ Register(uih_renderdialog);
+ DIALOGIFILE_I(gettext("File to render:"), "fract*.xaf");
+ DIALOGOFILE_I(gettext("Basename:"), "anim");
+ DIALOGINT_I(gettext("Width:"), 640);
+ DIALOGINT_I(gettext("Height:"), 480);
+ DIALOGFLOAT_I(gettext("Real width (cm):"), 29.0);
+ DIALOGFLOAT_I(gettext("Real height (cm):"), 21.0);
+ DIALOGFLOAT_I(gettext("Framerate:"), 30);
+ DIALOGCHOICE_I(gettext("Image type:"), imgtypes, 0);
+ DIALOGCHOICE_I(gettext("Antialiasing:"), yesno, 0);
+ DIALOGCHOICE_I(gettext("Always recalculate:"), yesno, 0);
+ DIALOGCHOICE_I(gettext("Calculate MPEG motion vectors:"), yesno, 0);
+ DIALOGINT_I(gettext("Recommended I frame distance:"), 27);
+ NULL_I();
+
+ Register(uih_viewdialog);
+ DIALOGCOORD_I(gettext("Center:"), 0, 0);
+ DIALOGFLOAT_I(gettext("Radius:"), 1);
+ DIALOGFLOAT_I(gettext("Angle:"), 0);
+ NULL_I();
+
+ Register(uih_linedialog);
+ DIALOGCHOICE_I(gettext("Mode:"), lineposs, 0);
+ DIALOGCOORD_I(gettext("Start:"), 0, 0);
+ DIALOGCOORD_I(gettext("End:"), 0, 0);
+ NULL_I();
+
+ Register(uih_colordialog);
+ DIALOGCHOICE_I(gettext("Color:"), uih_colornames, 0);
+ NULL_I();
+
+ Register(uih_rotationdialog);
+ DIALOGFLOAT_I(gettext("Rotations per second:"), 0);
+ NULL_I();
+
+ Register(uih_lettersdialog);
+ DIALOGINT_I(gettext("Letters per second:"), 0);
+ NULL_I();
+
+ Register(uih_iterdialog);
+ DIALOGINT_I(gettext("Iterations:"), 0);
+ NULL_I();
+
+ Register(dtextparam);
+ DIALOGSTR_I(gettext("Text:"), "");
+ NULL_I();
+
+ Register(dcommand);
+ DIALOGSTR_I(gettext("Your command:"), "");
+ NULL_I();
+
+ Register(loaddialog);
+ DIALOGIFILE_I(gettext("Filename:"), "fract*.xpf");
+ NULL_I();
+
+ Register(playdialog);
+ DIALOGIFILE_I(gettext("Filename:"), "anim*.xaf");
+ NULL_I();
+
+ Register(saveimgdialog);
+ DIALOGOFILE_I(gettext("Filename:"), "fract*.png");
+ NULL_I();
+
+ Register(saveposdialog);
+ DIALOGOFILE_I(gettext("Filename:"), "fract*.xpf");
+ NULL_I();
+
+ Register(uih_formuladialog);
+ DIALOGKEYSTR_I(gettext("Formula:"), "mandel");
+ NULL_I();
+
+ Register(uih_plviewdialog);
+ DIALOGFLOAT_I(gettext("X center:"), 0);
+ DIALOGFLOAT_I(gettext("Y center:"), 0);
+ DIALOGFLOAT_I(gettext("X Radius:"), 1);
+ DIALOGFLOAT_I(gettext("Y Radius:"), 1);
+ NULL_I();
+
+ Register(uih_coorddialog);
+ DIALOGCOORD_I(gettext("Coordinates:"), 0, 0);
+ NULL_I();
+
+ Register(uih_angledialog);
+ DIALOGFLOAT_I(gettext("Angle:"), 1);
+ NULL_I();
+
+ Register(uih_autorotatedialog);
+ DIALOGONOFF_I(gettext("continuous rotation"), 0);
+ NULL_I();
+
+ Register(uih_fastrotatedialog);
+ DIALOGONOFF_I(gettext("Fast rotation"), 0);
+ NULL_I();
+
+ Register(uih_filterdialog);
+ DIALOGKEYSTR_I(gettext("filter"), "");
+ DIALOGONOFF_I(gettext("enable"), 0);
+ NULL_I();
+
+ Register(uih_shiftdialog);
+ DIALOGINT_I(gettext("Amount:"), 0);
+ NULL_I();
+
+ Register(uih_speeddialog);
+ DIALOGFLOAT_I(gettext("Zooming speed:"), 0);
+ NULL_I();
+
+ Register(printdialog);
+ DIALOGSTR_I(gettext("Name:"), "");
+ NULL_I();
+
+ Register(uih_bailoutdialog);
+ DIALOGFLOAT_I(gettext("Bailout:"), 0);
+ NULL_I();
+
+ Register(saveanimdialog);
+ DIALOGOFILE_I(gettext("Filename:"), "anim*.xaf");
+ NULL_I();
+
+ Register(uih_juliamodedialog);
+ DIALOGONOFF_I(gettext("Julia mode:"), 0);
+ NULL_I();
+
+ Register(uih_textposdialog);
+ DIALOGCHOICE_I(gettext("Horizontal position:"), xtextposnames, 0);
+ DIALOGCHOICE_I(gettext("Vertical position:"), ytextposnames, 0);
+ NULL_I();
+
+ Register(uih_fastmodedialog);
+ DIALOGCHOICE_I(gettext("Dynamic resolution:"), save_fastmode, 0);
+ NULL_I();
+
+ Register(uih_timedialog);
+ DIALOGINT_I(gettext("Time:"), 0);
+ NULL_I();
+
+ Register(uih_numdialog);
+ DIALOGINT_I(gettext("Number:"), 0);
+ NULL_I();
+
+ Register(uih_fpdialog);
+ DIALOGFLOAT_I(gettext("Number:"), 0);
+ NULL_I();
+
+ Register(palettedialog);
+ DIALOGINT_I(gettext("Algorithm number:"), 0);
+ DIALOGINT_I(gettext("Seed:"), 0);
+ DIALOGINT_I(gettext("Shift:"), 0);
+ NULL_I();
+
+ Register(uih_cyclingdialog);
+ DIALOGINT_I(gettext("Frames per second:"), 0);
+ NULL_I();
+
+#ifdef SFFE_USING
+ Register(uih_sffedialog);
+ DIALOGSTR_I(gettext("Formula:"), "z^2+c");
+ NULL_I();
+
+ Register(uih_sffeinitdialog);
+ DIALOGSTR_I(gettext("Initialization:"), "");
+ NULL_I();
+#endif
+
+#ifdef DEBUG
+ printf("Filled %d widgets out of %d.\n",
+ no_menudialogs_i18n, MAX_MENUDIALOGS_I18N);
+#endif
+}
+
+#undef Register
+
+/*
+ * End of registering internationalized dialogs.
+ */
+
+#ifdef SFFE_USING
+void uih_sffein(uih_context * c, CONST char *text);
+void uih_sffeinitin(uih_context * c, CONST char *text);
+#endif
+
+static void uih_smoothmorph(struct uih_context *c, dialogparam * p)
+{
+ if (!c->playc)
+ return;
+ switch (p[0].dint) {
+ case 0:
+ c->playc->morphtimes[0] = p[1].dint;
+ c->playc->morphtimes[1] = p[2].dint;
+ break;
+ case 1:
+ c->playc->morphjuliatimes[0] = p[1].dint;
+ c->playc->morphjuliatimes[1] = p[2].dint;
+ break;
+ case 2:
+ c->playc->morphangletimes[0] = p[1].dint;
+ c->playc->morphangletimes[1] = p[2].dint;
+ break;
+ case 3:
+ c->playc->morphlinetimes[0] = p[1].dint;
+ c->playc->morphlinetimes[1] = p[2].dint;
+ break;
+ }
+}
+
+static void uih_render(struct uih_context *c, dialogparam * d)
+{
+#ifdef MACOSX
+ /*
+ * On Mac OS X, we must ensure basename specifies an absolute path in order
+ * to prevent png files from being rendered to the root directory.
+ */
+ if (d[1].dstring[0] != '/') {
+ uih_error(c,
+ gettext
+ ("renderanim: Must specify a valid absolute path for basename"));
+ return;
+ }
+#endif
+ if (d[2].dint <= 0 || d[2].dint > 4096) {
+ uih_error(c,
+ gettext
+ ("renderanim: Width parameter must be positive integer in the range 0..4096"));
+ return;
+ }
+ if (d[3].dint <= 0 || d[3].dint > 4096) {
+ uih_error(c,
+ gettext
+ ("renderanim: Height parameter must be positive integer in the range 0..4096"));
+ return;
+ }
+ if (d[4].number <= 0 || d[5].number <= 0) {
+ uih_error(c,
+ gettext
+ ("renderanim: Invalid real width and height dimensions"));
+ return;
+ }
+ if (d[6].number <= 0 || d[6].number >= 1000000) {
+ uih_error(c, gettext("renderanim: invalid framerate"));
+ return;
+ }
+ if (d[7].dint && d[8].dint) {
+ uih_error(c,
+ gettext
+ ("renderanim: antialiasing not supported in 256 color mode"));
+ return;
+ }
+ if (d[11].dint <= 0 || d[11].dint >= 1000000) {
+ uih_error(c, gettext("renderanim: incorrect I frame distance"));
+ return;
+ }
+ uih_renderanimation(c, d[1].dstring, (xio_path) d[0].dstring,
+ d[2].dint, d[3].dint, d[4].number / d[2].dint,
+ d[5].number / d[3].dint,
+ (int) (1000000 / d[6].number),
+#ifdef STRUECOLOR24
+ d[7].dint ? C256 : TRUECOLOR24,
+#else
+ d[7].dint ? C256 : TRUECOLOR,
+#endif
+ d[8].dint, d[9].dint, c->letterspersec, NULL,
+ d[10].dint, d[11].dint);
+}
+
+static menudialog *uih_getcolordialog(struct uih_context *c)
+{
+ if (c != NULL) {
+ uih_colordialog[0].defint = c->color;
+ }
+ return (uih_colordialog);
+}
+
+static void uih_setcolor(struct uih_context *c, int color)
+{
+ c->color = color;
+}
+
+
+static menudialog *uih_getperturbationdialog(struct uih_context *c)
+{
+ if (c != NULL) {
+ uih_perturbationdialog[0].deffloat = c->fcontext->bre;
+ uih_perturbationdialog[0].deffloat2 = c->fcontext->bim;
+ }
+ return (uih_perturbationdialog);
+}
+
+static menudialog *uih_getjuliadialog(struct uih_context *c)
+{
+ if (c != NULL) {
+ uih_juliadialog[0].deffloat = c->fcontext->pre;
+ uih_juliadialog[0].deffloat2 = c->fcontext->pim;
+ }
+ return (uih_juliadialog);
+}
+
+static void uih_plview(struct uih_context *c, dialogparam * d)
+{
+ if (d[2].number <= 0 || d[3].number <= 0) {
+ uih_error(c, gettext("animateview: Invalid viewpoint"));
+ return;
+ }
+ c->fcontext->s.cr = d[0].number;
+ c->fcontext->s.ci = d[1].number;
+ c->fcontext->s.rr = d[2].number;
+ c->fcontext->s.ri = d[3].number;
+ uih_newimage(c);
+}
+
+static void uih_plview2(struct uih_context *c, dialogparam * d)
+{
+ if (d[2].number <= 0 || d[3].number <= 0) {
+ uih_error(c, gettext("animateview: Invalid viewpoint"));
+ return;
+ }
+ c->fcontext->s.cr = d[0].number;
+ c->fcontext->s.ci = d[1].number;
+ c->fcontext->s.rr = d[2].number;
+ c->fcontext->s.ri = d[3].number;
+ uih_animate_image(c);
+}
+
+static void uih_dview(struct uih_context *c, dialogparam * d)
+{
+ if (d[1].number <= 0) {
+ uih_error(c, gettext("Invalid viewpoint"));
+ return;
+ }
+ c->fcontext->s.cr = d[0].dcoord[0];
+ c->fcontext->s.ci = d[0].dcoord[1];
+ c->fcontext->s.rr = d[1].number;
+ c->fcontext->s.ri = d[1].number;
+ uih_angle(c, d[2].number);
+ uih_newimage(c);
+}
+
+static menudialog *uih_getviewdialog(struct uih_context *c)
+{
+ number_t xs, ys;
+ if (c != NULL) {
+ xs = c->fcontext->s.rr;
+ ys = c->fcontext->s.ri * c->fcontext->windowwidth /
+ c->fcontext->windowheight;
+ uih_viewdialog[0].deffloat = c->fcontext->s.cr;
+ uih_viewdialog[0].deffloat2 = c->fcontext->s.ci;
+ uih_viewdialog[2].deffloat = c->fcontext->angle;
+ if (xs > ys)
+ uih_viewdialog[1].deffloat = c->fcontext->s.rr;
+ else
+ uih_viewdialog[1].deffloat = c->fcontext->s.ri;
+ }
+ return (uih_viewdialog);
+}
+
+static void uih_printdialog(struct uih_context *c, CONST char *name)
+{
+ CONST menuitem *item = menu_findcommand(name);
+ int y;
+ CONST menudialog *di;
+ if (item == NULL) {
+ fprintf(stderr, "print_dialog:unknown function %s\n", name);
+ return;
+ }
+ if (item->type != MENU_DIALOG && item->type != MENU_CUSTOMDIALOG) {
+ fprintf(stderr, "print_dialog:%s don't have any dialog. Sorry.\n",
+ name);
+ return;
+ }
+ di = menu_getdialog(c, item);
+ if (item->type == MENU_CUSTOMDIALOG)
+ printf("customdialog \"%s\"\n", item->shortname);
+ else
+ printf("dialog \"%s\"\n", item->shortname);
+ for (y = 0; di[y].question != NULL; y++) {
+ printf("dialogentry \"%s\" ", di[y].question);
+ switch (di[y].type) {
+ case DIALOG_INT:
+ printf("integer %i", di->defint);
+ break;
+ case DIALOG_FLOAT:
+ printf("float %f", (double) di->deffloat);
+ break;
+ case DIALOG_STRING:
+ printf("string \"%s\"", di->defstr);
+ case DIALOG_KEYSTRING:
+ printf("keyword \"%s\"", di->defstr);
+ break;
+ case DIALOG_IFILE:
+ printf("inputfile \"%s\"", di->defstr);
+ break;
+ case DIALOG_OFILE:
+ printf("outputfile \"%s\"", di->defstr);
+ break;
+ case DIALOG_ONOFF:
+ printf("onoff %s", di->defint ? "#t" : "#f");
+ break;
+ case DIALOG_COORD:
+ printf("complex %f %f", (double) di->deffloat,
+ (double) di->deffloat2);
+ break;
+ case DIALOG_CHOICE:
+ printf("choice {");
+ {
+ int y;
+ CONST char **str = (CONST char **) di->defstr;
+ for (y = 0; str[y] != NULL; y++)
+ printf("%s ", str[y]);
+ printf("}");
+ printf("%s ", str[di->defint]);
+ }
+ break;
+ }
+ printf("\n");
+ }
+ printf("enddialog\n");
+}
+
+static void
+uih_printmenu(struct uih_context *c, CONST char *name, int recursive)
+{
+ CONST char *fullname;
+ int i = 0;
+ CONST menuitem *item;
+ if ((fullname = menu_fullname(name)) == NULL) {
+ printf("Menu not found\n");
+ return;
+ }
+ printf("\n\nmenu \"%s\" \"%s\"\n", fullname, name);
+ for (i = 0; (item = menu_item(name, i)) != NULL; i++) {
+ if (item->type == MENU_SUBMENU) {
+ printf("submenu \"%s\" \"%s\"\n", item->name, item->shortname);
+ continue;
+ }
+ if (item->type == MENU_SUBMENU) {
+ printf("separator");
+ continue;
+ }
+ printf("menuentry \"%s\" \"%s\" ", item->name, item->shortname);
+ if (item->flags & MENUFLAG_RADIO)
+ printf("radio %s", menu_enabled(item, c) ? "on" : "off");
+ else if (item->flags & MENUFLAG_CHECKBOX)
+ printf("checkbox %s", menu_enabled(item, c) ? "on" : "off");
+ else
+ printf("normal");
+ if (item->flags & MENUFLAG_DIALOGATDISABLE)
+ printf(" dialogatdisable");
+ if (item->type == MENU_DIALOG || item->type == MENU_CUSTOMDIALOG)
+ printf(" dialog");
+ printf("\n");
+ }
+ printf("endmenu\n");
+ if (recursive)
+ for (i = 0; (item = menu_item(name, i)) != NULL; i++) {
+ if (item->type == MENU_SUBMENU) {
+ uih_printmenu(c, item->shortname, 1);
+ }
+ }
+}
+
+static void uih_printmenuwr(struct uih_context *c, CONST char *name)
+{
+ uih_printmenu(c, name, 0);
+}
+
+static void uih_printallmenus(struct uih_context *c)
+{
+ uih_printmenu(c, "root", 1);
+ uih_printmenu(c, "animroot", 1);
+ printf("endmenu\n");
+}
+
+static menudialog *uih_getlettersdialog(struct uih_context *c)
+{
+ if (c != NULL)
+ uih_lettersdialog[0].defint = c->letterspersec;
+ return (uih_lettersdialog);
+}
+
+static menudialog *uih_getiterdialog(struct uih_context *c)
+{
+ if (c != NULL)
+ uih_iterdialog[0].defint = c->fcontext->maxiter;
+ return (uih_iterdialog);
+}
+
+static menudialog *uih_getbailoutdialog(struct uih_context *c)
+{
+ if (c != NULL)
+ uih_bailoutdialog[0].deffloat = c->fcontext->bailout;
+ return (uih_bailoutdialog);
+}
+
+static int uih_saveanimenabled(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->save);
+}
+
+
+
+static menudialog *uih_getrotationdialog(struct uih_context *c)
+{
+ if (c != NULL)
+ uih_rotationdialog[0].deffloat = c->rotationspeed;
+ return (uih_rotationdialog);
+}
+
+static menudialog *uih_getpalettedialog(struct uih_context *uih)
+{
+ if (uih != NULL) {
+ palettedialog[0].defint = uih->palettetype;
+ palettedialog[1].defint = uih->paletteseed;
+ palettedialog[2].defint =
+ uih->paletteshift + uih->manualpaletteshift;
+ }
+ return (palettedialog);
+}
+
+static menudialog *uih_getcyclingdialog(struct uih_context *uih)
+{
+ if (uih != NULL)
+ uih_cyclingdialog[0].defint = uih->cyclingspeed * uih->direction;
+ return (uih_cyclingdialog);
+}
+
+static menudialog *uih_getspeeddialog(struct uih_context *uih)
+{
+ if (uih != NULL)
+ uih_speeddialog[0].deffloat = uih->speedup / STEP;
+ return (uih_speeddialog);
+}
+
+static void uih_setspeed(uih_context * c, number_t p)
+{
+ if (p >= 100)
+ p = 1.0;
+ if (p < 0)
+ p = 0;
+ c->speedup = STEP * p;
+ c->maxstep = MAXSTEP * p;
+
+}
+
+static void uih_palette(struct uih_context *uih, dialogparam * p)
+{
+ int n1 = p[0].dint;
+ int n2 = p[1].dint;
+ int shift = p[2].dint;
+ if (!n1) {
+ uih_playdefpalette(uih, shift);
+ return;
+ }
+ if (n1 < 1 || n1 > PALGORITHMS) {
+ uih_error(uih, gettext("Unknown palette type"));
+ }
+ if (uih->zengine->fractalc->palette == NULL)
+ return;
+ if (mkpalette(uih->zengine->fractalc->palette, n2, n1 - 1) != 0) {
+ uih_newimage(uih);
+ }
+ uih->manualpaletteshift = 0;
+ uih->palettetype = n1;
+ uih->palettechanged = 1;
+ uih->paletteseed = n2;
+ if (shiftpalette(uih->zengine->fractalc->palette, shift)) {
+ uih_newimage(uih);
+ }
+ uih->paletteshift = shift;
+}
+
+static int uih_rotateselected(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ if (!c->fastrotate)
+ return !n;
+ return (c->rotatemode == n);
+}
+
+static int uih_guessingselected(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->range == n);
+}
+
+static int uih_fastmode(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fastmode == n);
+}
+
+static int uih_periodicityselected(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->periodicity);
+}
+
+static void uih_periodicitysw(struct uih_context *c)
+{
+ uih_setperiodicity(c, c->fcontext->periodicity ^ 1);
+}
+
+static int uih_cyclingselected(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->cycling && c->cyclingdirection == 1);
+}
+
+static int uih_rcyclingselected(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->cycling && c->cyclingdirection == -1);
+}
+
+static void uih_cyclingsw(struct uih_context *c)
+{
+ // Andrew Stone: this fixes what I consider a bug - switching from Y to y should keep cycling:
+ if (c->cycling && c->cyclingdirection == -1)
+ uih_cycling_off(c);
+ c->cyclingdirection = 1;
+ if (c->cycling)
+ uih_cycling_off(c);
+ else if (!uih_cycling_on(c))
+ uih_error(c, gettext("Initialization of color cycling failed.")),
+ uih_message(c,
+ gettext("Try to enable palette emulation filter"));
+}
+
+static void uih_rcyclingsw(struct uih_context *c)
+{
+ // Andrew Stone: this fixes what I consider a bug - switching from y to Y should keep cycling:
+ if (c->cycling && c->cyclingdirection == 1)
+ uih_cycling_off(c);
+ c->cyclingdirection = -1;
+ if (c->cycling)
+ uih_cycling_off(c);
+ else if (!uih_cycling_on(c))
+ uih_error(c, gettext("Initialization of color cycling failed.")),
+ uih_message(c,
+ gettext("Try to enable palette emulation filter"));
+}
+
+static void uih_juliasw(struct uih_context *c)
+{
+ if (!c->juliamode)
+ uih_enablejulia(c);
+ else
+ uih_disablejulia(c);
+}
+
+static int uih_juliaselected(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->juliamode);
+}
+
+static int uih_mandelbrotselected(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->mandelbrot);
+}
+
+static void uih_mandelbrotsw(struct uih_context *c, number_t x, number_t y)
+{
+ c->fcontext->mandelbrot ^= 1;
+ if (c->fcontext->mandelbrot == 0 && !c->juliamode) {
+ c->fcontext->pre = x;
+ c->fcontext->pim = y;
+ } else
+ uih_disablejulia(c);
+ c->fcontext->version++;
+ uih_newimage(c);
+ uih_updatemenus(c, "uimandelbrot");
+}
+
+static int uih_autopilotselected(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->autopilot);
+}
+
+static int uih_fixedstepselected(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fixedstep);
+}
+
+static void uih_persw(struct uih_context *c, number_t x, number_t y)
+{
+ if (c->fcontext->bre || c->fcontext->bim)
+ uih_setperbutation(c, 0.0, 0.0);
+ else
+ uih_setperbutation(c, x, y);
+ // printf(""); // fixme: some newer versions of gcc crashes without this
+}
+
+static int uih_perselected(struct uih_context *c)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->bre || c->fcontext->bim);
+}
+
+static void uih_autopilotsw(struct uih_context *c)
+{
+ if (c->autopilot)
+ uih_autopilot_off(c);
+ else
+ uih_autopilot_on(c);
+}
+
+static void uih_fixedstepsw(struct uih_context *c)
+{
+ c->fixedstep ^= 1;
+}
+
+static void uih_setxtextpos(uih_context * c, int p)
+{
+ uih_settextpos(c, p, c->ytextpos);
+}
+
+static int uih_xtextselected(uih_context * c, int p)
+{
+ if (c == NULL)
+ return 0;
+ return (c->xtextpos == p);
+}
+
+static void uih_setytextpos(uih_context * c, int p)
+{
+ uih_settextpos(c, c->xtextpos, p);
+}
+
+static int uih_ytextselected(uih_context * c, int p)
+{
+ if (c == NULL)
+ return 0;
+ return (c->ytextpos == p);
+}
+
+static void uih_menumkpalette(uih_context * c)
+{
+ char s[256];
+ uih_mkpalette(c);
+ sprintf(s, gettext("Algorithm:%i seed:%i size:%i"), c->palettetype,
+ c->paletteseed, c->zengine->fractalc->palette->size);
+ uih_message(c, s);
+}
+
+static void uih_shiftpalette(uih_context * c, int shift)
+{
+ if (shiftpalette(c->zengine->fractalc->palette, shift)) {
+ uih_newimage(c);
+ }
+ c->manualpaletteshift += shift;
+}
+
+static void uih_fshift(uih_context * c)
+{
+ uih_shiftpalette(c, 1);
+}
+
+static void uih_bshift(uih_context * c)
+{
+ uih_shiftpalette(c, -1);
+}
+
+static CONST menuitem *menuitems; /*XaoS menu specifications */
+/* This structure is now empty. All static definitions have been moved
+ to uih_registermenus_i18n() which fills up its own static array. */
+
+
+/* Registering internationalized menus. See also include/xmenu.h
+ for details. Note that MAX_MENUITEMS_I18N should be increased
+ if more items will be added in future.
+
+ On 2006-07-12 J.B. Langston wrote:
+
+ The menu.c.diff file changes the MAX_MENUITEMS_I18N macro from
+ 200 to 250. As of 3.2.1, the number of allocated menu items had
+ been exceeded (there are 201 menu items now). This was causing
+ the memory within the application to be clobbered, resulting
+ in subtle bugs on the PowerPC platform (both X11 and OSX drivers).
+ For example, rendering animations generated a segmentation fault.
+ It's quite possible it could have been causing other subtle bugs
+ elsewhere in the program. */
+
+#define MAX_MENUITEMS_I18N 250
+static menuitem menuitems_i18n[MAX_MENUITEMS_I18N];
+int uih_no_menuitems_i18n;
+
+void uih_registermenus_i18n(void)
+{
+ // Special version (currently it's OK):
+ int no_menuitems_i18n = 0;
+ SUBMENU_I("", NULL, gettext("Root menu"), "root");
+ SUBMENU_I("", NULL, gettext("Animation root menu"), "animroot");
+ SUBMENU_I("", NULL, gettext("Replay only commands"), "plc");
+ SUBMENU_I("", NULL, gettext("Command line options only"), "comm");
+#define MP (MENUFLAG_NOMENU|MENUFLAG_NOPLAY|MENUFLAG_ATSTARTUP)
+ MENUNOP_I("comm", NULL,
+ gettext("print menus specifications of all menus"),
+ "print_menus", MP, uih_printallmenus);
+ MENUDIALOG_I("comm",
+ NULL,
+ gettext
+ ("print menu specification"),
+ "print_menu", MP, uih_printmenuwr, printdialog);
+ MENUDIALOG_I("comm", NULL,
+ gettext("print menu specification in xshl format"),
+ "xshl_print_menu", MP, uih_xshlprintmenu, printdialog);
+ MENUNOP_I("comm", NULL,
+ gettext
+ ("print all menu specifications in xshl format"),
+ "xshl_print_menus", MP, uih_xshlprintmenus);
+ MENUDIALOG_I("comm", NULL, gettext("print dialog specification"),
+ "print_dialog", MP, uih_printdialog, printdialog);
+#undef MP
+#define MP (MENUFLAG_NOMENU|MENUFLAG_NOOPTION)
+ /* Commands suitable only for animation replay */
+ SUBMENU_I("plc", NULL, gettext("Line drawing functions"), "linemenu");
+ MENUDIALOG_I("linemenu", NULL, gettext("Line"), "line", MP, uih_line,
+ uih_linedialog);
+ MENUDIALOG_I("linemenu", NULL,
+ gettext("Morph line"),
+ "morphline", MP, uih_morphline, uih_linedialog);
+ MENUDIALOG_I("linemenu", NULL, gettext("Morph last line"),
+ "morphlastline", MP, uih_morphlastline, uih_linedialog);
+ MENUDIALOG_I("linemenu", NULL,
+ gettext("Set line key"),
+ "linekey", MP, uih_setkey, uih_numdialog);
+ MENUNOP_I("linemenu", NULL, gettext("Clear line"), "clearline", MP,
+ uih_clear_line);
+ MENUNOP_I("linemenu", NULL,
+ gettext("Clear all lines"), "clearlines", MP,
+ uih_clear_lines);
+ SUBMENU_I("plc", NULL, gettext("Animation functions"), "animf");
+ MENUDIALOG_I("animf", NULL, gettext("View"), "animateview", MP,
+ uih_plview2, uih_plviewdialog);
+ MENUDIALOG_I("animf", NULL,
+ gettext
+ ("Morph view"),
+ "morphview", MP, uih_playmorph, uih_plviewdialog);
+ MENUDIALOG_I("animf", NULL, gettext("Morph julia"), "morphjulia", MP,
+ uih_playmorphjulia, uih_coorddialog);
+ MENUDIALOG_I("animf",
+ NULL,
+ gettext
+ ("Move view"), "moveview", MP, uih_playmove,
+ uih_coorddialog);
+ MENUDIALOG_I("animf", NULL, gettext("Morph angle"), "morphangle", MP,
+ uih_playmorphangle, uih_angledialog);
+ MENUDIALOG_I("animf", NULL, gettext("Zoom center"), "zoomcenter", MP,
+ uih_zoomcenter, uih_coorddialog);
+ MENUNOP_I("animf", NULL, gettext("Zoom"), "zoom", MP, uih_playzoom);
+ MENUNOP_I("animf", NULL, gettext("Un-zoom"),
+ "unzoom", MP, uih_playunzoom);
+ MENUNOP_I("animf",
+ NULL, gettext("Stop zooming"), "stop", MP, uih_playstop);
+ MENUDIALOG_I("animf", NULL, gettext("Smooth morphing parameters"),
+ "smoothmorph", MP, uih_smoothmorph,
+ uih_smoothmorphdialog);
+ SUBMENU_I("plc", NULL, gettext("Timing functions"), "time");
+ MENUDIALOG_I("time", NULL, gettext("Usleep"), "usleep", MP,
+ uih_playusleep, uih_timedialog);
+ MENUNOP_I("time", NULL,
+ gettext("Wait for text"), "textsleep", MP,
+ uih_playtextsleep);
+ MENUNOP_I("time", NULL, gettext("Wait for complete image"), "wait", MP,
+ uih_playwait);
+ MENUDIALOG_I("plc", NULL, gettext("Include file"), "load", MP,
+ uih_playload, loaddialog);
+ MENUDIALOG_I("palette", NULL, gettext("Default palette"),
+ "defaultpalette", MP, uih_playdefpalette, uih_numdialog);
+ MENUDIALOG_I("fractal", NULL, gettext("Formula"), "formula", MP,
+ uih_play_formula, uih_formuladialog);
+ MENUDIALOG_I("ui", NULL, gettext("Maximal zooming step"), "maxstep",
+ MP, uih_setmaxstep, uih_fpdialog);
+ MENUDIALOG_I("ui", NULL, gettext("Zooming speedup"), "speedup", MP,
+ uih_setspeedup, uih_fpdialog);
+ MENUDIALOG_I("mfilter", NULL, gettext("Filter"), "filter", MP,
+ uih_playfilter, uih_filterdialog);
+#undef MP
+#define UI (MENUFLAG_NOPLAY|MENUFLAG_NOOPTION)
+ MENUCDIALOG_I("ui", NULL, gettext("Letters per second"),
+ "letterspersec", MENUFLAG_NOMENU, uih_letterspersec,
+ uih_getlettersdialog);
+ MENUCDIALOG_I("uia", NULL,
+ gettext
+ ("Letters per second"),
+ "letters", UI, uih_letterspersec, uih_getlettersdialog);
+ MENUNOP_I("uia", "z", gettext("Interrupt"), "animinterrupt",
+ MENUFLAG_INTERRUPT | MENUFLAG_INCALC, uih_interrupt);
+ SUBMENU_I("root", "s", gettext("File"), "file");
+ SUBMENU_I("root", NULL, gettext("Edit"), "edit");
+ SUBMENU_I("root", NULL, gettext("Fractal"), "fractal");
+ SUBMENU_I("root", NULL, gettext("Calculation"), "calc");
+ SUBMENU_I("root", "e", gettext("Filters"), "mfilter");
+ SUBMENU_I("root", NULL, gettext("UI"), "ui");
+ SUBMENU_I("root", NULL, gettext("Misc"), "misc");
+#ifdef MACOSX
+ SUBMENU_I("root", NULL, gettext("Window"), "window");
+#endif
+ SUBMENU_I("root", NULL, gettext("Help"), "helpmenu");
+ SUBMENU_I("helpmenu", NULL, gettext("Tutorials"),
+ "tutor") SUBMENUNOOPT_I("animroot", "f", gettext("File"),
+ "file");
+ // You cannot have menu items directly on the root menu in some OS
+ // So we put the "Stop Replay" item in the UI menu instead
+ MENUSEPARATOR_I("uia");
+ MENUNOP_I("uia", "s", gettext("Stop replay"), "stopreplay",
+ UI | MENUFLAG_INTERRUPT, uih_replaydisable);
+ SUBMENUNOOPT_I("animroot", NULL, gettext("UI"), "uia");
+ SUBMENUNOOPT_I("animroot", NULL, gettext("Help"), "helpmenu");
+ MENUDIALOG_I("misc", "!", gettext("Command"), "command", UI,
+ uih_command, dcommand);
+ MENUDIALOG_I("misc", NULL, gettext("Play string"), "playstr",
+ MENUFLAG_NOMENU, uih_playstr, dcommand);
+ MENUDIALOG_I("misc", NULL, gettext("Render animation"), "renderanim",
+ UI, uih_render, uih_renderdialog);
+ MENUSEPARATOR_I("misc");
+ MENUNOP_I("misc", NULL, gettext("Clear screen"), "clearscreen",
+ MENUFLAG_NOOPTION, uih_clearscreen);
+ MENUNOP_I("misc", NULL, gettext("Display fractal"), "display",
+ MENUFLAG_NOOPTION, uih_display);
+ MENUSEPARATOR_I("misc");
+ MENUDIALOG_I("misc", NULL, gettext("Display text"), "text", 0, uih_text, dtextparam); /*FIXME: Should allow multiline */
+
+ MENUCDIALOG_I("misc", NULL, gettext("Color"), "color", 0, uih_setcolor,
+ uih_getcolordialog);
+ SUBMENU_I("misc", NULL, gettext("Horizontal text position"),
+ "xtextpos");
+ SUBMENU_I("misc", NULL, gettext("Vertical text position"), "ytextpos");
+ MENUDIALOG_I("misc", NULL,
+ gettext("Text position"),
+ "textposition",
+ MENUFLAG_NOMENU | MENUFLAG_INCALC,
+ uih_playtextpos, uih_textposdialog);
+ MENUDIALOG_I("misc", NULL, gettext("Message"), "message",
+ MENUFLAG_NOMENU, uih_playmessage, dtextparam);
+ /* The following 6 menu options should not be translated. The example
+ files heavily use these constants and lots of examples will not work
+ anymore... :-( Anyway, this should be fixed somehow. */
+
+ MENUINTRB_I("ytextpos", NULL, "Up", "ytextup", UI, uih_setytextpos,
+ UIH_TEXTTOP, uih_ytextselected);
+ MENUINTRB_I("ytextpos",
+ NULL, "Middle",
+ "ytextmiddle",
+ UI, uih_setytextpos, UIH_TEXTMIDDLE, uih_ytextselected);
+ MENUINTRB_I("ytextpos", NULL, "Bottom", "ytextbottom", UI,
+ uih_setytextpos, UIH_TEXTBOTTOM, uih_ytextselected);
+ MENUINTRB_I("xtextpos", NULL, "Left",
+ "xtextleft", UI,
+ uih_setxtextpos, UIH_TEXTLEFT, uih_xtextselected);
+ MENUINTRB_I("xtextpos", NULL, "Center", "xtextcenter", UI,
+ uih_setxtextpos, UIH_TEXTCENTER, uih_xtextselected);
+ MENUINTRB_I("xtextpos", NULL, "Right",
+ "xtexteight", UI,
+ uih_setxtextpos, UIH_TEXTRIGHT, uih_xtextselected);
+ MENUDIALOG_I("file", NULL, gettext("Load"), "loadpos",
+ MENUFLAG_INTERRUPT | MENUFLAG_NOPLAY, uih_loadfile,
+ loaddialog);
+ MENUDIALOG_I("file", NULL, gettext("Save"),
+ "savepos", 0, uih_saveposfile, saveposdialog);
+ MENUSEPARATOR_I("file") MENUDIALOGCB_I("file", NULL, gettext("Record"),
+ "record", 0, uih_saveanimfile,
+ saveanimdialog,
+ uih_saveanimenabled);
+ MENUDIALOG_I("file", NULL, gettext("Replay"), "play",
+ MENUFLAG_INTERRUPT | MENUFLAG_NOPLAY, uih_playfile,
+ playdialog);
+ MENUSEPARATOR_I("file");
+ MENUDIALOG_I("file",
+ NULL,
+ gettext
+ ("Save image"), "saveimg", 0, uih_savepngfile,
+ saveimgdialog);
+ MENUNOP_I("file", NULL, gettext("Load random example"), "loadexample",
+ MENUFLAG_INTERRUPT, uih_loadexample);
+ MENUNOP_I("file", NULL, gettext("Save configuration"), "savecfg", 0,
+ uih_savecfg);
+#ifndef MACOSX
+ MENUSEPARATOR_I("file");
+#endif
+ MENUNOP_I("edit", "u", gettext("Undo"), "undo",
+ MENUFLAG_INTERRUPT | MENUFLAG_NOPLAY |
+ MENUFLAG_NOOPTION, uih_undo);
+ MENUNOP_I("edit", NULL,
+ gettext("Redo"),
+ "redo",
+ MENUFLAG_INTERRUPT
+ | MENUFLAG_NOPLAY | MENUFLAG_NOOPTION, uih_redo);
+ SUBMENU_I("fractal", NULL, gettext("Formulae"), "mformula");
+ SUBMENU_I("fractal", NULL, gettext("More formulae"), "oformula");
+
+#ifdef SFFE_USING
+ /*FIXME: Should allow multiline */
+ MENUSEPARATOR_I("fractal");
+ MENUDIALOG_I("fractal", NULL, gettext("User formula"), "usrform", 0,
+ uih_sffein, uih_sffedialog);
+ MENUDIALOG_I("fractal", NULL, gettext("User initialization"),
+ "usrformInit", 0, uih_sffeinitin, uih_sffeinitdialog);
+#endif
+
+ MENUSEPARATOR_I("fractal");
+ SUBMENU_I("fractal", "f", gettext("Incoloring mode"), "mincoloring");
+ SUBMENU_I("fractal", "c", gettext("Outcoloring mode"), "moutcoloring");
+ SUBMENU_I("fractal", "i", gettext("Plane"), "mplane");
+ SUBMENU_I("fractal", NULL, gettext("Palette"), "palettemenu");
+ MENUSEPARATOR_I("fractal");
+ MENUCDIALOGCB_I("fractal", "m",
+ gettext("Mandelbrot mode"),
+ "uimandelbrot",
+ MENUFLAG_DIALOGATDISABLE |
+ MENUFLAG_INTERRUPT | UI,
+ uih_mandelbrotsw,
+ uih_getjuliadialog, uih_mandelbrotselected);
+ MENUCDIALOGCB_I("fractal", "b", gettext("Perturbation"),
+ "uiperturbation", MENUFLAG_INTERRUPT | UI, uih_persw,
+ uih_getperturbationdialog, uih_perselected);
+ MENUCDIALOG_I("fractal", NULL,
+ gettext("Perturbation"),
+ "perturbation",
+ MENUFLAG_NOMENU |
+ MENUFLAG_INTERRUPT,
+ uih_setperbutation, uih_getperturbationdialog);
+ MENUSEPARATOR_I("fractal");
+ MENUCDIALOG_I("fractal", NULL,
+ gettext("View"), "uiview",
+ MENUFLAG_INTERRUPT | UI, uih_dview, uih_getviewdialog);
+ MENUSEPARATOR_I("fractal");
+ MENUNOP_I("fractal", NULL,
+ gettext("Reset to defaults"), "initstate", 0, uih_initstate);
+ MENUDIALOG_I("fractal", NULL, gettext("Julia mode"), "julia",
+ MENUFLAG_NOMENU | MENUFLAG_INTERRUPT, uih_playjulia,
+ uih_juliamodedialog);
+ MENUDIALOG_I("fractal", NULL,
+ gettext("View"), "view",
+ MENUFLAG_NOMENU |
+ MENUFLAG_INTERRUPT, uih_plview, uih_plviewdialog);
+ MENUDIALOG_I("fractal", NULL, gettext("Set angle"), "angle",
+ MENUFLAG_NOMENU | MENUFLAG_INTERRUPT, uih_angle,
+ uih_angledialog);
+ MENUDIALOG_I("fractal", NULL,
+ gettext("Set plane"),
+ "plane",
+ MENUFLAG_NOMENU |
+ MENUFLAG_INTERRUPT, uih_setplane, uih_numdialog);
+ MENUDIALOG_I("fractal", NULL, gettext("Inside coloring mode"),
+ "incoloring", MENUFLAG_NOMENU | MENUFLAG_INTERRUPT,
+ uih_setincoloringmode, uih_numdialog);
+ MENUDIALOG_I("fractal", NULL,
+ gettext
+ ("Outside coloring mode"),
+ "outcoloring",
+ MENUFLAG_NOMENU |
+ MENUFLAG_INTERRUPT, uih_setoutcoloringmode,
+ uih_numdialog);
+ MENUDIALOG_I("fractal", NULL,
+ gettext("Inside truecolor coloring mode"), "intcoloring",
+ MENUFLAG_NOMENU | MENUFLAG_INTERRUPT, uih_setintcolor,
+ uih_numdialog);
+ MENUDIALOG_I("fractal", NULL,
+ gettext("Outside truecolor coloring mode"),
+ "outtcoloring", MENUFLAG_NOMENU | MENUFLAG_INTERRUPT,
+ uih_setouttcolor, uih_numdialog);
+ MENUDIALOG_I("fractal", NULL, gettext("Julia seed"), "juliaseed",
+ MENUFLAG_NOMENU | MENUFLAG_INTERRUPT, uih_setjuliaseed,
+ uih_coorddialog);
+ MENUNOP_I("palettemenu", "d", gettext("Default palette"), "defpalette",
+ 0, uih_mkdefaultpalette);
+ MENUNOP_I("palettemenu", "p", gettext("Random palette"),
+ "randompalette", 0, uih_menumkpalette);
+ MENUCDIALOG_I("palettemenu", NULL, gettext("Custom palette"),
+ "palette", 0, uih_palette, uih_getpalettedialog);
+ MENUSEPARATOR_I("palettemenu");
+ MENUNOPCB_I("palettemenu", "y",
+ gettext("Color cycling"),
+ "cycling", 0, uih_cyclingsw, uih_cyclingselected);
+ MENUNOPCB_I("palettemenu", "Y", gettext("Reversed color cycling"),
+ "rcycling", MENUFLAG_NOOPTION | MENUFLAG_NOPLAY,
+ uih_rcyclingsw, uih_rcyclingselected);
+ MENUCDIALOG_I("palettemenu", NULL,
+ gettext
+ ("Color cycling speed"),
+ "cyclingspeed", 0, uih_setcycling, uih_getcyclingdialog);
+ MENUSEPARATOR_I("palettemenu");
+ MENUDIALOG_I("palettemenu", NULL,
+ gettext("Shift palette"),
+ "shiftpalette", 0, uih_shiftpalette, uih_shiftdialog);
+ MENUNOP_I("palettemenu", "+", gettext("Shift one forward"), "fshift",
+ MENUFLAG_NOOPTION | MENUFLAG_NOPLAY, uih_fshift);
+ MENUNOP_I("palettemenu", "-",
+ gettext("Shift one backward"),
+ "bshift", MENUFLAG_NOOPTION | MENUFLAG_NOPLAY, uih_bshift);
+ SUBMENU_I("calc", NULL, gettext("Solid guessing"), "mguess");
+ SUBMENU_I("calc", NULL, gettext("Dynamic resolution"), "dynamic");
+ MENUNOPCB_I("calc", "k",
+ gettext("Periodicity checking"),
+ "periodicity", 0, uih_periodicitysw,
+ uih_periodicityselected);
+ MENUCDIALOG_I("calc", NULL, gettext("Iterations"), "maxiter",
+ MENUFLAG_INTERRUPT, uih_setmaxiter, uih_getiterdialog);
+ MENUCDIALOG_I("calc", NULL, gettext("Bailout"), "bailout",
+ MENUFLAG_INTERRUPT, uih_setbailout,
+ uih_getbailoutdialog);
+ MENUSEPARATOR_I("calc");
+ MENUNOPCB_I("calc", "j", gettext("Fast julia mode"), "fastjulia", 0,
+ uih_juliasw, uih_juliaselected);
+ SUBMENU_I("calc", "o", gettext("Rotation"), "rotate");
+ MENUDIALOG_I("calc", NULL, gettext("Solid guessing range"), "range",
+ MENUFLAG_NOMENU, uih_setguessing, uih_numdialog);
+ MENUINTRB_I("rotate", NULL,
+ gettext("Disable rotation"),
+ "norotate", UI, uih_rotate, 0, uih_rotateselected);
+ MENUSEPARATOR_I("rotate");
+ MENUINTRB_I("rotate", NULL,
+ gettext("Continuous rotation"),
+ "controtate", UI, uih_rotate,
+ ROTATE_CONTINUOUS, uih_rotateselected);
+ MENUINTRB_I("rotate", NULL, gettext("Rotate by mouse"), "mouserotate",
+ UI, uih_rotate, ROTATE_MOUSE, uih_rotateselected);
+ MENUCDIALOG_I("rotate", NULL,
+ gettext
+ ("Rotation speed"),
+ "rotationspeed", 0,
+ uih_rotationspeed, uih_getrotationdialog);
+ MENUDIALOG_I("rotate", NULL, gettext("Automatic rotation"),
+ "autorotate", MENUFLAG_NOMENU, uih_playautorotate,
+ uih_autorotatedialog);
+ MENUDIALOG_I("rotate", NULL,
+ gettext
+ ("Fast rotation mode"),
+ "fastrotate",
+ MENUFLAG_NOMENU,
+ (funcptr) uih_fastrotate, uih_fastrotatedialog);
+ MENUINTRB_I("dynamic", NULL, gettext("Disable dynamic resolution"),
+ "nodynamic", UI, uih_setfastmode, 1, uih_fastmode);
+ MENUSEPARATOR_I("dynamic");
+ MENUINTRB_I("dynamic", NULL, gettext("Use only during animation"),
+ "dynamicanimation", UI, uih_setfastmode, 2, uih_fastmode);
+ MENUINTRB_I("dynamic", NULL,
+ gettext
+ ("Use also for new images"),
+ "dynamicnew", UI, uih_setfastmode, 3, uih_fastmode);
+ MENUDIALOG_I("dynamic", NULL, gettext("Dynamic resolution mode"),
+ "fastmode", MENUFLAG_NOMENU, uih_setfastmode,
+ uih_fastmodedialog);
+ MENUNOPCB_I("ui", "a",
+ gettext("Autopilot"),
+ "autopilot", 0, uih_autopilotsw, uih_autopilotselected);
+ MENUSEPARATOR_I("ui");
+ MENUNOPCB_I("ui", "v",
+ gettext("VJ mode"),
+ "inhibittextoutput", 0, uih_inhibittextsw,
+ uih_inhibittextselected);
+ MENUSEPARATOR_I("ui");
+ MENUNOP_I("ui", "r", gettext("Recalculate"),
+ "recalculate", 0, uih_recalculate);
+ MENUNOP_I("ui", "z",
+ gettext
+ ("Interrupt"),
+ "interrupt",
+ MENUFLAG_INTERRUPT | MENUFLAG_INCALC, uih_interrupt);
+ MENUSEPARATOR_I("ui");
+ MENUCDIALOG_I("ui", NULL,
+ gettext("Zooming speed"), "speed",
+ 0, uih_setspeed, uih_getspeeddialog);
+ MENUNOPCB_I("ui", NULL, gettext("Fixed step"), "fixedstep", 0,
+ uih_fixedstepsw, uih_fixedstepselected);
+ MENUINTRB_I("mguess", NULL,
+ gettext
+ ("Disable solid guessing"),
+ "noguess", UI, uih_setguessing, 1, uih_guessingselected);
+ MENUSEPARATOR_I("mguess");
+ MENUINTRB_I("mguess", NULL,
+ gettext("Guess 2x2 rectangles"),
+ "guess2", UI, uih_setguessing, 2, uih_guessingselected);
+ MENUINTRB_I("mguess", NULL, gettext("Guess 3x3 rectangles"), "guess3",
+ UI, uih_setguessing, 3, uih_guessingselected);
+ MENUINTRB_I("mguess", NULL,
+ gettext
+ ("Guess 4x4 rectangles"),
+ "guess4", UI, uih_setguessing, 4, uih_guessingselected);
+ MENUINTRB_I("mguess", NULL, gettext("Guess 5x5 rectangles"), "guess5",
+ UI, uih_setguessing, 5, uih_guessingselected);
+ MENUINTRB_I("mguess", NULL,
+ gettext
+ ("Guess 6x6 rectangles"),
+ "guess6", UI, uih_setguessing, 6, uih_guessingselected);
+ MENUINTRB_I("mguess", NULL, gettext("Guess 7x7 rectangles"), "guess7",
+ UI, uih_setguessing, 7, uih_guessingselected);
+ MENUINTRB_I("mguess", NULL,
+ gettext
+ ("Guess 8x8 rectangles"),
+ "guess8", UI, uih_setguessing, 8, uih_guessingselected);
+ MENUINTRB_I("mguess", NULL, gettext("Guess unlimited rectangles"),
+ "guessall", UI, uih_setguessing, 2048,
+ uih_guessingselected);
+ /* Language selection is not sensible anymore if i18n is used: */
+#ifndef HAVE_GETTEXT
+ SUBMENU_I("tutor", NULL, gettext("Language"), "lang");
+ MENUSEPARATOR_I("tutor");
+#endif
+ SUBMENU_I("tutor", NULL, gettext("An introduction to fractals"),
+ "intro");
+ SUBMENU_I("tutor", NULL, gettext("XaoS features overview"),
+ "features");
+ SUBMENU_I("tutor", NULL, gettext("Math behind fractals"), "fmath");
+ SUBMENU_I("tutor", NULL, gettext("Other fractal types in XaoS"),
+ "otherf");
+ SUBMENU_I("tutor", NULL, gettext("What's new?"), "new");
+ /* Language selection is not sensible anymore if i18n is used: */
+#ifndef HAVE_GETTEXT
+ LANG_I("Cesky", "cesky");
+ LANG_I("Deutsch", "deutsch");
+ LANG_I("English", "english");
+ LANG_I("Espanhol", "espanhol");
+ LANG_I("Francais", "francais");
+ LANG_I("Magyar", "magyar");
+#endif
+ TUTOR_I("intro", gettext("Whole story"), "fractal.xaf");
+ MENUSEPARATOR_I("intro");
+ TUTOR_I("intro", gettext("Introduction"), "intro.xaf");
+ TUTOR_I("intro", gettext("Mandelbrot set"), "mset.xaf");
+ TUTOR_I("intro", gettext("Julia set"), "julia.xaf");
+ TUTOR_I("intro", gettext("Higher power Mandelbrots"), "power.xaf");
+ TUTOR_I("intro", gettext("Newton's method"), "newton.xaf");
+ TUTOR_I("intro", gettext("Barnsley's formula"), "barnsley.xaf");
+ TUTOR_I("intro", gettext("Phoenix"), "phoenix.xaf");
+ TUTOR_I("intro", gettext("Octo"), "octo.xaf");
+ TUTOR_I("intro", gettext("Magnet"), "magnet.xaf");
+ TUTOR_I("features", gettext("All features"), "features.xaf");
+ MENUSEPARATOR_I("features");
+ TUTOR_I("features", gettext("Outcoloring modes"), "outcolor.xaf");
+ TUTOR_I("features", gettext("Incoloring modes"), "incolor.xaf");
+ TUTOR_I("features", gettext("True-color coloring modes"),
+ "truecol.xaf");
+ TUTOR_I("features", gettext("Filters"), "filter.xaf");
+ TUTOR_I("features", gettext("Planes"), "plane.xaf");
+ TUTOR_I("features", gettext("Animations and position files"),
+ "anim.xaf");
+ TUTOR_I("features", gettext("Perturbation"), "pert.xaf");
+ TUTOR_I("features", gettext("Random palettes"), "palette.xaf");
+ TUTOR_I("features", gettext("Other noteworthy features"), "other.xaf");
+ TUTOR_I("fmath", gettext("Whole story"), "fmath.xaf");
+ MENUSEPARATOR_I("fmath");
+ TUTOR_I("fmath", gettext("The definition and fractal dimension"),
+ "dimension.xaf");
+ TUTOR_I("fmath", gettext("Escape time fractals"), "escape.xaf");
+ TUTOR_I("otherf", gettext("Other fractal types in XaoS"),
+ "otherfr.xaf");
+ MENUSEPARATOR_I("otherf");
+ TUTOR_I("otherf", gettext("Triceratops and Catseye fractals"),
+ "trice.xaf");
+ TUTOR_I("otherf", gettext("Mandelbar, Lambda, Manowar and Spider"),
+ "fourfr.xaf");
+ TUTOR_I("otherf",
+ gettext("Sierpinski Gasket, S.Carpet, Koch Snowflake"),
+ "classic.xaf");
+ TUTOR_I("new", gettext("What's new in 3.0?"), "new30.xaf");
+#ifdef DEBUG
+ printf("Filled %d menu items out of %d.\n", no_menuitems_i18n,
+ MAX_MENUITEMS_I18N);
+#endif
+ menu_add(menuitems_i18n, no_menuitems_i18n);
+ uih_no_menuitems_i18n = no_menuitems_i18n;
+}
+
+
+static CONST menuitem menuitems2[] = {
+ SUBMENU("mincoloring", NULL, "True-color incoloring mode",
+ "tincoloring"),
+ SUBMENU("moutcoloring", NULL, "True-color outcoloring mode",
+ "toutcoloring")
+};
+
+static int uih_selectedformula(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->currentformula == formulas + n);
+}
+
+static int uih_selectedincoloring(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->incoloringmode == n);
+}
+
+static void uih_setintruecolor(struct uih_context *c, int n)
+{
+ uih_setincoloringmode(c, 10);
+ uih_setintcolor(c, n);
+}
+
+static int uih_selectedintcoloring(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->intcolor == n);
+}
+
+static int uih_selectedoutcoloring(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->coloringmode == n);
+}
+
+static int uih_selectedplane(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->plane == n);
+}
+
+static void uih_setouttruecolor(struct uih_context *c, int n)
+{
+ uih_setoutcoloringmode(c, 10);
+ uih_setouttcolor(c, n);
+}
+
+static int uih_selectedouttcoloring(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->fcontext->outtcolor == n);
+}
+
+static int uih_filterenabled(struct uih_context *c, int n)
+{
+ if (c == NULL)
+ return 0;
+ return (c->filter[n] != NULL);
+}
+
+static void uih_filtersw(struct uih_context *c, int n)
+{
+ if (c->filter[n] != NULL)
+ uih_disablefilter(c, n);
+ else
+ uih_enablefilter(c, n);
+}
+
+static menuitem *formulaitems;
+static menuitem *filteritems;
+static char (*keys)[2];
+void uih_registermenus(void)
+{
+ menuitem *item;
+ int i;
+ menu_add(menuitems, NITEMS(menuitems));
+ formulaitems = item =
+ (menuitem *) malloc(sizeof(menuitem) * nformulas);
+
+ /* This code automatically generates code for fractal, incoloring and other
+ * menus*/
+ keys = malloc(sizeof(*keys) * nformulas);
+ for (i = 0; i < nformulas; i++) {
+ if (i < nmformulas) {
+ item[i].menuname = "mformula";
+ } else {
+ item[i].menuname = "oformula";
+ }
+ item[i].key = keys[i];
+ if (i < 9)
+ keys[i][0] = '1' + i;
+ else if (i == 9)
+ keys[i][0] = '0';
+#ifndef _MAC
+ else
+ keys[i][0] = '7' + i;
+#endif
+ keys[i][1] = 0;
+ item[i].type = MENU_INT;
+ item[i].flags =
+ MENUFLAG_RADIO | MENUFLAG_INTERRUPT | MENUFLAG_NOPLAY;
+ item[i].iparam = i;
+ item[i].name = formulas[i].name[!formulas[i].mandelbrot];
+ item[i].shortname = formulas[i].shortname;
+ item[i].function = (void (*)(void)) uih_setformula;
+ item[i].control = (int (*)(void)) uih_selectedformula;
+ }
+ menu_add(item, nformulas);
+
+ menu_genernumbered(INCOLORING - 1, "mincoloring", incolorname, NULL,
+ MENU_INT, UI | MENUFLAG_RADIO | MENUFLAG_INTERRUPT,
+ uih_setincoloringmode, uih_selectedincoloring,
+ "in");
+
+ menu_genernumbered(TCOLOR - 1, "tincoloring", tcolorname, NULL,
+ MENU_INT, UI | MENUFLAG_RADIO | MENUFLAG_INTERRUPT,
+ uih_setintruecolor, uih_selectedintcoloring, "int");
+
+ menu_genernumbered(OUTCOLORING - 1, "moutcoloring", outcolorname, NULL,
+ MENU_INT, UI | MENUFLAG_RADIO | MENUFLAG_INTERRUPT,
+ uih_setoutcoloringmode, uih_selectedoutcoloring,
+ "out");
+
+ menu_genernumbered(TCOLOR - 1, "toutcoloring", tcolorname, NULL,
+ MENU_INT, UI | MENUFLAG_RADIO | MENUFLAG_INTERRUPT,
+ uih_setouttruecolor, uih_selectedouttcoloring,
+ "outt");
+
+ {
+ int i;
+ for (i = 0; planename[i] != NULL; i++);
+ menu_genernumbered(i, "mplane", planename, NULL, MENU_INT,
+ UI | MENUFLAG_RADIO | MENUFLAG_INTERRUPT,
+ uih_setplane, uih_selectedplane, "plane");
+ }
+ filteritems = item =
+ (menuitem *) malloc(sizeof(menuitem) * uih_nfilters);
+
+ /* This code automatically generates code for fractal, incoloring and other
+ * menus*/
+ for (i = 0; i < uih_nfilters; i++) {
+ item[i].menuname = "mfilter";
+ item[i].key = NULL;
+ item[i].type = MENU_INT;
+ item[i].flags =
+ MENUFLAG_CHECKBOX | MENUFLAG_INTERRUPT | MENUFLAG_NOPLAY;
+ item[i].iparam = i;
+ item[i].name = uih_filters[i]->name;
+ item[i].shortname = uih_filters[i]->shortname;
+ if (!strcmp(item[i].shortname, "palette"))
+ item[i].shortname = "palettef";
+ /*this is one name collision because of ugly historical reasons */
+ item[i].function = (void (*)(void)) uih_filtersw;
+ item[i].control = (int (*)(void)) uih_filterenabled;
+ }
+ menu_add(item, uih_nfilters);
+
+ menu_add(menuitems2, NITEMS(menuitems2));
+}
+
+void uih_unregistermenus(void)
+{
+ menu_delete(menuitems, NITEMS(menuitems));
+ menu_delete(menuitems_i18n, uih_no_menuitems_i18n);
+
+ free(keys);
+ menu_delete(formulaitems, nformulas);
+ free(formulaitems);
+
+ menu_delnumbered(INCOLORING - 1, "in");
+
+ menu_delnumbered(TCOLOR - 1, "int");
+
+ menu_delnumbered(OUTCOLORING - 1, "out");
+
+ menu_delnumbered(TCOLOR - 1, "outt");
+ {
+ int i;
+ for (i = 0; planename[i] != NULL; i++);
+ menu_delnumbered(i, "plane");
+ }
+
+ menu_delete(filteritems, uih_nfilters);
+ free(filteritems);
+
+ menu_delete(menuitems2, NITEMS(menuitems2));
+}
+
+#ifdef SFFE_USING
+void uih_sffein(uih_context * c, CONST char *text)
+{
+ char str[200];
+ int err;
+ if (strlen(text)) {
+ c->parser->errormsg = (char *) str;
+ if ((err = sffe_parse(&c->parser, (char *) text)) > 0) {
+ uih_message(c, str);
+ sffe_parse(&c->parser, "z^2+c");
+ uih_sffedialog->defstr = c->parser->expression;
+ } else {
+ uih_sffedialog->defstr = c->parser->expression;
+ uih_message(c, c->parser->expression);
+ if (!(c->fcontext->currentformula->flags & SFFE_FRACTAL)) {
+ uih_play_formula(c, "user");
+ } else
+ uih_recalculate(c);
+ };
+
+ c->parser->errormsg = NULL;
+ };
+};
+
+void uih_sffeinitin(uih_context * c, CONST char *text)
+{
+ extern cmplx pZ;
+ extern cmplx C;
+ char str[200];
+ int err;
+ uih_sffeinitdialog->defstr = "";
+ if (strlen(text)) {
+ if (!c->pinit) {
+ c->pinit = sffe_alloc();
+ sffe_regvar(&c->pinit, &pZ, 'p');
+ sffe_regvar(&c->pinit, &C, 'c');
+ };
+
+ c->pinit->errormsg = (char *) str;
+ if ((err = sffe_parse(&c->pinit, (char *) text)) > 0) {
+ uih_message(c, str);
+ sffe_free(&c->pinit);
+ c->pinit = NULL;
+ } else {
+ uih_sffeinitdialog->defstr = c->pinit->expression; /*FIXME shouldnt this be done by str copy */
+ uih_message(c, c->pinit->expression);
+ if (!(c->fcontext->currentformula->flags & SFFE_FRACTAL)) {
+ uih_play_formula(c, "user");
+ } else
+ uih_recalculate(c);
+ c->pinit->errormsg = NULL;
+ };
+
+ } else if (c->pinit) {
+ sffe_free(&c->pinit);
+ c->pinit = NULL;
+ uih_recalculate(c);
+ };
+};
+#endif
diff --git a/src/ui-hlp/messg.c b/src/ui-hlp/messg.c
new file mode 100644
index 0000000..2a66fe2
--- /dev/null
+++ b/src/ui-hlp/messg.c
@@ -0,0 +1,145 @@
+#ifdef _plan9_
+#include <u.h>
+#include <libc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+#include <filter.h>
+#include <fractal.h>
+#include <timers.h>
+#include <ui_helper.h>
+#include <xerror.h>
+#include <misc-f.h>
+#include "grlib.h"
+#define EXPIRETIME 4000000
+static void
+getpos(uih_context * c, int *x, int *y, int *w, int *h, void *data)
+{
+ int n = (int) data;
+ if (c->messg.message[n] != NULL) {
+ int he = xtextheight(c->font);
+ *y = c->messg.messagestart + he * n;
+ *h = he;
+ *w = xtextwidth(c->font, c->messg.message[n]);
+ *x = (c->image->width - *w) / 2;
+ } else {
+ *w = *h = *x = *y = 0;
+ }
+}
+
+static void draw(uih_context * c, void *data)
+{
+ int x, y, w;
+ int n = (int) data;
+ if (c->messg.message[n] != NULL) {
+ int h = xtextheight(c->font);
+ y = c->messg.messagestart + h * n;
+ w = xtextwidth(c->font, c->messg.message[n]);
+ x = (c->image->width - w) / 2;
+ if (c->messg.messagetype[n])
+ xprint(c->image, c->font, x, y, c->messg.message[n],
+ (c->image->flags & AAIMAGE) ? BGCOLOR(c) : SELCOLOR(c),
+ BGCOLOR(c), 0);
+ else
+ xprint(c->image, c->font, x, y, c->messg.message[n],
+ (c->image->flags & AAIMAGE) ? BGCOLOR(c) : FGCOLOR(c),
+ BGCOLOR(c), 0);
+ }
+}
+
+void uih_rmmessage(uih_context * c, int pid)
+{
+ int i;
+ for (i = 0; i < NMESSAGES && c->messg.pid[i] != pid; i++);
+ if (i == NMESSAGES)
+ return;
+ if (c->messg.message[i] == NULL)
+ return;
+ free(c->messg.message[i]);
+ tl_remove_timer(c->messg.messagetimer[i]);
+ tl_free_timer(c->messg.messagetimer[i]);
+ c->messg.message[i] = NULL;
+ for (; i < NMESSAGES - 1; i++) {
+ c->messg.message[i] = c->messg.message[i + 1];
+ c->messg.messagetimer[i] = c->messg.messagetimer[i + 1];
+ c->messg.messagetype[i] = c->messg.messagetype[i + 1];
+ c->messg.pid[i] = c->messg.pid[i + 1];
+ }
+ c->messg.message[NMESSAGES - 1] = NULL;
+ c->display = 1;
+}
+
+void uih_scrollup(uih_context * c)
+{
+ uih_rmmessage(c, c->messg.pid[0]);
+}
+
+void uih_clearmessages(uih_context * c)
+{
+ while (c->messg.message[0] != NULL)
+ uih_scrollup(c);
+}
+
+void uih_initmessages(uih_context * c)
+{
+ int i;
+ for (i = 0; i < NMESSAGES; i++) {
+ c->messg.message[i] = NULL;
+ c->messg.w[i] = uih_registerw(c, getpos, draw, (void *) i, 0);
+ }
+ c->messg.messagestart = 0;
+}
+
+void uih_destroymessages(uih_context * c)
+{
+ int i;
+ uih_clearmessages(c);
+ for (i = 0; i < NMESSAGES; i++)
+ uih_removew(c, c->messg.w[i]);
+}
+
+static int uih_message1(uih_context * c, CONST char *message, int type)
+{
+ static int pid;
+ int i;
+ for (i = 0; i < NMESSAGES && c->messg.message[i] != NULL; i++);
+ if (i == NMESSAGES)
+ uih_scrollup(c), i--;
+ c->messg.message[i] = mystrdup(message);
+ c->messg.messagetype[i] = type;
+ c->messg.messagetimer[i] = tl_create_timer();
+ tl_reset_timer(c->messg.messagetimer[i]);
+ tl_set_interval(c->messg.messagetimer[i], 1);;
+ tl_slowdown_timer(c->messg.messagetimer[i], EXPIRETIME);;
+ tl_set_handler(c->messg.messagetimer[i],
+ (void (*)(void *)) uih_scrollup, c);
+ tl_add_timer(syncgroup, c->messg.messagetimer[i]);
+ /*tl_remove_timer (c->messg.messagetimer[i]); */
+ c->messg.pid[i] = ++pid;
+ c->display = 1;
+ return (pid);
+}
+
+int uih_message(uih_context * c, CONST char *message)
+{
+ if (c->inhibittextoutput)
+ return 0;
+
+ return (uih_message1(c, message, 0));
+}
+
+int uih_error(uih_context * c, CONST char *error)
+{
+ char str[256];
+ sprintf(str, "Error: %s", error);
+ c->errstring = error;
+ return (uih_message1(c, str, 1));
+}
+
+void uih_printmessages(uih_context * c)
+{
+ int i;
+ for (i = 0; i < NMESSAGES && c->messg.message[i] != NULL; i++)
+ x_message(c->messg.message[i], stderr);
+}
diff --git a/src/ui-hlp/play.c b/src/ui-hlp/play.c
new file mode 100644
index 0000000..17430d6
--- /dev/null
+++ b/src/ui-hlp/play.c
@@ -0,0 +1,946 @@
+#include <config.h>
+#ifndef _plan9_
+#include <limits.h>
+#ifdef NO_MALLOC_H
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include <string.h>
+#else
+#include <u.h>
+#include <libc.h>
+#endif
+#include <fconfig.h>
+#include <filter.h>
+#include <fractal.h>
+#include <ui_helper.h>
+#include <catalog.h>
+#include <xmenu.h>
+#include <grlib.h>
+#include "play.h"
+
+#ifdef HAVE_GETTEXT
+#include <libintl.h>
+#else
+#define gettext(STRING) STRING
+#endif
+
+#define nextchar() (uih->playstring==NULL?xio_getc(FD):uih->playstring[uih->playpos++])
+#define ungetchar(c) (uih->playstring==NULL?xio_ungetc(c,FD):uih->playpos--)
+#define endoffile() (uih->playstring==NULL?xio_feof(FD):uih->playstring[uih->playpos]==0)
+static int nonblockmode;
+static catalog_t *catalog; /*The message catalog should be "session wide" */
+CONST static char *errstring;
+#define seterr(str) {if(errstring==NULL) errstring=str;}
+#define FD uih->playc->file
+static char token[1024];
+static int first;
+static int last;
+static int parsenext;
+
+static CONST char *CONST animroot = "animroot";
+
+static inline struct uih_line *uih_findkey(uih_context * c, int key)
+{
+ struct uih_line *l = c->playc->lines.first;
+ while (l != NULL) {
+ if (l->key == key)
+ return l;
+ l = l->next;
+ }
+ return NULL;
+}
+
+static inline void uih_removeline(uih_context * c, struct uih_line *l)
+{
+ if (l == NULL)
+ return;
+ uih_removew(c, l->w);
+ if (l->prev)
+ l->prev->next = l->next;
+ else
+ c->playc->lines.first = l->next;
+ if (l->next)
+ l->next->prev = l->prev;
+ free(l);
+}
+
+void uih_line(uih_context * c, dialogparam * d)
+{
+ struct uih_window *w;
+ struct uih_line *l;
+ if (c->playstring != NULL) {
+ seterr(gettext("line available only in animation replay"));
+ return;
+ }
+ w = uih_registerline(c, 0, -1, -1, -1, -1);
+ uih_removeline(c, uih_findkey(c, c->playc->lines.currkey));
+ l = (struct uih_line *) calloc(1, sizeof(*l));
+ l->posmode = d[0].dint;
+ l->w = w;
+ l->x1 = d[1].dcoord[0];
+ l->y1 = d[1].dcoord[1];
+ l->x2 = d[2].dcoord[0];
+ l->y2 = d[2].dcoord[1];
+ l->color = c->color;
+ l->morph = 0;
+ l->key = c->playc->lines.currkey++;
+ l->prev = NULL;
+ l->next = c->playc->lines.first;
+ c->playc->lines.first = l;
+}
+
+void uih_morphline(uih_context * c, dialogparam * d)
+{
+ struct uih_line *l;
+ l = uih_findkey(c, c->playc->lines.currkey);
+ if (l == NULL) {
+ seterr(gettext("Morphing non existing line!"));
+ return;
+ }
+ c->playc->lines.currkey++;
+ l->mposmode = d[0].dint;
+ l->mx1 = d[1].dcoord[0];
+ l->my1 = d[1].dcoord[1];
+ l->mx2 = d[2].dcoord[0];
+ l->my2 = d[2].dcoord[1];
+ l->morph = 1;
+ c->playc->lines.morphing = 1;
+}
+
+void uih_morphlastline(uih_context * c, dialogparam * d)
+{
+ c->playc->lines.currkey--;
+ uih_morphline(c, d);
+}
+
+void uih_setkey(uih_context * c, int line)
+{
+ if (!c->play) {
+ seterr(gettext("linekey not available in this context!"));
+ return;
+ }
+ c->playc->lines.currkey = line;
+}
+
+static void uih_stopmorphing(uih_context * c)
+{
+ struct uih_line *l = c->playc->lines.first;
+ while (l) {
+ if (l->morph) {
+ l->x1 = l->mx1;
+ l->y1 = l->my1;
+ l->x2 = l->mx2;
+ l->y2 = l->my2;
+ l->posmode = l->mposmode;
+ l->morph = 0;
+ c->playc->lines.morphing = 1;
+ }
+ l = l->next;
+ }
+}
+
+void uih_update_lines(uih_context * c)
+{
+ int m = 0;
+ int co;
+ struct uih_line *l = c->playc->lines.first;
+ int x1, y1, x2, y2;
+ number_t x, y;
+ 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->morphlinetimes[0],
+ c->playc->morphlinetimes[1]);
+
+
+ while (l) {
+ switch (l->posmode) {
+ case 0:
+ x1 = (int) (c->image->width * l->x1);
+ y1 = (int) (c->image->height * l->y1);
+ x2 = (int) (c->image->width * l->x2);
+ y2 = (int) (c->image->height * l->y2);
+ break;
+ case 1:
+ x = c->image->width * c->image->pixelwidth;
+ y = c->image->height * c->image->pixelheight;
+ if (x > y)
+ x = y;
+ x1 = (int) (c->image->width / 2 +
+ (l->x1 - 0.5) * x / c->image->pixelwidth);
+ y1 = (int) (c->image->height / 2 +
+ (l->y1 - 0.5) * x / c->image->pixelheight);
+ x2 = (int) (c->image->width / 2 +
+ (l->x2 - 0.5) * x / c->image->pixelwidth);
+ y2 = (int) (c->image->height / 2 +
+ (l->y2 - 0.5) * x / c->image->pixelheight);
+ break;
+ case 2:
+ x = l->x1;
+ y = l->y1;
+ rotate(*(c->fcontext), x, y);
+ x = (x - c->fcontext->rs.nc) / (c->fcontext->rs.mc -
+ c->fcontext->rs.nc) *
+ c->zengine->image->width;
+ y = (y - c->fcontext->rs.ni) / (c->fcontext->rs.mi -
+ c->fcontext->rs.ni) *
+ c->zengine->image->height;
+ x1 = (int) x;
+ y1 = (int) y;
+ c->zengine->action->convertup(c->zengine, &x1, &y1);
+ x = l->x2;
+ y = l->y2;
+ rotate(*(c->fcontext), x, y);
+ x = (x - c->fcontext->rs.nc) / (c->fcontext->rs.mc -
+ c->fcontext->rs.nc) *
+ c->zengine->image->width;
+ y = (y - c->fcontext->rs.ni) / (c->fcontext->rs.mi -
+ c->fcontext->rs.ni) *
+ c->zengine->image->height;
+ x2 = (int) x;
+ y2 = (int) y;
+ c->zengine->action->convertup(c->zengine, &x2, &y2);
+ break;
+ }
+ if (l->morph) {
+ int mx1, mx2, my1, my2;
+ m = 1;
+ switch (l->mposmode) {
+ case 0:
+ mx1 = (int) (c->image->width * l->mx1);
+ my1 = (int) (c->image->height * l->my1);
+ mx2 = (int) (c->image->width * l->mx2);
+ my2 = (int) (c->image->height * l->my2);
+ break;
+ case 1:
+ x = c->image->width * c->image->pixelwidth;
+ y = c->image->height * c->image->pixelheight;
+ if (x > y)
+ x = y;
+ mx1 =
+ (int) (c->image->width / 2 +
+ (l->mx1 - 0.5) * x / c->image->pixelwidth);
+ my1 =
+ (int) (c->image->height / 2 +
+ (l->my1 - 0.5) * x / c->image->pixelheight);
+ mx2 =
+ (int) (c->image->width / 2 +
+ (l->mx2 - 0.5) * x / c->image->pixelwidth);
+ my2 =
+ (int) (c->image->height / 2 +
+ (l->my2 - 0.5) * x / c->image->pixelheight);
+ break;
+ default:
+ x = l->mx1;
+ y = l->my1;
+ rotate(*(c->fcontext), x, y);
+ x = (x - c->fcontext->rs.nc) / (c->fcontext->rs.mc -
+ c->fcontext->rs.nc) *
+ c->zengine->image->width;
+ y = (y - c->fcontext->rs.ni) / (c->fcontext->rs.mi -
+ c->fcontext->rs.ni) *
+ c->zengine->image->height;
+ mx1 = (int) x;
+ my1 = (int) y;
+ c->zengine->action->convertup(c->zengine, &mx1, &my1);
+ x = l->mx2;
+ y = l->my2;
+ rotate(*(c->fcontext), x, y);
+ x = (x - c->fcontext->rs.nc) / (c->fcontext->rs.mc -
+ c->fcontext->rs.nc) *
+ c->zengine->image->width;
+ y = (y - c->fcontext->rs.ni) / (c->fcontext->rs.mi -
+ c->fcontext->rs.ni) *
+ c->zengine->image->height;
+ mx2 = (int) x;
+ my2 = (int) y;
+ c->zengine->action->convertup(c->zengine, &mx2, &my2);
+ break;
+ }
+ x1 = (int) (x1 + (mx1 - x1) * mmul);
+ y1 = (int) (y1 + (my1 - y1) * mmul);
+ x2 = (int) (x2 + (mx2 - x2) * mmul);
+ y2 = (int) (y2 + (my2 - y2) * mmul);
+ }
+ switch (l->color) {
+ case 1:
+ co = BGCOLOR(c);
+ break;
+ case 0:
+ co = FGCOLOR(c);
+ break;
+ default:
+ co = SELCOLOR(c);
+ break;
+ }
+ uih_setline(c, l->w, co, x1, y1, x2, y2);
+
+ l = l->next;
+ }
+ c->playc->lines.morphing = m;
+ if (m)
+ c->display = 1;
+
+}
+
+void uih_clear_line(uih_context * c)
+{
+ if (c->playstring != NULL) {
+ seterr(gettext("clear_line available only in animation replay"));
+ return;
+ }
+ uih_removeline(c, uih_findkey(c, c->playc->lines.currkey++));
+}
+
+void uih_clear_lines(uih_context * c)
+{
+ if (c->playstring != NULL) {
+ seterr(gettext("clear_lines available only in animation replay"));
+ return;
+ }
+ while (c->playc->lines.first != NULL)
+ uih_removeline(c, c->playc->lines.first);
+ c->playc->lines.currkey = 0;
+}
+
+void uih_freecatalog(uih_context * c)
+{
+ if (catalog != NULL)
+ free_catalog(catalog), catalog = NULL;
+}
+
+void uih_setfont(struct uih_context *uih)
+{
+ if (catalog != NULL && find_text(catalog, "encoding")
+ && find_text(catalog, "encoding")[0] == '2')
+ uih->encoding = 2;
+ else
+ uih->encoding = 1;
+ if (uih->image->flags & AAIMAGE)
+ uih->font = &xaafont;
+ else {
+ if (uih->encoding == 2) {
+ // A better heuristics would be used later.
+ if (uih->image->width > 1000 && uih->image->height > 720)
+ uih->font = &xbigfont3;
+ else {
+ if (uih->image->width > 800 && uih->image->height > 600)
+ uih->font = &xbigfont2;
+ else {
+ if (uih->image->pixelheight < 0.07)
+ uih->font = &xbigfont;
+ else
+ uih->font = &xsmallfont;
+ }
+ }
+ } else {
+ if (uih->image->pixelheight < 0.04)
+ uih->font = &xbigfontil1;
+ else if (uih->image->pixelheight < 0.07)
+ uih->font = &xmedfontil1;
+ else
+ uih->font = &xsmallfontil1;
+ }
+ }
+}
+
+int uih_loadcatalog(uih_context * c, CONST char *name)
+{
+ static int firsttime = 1;
+ static CONST char *str;
+ xio_file f = xio_getcatalog(name);
+ if (f == XIO_FAILED) {
+ if (firsttime) {
+ firsttime = 0;
+ return 0;
+ } /*Let XaoS work as stand alone executable */
+ uih_error(c, gettext("Catalog file not found"));
+ return 0;
+ }
+ firsttime = 0;
+ if (catalog != NULL)
+ free_catalog(catalog);
+ catalog = load_catalog(f, &str);
+ if (str != NULL)
+ uih_error(c, str);
+ uih_setfont(c);
+ return (catalog != NULL);
+}
+
+static void handler(void *userdata)
+{
+ struct uih_context *uih = (struct uih_context *) userdata;
+ uih->playc->playframe++;
+ uih->inanimation = 2;
+ if (uih->playc->timerin)
+ tl_remove_timer(uih->playc->timer);
+ uih->playc->timerin = 0;
+}
+
+static void handler1(void *userdata)
+{
+ struct uih_context *uih = (struct uih_context *) userdata;
+ uih->playc->playframe++;
+ uih->inanimation = 2;
+ tl_update_time();
+ tl_reset_timer(uih->playc->timer);
+ uih_setcomplettehandler(uih, NULL, NULL);
+}
+
+void uih_skipframe(struct uih_context *uih)
+{
+ if (uih->play && uih->playc->timerin)
+ handler(uih), tl_reset_timer(uih->playc->timer);
+}
+
+int
+uih_replayenable(struct uih_context *uih, xio_file f,
+ xio_constpath filename, int animr)
+{
+ struct uih_playcontext *p;
+ CONST char *s;
+ if (uih->play) {
+ uih_error(uih, gettext("Replay is already active"));
+ return 0;
+ }
+ if (f == XIO_FAILED) {
+ uih_error(uih, gettext("File open failed"));
+ return 0;
+ }
+ p = (struct uih_playcontext *) calloc(1, sizeof(*p));
+ if (p == NULL) {
+ uih_error(uih, gettext("Out of memory"));
+ return 0;
+ }
+ if (animr) {
+ uih->menuroot = animroot;
+ uih_updatemenus(uih, NULL);
+ }
+ p->file = f;
+ p->playframe = 1;
+ p->timer = tl_create_timer();
+ p->frametime = 0;
+ p->morph = 0;
+ p->morphjulia = 0;
+ p->lines.first = NULL;
+ p->lines.morphing = 0;
+ p->lines.currkey = 0;
+ tl_update_time();
+ tl_set_handler(p->timer, handler, uih);
+ uih_stoptimers(uih);
+ if (uih->stoppedtimers)
+ tl_stop_timer(p->timer);
+ uih->playc = p;
+ uih->play = 1;
+ uih_emulatetimers(uih);
+ tl_reset_timer(p->timer);
+ uih->playc->line = 1;
+ if (filename != NULL) {
+ uih->playc->directory = xio_getdirectory(filename);
+ } else {
+ uih->playc->directory = xio_getdirectory(XIO_EMPTYPATH);
+ }
+ uih->playc->level = 0;
+ s = uih->playstring;
+ uih->playstring = NULL;
+ uih_playupdate(uih);
+ uih->playstring = s;
+ return 1;
+}
+
+void uih_replaydisable(struct uih_context *uih)
+{
+ if (uih->play) {
+ int i;
+ uih->play = 0;
+ tl_free_timer(uih->playc->timer);
+ if (uih->menuroot == animroot) {
+ uih->menuroot = "root";
+ uih_updatemenus(uih, NULL);
+ }
+ xio_close(uih->playc->file);
+ for (i = 0; i < uih->playc->level; i++)
+ xio_close(uih->playc->prevfiles[i]);
+ uih->display = 1;
+ uih->nonfractalscreen = 0;
+ uih_setcomplettehandler(uih, NULL, NULL);
+ uih_clear_lines(uih);
+ free(uih->playc->directory);
+ free(uih->playc);
+ uih_display(uih);
+ }
+}
+
+static void skipblank(struct uih_context *uih)
+{
+ int c;
+ if (uih->playstring != NULL) {
+ while ((uih->playstring[uih->playpos] == ' ' ||
+ uih->playstring[uih->playpos] == '\t' ||
+ uih->playstring[uih->playpos] == '\r' ||
+ uih->playstring[uih->playpos] == '\n'))
+ uih->playpos++;
+ return;
+ }
+ do {
+ c = xio_getc(FD);
+ if (c == '\n')
+ uih->playc->line++;
+ if (c == ';')
+ while (c != '\n' && !xio_feof(FD)) {
+ c = xio_getc(FD);
+ if (c == '\n')
+ uih->playc->line++;
+ }
+ while (xio_feof(FD) && uih->playc->level) {
+ c = XIO_EOF + 1;
+ xio_close(FD);
+ uih->playc->file = uih->playc->prevfiles[--uih->playc->level];
+ uih->playc->line = 1;
+ }
+ }
+ while (c == ' ' || c == '\t' || c == '\n' || c == '\r'
+ || c == XIO_EOF + 1);
+ if (c != XIO_EOF)
+ xio_ungetc(c, FD);
+}
+
+static int gettoken(struct uih_context *uih)
+{
+ int c;
+ int i = 0;
+ skipblank(uih);
+ if (first && ((c = nextchar()) != '(')) {
+ if (c && !endoffile()) {
+ seterr("'(' expected");
+ }
+ last = 1;
+ return -1;
+ }
+ if (first)
+ skipblank(uih), first = 0;
+ if (endoffile()) {
+ if (uih->playstring) {
+ seterr(gettext("Missing parameter"));
+ } else
+ seterr(gettext("Unexpected end of file"));
+ return 0;
+ }
+ if ((c = nextchar()) == '"') {
+ while (c == '\r')
+ c = nextchar();
+ token[i] = '"';
+ i++;
+ do {
+ c = nextchar();
+ while (c == '\r')
+ c = nextchar();
+ if (c == XIO_EOF || c == 0) {
+ if (uih->playstring) {
+ seterr(gettext("Missing parameter"));
+ } else
+ seterr(gettext("Unexpected end of file"));
+ return 0;
+ }
+ if (c == '\n' && uih->playstring == NULL)
+ uih->playc->line++;
+ if (c == '\\')
+ token[i] = nextchar();
+ else
+ token[i] = c;
+ i++;
+ if (i >= 1024) {
+ seterr(gettext("Token is too long"));
+ i = 0;
+ }
+ }
+ while (c != '"');
+ } else
+ ungetchar(c);
+ do {
+ c = nextchar();
+ if (c == XIO_EOF || c == 0) {
+ if (uih->playstring) {
+ seterr(gettext("Missing parameter"));
+ } else
+ seterr(gettext("Unexpected end of file"));
+ return 0;
+ }
+ token[i] = c;
+ i++;
+ if (i >= 1024) {
+ seterr(gettext("Token is too long"));
+ i = 0;
+ }
+ }
+ while (c != ' ' && c != '\t' && c != ')' && c != '\n' && c != '\r');
+ i--;
+ token[i] = 0;
+ skipblank(uih);
+ if (c == ')') {
+ last = 1;
+ return i;
+ }
+ c = nextchar();
+ if (uih->playstring == NULL) {
+ while (xio_feof(FD) && uih->playc->level)
+ uih->playc->file =
+ uih->playc->prevfiles[--uih->playc->level],
+ uih->playc->line = 1;
+ }
+ if (c == XIO_EOF || c == 0) {
+ if (uih->playstring) {
+ seterr(gettext("Missing parameter"));
+ } else
+ seterr(gettext("Unexpected end of file"));
+ return 0;
+ }
+ if (c == ')') {
+ last = 1;
+ return i;
+ }
+ ungetchar(c);
+ return i;
+}
+
+static char *gettokenwr(struct uih_context *c)
+{
+ if (last)
+ return NULL;
+ if (gettoken(c) < 0)
+ return NULL;
+ if (errstring)
+ return NULL;
+ return (token);
+}
+
+void uih_play_formula(struct uih_context *uih, char *fname)
+{
+ int i;
+ for (i = 0; i < nformulas; i++) {
+ if (!strcmp(formulas[i].shortname, fname)) {
+ set_formula(uih->fcontext, i);
+ uih_newimage(uih);
+ return;
+ }
+ }
+ seterr(gettext("Unknown formula type"));
+}
+
+void uih_playmorph(struct uih_context *uih, dialogparam * d)
+{
+ if (uih->playstring != NULL) {
+ seterr(gettext("morph available only in animation replay"));
+ return;
+ }
+ if (d[2].number <= 0 || d[3].number <= 0) {
+ seterr(gettext("morphview: Invalid viewpoint"));
+ uih->playc->destination = uih->fcontext->currentformula->v;
+ }
+ uih->playc->source = uih->fcontext->s;
+ uih->playc->destination.cr = d[0].number;
+ uih->playc->destination.ci = d[1].number;
+ uih->playc->destination.rr = d[2].number;
+ uih->playc->destination.ri = d[3].number;
+ uih->playc->morph = 1;
+}
+
+void uih_playmove(struct uih_context *uih, number_t x, number_t y)
+{
+ if (uih->playstring != NULL) {
+ seterr(gettext("move available only in animation replay"));
+ return;
+ }
+ uih->playc->source = uih->fcontext->s;
+ uih->playc->destination.cr = x;
+ uih->playc->destination.ci = y;
+ uih->playc->destination.rr = uih->fcontext->s.rr;
+ uih->playc->destination.ri = uih->fcontext->s.ri;
+ uih->playc->morph = 1;
+}
+
+void uih_playmorphjulia(struct uih_context *uih, number_t x, number_t y)
+{
+ if (uih->playstring != NULL) {
+ seterr(gettext("morphjulia available only in animation replay"));
+ return;
+ }
+ uih->playc->sr = uih->fcontext->pre;
+ uih->playc->si = uih->fcontext->pim;
+ uih->playc->dr = x;
+ uih->playc->di = y;
+ uih->playc->morphjulia = 1;
+}
+
+void uih_playmorphangle(struct uih_context *uih, number_t angle)
+{
+ if (uih->playstring != NULL) {
+ seterr(gettext("morphangle available only in animation replay"));
+ return;
+ }
+ uih->playc->morphangle = 1;
+ uih->playc->srcangle = uih->fcontext->angle;
+ uih->playc->destangle = angle;
+}
+
+void uih_playautorotate(struct uih_context *uih, int mode)
+{
+ if (mode) {
+ uih_fastrotateenable(uih);
+ uih_rotatemode(uih, ROTATE_CONTINUOUS);
+ } else
+ uih_rotatemode(uih, ROTATE_NONE);
+}
+
+void uih_playfilter(struct uih_context *uih, dialogparam * p)
+{
+ CONST char *fname = p[0].dstring;
+ int mode;
+ int i;
+ for (i = 0; i < uih_nfilters; i++) {
+ if (!strcmp(uih_filters[i]->shortname, fname)) {
+ mode = p[1].dint;
+ if (mode)
+ uih_enablefilter(uih, i);
+ else
+ uih_disablefilter(uih, i);
+ return;
+ }
+ }
+ seterr(gettext("Unknown filter"));
+}
+
+void uih_playdefpalette(struct uih_context *uih, int shift)
+{
+ if (uih->zengine->fractalc->palette == NULL)
+ return;
+ if (mkdefaultpalette(uih->zengine->fractalc->palette) != 0) {
+ uih_newimage(uih);
+ }
+ uih->palettetype = 0;
+ uih->palettechanged = 1;
+ if (shiftpalette(uih->zengine->fractalc->palette, shift)) {
+ uih_newimage(uih);
+ }
+ uih->manualpaletteshift = 0;
+ uih->paletteshift = shift;
+}
+
+void uih_zoomcenter(struct uih_context *uih, number_t x, number_t y)
+{
+ uih->xcenter = x;
+ uih->ycenter = y;
+ uih->xcenterm = INT_MAX;
+ uih->ycenterm = INT_MAX;
+}
+
+extern char *xtextposnames[];
+extern char *ytextposnames[];
+void uih_playtextpos(struct uih_context *uih, dialogparam * p)
+{
+ int x, y;
+ x = p[0].dint;
+ y = p[1].dint;
+ uih_settextpos(uih, x, y);
+}
+
+void uih_playusleep(struct uih_context *uih, int time)
+{
+ parsenext = 0;
+ if (uih->playstring != NULL) {
+ seterr(gettext("sleep available only in animation replay"));
+ return;
+ }
+ uih->playc->frametime = time;
+ if (time < tl_lookup_timer(uih->playc->timer) /*&&((!uih->step)||(!uih->zoomactive)) */
+ ) {
+ tl_slowdown_timer(uih->playc->timer, time);
+ uih->playc->playframe++;
+ } else {
+ tl_set_interval(uih->playc->timer, time);
+ if (!uih->playc->timerin) {
+ uih->playc->timerin = 1;
+ tl_add_timer(syncgroup, uih->playc->timer);
+ } else
+ printf(gettext("Internal program error #12 %i\n"),
+ uih->playc->playframe);
+ }
+ uih->playc->starttime = tl_lookup_timer(uih->playc->timer);
+}
+
+void uih_playtextsleep(struct uih_context *uih)
+{
+ uih_playusleep(uih,
+ 500000 + 1000000 * (uih->nletters +
+ uih->todisplayletters) /
+ uih->letterspersec);
+ uih->nletters = 0;
+ uih->todisplayletters = 0;
+}
+
+
+void uih_playwait(struct uih_context *uih)
+{
+ parsenext = 0;
+ if (uih->playstring != NULL) {
+ seterr(gettext("wait available only in animation replay"));
+ return;
+ }
+ if (!uih->uncomplette && !uih->display && !uih->recalculatemode
+ && !uih->displaytext && !uih->clearscreen) {
+ uih->playc->playframe++;
+ } else {
+ uih_setcomplettehandler(uih, handler1, uih);
+ }
+}
+
+void uih_playjulia(struct uih_context *uih, int julia)
+{
+ julia = !julia;
+ if (julia != uih->fcontext->mandelbrot) {
+ uih->fcontext->mandelbrot = julia;
+ uih->fcontext->version++;
+ uih_updatemenus(uih, "uimandelbrot");
+ uih_newimage(uih);
+ }
+}
+
+void uih_playcalculate(struct uih_context *uih)
+{
+ uih_newimage(uih);
+}
+
+void uih_playzoom(struct uih_context *uih)
+{
+ uih->zoomactive = 1;
+}
+
+void uih_playunzoom(struct uih_context *uih)
+{
+ uih->zoomactive = -1;
+}
+
+void uih_playstop(struct uih_context *uih)
+{
+ uih->zoomactive = 0;
+}
+
+void uih_playmessage(struct uih_context *uih, char *name)
+{
+ char *message;
+ if (catalog == NULL) {
+ uih_text(uih, gettext("No catalog file loaded"));
+ return;
+ }
+ message = find_text(catalog, name);
+ if (message == NULL) {
+ uih_text(uih, gettext("Message not found in catalog file"));
+ return;
+ }
+ uih_text(uih, message);
+}
+
+void uih_playload(struct uih_context *uih, xio_path file)
+{
+ xio_file f;
+ xio_pathdata tmp;
+ if (uih->playstring != NULL) {
+ seterr(gettext("load available only in animation replay"));
+ return;
+ }
+ if (uih->playc->level == MAXLEVEL) {
+ seterr(gettext("Include level overflow"));
+ return;
+ }
+
+
+ xio_addfname(tmp, uih->playc->directory, file);
+ f = xio_ropen(tmp);
+
+ if (f == XIO_FAILED) {
+ seterr(gettext("File not found"));
+ return;
+ }
+ uih->playc->prevfiles[uih->playc->level] = uih->playc->file;
+ uih->playc->level++;
+ uih->playc->file = f;
+ uih->playc->line = 1;
+}
+
+static void uih_processcommand(struct uih_context *uih, int flags)
+{
+ CONST char *error;
+ first = 1;
+ last = 0;
+ error = menu_processcommand(uih, gettokenwr, 1, flags, uih->menuroot);
+ if (error != NULL)
+ seterr(error);
+ if (!last) {
+ seterr(gettext("Too many parameters"));
+ }
+}
+
+void uih_playupdate(struct uih_context *uih)
+{
+ static char errtext[1024];
+ errstring = NULL;
+ while (uih->play && uih->playc->playframe && errstring == NULL) {
+ parsenext = 1;
+ uih->playc->playframe--;
+ if (uih->playc->lines.morphing) {
+ uih_stopmorphing(uih);
+ uih->display = 1;
+ }
+ if (uih->playc->morph) {
+ uih->fcontext->s = uih->playc->destination;
+ uih_animate_image(uih);
+ uih->playc->morph = 0;
+ }
+ if (uih->playc->morphangle) {
+ uih_angle(uih, uih->playc->destangle);
+ uih->playc->morphangle = 0;
+ }
+ if (uih->playc->morphjulia) {
+ uih_setjuliaseed(uih, uih->playc->dr, uih->playc->di);
+ uih->playc->morphjulia = 0;
+ }
+ while (!xio_feof(FD) && parsenext && errstring == NULL) {
+ uih_processcommand(uih, MENUFLAG_NOPLAY);
+ } /*while parsenext */
+ uih_update_lines(uih);
+ if (errstring != NULL) {
+ uih_error(uih, errstring);
+ if (uih->play) {
+ sprintf(errtext, gettext("Replay disabled at line %i"),
+ uih->playc->line);
+ uih_message(uih, errtext);
+ }
+ /*errstring[255]=0; */
+ }
+ if ((xio_feof(FD) && parsenext) || errstring) {
+ uih_replaydisable(uih);
+ }
+ } /*while play&&playframe */
+}
+
+void uih_load(struct uih_context *uih, xio_file f, xio_constpath filename)
+{
+ nonblockmode = 1;
+ uih_replayenable(uih, f, filename, 0);
+ uih_replaydisable(uih);
+ nonblockmode = 0;
+}
+
+void uih_command(struct uih_context *uih, CONST char *command)
+{
+ errstring = NULL;
+ uih->playpos = 0;
+ uih->playstring = command;
+ uih_processcommand(uih, (uih->play ? MENUFLAG_NOMENU : 0));
+ uih->playstring = NULL;
+ if (errstring != NULL) {
+ uih_error(uih, errstring);
+ }
+}
diff --git a/src/ui-hlp/play.h b/src/ui-hlp/play.h
new file mode 100644
index 0000000..62b7657
--- /dev/null
+++ b/src/ui-hlp/play.h
@@ -0,0 +1,50 @@
+#ifndef PLAY_H
+#define PLAY_H
+struct keyword {
+ char *name;
+ int type;
+ void (*callback) (void);
+ void *userdata;
+};
+typedef void (*funcptr) (void);
+#define GENERIC 0
+#define PARAM_INTEGER 1
+#define PARAM_BOOL 2
+#define PARAM_NSTRING 3
+#define PARAM_FLOAT 4
+#define PARAM_KEYSTRING 5
+#define PARAM_COORD 6
+#define PARAM_STRING 7
+extern CONST char *CONST save_fastmode[];
+extern CONST char *CONST uih_colornames[];
+void uih_play_formula(struct uih_context *uih, char *name);
+void uih_playfilter(struct uih_context *uih, dialogparam * p);
+void uih_zoomcenter(struct uih_context *uih, number_t x, number_t y);
+void uih_playpalette(struct uih_context *uih);
+void uih_playdefpalette(struct uih_context *uih, int shift);
+void uih_playusleep(struct uih_context *uih, int time);
+void uih_playtextsleep(struct uih_context *uih);
+void uih_playwait(struct uih_context *uih);
+void uih_playjulia(struct uih_context *uih, int julia);
+void uih_playzoom(struct uih_context *uih);
+void uih_playunzoom(struct uih_context *uih);
+void uih_playstop(struct uih_context *uih);
+void uih_playmorph(struct uih_context *uih, dialogparam * p);
+void uih_playmove(struct uih_context *uih, number_t x, number_t y);
+void uih_playtextpos(struct uih_context *uih, dialogparam * p);
+void uih_playcalculate(struct uih_context *uih);
+void uih_playmorphjulia(struct uih_context *uih, number_t x, number_t y);
+void uih_playmorphangle(struct uih_context *uih, number_t angle);
+void uih_playautorotate(struct uih_context *uih, int mode);
+void uih_playmessage(struct uih_context *uih, char *message);
+void uih_playload(struct uih_context *uih, char *message);
+void uih_playinit(struct uih_context *uih);
+
+void uih_line(uih_context * c, dialogparam * d);
+void uih_morphline(uih_context * c, dialogparam * d);
+void uih_morphlastline(uih_context * c, dialogparam * d);
+void uih_setkey(uih_context * c, int line);
+void uih_clear_line(uih_context * c);
+void uih_clear_lines(uih_context * c);
+
+#endif
diff --git a/src/ui-hlp/playtext.c b/src/ui-hlp/playtext.c
new file mode 100644
index 0000000..270134e
--- /dev/null
+++ b/src/ui-hlp/playtext.c
@@ -0,0 +1,174 @@
+#ifndef _plan9_
+#include <stdlib.h>
+#else
+#include <u.h>
+#include <libc.h>
+#endif
+#include <fconfig.h>
+#include <filter.h>
+#include <fractal.h>
+#include <ui_helper.h>
+#include <xerror.h>
+#include <grlib.h>
+
+static inline void
+prepare(struct uih_context *c, char *string, int *xmax, int *nr)
+{
+ int xm = 0;
+ int n = 1;
+ int pos = 0;
+ int tmp;
+ while (1) {
+ tmp = 0;
+ while (*string != '\n') {
+ if (*string == 0) {
+ tmp++;
+ if (tmp > xm)
+ xm = tmp;
+ *xmax = xm;
+ *nr = n;
+ return;
+ } else
+ tmp += xtextcharw(c->font, *string);
+ if (pos > 255)
+ break;
+ string++;
+ pos++;
+ }
+ tmp++;
+ if (tmp > xm)
+ xm = tmp;
+ n++;
+ if (n > 30) {
+ n = 30;
+ *xmax = tmp;
+ *nr = n;
+ return;
+ }
+ pos = 0;
+ string++;
+ }
+}
+
+static void
+getpos(uih_context * c, int *x, int *y, int *w, int *h, void *data)
+{
+ int num = (int) data;
+ int xmax, nr;
+ if (c->text[num] == NULL) {
+ *x = *y = *h = *w;
+ return;
+ }
+ prepare(c, c->text[num], &xmax, &nr);
+ nr *= xtextheight(c->font);
+ switch (num) {
+ case 0:
+ *y = 0;
+ break;
+ case 1:
+ *y = (c->image->height - nr) / 2;
+ break;
+ case 2:
+ *y = c->image->height - nr;
+ break;
+ }
+ *h = nr;
+ switch (c->textpos[num]) {
+ case 0:
+ *x = 0;
+ break;
+ case 1:
+ *x = (c->image->width - xmax) / 2;
+ break;
+ case 2:
+ *x = c->image->width - xmax;
+ break;
+ }
+ *w = xmax;
+}
+
+static void draw(uih_context * c, void *data)
+{
+ int num = (int) data;
+ int flags = 0;
+ int xmax, n, nr, i;
+ int x = 0, y = 0;
+ char *string;
+ int fgcolor = 0, bgcolor = 0;
+ if (c->text[num] == NULL)
+ return;
+ prepare(c, c->text[num], &xmax, &n);
+ nr = n * xtextheight(c->font);
+ switch (c->textcolor[num]) {
+ case 0:
+ fgcolor = FGCOLOR(c);
+ bgcolor = BGCOLOR(c);
+ break;
+ case 1:
+ fgcolor = BGCOLOR(c);
+ bgcolor = BGCOLOR(c);
+ flags = TEXT_PRESSED;
+ break;
+ case 2:
+ fgcolor = SELCOLOR(c);
+ bgcolor = BGCOLOR(c);
+ break;
+ default:
+ x_fatalerror("playtext:unknown color\n");
+ }
+ if (c->image->flags & AAIMAGE)
+ fgcolor = BGCOLOR(c);
+ switch (num) {
+ case 0:
+ y = 0;
+ break;
+ case 1:
+ y = (c->image->height - nr) / 2;
+ break;
+ case 2:
+ y = c->image->height - nr;
+ break;
+ }
+ string = c->text[num];
+ for (i = 0; i < n; i++) {
+ xmax = xtextwidth(c->font, string);
+ switch (c->textpos[num]) {
+ case 0:
+ x = 0;
+ break;
+ case 1:
+ x = (c->image->width - xmax) / 2;
+ break;
+ case 2:
+ x = c->image->width - xmax;
+ break;
+ }
+ string +=
+ xprint(c->image, c->font, x, y, string,
+ fgcolor, bgcolor,
+ flags) + 1;
+ y += xtextheight(c->font);
+ }
+}
+
+void uih_inittext(uih_context * c)
+{
+ c->text[0] = c->text[1] = c->text[2] = NULL;
+ c->textpos[0] = c->textpos[1] = c->textpos[2] = 0;
+ c->textwindow[0] = uih_registerw(c, getpos, draw, (void *) 0, 0);
+ c->textwindow[1] = uih_registerw(c, getpos, draw, (void *) 1, 0);
+ c->textwindow[2] = uih_registerw(c, getpos, draw, (void *) 2, 0);
+}
+
+void uih_destroytext(uih_context * c)
+{
+ 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;
+ uih_removew(c, c->textwindow[0]);
+ uih_removew(c, c->textwindow[1]);
+ uih_removew(c, c->textwindow[2]);
+}
diff --git a/src/ui-hlp/render.c b/src/ui-hlp/render.c
new file mode 100644
index 0000000..f105e92
--- /dev/null
+++ b/src/ui-hlp/render.c
@@ -0,0 +1,664 @@
+
+#ifdef _plan9_
+#include <u.h>
+#include <libc.h>
+#ifdef _plan9v2_
+#include <stdarg.h> /* not needed in plan9v3 */
+#endif
+#else
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#endif
+
+#include <ui.h>
+#include <fconfig.h>
+#include <filter.h>
+#include <fractal.h>
+#include <ui_helper.h>
+#include <misc-f.h>
+#include <xmenu.h>
+#include <xerror.h>
+
+#ifdef HAVE_GETTEXT
+#include <libintl.h>
+#else
+#define gettext(STRING) STRING
+#endif
+
+#define SILENT 0
+#define ERRORS 1
+#define MESSAGES 2
+#define ALL 3
+static int noiselevel;
+/*static struct uih_context *uih, *gc;*/
+static struct uih_context *gc;
+static struct uih_context *uih;
+static int newline = 1;
+static int interrupt = 0;
+static void error(CONST char *str)
+{
+ if (noiselevel < ERRORS)
+ return;
+ if (!gc)
+ x_error(gettext("Error: %s"), str);
+ uih_error(gc, str);
+}
+
+static void uiherror(struct uih_context *c)
+{
+ if (noiselevel < ERRORS)
+ return;
+ if (!gc) {
+ uih_printmessages(c);
+ } else
+ uih_error(gc, uih->errstring);
+}
+
+static void printmsg(const char *text, ...)
+{
+ va_list ap;
+ if (noiselevel < MESSAGES)
+ return;
+ va_start(ap, text);
+ if (!gc) {
+ vprintf(text, ap);
+ printf("\n");
+ } else {
+ char s[256];
+ vsprintf(s, text, ap);
+ uih_message(gc, s);
+ interrupt |= gc->interrupt |= gc->passfunc(gc, 1, s, 100);
+ uih_clearwindows(gc);
+ }
+}
+
+static int
+passfunc(struct uih_context *c, int display, CONST char *text,
+ float percent)
+{
+ if (noiselevel < ALL)
+ return 0;
+ if (gc) {
+ if (gc->passfunc != NULL)
+ interrupt |= gc->interrupt |=
+ gc->passfunc(gc, display, text, percent);
+ uih_clearwindows(gc);
+ return interrupt;
+ } else if (display) {
+ {
+ if (newline)
+ printf("\n"), newline = 0;
+ printf("\r %s %3.2f%% ", text, (double) percent);
+ fflush(stdout);
+ }
+ }
+ return 0;
+}
+
+
+struct frame_info {
+ vrect rect;
+ number_t angle;
+ char *name;
+ int newimage;
+};
+static void
+save_frame_dist(uih_context * c, int backward, struct frame_info *f1,
+ struct frame_info *f2)
+{
+ xio_file f;
+ int x1, y1;
+ char str[256];
+ if (!(f2->rect.mc - f2->rect.nc) || !(f2->rect.mi - f2->rect.ni))
+ return;
+ /*printf ("Frame\n"); */
+ sprintf(str, "%s.%c", f1->name, backward ? 'b' : 'p');
+ f = xio_wopen(str);
+ if (f == NULL) {
+ x_error(gettext("Cannot open motion vector file!"));
+ return;
+ }
+ for (y1 = 0; y1 < (c->image->height + 7) / 8; y1++) {
+ for (x1 = 0; x1 < (c->image->width + 7) / 8; x1++) {
+ number_t x, y;
+ number_t x2, y2;
+ number_t tmp;
+ x = f1->rect.nc + (x1 * 8 + 4) * (f1->rect.mc -
+ f1->rect.nc) /
+ c->image->width;
+ y = f1->rect.ni + (y1 * 8 + 4) * (f1->rect.mi -
+ f1->rect.ni) /
+ c->image->height;
+
+ if (f2->angle != f1->angle) {
+ tmp =
+ x * cos(f2->angle - f1->angle) - y * sin(f2->angle -
+ f1->angle);
+ y = x * sin(f2->angle - f1->angle) + y * cos(f2->angle -
+ f1->angle);
+ x = tmp;
+ }
+ x2 = (x - f2->rect.nc) * c->image->width / (f2->rect.mc -
+ f2->rect.nc);
+ y2 = (y - f2->rect.ni) * c->image->height / (f2->rect.mi -
+ f2->rect.ni);
+ sprintf(str, "%3.2g %3.2g ",
+ ((int) ((x2 - (x1 * 8 + 4)) * 10)) / 10.0,
+ ((int) ((y2 - (y1 * 8 + 4)) * 10)) / 10.0);
+ xio_puts(str, f);
+ }
+ xio_putc('\n', f);
+ }
+ xio_close(f);
+ /*printf ("Frameend\n"); */
+}
+
+#define MAXBFRAMES 5
+#define IFRAMEDIST (27)
+static int iframedist;
+static int mvectors;
+static xio_file patf;
+static void
+uih_encodeframe(int startpos, int endpos, struct frame_info *curframe)
+{
+ static int lastiframe = -200;
+ static struct frame_info lastp;
+ static struct frame_info bframes[MAXBFRAMES];
+ static int nbframes = 0;
+ int i;
+ char type;
+ if (!gc)
+ printf(" motion");
+ fflush(stdout);
+ if (endpos > startpos + 4) {
+ if (endpos - lastiframe > iframedist)
+ type = 'I';
+ else
+ type = 'P';
+ } else {
+ if (endpos - lastiframe > iframedist)
+ type = 'I';
+ else
+ type = (startpos - lastiframe) % 3 ? 'B' : 'P';
+ if (startpos != endpos)
+ type = 'P';
+ }
+ if (curframe->newimage)
+ type = 'I';
+ if (mvectors) {
+ switch (type) {
+ case 'I':
+ if (startpos)
+ save_frame_dist(uih, 0, curframe, &lastp);
+ lastp = *curframe;
+ break;
+ case 'P':
+ save_frame_dist(uih, 0, curframe, &lastp);
+ lastp = *curframe;
+ break;
+ case 'B':
+ save_frame_dist(uih, 0, curframe, &lastp);
+ if (nbframes < MAXBFRAMES) {
+ bframes[nbframes] = *curframe;
+ bframes[nbframes].name = mystrdup(curframe->name);
+ nbframes++;
+ }
+ break;
+ }
+ }
+ xio_putc(type, patf);
+ if (type == 'I')
+ lastiframe = startpos;
+ if (startpos != endpos) {
+ while (startpos != endpos)
+ xio_putc('p', patf), startpos++;
+ }
+ if (!gc)
+ printf(" %c", type);
+ fflush(stdout);
+ if (mvectors) {
+ if (type != 'B' && nbframes) {
+ if (!gc)
+ printf(" backframes");
+ fflush(stdout);
+ for (i = 0; i < nbframes; i++) {
+ save_frame_dist(uih, 1, bframes + i, curframe);
+ fflush(stdout);
+ free(bframes[i].name);
+ }
+ nbframes = 0;
+ }
+ }
+ xio_flush(patf);
+}
+
+extern struct filteraction antialias_filter;
+int
+uih_renderanimation(struct uih_context *gc1, CONST char *basename,
+ CONST xio_constpath animation, int width, int height,
+ float pixelwidth, float pixelheight, int frametime,
+ int type, int antialias, int slowmode,
+ int letterspersec, CONST char *catalog,
+ int motionvectors, int iframedist2)
+{
+ struct palette *pal =
+ createpalette(0, 0, type, 0, 0, NULL, NULL, NULL, NULL, NULL);
+ struct image *img;
+ xio_file of;
+ FILE *f;
+ xio_file af;
+ char s[200];
+ int lastframenum = -1;
+ int aliasnum = 0;
+ static char *saveddata;
+ int newimage;
+ int y;
+
+ struct frame_info curframe;
+ int framenum = 0;
+
+
+ noiselevel = ALL;
+ gc = gc1;
+ if (gc)
+ gc->incalculation = 1;
+
+ mvectors = motionvectors;
+ printmsg(gettext("Vectors: %i"), motionvectors);
+ if (iframedist2)
+ iframedist = iframedist2;
+ else
+ iframedist = 27;
+
+ printmsg(gettext("Initializing"));
+ if (!(type & (TRUECOLOR24 | TRUECOLOR | TRUECOLOR16 | GRAYSCALE)))
+ antialias = 0;
+
+ while (uih_filters[aliasnum] != &antialias_filter)
+ aliasnum++;
+
+ if (!pal) {
+ error(gettext("Cannot create palette"));
+ if (gc)
+ gc->incalculation = 0;
+ return 0;
+ }
+ if (!pixelwidth)
+ pixelwidth = 29.0 / width;
+ if (!pixelheight)
+ pixelheight = 21.5 / height;
+ img = create_image_mem(width, height, 2, pal, pixelwidth, pixelheight);
+ if (!img) {
+ error(gettext("Cannot create image\n"));
+ if (gc)
+ gc->incalculation = 0;
+ destroypalette(pal);
+ return 0;
+ }
+ saveddata =
+ (char *) malloc(img->width * img->height * img->bytesperpixel);
+ if (saveddata == NULL) {
+ error(gettext("Cannot create checking buffer!"));
+ if (gc)
+ gc->incalculation = 0;
+ destroy_image(img);
+ destroypalette(pal);
+ return 0;
+ }
+ uih = uih_mkcontext(0, img, passfunc, NULL, NULL);
+ if (!uih) {
+ error(gettext("Cannot create context\n"));
+ if (gc)
+ gc->incalculation = 0;
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ return 0;
+ }
+ uih->fcontext->slowmode = 1;
+ uih_constantframetime(uih, frametime);
+ af = xio_ropen(animation);
+ if (af == NULL) {
+ error(gettext("Cannot open animation file\n"));
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ return 0;
+ }
+
+ if (!gc) {
+ printmsg(gettext("Loading catalogs"));
+ if (!gc) {
+ uih_loadcatalog(uih, "english");
+ if (uih->errstring) {
+ uiherror(uih);
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ xio_close(af);
+ return 0;
+ }
+ }
+ if (catalog != NULL)
+ uih_loadcatalog(uih, catalog);
+ if (uih->errstring) {
+ uiherror(uih);
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ if (!gc)
+ uih_freecatalog(uih);
+ xio_close(af);
+ return 0;
+ }
+ printmsg(gettext("Processing command line options"));
+ {
+ CONST menuitem *item;
+ dialogparam *d;
+ while ((item = menu_delqueue(&d)) != NULL) {
+ menu_activate(item, uih, d);
+ }
+ }
+ if (uih->errstring) {
+ uiherror(uih);
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ if (!gc)
+ uih_freecatalog(uih);
+ xio_close(af);
+ return 0;
+ }
+ }
+
+ printmsg(gettext("Enabling animation replay\n"));
+
+ uih_replayenable(uih, af, animation, 1);
+
+ sprintf(s, "%s.par", basename);
+ of = xio_wopen(s);
+ if (of == NULL) {
+ error(gettext("Cannot open image file"));
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ if (!gc)
+ uih_freecatalog(uih);
+ return 0;
+ }
+ sprintf(s, "%s.pat", basename);
+ patf = xio_wopen(s);
+ if (patf == NULL) {
+ error(gettext("Cannot open pattern file"));
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ if (!gc)
+ uih_freecatalog(uih);
+ xio_close(of);
+ return 0;
+ }
+ uih_letterspersec(uih, letterspersec);
+
+
+
+ if (!gc)
+ x_message(gettext("Entering calculation loop!"));
+ else
+ printmsg(gettext("Entering calculation loop!"));
+
+ while ((uih->play || uih->display) && !interrupt) {
+ if (uih->errstring) {
+ uiherror(uih);
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ if (!gc)
+ uih_freecatalog(uih);
+ xio_close(of);
+ xio_close(patf);
+ return 0;
+ }
+ fflush(stdout);
+ tl_process_group(syncgroup, NULL);
+ uih_update(uih, 0, 0, 0);
+
+
+ if (uih->display) {
+
+ if (lastframenum < framenum - 1) {
+ if (lastframenum == framenum - 1)
+ printmsg(gettext("Frame %i skipped."), framenum - 1);
+ else
+ printmsg(gettext("Frames %i - %i skipped."),
+ lastframenum, framenum - 1);
+ }
+
+ printmsg(gettext("Frame %4i: "), framenum);
+
+ newline = 1;
+ newimage = 0;
+ if (uih->recalculatemode > 0) {
+ if (!gc)
+ printf("calculating"), fflush(stdout);
+ if (slowmode)
+ uih_newimage(uih), uih->fcontext->version++;
+ }
+ if (antialias && !uih->filter[aliasnum]) {
+ if (!gc)
+ printf("antialias ");
+ uih->aliasnum = aliasnum;
+ uih_enablefilter(uih, aliasnum);
+ }
+ uih_prepare_image(uih);
+
+ if (!gc)
+ printf(" rendering");
+ fflush(stdout);
+ uih_drawwindows(uih);
+
+ y = 0;
+ if (lastframenum >= 0) {
+ for (; y < img->height; y++)
+ if (memcmp
+ (saveddata + img->width * img->bytesperpixel * y,
+ uih->image->currlines[y],
+ img->width * img->bytesperpixel))
+ break;
+ }
+
+
+ if (y != img->height) {
+ for (; y < img->height; y++)
+ memcpy(saveddata + img->width * img->bytesperpixel * y,
+ uih->image->currlines[y],
+ img->width * img->bytesperpixel);
+ if (framenum)
+ uih_encodeframe(lastframenum, framenum - 1, &curframe);
+ if (!gc)
+ printf(" saving");
+ fflush(stdout);
+ sprintf(s, "%s%04i.png", basename, framenum);
+ curframe.rect = uih->fcontext->rs;
+ curframe.angle = uih->fcontext->angle;
+ curframe.name = s;
+ curframe.newimage = newimage;
+
+
+ f = fopen(s, "wb");
+ if (f == NULL) {
+ error(gettext("Cannot open image file"));
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ if (!gc)
+ uih_freecatalog(uih);
+ xio_close(of);
+ xio_close(patf);
+ return 0;
+ }
+ writepng(f, uih->image);
+ printmsg(gettext(" done."));
+ uih_displayed(uih);
+ lastframenum = framenum;
+ } else {
+ printmsg(gettext(" skipping..."));
+ uih_displayed(uih);
+ }
+ }
+ xio_puts(s, of);
+ xio_puts("\n", of);
+ xio_flush(of);
+ framenum++;
+ }
+ curframe.newimage = 1;
+ if (framenum)
+ uih_encodeframe(lastframenum, framenum - 1, &curframe);
+ if (uih->errstring) {
+ uiherror(uih);
+ if (gc)
+ gc->incalculation = 0;
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ free(saveddata);
+ if (!gc)
+ uih_freecatalog(uih);
+ xio_close(of);
+ xio_close(patf);
+ return 0;
+ }
+ xio_close(of);
+ free(saveddata);
+ xio_close(patf);
+ uih_freecontext(uih);
+ destroy_image(img);
+ destroypalette(pal);
+ if (interrupt)
+ error(gettext("Calculation interrupted"));
+ else {
+ if (!gc)
+ x_message(gettext("Calculation finished"));
+ else
+ printmsg(gettext("Calculation finished"));
+ }
+ if (gc)
+ gc->incalculation = 0;
+ if (!gc)
+ uih_freecatalog(uih);
+ return 1;
+}
+
+int
+uih_renderimage(struct uih_context *gc1, xio_file af,
+ CONST xio_constpath path, struct image *img, int antialias,
+ CONST char *catalog, int noise)
+{
+ int aliasnum = 0;
+ int ok = 1;
+ noiselevel = noise;
+ gc = gc1;
+ if (gc)
+ gc->incalculation = 1;
+
+ while (uih_filters[aliasnum] != &antialias_filter)
+ aliasnum++;
+
+ uih = uih_mkcontext(0, img, passfunc, NULL, NULL);
+ if (!uih) {
+ error(gettext("Cannot create context\n"));
+ if (gc)
+ gc->incalculation = 0;
+ return 0;
+ }
+ uih->fcontext->slowmode = 1;
+ uih_constantframetime(uih, 1000000 / 10);
+
+ if (!gc) {
+ printmsg(gettext("Loading catalogs"));
+ uih_loadcatalog(uih, "english");
+ if (uih->errstring) {
+ fprintf(stderr, uih->errstring);
+ uih_clearmessages(uih);
+ uih->errstring = NULL;
+ }
+ if (catalog != NULL)
+ uih_loadcatalog(uih, catalog);
+ if (uih->errstring) {
+ fprintf(stderr, uih->errstring);
+ uih_clearmessages(uih);
+ uih->errstring = NULL;
+ }
+ if (uih->errstring) {
+ uih_freecatalog(uih);
+ uih_freecontext(uih);
+ uiherror(uih);
+ if (gc)
+ gc->incalculation = 0;
+ return 0;
+ }
+ }
+
+ uih_load(uih, af, path);
+ if (uih->errstring) {
+ uiherror(uih);
+ uih_freecatalog(uih);
+ uih_freecontext(uih);
+ if (gc)
+ gc->incalculation = 0;
+ return 0;
+ }
+ printmsg(gettext("Entering calculation loop!"));
+
+ tl_process_group(syncgroup, NULL);
+ uih_update(uih, 0, 0, 0);
+
+ uih_newimage(uih), uih->fcontext->version++;
+ if (antialias && !uih->filter[aliasnum]) {
+ uih->aliasnum = aliasnum;
+ uih_enablefilter(uih, aliasnum);
+ }
+ uih_prepare_image(uih);
+ if (uih->errstring)
+ ok = 0;
+ uih_drawwindows(uih);
+ if (uih->errstring)
+ ok = 0;
+ uih_freecontext(uih);
+ uih_freecatalog(uih);
+ if (interrupt)
+ error(gettext("Calculation interrupted"));
+ else {
+ printmsg(gettext("Calculation finished"));
+ }
+ if (gc)
+ gc->incalculation = 0;
+ return 1;
+}
diff --git a/src/ui-hlp/save.c b/src/ui-hlp/save.c
new file mode 100644
index 0000000..853b61b
--- /dev/null
+++ b/src/ui-hlp/save.c
@@ -0,0 +1,704 @@
+#include <config.h>
+#ifndef _plan9_
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#ifndef NO_MALLOC_H
+#include <malloc.h>
+#endif
+#else
+#include <u.h>
+#include <libc.h>
+#endif
+#include <filter.h>
+#include <fractal.h>
+#include <ui_helper.h>
+#include <config.h>
+#include <version.h>
+#include <xmenu.h>
+#include <xldio.h>
+#include "play.h"
+#define myputs(s) ((xio_puts(s,uih->savec->file)==XIO_EOF)?outputerror(uih),1:0)
+#define myputc(s) ((xio_putc(s,uih->savec->file)==XIO_EOF)?outputerror(uih),1:0)
+static int first;
+static int changed;
+static int last;
+CONST char *CONST save_fastmode[] =
+ { "zero", "never", "animation", "new", "allways", NULL };
+CONST char *CONST xtextposnames[] = { "left", "center", "right", NULL };
+CONST char *CONST ytextposnames[] = { "top", "middle", "bottom", NULL };
+
+REGISTERS(3)
+static void outputerror(struct uih_context *uih)
+{
+ static char error[245];
+ if (uih->savec->writefailed)
+ return;
+ sprintf(error, "Write failed:%s", xio_errorstring());
+ uih_error(uih, error);
+ uih->savec->writefailed = 1;
+}
+
+REGISTERS(3)
+static void start_save(struct uih_context *uih, CONST char *name)
+{
+ if (!changed && !uih->savec->firsttime) {
+ char s[256];
+ sprintf(s, "\n(usleep %i)\n", tl_lookup_timer(uih->savec->timer));
+ myputs(s);
+ tl_reset_timer(uih->savec->timer);
+ }
+ changed = 1;
+ myputc('(');
+ myputs(name);
+ first = 0;
+}
+
+REGISTERS(3)
+static void stop_save(struct uih_context *uih)
+{
+ myputc(')');
+ myputc('\n');
+}
+
+#ifdef SAVEKEYWORDUSED
+REGISTERS(3)
+static void save_keyword(struct uih_context *uih, CONST char *name)
+{
+ if (!first)
+ myputc(' ');
+ else
+ first = 0;
+ myputs(name);
+}
+#endif
+REGISTERS(3)
+static void save_keystring(struct uih_context *uih, CONST char *name)
+{
+ if (!first)
+ myputc(' ');
+ else
+ first = 0;
+ myputc('\'');
+ myputs(name);
+}
+
+REGISTERS(3)
+static void save_float(struct uih_context *uih, number_t number)
+{
+ if (!first)
+ myputc(' ');
+ else
+ first = 0;
+#ifdef HAVE_LONG_DOUBLE
+ /*20 should be enought to specify 64digit number :) */
+#ifdef USE_XLDIO
+ x_ldout((long double) number, 20, uih->savec->file);
+#else
+ {
+ char s[256];
+ sprintf(s, "%.20LG", (long double) number);
+ myputs(s);
+ }
+#endif
+#else
+ {
+ char s[256];
+ sprintf(s, "%.20G", (double) number);
+ myputs(s);
+ }
+#endif
+}
+
+REGISTERS(3)
+static void
+save_float2(struct uih_context *uih, number_t number, int places)
+{
+ char fs[10];
+ if (!first)
+ myputc(' ');
+ else
+ first = 0;
+ if (places < 0)
+ places = 0;
+ if (places > 20)
+ places = 20;
+#ifdef HAVE_LONG_DOUBLE
+#ifdef USE_XLDIO
+ fs[0] = 0; /* Avoid warning */
+ x_ldout((long double) number, places, uih->savec->file);
+#else
+ {
+ char s[256];
+ sprintf(fs, "%%.%iLG", places);
+ sprintf(s, fs, (long double) number);
+ myputs(s);
+ }
+#endif
+#else
+ {
+ char s[256];
+ sprintf(fs, "%%.%iG", places);
+ sprintf(s, fs, (double) number);
+ myputs(s);
+ }
+#endif
+}
+
+REGISTERS(3)
+static void save_int(struct uih_context *uih, int number)
+{
+ char s[256];
+ if (!first)
+ myputc(' ');
+ else
+ first = 0;
+ sprintf(s, "%i", number);
+ myputs(s);
+}
+
+REGISTERS(3)
+static void save_onoff(struct uih_context *uih, int number)
+{
+ if (!first)
+ myputc(' ');
+ else
+ first = 0;
+ myputs(number ? "#t" : "#f");
+}
+
+REGISTERS(3)
+static void save_string(struct uih_context *uih, CONST char *text)
+{
+ int i = 0;
+ if (!first)
+ myputc(' ');
+ else
+ first = 0;
+ myputc('"');
+ while (text[i] != 0) {
+ if (text[i] == '"')
+ myputc('\\');
+ myputc(text[i]);
+ i++;
+ }
+ myputc('"');
+}
+
+REGISTERS(3)
+static void
+save_intc(struct uih_context *uih, CONST char *name, int number)
+{
+ start_save(uih, name);
+ save_int(uih, number);
+ stop_save(uih);
+}
+
+REGISTERS(3)
+static void
+save_onoffc(struct uih_context *uih, CONST char *name, int number)
+{
+ start_save(uih, name);
+ save_onoff(uih, number);
+ stop_save(uih);
+}
+
+REGISTERS(3)
+static void
+save_floatc(struct uih_context *uih, CONST char *name, number_t number)
+{
+ start_save(uih, name);
+ save_float(uih, number);
+ stop_save(uih);
+}
+
+REGISTERS(3)
+static void
+save_float2c(struct uih_context *uih, CONST char *name,
+ number_t number, int places)
+{
+ start_save(uih, name);
+ save_float2(uih, number, places);
+ stop_save(uih);
+}
+
+REGISTERS(3)
+static void
+save_coordc(struct uih_context *uih, CONST char *name,
+ number_t number, number_t number2)
+{
+ start_save(uih, name);
+ save_float(uih, number);
+ save_float(uih, number2);
+ stop_save(uih);
+}
+
+REGISTERS(3)
+static void
+save_keystringc(struct uih_context *uih, CONST char *name,
+ CONST char *param)
+{
+ start_save(uih, name);
+ save_keystring(uih, param);
+ stop_save(uih);
+}
+
+REGISTERS(3)
+static void
+save_stringc(struct uih_context *uih, CONST char *name, CONST char *param)
+{
+ start_save(uih, name);
+ save_string(uih, param);
+ stop_save(uih);
+}
+
+REGISTERS(3)
+static void save_noparam(struct uih_context *uih, CONST char *name)
+{
+ start_save(uih, name);
+ stop_save(uih);
+}
+
+REGISTERS(3)
+static void
+save_nstring(struct uih_context *uih, int number,
+ CONST char *CONST * CONST texts)
+{
+ save_keystring(uih, texts[number]);
+}
+
+REGISTERS(3)
+static void
+save_nstringc(struct uih_context *uih, CONST char *name, int number,
+ CONST char *CONST * CONST texts)
+{
+ save_keystringc(uih, name, texts[number]);
+}
+
+static int ndecimals(struct uih_context *uih)
+{
+ number_t n = 10000;
+ number_t m = uih->fcontext->s.rr;
+ int i;
+ if (uih->fcontext->s.ri < m)
+ m = uih->fcontext->s.ri;
+ if (uih->fcontext->s.ri > 100 || uih->fcontext->s.rr > 100)
+ return (20);
+ for (i = 0; i < 20 && m < n; i++, n /= 10);
+ return (i);
+}
+
+static void savepos(struct uih_context *uih) REGISTERS(3);
+REGISTERS(3)
+static void savepos(struct uih_context *uih)
+{
+ int n = ndecimals(uih);
+ start_save(uih, "view");
+ save_float2(uih, uih->fcontext->s.cr, n);
+ save_float2(uih, uih->fcontext->s.ci, n);
+ save_float2(uih, uih->fcontext->s.rr, n);
+ save_float2(uih, uih->fcontext->s.ri, n);
+ stop_save(uih);
+ uih->savec->fcontext->s = uih->fcontext->s;
+}
+
+static void savepos2(struct uih_context *uih) REGISTERS(3);
+REGISTERS(3)
+static void savepos2(struct uih_context *uih)
+{
+ int n = ndecimals(uih);
+ start_save(uih, "animateview");
+ save_float2(uih, uih->fcontext->s.cr, n);
+ save_float2(uih, uih->fcontext->s.ci, n);
+ save_float2(uih, uih->fcontext->s.rr, n);
+ save_float2(uih, uih->fcontext->s.ri, n);
+ stop_save(uih);
+ uih->savec->fcontext->s = uih->fcontext->s;
+}
+
+static void savepos3(struct uih_context *uih) REGISTERS(3);
+REGISTERS(3)
+static void savepos3(struct uih_context *uih)
+{
+ int n = ndecimals(uih);
+ start_save(uih, "morphview");
+ save_float2(uih, uih->fcontext->s.cr, n);
+ save_float2(uih, uih->fcontext->s.ci, n);
+ save_float2(uih, uih->fcontext->s.rr, n);
+ save_float2(uih, uih->fcontext->s.ri, n);
+ stop_save(uih);
+ uih->savec->fcontext->s = uih->fcontext->s;
+}
+
+void uih_saveframe(struct uih_context *uih)
+{
+ struct uih_savedcontext *s = uih->savec;
+ int i;
+ int resetsync = 0;
+ if (uih->save) {
+ changed = 0;
+ if (s->firsttime)
+ save_noparam(uih, "initstate");
+ if (s->nonfractalscreen && !uih->nonfractalscreen)
+ save_noparam(uih, "display"), s->nonfractalscreen = 0;
+ for (i = uih_nfilters; i >= 0; i--) {
+ if (uih->filter[i] != NULL) {
+ if (s->filter[i] != 1) {
+ start_save(uih, "filter");
+ save_keystring(uih, uih->filter[i]->action->shortname);
+ save_onoff(uih, 1);
+ s->filter[i] = 1;
+ stop_save(uih);
+ }
+ } else if (s->filter[i] != 0) {
+ s->filter[i] = 0;
+ start_save(uih, "filter");
+ save_keystring(uih, uih_filters[i]->shortname);
+ save_onoff(uih, 0);
+ stop_save(uih);
+ }
+ }
+ if (uih->palettechanged) {
+ switch (uih->palettetype) {
+ case 0:
+ save_intc(uih, "defaultpalette", uih->paletteshift);
+ break;
+ default:
+ start_save(uih, "palette");
+ save_int(uih, uih->palettetype);
+ save_int(uih, uih->paletteseed);
+ save_int(uih, uih->paletteshift);
+ stop_save(uih);
+ break;
+ }
+ uih->palettechanged = 0;
+ s->manualpaletteshift = 0;
+ }
+ if (s->manualpaletteshift != uih->manualpaletteshift)
+ save_intc(uih, "shiftpalette",
+ uih->manualpaletteshift - s->manualpaletteshift),
+ s->manualpaletteshift = uih->manualpaletteshift;
+ if (s->fcontext->currentformula != uih->fcontext->currentformula) {
+ save_keystringc(uih, "formula",
+ uih->fcontext->currentformula->shortname),
+ s->fcontext->currentformula =
+ uih->fcontext->currentformula;
+#ifdef SFFE_USING
+/*SFFE : malczak */
+ if ((int) (uih->fcontext->currentformula - formulas) == 24) //user formula
+ {
+ save_stringc(uih, "usrform", uih->parser->expression);
+ if (uih->pinit)
+ save_stringc(uih, "usrformInit",
+ uih->pinit->expression);
+ else
+ save_stringc(uih, "usrformInit", "");
+ };
+/*SFFE : malczak */
+#endif
+ set_formula(s->fcontext,
+ (int) (uih->fcontext->currentformula - formulas));
+ }
+ if (s->mode >= UIH_SAVEALL)
+ save_intc(uih, "letterspersec", uih->letterspersec);
+ if (s->mode > UIH_SAVEPOS) {
+ if (s->speedup != uih->speedup)
+ save_floatc(uih, "speedup", uih->speedup), s->speedup =
+ uih->speedup;
+ if (s->maxstep != uih->maxstep)
+ save_floatc(uih, "maxstep", uih->maxstep), s->maxstep =
+ uih->maxstep;
+ if (s->fastmode != uih->fastmode)
+ save_nstringc(uih, "fastmode", uih->fastmode,
+ save_fastmode), s->fastmode = uih->fastmode;
+ }
+ if (s->juliamode != uih->juliamode)
+ save_onoffc(uih, "fastjulia", uih->juliamode), s->juliamode =
+ uih->juliamode;
+ if (s->cycling != uih->cycling)
+ save_onoffc(uih, "cycling", uih->cycling), s->cycling =
+ uih->cycling;
+ if (s->mode >= UIH_SAVEPOS
+ && s->fcontext->periodicity != uih->fcontext->periodicity)
+ save_onoffc(uih, "periodicity", uih->fcontext->periodicity),
+ s->fcontext->periodicity = uih->fcontext->periodicity;
+ if ((uih->cycling || s->mode >= UIH_SAVEALL)
+ && (s->cyclingspeed != uih->cyclingspeed
+ || s->direction != uih->direction * uih->cyclingdirection))
+ save_intc(uih, "cyclingspeed",
+ uih->cyclingspeed * uih->direction *
+ uih->cyclingdirection), s->cyclingspeed =
+ uih->cyclingspeed, s->direction =
+ uih->direction * uih->cyclingdirection;
+ if ((s->mode > UIH_SAVEPOS && (uih->step || uih->zoomactive))
+ && (s->xcenter != uih->xcenter || s->ycenter != uih->ycenter))
+ save_coordc(uih, "zoomcenter", uih->xcenter, uih->ycenter),
+ s->xcenter = uih->xcenter, s->ycenter = uih->ycenter;
+ if ((!uih->fcontext->mandelbrot || uih->juliamode)
+ && (s->fcontext->pre != uih->fcontext->pre
+ || s->fcontext->pim != uih->fcontext->pim)) {
+ if (uih->juliamode && uih->pressed)
+ save_coordc(uih, "morphjulia", uih->fcontext->pre,
+ uih->fcontext->pim), s->fcontext->pre =
+ uih->fcontext->pre, s->fcontext->pim =
+ uih->fcontext->pim;
+ else
+ save_coordc(uih, "juliaseed", uih->fcontext->pre,
+ uih->fcontext->pim), s->fcontext->pre =
+ uih->fcontext->pre, s->fcontext->pim =
+ uih->fcontext->pim;
+ }
+ if (uih->fcontext->bre != s->fcontext->bre
+ || uih->fcontext->bim != s->fcontext->bim) {
+ save_coordc(uih, "perturbation", uih->fcontext->bre,
+ uih->fcontext->bim), s->fcontext->bre =
+ uih->fcontext->bre, s->fcontext->bim = uih->fcontext->bim;
+ }
+ if (uih->fastrotate != s->fastrotate && s->mode > UIH_SAVEPOS) {
+ save_onoffc(uih, "fastrotate", uih->fastrotate);
+ s->fastrotate = uih->fastrotate;
+ }
+ if (uih->fcontext->angle != s->fcontext->angle
+ && s->autorotate != 1) {
+ if (s->rotatepressed && s->mode == UIH_SAVEANIMATION)
+ save_float2c(uih, "morphangle", uih->fcontext->angle, 5);
+ else
+ save_float2c(uih, "angle", uih->fcontext->angle, 5);
+ s->rotatepressed = uih->rotatepressed;
+ s->fcontext->angle = uih->fcontext->angle;
+ }
+ if (uih->rotationspeed != s->rotationspeed
+ &&
+ ((s->mode > UIH_SAVEPOS
+ && uih->rotatemode == ROTATE_CONTINUOUS)
+ || s->mode >= UIH_SAVEALL)) {
+ save_float2c(uih, "rotationspeed", uih->rotationspeed, 6);
+ s->rotationspeed = uih->rotationspeed;
+ }
+ if (s->autorotate != (uih->rotatemode == ROTATE_CONTINUOUS)) {
+ s->autorotate = (uih->rotatemode == ROTATE_CONTINUOUS);
+ save_onoffc(uih, "autorotate", s->autorotate);
+ }
+ if (s->fcontext->maxiter != uih->fcontext->maxiter)
+ save_intc(uih, "maxiter", uih->fcontext->maxiter),
+ s->fcontext->maxiter = uih->fcontext->maxiter;
+ if (s->fcontext->bailout != uih->fcontext->bailout)
+ save_floatc(uih, "bailout", uih->fcontext->bailout),
+ s->fcontext->bailout = uih->fcontext->bailout;
+ if (s->fcontext->coloringmode != uih->fcontext->coloringmode)
+ save_intc(uih, "outcoloring", uih->fcontext->coloringmode),
+ s->fcontext->coloringmode = uih->fcontext->coloringmode;
+ if (s->fcontext->incoloringmode != uih->fcontext->incoloringmode)
+ save_intc(uih, "incoloring", uih->fcontext->incoloringmode),
+ s->fcontext->incoloringmode =
+ uih->fcontext->incoloringmode;
+ if (s->fcontext->incoloringmode != uih->fcontext->incoloringmode)
+ save_intc(uih, "incoloring", uih->fcontext->incoloringmode),
+ s->fcontext->incoloringmode =
+ uih->fcontext->incoloringmode;
+ if ((s->fcontext->incoloringmode == 10 || s->mode >= UIH_SAVEALL)
+ && s->fcontext->intcolor != uih->fcontext->intcolor)
+ save_intc(uih, "intcoloring", uih->fcontext->intcolor),
+ s->fcontext->intcolor = uih->fcontext->intcolor;
+ if ((s->fcontext->coloringmode == 10 || s->mode >= UIH_SAVEALL)
+ && s->fcontext->outtcolor != uih->fcontext->outtcolor)
+ save_intc(uih, "outtcoloring", uih->fcontext->outtcolor),
+ s->fcontext->outtcolor = uih->fcontext->outtcolor;
+ if (s->fcontext->mandelbrot != uih->fcontext->mandelbrot)
+ save_onoffc(uih, "julia", !uih->fcontext->mandelbrot),
+ s->fcontext->mandelbrot = uih->fcontext->mandelbrot;
+ if (s->mode > UIH_SAVEPOS
+ && s->fcontext->range != uih->fcontext->range)
+ save_intc(uih, "range", uih->fcontext->range),
+ s->fcontext->range = uih->fcontext->range;
+ if (s->fcontext->plane != uih->fcontext->plane)
+ save_intc(uih, "plane", uih->fcontext->plane),
+ s->fcontext->plane = uih->fcontext->plane;
+ if (s->zoomactive != uih->zoomactive && s->mode > UIH_SAVEPOS) {
+ switch (uih->zoomactive) {
+ case -1:
+ save_noparam(uih, "unzoom");
+ break;
+ case 1:
+ save_noparam(uih, "zoom");
+ break;
+ default:
+ save_noparam(uih, "stop");
+ break;
+ }
+ s->zoomactive = uih->zoomactive;
+ }
+ if ((s->mode >= UIH_SAVEPOS || uih->displaytext)
+ && s->color != uih->color) {
+ start_save(uih, "color");
+ save_nstring(uih, uih->color, uih_colornames);
+ stop_save(uih);
+ s->color = uih->color;
+ }
+ if (s->clearscreen) {
+ save_noparam(uih, "clearscreen");
+ s->clearscreen = 0;
+ s->nonfractalscreen = 1;
+ }
+ if (uih->displaytext) {
+ for (i = 0; i < 3; i++) {
+ if (uih->displaytext & (1 << i)) {
+ if (s->ytextpos != i || s->xtextpos != uih->textpos[i]) {
+ start_save(uih, "textpossition");
+ save_nstring(uih, uih->xtextpos, xtextposnames);
+ save_nstring(uih, uih->ytextpos, ytextposnames);
+ stop_save(uih);
+ s->xtextpos = uih->xtextpos;
+ s->ytextpos = uih->ytextpos;
+ }
+ save_stringc(uih, "text", uih->text[i]);
+ s->nonfractalscreen = 1;
+ }
+ }
+ save_noparam(uih, "textsleep");
+ uih->displaytext = 0;
+ }
+ if (s->autorotate && changed
+ && tl_lookup_timer(uih->savec->synctimer) > 500000)
+ save_float2c(uih, "angle", uih->fcontext->angle, 5),
+ resetsync = 1;
+ if (s->mode == UIH_SAVEPOS)
+ savepos(uih);
+ else {
+ if (uih->viewchanged)
+ savepos(uih), uih->viewchanged = 0;
+ else if (uih->moved)
+ savepos3(uih), uih->moved = 0;
+ else if (((changed && uih->step) || last)
+ && tl_lookup_timer(uih->savec->synctimer) > 500000)
+ resetsync = 1, savepos2(uih);
+ }
+ if (uih->savec->firsttime)
+ uih->savec->firsttime = 0;
+ if (s->writefailed)
+ uih_save_disable(uih);
+ if (resetsync)
+ tl_reset_timer(uih->savec->synctimer);
+ } /*if uih->save */
+}
+
+int uih_save_enable(struct uih_context *uih, xio_file f, int mode)
+{
+ struct uih_savedcontext *s;
+ int i;
+ last = 0;
+ if (uih->save) {
+ uih_error(uih, "Recording is already enabled");
+ return 0;
+ }
+ s = (struct uih_savedcontext *) calloc(1, sizeof(*s));
+ if (f == NULL || s == NULL) {
+ uih_error(uih, "File could not be opended or out of memory");
+ return 0;
+ }
+ uih->savec = s;
+ s->fcontext =
+ make_fractalc(1, uih->image->pixelwidth * uih->image->width,
+ uih->image->pixelheight * uih->image->height);
+ if (s->fcontext == NULL) {
+ uih_error(uih, "File could not be opended or out of memory");
+ return 0;
+ }
+ s->mode = mode;
+ /*Invalidate context to force save everything first */
+ s->speedup = STEP;
+ s->maxstep = MAXSTEP;
+ s->xcenter = INT_MAX;
+ s->fastmode = 2;
+ s->juliamode = 0;
+ s->cycling = 0;
+ for (i = 0; i < uih_nfilters; i++)
+ s->filter[i] = 0;
+ s->pressed = 0;
+ s->firsttime = 1;
+ uih->palettechanged = 1;
+ s->cyclingspeed = 30;
+ s->fcontext->pre = s->fcontext->pim = 0;
+ s->fcontext->bre = s->fcontext->bim = 0;
+ s->fcontext->currentformula = NULL;
+ s->fcontext->periodicity = 1;
+ s->fcontext->maxiter = 170;
+ s->fcontext->bailout = 4;
+ s->fcontext->coloringmode = 0;
+ s->fcontext->incoloringmode = 0;
+ s->fcontext->outtcolor = 0;
+ s->fcontext->intcolor = 0;
+ s->fcontext->mandelbrot = 1;
+ s->fcontext->plane = 0;
+ s->fcontext->range = 3;
+ s->fcontext->angle = 0;
+ s->rotatepressed = 0;
+ s->autorotate = 0;
+ s->fastrotate = 0;
+ s->rotationspeed = 10;
+ s->clearscreen = 0;
+ s->color = 0;
+ s->xtextpos = 1;
+ s->ytextpos = 1;
+ s->file = f;
+ s->timer = tl_create_timer();
+ s->synctimer = tl_create_timer();
+ uih->viewchanged = 1;
+ uih->palettechanged = 1;
+ uih->save = 1;
+ uih_emulatetimers(uih);
+ tl_reset_timer(s->timer);
+ uih->moved = 0;
+#ifndef _plan9_
+ if (mode == UIH_SAVEANIMATION)
+ myputs(";Animation file automatically generated by XaoS "
+ XaoS_VERSION "\n"
+ "; - a realtime interactive fractal zoomer\n"
+ ";Use xaos -play <filename> to replay it\n");
+ else if (mode == UIH_SAVEPOS)
+ myputs(";Position file automatically generated by XaoS "
+ XaoS_VERSION "\n"
+ "; - a realtime interactive fractal zoomer\n"
+ ";Use xaos -load <filename> to display it\n");
+#endif
+ uih_saveframe(uih);
+ uih_updatemenus(uih, "save");
+ xio_putc('\n', f);
+ return 1;
+}
+
+void uih_save_disable(struct uih_context *uih)
+{
+ if (uih->save) {
+ last = 1;
+ if (uih->savec->mode >= UIH_SAVEANIMATION)
+ uih_saveframe(uih);
+ if (xio_close(uih->savec->file))
+ outputerror(uih);
+ uih->save = 0;
+ free(uih->savec->fcontext);
+ tl_free_timer(uih->savec->timer);
+ tl_free_timer(uih->savec->synctimer);
+ free(uih->savec);
+ uih_updatemenus(uih, "save");
+ }
+}
+
+void uih_save_possition(struct uih_context *uih, xio_file f, int mode)
+{
+ struct uih_savedcontext *c = uih->savec;
+ int save = uih->save;
+ int vc = uih->viewchanged;
+ int pc = uih->palettechanged;
+ int mov = uih->moved = 0;
+ uih->moved = 0;
+ uih->save = 0;
+ uih->savec = NULL;
+ uih_save_enable(uih, f, mode);
+ uih_save_disable(uih);
+ uih->savec = c;
+ uih->save = save;
+ uih->viewchanged = vc;
+ uih->palettechanged = pc;
+ mov = uih->moved;
+}
diff --git a/src/ui-hlp/ui-hlp.pri b/src/ui-hlp/ui-hlp.pri
new file mode 100644
index 0000000..22c401a
--- /dev/null
+++ b/src/ui-hlp/ui-hlp.pri
@@ -0,0 +1,12 @@
+SOURCES += $$PWD/autopilot.c \
+ $$PWD/ui_helper.c \
+ $$PWD/menu.c \
+ $$PWD/play.c \
+ $$PWD/render.c \
+ $$PWD/playtext.c \
+ $$PWD/save.c \
+ $$PWD/messg.c \
+ $$PWD/wstack.c
+
+OTHER_FILES += \
+ $$PWD/autod.c
diff --git a/src/ui-hlp/ui_helper.c b/src/ui-hlp/ui_helper.c
new file mode 100644
index 0000000..04cd903
--- /dev/null
+++ b/src/ui-hlp/ui_helper.c
@@ -0,0 +1,2303 @@
+#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>
+#include <libgen.h>
+
+#ifdef SFFE_USING
+#include "sffe.h"
+#endif
+
+#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."), basename(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)
+{
+ CONST char *r;
+ uih_cycling_stop(c);
+ uih_stoptimers(c);
+ uih_clearwindows(c);
+ r = writepng(filename, 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;
+ //if ( c->fcontext->plane == P_USER )
+ //printf("USER NOT IMPLEMENTED");
+ //uih_sffein( c, "z^3-c" )
+ 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);
+}
+
+#ifdef SFFE_USING
+extern cmplx C, Z, pZ;
+#endif
+struct uih_context *globaluih;
+
+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();
+#ifdef SFFE_USING
+ uih->pinit = NULL;
+ uih->parser = sffe_alloc();
+ /* uih->cparser = sffe_alloc(); */
+ sffe_regvar(&uih->parser, &pZ, 'p');
+ sffe_regvar(&uih->parser, &Z, 'z');
+ sffe_regvar(&uih->parser, &C, 'c');
+ /* sffe_regvar( &uih->cparser, &C, */
+#endif
+ /* 25.I.2009, Bugfix #2507911, malczak
+ * initilize globaluih here, not in 'ui.c'
+ */
+ globaluih = uih;
+
+ 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_loadpalette(uih_context * c, struct palette *palette)
+{
+ if (c->palette2)
+ destroypalette(c->palette2);
+ c->palette2 = clonepalette(palette);
+ uih_restorepalette(c);
+ uih_palettechg(c);
+}
+
+struct palette *uih_clonepalette(uih_context * c)
+{
+ if (c->zengine->fractalc->palette != NULL)
+ return clonepalette(c->zengine->fractalc->palette);
+ // I hope this is OK:
+ return NULL;
+}
+
+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;
+#ifdef SFFE_USING
+ /* sffe_free(&c->cparser); */
+ sffe_free(&c->parser);
+ if (c->pinit)
+ sffe_free(&c->pinit);
+#endif
+ 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;
+}
+
+void uih_inhibittextsw(uih_context * c)
+{
+ c->inhibittextoutput ^= 1;
+ uih_updatemenus(c, "inhibittextoutput");
+}
+
+int uih_inhibittextselected(uih_context * c)
+{
+ if (c == NULL)
+ return 0;
+ return c->inhibittextoutput;
+}
diff --git a/src/ui-hlp/wstack.c b/src/ui-hlp/wstack.c
new file mode 100644
index 0000000..cfabab1
--- /dev/null
+++ b/src/ui-hlp/wstack.c
@@ -0,0 +1,528 @@
+#ifdef _plan9_
+#include <u.h>
+#include <libc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#endif
+#include <fconfig.h>
+#include <filter.h>
+#include <ui_helper.h>
+#include <archaccel.h>
+#include "grlib.h"
+
+/* This is quite simple and ugly implementation of windows.
+ * it redraws all windows every frame and removes them before calculation
+ * it should be OK for small windows (like texts) used by ui_helper
+ * I plan to abuse it in ugly interface too, in case it will be fast enought
+ */
+
+static void
+uih_darkrectangle(struct image *image, int x, int y, int width, int height)
+{
+
+ int mask = 0;
+ unsigned int *current, *end;
+ if (x + width < 0 || y + height < 0 || y >= image->height
+ || x >= image->width)
+ return;
+ if (x + width >= image->width)
+ width = image->width - x;
+ if (x < 0)
+ width += x, x = 0;
+ if (width <= 0)
+ return;
+ if (y + height >= image->height)
+ height = image->height - y;
+ if (y < 0)
+ height += y, y = 0;
+ if (height <= 0)
+ return;
+ assert(x >= 0 && y >= 00 && width > 0 && height > 0
+ && x + width <= image->width && y + height <= image->height);
+ if (image->bytesperpixel == 2) {
+ int x1 = x / 2;
+ width = (x + width + 1) / 2 - x1;
+ x = x1;
+ }
+ if (image->bytesperpixel == 3) {
+ int x1 = x * 3 / 4;
+ width = (x + width + 2) * 3 / 4 - x1;
+ x = x1;
+ }
+ switch (image->palette->type) {
+ case TRUECOLOR:
+ case TRUECOLOR24:
+ mask =
+ ~((1 <<
+ (image->palette->info.truec.rshift + 7 -
+ image->palette->info.truec.rprec)) | (1 << (image->
+ palette->info.
+ truec.gshift +
+ 7 -
+ image->
+ palette->info.
+ truec.
+ gprec)) | (1 <<
+ (image->
+ palette->
+ info.
+ truec.
+ bshift
+ +
+ 7 -
+ image->
+ palette->
+ info.
+ truec.
+ bprec)));
+ break;
+ case TRUECOLOR16:
+ mask =
+ ((1 <<
+ (image->palette->info.truec.rshift + 7 -
+ image->palette->info.truec.rprec)) | (1 << (image->
+ palette->info.
+ truec.gshift +
+ 7 -
+ image->
+ palette->info.
+ truec.
+ gprec)) | (1 <<
+ (image->palette->info.truec.bshift
+ +
+ 7 -
+ image->palette->info.truec.bprec)));
+ mask = ~(mask | (mask << 16));
+ break;
+ }
+ height += y;
+ while (y < height) {
+ current = ((unsigned int *) image->currlines[y]) + x;
+ end = current + width;
+ while (current < end)
+ *current = (*current >> 1) & mask, current++;
+ y++;
+ }
+
+}
+
+void
+uih_drawborder(struct uih_context *uih, int x, int y, int width,
+ int height, int flags)
+{
+ int leftcolor;
+ int rightcolor;
+ int bgcolor;
+ if (uih->palette->type & BITMAPS) {
+ if (flags & BORDER_PRESSED) {
+ bgcolor = FGCOLOR(uih);
+ rightcolor = BGCOLOR(uih);
+ leftcolor = BGCOLOR(uih);
+ } else {
+ bgcolor = BGCOLOR(uih);
+ rightcolor = FGCOLOR(uih);
+ leftcolor = FGCOLOR(uih);
+ }
+ } else {
+ if (flags & BORDER_LIGHT) {
+ bgcolor = LIGHTGRAYCOLOR(uih);
+ rightcolor = BGCOLOR(uih);
+ leftcolor = LIGHTGRAYCOLOR2(uih);
+ } else {
+ bgcolor = DARKGRAYCOLOR(uih);
+ rightcolor = BGCOLOR(uih);
+ leftcolor = LIGHTGRAYCOLOR(uih);
+ }
+ if (flags & BORDER_PRESSED) {
+ int i = leftcolor;
+ leftcolor = rightcolor;
+ rightcolor = i;
+ }
+ if (uih->image->flags & AAIMAGE)
+ bgcolor = BGCOLOR(uih);
+ }
+ if (uih->image->bytesperpixel > 1 && (flags & BORDER_TRANSPARENT))
+ uih_darkrectangle(uih->image, x + 1, y + 1, width - 2,
+ height - 2) /*, leftcolor = GRAYCOLOR (uih) */ ;
+ else {
+ xrectangle(uih->image, x + 1, y + 1, width - 2, height - 2,
+ bgcolor);
+ }
+ xhline(uih->image, x, y, width - 1, leftcolor);
+ xhline(uih->image, x, y + height - 1, width - 1, rightcolor);
+ xvline(uih->image, x, y, height - 1, leftcolor);
+ xvline(uih->image, x + width - 1, y, height - 1, rightcolor);
+}
+
+struct uih_window *uih_registerw(struct uih_context *uih, uih_getposfunc
+ getpos, uih_drawfunc draw, void *data,
+ int flags)
+{
+ struct uih_window *w =
+ (struct uih_window *) calloc(1, sizeof(struct uih_window));
+ struct uih_window *w1;
+ assert(uih != NULL && getpos != NULL && draw != NULL && flags >= 0);
+ if (w == NULL)
+ return NULL;
+ uih_clearwindows(uih);
+ w1 = uih->wtop;
+ w->getpos = getpos;
+ w->draw = draw;
+ w->data = data;
+ w->flags = flags;
+ w->savedline = -1;
+ w->saveddata = NULL;
+ w->flags |= BORDER_TRANSPARENT | BORDER_PRESSED | BORDER_LIGHT;
+ w->next = NULL;
+ if (w1 == NULL) {
+ uih->wtop = w;
+ } else {
+ while (w1->next != NULL)
+ w1 = w1->next;
+ w1->next = w;
+ }
+ w->previous = w1;
+ w->x = -65536;
+ return w;
+}
+
+void
+uih_setline(struct uih_context *uih, struct uih_window *w, int color,
+ int x1, int y1, int x2, int y2)
+{
+ if (w->savedline != color || w->x != x1 || w->y != y1
+ || w->width != x2 - x1 || w->height != y2 - y1) {
+ uih_clearwindows(uih);
+ uih->display = 1;
+ w->savedline = color;
+ w->x = x1;
+ w->y = y1;
+ w->width = x2 - x1;
+ w->height = y2 - y1;
+ }
+}
+
+struct uih_window *uih_registerline(struct uih_context *uih, int color,
+ int x1, int y1, int x2, int y2)
+{
+ struct uih_window *w =
+ (struct uih_window *) calloc(1, sizeof(struct uih_window));
+ struct uih_window *w1;
+ if (w == NULL)
+ return NULL;
+ uih_clearwindows(uih);
+ w1 = uih->wtop;
+ uih->display = 1;
+ w->getpos = NULL;
+ w->savedline = color;
+ w->flags = 0;
+ w->x = x1;
+ w->y = y1;
+ w->width = x2 - x1;
+ w->height = y2 - y1;
+ w->saveddata = NULL;
+ w->next = NULL;
+ if (w1 == NULL) {
+ uih->wtop = w;
+ } else {
+ while (w1->next != NULL)
+ w1 = w1->next;
+ w1->next = w;
+ }
+ w->previous = w1;
+ return w;
+}
+
+void uih_removew(struct uih_context *uih, struct uih_window *w)
+{
+ uih_clearwindows(uih);
+ assert(uih->wtop != NULL);
+ assert(w != NULL);
+ uih->display = 1;
+
+ if (w->previous == NULL) {
+ assert(uih->wtop == w);
+ uih->wtop = w->next;
+ } else {
+ w->previous->next = w->next;
+ }
+ if (w->next != NULL) {
+ w->next->previous = w->previous;
+ }
+ free(w);
+}
+
+/*Remove all drawed windows from screen */
+void uih_clearwindows(struct uih_context *uih)
+{
+ struct uih_window *w = uih->wtop;
+ int savedline = 0;
+ int savedpos = 0;
+ int destwidth = uih->image->width * uih->image->bytesperpixel;
+ if (!uih->wdisplayed)
+ return;
+ if (!uih->image->bytesperpixel) {
+ destwidth = (w->x + uih->image->width + 7) / 8;
+ }
+ uih->wdisplayed = 0;
+ if (uih->wflipped)
+ uih->image->flip(uih->image), uih->wflipped = 0;
+ while (w) {
+ if (w->getpos == NULL) {
+ if (w->saveddata != NULL) {
+ xrestoreline(uih->image, w->saveddata, w->x, w->y,
+ w->width + w->x, w->height + w->y);
+ free(w->saveddata);
+ w->saveddata = NULL;
+ }
+ } else {
+ if (w->savedline != -1 || w->saveddata != NULL) {
+ int i;
+ int xskip = w->x * uih->image->bytesperpixel;
+ int width = w->width * uih->image->bytesperpixel;
+ if (!uih->image->bytesperpixel) {
+ xskip = w->x / 8;
+ width = (w->x + w->width + 7) / 8 - xskip;
+ }
+ assert(w->width);
+ assert(w->height);
+ assert(w->x >= 0);
+ assert(w->y >= 0);
+ assert(w->x + w->width <= uih->image->width);
+ assert(w->y + w->height <= uih->image->height);
+ if (w->savedline != -1) {
+ savedline = w->savedline;
+ savedpos = w->savedpos;
+ for (i = w->y; i < w->y + w->height; i++) {
+ unsigned char *data =
+ uih->image->currlines[i] + xskip;
+ assert(savedline < uih->image->height);
+ assert(savedline >= 0);
+ assert(savedpos >= 0 && savedpos <= destwidth);
+ if (width + savedpos > destwidth) {
+ int width1;
+ memcpy(data,
+ uih->image->oldlines[savedline] +
+ savedpos, destwidth - savedpos);
+ savedline++;
+ width1 = width - destwidth + savedpos;
+ memcpy(data + (destwidth - savedpos),
+ uih->image->oldlines[savedline],
+ width1);
+ savedpos = width1;
+ } else
+ memcpy(data,
+ uih->image->oldlines[savedline] +
+ savedpos, width), savedpos += width;
+ }
+ w->savedline = -1;
+ } else {
+ assert(w->saveddata);
+ for (i = w->y; i < w->y + w->height; i++) {
+ unsigned char *data =
+ uih->image->currlines[i] + xskip;
+ memcpy(data, w->saveddata + (i - w->y) * width,
+ width);
+ }
+ free(w->saveddata);
+ w->saveddata = NULL;
+ }
+ }
+ }
+ w = w->next;
+ }
+}
+
+void uih_drawwindows(struct uih_context *uih)
+{
+ struct uih_window *w = uih->wtop;
+ struct image *img = uih->image;
+ int size = 0;
+ int nocopy = 0;
+ int savedline = 0;
+ int savedpos = 0;
+ int destwidth = uih->image->width * uih->image->bytesperpixel;
+ if (!uih->image->bytesperpixel) {
+ destwidth = (w->x + uih->image->width + 7) / 8;
+ }
+ if (uih->wdisplayed)
+ return;
+ uih->wdisplayed = 1;
+ while (w) {
+ if (w->getpos != NULL) {
+ int test = w->x == -65536;
+ w->getpos(uih, &w->x, &w->y, &w->width, &w->height, w->data);
+ if (w->x < 0)
+ w->width -= w->x, w->x = 0;
+ if (w->y < 0)
+ w->height -= w->y, w->y = 0;
+ if (w->x > img->width)
+ w->width = 0, w->height = 0, w->x = 0;
+ if (w->y > img->height)
+ w->width = 0, w->height = 0, w->y = 0;
+ if (w->x + w->width > img->width)
+ w->width = img->width - w->x;
+ if (w->y + w->height > img->height)
+ w->height = img->height - w->y;
+ if (w->width < 0)
+ w->width = 0;
+ if (w->height < 0)
+ w->height = 0;
+ if (test) {
+ struct uih_window *w1 = uih->wtop;
+ while (w1) {
+ if (w != w1 && (w1->flags & DRAWBORDER) &&
+ ((((w1->x > w->x + 5
+ && w1->x + 5 < w->x + w->width)
+ || (w->x > w1->x + 5
+ && w->x + 5 < w1->x + w1->width))
+ &&
+ ((w1->y > w->y + 5
+ && w1->y + 5 < w->y + w->height)
+ || (w->y > w1->y + 5
+ && w->y + 5 < w1->y + w1->height)))
+ ||
+ (((w1->x + w1->width > w->x + 5
+ && w1->x + w1->width + 5 < w->x + w->width)
+ || (w->x + w->width > w1->x + 5
+ && w->x + w->width + 5 < w1->x + w1->width))
+ &&
+ ((w1->y + w1->height > w->y + 5
+ && w1->y + w1->height + 5 < w->y + w->height)
+ || (w->y + w->height > w1->y + 5
+ && w->y + w->height + 5 <
+ w1->y + w1->height))))) {
+ w->flags &= ~BORDER_TRANSPARENT;
+ break;
+ }
+ w1 = w1->next;
+ }
+ }
+ size += w->width * w->height;
+ if (w->x == 0 && w->y == 0 && w->width == img->width
+ && w->height == img->height)
+ nocopy = 1;
+ assert(w->width >= 0);
+ assert(w->height >= 0);
+ assert(w->x >= 0);
+ assert(w->y >= 0);
+ assert(w->x + w->width <= uih->image->width);
+ assert(w->y + w->height <= uih->image->height);
+ }
+ w = w->next;
+ }
+ if (size > img->width * img->height / 2) {
+ int i;
+ int width = img->width * img->bytesperpixel;
+ if (!width)
+ width = (img->width + 7) / 8;
+ uih->wflipped = 1;
+ if (!nocopy)
+ for (i = 0; i < img->height; i++)
+ memcpy(img->oldlines[i], img->currlines[i], width);
+ uih->image->flip(uih->image);
+ } else {
+ int savedminx = -1;
+ int savedmaxx = -1;
+ int savedminy = -1;
+ int savedmaxy = -1;
+ uih->wflipped = 0;
+ w = uih->wtop;
+ while (w) {
+ int i;
+ assert(w->saveddata == NULL);
+ if (w->getpos == NULL) {
+ if ((w->x < savedminx || w->y < savedminy
+ || w->x + w->width > savedmaxx
+ || w->x + w->height > savedmaxy
+ || w->x + w->width < savedminx
+ || w->y + w->height < savedminy || w->x > savedmaxx
+ || w->y > savedmaxy)) {
+ w->saveddata =
+ xsaveline(uih->image, w->x, w->y, w->width + w->x,
+ w->height + w->y);
+ }
+ } else {
+ assert(w->savedline == -1);
+ if (w->width && w->height
+ && (w->x < savedminx || w->y < savedminy
+ || w->x + w->width > savedmaxx
+ || w->y + w->height > savedmaxy)) {
+ int xskip = w->x * uih->image->bytesperpixel;
+ int width = w->width * uih->image->bytesperpixel;
+ savedminx = w->x;
+ savedminy = w->y;
+ savedmaxx = w->x + w->width;
+ savedmaxy = w->y + w->height;
+ if (!uih->image->bytesperpixel) {
+ xskip = w->x / 8;
+ width = (w->x + w->width + 7) / 8 - xskip;
+ }
+ if (uih->image->flags & PROTECTBUFFERS || 1) {
+ w->saveddata =
+ (char *) malloc(width * w->height + 1);
+ if (w->saveddata != NULL)
+ for (i = w->y; i < w->y + w->height; i++) {
+ unsigned char *data =
+ img->currlines[i] + xskip;
+ memcpy(w->saveddata + (i - w->y) * width,
+ data, width);
+ }
+
+ } else {
+ w->savedline = savedline;
+ w->savedpos = savedpos;
+ for (i = w->y; i < w->y + w->height; i++) {
+ unsigned char *data =
+ img->currlines[i] + xskip;
+ if (width + savedpos > destwidth) {
+ int width1;
+ memcpy(uih->image->oldlines[savedline] +
+ savedpos, data,
+ destwidth - savedpos);
+ savedline++;
+ width1 = width - destwidth + savedpos;
+ memcpy(uih->image->oldlines[savedline],
+ data + (destwidth - savedpos),
+ width1);
+ savedpos = width1;
+ } else
+ memcpy(uih->image->oldlines[savedline] +
+ savedpos, data, width), savedpos +=
+ width;
+ }
+ }
+ }
+ }
+ w = w->next;
+ }
+ }
+ w = uih->wtop;
+ while (w) {
+ if (w->getpos == NULL) {
+// This code unfortunately won't work for the Julia show, so
+// deactivated:
+#if 0
+ int lw = 0, lwi = 0, lwj = 0;
+ if (uih->image->width > 800 && uih->image->height > 600)
+ lw = 3;
+
+ for (; lwi <= lw; ++lwi)
+ for (; lwj <= lw; ++lwj)
+#endif
+#define lwi 0
+#define lwj 0
+ xline(uih->image, w->x + lwi, w->y + lwj,
+ w->width + w->x + lwi, w->height + w->y + lwj,
+ w->savedline);
+ } else if (w->width && w->height) {
+ if (w->flags & DRAWBORDER)
+ uih_drawborder(uih, w->x, w->y, w->width, w->height,
+ (BORDER_TRANSPARENT) & w->flags);
+ w->draw(uih, w->data);
+ }
+ w = w->next;
+ }
+}