home *** CD-ROM | disk | FTP | other *** search
/ Fractal Creations (Second Edition) / FRACTALS_2E.iso / frasrc.exe / JIIM.C < prev    next >
C/C++ Source or Header  |  1993-08-21  |  37KB  |  1,551 lines

  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.  * This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
  10.  *
  11.  *
  12.  * The routines used to set/move the cursor and to save/restore the
  13.  * window were "borrowed" from editpal.c (TW - now we *use* the editpal code)
  14.  *     (if you don't know how to write good code, look for someone who does)
  15.  *
  16.  *    JJB  [jbuhler@gidef.edu.ar]
  17.  *    TIW  Tim Wegner
  18.  *    MS   Michael Snyder
  19.  *    KS   Ken Shirriff
  20.  * Revision History:
  21.  *
  22.  *        7-28-92       JJB  Initial release out of editpal.c
  23.  *        7-29-92       JJB  Added SaveRect() & RestoreRect() - now the
  24.  *                           screen is restored after leaving.
  25.  *        7-30-92       JJB  Now, if the cursor goes into the window, the
  26.  *                           window is moved to the other side of the screen.
  27.  *                           Worked from the first time!
  28.  *        10-09-92      TIW  A major rewrite that merged cut routines duplicated
  29.  *                           in EDITPAL.C and added orbits feature.
  30.  *        11-02-92      KS   Made cursor blink
  31.  *        11-18-92      MS   Altered Inverse Julia to use MIIM method.
  32.  *      11-25-92    MS   Modified MIIM support routines to better be
  33.  *                 shared with stand-alone inverse julia in
  34.  *                 LORENZ.C, and to use DISKVID for swap space.
  35.  *        05-05-93      TIW  Boy this change file really got out of date.
  36.  *                 Added orbits capability, various commands, some 
  37.  *                  of Dan Farmer's ideas like circles and lines 
  38.  *                 connecting orbits points.
  39.  */
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44.  
  45. #ifndef XFRACT
  46. #include <stdarg.h>
  47. #include <dos.h>     /* for FP_SEG & FP_OFF */
  48. #else
  49. #include <varargs.h>
  50. #endif
  51.  
  52. #include <math.h>
  53.  
  54. #ifdef __TURBOC__
  55. #   include <mem.h>   /* to get mem...() declarations */
  56. #endif
  57.  
  58. #include "helpdefs.h"
  59. #include "fractint.h" /* for overlay stuff */
  60. #include "fractype.h"
  61. #include "prototyp.h"
  62.  
  63. #define FAR_RESERVE     8192L     /* amount of far mem we will leave avail. */
  64. #define MAXRECT         1024      /* largest width of SaveRect/RestoreRect */
  65.  
  66. #define newx(size)     mem_alloc(size)
  67. #define delete(block)
  68.  
  69. enum stored_at_values
  70.    {
  71.    NOWHERE,
  72.    DISK,
  73.    MEMORY
  74.    } ;
  75.  
  76. /* borrowed from LORENZ.C */
  77. struct affine
  78. {
  79.    /* weird order so a,b,e and c,d,f are vectors */
  80.    double a;
  81.    double b;
  82.    double e;
  83.    double c;
  84.    double d;
  85.    double f;
  86. };
  87.  
  88. extern int  setup_convert_to_screen(struct affine *);
  89.  
  90. int show_numbers =0;              /* toggle for display of coords */
  91. int stored_at;
  92. char far *memory = NULL;            /* pointer to saved rectangle */
  93. FILE *file;
  94. int windows = 0;               /* windows management system */
  95.  
  96. extern char scrnfile[];   /* file where screen portion is */
  97.                   /* stored */
  98. extern BYTE      *line_buff;   /* must be alloced!!! */
  99. extern int           sxdots;             /* width of physical screen         */
  100. extern int           sydots;             /* depth of physical screen         */
  101. extern int           sxoffs;             /* start of logical screen          */
  102. extern int           syoffs;             /* start of logical screen          */
  103. extern int           strlocn[];          /* 10K buffer to store classes in   */
  104. extern int           colors;             /* # colors avail.                  */
  105. extern int       using_jiim;
  106. extern int       viewwindow;     /* 0 for full screen, 1 for window */
  107. extern float     viewreduction;  /* window auto-sizing */
  108. extern int       viewcrop;               /* nonzero to crop default coords */
  109. extern float     finalaspectratio;              /* for view shape and rotation */
  110. extern int       viewxdots,viewydots;   /* explicit view sizing */
  111. extern double    dxsize, dysize;
  112. extern int       xdots;                  /* width of logical screen          */
  113. extern int       ydots;                  /* depth of logical screen          */
  114. extern double    xxmax,xxmin;    /* limits of the "window"       */
  115. extern double    yymax,yymin;    /* on the z-plane               */
  116. extern int           color_bright;       /* brightest color in palette       */
  117. extern int           color_dark;         /* darkest color in palette         */
  118. extern int           color_medium;       /* nearest to medbright gray color  */
  119. extern int           lookatmouse;        /* mouse mode for getakey(), etc    */
  120. extern int           maxit;                  /* try this many iterations */
  121. extern int           fractype;       /* fractal type */
  122. extern _CMPLX     old,new,init;
  123. extern double tempsqrx,tempsqry;
  124. static int xc, yc;                       /* corners of the window */
  125. static int xd, yd;                       /* dots in the window    */
  126. extern void displayc(int x, int y, int fg, int bg, int ch);
  127. extern float screenaspect;
  128. double xcjul = BIG;
  129. double ycjul = BIG;
  130. extern int hasinverse;
  131.  
  132. void displays(int x, int y, int fg, int bg, char *str, int len)
  133. {
  134.    int i;
  135.    for(i=0;i<len; i++)
  136.       displayc(x+i*8, y, fg, bg, str[i]);
  137. }
  138.  
  139. /* circle routines from Dr. Dobbs June 1990 */
  140. int xbase, ybase;
  141. unsigned xAspect, yAspect;
  142.  
  143. void SetAspect(double aspect)
  144. {
  145.    xAspect = 0;
  146.    yAspect = 0;
  147.    aspect = fabs(aspect);
  148.    if (aspect != 1.0)
  149.       if (aspect > 1.0)
  150.      yAspect = 65536.0 / aspect;
  151.       else
  152.      xAspect = 65536.0 * aspect;
  153. }
  154.  
  155. void _fastcall c_putcolor(int x, int y, int color)
  156.    {
  157.    /* avoid writing outside window */
  158.    if ( x < xc || y < yc || x >= xc + xd || y >= yc + yd )
  159.       return ;
  160.    if(y >= sydots - show_numbers) /* avoid overwriting coords */
  161.       return;
  162.    if(windows == 2) /* avoid overwriting fractal */
  163.       if (0 <= x && x < xdots && 0 <= y && y < ydots)
  164.      return;
  165.    putcolor(x, y, color);
  166.    }
  167.  
  168.  
  169. int  c_getcolor(int x, int y)
  170.    {
  171.    /* avoid reading outside window */
  172.    if ( x < xc || y < yc || x >= xc + xd || y >= yc + yd )
  173.       return 1000;
  174.    if(y >= sydots - show_numbers) /* avoid overreading coords */
  175.       return 1000;
  176.    if(windows == 2) /* avoid overreading fractal */
  177.       if (0 <= x && x < xdots && 0 <= y && y < ydots)
  178.      return 1000;
  179.    return getcolor(x, y);
  180.    }
  181.  
  182. void circleplot(int x, int y, int color)
  183. {
  184.    if (xAspect == 0)
  185.       if (yAspect == 0)
  186.      c_putcolor(x+xbase, y+ybase,color);
  187.       else
  188.      c_putcolor(x+xbase, (short)(ybase + (((long) y * (long) yAspect) >> 16)),color);
  189.    else
  190.       c_putcolor((int)(xbase + (((long) x * (long) xAspect) >> 16)), y+ybase, color);
  191. }
  192.  
  193. void plot8(int x, int y, int color)
  194. {
  195.    circleplot(x,y,color);
  196.    circleplot(-x,y,color);
  197.    circleplot(x,-y,color);
  198.    circleplot(-x,-y,color);
  199.    circleplot(y,x,color);
  200.    circleplot(-y,x,color);
  201.    circleplot(y,-x,color);
  202.    circleplot(-y,-x,color);
  203. }
  204.  
  205. void circle(int radius, int color)
  206. {
  207.    int x,y,sum;
  208.  
  209.    x = 0;
  210.    y = radius << 1;
  211.    sum = 0;
  212.  
  213.    while (x <= y)
  214.    {
  215.       if ( !(x & 1) )   /* plot if x is even */
  216.      plot8( x >> 1, (y+1) >> 1, color);
  217.       sum += (x << 1) + 1;
  218.       x++;
  219.       if (sum > 0)
  220.       {
  221.      sum -= (y << 1) - 1;
  222.      y--;
  223.       }
  224.    }
  225. }
  226.  
  227.  
  228. /*
  229.  * MIIM section:
  230.  *
  231.  * Global variables and service functions used for computing
  232.  * MIIM Julias will be grouped here (and shared by code in LORENZ.C)
  233.  *
  234.  */
  235.  
  236.  
  237.  long   ListFront, ListBack, ListSize;  /* head, tail, size of MIIM Queue */
  238.  long   lsize, lmax;            /* how many in queue (now, ever) */
  239.  int    maxhits = 1;
  240.  int    OKtoMIIM;
  241.  int    SecretExperimentalMode;
  242.  float  luckyx = 0, luckyy = 0;
  243.  extern int debugflag;
  244.  extern int           bitshift;         /* bit shift for fudge */
  245.  extern long          fudge;            /* fudge factor (2**n) */
  246.  
  247.  
  248. long lsqrt(long f)
  249. {
  250.     int N;
  251.     unsigned long y0, z;
  252.     static long a=0, b=0, c=0;                  /* constant factors */
  253.  
  254.     if (f == 0)
  255.     return f;
  256.     if (f <  0)
  257.     return 0;
  258.  
  259.     if (a==0)                                   /* one-time compute consts */
  260.     {
  261.     a = fudge * .41731;
  262.     b = fudge * .59016;
  263.     c = fudge * .7071067811;
  264.     }
  265.  
  266.     N  = 0;
  267.     while (f & 0xff000000L)                     /* shift arg f into the */
  268.     {                                           /* range: 0.5 <= f < 1  */
  269.     N++;
  270.     f /= 2;
  271.     }
  272.     while (!(f & 0xff800000L))
  273.     {
  274.     N--;
  275.     f *= 2;
  276.     }
  277.  
  278.     y0 = a + multiply(b, f,  bitshift);         /* Newton's approximation */
  279.  
  280.     z  = y0 + divide (f, y0, bitshift);
  281.     y0 = (z>>2) + divide(f, z,  bitshift);
  282.  
  283.     if (N % 2)
  284.     {
  285.     N++;
  286.     y0 = multiply(c,y0, bitshift);
  287.     }
  288.     N /= 2;
  289.     if (N >= 0)
  290.     return y0 <<  N;                        /* correct for shift above */
  291.     else
  292.     return y0 >> -N;
  293. }
  294.  
  295. #define SinCosFudge 0x10000L
  296.  
  297.  
  298. LCMPLX
  299. ComplexSqrtLong(long x, long y)
  300. {
  301.    double    mag, theta;
  302.    long      maglong, thetalong;
  303.    LCMPLX    result;
  304.  
  305. #if 1
  306.    mag       = sqrt(sqrt(((double) multiply(x,x,bitshift))/fudge +
  307.              ((double) multiply(y,y,bitshift))/ fudge));
  308.    maglong   = mag * fudge;
  309. #else
  310.    maglong   = lsqrt(lsqrt(multiply(x,x,bitshift)+multiply(y,y,bitshift)));
  311. #endif
  312.    theta     = atan2((double) y/fudge, (double) x/fudge)/2;
  313.    thetalong = theta * SinCosFudge;
  314.    SinCos086(thetalong, &result.y, &result.x);
  315.    result.x  = multiply(result.x << (bitshift - 16), maglong, bitshift);
  316.    result.y  = multiply(result.y << (bitshift - 16), maglong, bitshift);
  317.    return result;
  318. }
  319.  
  320. _CMPLX
  321. ComplexSqrtFloat(double x, double y)
  322. {
  323.    double mag   = sqrt(sqrt(x*x + y*y));
  324.    double theta = atan2(y, x) / 2;
  325.    _CMPLX  result;
  326.  
  327.    FPUsincos(&theta, &result.y, &result.x);
  328.    result.x *= mag;
  329.    result.y *= mag;
  330.    return result;
  331. }
  332.  
  333.  
  334. extern char dstack[];
  335.  
  336. static void fillrect(int x, int y, int width, int depth, int color)
  337. {
  338.    /* fast version of fillrect */
  339.    if(hasinverse == 0)
  340.       return;
  341.    memset(dstack, color % colors, width);
  342.    while (depth-- > 0)
  343.    {
  344.       if(keypressed()) /* we could do this less often when in fast modes */
  345.          return;
  346.       putrow(x, y++, width, dstack);
  347.    }
  348. }
  349.  
  350. /*
  351.  * Queue/Stack Section:
  352.  *
  353.  * Defines a buffer that can be used as a FIFO queue or LIFO stack.
  354.  */
  355.  
  356. int
  357. QueueEmpty()        /* True if NO points remain in queue */
  358. {
  359.    return (ListFront == ListBack);
  360. }
  361.  
  362. int
  363. QueueFull()        /* True if room for NO more points in queue */
  364. {
  365.    return (((ListFront + 1) % ListSize) == ListBack);
  366. }
  367.  
  368. int
  369. QueueFullAlmost()    /* True if room for ONE more point in queue */
  370. {
  371.    return (((ListFront + 2) % ListSize) == ListBack);
  372. }
  373.  
  374. void
  375. ClearQueue()
  376. {
  377.    ListFront = ListBack = lsize = lmax = 0;
  378. }
  379.  
  380.  
  381. /*
  382.  * Queue functions for MIIM julia:
  383.  * move to JIIM.C when done
  384.  */
  385.  
  386. extern long  ListSize, ListFront, ListBack, lsize, lmax;
  387. extern float luckyx, luckyy;
  388.  
  389. int Init_Queue(unsigned long request)
  390. {
  391.    extern int _fastcall common_startdisk(long, long, int);
  392.    extern unsigned int xmmlongest();
  393.    extern unsigned int xmmreallocate(unsigned int, unsigned int);
  394.    extern int dotmode;
  395.    unsigned int        largest;
  396.  
  397.  
  398.    if (dotmode == 11)
  399.    {
  400.       static char far *nono = "Don't try this in disk video mode, kids...\n";
  401.       stopmsg(0, nono);
  402.       ListSize = 0;
  403.       return 0;
  404.    }
  405.  
  406. #if 0
  407.    if (xmmquery() && debugflag != 420)    /* use LARGEST extended mem */
  408.       if ((largest = xmmlongest()) > request / 128)
  409.      request   = (unsigned long) largest * 128L;
  410. #endif
  411.  
  412.    for (ListSize = request; ListSize > 1024; ListSize -= 512)
  413.       switch (common_startdisk(ListSize * 8, 1, 256))
  414.       {
  415.      case 0:                        /* success */
  416.         ListFront = ListBack = 0;
  417.         lsize = lmax = 0;
  418.         return 1;
  419.      case -1:
  420.         continue;            /* try smaller queue size */
  421.      case -2:
  422.         ListSize = 0;               /* cancelled by user      */
  423.         return 0;
  424.       }
  425.  
  426.    /* failed to get memory for MIIM Queue */
  427.    ListSize = 0;
  428.    return 0;
  429. }
  430.  
  431. void
  432. Free_Queue()
  433. {
  434.    enddisk();
  435.    ListFront = ListBack = ListSize = lsize = lmax = 0;
  436. }
  437.  
  438. extern int ToMemDisk  (long, int, void far *);
  439. extern int FromMemDisk(long, int, void far *);
  440.  
  441. int
  442. PushLong(long x, long y)
  443. {
  444.    if (((ListFront + 1) % ListSize) != ListBack)
  445.    {
  446.       if (ToMemDisk(8*ListFront, sizeof(x), &x) &&
  447.       ToMemDisk(8*ListFront +sizeof(x), sizeof(y), &y))
  448.       {
  449.      ListFront = (ListFront + 1) % ListSize;
  450.      if (++lsize > lmax)
  451.      {
  452.         lmax   = lsize;
  453.         luckyx = x;
  454.         luckyy = y;
  455.      }
  456.      return 1;
  457.       }
  458.    }
  459.    return 0;            /* fail */
  460. }
  461.  
  462. int
  463. PushFloat(float x, float y)
  464. {
  465.    if (((ListFront + 1) % ListSize) != ListBack)
  466.    {
  467.       if (ToMemDisk(8*ListFront, sizeof(x), &x) &&
  468.       ToMemDisk(8*ListFront +sizeof(x), sizeof(y), &y))
  469.       {
  470.      ListFront = (ListFront + 1) % ListSize;
  471.      if (++lsize > lmax)
  472.      {
  473.         lmax   = lsize;
  474.         luckyx = x;
  475.         luckyy = y;
  476.      }
  477.      return 1;
  478.       }
  479.    }
  480.    return 0;            /* fail */
  481. }
  482.  
  483. _CMPLX
  484. PopFloat()
  485. {
  486.    _CMPLX pop;
  487.    float  popx, popy;
  488.  
  489.    if (!QueueEmpty())
  490.    {
  491.       ListFront--;
  492.       if (ListFront < 0)
  493.       ListFront = ListSize - 1;
  494.       if (FromMemDisk(8*ListFront, sizeof(popx), &popx) &&
  495.       FromMemDisk(8*ListFront +sizeof(popx), sizeof(popy), &popy))
  496.       {
  497.      pop.x = popx;
  498.      pop.y = popy;
  499.      --lsize;
  500.       }
  501.       return pop;
  502.    }
  503.    pop.x = 0;
  504.    pop.y = 0;
  505.    return pop;
  506. }
  507.  
  508. LCMPLX
  509. PopLong()
  510. {
  511.    LCMPLX pop;
  512.  
  513.    if (!QueueEmpty())
  514.    {
  515.       ListFront--;
  516.       if (ListFront < 0)
  517.       ListFront = ListSize - 1;
  518.       if (FromMemDisk(8*ListFront, sizeof(pop.x), &pop.x) &&
  519.       FromMemDisk(8*ListFront +sizeof(pop.x), sizeof(pop.y), &pop.y))
  520.      --lsize;
  521.       return pop;
  522.    }
  523.    pop.x = 0;
  524.    pop.y = 0;
  525.    return pop;
  526. }
  527.  
  528. int
  529. EnQueueFloat(float x, float y)
  530. {
  531.    return PushFloat(x, y);
  532. }
  533.  
  534. int
  535. EnQueueLong(long x, long y)
  536. {
  537.    return PushLong(x, y);
  538. }
  539.  
  540. _CMPLX
  541. DeQueueFloat()
  542. {
  543.    _CMPLX out;
  544.    float outx, outy;
  545.  
  546.    if (ListBack != ListFront)
  547.    {
  548.       if (FromMemDisk(8*ListBack, sizeof(outx), &outx) &&
  549.       FromMemDisk(8*ListBack +sizeof(outx), sizeof(outy), &outy))
  550.       {
  551.      ListBack = (ListBack + 1) % ListSize;
  552.      out.x = outx;
  553.      out.y = outy;
  554.      lsize--;
  555.       }
  556.       return out;
  557.    }
  558.    out.x = 0;
  559.    out.y = 0;
  560.    return out;
  561. }
  562.  
  563. LCMPLX
  564. DeQueueLong()
  565. {
  566.    LCMPLX out;
  567.    out.x = 0;
  568.    out.y = 0;
  569.  
  570.    if (ListBack != ListFront)
  571.    {
  572.       if (FromMemDisk(8*ListBack, sizeof(out.x), &out.x) &&
  573.       FromMemDisk(8*ListBack +sizeof(out.x), sizeof(out.y), &out.y))
  574.       {
  575.      ListBack = (ListBack + 1) % ListSize;
  576.      lsize--;
  577.       }
  578.       return out;
  579.    }
  580.    out.x = 0;
  581.    out.y = 0;
  582.    return out;
  583. }
  584.  
  585.  
  586.  
  587. /*
  588.  * End MIIM section;
  589.  */
  590.  
  591.  
  592.  
  593. static BOOLEAN MemoryAlloc(long size)
  594. {
  595.    char far *temp;
  596.    
  597.    if (debugflag == 420)
  598.       return(FALSE);
  599.    temp = (char far *)farmemalloc(FAR_RESERVE);   /* minimum free space */
  600.  
  601.    if (temp == NULL)
  602.    {
  603.       stored_at = NOWHERE;
  604.       return (FALSE);   /* can't do it */
  605.    }
  606.  
  607.    memory = (char far *)farmemalloc( size );
  608.    farmemfree(temp);
  609.  
  610.    if ( memory == NULL )
  611.    {
  612.       stored_at = NOWHERE;
  613.       return (FALSE);
  614.    }
  615.    else
  616.    {
  617.       stored_at = MEMORY;
  618.       return (TRUE);
  619.    }
  620. }
  621.  
  622.  
  623. static void SaveRect(int x, int y, int width, int depth)
  624. {
  625.    char buff[MAXRECT];
  626.    int  yoff;
  627.    if(hasinverse == 0)
  628.       return;
  629.    /* first, do any de-allocationg */
  630.  
  631.    switch( stored_at )
  632.    {
  633.    case NOWHERE:
  634.       break;
  635.  
  636.    case DISK:
  637.       break;
  638.  
  639.    case MEMORY:
  640.       if (memory != NULL)
  641.       {
  642.      farmemfree(memory);
  643.       }
  644.       memory = NULL;
  645.       break;
  646.    }
  647.  
  648.    /* allocate space and store the rect */
  649.  
  650.    memset(dstack, color_dark, width);
  651.    if ( MemoryAlloc( (long)width*(long)depth) )
  652.    {
  653.       char far  *ptr = memory;
  654.       char far  *bufptr = buff; /* MSC needs this indirection to get it right */
  655.  
  656.       Cursor_Hide();
  657.       for (yoff=0; yoff<depth; yoff++)
  658.       {
  659.      getrow(x, y+yoff, width, buff);
  660.      putrow(x, y+yoff, width, dstack);
  661.      movedata(FP_SEG(bufptr), FP_OFF(bufptr), FP_SEG(ptr), FP_OFF(ptr), width);
  662.      ptr = (char far *)normalize(ptr+width);
  663.       }
  664.       Cursor_Show();
  665.    }
  666.  
  667.    else /* to disk */
  668.    {
  669.       stored_at = DISK;
  670.  
  671.       if ( file == NULL )
  672.       {
  673.      file = fopen(scrnfile, "w+b");
  674.      if (file == NULL)
  675.      {
  676.         stored_at = NOWHERE;
  677.         buzzer(3);
  678.         return ;
  679.      }
  680.       }
  681.  
  682.       rewind(file);
  683.       Cursor_Hide();
  684.       for (yoff=0; yoff<depth; yoff++)
  685.       {
  686.      getrow(x, y+yoff, width, buff);
  687.      putrow(x, y+yoff, width, dstack);
  688.      if ( fwrite(buff, width, 1, file) != 1 )
  689.      {
  690.         buzzer(3);
  691.         break;
  692.      }
  693.       }
  694.       Cursor_Show();
  695.    }
  696. }
  697.  
  698.  
  699. static void RestoreRect(x, y, width, depth)
  700. {
  701.    char buff[MAXRECT];
  702.    int  yoff;
  703.    if(hasinverse == 0)
  704.       return;
  705.  
  706.    switch ( stored_at )
  707.    {
  708.    case DISK:
  709.       rewind(file);
  710.       Cursor_Hide();
  711.       for (yoff=0; yoff<depth; yoff++)
  712.       {
  713.      if ( fread(buff, width, 1, file) != 1 )
  714.      {
  715.         buzzer(3);
  716.         break;
  717.      }
  718.      putrow(x, y+yoff, width, buff);
  719.       }
  720.       Cursor_Show();
  721.       break;
  722.  
  723.    case MEMORY:
  724.       {
  725.      char far  *ptr = memory;
  726.      char far  *bufptr = buff; /* MSC needs this indirection to get it right */
  727.  
  728.      Cursor_Hide();
  729.      for (yoff=0; yoff<depth; yoff++)
  730.      {
  731.         movedata(FP_SEG(ptr), FP_OFF(ptr), FP_SEG(bufptr), FP_OFF(bufptr), width);
  732.         putrow(x, y+yoff, width, buff);
  733.         ptr = (char far *)normalize(ptr+width);
  734.      }
  735.      Cursor_Show();
  736.      break;
  737.       }
  738.  
  739.    case NOWHERE:
  740.       break;
  741.    } /* switch */
  742. }
  743.  
  744. /*
  745.  * interface to FRACTINT
  746.  */
  747. int jfractype;
  748.  
  749. extern int row, col;
  750. extern double far *dx0, far *dy0;
  751. extern double far *dx1, far *dy1;
  752. extern int integerfractal;
  753. extern long far *lx0, far *ly0;
  754. extern long far *lx1, far *ly1;
  755. extern int bitshift;
  756. extern int helpmode;
  757.  
  758. /* the following macros and function call the setup, per_pixel, and orbit
  759.    routines and calculate an orbit at row 0 column 0. Have to save and 
  760.    restore the first elements of dx0 ... dy1 as well as row and col */
  761.  
  762. #define PER_IMAGE fractalspecific[o_fractype].per_image
  763. #define PER_PIXEL fractalspecific[o_fractype].per_pixel
  764. #define ORBITCALC   fractalspecific[o_fractype].orbitcalc
  765.  
  766. int do_fractal_routines(double cr, double ci, int (*func)())
  767. {
  768.    int ret;
  769.    int old_row, old_col;
  770.    double old_dx0, old_dx1, old_dy0, old_dy1;
  771.    old_dx0 = *dx0; old_dx1 = *dx1;
  772.    old_dy0 = *dy0; old_dy1 = *dy1;
  773.    old_row = row;  old_col = col;
  774.    row = col = 0;
  775.    *dx0 = cr; *dy0 = ci; *dx1 = *dy1 = 0.0;
  776.    ret = func();
  777.    *dx0 = old_dx0; *dx1 = old_dx1;
  778.    *dy0 = old_dy0; *dy1 = old_dy1;
  779.    row = old_row;  col = old_col;
  780.    return(ret);
  781. }
  782.  
  783.  
  784. void Jiim(int which)         /* called by fractint */
  785. {
  786.    struct affine cvt;
  787.    int exact = 0;
  788.    int oldhelpmode;
  789.    int count = 0;            /* coloring julia */
  790.    static int mode = 0;      /* point, circle, ... */
  791.    int       oldlookatmouse = lookatmouse;
  792.    double cr, ci, r;
  793.    int xfactor, yfactor;             /* aspect ratio          */
  794.  
  795.    int xoff, yoff;                   /* center of the window  */
  796.    int x, y;
  797.    int still, kbdchar;
  798.    int xcrsr,ycrsr;     /* coords of the cursor / offsets to move it  */
  799.    int iter;
  800.    int color;
  801.    float zoom;
  802.    int oldsxoffs, oldsyoffs;
  803.    int savehasinverse;
  804.    int (*oldcalctype)();
  805.    extern int (*calctype)();
  806.    int o_fractype;
  807.    int old_x, old_y;
  808.    double aspect;
  809.    static int randir = 0;
  810.    static int rancnt = 0;
  811.    static _CMPLX SaveC = {-3000.0, -3000.0};
  812.    int actively_computing = 1;
  813.    int first_time = 1;
  814.  
  815.    ENTER_OVLY(OVLY_ROTATE);
  816.    /* must use standard fractal and have a float variant */
  817.    if(fractalspecific[fractype].calctype != StandardFractal ||
  818.      (fractalspecific[fractype].isinteger &&
  819.      fractalspecific[fractype].tofloat == NOFRACTAL))
  820.    {
  821.        EXIT_OVLY;
  822.        return;
  823.    }
  824.    oldhelpmode = helpmode;
  825.    if(which == JIIM)
  826.       helpmode = HELP_JIIM;
  827.    else
  828.    {
  829.       helpmode = HELP_ORBITS;
  830.       hasinverse = 1;
  831.    }
  832.    if(fractalspecific[fractype].isinteger)
  833.       o_fractype = fractalspecific[fractype].tofloat;
  834.    else
  835.       o_fractype = fractype;
  836.    oldsxoffs = sxoffs;
  837.    oldsyoffs = syoffs;
  838.    oldcalctype = calctype;
  839.    show_numbers = 0;
  840.    using_jiim = 1;
  841.    mem_init(strlocn, 10*1024);
  842.    line_buff = newx(max(sxdots,sydots));
  843.    aspect = ((double)xdots*3)/((double)ydots*4);  /* assumes 4:3 */
  844.      actively_computing = 1;
  845.    SetAspect(aspect);
  846.    lookatmouse = 3;
  847.    Cursor_Construct();
  848.  
  849. /*
  850.  * MIIM code:
  851.  * Grab far memory for Queue/Stack before SaveRect gets it.
  852.  */
  853.    OKtoMIIM  = 0;
  854.    if (which == JIIM && debugflag != 300)
  855.       OKtoMIIM = Init_Queue((long)8*1024); /* Queue Set-up Successful? */
  856.  
  857.    maxhits = 1;
  858.    if (which == ORBIT)
  859.       plot = c_putcolor;             /* for line with clipping */
  860.  
  861. /*
  862.  * end MIIM code.
  863.  */
  864.  
  865.  
  866.    if(sxoffs != 0 || syoffs != 0) /* we're in view windows */
  867.    {
  868.       savehasinverse = hasinverse;
  869.       hasinverse = 1;
  870.       SaveRect(0,0,xdots,ydots);
  871.       sxoffs = 0;
  872.       syoffs = 0;
  873.       RestoreRect(0,0,xdots,ydots);
  874.       hasinverse = savehasinverse;
  875.    }
  876.  
  877.    if(which == ORBIT)
  878.       do_fractal_routines(cr, ci,PER_IMAGE);
  879.    else
  880.       color = color_bright;
  881.  
  882.    oldhelpmode = helpmode;
  883.    if(which == JIIM)
  884.       helpmode = HELP_JIIM;
  885.    else
  886.       helpmode = HELP_ORBITS;
  887.  
  888.    if(xdots == sxdots || ydots == sydots ||
  889.        sxdots-xdots < sxdots/3 ||
  890.        sydots-ydots < sydots/3 ||
  891.        xdots >= MAXRECT )
  892.    {
  893.       /* this mode puts orbit/julia in an overlapping window 1/3 the size of
  894.      the physical screen */
  895.       windows = 0; /* full screen or large view window */
  896.       xd = sxdots / 3;
  897.       yd = sydots / 3;
  898.       xc = xd * 2;
  899.       yc = yd * 2;
  900.       xoff = xd * 5 / 2;
  901.       yoff = yd * 5 / 2;
  902.    }
  903.    else if(xdots > sxdots/3 && ydots > sydots/3)
  904.    {
  905.       /* Julia/orbit and fractal don't overlap */
  906.       windows = 1;
  907.       xd = sxdots-xdots;
  908.       yd = sydots-ydots;
  909.       xc = xdots;
  910.       yc = ydots;
  911.       xoff = xc + xd/2;
  912.       yoff = yc + yd/2;
  913.  
  914.    }
  915.    else
  916.    {
  917.       /* Julia/orbit takes whole screen */
  918.       windows = 2;
  919.       xd = sxdots;
  920.       yd = sydots;
  921.       xc = 0;
  922.       yc = 0;
  923.       xoff = xd/2;
  924.       yoff = yd/2;
  925.    }
  926.  
  927.    xfactor = xd/5.33;
  928.    yfactor = -yd/4;
  929.  
  930.    if(windows == 0)
  931.       SaveRect(xc,yc,xd,yd);
  932.    else if(windows == 2)  /* leave the fractal */
  933.    {
  934.       fillrect(xdots, yc, xd-xdots, yd, color_dark);
  935.       fillrect(xc   , ydots, xdots, yd-ydots, color_dark);
  936.    }
  937.    else  /* blank whole window */
  938.       fillrect(xc, yc, xd, yd, color_dark);
  939.  
  940.    setup_convert_to_screen(&cvt);
  941.  
  942.    /* reuse last location if inside window */
  943.    xcrsr = cvt.a*SaveC.x + cvt.b*SaveC.y + cvt.e + .5;
  944.    ycrsr = cvt.c*SaveC.x + cvt.d*SaveC.y + cvt.f + .5;
  945.    if(xcrsr < 0 || xcrsr >= xdots ||
  946.       ycrsr < 0 || ycrsr >= ydots)
  947.    {
  948.       cr = (xxmax + xxmin) / 2.0;
  949.       ci = (yymax + yymin) / 2.0;
  950.    }
  951.    else
  952.    {
  953.       cr = SaveC.x;
  954.       ci = SaveC.y;
  955.    }
  956.  
  957.    old_x = old_y = -1;
  958.  
  959.    xcrsr = cvt.a*cr + cvt.b*ci + cvt.e + .5;
  960.    ycrsr = cvt.c*cr + cvt.d*ci + cvt.f + .5;
  961.  
  962.    Cursor_SetPos(xcrsr, ycrsr);
  963.    Cursor_Show();
  964.    color = color_bright;
  965.  
  966.    iter = 1;
  967.    still = 1;
  968.    zoom = 1;
  969.  
  970. #ifdef XFRACT
  971.    Cursor_StartMouseTracking();
  972. #endif
  973.  
  974.    while (still)
  975.    {
  976.       int dxcrsr, dycrsr;
  977.       if (actively_computing) {
  978.       Cursor_CheckBlink();
  979.       } else {
  980.       Cursor_WaitKey();
  981.       }
  982.       if(keypressed() || first_time) /* prevent burning up UNIX CPU */
  983.       {
  984.      first_time = 0;
  985.      while(keypressed())
  986.      {
  987.         Cursor_WaitKey();
  988.         kbdchar = getakey();
  989.  
  990.         dxcrsr = dycrsr = 0;
  991.         xcjul = BIG;
  992.         ycjul = BIG;
  993.         switch (kbdchar)
  994.         {
  995.             case 1143:    /* ctrl - keypad 5 */
  996.         case 1076:    /* keypad 5        */
  997.            break;     /* do nothing */
  998.         case CTL_PAGE_UP:
  999.            dxcrsr = 4;
  1000.            dycrsr = -4;
  1001.            break;
  1002.         case CTL_PAGE_DOWN:
  1003.            dxcrsr = 4;
  1004.            dycrsr = 4;
  1005.            break;
  1006.         case CTL_HOME:
  1007.            dxcrsr = -4;
  1008.            dycrsr = -4;
  1009.            break;
  1010.         case CTL_END:
  1011.            dxcrsr = -4;
  1012.            dycrsr = 4;
  1013.            break;
  1014.         case PAGE_UP:
  1015.            dxcrsr = 1;
  1016.            dycrsr = -1;
  1017.            break;
  1018.         case PAGE_DOWN:
  1019.            dxcrsr = 1;
  1020.            dycrsr = 1;
  1021.            break;
  1022.         case HOME:
  1023.            dxcrsr = -1;
  1024.            dycrsr = -1;
  1025.            break;
  1026.         case END:
  1027.            dxcrsr = -1;
  1028.            dycrsr = 1;
  1029.            break;
  1030.         case UP_ARROW:
  1031.            dycrsr = -1;
  1032.            break;
  1033.         case DOWN_ARROW:
  1034.            dycrsr = 1;
  1035.            break;
  1036.         case LEFT_ARROW:
  1037.            dxcrsr = -1;
  1038.            break;
  1039.         case RIGHT_ARROW:
  1040.            dxcrsr = 1;
  1041.            break;
  1042.         case UP_ARROW_2:
  1043.            dycrsr = -4;
  1044.            break;
  1045.         case DOWN_ARROW_2:
  1046.            dycrsr = 4;
  1047.            break;
  1048.         case LEFT_ARROW_2:
  1049.            dxcrsr = -4;
  1050.            break;
  1051.         case RIGHT_ARROW_2:
  1052.            dxcrsr = 4;
  1053.            break;
  1054.         case 'z':
  1055.         case 'Z':
  1056.            zoom = 1.0;
  1057.            break;
  1058.         case '<':
  1059.         case ',':
  1060.            zoom /= 1.15;
  1061.            break;
  1062.         case '>':
  1063.         case '.':
  1064.            zoom *= 1.15;
  1065.            break;
  1066.         case SPACE:
  1067.            xcjul = cr;
  1068.            ycjul = ci;
  1069.            goto finish;
  1070.            break;
  1071.         case 'c':   /* circle toggle */
  1072.         case 'C':   /* circle toggle */
  1073.            mode = mode ^ 1;
  1074.            break;
  1075.         case 'l':
  1076.         case 'L':
  1077.            mode = mode ^ 2;
  1078.            break;
  1079.         case 'n':
  1080.         case 'N':
  1081.            show_numbers = 8 - show_numbers;
  1082.            if(windows == 0 && show_numbers == 0)
  1083.            {
  1084.           Cursor_Hide();
  1085.           cleartempmsg();
  1086.           Cursor_Show();
  1087.            }
  1088.            break;
  1089.         case 'p':
  1090.         case 'P':
  1091.            get_a_number(&cr,&ci);
  1092.                exact = 1;
  1093.                xcrsr = cvt.a*cr + cvt.b*ci + cvt.e + .5;
  1094.                ycrsr = cvt.c*cr + cvt.d*ci + cvt.f + .5;
  1095.                dxcrsr = dycrsr = 0;
  1096.            break;
  1097.         case 'h':   /* hide fractal toggle */
  1098.         case 'H':   /* hide fractal toggle */
  1099.            if(windows == 2)
  1100.           windows = 3;
  1101.            else if(windows == 3 && xd == sxdots)
  1102.            {
  1103.           RestoreRect(0, 0, xdots, ydots);
  1104.           windows = 2;
  1105.            }
  1106.            break;
  1107. #ifdef XFRACT
  1108.         case ENTER:
  1109.         break;
  1110. #endif
  1111.         case '0':
  1112.         case '1':
  1113.         case '2':
  1114. /*        case '3': */  /* don't use '3', it's already meaningful */
  1115.         case '4':
  1116.         case '5':
  1117.         case '6':
  1118.         case '7':
  1119.         case '8':
  1120.         case '9':
  1121.            if (which == JIIM)
  1122.            {
  1123.           SecretExperimentalMode = kbdchar - '0';
  1124.           break;
  1125.            }
  1126.         default:
  1127.            still = 0;
  1128.         }  /* switch */
  1129.         if(kbdchar == 's' || kbdchar == 'S')
  1130.            goto finish;
  1131.             if(dxcrsr > 0 || dycrsr > 0)
  1132.                exact = 0;
  1133.             xcrsr += dxcrsr;
  1134.             ycrsr += dycrsr;
  1135.             
  1136.         /* keep cursor in logical screen */
  1137.        if(xcrsr >= xdots)
  1138.           xcrsr = xdots -1, exact = 0;
  1139.        if(ycrsr >= ydots)
  1140.           ycrsr = ydots -1, exact = 0;
  1141.        if(xcrsr < 0)
  1142.           xcrsr = 0, exact = 0;
  1143.        if(ycrsr < 0)
  1144.           ycrsr = 0, exact = 0;
  1145.         
  1146.             Cursor_SetPos(xcrsr,ycrsr);
  1147.      }  /* end while (keypressed) */
  1148.  
  1149.          if(exact == 0)
  1150.          {
  1151.         if(integerfractal)
  1152.         {
  1153.            cr = lx0[xcrsr]+lx1[ycrsr];  /* supports rotated zoom boxes! */
  1154.            ci = ly0[ycrsr]+ly1[xcrsr];
  1155.            cr /= (1L<<bitshift);
  1156.            ci /= (1L<<bitshift);
  1157.         }
  1158.         else
  1159.         {
  1160.            cr = dx0[xcrsr]+dx1[ycrsr];
  1161.            ci = dy0[ycrsr]+dy1[xcrsr];
  1162.         }
  1163.      }
  1164.      actively_computing = 1;
  1165.      if(show_numbers) /* write coordinates on screen */
  1166.      {
  1167.         char str[80];
  1168.         sprintf(str,"x=%16.14f y=%16.14f   ",cr,ci);
  1169.         str[40] = 0;
  1170.         if(windows == 0)
  1171.         {
  1172.            Cursor_Hide();
  1173.            actively_computing = 1;
  1174.            showtempmsg(str);
  1175.            Cursor_Show();
  1176.         }
  1177.         else
  1178.            displays(5, sydots-show_numbers, WHITE, BLACK, str,strlen(str));
  1179.      }
  1180.      iter = 1;
  1181.      old.x = old.y = 0;
  1182.      SaveC.x = init.x =  cr;
  1183.      SaveC.y = init.y =  ci;
  1184.      old_x = old_y = -1;
  1185. /*
  1186.  * MIIM code:
  1187.  * compute fixed points and use them as starting points of JIIM
  1188.  */
  1189.      if (which == JIIM && OKtoMIIM)
  1190.      {
  1191.         _CMPLX f1, f2, Sqrt;    /* Fixed points of Julia */
  1192.  
  1193.         Sqrt = ComplexSqrtFloat(1 - 4 * cr, -4 * ci);
  1194.         f1.x = (1 + Sqrt.x) / 2;
  1195.         f2.x = (1 - Sqrt.x) / 2;
  1196.         f1.y =  Sqrt.y / 2;
  1197.         f2.y = -Sqrt.y / 2;
  1198.  
  1199.         ClearQueue();
  1200.         maxhits = 1;
  1201.         EnQueueFloat(f1.x, f1.y);
  1202.         EnQueueFloat(f2.x, f2.y);
  1203.      }
  1204. /*
  1205.  * End MIIM code.
  1206.  */
  1207.      if(which == ORBIT)
  1208.            do_fractal_routines(cr, ci,PER_PIXEL);
  1209.      /* move window if bumped */
  1210.      if(windows==0 && xcrsr>xc && xcrsr < xc+xd && ycrsr>yc && ycrsr < yc+yd)
  1211.      {
  1212.         RestoreRect(xc,yc,xd,yd);
  1213.         if (xc == xd*2)
  1214.            xc = 2;
  1215.         else
  1216.            xc = xd*2;
  1217.         xoff = xc + xd /  2;
  1218.         SaveRect(xc,yc,xd,yd);
  1219.      }
  1220.      if(windows == 2)
  1221.      {
  1222.         fillrect(xdots, yc, xd-xdots, yd-show_numbers, color_dark);
  1223.         fillrect(xc   , ydots, xdots, yd-ydots-show_numbers, color_dark);
  1224.      }
  1225.      else
  1226.         fillrect(xc, yc, xd, yd, color_dark);
  1227.  
  1228.       } /* end if (keypressed) */
  1229.  
  1230.       if(which == JIIM)
  1231.       {
  1232.          if(hasinverse == 0)
  1233.             continue;
  1234. /*
  1235.  * MIIM code:
  1236.  * If we have MIIM queue allocated, then use MIIM method.
  1237.  */
  1238.      if (OKtoMIIM)
  1239.      {
  1240.         if (QueueEmpty())
  1241.         {
  1242.            if (maxhits < colors - 1 && maxhits < 5 &&
  1243.           (luckyx != 0.0 || luckyy != 0.0))
  1244.            {
  1245.           int i;
  1246.  
  1247.           lsize  = lmax   = 0;
  1248.           old.x  = new.x  = luckyx;
  1249.           old.y  = new.y  = luckyy;
  1250.           luckyx = luckyy = 0.0;
  1251.           for (i=0; i<199; i++)
  1252.           {
  1253.              old = ComplexSqrtFloat(old.x - cr, old.y - ci);
  1254.              new = ComplexSqrtFloat(new.x - cr, new.y - ci);
  1255.              EnQueueFloat( new.x,  new.y);
  1256.              EnQueueFloat(-old.x, -old.y);
  1257.           }
  1258.           maxhits++;
  1259.            }
  1260.            else
  1261.           continue;        /* loop while (still) */
  1262.         }
  1263.  
  1264.         old = DeQueueFloat();
  1265.  
  1266. #if 0 /* try a different new method */
  1267.         if (lsize < (lmax / 8) && maxhits < 5)    /* NEW METHOD */
  1268.            if (maxhits < colors - 1)
  1269.            maxhits++;
  1270. #endif
  1271.         x = old.x * xfactor * zoom + xoff;
  1272.         y = old.y * yfactor * zoom + yoff;
  1273.         color = c_getcolor(x, y);
  1274.         if (color < maxhits)
  1275.         {
  1276.            c_putcolor(x, y, color + 1);
  1277.            new = ComplexSqrtFloat(old.x - cr, old.y - ci);
  1278.            EnQueueFloat( new.x,  new.y);
  1279.            EnQueueFloat(-new.x, -new.y);
  1280.         }
  1281.      }
  1282.      else
  1283.      {
  1284. /*
  1285.  * end Msnyder code, commence if not MIIM code.
  1286.  */
  1287.      old.x -= cr;
  1288.      old.y -= ci;
  1289.      r = old.x*old.x + old.y*old.y;
  1290.      if(r > 10.0)
  1291.      {
  1292.          old.x = old.y = 0.0; /* avoids math error */
  1293.          iter = 1;
  1294.      }
  1295.      iter++;
  1296.      color = ((count++)>>5)&(colors-1); /* chg color every 32 pts */
  1297.      if(color==0)
  1298.       color = 1;
  1299.  
  1300.      r = sqrt(old.x*old.x + old.y*old.y);
  1301.      new.x = sqrt(fabs((r + old.x)/2));
  1302.      if (old.y < 0)
  1303.         new.x = -new.x;
  1304.  
  1305.      new.y = sqrt(fabs((r - old.x)/2));
  1306.  
  1307.  
  1308.      switch (SecretExperimentalMode) {
  1309.         case 0:            /* unmodified random walk */
  1310.         default:
  1311.         if (rand() % 2)
  1312.         {
  1313.            new.x = -new.x;
  1314.            new.y = -new.y;
  1315.         }
  1316.         x = new.x * xfactor * zoom + xoff;
  1317.         y = new.y * yfactor * zoom + yoff;
  1318.         break;
  1319.         case 1:              /* always go one direction */
  1320.         if (SaveC.y < 0)
  1321.         {
  1322.            new.x = -new.x;
  1323.            new.y = -new.y;
  1324.         }
  1325.         x = new.x * xfactor * zoom + xoff;
  1326.         y = new.y * yfactor * zoom + yoff;
  1327.         break;
  1328.         case 2:            /* go one dir, draw the other */
  1329.         if (SaveC.y < 0)
  1330.         {
  1331.            new.x = -new.x;
  1332.            new.y = -new.y;
  1333.         }
  1334.         x = -new.x * xfactor * zoom + xoff;
  1335.         y = -new.y * yfactor * zoom + yoff;
  1336.         break;
  1337.         case 4:            /* go negative if max color */
  1338.         x = new.x * xfactor * zoom + xoff;
  1339.         y = new.y * yfactor * zoom + yoff;
  1340.         if (c_getcolor(x, y) == colors - 1)
  1341.         {
  1342.            new.x = -new.x;
  1343.            new.y = -new.y;
  1344.            x = new.x * xfactor * zoom + xoff;
  1345.            y = new.y * yfactor * zoom + yoff;
  1346.         }
  1347.         break;
  1348.         case 5:            /* go positive if max color */
  1349.         new.x = -new.x;
  1350.         new.y = -new.y;
  1351.         x = new.x * xfactor * zoom + xoff;
  1352.         y = new.y * yfactor * zoom + yoff;
  1353.         if (c_getcolor(x, y) == colors - 1)
  1354.         {
  1355.            x = new.x * xfactor * zoom + xoff;
  1356.            y = new.y * yfactor * zoom + yoff;
  1357.         }
  1358.         break;
  1359.         case 7:
  1360.         if (SaveC.y < 0)
  1361.         {
  1362.            new.x = -new.x;
  1363.            new.y = -new.y;
  1364.         }
  1365.         x = -new.x * xfactor * zoom + xoff;
  1366.         y = -new.y * yfactor * zoom + yoff;
  1367.         if(iter > 10)
  1368.         {
  1369.            if(mode == 0)            /* pixels  */
  1370.               c_putcolor(x, y, color);
  1371.            else if (mode & 1)            /* circles */
  1372.            {
  1373.               xbase = x;
  1374.               ybase = y;
  1375.               circle((int)(zoom*(xd >> 1)/iter),color);
  1376.            }
  1377.            if ((mode & 2) && x > 0 && y > 0 && old_x > 0 && old_y > 0)
  1378.            {
  1379.               draw_line(x, y, old_x, old_y, color);
  1380.            }
  1381.            old_x = x;
  1382.            old_y = y;
  1383.         }
  1384.         x = new.x * xfactor * zoom + xoff;
  1385.         y = new.y * yfactor * zoom + yoff;
  1386.         break;
  1387.         case 8:            /* go in long zig zags */
  1388.         if (rancnt >= 300)
  1389.             rancnt = -300;
  1390.         if (rancnt < 0)
  1391.         {
  1392.             new.x = -new.x;
  1393.             new.y = -new.y;
  1394.         }
  1395.         x = new.x * xfactor * zoom + xoff;
  1396.         y = new.y * yfactor * zoom + yoff;
  1397.         break;
  1398.         case 9:            /* "random run" */
  1399.         switch (randir) {
  1400.             case 0:             /* go random direction for a while */
  1401.             if (rand() % 2)
  1402.             {
  1403.                 new.x = -new.x;
  1404.                 new.y = -new.y;
  1405.             }
  1406.             if (++rancnt > 1024)
  1407.             {
  1408.                 rancnt = 0;
  1409.                 if (rand() % 2)
  1410.                 randir =  1;
  1411.                 else
  1412.                 randir = -1;
  1413.             }
  1414.             break;
  1415.             case 1:             /* now go negative dir for a while */
  1416.             new.x = -new.x;
  1417.             new.y = -new.y;
  1418.             /* fall through */
  1419.             case -1:            /* now go positive dir for a while */
  1420.             if (++rancnt > 512)
  1421.                 randir = rancnt = 0;
  1422.             break;
  1423.         }
  1424.         x = new.x * xfactor * zoom + xoff;
  1425.         y = new.y * yfactor * zoom + yoff;
  1426.         break;
  1427.      } /* end switch SecretMode (sorry about the indentation) */
  1428.      } /* end if not MIIM */
  1429.       }
  1430.       else /* orbits */
  1431.       {
  1432.      if(iter < maxit)
  1433.      {
  1434.         color = iter&(colors-1);
  1435.         x = (old.x - init.x) * xfactor * 3 * zoom + xoff;
  1436.         y = (old.y - init.y) * yfactor * 3 * zoom + yoff;
  1437.         if(do_fractal_routines(cr, ci,ORBITCALC))
  1438.            iter = maxit;
  1439.         else
  1440.            iter++;
  1441.      }
  1442.      else
  1443.      {
  1444.         x = y = -1;
  1445.         actively_computing = 0;
  1446.      }
  1447.       }
  1448.       if(which == ORBIT || iter > 10)
  1449.       {
  1450.      if(mode == 0)            /* pixels  */
  1451.         c_putcolor(x, y, color);
  1452.      else if (mode & 1)            /* circles */
  1453.      {
  1454.         xbase = x;
  1455.         ybase = y;
  1456.         circle((int)(zoom*(xd >> 1)/iter),color);
  1457.      }
  1458.      if ((mode & 2) && x > 0 && y > 0 && old_x > 0 && old_y > 0)
  1459.      {
  1460.         draw_line(x, y, old_x, old_y, color);
  1461.      }
  1462.      old_x = x;
  1463.      old_y = y;
  1464.       }
  1465.       old = new;
  1466.    } /* end while(still) */
  1467. finish:
  1468.  
  1469. /*
  1470.  * Msnyder code:
  1471.  * free MIIM queue
  1472.  */
  1473.  
  1474.    Free_Queue();
  1475. /*
  1476.  * end Msnyder code.
  1477.  */
  1478.  
  1479.    if(kbdchar != 's'&& kbdchar != 'S')
  1480.    {
  1481.       Cursor_Hide();
  1482.       if(windows == 0)
  1483.      RestoreRect(xc,yc,xd,yd);
  1484.       else if(windows >= 2 )
  1485.       {
  1486.      if(windows == 2)
  1487.      {
  1488.         fillrect(xdots, yc, xd-xdots, yd, color_dark);
  1489.         fillrect(xc   , ydots, xdots, yd-ydots, color_dark);
  1490.      }
  1491.      else
  1492.         fillrect(xc, yc, xd, yd, color_dark);
  1493.          if(windows == 3 && xd == sxdots) /* unhide */
  1494.          {
  1495.             RestoreRect(0, 0, xdots, ydots);
  1496.             windows = 2;
  1497.          }
  1498.      Cursor_Hide();
  1499.      savehasinverse = hasinverse;
  1500.      hasinverse = 1;
  1501.      SaveRect(0,0,xdots,ydots);
  1502.      sxoffs = oldsxoffs;
  1503.      syoffs = oldsyoffs;
  1504.      RestoreRect(0,0,xdots,ydots);
  1505.      hasinverse = savehasinverse;
  1506.       }
  1507.    }
  1508.    Cursor_Destroy();
  1509. #ifdef XFRACT
  1510.    Cursor_EndMouseTracking();
  1511. #endif
  1512.    delete(line_buff);
  1513.    if (memory)            /* done with memory, free it */
  1514.    {
  1515.       farmemfree(memory);
  1516.       memory = NULL;
  1517.    }
  1518.  
  1519.    lookatmouse = oldlookatmouse;
  1520.    using_jiim = 0;
  1521.    calctype = oldcalctype;
  1522.  
  1523.    helpmode = oldhelpmode;
  1524.    if(kbdchar == 's' || kbdchar == 'S')
  1525.    {
  1526.       viewwindow = viewxdots = viewydots = 0;
  1527.       viewreduction = 4.2;
  1528.       viewcrop = 1;
  1529.       finalaspectratio = screenaspect;
  1530.       xdots = sxdots;
  1531.       ydots = sydots;
  1532.       dxsize = xdots - 1;
  1533.       dysize = ydots - 1;
  1534.       sxoffs = 0;
  1535.       syoffs = 0;
  1536.       freetempmsg();
  1537.    }
  1538.    else
  1539.       cleartempmsg();
  1540.    if (file != NULL)
  1541.       {
  1542.       fclose(file);
  1543.       file = NULL;
  1544.       remove(scrnfile);
  1545.       }
  1546.    show_numbers = 0;
  1547.    ungetakey(kbdchar);
  1548.    EXIT_OVLY;
  1549. }
  1550.   
  1551.