File: common\lsys.c

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