File: common\jiim.c

    1 /*
    2  * JIIM.C
    3  *
    4  * Generates Inverse Julia in real time, lets move a cursor which determines
    5  * the J-set.
    6  *
    7  *  The J-set is generated in a fixed-size window, a third of the screen.
    8  *
    9  * The routines used to set/move the cursor and to save/restore the
   10  * window were "borrowed" from editpal.c (TW - now we *use* the editpal code)
   11  *     (if you don't know how to write good code, look for someone who does)
   12  *
   13  *    JJB  [jbuhler@gidef.edu.ar]
   14  *    TIW  Tim Wegner
   15  *    MS   Michael Snyder
   16  *    KS   Ken Shirriff
   17  * Revision History:
   18  *
   19  *        7-28-92       JJB  Initial release out of editpal.c
   20  *        7-29-92       JJB  Added SaveRect() & RestoreRect() - now the
   21  *                           screen is restored after leaving.
   22  *        7-30-92       JJB  Now, if the cursor goes into the window, the
   23  *                           window is moved to the other side of the screen.
   24  *                           Worked from the first time!
   25  *        10-09-92      TIW  A major rewrite that merged cut routines duplicated
   26  *                           in EDITPAL.C and added orbits feature.
   27  *        11-02-92      KS   Made cursor blink
   28  *        11-18-92      MS   Altered Inverse Julia to use MIIM method.
   29  *        11-25-92      MS   Modified MIIM support routines to better be
   30  *                           shared with stand-alone inverse julia in
   31  *                           LORENZ.C, and to use DISKVID for swap space.
   32  *        05-05-93      TIW  Boy this change file really got out of date.
   33  *                           Added orbits capability, various commands, some
   34  *                           of Dan Farmer's ideas like circles and lines
   35  *                           connecting orbits points.
   36  *        12-18-93      TIW  Removed use of float only for orbits, fixed a
   37  *                           helpmode bug.
   38  *
   39  */
   40 
   41 #include <string.h>
   42 
   43 #ifndef USE_VARARGS
   44 #include <stdarg.h>
