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