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