1 
2 #include <string.h>
3 #ifdef __TURBOC__
4 #include <alloc.h>
5 #elif defined(__APPLE__)
6 #include <malloc/malloc.h>
7 #elif !defined(BIG_ANSI_C)
8 #include <malloc.h>
9 #endif
10 
11   /* see Fractint.c for a description of the "include"  hierarchy */
12 #include "port.h"
13 #include "prototyp.h"
14 #include "lsys.h"
15 
16 struct lsys_cmd {
17     void (*f)(struct lsys_turtlestatei *);
18     long n;
19     char ch;
20 };
21 
22 static int _fastcall readLSystemFile(char *);
23 static void _fastcall free_rules_mem(void);
24 static int _fastcall rule_present(char symbol);
25 static int _fastcall save_rule(char *,char far **);
26 static int _fastcall append_rule(char *rule, int index);
27 static void free_lcmds(void);
28 static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_turtlestatei *, struct lsys_cmd far **,int);
29 static struct lsys_cmd far * drawLSysI(struct lsys_cmd far *command,struct lsys_turtlestatei *ts, struct lsys_cmd far **rules,int depth);
30 static int lsysi_findscale(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth);
31 static struct lsys_cmd far *LSysISizeTransform(char far *s, struct lsys_turtlestatei *ts);
32 static struct lsys_cmd far *LSysIDrawTransform(char far *s, struct lsys_turtlestatei *ts);
33 static void _fastcall lsysi_dosincos(void);
34 
35 static void lsysi_doslash(struct lsys_turtlestatei *cmd);
36 static void lsysi_dobslash(struct lsys_turtlestatei *cmd);
37 static void lsysi_doat(struct lsys_turtlestatei *cmd);
38 static void lsysi_dopipe(struct lsys_turtlestatei *cmd);
39 static void lsysi_dosizedm(struct lsys_turtlestatei *cmd);
40 static void lsysi_dosizegf(struct lsys_turtlestatei *cmd);
41 static void lsysi_dodrawd(struct lsys_turtlestatei *cmd);
42 static void lsysi_dodrawm(struct lsys_turtlestatei *cmd);
43 static void lsysi_dodrawg(struct lsys_turtlestatei *cmd);
44 static void lsysi_dodrawf(struct lsys_turtlestatei *cmd);
45 static void lsysi_dodrawc(struct lsys_turtlestatei *cmd);
46 static void lsysi_dodrawgt(struct lsys_turtlestatei *cmd);
47 static void lsysi_dodrawlt(struct lsys_turtlestatei *cmd);
48 
49 /* Some notes to Adrian from PB, made when I integrated with v15:
50      printfs changed to work with new user interface
51      bug at end of readLSystemFile, the line which said rulind=0 fixed
52        to say *rulind=0
53      the calloc was not worthwhile, it was just for a 54 byte area, cheaper
54        to keep it as a static;  but there was a static 201 char buffer I
55        changed to not be static
56      use of strdup was a nono, caused problems running out of space cause
57        the memory allocated each time was never freed; I've changed to
58        use far memory and to free when done
59    */
60 
61 #define sins ((long *)(boxy))
62 #define coss (((long *)(boxy)+50)) /* 50 after the start of sins */
63 static char far *ruleptrs[MAXRULES];
64 static struct lsys_cmd far *rules2[MAXRULES];
65 char maxangle;
66 static char loaded=0;
67 
68 
ispow2(int n)69 int _fastcall ispow2(int n)
70 {
71   return (n == (n & -n));
72 }
73 
getnumber(char far ** str)74 LDBL _fastcall getnumber(char far **str)
75 {
76    char numstr[30];
77    LDBL ret;
78    int i,root,inverse;
79 
80    root=0;
81    inverse=0;
82    strcpy(numstr,"");
83    (*str)++;
84    switch (**str)
85    {
86    case 'q':
87       root=1;
88       (*str)++;
89       break;
90    case 'i':
91       inverse=1;
92       (*str)++;
93       break;
94    }
95    switch (**str)
96    {
97    case 'q':
98       root=1;
99       (*str)++;
100       break;
101    case 'i':
102       inverse=1;
103       (*str)++;
104       break;
105    }
106    i=0;
107    while ((**str<='9' && **str>='0') || **str=='.')
108    {
109       numstr[i++]= **str;
110       (*str)++;
111    }
112    (*str)--;
113    numstr[i]=0;
114    ret=atof(numstr);
115    if (ret <= 0.0) /* this is a sanity check, JCO 8/31/94 */
116       return 0;
117    if (root)
118      ret=sqrtl(ret);
119    if (inverse)
120      ret = 1.0/ret;
121    return ret;
122 }
123 
124 #ifndef XFRACT
125 #define LDBL            double
126 #endif
127 
readLSystemFile(char * str)128 static int _fastcall readLSystemFile(char *str)
129 {
130    int c;
131    char far **rulind;
132    int err=0;
133    int linenum,check=0;
134    char inline1[MAX_LSYS_LINE_LEN+1],fixed[MAX_LSYS_LINE_LEN+1],*word;
135    FILE *infile;
136    char msgbuf[481]; /* enough for 6 full lines */
137 
138    if (find_file_item(LFileName,str,&infile, 2) < 0)
139       return -1;
140    while ((c = fgetc(infile)) != '{')
141       if (c == EOF) return -1;
142    maxangle=0;
143    for(linenum=0;linenum<MAXRULES;++linenum) ruleptrs[linenum]=NULL;
144    rulind= &ruleptrs[1];
145    msgbuf[0]=(char)(linenum=0);
146 
147    while(file_gets(inline1,MAX_LSYS_LINE_LEN,infile) > -1)  /* Max line length chars */
148    {
149       static FCODE out_of_mem[] = {"Error:  out of memory\n"};
150       linenum++;
151       if ((word = strchr(inline1,';')) != NULL) /* strip comment */
152          *word = 0;
153       strlwr(inline1);
154 
155       if ((int)strspn(inline1," \t\n") < (int)strlen(inline1)) /* not a blank line */
156       {
157          word=strtok(inline1," =\t\n");
158          if (!strcmp(word,"axiom"))
159          {
160             if (save_rule(strtok(NULL," \t\n"),&ruleptrs[0])) {
161                 far_strcat(msgbuf,out_of_mem);
162                 ++err;
163                 break;
164             }
165             check=1;
166          }
167          else if (!strcmp(word,"angle"))
168          {
169             maxangle=(char)atoi(strtok(NULL," \t\n"));
170             check=1;
171          }
172          else if (!strcmp(word,"}"))
173             break;
174          else if (!word[1])
175          {
176             char *temp;
177             int index, memerr = 0;
178 
179             if (strchr("+-/\\@|!c<>][", *word))
180             {
181                sprintf(&msgbuf[strlen(msgbuf)],
182                "Syntax error line %d: Redefined reserved symbol %s\n",linenum,word);
183                ++err;
184                break;
185             }
186             temp = strtok(NULL," =\t\n");
187             index = rule_present(*word);
188 
189             if (!index)
190             {
191                strcpy(fixed,word);
192                if (temp)
193                   strcat(fixed,temp);
194                memerr = save_rule(fixed,rulind++);
195             }
196             else if (temp)
197             {
198                strcpy(fixed,temp);
199                memerr = append_rule(fixed,index);
200             }
201             if (memerr) {
202                 far_strcat(msgbuf, out_of_mem);
203                 ++err;
204                 break;
205             }
206             check=1;
207          }
208          else
209             if (err<6)
210             {
211                sprintf(&msgbuf[strlen(msgbuf)],
212                        "Syntax error line %d: %s\n",linenum,word);
213                ++err;
214             }
215          if (check)
216          {
217             check=0;
218             if((word=strtok(NULL," \t\n"))!=NULL)
219                if (err<6)
220                {
221                   sprintf(&msgbuf[strlen(msgbuf)],
222                          "Extra text after command line %d: %s\n",linenum,word);
223                   ++err;
224                }
225          }
226       }
227    }
228    fclose(infile);
229    if (!ruleptrs[0] && err<6)
230    {
231       static FCODE no_axiom[] = {"Error:  no axiom\n"};
232       far_strcat(msgbuf,no_axiom);
233       ++err;
234    }
235    if ((maxangle<3||maxangle>50) && err<6)
236    {
237       static FCODE missing_angle[] = {"Error:  illegal or missing angle\n"};
238       far_strcat(msgbuf,missing_angle);
239       ++err;
240    }
241    if (err)
242    {
243       msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */
244       stopmsg(0,msgbuf);
245       return -1;
246    }
247    *rulind=NULL;
248    return 0;
249 }
250 
Lsystem(void)251 int Lsystem(void)
252 {
253    int order;
254    char far **rulesc;
255    struct lsys_cmd far **sc;
256    int stackoflow = 0;
257 
258    if ( (!loaded) && LLoad())
259      return -1;
260 
261    overflow = 0;                /* reset integer math overflow flag */
262 
263    order=(int)param[0];
264    if (order<=0)
265      order=0;
266    if (usr_floatflag)
267         overflow = 1;
268    else {
269         struct lsys_turtlestatei ts;
270 
271         ts.stackoflow = 0;
272         ts.maxangle = maxangle;
273         ts.dmaxangle = (char)(maxangle - 1);
274 
275         sc = rules2;
276         for (rulesc = ruleptrs; *rulesc; rulesc++)
277             *sc++ = LSysISizeTransform(*rulesc, &ts);
278         *sc = NULL;
279 
280         lsysi_dosincos();
281         if (lsysi_findscale(rules2[0], &ts, &rules2[1], order)) {
282             ts.realangle = ts.angle = ts.reverse = 0;
283 
284             free_lcmds();
285             sc = rules2;
286             for (rulesc = ruleptrs; *rulesc; rulesc++)
287                 *sc++ = LSysIDrawTransform(*rulesc, &ts);
288             *sc = NULL;
289 
290             /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
291             if ((ts.curcolor=15) > colors)
292                 ts.curcolor=(char)(colors-1);
293             drawLSysI(rules2[0], &ts, &rules2[1], order);
294         }
295         stackoflow = ts.stackoflow;
296    }
297 
298    if (stackoflow) {
299       static FCODE msg[]={"insufficient memory, try a lower order"};
300       stopmsg(0,msg);
301    }
302    else if (overflow) {
303         struct lsys_turtlestatef ts;
304 
305         overflow = 0;
306 
307         ts.stackoflow = 0;
308         ts.maxangle = maxangle;
309         ts.dmaxangle = (char)(maxangle - 1);
310 
311         sc = rules2;
312         for (rulesc = ruleptrs; *rulesc; rulesc++)
313             *sc++ = LSysFSizeTransform(*rulesc, &ts);
314         *sc = NULL;
315 
316         lsysf_dosincos();
317         if (lsysf_findscale(rules2[0], &ts, &rules2[1], order)) {
318             ts.realangle = ts.angle = ts.reverse = 0;
319 
320             free_lcmds();
321             sc = rules2;
322             for (rulesc = ruleptrs; *rulesc; rulesc++)
323                 *sc++ = LSysFDrawTransform(*rulesc, &ts);
324             *sc = NULL;
325 
326             /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
327             if ((ts.curcolor=15) > colors)
328                 ts.curcolor=(char)(colors-1);
329             lsys_prepfpu(&ts);
330             drawLSysF(rules2[0], &ts, &rules2[1], order);
331             lsys_donefpu(&ts);
332         }
333         overflow = 0;
334    }
335    free_rules_mem();
336    free_lcmds();
337    loaded=0;
338    return 0;
339 }
340 
LLoad(void)341 int LLoad(void)
342 {
343    if (readLSystemFile(LName)) { /* error occurred */
344       free_rules_mem();
345       loaded=0;
346       return -1;
347    }
348    loaded=1;
349    return 0;
350 }
351 
free_rules_mem(void)352 static void _fastcall free_rules_mem(void)
353 {
354    int i;
355    for(i=0;i<MAXRULES;++i)
356       if(ruleptrs[i]) farmemfree(ruleptrs[i]);
357 }
358 
rule_present(char symbol)359 static int _fastcall rule_present(char symbol)
360 {
361    int i;
362 
363    for (i = 1; i < MAXRULES && ruleptrs[i] && *ruleptrs[i] != symbol ; i++)
364       ;
365    return (i < MAXRULES && ruleptrs[i]) ? i : 0;
366 }
367 
save_rule(char * rule,char far ** saveptr)368 static int _fastcall save_rule(char *rule,char far **saveptr)
369 {
370    int i;
371    char far *tmpfar;
372    i=strlen(rule)+1;
373    if((tmpfar=(char far *)farmemalloc((long)i))==NULL) {
374        return -1;
375    }
376    *saveptr=tmpfar;
377    while(--i>=0) *(tmpfar++)= *(rule++);
378    return 0;
379 }
380 
append_rule(char * rule,int index)381 static int _fastcall append_rule(char *rule, int index)
382 {
383    char far *dst, far *old, far *sav;
384    int i, j;
385 
386    old = sav = ruleptrs[index];
387    for (i = 0; *(old++); i++)
388       ;
389    j = strlen(rule) + 1;
390    if ((dst = (char far *)farmemalloc((long)(i + j))) == NULL)
391       return -1;
392 
393    old = sav;
394    ruleptrs[index] = dst;
395    while (i-- > 0) *(dst++) = *(old++);
396    while (j-- > 0) *(dst++) = *(rule++);
397    farmemfree(sav);
398    return 0;
399 }
400 
free_lcmds(void)401 static void free_lcmds(void)
402 {
403   struct lsys_cmd far **sc = rules2;
404 
405   while (*sc)
406     farmemfree(*sc++);
407 }
408 
409 #ifdef XFRACT
410 #define lsysi_doslash_386 lsysi_doslash
411 #define lsysi_dobslash_386 lsysi_dobslash
412 #define lsys_doat lsysi_doat
413 #define lsys_dosizegf lsysi_dosizegf
414 #define lsys_dodrawg lsysi_dodrawg
lsys_prepfpu(struct lsys_turtlestatef * x)415 void lsys_prepfpu(struct lsys_turtlestatef *x) { }
lsys_donefpu(struct lsys_turtlestatef * x)416 void lsys_donefpu(struct lsys_turtlestatef *x) { }
417 #endif
418 
419 /* integer specific routines */
420 
421 #ifdef XFRACT
lsysi_doplus(struct lsys_turtlestatei * cmd)422 static void lsysi_doplus(struct lsys_turtlestatei *cmd)
423 {
424     if (cmd->reverse) {
425         if (++cmd->angle == cmd->maxangle)
426             cmd->angle = 0;
427     }
428     else {
429         if (cmd->angle)
430             cmd->angle--;
431         else
432             cmd->angle = cmd->dmaxangle;
433     }
434 }
435 #else
436 extern void lsysi_doplus(struct lsys_turtlestatei *cmd);
437 #endif
438 
439 #ifdef XFRACT
440 /* This is the same as lsys_doplus, except maxangle is a power of 2. */
lsysi_doplus_pow2(struct lsys_turtlestatei * cmd)441 static void lsysi_doplus_pow2(struct lsys_turtlestatei *cmd)
442 {
443     if (cmd->reverse) {
444         cmd->angle++;
445         cmd->angle &= cmd->dmaxangle;
446     }
447     else {
448         cmd->angle--;
449         cmd->angle &= cmd->dmaxangle;
450     }
451 }
452 #else
453 extern void lsysi_doplus_pow2(struct lsys_turtlestatei *cmd);
454 #endif
455 
456 #ifdef XFRACT
lsysi_dominus(struct lsys_turtlestatei * cmd)457 static void lsysi_dominus(struct lsys_turtlestatei *cmd)
458 {
459     if (cmd->reverse) {
460         if (cmd->angle)
461             cmd->angle--;
462         else
463             cmd->angle = cmd->dmaxangle;
464     }
465     else {
466         if (++cmd->angle == cmd->maxangle)
467             cmd->angle = 0;
468     }
469 }
470 #else
471 extern void lsysi_dominus(struct lsys_turtlestatei *cmd);
472 #endif
473 
474 #ifdef XFRACT
lsysi_dominus_pow2(struct lsys_turtlestatei * cmd)475 static void lsysi_dominus_pow2(struct lsys_turtlestatei *cmd)
476 {
477     if (cmd->reverse) {
478         cmd->angle--;
479         cmd->angle &= cmd->dmaxangle;
480     }
481     else {
482         cmd->angle++;
483         cmd->angle &= cmd->dmaxangle;
484     }
485 }
486 #else
487 extern void lsysi_dominus_pow2(struct lsys_turtlestatei *cmd);
488 #endif
489 
lsysi_doslash(struct lsys_turtlestatei * cmd)490 static void lsysi_doslash(struct lsys_turtlestatei *cmd)
491 {
492     if (cmd->reverse)
493         cmd->realangle -= cmd->num;
494     else
495         cmd->realangle += cmd->num;
496 }
497 
498 #ifndef XFRACT
499 extern void lsysi_doslash_386(struct lsys_turtlestatei *cmd);
500 #endif
501 
lsysi_dobslash(struct lsys_turtlestatei * cmd)502 static void lsysi_dobslash(struct lsys_turtlestatei *cmd)
503 {
504     if (cmd->reverse)
505         cmd->realangle += cmd->num;
506     else
507         cmd->realangle -= cmd->num;
508 }
509 
510 #ifndef XFRACT
511 extern void lsysi_dobslash_386(struct lsys_turtlestatei *cmd);
512 #endif
513 
lsysi_doat(struct lsys_turtlestatei * cmd)514 static void lsysi_doat(struct lsys_turtlestatei *cmd)
515 {
516     cmd->size = multiply(cmd->size, cmd->num, 19);
517 }
518 
lsysi_dopipe(struct lsys_turtlestatei * cmd)519 static void lsysi_dopipe(struct lsys_turtlestatei *cmd)
520 {
521     cmd->angle = (char)(cmd->angle + (char)(cmd->maxangle / 2));
522     cmd->angle %= cmd->maxangle;
523 }
524 
525 #ifdef XFRACT
lsysi_dopipe_pow2(struct lsys_turtlestatei * cmd)526 static void lsysi_dopipe_pow2(struct lsys_turtlestatei *cmd)
527 {
528     cmd->angle += cmd->maxangle >> 1;
529     cmd->angle &= cmd->dmaxangle;
530 }
531 #else
532 extern void lsysi_dopipe_pow2(struct lsys_turtlestatei *cmd);
533 #endif
534 
535 #ifdef XFRACT
lsysi_dobang(struct lsys_turtlestatei * cmd)536 static void lsysi_dobang(struct lsys_turtlestatei *cmd)
537 {
538     cmd->reverse = ! cmd->reverse;
539 }
540 #else
541 extern void lsysi_dobang(struct lsys_turtlestatei *cmd);
542 #endif
543 
lsysi_dosizedm(struct lsys_turtlestatei * cmd)544 static void lsysi_dosizedm(struct lsys_turtlestatei *cmd)
545 {
546     LDBL angle = (LDBL) cmd->realangle * ANGLE2DOUBLE;
547     LDBL s, c;
548     long fixedsin, fixedcos;
549 
550     FPUsincos(&angle, &s, &c);
551     fixedsin = (long) (s * FIXEDLT1);
552     fixedcos = (long) (c * FIXEDLT1);
553 
554     cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
555     cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
556 
557 /* xpos+=size*aspect*cos(realangle*PI/180); */
558 /* ypos+=size*sin(realangle*PI/180); */
559     if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
560     if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
561     if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
562     if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
563 }
564 
lsysi_dosizegf(struct lsys_turtlestatei * cmd)565 static void lsysi_dosizegf(struct lsys_turtlestatei *cmd)
566 {
567   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[(int)cmd->angle], 29));
568   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[(int)cmd->angle], 29));
569 /* xpos+=size*coss[angle]; */
570 /* ypos+=size*sins[angle]; */
571   if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
572   if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
573   if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
574   if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
575 }
576 
lsysi_dodrawd(struct lsys_turtlestatei * cmd)577 static void lsysi_dodrawd(struct lsys_turtlestatei *cmd)
578 {
579   LDBL angle = (LDBL) cmd->realangle * ANGLE2DOUBLE;
580   LDBL s, c;
581   long fixedsin, fixedcos;
582   int lastx, lasty;
583 
584   FPUsincos(&angle, &s, &c);
585   fixedsin = (long) (s * FIXEDLT1);
586   fixedcos = (long) (c * FIXEDLT1);
587 
588   lastx=(int) (cmd->xpos >> 19);
589   lasty=(int) (cmd->ypos >> 19);
590   cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
591   cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
592 /* xpos+=size*aspect*cos(realangle*PI/180); */
593 /* ypos+=size*sin(realangle*PI/180); */
594   draw_line(lastx,lasty,(int)(cmd->xpos >> 19),(int)(cmd->ypos >> 19),cmd->curcolor);
595 }
596 
lsysi_dodrawm(struct lsys_turtlestatei * cmd)597 static void lsysi_dodrawm(struct lsys_turtlestatei *cmd)
598 {
599   LDBL angle = (LDBL) cmd->realangle * ANGLE2DOUBLE;
600   LDBL s, c;
601   long fixedsin, fixedcos;
602 
603   FPUsincos(&angle, &s, &c);
604   fixedsin = (long) (s * FIXEDLT1);
605   fixedcos = (long) (c * FIXEDLT1);
606 
607 /* xpos+=size*aspect*cos(realangle*PI/180); */
608 /* ypos+=size*sin(realangle*PI/180); */
609   cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
610   cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
611 }
612 
lsysi_dodrawg(struct lsys_turtlestatei * cmd)613 static void lsysi_dodrawg(struct lsys_turtlestatei *cmd)
614 {
615   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[(int)cmd->angle], 29));
616   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[(int)cmd->angle], 29));
617 /* xpos+=size*coss[angle]; */
618 /* ypos+=size*sins[angle]; */
619 }
620 
lsysi_dodrawf(struct lsys_turtlestatei * cmd)621 static void lsysi_dodrawf(struct lsys_turtlestatei *cmd)
622 {
623   int lastx = (int) (cmd->xpos >> 19);
624   int lasty = (int) (cmd->ypos >> 19);
625   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[(int)cmd->angle], 29));
626   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[(int)cmd->angle], 29));
627 /* xpos+=size*coss[angle]; */
628 /* ypos+=size*sins[angle]; */
629   draw_line(lastx,lasty,(int)(cmd->xpos >> 19),(int)(cmd->ypos >> 19),cmd->curcolor);
630 }
631 
lsysi_dodrawc(struct lsys_turtlestatei * cmd)632 static void lsysi_dodrawc(struct lsys_turtlestatei *cmd)
633 {
634   cmd->curcolor = (char)(((int) cmd->num) % colors);
635 }
636 
lsysi_dodrawgt(struct lsys_turtlestatei * cmd)637 static void lsysi_dodrawgt(struct lsys_turtlestatei *cmd)
638 {
639   cmd->curcolor = (char)(cmd->curcolor - (char)cmd->num);
640   if ((cmd->curcolor %= colors) == 0)
641     cmd->curcolor = (char)(colors-1);
642 }
643 
lsysi_dodrawlt(struct lsys_turtlestatei * cmd)644 static void lsysi_dodrawlt(struct lsys_turtlestatei *cmd)
645 {
646   cmd->curcolor = (char)(cmd->curcolor + (char)cmd->num);
647   if ((cmd->curcolor %= colors) == 0)
648     cmd->curcolor = 1;
649 }
650 
651 static struct lsys_cmd far * _fastcall
findsize(struct lsys_cmd far * command,struct lsys_turtlestatei * ts,struct lsys_cmd far ** rules,int depth)652 findsize(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth)
653 {
654    struct lsys_cmd far **rulind;
655    int tran;
656 
657 if (overflow)     /* integer math routines overflowed */
658     return NULL;
659 
660    if (stackavail() < 400) { /* leave some margin for calling subrtns */
661       ts->stackoflow = 1;
662       return NULL;
663    }
664 
665    while (command->ch && command->ch !=']') {
666       static FCODE thinking_msg[] =
667          {"L-System thinking (higher orders take longer)"};
668       if (! (ts->counter++)) {
669          /* let user know we're not dead */
670          if (thinking(1,thinking_msg)) {
671             ts->counter--;
672             return NULL;
673          }
674       }
675       tran=0;
676       if (depth) {
677          for(rulind=rules;*rulind;rulind++)
678             if ((*rulind)->ch==command->ch) {
679                tran=1;
680                if (findsize((*rulind)+1,ts,rules,depth-1) == NULL)
681                   return(NULL);
682             }
683       }
684       if (!depth || !tran) {
685         if (command->f) {
686           ts->num = command->n;
687           (*command->f)(ts);
688           }
689         else if (command->ch == '[') {
690           char saveang,saverev;
691           long savesize,savex,savey;
692           unsigned long saverang;
693 
694           saveang=ts->angle;
695           saverev=ts->reverse;
696           savesize=ts->size;
697           saverang=ts->realangle;
698           savex=ts->xpos;
699           savey=ts->ypos;
700           if ((command=findsize(command+1,ts,rules,depth)) == NULL)
701              return(NULL);
702           ts->angle=saveang;
703           ts->reverse=saverev;
704           ts->size=savesize;
705           ts->realangle=saverang;
706           ts->xpos=savex;
707           ts->ypos=savey;
708         }
709       }
710       command++;
711    }
712    return command;
713 }
714 
715 static int
lsysi_findscale(struct lsys_cmd far * command,struct lsys_turtlestatei * ts,struct lsys_cmd far ** rules,int depth)716 lsysi_findscale(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth)
717 {
718    float horiz,vert;
719    double xmin, xmax, ymin, ymax;
720    double locsize;
721    double locaspect;
722    struct lsys_cmd far *fsret;
723 
724    locaspect=screenaspect*xdots/ydots;
725    ts->aspect = FIXEDPT(locaspect);
726    ts->xpos =
727    ts->ypos =
728    ts->xmin =
729    ts->xmax =
730    ts->ymax =
731    ts->ymin =
732    ts->realangle =
733    ts->angle =
734    ts->reverse =
735    ts->counter = 0;
736    ts->size=FIXEDPT(1L);
737    fsret = findsize(command,ts,rules,depth);
738    thinking(0, NULL); /* erase thinking message if any */
739    xmin = (double) ts->xmin / FIXEDMUL;
740    xmax = (double) ts->xmax / FIXEDMUL;
741    ymin = (double) ts->ymin / FIXEDMUL;
742    ymax = (double) ts->ymax / FIXEDMUL;
743    if (fsret == NULL)
744       return 0;
745    if (xmax == xmin)
746       horiz = (float)1E37;
747    else
748       horiz = (float)((xdots-10)/(xmax-xmin));
749    if (ymax == ymin)
750       vert = (float)1E37;
751    else
752       vert = (float)((ydots-6) /(ymax-ymin));
753    locsize = (vert<horiz) ? vert : horiz;
754 
755    if (horiz == 1E37)
756       ts->xpos = FIXEDPT(xdots/2);
757    else
758 /*    ts->xpos = FIXEDPT(-xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2); */
759       ts->xpos = FIXEDPT((xdots-locsize*(xmax+xmin))/2);
760    if (vert == 1E37)
761       ts->ypos = FIXEDPT(ydots/2);
762    else
763 /*    ts->ypos = FIXEDPT(-ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2); */
764       ts->ypos = FIXEDPT((ydots-locsize*(ymax+ymin))/2);
765    ts->size = FIXEDPT(locsize);
766 
767    return 1;
768 }
769 
770 static struct lsys_cmd far *
drawLSysI(struct lsys_cmd far * command,struct lsys_turtlestatei * ts,struct lsys_cmd far ** rules,int depth)771 drawLSysI(struct lsys_cmd far *command,struct lsys_turtlestatei *ts, struct lsys_cmd far **rules,int depth)
772 {
773    struct lsys_cmd far **rulind;
774    int tran;
775 
776    if (overflow)     /* integer math routines overflowed */
777       return NULL;
778 
779    if (stackavail() < 400) { /* leave some margin for calling subrtns */
780       ts->stackoflow = 1;
781       return NULL;
782    }
783 
784 
785    while (command->ch && command->ch !=']') {
786       if (!(ts->counter++)) {
787          if (keypressed()) {
788             ts->counter--;
789             return NULL;
790          }
791       }
792       tran=0;
793       if (depth) {
794          for(rulind=rules;*rulind;rulind++)
795             if ((*rulind)->ch == command->ch) {
796                tran=1;
797                if (drawLSysI((*rulind)+1,ts,rules,depth-1) == NULL)
798                   return NULL;
799             }
800       }
801       if (!depth||!tran) {
802         if (command->f) {
803           ts->num = command->n;
804           (*command->f)(ts);
805           }
806         else if (command->ch == '[') {
807           char saveang,saverev,savecolor;
808           long savesize,savex,savey;
809           unsigned long saverang;
810 
811           saveang=ts->angle;
812           saverev=ts->reverse;
813           savesize=ts->size;
814           saverang=ts->realangle;
815           savex=ts->xpos;
816           savey=ts->ypos;
817           savecolor=ts->curcolor;
818           if ((command=drawLSysI(command+1,ts,rules,depth)) == NULL)
819              return(NULL);
820           ts->angle=saveang;
821           ts->reverse=saverev;
822           ts->size=savesize;
823           ts->realangle=saverang;
824           ts->xpos=savex;
825           ts->ypos=savey;
826           ts->curcolor=savecolor;
827         }
828       }
829       command++;
830    }
831    return command;
832 }
833 
834 static struct lsys_cmd far *
LSysISizeTransform(char far * s,struct lsys_turtlestatei * ts)835 LSysISizeTransform(char far *s, struct lsys_turtlestatei *ts)
836 {
837   struct lsys_cmd far *ret;
838   struct lsys_cmd far *doub;
839   int maxval = 10;
840   int n = 0;
841   void (*f)();
842   long num;
843 
844   void (*plus)() = (ispow2(ts->maxangle)) ? lsysi_doplus_pow2 : lsysi_doplus;
845   void (*minus)() = (ispow2(ts->maxangle)) ? lsysi_dominus_pow2 : lsysi_dominus;
846   void (*pipe)() = (ispow2(ts->maxangle)) ? lsysi_dopipe_pow2 : lsysi_dopipe;
847 
848   void (*slash)() =  (cpu >= 386) ? lsysi_doslash_386 : lsysi_doslash;
849   void (*bslash)() = (cpu >= 386) ? lsysi_dobslash_386 : lsysi_dobslash;
850   void (*at)() =     (cpu >= 386) ? lsysi_doat_386 : lsysi_doat;
851   void (*dogf)() =   (cpu >= 386) ? lsysi_dosizegf_386 : lsysi_dosizegf;
852 
853   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
854   if (ret == NULL) {
855        ts->stackoflow = 1;
856        return NULL;
857        }
858   while (*s) {
859     f = NULL;
860     num = 0;
861     ret[n].ch = *s;
862     switch (*s) {
863       case '+': f = plus;            break;
864       case '-': f = minus;           break;
865       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
866       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
867       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
868       case '|': f = pipe;            break;
869       case '!': f = lsysi_dobang;     break;
870       case 'd':
871       case 'm': f = lsysi_dosizedm;   break;
872       case 'g':
873       case 'f': f = dogf;       break;
874       case '[': num = 1;        break;
875       case ']': num = 2;        break;
876       default:
877         num = 3;
878         break;
879     }
880 #ifdef XFRACT
881     ret[n].f = (void (*)())f;
882 #else
883     ret[n].f = (void (*)(struct lsys_turtlestatei *))f;
884 #endif
885     ret[n].n = num;
886     if (++n == maxval) {
887       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
888       if (doub == NULL) {
889          farmemfree(ret);
890          ts->stackoflow = 1;
891          return NULL;
892          }
893       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
894       farmemfree(ret);
895       ret = doub;
896       maxval <<= 1;
897     }
898     s++;
899   }
900   ret[n].ch = 0;
901   ret[n].f = NULL;
902   ret[n].n = 0;
903   n++;
904 
905   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
906   if (doub == NULL) {
907        farmemfree(ret);
908        ts->stackoflow = 1;
909        return NULL;
910        }
911   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
912   farmemfree(ret);
913   return doub;
914 }
915 
916 static struct lsys_cmd far *
LSysIDrawTransform(char far * s,struct lsys_turtlestatei * ts)917 LSysIDrawTransform(char far *s, struct lsys_turtlestatei *ts)
918 {
919   struct lsys_cmd far *ret;
920   struct lsys_cmd far *doub;
921   int maxval = 10;
922   int n = 0;
923   void (*f)();
924   long num;
925 
926   void (*plus)() = (ispow2(ts->maxangle)) ? lsysi_doplus_pow2 : lsysi_doplus;
927   void (*minus)() = (ispow2(ts->maxangle)) ? lsysi_dominus_pow2 : lsysi_dominus;
928   void (*pipe)() = (ispow2(ts->maxangle)) ? lsysi_dopipe_pow2 : lsysi_dopipe;
929 
930   void (*slash)() =  (cpu >= 386) ? lsysi_doslash_386 : lsysi_doslash;
931   void (*bslash)() = (cpu >= 386) ? lsysi_dobslash_386 : lsysi_dobslash;
932   void (*at)() =     (cpu >= 386) ? lsysi_doat_386 : lsysi_doat;
933   void (*drawg)() =  (cpu >= 386) ? lsysi_dodrawg_386 : lsysi_dodrawg;
934 
935   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
936   if (ret == NULL) {
937        ts->stackoflow = 1;
938        return NULL;
939        }
940   while (*s) {
941     f = NULL;
942     num = 0;
943     ret[n].ch = *s;
944     switch (*s) {
945       case '+': f = plus;            break;
946       case '-': f = minus;           break;
947       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
948       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
949       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
950       case '|': f = pipe;            break;
951       case '!': f = lsysi_dobang;     break;
952       case 'd': f = lsysi_dodrawd;    break;
953       case 'm': f = lsysi_dodrawm;    break;
954       case 'g': f = drawg;           break;
955       case 'f': f = lsysi_dodrawf;    break;
956       case 'c': f = lsysi_dodrawc;    num = (long) getnumber(&s);    break;
957       case '<': f = lsysi_dodrawlt;   num = (long) getnumber(&s);    break;
958       case '>': f = lsysi_dodrawgt;   num = (long) getnumber(&s);    break;
959       case '[': num = 1;        break;
960       case ']': num = 2;        break;
961       default:
962         num = 3;
963         break;
964     }
965 #ifdef XFRACT
966     ret[n].f = (void (*)())f;
967 #else
968     ret[n].f = (void (*)(struct lsys_turtlestatei *))f;
969 #endif
970     ret[n].n = num;
971     if (++n == maxval) {
972       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
973       if (doub == NULL) {
974            farmemfree(ret);
975            ts->stackoflow = 1;
976            return NULL;
977            }
978       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
979       farmemfree(ret);
980       ret = doub;
981       maxval <<= 1;
982     }
983     s++;
984   }
985   ret[n].ch = 0;
986   ret[n].f = NULL;
987   ret[n].n = 0;
988   n++;
989 
990   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
991   if (doub == NULL) {
992        farmemfree(ret);
993        ts->stackoflow = 1;
994        return NULL;
995        }
996   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
997   farmemfree(ret);
998   return doub;
999 }
1000 
lsysi_dosincos(void)1001 static void _fastcall lsysi_dosincos(void)
1002 {
1003    LDBL locaspect;
1004    LDBL TWOPI = 2.0 * PI;
1005    LDBL twopimax;
1006    LDBL twopimaxi;
1007    LDBL s, c;
1008    int i;
1009 
1010    locaspect=screenaspect*xdots/ydots;
1011    twopimax = TWOPI / maxangle;
1012    for(i=0;i<maxangle;i++) {
1013       twopimaxi = i * twopimax;
1014       FPUsincos(&twopimaxi, &s, &c);
1015       sins[i] = (long) (s * FIXEDLT1);
1016       coss[i] = (long) ((locaspect * c) * FIXEDLT1);
1017    }
1018 }
1019