45 #else 46 #include <varargs.h>
47 #endif 48 49 #ifdef __TURBOC__
50 # include <mem.h> /* to get mem...() declarations */
51 #endif 52 53 /* see Fractint.c for a description of the "include" hierarchy */ 54 #include "port.h" 55 #include "prototyp.h" 56 #include "helpdefs.h" 57 #include "fractype.h" 58 59 #define FAR_RESERVE 8192L /* amount of far mem we will leave avail. */ 60 #define MAXRECT 1024 /* largest width of SaveRect/RestoreRect */ 61 62 #define newx(size) mem_alloc(size) 63 #define delete(block) block=NULL 64 65 int show_numbers =0; /* toggle for display of coords */ 66 U16 memory_handle = 0; 67 FILE *file; 68 int windows = 0; /* windows management system */ 69 70 int xc, yc; /* corners of the window */ 71 int xd, yd; /* dots in the window */ 72 double xcjul = BIG; 73 double ycjul = BIG; 74 75 void displays(int x, int y, int fg, int bg, char *str, int len) 76 { 77 int i; 78 for(i=0;i<len; i++) 79 displayc(x+i*8, y, fg, bg, str[i]); 80 } 81 82 /* circle routines from Dr. Dobbs June 1990 */ 83 int xbase, ybase; 84 unsigned int xAspect, yAspect; 85 86 void SetAspect(double aspect) 87 { 88 xAspect = 0; 89 yAspect = 0; 90 aspect = fabs(aspect); 91 if (aspect != 1.0) { 92 if (aspect > 1.0) 93 yAspect = (unsigned int)(65536.0 / aspect); 94 else 95 xAspect = (unsigned int)(65536.0 * aspect); 96 } 97 } 98 99 void _fastcall c_putcolor(int x, int y, int color) 100 { 101 /* avoid writing outside window */ 102 if ( x < xc || y < yc || x >= xc + xd || y >= yc + yd ) 103 return ; 104 if(y >= sydots - show_numbers) /* avoid overwriting coords */ 105 return; 106 if(windows == 2) /* avoid overwriting fractal */ 107 if (0 <= x && x < xdots && 0 <= y && y < ydots) 108 return; 109 putcolor(x, y, color); 110 } 111 112 113 int c_getcolor(int x, int y) 114 { 115 /* avoid reading outside window */ 116 if ( x < xc || y < yc || x >= xc + xd || y >= yc + yd ) 117 return 1000; 118 if(y >= sydots - show_numbers) /* avoid overreading coords */ 119 return 1000; 120 if(windows == 2) /* avoid overreading fractal */ 121 if (0 <= x && x < xdots && 0 <= y && y < ydots) 122 return 1000; 123 return getcolor(x, y); 124 } 125 126 void circleplot(int x, int y, int color) 127 { 128 if (xAspect == 0) 129 if (yAspect == 0) 130 c_putcolor(x+xbase, y+ybase,color); 131 else 132 c_putcolor(x+xbase, (short)(ybase + (((long) y * (long) yAspect) >> 16)),color); 133 else 134 c_putcolor((int)(xbase + (((long) x * (long) xAspect) >> 16)), y+ybase, color); 135 } 136 137 void plot8(int x, int y, int color) 138 { 139 circleplot(x,y,color); 140 circleplot(-x,y,color); 141 circleplot(x,-y,color); 142 circleplot(-x,-y,color); 143 circleplot(y,x,color); 144 circleplot(-y,x,color); 145 circleplot(y,-x,color); 146 circleplot(-y,-x,color); 147 } 148 149 void circle(int radius, int color) 150 { 151 int x,y,sum; 152 153 x = 0; 154 y = radius << 1; 155 sum = 0; 156 157 while (x <= y) 158 { 159 if ( !(x & 1) ) /* plot if x is even */ 160 plot8( x >> 1, (y+1) >> 1, color); 161 sum += (x << 1) + 1; 162 x++; 163 if (sum > 0) 164 { 165 sum -= (y << 1) - 1; 166 y--; 167 } 168 } 169 } 170 171 172 /* 173 * MIIM section: 174 * 175 * Global variables and service functions used for computing 176 * MIIM Julias will be grouped here (and shared by code in LORENZ.C) 177 * 178 */ 179 180 181 long ListFront, ListBack, ListSize; /* head, tail, size of MIIM Queue */ 182 long lsize, lmax; /* how many in queue (now, ever) */ 183 int maxhits = 1; 184 int OKtoMIIM; 185 int SecretExperimentalMode; 186 float luckyx = 0, luckyy = 0; 187 188 static void fillrect(int x, int y, int width, int depth, int color) 189 { 190 /* fast version of fillrect */ 191 if(hasinverse == 0) 192 return; 193 memset(dstack, color % colors, width); 194 while (depth-- > 0) 195 { 196 if(keypressed()) /* we could do this less often when in fast modes */ 197 return; 198 putrow(x, y++, width, (char *)dstack); 199 } 200 } 201 202 /* 203 * Queue/Stack Section: 204 * 205 * Defines a buffer that can be used as a FIFO queue or LIFO stack. 206 */ 207 208 int 209 QueueEmpty() /* True if NO points remain in queue */ 210 { 211 return (ListFront == ListBack); 212 } 213 214 #if 0 /* not used */
215 int 216 QueueFull() /* True if room for NO more points in queue */ 217 { 218 return (((ListFront + 1) % ListSize) == ListBack); 219 }
220 #endif 221 222 int 223 QueueFullAlmost() /* True if room for ONE more point in queue */ 224 { 225 return (((ListFront + 2) % ListSize) == ListBack); 226 } 227 228 void 229 ClearQueue() 230 { 231 ListFront = ListBack = lsize = lmax = 0; 232 } 233 234 235 /* 236 * Queue functions for MIIM julia: 237 * move to JIIM.C when done 238 */ 239 240 int Init_Queue(unsigned long request) 241 { 242 if (dotmode == 11) 243 { 244 static FCODE nono[] = "Don't try this in disk video mode, kids...\n"; 245 stopmsg(0, nono); 246 ListSize = 0; 247 return 0; 248 } 249 250 #if 0
251 if (xmmquery() && debugflag != 420) /* use LARGEST extended mem */ 252 if ((largest = xmmlongest()) > request / 128) 253 request = (unsigned long) largest * 128L;
254 #endif 255 256 for (ListSize = request; ListSize > 1024; ListSize /= 2) 257 switch (common_startdisk(ListSize * 8, 1, 256)) 258 { 259 case 0: /* success */ 260 ListFront = ListBack = 0; 261 lsize = lmax = 0; 262 return 1; 263 case -1: 264 continue; /* try smaller queue size */ 265 case -2: 266 ListSize = 0; /* cancelled by user */ 267 return 0; 268 } 269 270 /* failed to get memory for MIIM Queue */ 271 ListSize = 0; 272 return 0; 273 } 274 275 void 276 Free_Queue() 277 { 278 enddisk(); 279 ListFront = ListBack = ListSize = lsize = lmax = 0; 280 } 281 282 int 283 PushLong(long x, long y) 284 { 285 if (((ListFront + 1) % ListSize) != ListBack) 286 { 287 if (ToMemDisk(8*ListFront, sizeof(x), &x) && 288 ToMemDisk(8*ListFront +sizeof(x), sizeof(y), &y)) 289 { 290 ListFront = (ListFront + 1) % ListSize; 291 if (++lsize > lmax) 292 { 293 lmax = lsize; 294 luckyx = (float)x; 295 luckyy = (float)y; 296 } 297 return 1; 298 } 299 } 300 return 0; /* fail */ 301 } 302 303 int 304 PushFloat(float x, float y) 305 { 306 if (((ListFront + 1) % ListSize) != ListBack) 307 { 308 if (ToMemDisk(8*ListFront, sizeof(x), &x) && 309 ToMemDisk(8*ListFront +sizeof(x), sizeof(y), &y)) 310 { 311 ListFront = (ListFront + 1) % ListSize; 312 if (++lsize > lmax) 313 { 314 lmax = lsize; 315 luckyx = x; 316 luckyy = y; 317 } 318 return 1; 319 } 320 } 321 return 0; /* fail */ 322 } 323 324 _CMPLX 325 PopFloat() 326 { 327 _CMPLX pop; 328 float popx, popy; 329 330 if (!QueueEmpty()) 331 { 332 ListFront--; 333 if (ListFront < 0) 334 ListFront = ListSize - 1; 335 if (FromMemDisk(8*ListFront, sizeof(popx), &popx) && 336 FromMemDisk(8*ListFront +sizeof(popx), sizeof(popy), &popy)) 337 { 338 pop.x = popx; 339 pop.y = popy; 340 --lsize; 341 } 342 return pop; 343 } 344 pop.x = 0; 345 pop.y = 0; 346 return pop; 347 } 348 349 LCMPLX 350 PopLong() 351 { 352 LCMPLX pop; 353 354 if (!QueueEmpty()) 355 { 356 ListFront--; 357 if (ListFront < 0) 358 ListFront = ListSize - 1; 359 if (FromMemDisk(8*ListFront, sizeof(pop.x), &pop.x) && 360 FromMemDisk(8*ListFront +sizeof(pop.x), sizeof(pop.y), &pop.y)) 361 --lsize; 362 return pop; 363 } 364 pop.x = 0; 365 pop.y = 0; 366 return pop; 367 } 368 369 int 370 EnQueueFloat(float x, float y) 371 { 372 return PushFloat(x, y); 373 } 374 375 int 376 EnQueueLong(long x, long y) 377 { 378 return PushLong(x, y); 379 } 380 381 _CMPLX 382 DeQueueFloat() 383 { 384 _CMPLX out; 385 float outx, outy; 386 387 if (ListBack != ListFront) 388 { 389 if (FromMemDisk(8*ListBack, sizeof(outx), &outx) && 390 FromMemDisk(8*ListBack +sizeof(outx), sizeof(outy), &outy)) 391 { 392 ListBack = (ListBack + 1) % ListSize; 393 out.x = outx; 394 out.y = outy; 395 lsize--; 396 } 397 return out; 398 } 399 out.x = 0; 400 out.y = 0; 401 return out; 402 } 403 404 LCMPLX 405 DeQueueLong() 406 { 407 LCMPLX out; 408 out.x = 0; 409 out.y = 0; 410 411 if (ListBack != ListFront) 412 { 413 if (FromMemDisk(8*ListBack, sizeof(out.x), &out.x) && 414 FromMemDisk(8*ListBack +sizeof(out.x), sizeof(out.y), &out.y)) 415 { 416 ListBack = (ListBack + 1) % ListSize; 417 lsize--; 418 } 419 return out; 420 } 421 out.x = 0; 422 out.y = 0; 423 return out; 424 } 425 426 427 428 /* 429 * End MIIM section; 430 */ 431 432 static void SaveRect(int x, int y, int width, int depth) 433 { 434 char buff[MAXRECT]; 435 int yoff; 436 if(hasinverse == 0) 437 return; 438 /* first, do any de-allocationg */ 439 440 if (memory_handle != 0) 441 MemoryRelease(memory_handle); 442 443 /* allocate space and store the rect */ 444 445 memset(dstack, color_dark, width); 446 if ((memory_handle = MemoryAlloc( (U16)width, (long)depth, FARMEM)) != 0) 447 { 448 Cursor_Hide(); 449 for (yoff=0; yoff<depth; yoff++) 450 { 451 getrow(x, y+yoff, width, buff); 452 putrow(x, y+yoff, width, (char *)dstack); 453 MoveToMemory((BYTE *)buff, (U16)width, 1L, (long)(yoff), memory_handle); 454 } 455 Cursor_Show(); 456 } 457 } 458 459 460 static void RestoreRect(int x, int y, int width, int depth) 461 { 462 char buff[MAXRECT]; 463 int yoff; 464 if(hasinverse == 0) 465 return; 466 467 Cursor_Hide(); 468 for (yoff=0; yoff<depth; yoff++) 469 { 470 MoveFromMemory((BYTE *)buff, (U16)width, 1L, (long)(yoff), memory_handle); 471 putrow(x, y+yoff, width, buff); 472 } 473 Cursor_Show(); 474 } 475 476 /* 477 * interface to FRACTINT 478 */ 479 480 _CMPLX SaveC = {-3000.0, -3000.0}; 481 482 void Jiim(int which) /* called by fractint */ 483 { 484 struct affine cvt; 485 int exact = 0; 486 int oldhelpmode; 487 int count = 0; /* coloring julia */ 488 static int mode = 0; /* point, circle, ... */ 489 int oldlookatmouse = lookatmouse; 490 double cr, ci, r; 491 int xfactor, yfactor; /* aspect ratio */ 492 493 int xoff, yoff; /* center of the window */ 494 int x, y; 495 int still, kbdchar= -1; 496 497 long iter; 498 int color; 499 float zoom; 500 int oldsxoffs, oldsyoffs; 501 int savehasinverse; 502 int (*oldcalctype)(void); 503 int old_x, old_y; 504 double aspect; 505 static int randir = 0; 506 static int rancnt = 0; 507 int actively_computing = 1; 508 int first_time = 1; 509 int old_debugflag; 510 511 old_debugflag = debugflag; 512 /* must use standard fractal or be calcfroth */ 513 if(fractalspecific[fractype].calctype != StandardFractal 514 && fractalspecific[fractype].calctype != calcfroth) 515 return; 516 oldhelpmode = helpmode; 517 if(which == JIIM) 518 helpmode = HELP_JIIM; 519 else 520 { 521 helpmode = HELP_ORBITS; 522 hasinverse = 1; 523 524 #if 0 /* I don't think this is needed any more */
525 /* Earth to Chuck Ebbert - remove this code when your code supports 526 my changes to PARSER.C */ 527 if(fractype == FFORMULA) 528 { 529 debugflag = 90; 530 }
531 #endif 532 } 533 oldsxoffs = sxoffs; 534 oldsyoffs = syoffs; 535 oldcalctype = calctype; 536 show_numbers = 0; 537 using_jiim = 1; 538 mem_init(strlocn, 10*1024); 539 line_buff = newx(max(sxdots,sydots)); 540 aspect = ((double)xdots*3)/((double)ydots*4); /* assumes 4:3 */ 541 actively_computing = 1; 542 SetAspect(aspect); 543 lookatmouse = 3; 544 545 /* this code moved from just below to avoid boxx/strlocn conflict */ 546 if(which == ORBIT) 547 (*PER_IMAGE)(); 548 else 549 color = color_bright; 550 /* end moved code */ 551 552 Cursor_Construct(); 553 554 /* 555 * MIIM code: 556 * Grab far memory for Queue/Stack before SaveRect gets it. 557 */ 558 OKtoMIIM = 0; 559 if (which == JIIM && debugflag != 300) 560 OKtoMIIM = Init_Queue((long)8*1024); /* Queue Set-up Successful? */ 561 562 maxhits = 1; 563 if (which == ORBIT) 564 plot = c_putcolor; /* for line with clipping */ 565 566 /* 567 * end MIIM code. 568 */ 569 570 if (!video_scroll) { 571 vesa_xres = sxdots; 572 vesa_yres = sydots; 573 } 574 575 if(sxoffs != 0 || syoffs != 0) /* we're in view windows */ 576 { 577 savehasinverse = hasinverse; 578 hasinverse = 1; 579 SaveRect(0,0,xdots,ydots); 580 sxoffs = video_startx; 581 syoffs = video_starty; 582 RestoreRect(0,0,xdots,ydots); 583 hasinverse = savehasinverse; 584 } 585 586 if(xdots == vesa_xres || ydots == vesa_yres || 587 vesa_xres-xdots < vesa_xres/3 || 588 vesa_yres-ydots < vesa_yres/3 || 589 xdots >= MAXRECT ) 590 { 591 /* this mode puts orbit/julia in an overlapping window 1/3 the size of 592 the physical screen */ 593 windows = 0; /* full screen or large view window */ 594 xd = vesa_xres / 3; 595 yd = vesa_yres / 3; 596 xc = video_startx + xd * 2; 597 yc = video_starty + yd * 2; 598 xoff = video_startx + xd * 5 / 2; 599 yoff = video_starty + yd * 5 / 2; 600 } 601 else if(xdots > vesa_xres/3 && ydots > vesa_yres/3) 602 { 603 /* Julia/orbit and fractal don't overlap */ 604 windows = 1; 605 xd = vesa_xres - xdots; 606 yd = vesa_yres - ydots; 607 xc = video_startx + xdots; 608 yc = video_starty + ydots; 609 xoff = xc + xd/2; 610 yoff = yc + yd/2; 611 612 } 613 else 614 { 615 /* Julia/orbit takes whole screen */ 616 windows = 2; 617 xd = vesa_xres; 618 yd = vesa_yres; 619 xc = video_startx; 620 yc = video_starty; 621 xoff = video_startx + xd/2; 622 yoff = video_starty + yd/2; 623 } 624 625 xfactor = (int)(xd/5.33); 626 yfactor = (int)(-yd/4); 627 628 if(windows == 0) 629 SaveRect(xc,yc,xd,yd); 630 else if(windows == 2) /* leave the fractal */ 631 { 632 fillrect(xdots, yc, xd-xdots, yd, color_dark); 633 fillrect(xc , ydots, xdots, yd-ydots, color_dark); 634 } 635 else /* blank whole window */ 636 fillrect(xc, yc, xd, yd, color_dark); 637 638 setup_convert_to_screen(&cvt); 639 640 /* reuse last location if inside window */ 641 col = (int)(cvt.a*SaveC.x + cvt.b*SaveC.y + cvt.e + .5); 642 row = (int)(cvt.c*SaveC.x + cvt.d*SaveC.y + cvt.f + .5); 643 if(col < 0 || col >= xdots || 644 row < 0 || row >= ydots) 645 { 646 cr = (xxmax + xxmin) / 2.0; 647 ci = (yymax + yymin) / 2.0; 648 } 649 else 650 { 651 cr = SaveC.x; 652 ci = SaveC.y; 653 } 654 655 old_x = old_y = -1; 656 657 col = (int)(cvt.a*cr + cvt.b*ci + cvt.e + .5); 658 row = (int)(cvt.c*cr + cvt.d*ci + cvt.f + .5); 659 660 /* possible extraseg arrays have been trashed, so set up again */ 661 if(integerfractal) 662 fill_lx_array(); 663 else 664 fill_dx_array(); 665 666 Cursor_SetPos(col, row); 667 Cursor_Show(); 668 color = color_bright; 669 670 iter = 1; 671 still = 1; 672 zoom = 1; 673 674 #ifdef XFRACT
675 Cursor_StartMouseTracking();
676 #endif 677 678 while (still) 679 { 680 int dcol, drow; 681 if (actively_computing) { 682 Cursor_CheckBlink(); 683 } else { 684 Cursor_WaitKey(); 685 } 686 if(keypressed() || first_time) /* prevent burning up UNIX CPU */ 687 { 688 first_time = 0; 689 while(keypressed()) 690 { 691 Cursor_WaitKey(); 692 kbdchar = getakey(); 693 694 dcol = drow = 0; 695 xcjul = BIG; 696 ycjul = BIG; 697 switch (kbdchar) 698 { 699 case 1143: /* ctrl - keypad 5 */ 700 case 1076: /* keypad 5 */ 701 break; /* do nothing */ 702 case CTL_PAGE_UP: 703 dcol = 4; 704 drow = -4; 705 break; 706 case CTL_PAGE_DOWN: 707 dcol = 4; 708 drow = 4; 709 break; 710 case CTL_HOME: 711 dcol = -4; 712 drow = -4; 713 break; 714 case CTL_END: 715 dcol = -4; 716 drow = 4; 717 break; 718 case PAGE_UP: 719 dcol = 1; 720 drow = -1; 721 break; 722 case PAGE_DOWN: 723 dcol = 1; 724 drow = 1; 725 break; 726 case HOME: 727 dcol = -1; 728 drow = -1; 729 break; 730 case END: 731 dcol = -1; 732 drow = 1; 733 break; 734 case UP_ARROW: 735 drow = -1; 736 break; 737 case DOWN_ARROW: 738 drow = 1; 739 break; 740 case LEFT_ARROW: 741 dcol = -1; 742 break; 743 case RIGHT_ARROW: 744 dcol = 1; 745 break; 746 case UP_ARROW_2: 747 drow = -4; 748 break; 749 case DOWN_ARROW_2: 750 drow = 4; 751 break; 752 case LEFT_ARROW_2: 753 dcol = -4; 754 break; 755 case RIGHT_ARROW_2: 756 dcol = 4; 757 break; 758 case 'z': 759 case 'Z': 760 zoom = (float)1.0; 761 break; 762 case '<': 763 case ',': 764 zoom /= (float)1.15; 765 break; 766 case '>': 767 case '.': 768 zoom *= (float)1.15; 769 break; 770 case SPACE: 771 xcjul = cr; 772 ycjul = ci; 773 goto finish; 774 /* break; */ 775 case 'c': /* circle toggle */ 776 case 'C': /* circle toggle */ 777 mode = mode ^ 1; 778 break; 779 case 'l': 780 case 'L': 781 mode = mode ^ 2; 782 break; 783 case 'n': 784 case 'N': 785 show_numbers = 8 - show_numbers; 786 if(windows == 0 && show_numbers == 0) 787 { 788 Cursor_Hide(); 789 cleartempmsg(); 790 Cursor_Show(); 791 } 792 break; 793 case 'p': 794 case 'P': 795 get_a_number(&cr,&ci); 796 exact = 1; 797 col = (int)(cvt.a*cr + cvt.b*ci + cvt.e + .5); 798 row = (int)(cvt.c*cr + cvt.d*ci + cvt.f + .5); 799 dcol = drow = 0; 800 break; 801 case 'h': /* hide fractal toggle */ 802 case 'H': /* hide fractal toggle */ 803 if(windows == 2) 804 windows = 3; 805 else if(windows == 3 && xd == vesa_xres) 806 { 807 RestoreRect(video_startx, video_starty, xdots, ydots); 808 windows = 2; 809 } 810 break; 811 #ifdef XFRACT
812 case ENTER: 813 break;
814 #endif 815 case '0': 816 case '1': 817 case '2': 818 /* case '3': */ /* don't use '3', it's already meaningful */ 819 case '4': 820 case '5': 821 case '6': 822 case '7': 823 case '8': 824 case '9': 825 if (which == JIIM) 826 { 827 SecretExperimentalMode = kbdchar - '0'; 828 break; 829 } 830 default: 831 still = 0; 832 /* ismand = (short)(1 - ismand); */ 833 } /* switch */ 834 if(kbdchar == 's' || kbdchar == 'S') 835 goto finish; 836 if(dcol > 0 || drow > 0) 837 exact = 0; 838 col += dcol; 839 row += drow; 840 #ifdef XFRACT
841 if (kbdchar == ENTER) { 842 /* We want to use the position of the cursor */ 843 exact=0; 844 col = Cursor_GetX(); 845 row = Cursor_GetY(); 846 }
847 #endif 848 849 /* keep cursor in logical screen */ 850 if(col >= xdots) { 851 col = xdots -1; exact = 0; 852 } 853 if(row >= ydots) { 854 row = ydots -1; exact = 0; 855 } 856 if(col < 0) { 857 col = 0; exact = 0; 858 } 859 if(row < 0) { 860 row = 0; exact = 0; 861 } 862 863 Cursor_SetPos(col,row); 864 } /* end while (keypressed) */ 865 866 if(exact == 0) 867 { 868 if(integerfractal) 869 { 870 cr = lxpixel(); 871 ci = lypixel(); 872 cr /= (1L<<bitshift); 873 ci /= (1L<<bitshift); 874 } 875 else 876 { 877 cr = dxpixel(); 878 ci = dypixel(); 879 } 880 } 881 actively_computing = 1; 882 if(show_numbers) /* write coordinates on screen */ 883 { 884 char str[41]; 885 sprintf(str,"%16.14f %16.14f %3d",cr,ci,getcolor(col,row)); 886 if(windows == 0) 887 { 888 /* show temp msg will clear self if new msg is a 889 different length - pad to length 40*/ 890 while((int)strlen(str) < 40) 891 strcat(str," "); 892 str[40] = 0; 893 Cursor_Hide(); 894 actively_computing = 1; 895 showtempmsg(str); 896 Cursor_Show(); 897 } 898 else 899 displays(5, vesa_yres-show_numbers, WHITE, BLACK, str,strlen(str)); 900 } 901 iter = 1; 902 old.x = old.y = lold.x = lold.y = 0; 903 SaveC.x = init.x = cr; 904 SaveC.y = init.y = ci; 905 linit.x = (long)(init.x*fudge); 906 linit.y = (long)(init.y*fudge); 907 908 old_x = old_y = -1; 909 /* 910 * MIIM code: 911 * compute fixed points and use them as starting points of JIIM 912 */ 913 if (which == JIIM && OKtoMIIM) 914 { 915 _CMPLX f1, f2, Sqrt; /* Fixed points of Julia */ 916 917 Sqrt = ComplexSqrtFloat(1 - 4 * cr, -4 * ci); 918 f1.x = (1 + Sqrt.x) / 2; 919 f2.x = (1 - Sqrt.x) / 2; 920 f1.y = Sqrt.y / 2; 921 f2.y = -Sqrt.y / 2; 922 923 ClearQueue(); 924 maxhits = 1; 925 EnQueueFloat((float)f1.x, (float)f1.y); 926 EnQueueFloat((float)f2.x, (float)f2.y); 927 } 928 /* 929 * End MIIM code. 930 */ 931 if(which == ORBIT) 932 { 933 PER_PIXEL(); 934 } 935 /* move window if bumped */ 936 if(windows==0 && col>xc && col < xc+xd && row>yc && row < yc+yd) 937 { 938 RestoreRect(xc,yc,xd,yd); 939 if (xc == video_startx + xd*2) 940 xc = video_startx + 2; 941 else 942 xc = video_startx + xd*2; 943 xoff = xc + xd / 2; 944 SaveRect(xc,yc,xd,yd); 945 } 946 if(windows == 2) 947 { 948 fillrect(xdots, yc, xd-xdots, yd-show_numbers, color_dark); 949 fillrect(xc , ydots, xdots, yd-ydots-show_numbers, color_dark); 950 } 951 else 952 fillrect(xc, yc, xd, yd, color_dark); 953 954 } /* end if (keypressed) */ 955 956 if(which == JIIM) 957 { 958 if(hasinverse == 0) 959 continue; 960 /* 961 * MIIM code: 962 * If we have MIIM queue allocated, then use MIIM method. 963 */ 964 if (OKtoMIIM) 965 { 966 if (QueueEmpty()) 967 { 968 if (maxhits < colors - 1 && maxhits < 5 && 969 (luckyx != 0.0 || luckyy != 0.0)) 970 { 971 int i; 972 973 lsize = lmax = 0; 974 old.x = new.x = luckyx; 975 old.y = new.y = luckyy; 976 luckyx = luckyy = (float)0.0; 977 for (i=0; i<199; i++) 978 { 979 old = ComplexSqrtFloat(old.x - cr, old.y - ci); 980 new = ComplexSqrtFloat(new.x - cr, new.y - ci); 981 EnQueueFloat( (float)new.x, (float)new.y); 982 EnQueueFloat((float)-old.x, (float)-old.y); 983 } 984 maxhits++; 985 } 986 else 987 continue; /* loop while (still) */ 988 } 989 990 old = DeQueueFloat(); 991 992 #if 0 /* try a different new method */
993 if (lsize < (lmax / 8) && maxhits < 5) /* NEW METHOD */ 994 if (maxhits < colors - 1) 995 maxhits++;
996 #endif 997 x = (int)(old.x * xfactor * zoom + xoff); 998 y = (int)(old.y * yfactor * zoom + yoff); 999 color = c_getcolor(x, y); 1000 if (color < maxhits) 1001 { 1002 c_putcolor(x, y, color + 1); 1003 new = ComplexSqrtFloat(old.x - cr, old.y - ci); 1004 EnQueueFloat( (float)new.x, (float)new.y); 1005 EnQueueFloat((float)-new.x, (float)-new.y); 1006 } 1007 } 1008 else 1009 { 1010 /* 1011 * end Msnyder code, commence if not MIIM code. 1012 */ 1013 old.x -= cr; 1014 old.y -= ci; 1015 r = old.x*old.x + old.y*old.y; 1016 if(r > 10.0) 1017 { 1018 old.x = old.y = 0.0; /* avoids math error */ 1019 iter = 1; 1020 r = 0; 1021 } 1022 iter++; 1023 color = ((count++)>>5)%colors; /* chg color every 32 pts */ 1024 if(color==0) 1025 color = 1; 1026 1027 /* r = sqrt(old.x*old.x + old.y*old.y); calculated above */ 1028 r = sqrt(r); 1029 new.x = sqrt(fabs((r + old.x)/2)); 1030 if (old.y < 0) 1031 new.x = -new.x; 1032 1033 new.y = sqrt(fabs((r - old.x)/2)); 1034 1035 1036 switch (SecretExperimentalMode) { 1037 case 0: /* unmodified random walk */ 1038 default: 1039 if (rand() % 2) 1040 { 1041 new.x = -new.x; 1042 new.y = -new.y; 1043 } 1044 x = (int)(new.x * xfactor * zoom + xoff); 1045 y = (int)(new.y * yfactor * zoom + yoff); 1046 break; 1047 case 1: /* always go one direction */ 1048 if (SaveC.y < 0) 1049 { 1050 new.x = -new.x; 1051 new.y = -new.y; 1052 } 1053 x = (int)(new.x * xfactor * zoom + xoff); 1054 y = (int)(new.y * yfactor * zoom + yoff); 1055 break; 1056 case 2: /* go one dir, draw the other */ 1057 if (SaveC.y < 0) 1058 { 1059 new.x = -new.x; 1060 new.y = -new.y; 1061 } 1062 x = (int)(-new.x * xfactor * zoom + xoff); 1063 y = (int)(-new.y * yfactor * zoom + yoff); 1064 break; 1065 case 4: /* go negative if max color */ 1066 x = (int)(new.x * xfactor * zoom + xoff); 1067 y = (int)(new.y * yfactor * zoom + yoff); 1068 if (c_getcolor(x, y) == colors - 1) 1069 { 1070 new.x = -new.x; 1071 new.y = -new.y; 1072 x = (int)(new.x * xfactor * zoom + xoff); 1073 y = (int)(new.y * yfactor * zoom + yoff); 1074 } 1075 break; 1076 case 5: /* go positive if max color */ 1077 new.x = -new.x; 1078 new.y = -new.y; 1079 x = (int)(new.x * xfactor * zoom + xoff); 1080 y = (int)(new.y * yfactor * zoom + yoff); 1081 if (c_getcolor(x, y) == colors - 1) 1082 { 1083 x = (int)(new.x * xfactor * zoom + xoff); 1084 y = (int)(new.y * yfactor * zoom + yoff); 1085 } 1086 break; 1087 case 7: 1088 if (SaveC.y < 0) 1089 { 1090 new.x = -new.x; 1091 new.y = -new.y; 1092 } 1093 x = (int)(-new.x * xfactor * zoom + xoff); 1094 y = (int)(-new.y * yfactor * zoom + yoff); 1095 if(iter > 10) 1096 { 1097 if(mode == 0) /* pixels */ 1098 c_putcolor(x, y, color); 1099 else if (mode & 1) /* circles */ 1100 { 1101 xbase = x; 1102 ybase = y; 1103 circle((int)(zoom*(xd >> 1)/iter),color); 1104 } 1105 if ((mode & 2) && x > 0 && y > 0 && old_x > 0 && old_y > 0) 1106 { 1107 draw_line(x, y, old_x, old_y, color); 1108 } 1109 old_x = x; 1110 old_y = y; 1111 } 1112 x = (int)(new.x * xfactor * zoom + xoff); 1113 y = (int)(new.y * yfactor * zoom + yoff); 1114 break; 1115 case 8: /* go in long zig zags */ 1116 if (rancnt >= 300) 1117 rancnt = -300; 1118 if (rancnt < 0) 1119 { 1120 new.x = -new.x; 1121 new.y = -new.y; 1122 } 1123 x = (int)(new.x * xfactor * zoom + xoff); 1124 y = (int)(new.y * yfactor * zoom + yoff); 1125 break; 1126 case 9: /* "random run" */ 1127 switch (randir) { 1128 case 0: /* go random direction for a while */ 1129 if (rand() % 2) 1130 { 1131 new.x = -new.x; 1132 new.y = -new.y; 1133 } 1134 if (++rancnt > 1024) 1135 { 1136 rancnt = 0; 1137 if (rand() % 2) 1138 randir = 1; 1139 else 1140 randir = -1; 1141 } 1142 break; 1143 case 1: /* now go negative dir for a while */ 1144 new.x = -new.x; 1145 new.y = -new.y; 1146 /* fall through */ 1147 case -1: /* now go positive dir for a while */ 1148 if (++rancnt > 512) 1149 randir = rancnt = 0; 1150 break; 1151 } 1152 x = (int)(new.x * xfactor * zoom + xoff); 1153 y = (int)(new.y * yfactor * zoom + yoff); 1154 break; 1155 } /* end switch SecretMode (sorry about the indentation) */ 1156 } /* end if not MIIM */ 1157 } 1158 else /* orbits */ 1159 { 1160 if(iter < maxit) 1161 { 1162 color = (int)iter%colors; 1163 if(integerfractal) 1164 { 1165 old.x = lold.x; old.x /= fudge; 1166 old.y = lold.y; old.y /= fudge; 1167 } 1168 x = (int)((old.x - init.x) * xfactor * 3 * zoom + xoff); 1169 y = (int)((old.y - init.y) * yfactor * 3 * zoom + yoff); 1170 if((*ORBITCALC)()) 1171 iter = maxit; 1172 else 1173 iter++; 1174 } 1175 else 1176 { 1177 x = y = -1; 1178 actively_computing = 0; 1179 } 1180 } 1181 if(which == ORBIT || iter > 10) 1182 { 1183 if(mode == 0) /* pixels */ 1184 c_putcolor(x, y, color); 1185 else if (mode & 1) /* circles */ 1186 { 1187 xbase = x; 1188 ybase = y; 1189 circle((int)(zoom*(xd >> 1)/iter),color); 1190 } 1191 if ((mode & 2) && x > 0 && y > 0 && old_x > 0 && old_y > 0) 1192 { 1193 draw_line(x, y, old_x, old_y, color); 1194 } 1195 old_x = x; 1196 old_y = y; 1197 } 1198 old = new; 1199 lold = lnew; 1200 } /* end while(still) */ 1201 finish: 1202 1203 /* 1204 * Msnyder code: 1205 * free MIIM queue 1206 */ 1207 1208 Free_Queue(); 1209 /* 1210 * end Msnyder code. 1211 */ 1212 1213 if(kbdchar != 's'&& kbdchar != 'S') 1214 { 1215 Cursor_Hide(); 1216 if(windows == 0) 1217 RestoreRect(xc,yc,xd,yd); 1218 else if(windows >= 2 ) 1219 { 1220 if(windows == 2) 1221 { 1222 fillrect(xdots, yc, xd-xdots, yd, color_dark); 1223 fillrect(xc , ydots, xdots, yd-ydots, color_dark); 1224 } 1225 else 1226 fillrect(xc, yc, xd, yd, color_dark); 1227 if(windows == 3 && xd == vesa_xres) /* unhide */ 1228 { 1229 RestoreRect(0, 0, xdots, ydots); 1230 windows = 2; 1231 } 1232 Cursor_Hide(); 1233 savehasinverse = hasinverse; 1234 hasinverse = 1; 1235 SaveRect(0,0,xdots,ydots); 1236 sxoffs = oldsxoffs; 1237 syoffs = oldsyoffs; 1238 RestoreRect(0,0,xdots,ydots); 1239 hasinverse = savehasinverse; 1240 } 1241 } 1242 Cursor_Destroy(); 1243 #ifdef XFRACT
1244 Cursor_EndMouseTracking();
1245 #endif 1246 delete(line_buff); 1247 1248 if (memory_handle != 0) { 1249 MemoryRelease(memory_handle); 1250 memory_handle = 0; 1251 } 1252 #if 0
1253 if (memory) /* done with memory, free it */ 1254 { 1255 farmemfree(memory); 1256 memory = NULL; 1257 }
1258 #endif 1259 1260 lookatmouse = oldlookatmouse; 1261 using_jiim = 0; 1262 calctype = oldcalctype; 1263 debugflag = old_debugflag; /* yo Chuck! */ 1264 helpmode = oldhelpmode; 1265 if(kbdchar == 's' || kbdchar == 'S') 1266 { 1267 viewwindow = viewxdots = viewydots = 0; 1268 viewreduction = (float)4.2; 1269 viewcrop = 1; 1270 finalaspectratio = screenaspect; 1271 xdots = sxdots; 1272 ydots = sydots; 1273 dxsize = xdots - 1; 1274 dysize = ydots - 1; 1275 sxoffs = 0; 1276 syoffs = 0; 1277 freetempmsg(); 1278 } 1279 else 1280 cleartempmsg(); 1281 if (file != NULL) 1282 { 1283 fclose(file); 1284 file = NULL; 1285 dir_remove(tempdir,scrnfile); 1286 } 1287 show_numbers = 0; 1288 ungetakey(kbdchar); 1289 1290 if (curfractalspecific->calctype == calcfroth) 1291 froth_cleanup(); 1292 } 1293