diff options
Diffstat (limited to 'src/ui-hlp')
-rw-r--r-- | src/ui-hlp/Makefile.in | 47 | ||||
-rw-r--r-- | src/ui-hlp/autod.c | 112 | ||||
-rw-r--r-- | src/ui-hlp/autopilot.c | 214 | ||||
-rw-r--r-- | src/ui-hlp/autopilot.h | 33 | ||||
-rw-r--r-- | src/ui-hlp/menu.c | 1678 | ||||
-rw-r--r-- | src/ui-hlp/messg.c | 145 | ||||
-rw-r--r-- | src/ui-hlp/play.c | 946 | ||||
-rw-r--r-- | src/ui-hlp/play.h | 50 | ||||
-rw-r--r-- | src/ui-hlp/playtext.c | 174 | ||||
-rw-r--r-- | src/ui-hlp/render.c | 664 | ||||
-rw-r--r-- | src/ui-hlp/save.c | 704 | ||||
-rw-r--r-- | src/ui-hlp/ui-hlp.pri | 12 | ||||
-rw-r--r-- | src/ui-hlp/ui_helper.c | 2303 | ||||
-rw-r--r-- | src/ui-hlp/wstack.c | 528 |
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; + } +} |