1 #include <climits>
2 #include <cstdlib>
3 #include <cstring>
4 #include "config.h"
5 #include "filter.h"
6 #include "fractal.h"
7 #include "ui_helper.h"
8 #include "catalog.h"
9 #include "xmenu.h"
10 #include "grlib.h"
11 #include "play.h"
12 #include "i18n.h"
13 
14 #define nextchar()                                                             \
15     (uih->playstring == NULL ? xio_getc(FD) : uih->playstring[uih->playpos++])
16 #define ungetchar(c)                                                           \
17     (uih->playstring == NULL ? xio_ungetc(c, FD) : uih->playpos--)
18 #define endoffile()                                                            \
19     (uih->playstring == NULL ? xio_feof(FD)                                    \
20                              : uih->playstring[uih->playpos] == 0)
21 static int nonblockmode;
22 static catalog_t *catalog; /*The message catalog should be "session wide" */
23 const static char *errstring;
24 #define seterr(str)                                                            \
25     {                                                                          \
26         if (errstring == NULL)                                                 \
27             errstring = str;                                                   \
28     }
29 #define FD uih->playc->file
30 static char token[1024];
31 static int first;
32 static int last;
33 static int parsenext;
34 
35 static const char *const animroot = "animroot";
36 
uih_findkey(uih_context * c,int key)37 static inline struct uih_line *uih_findkey(uih_context *c, int key)
38 {
39     struct uih_line *l = c->playc->lines.first;
40     while (l != NULL) {
41         if (l->key == key)
42             return l;
43         l = l->next;
44     }
45     return NULL;
46 }
47 
uih_removeline(uih_context * c,struct uih_line * l)48 static inline void uih_removeline(uih_context *c, struct uih_line *l)
49 {
50     if (l == NULL)
51         return;
52     uih_removew(c, l->w);
53     if (l->prev)
54         l->prev->next = l->next;
55     else
56         c->playc->lines.first = l->next;
57     if (l->next)
58         l->next->prev = l->prev;
59     free(l);
60 }
61 
uih_line(uih_context * c,dialogparam * d)62 void uih_line(uih_context *c, dialogparam *d)
63 {
64     struct uih_window *w;
65     struct uih_line *l;
66     if (c->playstring != NULL) {
67         seterr(TR("Error", "line available only in animation replay"));
68         return;
69     }
70     w = uih_registerline(c, 0, -1, -1, -1, -1);
71     uih_removeline(c, uih_findkey(c, c->playc->lines.currkey));
72     l = (struct uih_line *)calloc(1, sizeof(*l));
73     l->posmode = d[0].dint;
74     l->w = w;
75     l->x1 = d[1].dcoord[0];
76     l->y1 = d[1].dcoord[1];
77     l->x2 = d[2].dcoord[0];
78     l->y2 = d[2].dcoord[1];
79     l->color = c->color;
80     l->morph = 0;
81     l->key = c->playc->lines.currkey++;
82     l->prev = NULL;
83     l->next = c->playc->lines.first;
84     c->playc->lines.first = l;
85 }
86 
uih_morphline(uih_context * c,dialogparam * d)87 void uih_morphline(uih_context *c, dialogparam *d)
88 {
89     struct uih_line *l;
90     l = uih_findkey(c, c->playc->lines.currkey);
91     if (l == NULL) {
92         seterr(TR("Error", "Morphing non existing line!"));
93         return;
94     }
95     c->playc->lines.currkey++;
96     l->mposmode = d[0].dint;
97     l->mx1 = d[1].dcoord[0];
98     l->my1 = d[1].dcoord[1];
99     l->mx2 = d[2].dcoord[0];
100     l->my2 = d[2].dcoord[1];
101     l->morph = 1;
102     c->playc->lines.morphing = 1;
103 }
104 
uih_morphlastline(uih_context * c,dialogparam * d)105 void uih_morphlastline(uih_context *c, dialogparam *d)
106 {
107     c->playc->lines.currkey--;
108     uih_morphline(c, d);
109 }
110 
uih_setkey(uih_context * c,int line)111 void uih_setkey(uih_context *c, int line)
112 {
113     if (!c->play) {
114         seterr(TR("Error", "linekey not available in this context!"));
115         return;
116     }
117     c->playc->lines.currkey = line;
118 }
119 
uih_stopmorphing(uih_context * c)120 static void uih_stopmorphing(uih_context *c)
121 {
122     struct uih_line *l = c->playc->lines.first;
123     while (l) {
124         if (l->morph) {
125             l->x1 = l->mx1;
126             l->y1 = l->my1;
127             l->x2 = l->mx2;
128             l->y2 = l->my2;
129             l->posmode = l->mposmode;
130             l->morph = 0;
131             c->playc->lines.morphing = 1;
132         }
133         l = l->next;
134     }
135 }
136 
uih_update_lines(uih_context * c)137 void uih_update_lines(uih_context *c)
138 {
139     int m = 0;
140     int co;
141     struct uih_line *l = c->playc->lines.first;
142     int x1, y1, x2, y2;
143     number_t x, y;
144     int timer = tl_lookup_timer(c->playc->timer) - c->playc->starttime;
145     number_t
146         mmul = /*(tl_lookup_timer (c->playc->timer) - c->playc->starttime) /
147                   (number_t) (c->playc->frametime - c->playc->starttime); */
148         MORPHVALUE(timer, c->playc->frametime - c->playc->starttime,
149                    c->playc->morphlinetimes[0], c->playc->morphlinetimes[1]);
150 
151     while (l) {
152         switch (l->posmode) {
153             case 0:
154                 x1 = (int)(c->image->width * l->x1);
155                 y1 = (int)(c->image->height * l->y1);
156                 x2 = (int)(c->image->width * l->x2);
157                 y2 = (int)(c->image->height * l->y2);
158                 break;
159             case 1:
160                 x = c->image->width * c->image->pixelwidth;
161                 y = c->image->height * c->image->pixelheight;
162                 if (x > y)
163                     x = y;
164                 x1 = (int)(c->image->width / 2 +
165                            (l->x1 - 0.5) * x / c->image->pixelwidth);
166                 y1 = (int)(c->image->height / 2 +
167                            (l->y1 - 0.5) * x / c->image->pixelheight);
168                 x2 = (int)(c->image->width / 2 +
169                            (l->x2 - 0.5) * x / c->image->pixelwidth);
170                 y2 = (int)(c->image->height / 2 +
171                            (l->y2 - 0.5) * x / c->image->pixelheight);
172                 break;
173             case 2:
174                 x = l->x1;
175                 y = l->y1;
176                 rotate(*(c->fcontext), x, y);
177                 x = (x - c->fcontext->rs.nc) /
178                     (c->fcontext->rs.mc - c->fcontext->rs.nc) *
179                     c->zengine->image->width;
180                 y = (y - c->fcontext->rs.ni) /
181                     (c->fcontext->rs.mi - c->fcontext->rs.ni) *
182                     c->zengine->image->height;
183                 x1 = (int)x;
184                 y1 = (int)y;
185                 c->zengine->action->convertup(c->zengine, &x1, &y1);
186                 x = l->x2;
187                 y = l->y2;
188                 rotate(*(c->fcontext), x, y);
189                 x = (x - c->fcontext->rs.nc) /
190                     (c->fcontext->rs.mc - c->fcontext->rs.nc) *
191                     c->zengine->image->width;
192                 y = (y - c->fcontext->rs.ni) /
193                     (c->fcontext->rs.mi - c->fcontext->rs.ni) *
194                     c->zengine->image->height;
195                 x2 = (int)x;
196                 y2 = (int)y;
197                 c->zengine->action->convertup(c->zengine, &x2, &y2);
198                 break;
199         }
200         if (l->morph) {
201             int mx1, mx2, my1, my2;
202             m = 1;
203             switch (l->mposmode) {
204                 case 0:
205                     mx1 = (int)(c->image->width * l->mx1);
206                     my1 = (int)(c->image->height * l->my1);
207                     mx2 = (int)(c->image->width * l->mx2);
208                     my2 = (int)(c->image->height * l->my2);
209                     break;
210                 case 1:
211                     x = c->image->width * c->image->pixelwidth;
212                     y = c->image->height * c->image->pixelheight;
213                     if (x > y)
214                         x = y;
215                     mx1 = (int)(c->image->width / 2 +
216                                 (l->mx1 - 0.5) * x / c->image->pixelwidth);
217                     my1 = (int)(c->image->height / 2 +
218                                 (l->my1 - 0.5) * x / c->image->pixelheight);
219                     mx2 = (int)(c->image->width / 2 +
220                                 (l->mx2 - 0.5) * x / c->image->pixelwidth);
221                     my2 = (int)(c->image->height / 2 +
222                                 (l->my2 - 0.5) * x / c->image->pixelheight);
223                     break;
224                 default:
225                     x = l->mx1;
226                     y = l->my1;
227                     rotate(*(c->fcontext), x, y);
228                     x = (x - c->fcontext->rs.nc) /
229                         (c->fcontext->rs.mc - c->fcontext->rs.nc) *
230                         c->zengine->image->width;
231                     y = (y - c->fcontext->rs.ni) /
232                         (c->fcontext->rs.mi - c->fcontext->rs.ni) *
233                         c->zengine->image->height;
234                     mx1 = (int)x;
235                     my1 = (int)y;
236                     c->zengine->action->convertup(c->zengine, &mx1, &my1);
237                     x = l->mx2;
238                     y = l->my2;
239                     rotate(*(c->fcontext), x, y);
240                     x = (x - c->fcontext->rs.nc) /
241                         (c->fcontext->rs.mc - c->fcontext->rs.nc) *
242                         c->zengine->image->width;
243                     y = (y - c->fcontext->rs.ni) /
244                         (c->fcontext->rs.mi - c->fcontext->rs.ni) *
245                         c->zengine->image->height;
246                     mx2 = (int)x;
247                     my2 = (int)y;
248                     c->zengine->action->convertup(c->zengine, &mx2, &my2);
249                     break;
250             }
251             x1 = (int)(x1 + (mx1 - x1) * mmul);
252             y1 = (int)(y1 + (my1 - y1) * mmul);
253             x2 = (int)(x2 + (mx2 - x2) * mmul);
254             y2 = (int)(y2 + (my2 - y2) * mmul);
255         }
256         switch (l->color) {
257             case 1:
258                 co = BGCOLOR(c);
259                 break;
260             case 0:
261                 co = FGCOLOR(c);
262                 break;
263             default:
264                 co = SELCOLOR(c);
265                 break;
266         }
267         uih_setline(c, l->w, co, x1, y1, x2, y2);
268 
269         l = l->next;
270     }
271     c->playc->lines.morphing = m;
272     if (m)
273         c->display = 1;
274 }
275 
uih_clear_line(uih_context * c)276 void uih_clear_line(uih_context *c)
277 {
278     if (c->playstring != NULL) {
279         seterr(TR("Error", "clear_line available only in animation replay"));
280         return;
281     }
282     uih_removeline(c, uih_findkey(c, c->playc->lines.currkey++));
283 }
284 
uih_clear_lines(uih_context * c)285 void uih_clear_lines(uih_context *c)
286 {
287     if (c->playstring != NULL) {
288         seterr(TR("Error", "clear_lines available only in animation replay"));
289         return;
290     }
291     while (c->playc->lines.first != NULL)
292         uih_removeline(c, c->playc->lines.first);
293     c->playc->lines.currkey = 0;
294 }
295 
uih_freecatalog(uih_context *)296 void uih_freecatalog(uih_context */*c*/)
297 {
298     if (catalog != NULL)
299         free_catalog(catalog), catalog = NULL;
300 }
301 
uih_setfont(struct uih_context *)302 void uih_setfont(struct uih_context */*uih*/) {}
303 
uih_loadcatalog(uih_context * c,const char * name)304 int uih_loadcatalog(uih_context *c, const char *name)
305 {
306     static int firsttime = 1;
307     static const char *str;
308     xio_file f = xio_getcatalog(name);
309     if (f == XIO_FAILED) {
310         if (firsttime) {
311             firsttime = 0;
312             return 0;
313         } /*Let XaoS work as stand alone executable */
314         uih_error(c, TR("Error", "Catalog file not found"));
315         return 0;
316     }
317     firsttime = 0;
318     if (catalog != NULL)
319         free_catalog(catalog);
320     catalog = load_catalog(f, &str);
321     if (str != NULL)
322         uih_error(c, str);
323     uih_setfont(c);
324     return (catalog != NULL);
325 }
326 
handler(void * userdata)327 static void handler(void *userdata)
328 {
329     struct uih_context *uih = (struct uih_context *)userdata;
330     uih->playc->playframe++;
331     uih->inanimation = 2;
332     if (uih->playc->timerin)
333         tl_remove_timer(uih->playc->timer);
334     uih->playc->timerin = 0;
335 }
336 
handler1(void * userdata)337 static void handler1(void *userdata)
338 {
339     struct uih_context *uih = (struct uih_context *)userdata;
340     uih->playc->playframe++;
341     uih->inanimation = 2;
342     tl_update_time();
343     tl_reset_timer(uih->playc->timer);
344     uih_setcomplettehandler(uih, NULL, NULL);
345 }
346 
uih_skipframe(struct uih_context * uih)347 void uih_skipframe(struct uih_context *uih)
348 {
349     if (uih->play && uih->playc->timerin)
350         handler(uih), tl_reset_timer(uih->playc->timer);
351 }
352 
uih_replayenable(struct uih_context * uih,xio_file f,xio_constpath filename,int animr)353 int uih_replayenable(struct uih_context *uih, xio_file f,
354                      xio_constpath filename, int animr)
355 {
356     struct uih_playcontext *p;
357     const char *s;
358     if (uih->play) {
359         uih_error(uih, TR("Error", "Replay is already active"));
360         return 0;
361     }
362     if (f == XIO_FAILED) {
363         uih_error(uih, TR("Error", "File open failed"));
364         return 0;
365     }
366     p = (struct uih_playcontext *)calloc(1, sizeof(*p));
367     if (p == NULL) {
368         uih_error(uih, TR("Error", "Out of memory"));
369         return 0;
370     }
371     if (animr) {
372         uih->menuroot = animroot;
373         uih_updatemenus(uih, NULL);
374     }
375     p->file = f;
376     p->playframe = 1;
377     p->timer = tl_create_timer();
378     p->frametime = 0;
379     p->morph = 0;
380     p->morphjulia = 0;
381     p->lines.first = NULL;
382     p->lines.morphing = 0;
383     p->lines.currkey = 0;
384     tl_update_time();
385     tl_set_handler(p->timer, handler, uih);
386     uih_stoptimers(uih);
387     if (uih->stoppedtimers)
388         tl_stop_timer(p->timer);
389     uih->playc = p;
390     uih->play = 1;
391     uih_emulatetimers(uih);
392     tl_reset_timer(p->timer);
393     uih->playc->line = 1;
394     if (filename != NULL) {
395         uih->playc->directory = xio_getdirectory(filename);
396     } else {
397         uih->playc->directory = xio_getdirectory(XIO_EMPTYPATH);
398     }
399     uih->playc->level = 0;
400     s = uih->playstring;
401     uih->playstring = NULL;
402     uih_playupdate(uih);
403     uih->playstring = s;
404     return 1;
405 }
406 
uih_replaydisable(struct uih_context * uih)407 void uih_replaydisable(struct uih_context *uih)
408 {
409     if (uih->play) {
410         int i;
411         uih->play = 0;
412         tl_free_timer(uih->playc->timer);
413         if (uih->menuroot == animroot) {
414             uih->menuroot = "root";
415             uih_updatemenus(uih, NULL);
416         }
417         xio_close(uih->playc->file);
418         for (i = 0; i < uih->playc->level; i++)
419             xio_close(uih->playc->prevfiles[i]);
420         uih->display = 1;
421         uih->nonfractalscreen = 0;
422         uih_setcomplettehandler(uih, NULL, NULL);
423         uih_clear_lines(uih);
424         free(uih->playc->directory);
425         free(uih->playc);
426         uih_display(uih);
427     }
428 }
429 
skipblank(struct uih_context * uih)430 static void skipblank(struct uih_context *uih)
431 {
432     int c;
433     if (uih->playstring != NULL) {
434         while ((uih->playstring[uih->playpos] == ' ' ||
435                 uih->playstring[uih->playpos] == '\t' ||
436                 uih->playstring[uih->playpos] == '\r' ||
437                 uih->playstring[uih->playpos] == '\n'))
438             uih->playpos++;
439         return;
440     }
441     do {
442         c = xio_getc(FD);
443         if (c == '\n')
444             uih->playc->line++;
445         if (c == ';')
446             while (c != '\n' && !xio_feof(FD)) {
447                 c = xio_getc(FD);
448                 if (c == '\n')
449                     uih->playc->line++;
450             }
451         while (xio_feof(FD) && uih->playc->level) {
452             c = XIO_EOF + 1;
453             xio_close(FD);
454             uih->playc->file = uih->playc->prevfiles[--uih->playc->level];
455             uih->playc->line = 1;
456         }
457     } while (c == ' ' || c == '\t' || c == '\n' || c == '\r' ||
458              c == XIO_EOF + 1);
459     if (c != XIO_EOF)
460         xio_ungetc(c, FD);
461 }
462 
gettoken(struct uih_context * uih)463 static int gettoken(struct uih_context *uih)
464 {
465     int c;
466     int i = 0;
467     skipblank(uih);
468     if (first && ((c = nextchar()) != '(')) {
469         if (c && !endoffile()) {
470             seterr("'(' expected");
471         }
472         last = 1;
473         return -1;
474     }
475     if (first)
476         skipblank(uih), first = 0;
477     if (endoffile()) {
478         if (uih->playstring) {
479             seterr(TR("Error", "Missing parameter"));
480         } else
481             seterr(TR("Error", "Unexpected end of file"));
482         return 0;
483     }
484     if ((c = nextchar()) == '"') {
485         while (c == '\r')
486             c = nextchar();
487         token[i] = '"';
488         i++;
489         do {
490             c = nextchar();
491             while (c == '\r')
492                 c = nextchar();
493             if (c == XIO_EOF || c == 0) {
494                 if (uih->playstring) {
495                     seterr(TR("Error", "Missing parameter"));
496                 } else
497                     seterr(TR("Error", "Unexpected end of file"));
498                 return 0;
499             }
500             if (c == '\n' && uih->playstring == NULL)
501                 uih->playc->line++;
502             if (c == '\\')
503                 token[i] = nextchar();
504             else
505                 token[i] = c;
506             i++;
507             if (i >= 1024) {
508                 seterr(TR("Error", "Token is too long"));
509                 i = 0;
510             }
511         } while (c != '"');
512     } else
513         ungetchar(c);
514     do {
515         c = nextchar();
516         if (c == XIO_EOF || c == 0) {
517             if (uih->playstring) {
518                 seterr(TR("Error", "Missing parameter"));
519             } else
520                 seterr(TR("Error", "Unexpected end of file"));
521             return 0;
522         }
523         token[i] = c;
524         i++;
525         if (i >= 1024) {
526             seterr(TR("Error", "Token is too long"));
527             i = 0;
528         }
529     } while (c != ' ' && c != '\t' && c != ')' && c != '\n' && c != '\r');
530     i--;
531     token[i] = 0;
532     skipblank(uih);
533     if (c == ')') {
534         last = 1;
535         return i;
536     }
537     c = nextchar();
538     if (uih->playstring == NULL) {
539         while (xio_feof(FD) && uih->playc->level)
540             uih->playc->file = uih->playc->prevfiles[--uih->playc->level],
541             uih->playc->line = 1;
542     }
543     if (c == XIO_EOF || c == 0) {
544         if (uih->playstring) {
545             seterr(TR("Error", "Missing parameter"));
546         } else
547             seterr(TR("Error", "Unexpected end of file"));
548         return 0;
549     }
550     if (c == ')') {
551         last = 1;
552         return i;
553     }
554     ungetchar(c);
555     return i;
556 }
557 
gettokenwr(struct uih_context * c)558 static char *gettokenwr(struct uih_context *c)
559 {
560     if (last)
561         return NULL;
562     if (gettoken(c) < 0)
563         return NULL;
564     if (errstring)
565         return NULL;
566     return (token);
567 }
568 
uih_play_formula(struct uih_context * uih,const char * fname)569 void uih_play_formula(struct uih_context *uih, const char *fname)
570 {
571     int i;
572     for (i = 0; i < nformulas; i++) {
573         if (!strcmp(formulas[i].shortname, fname)) {
574             set_formula(uih->fcontext, i);
575             uih_newimage(uih);
576             return;
577         }
578     }
579     seterr(TR("Error", "Unknown formula type"));
580 }
581 
uih_playmorph(struct uih_context * uih,dialogparam * d)582 void uih_playmorph(struct uih_context *uih, dialogparam *d)
583 {
584     if (uih->playstring != NULL) {
585         seterr(TR("Error", "morph available only in animation replay"));
586         return;
587     }
588     if (d[2].number <= 0 || d[3].number <= 0) {
589         seterr(TR("Error", "morphview: Invalid viewpoint"));
590         uih->playc->destination = uih->fcontext->currentformula->v;
591     }
592     uih->playc->source = uih->fcontext->s;
593     uih->playc->destination.cr = d[0].number;
594     uih->playc->destination.ci = d[1].number;
595     uih->playc->destination.rr = d[2].number;
596     uih->playc->destination.ri = d[3].number;
597     uih->playc->morph = 1;
598 }
599 
uih_playmove(struct uih_context * uih,number_t x,number_t y)600 void uih_playmove(struct uih_context *uih, number_t x, number_t y)
601 {
602     if (uih->playstring != NULL) {
603         seterr(TR("Error", "move available only in animation replay"));
604         return;
605     }
606     uih->playc->source = uih->fcontext->s;
607     uih->playc->destination.cr = x;
608     uih->playc->destination.ci = y;
609     uih->playc->destination.rr = uih->fcontext->s.rr;
610     uih->playc->destination.ri = uih->fcontext->s.ri;
611     uih->playc->morph = 1;
612 }
613 
uih_playmorphjulia(struct uih_context * uih,number_t x,number_t y)614 void uih_playmorphjulia(struct uih_context *uih, number_t x, number_t y)
615 {
616     if (uih->playstring != NULL) {
617         seterr(TR("Error", "morphjulia available only in animation replay"));
618         return;
619     }
620     uih->playc->sr = uih->fcontext->pre;
621     uih->playc->si = uih->fcontext->pim;
622     uih->playc->dr = x;
623     uih->playc->di = y;
624     uih->playc->morphjulia = 1;
625 }
626 
uih_playmorphangle(struct uih_context * uih,number_t angle)627 void uih_playmorphangle(struct uih_context *uih, number_t angle)
628 {
629     if (uih->playstring != NULL) {
630         seterr(TR("Error", "morphangle available only in animation replay"));
631         return;
632     }
633     uih->playc->morphangle = 1;
634     uih->playc->srcangle = uih->fcontext->angle;
635     uih->playc->destangle = angle;
636 }
637 
uih_playautorotate(struct uih_context * uih,int mode)638 void uih_playautorotate(struct uih_context *uih, int mode)
639 {
640     if (mode) {
641         uih_fastrotateenable(uih);
642         uih_rotatemode(uih, ROTATE_CONTINUOUS);
643     } else
644         uih_rotatemode(uih, ROTATE_NONE);
645 }
646 
uih_playfilter(struct uih_context * uih,dialogparam * p)647 void uih_playfilter(struct uih_context *uih, dialogparam *p)
648 {
649     const char *fname = p[0].dstring;
650     int mode;
651     int i;
652     // ignore removed truecolor filter in old xpf/xaf files that used it.
653     if (!strcmp("truecolor", fname))
654         return;
655     for (i = 0; i < uih_nfilters; i++) {
656         if (!strcmp(uih_filters[i]->shortname, fname)) {
657             mode = p[1].dint;
658             if (mode)
659                 uih_enablefilter(uih, i);
660             else
661                 uih_disablefilter(uih, i);
662             return;
663         }
664     }
665     seterr(TR("Error", "Unknown filter"));
666 }
667 
uih_playdefpalette(struct uih_context * uih,int shift)668 void uih_playdefpalette(struct uih_context *uih, int shift)
669 {
670     if (uih->zengine->fractalc->palette == NULL)
671         return;
672     if (mkdefaultpalette(uih->zengine->fractalc->palette) != 0) {
673         uih_newimage(uih);
674     }
675     uih->palettetype = 0;
676     uih->palettechanged = 1;
677     if (shiftpalette(uih->zengine->fractalc->palette, shift)) {
678         uih_newimage(uih);
679     }
680     uih->manualpaletteshift = 0;
681     uih->paletteshift = shift;
682 }
683 
uih_zoomcenter(struct uih_context * uih,number_t x,number_t y)684 void uih_zoomcenter(struct uih_context *uih, number_t x, number_t y)
685 {
686     uih->xcenter = x;
687     uih->ycenter = y;
688     uih->xcenterm = INT_MAX;
689     uih->ycenterm = INT_MAX;
690 }
691 
uih_playtextpos(struct uih_context * uih,dialogparam * p)692 void uih_playtextpos(struct uih_context *uih, dialogparam *p)
693 {
694     int x, y;
695     x = p[0].dint;
696     y = p[1].dint;
697     uih_settextpos(uih, x, y);
698 }
699 
uih_playusleep(struct uih_context * uih,int time)700 void uih_playusleep(struct uih_context *uih, int time)
701 {
702     parsenext = 0;
703     if (uih->playstring != NULL) {
704         seterr(TR("Error", "sleep available only in animation replay"));
705         return;
706     }
707     uih->playc->frametime = time;
708     if (time < tl_lookup_timer(
709                    uih->playc->timer) /*&&((!uih->step)||(!uih->zoomactive)) */
710     ) {
711         tl_slowdown_timer(uih->playc->timer, time);
712         uih->playc->playframe++;
713     } else {
714         tl_set_interval(uih->playc->timer, time);
715         if (!uih->playc->timerin) {
716             uih->playc->timerin = 1;
717             tl_add_timer(syncgroup, uih->playc->timer);
718         } else
719             printf(TR("Error", "Internal program error #12 %i\n"),
720                    uih->playc->playframe);
721     }
722     uih->playc->starttime = tl_lookup_timer(uih->playc->timer);
723 }
724 
uih_playtextsleep(struct uih_context * uih)725 void uih_playtextsleep(struct uih_context *uih)
726 {
727     uih_playusleep(uih, 500000 + 1000000 *
728                                      (uih->nletters + uih->todisplayletters) /
729                                      uih->letterspersec);
730     uih->nletters = 0;
731     uih->todisplayletters = 0;
732 }
733 
uih_playwait(struct uih_context * uih)734 void uih_playwait(struct uih_context *uih)
735 {
736     parsenext = 0;
737     if (uih->playstring != NULL) {
738         seterr(TR("Error", "wait available only in animation replay"));
739         return;
740     }
741     if (!uih->incomplete && !uih->display && !uih->recalculatemode &&
742         !uih->displaytext && !uih->clearscreen) {
743         uih->playc->playframe++;
744     } else {
745         uih_setcomplettehandler(uih, handler1, uih);
746     }
747 }
748 
uih_playjulia(struct uih_context * uih,int julia)749 void uih_playjulia(struct uih_context *uih, int julia)
750 {
751     julia = !julia;
752     if (julia != uih->fcontext->mandelbrot) {
753         uih->fcontext->mandelbrot = julia;
754         uih->fcontext->version++;
755         uih_updatemenus(uih, "uimandelbrot");
756         uih_newimage(uih);
757     }
758 }
759 
uih_playcalculate(struct uih_context * uih)760 void uih_playcalculate(struct uih_context *uih) { uih_newimage(uih); }
761 
uih_playzoom(struct uih_context * uih)762 void uih_playzoom(struct uih_context *uih) { uih->zoomactive = 1; }
763 
uih_playunzoom(struct uih_context * uih)764 void uih_playunzoom(struct uih_context *uih) { uih->zoomactive = -1; }
765 
uih_playstop(struct uih_context * uih)766 void uih_playstop(struct uih_context *uih) { uih->zoomactive = 0; }
767 
uih_playmessage(struct uih_context * uih,char * name)768 void uih_playmessage(struct uih_context *uih, char *name)
769 {
770     char *message;
771     if (catalog == NULL) {
772         uih_text(uih, TR("Error", "No catalog file loaded"));
773         return;
774     }
775     message = find_text(catalog, name);
776     if (message == NULL) {
777         uih_text(uih, TR("Error", "Message not found in catalog file"));
778         return;
779     }
780     uih_text(uih, message);
781 }
782 
uih_playload(struct uih_context * uih,xio_path file)783 void uih_playload(struct uih_context *uih, xio_path file)
784 {
785     xio_file f;
786     xio_pathdata tmp;
787     if (uih->playstring != NULL) {
788         seterr(TR("Error", "load available only in animation replay"));
789         return;
790     }
791     if (uih->playc->level == MAXLEVEL) {
792         seterr(TR("Error", "Include level overflow"));
793         return;
794     }
795 
796     xio_addfname(tmp, uih->playc->directory, file);
797     f = xio_ropen(tmp);
798 
799     if (f == XIO_FAILED) {
800         seterr(TR("Error", "File not found"));
801         return;
802     }
803     uih->playc->prevfiles[uih->playc->level] = uih->playc->file;
804     uih->playc->level++;
805     uih->playc->file = f;
806     uih->playc->line = 1;
807 }
808 
uih_processcommand(struct uih_context * uih,int flags)809 static void uih_processcommand(struct uih_context *uih, int flags)
810 {
811     const char *error;
812     first = 1;
813     last = 0;
814     error = menu_processcommand(uih, gettokenwr, 1, flags, uih->menuroot);
815     if (error != NULL)
816         seterr(error);
817     if (!last) {
818         seterr(TR("Error", "Too many parameters"));
819     }
820 }
821 
uih_playupdate(struct uih_context * uih)822 void uih_playupdate(struct uih_context *uih)
823 {
824     static char errtext[1024];
825     errstring = NULL;
826     while (uih->play && uih->playc->playframe && errstring == NULL) {
827         parsenext = 1;
828         uih->playc->playframe--;
829         if (uih->playc->lines.morphing) {
830             uih_stopmorphing(uih);
831             uih->display = 1;
832         }
833         if (uih->playc->morph) {
834             uih->fcontext->s = uih->playc->destination;
835             uih_animate_image(uih);
836             uih->playc->morph = 0;
837         }
838         if (uih->playc->morphangle) {
839             uih_angle(uih, uih->playc->destangle);
840             uih->playc->morphangle = 0;
841         }
842         if (uih->playc->morphjulia) {
843             uih_setjuliaseed(uih, uih->playc->dr, uih->playc->di);
844             uih->playc->morphjulia = 0;
845         }
846         while (!xio_feof(FD) && parsenext && errstring == NULL) {
847             uih_processcommand(uih, MENUFLAG_NOPLAY);
848         } /*while parsenext */
849         uih_update_lines(uih);
850         if (errstring != NULL) {
851             uih_error(uih, errstring);
852             if (uih->play) {
853                 sprintf(errtext, TR("Message", "Replay disabled at line %i"),
854                         uih->playc->line);
855                 uih_message(uih, errtext);
856             }
857             /*errstring[255]=0; */
858         }
859         if ((xio_feof(FD) && parsenext) || errstring) {
860             uih_replaydisable(uih);
861         }
862     } /*while play&&playframe */
863 }
864 
uih_load(struct uih_context * uih,xio_file f,xio_constpath filename)865 void uih_load(struct uih_context *uih, xio_file f, xio_constpath filename)
866 {
867     nonblockmode = 1;
868     uih_replayenable(uih, f, filename, 0);
869     uih_replaydisable(uih);
870     nonblockmode = 0;
871 }
872 
uih_command(struct uih_context * uih,const char * command)873 void uih_command(struct uih_context *uih, const char *command)
874 {
875     errstring = NULL;
876     uih->playpos = 0;
877     uih->playstring = command;
878     uih_processcommand(uih, (uih->play ? MENUFLAG_NOMENU : 0));
879     uih->playstring = NULL;
880     if (errstring != NULL) {
881         uih_error(uih, errstring);
882     }
883 }
884