home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / progmisc / frasrc18.zip / MISCRES.C < prev    next >
C/C++ Source or Header  |  1993-04-16  |  27KB  |  918 lines

  1. /*
  2.     Resident odds and ends that don't fit anywhere else.
  3. */
  4.  
  5. #include <string.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <time.h>
  10. #ifndef XFRACT
  11. #include <stdarg.h>
  12. #include <io.h>
  13. #else
  14. #include <varargs.h>
  15. #endif
  16. #include <math.h>
  17. #ifdef __TURBOC__
  18. #include <dir.h>
  19. #endif
  20. #include "fractint.h"
  21. #include "fractype.h"
  22. #include "helpdefs.h"
  23. #include "prototyp.h"
  24.  
  25. /* routines in this module    */
  26.  
  27. static    void trigdetails(char *);
  28. static void area();
  29.  
  30. int active_ovly = -1;
  31.  
  32. extern char IFSFileName[80];
  33. extern char IFSName[40];
  34. extern float far *ifs_defn;
  35. extern int  ifs_changed;
  36. extern int  ifs_type;
  37. extern int neworbittype;
  38. extern char temp[], temp1[256];   /* temporary strings          */
  39.  
  40. extern int  active_ovly;
  41. extern int  xdots, ydots;
  42. extern int  dotmode;
  43. extern int  show_orbit;
  44. extern int  debugflag;
  45. extern int  maxit;
  46. extern int  fractype;
  47. extern int  got_status,curpass,totpasses,currow,curcol;
  48. extern int  fileydots;
  49. extern int  xxstart,xxstop,yystart,yystop;
  50. extern int  display3d;
  51. extern char overwrite;
  52. extern int  inside;
  53. extern int  outside;
  54. extern double xxmax,xxmin,yymax,yymin,xx3rd,yy3rd;
  55.  
  56.  
  57. /* TW's static string consolidation campaign to help brain-dead compilers */
  58. char s_cantopen[]       = {"Can't open %s"};
  59. char s_cantwrite[]      = {"Can't write %s"};
  60. char s_cantcreate[]     = {"Can't create %s"};
  61. char s_cantunderstand[] = {"Can't understand %s"};
  62. char s_cantfind[]       = {"Can't find %s"};
  63.  
  64. /* call next when returning from resident routine and unsure whether
  65.    caller is an overlay which has been displaced */
  66. void restore_active_ovly()
  67. {
  68.    switch (active_ovly) {
  69.       case OVLY_MISCOVL:  miscovl_overlay();  break;
  70.       case OVLY_CMDFILES: cmdfiles_overlay(); break;
  71.       case OVLY_HELP:      help_overlay();     break;
  72.       case OVLY_PROMPTS1: prompts1_overlay(); break;
  73.       case OVLY_PROMPTS2: prompts2_overlay(); break;
  74.       case OVLY_LOADFILE: loadfile_overlay(); break;
  75.       case OVLY_ROTATE:   rotate_overlay();   break;
  76.       case OVLY_PRINTER:  printer_overlay();  break;
  77.       case OVLY_LINE3D:   line3d_overlay();   break;
  78.       case OVLY_ENCODER:  encoder_overlay();  break;
  79.       case OVLY_CALCFRAC: calcfrac_overlay(); break;
  80.       case OVLY_INTRO:      intro_overlay();    break;
  81.       case OVLY_DECODER:  decoder_overlay();  break;
  82.       }
  83. }
  84.  
  85.  
  86. #ifndef XFRACT
  87. void findpath(char *filename, char *fullpathname) /* return full pathnames */
  88. {
  89.    if (filename[0] == SLASHC
  90.      || (filename[0] && filename[1] == ':')) {
  91.       strcpy(fullpathname,filename);
  92.       return;
  93.       }
  94.    fullpathname[0] = 0;             /* indicate none found */
  95. #ifdef __TURBOC__                /* look for the file */
  96.    strcpy(fullpathname,searchpath(filename));
  97. #else
  98.    _searchenv(filename,"PATH",fullpathname);
  99. #endif
  100.    if (fullpathname[0] != 0)            /* found it! */
  101.       if (strncmp(&fullpathname[2],SLASHSLASH,2) == 0) /* stupid klooge! */
  102.      strcpy(&fullpathname[3],filename);
  103. }
  104. #endif
  105.  
  106.  
  107. void notdiskmsg()
  108. {
  109. static char far sorrymsg[]={
  110. "I'm sorry, but because of its random-screen-access algorithms, this\n\
  111. type cannot be created using a real-disk based 'video' mode."};
  112.    stopmsg(1,sorrymsg);
  113. }
  114.  
  115.  
  116. /* convert corners to center/mag */
  117. int cvtcentermag(double *Xctr, double *Yctr, double *Magnification)
  118. {
  119.    double Width, Height, Radius, Ratio;
  120.    Width  = xxmax - xxmin;
  121.    Height = yymax - yymin;
  122.    Ratio = Height / Width;
  123.    if(xx3rd != xxmin || yy3rd != yymin || Width < 0
  124.      || (Width > 1e-8 && (Ratio <= 0.74 || Ratio >= 0.76))
  125.      || Ratio < 0.66 || Ratio > 0.84)
  126.       return(0);
  127.    /* calculate center and magnification */
  128.    Radius = Height / 2.0;
  129.    *Xctr = xxmin + (Width / 2.0);
  130.    *Yctr = yymin + Radius;
  131.    *Magnification = 1.0 / Radius;
  132.    return(1);
  133. }
  134.  
  135.  
  136. void updatesavename(char *filename) /* go to the next file name */
  137. {
  138.    char *save, *hold;
  139.    char name[80],suffix[80];
  140.    char *dotptr;
  141.  
  142.    strcpy(name,filename);
  143.    suffix[0] = 0;
  144.    if ((dotptr = strrchr(name,'.')) != NULL
  145.      && dotptr > strrchr(name,SLASHC)) {
  146.       strcpy(suffix,dotptr);
  147.       *dotptr = 0;
  148.       }
  149.  
  150.    hold = name + strlen(name) - 1; /* start at the end */
  151.    while(hold >= name && (*hold == ' ' || isdigit(*hold))) /* skip backwards */
  152.       hold--;
  153.    hold++;            /* recover first digit */
  154.    while (*hold == '0')         /* skip leading zeros */
  155.       hold++;
  156.    save = hold;
  157.    while (*save) {        /* check for all nines */
  158.       if (*save != '9')
  159.      break;
  160.       save++;
  161.       }
  162.    if (!*save)            /* if the whole thing is nines then back */
  163.       save = hold - 1;        /* up one place. Note that this will eat */
  164.                 /* your last letter if you go to far.     */
  165.    else
  166.       save = hold;
  167.    sprintf(save,"%d",atoi(hold)+1); /* increment the number */
  168.    strcpy(filename,name);
  169.    strcat(filename,suffix);
  170. }
  171.  
  172. int check_writefile(char *name,char *ext)
  173. {
  174.  /* after v16 release, change encoder.c to also use this routine */
  175.    char openfile[80];
  176.    char opentype[20];
  177.    int i;
  178. nextname:
  179.    strcpy(openfile,name);
  180.    strcpy(opentype,ext);
  181.    for (i = 0; i < strlen(openfile); i++)
  182.       if (openfile[i] == '.') {
  183.      strcpy(opentype,&openfile[i]);
  184.      openfile[i] = 0;
  185.      }
  186.    strcat(openfile,opentype);
  187.    if (access(openfile,0) != 0) /* file doesn't exist */
  188.    {
  189.       strcpy(name,openfile);
  190.       return 0;
  191.     }
  192.    /* file already exists */
  193.    if (overwrite == 0) {
  194.       updatesavename(name);
  195.       goto nextname;
  196.       }
  197.    return 1;
  198. }
  199.  
  200. /* ('check_key()' was moved to FRACTINT.C for MSC7-overlay speed purposes) */
  201. /* ('timer()'     was moved to FRACTINT.C for MSC7-overlay speed purposes) */
  202.  
  203. BYTE trigndx[] = {SIN,SQR,SINH,COSH};
  204. #ifndef XFRACT
  205. void (*ltrig0)(void) = lStkSin;
  206. void (*ltrig1)(void) = lStkSqr;
  207. void (*ltrig2)(void) = lStkSinh;
  208. void (*ltrig3)(void) = lStkCosh;
  209. void (*mtrig0)(void) = mStkSin;
  210. void (*mtrig1)(void) = mStkSqr;
  211. void (*mtrig2)(void) = mStkSinh;
  212. void (*mtrig3)(void) = mStkCosh;
  213. #endif
  214. void (*dtrig0)(void) = dStkSin;
  215. void (*dtrig1)(void) = dStkSqr;
  216. void (*dtrig2)(void) = dStkSinh;
  217. void (*dtrig3)(void) = dStkCosh;
  218.  
  219. struct trig_funct_lst trigfn[] =
  220. /* changing the order of these alters meaning of *.fra file */
  221. /* maximum 6 characters in function names or recheck all related code */
  222. {
  223. #ifndef XFRACT
  224.    {"sin",   lStkSin,   dStkSin,   mStkSin   },
  225.    {"cosxx", lStkCosXX, dStkCosXX, mStkCosXX },
  226.    {"sinh",  lStkSinh,  dStkSinh,  mStkSinh  },
  227.    {"cosh",  lStkCosh,  dStkCosh,  mStkCosh  },
  228.    {"exp",   lStkExp,   dStkExp,   mStkExp   },
  229.    {"log",   lStkLog,   dStkLog,   mStkLog   },
  230.    {"sqr",   lStkSqr,   dStkSqr,   mStkSqr   },
  231.    {"recip", lStkRecip, dStkRecip, mStkRecip }, /* from recip on new in v16 */
  232.    {"ident", StkIdent,  StkIdent,  StkIdent  },
  233.    {"cos",   lStkCos,   dStkCos,   mStkCos   },
  234.    {"tan",   lStkTan,   dStkTan,   mStkTan   },
  235.    {"tanh",  lStkTanh,  dStkTanh,  mStkTanh  },
  236.    {"cotan", lStkCoTan, dStkCoTan, mStkCoTan },
  237.    {"cotanh",lStkCoTanh,dStkCoTanh,mStkCoTanh},
  238.    {"flip",  lStkFlip,  dStkFlip,  mStkFlip  },
  239.    {"conj",  lStkConj,  dStkConj,  mStkConj  },
  240.    {"zero",  lStkZero,  dStkZero,  mStkZero  },
  241. #else
  242.    {"sin",   dStkSin,   dStkSin,   dStkSin   },
  243.    {"cosxx", dStkCosXX, dStkCosXX, dStkCosXX },
  244.    {"sinh",  dStkSinh,  dStkSinh,  dStkSinh  },
  245.    {"cosh",  dStkCosh,  dStkCosh,  dStkCosh  },
  246.    {"exp",   dStkExp,   dStkExp,   dStkExp   },
  247.    {"log",   dStkLog,   dStkLog,   dStkLog   },
  248.    {"sqr",   dStkSqr,   dStkSqr,   dStkSqr   },
  249.    {"recip", dStkRecip, dStkRecip, dStkRecip }, /* from recip on new in v16 */
  250.    {"ident", StkIdent,  StkIdent,  StkIdent  },
  251.    {"cos",   dStkCos,   dStkCos,   dStkCos   },
  252.    {"tan",   dStkTan,   dStkTan,   dStkTan   },
  253.    {"tanh",  dStkTanh,  dStkTanh,  dStkTanh  },
  254.    {"cotan", dStkCoTan, dStkCoTan, dStkCoTan },
  255.    {"cotanh",dStkCoTanh,dStkCoTanh,dStkCoTanh},
  256.    {"flip",  dStkFlip,  dStkFlip,  dStkFlip  },
  257.    {"conj",  dStkConj,  dStkConj,  dStkConj  },
  258.    {"zero",  dStkZero,  dStkZero,  dStkZero  },
  259. #endif
  260. };
  261. int numtrigfn = sizeof(trigfn)/sizeof(struct trig_funct_lst);
  262.  
  263. void showtrig(char *buf) /* return display form of active trig functions */
  264. {
  265.    char tmpbuf[30];
  266.    *buf = 0; /* null string if none */
  267.    trigdetails(tmpbuf);
  268.    if (tmpbuf[0])
  269.       sprintf(buf," function=%s",tmpbuf);
  270. }
  271.  
  272. static void trigdetails(char *buf)
  273. {
  274.    extern char maxfn;
  275.    int i, numfn;
  276.    char tmpbuf[20];
  277.    if(fractype==JULIBROT || fractype==JULIBROTFP)
  278.       numfn = (fractalspecific[neworbittype].flags >> 6) & 7;
  279.    else
  280.       numfn = (curfractalspecific->flags >> 6) & 7;
  281.    if(curfractalspecific == &fractalspecific[FORMULA] ||
  282.       curfractalspecific == &fractalspecific[FFORMULA]    )
  283.       numfn = maxfn;
  284.    *buf = 0; /* null string if none */
  285.    if (numfn>0) {
  286.       strcpy(buf,trigfn[trigndx[0]].name);
  287.       i = 0;
  288.       while(++i < numfn) {
  289.      sprintf(tmpbuf,"/%s",trigfn[trigndx[i]].name);
  290.      strcat(buf,tmpbuf);
  291.      }
  292.       }
  293. }
  294.  
  295. /* set array of trig function indices according to "function=" command */
  296. int set_trig_array(int k, char *name)
  297. {
  298.    char trigname[10];
  299.    int i;
  300.    char *slash;
  301.    strncpy(trigname,name,6);
  302.    trigname[6] = 0; /* safety first */
  303.  
  304.    if ((slash = strchr(trigname,'/')))
  305.       *slash = 0;
  306.  
  307.    strlwr(trigname);
  308.  
  309.    for(i=0;i<numtrigfn;i++)
  310.    {
  311.       if(strcmp(trigname,trigfn[i].name)==0)
  312.       {
  313.      trigndx[k] = i;
  314.      set_trig_pointers(k);
  315.      break;
  316.       }
  317.    }
  318.    return(0);
  319. }
  320. void set_trig_pointers(int which)
  321. {
  322.   /* set trig variable functions to avoid array lookup time */
  323.    int i;
  324.    switch(which)
  325.    {
  326.    case 0:
  327. #ifndef XFRACT
  328.       ltrig0 = trigfn[trigndx[0]].lfunct;
  329.       mtrig0 = trigfn[trigndx[0]].mfunct;
  330. #endif
  331.       dtrig0 = trigfn[trigndx[0]].dfunct;
  332.       break;
  333.    case 1:
  334. #ifndef XFRACT
  335.       ltrig1 = trigfn[trigndx[1]].lfunct;
  336.       mtrig1 = trigfn[trigndx[1]].mfunct;
  337. #endif
  338.       dtrig1 = trigfn[trigndx[1]].dfunct;
  339.       break;
  340.    case 2:
  341. #ifndef XFRACT
  342.       ltrig2 = trigfn[trigndx[2]].lfunct;
  343.       mtrig2 = trigfn[trigndx[2]].mfunct;
  344. #endif
  345.       dtrig2 = trigfn[trigndx[2]].dfunct;
  346.       break;
  347.    case 3:
  348. #ifndef XFRACT
  349.       ltrig3 = trigfn[trigndx[3]].lfunct;
  350.       mtrig3 = trigfn[trigndx[3]].mfunct;
  351. #endif
  352.       dtrig3 = trigfn[trigndx[3]].dfunct;
  353.       break;
  354.    default: /* do 'em all */
  355.       for(i=0;i<4;i++)
  356.      set_trig_pointers(i);
  357.       break;
  358.    }
  359. }
  360.  
  361.  
  362. int tab_display()    /* display the status of the current image */
  363. {
  364. /* TW's static string consolidation campaign to help brain-dead compilers */
  365.    static char far sfractal_type[] =     {"Fractal type:"};
  366.    static char far s3D_transform[] =     {"3D Transform"};
  367.    static char far syou_are_cycling[] =  {"You are in color-cycling mode"};
  368.    static char far sfloating_point[] =   {"Floating-point"};
  369.    static char far sruns_forever[] =     {"Note: this type runs forever."};
  370.    static char far ssolid_guessing[] =   {"Solid Guessing"};
  371.    static char far sboundary_tracing[] = {"Boundary Tracing"};
  372.    static char far stesseral[] =         {"Tesseral"};
  373.    static char far scalculation_time[] = {"Calculation time:"};
  374.    static char far scornersxy[] =        {"Corners:                X                     Y"};
  375.    static char far stop_left[] =         {"top-left"};
  376.    static char far sbottom_right[] =     {"bottom-right"};
  377.    static char far scenter[] =           {"Center: "};
  378.    static char far smag[] =              {"  Mag: "};
  379.    static char far sbottom_left[] =      {"bottom-left"};
  380.    static char far sparams[] =           {"Params,"};
  381.    static char far siteration_maximum[] ={"Iteration maximum: "};
  382.    static char far seffective_bailout[] ={"     Effective bailout: "};
  383.    static char far scurrent_rseed[] =    {"Current 'rseed': "};
  384.    static char far sinversion_radius[] = {"Inversion radius: "};
  385.    static char far sxcenter[] =          {"  xcenter: "};
  386.    static char far sycenter[] =          {"  ycenter: "};
  387.    static char far sparms_chgd[] = {"Parms chgd since generated"};
  388.    static char far sstill_being[] = {"Still being generated"};
  389.    static char far sinterrupted_resumable[] = {"Interrupted, resumable"};
  390.    static char far sinterrupted_non_resumable[] = {"Interrupted, non-resumable"};
  391.    static char far simage_completed[] = {"Image completed"};
  392.    static char far sflag_is_activated[] = {" flag is activated"};
  393.    static char far sinteger_math[]      = {"Integer math is in use"};
  394.    static char far sin_use_required[] = {" in use (required)"};
  395.  
  396.    extern char floatflag;
  397.    extern char usr_floatflag;
  398.    extern double param[];
  399.    extern double rqlim;
  400.    extern long calctime, timer_start;
  401.    extern int  calc_status;
  402.    extern char FormName[];
  403.    extern char LName[];
  404.    extern char IFSName[];
  405.    extern int  rseed;
  406.    extern int  invert;
  407.    int row, i, j;
  408.    double Xctr, Yctr, Magnification;
  409.    char msg[81];
  410.    char far *msgptr;
  411.    int key;
  412.  
  413.    if (calc_status < 0)     /* no active fractal image */
  414.       return(0);        /* (no TAB on the credits screen) */
  415.    if (calc_status == 1)    /* next assumes CLK_TCK is 10^n, n>=2 */
  416.       calctime += (clock_ticks() - timer_start) / (CLK_TCK/100);
  417.    stackscreen();
  418. top:
  419.    helptitle();
  420.    setattr(1,0,C_GENERAL_MED,24*80); /* init rest to background */
  421.  
  422.    row = 2;
  423.    putstring(row,2,C_GENERAL_MED,sfractal_type);
  424.    if (display3d > 0)
  425.       putstring(row,16,C_GENERAL_HI,s3D_transform);
  426.    else {
  427.       putstring(row,16,C_GENERAL_HI,
  428.        curfractalspecific->name[0] == '*' ?
  429.          &curfractalspecific->name[1] :
  430.          curfractalspecific->name);
  431.       i = 0;
  432.       if (fractype == FORMULA || fractype == FFORMULA)
  433.       {
  434.      putstring(row+1,16,C_GENERAL_HI,FormName);
  435.       i = strlen(FormName)+1;
  436.       }
  437.       trigdetails(msg);
  438.       putstring(row+1,16+i,C_GENERAL_HI,msg);
  439.       if (fractype == LSYSTEM)
  440.      putstring(row+1,16,C_GENERAL_HI,LName);
  441.       if (fractype == IFS || fractype == IFS3D)
  442.      putstring(row+1,16,C_GENERAL_HI,IFSName);
  443.       }
  444.  
  445.    switch (calc_status) {
  446.       case 0:  msgptr = sparms_chgd;
  447.            break;
  448.       case 1:  msgptr = sstill_being;
  449.            break;
  450.       case 2:  msgptr = sinterrupted_resumable;
  451.            break;
  452.       case 3:  msgptr = sinterrupted_non_resumable;
  453.            break;
  454.       case 4:  msgptr = simage_completed;
  455.            break;
  456.       default: msgptr = "";
  457.       }
  458.    putstring(row,45,C_GENERAL_HI,msgptr);
  459.    if (helpmode == HELPCYCLING)
  460.       putstring(row+1,45,C_GENERAL_HI,syou_are_cycling);
  461.    row += 2;
  462.  
  463.     i = j = 0;
  464.     if (display3d > 0) {
  465.        if (usr_floatflag)
  466.       j = 1;
  467.        }
  468.     else
  469.        if (floatflag)
  470.       j = (usr_floatflag) ? 1 : 2;
  471.     if (j) {
  472.        putstring(row,45,C_GENERAL_HI,sfloating_point);
  473.  
  474.        putstring(-1,-1,C_GENERAL_HI,(j == 1) ? sflag_is_activated
  475.                          : sin_use_required );
  476.       i = 1;
  477.       }
  478.       else
  479.       {
  480.        putstring(row,45,C_GENERAL_HI,sinteger_math);
  481.       i = 1;
  482.       }
  483.    if (calc_status == 1 || calc_status == 2)
  484.       if (curfractalspecific->flags&INFCALC) {
  485.      putstring(row,2,C_GENERAL_HI,sruns_forever);
  486.      i = 1;
  487.      }
  488.    row += i;
  489.  
  490.    if (calc_status == 1 || calc_status == 2)
  491.       if (curfractalspecific->flags&NORESUME)
  492.       {
  493.      static char far msg[] = {"Note: can't resume this type after interrupts other than <tab> and <F1>"};
  494.      putstring(row++,2,C_GENERAL_HI,msg);
  495.       }
  496.    ++row;
  497.  
  498.    if (got_status >= 0 && (calc_status == 1 || calc_status == 2)) {
  499.       switch (got_status) {
  500.      case 0:
  501.         sprintf(msg,"%d Pass Mode",totpasses);
  502.         putstring(row,2,C_GENERAL_HI,msg);
  503.         break;
  504.      case 1:
  505.         putstring(row,2,C_GENERAL_HI,ssolid_guessing);
  506.         break;
  507.      case 2:
  508.         putstring(row,2,C_GENERAL_HI,sboundary_tracing);
  509.         break;
  510.      case 3:
  511.         sprintf(msg,"Processing row %d (of %d) of input image",currow,fileydots);
  512.         putstring(row,2,C_GENERAL_HI,msg);
  513.         break;
  514.      case 4:
  515.         putstring(row,2,C_GENERAL_HI,stesseral);
  516.         break;
  517.      }
  518.       ++row;
  519.       if (got_status != 3) {
  520.      sprintf(msg,"Working on block (y,x) [%d,%d]...[%d,%d], ",
  521.         yystart,xxstart,yystop,xxstop);
  522.      putstring(row,2,C_GENERAL_MED,msg);
  523.      if (got_status == 2 || got_status == 4) { /* btm or tesseral */
  524.         putstring(-1,-1,C_GENERAL_MED,"at ");
  525.         sprintf(msg,"[%d,%d]",currow,curcol);
  526.         putstring(-1,-1,C_GENERAL_HI,msg);
  527.         }
  528.      else {
  529.         if (totpasses > 1) {
  530.            putstring(-1,-1,C_GENERAL_MED,"pass ");
  531.            sprintf(msg,"%d",curpass);
  532.            putstring(-1,-1,C_GENERAL_HI,msg);
  533.            putstring(-1,-1,C_GENERAL_MED," of ");
  534.            sprintf(msg,"%d",totpasses);
  535.            putstring(-1,-1,C_GENERAL_HI,msg);
  536.            putstring(-1,-1,C_GENERAL_MED,", ");
  537.            }
  538.         putstring(-1,-1,C_GENERAL_MED,"at row ");
  539.         sprintf(msg,"%d",currow);
  540.         putstring(-1,-1,C_GENERAL_HI,msg);
  541.         }
  542.      ++row;
  543.      }
  544.       }
  545.    putstring(row,2,C_GENERAL_MED,scalculation_time);
  546.    sprintf(msg,"%3ld:%02ld:%02ld.%02ld", calctime/360000,
  547.       (calctime%360000)/6000, (calctime%6000)/100, calctime%100);
  548.    putstring(-1,-1,C_GENERAL_HI,msg);
  549.    row += 2;
  550.  
  551.    if (videoentry.xdots) {
  552.       sprintf(msg,"Video: %dx%dx%d %s %s",
  553.           videoentry.xdots, videoentry.ydots, videoentry.colors,
  554.           videoentry.name, videoentry.comment);
  555.       putstring(row,2,C_GENERAL_MED,msg);
  556.       }
  557.    ++row;
  558.  
  559.    putstring(row,2,C_GENERAL_MED,scornersxy);
  560.    putstring(++row,3,C_GENERAL_MED,stop_left);
  561.    sprintf(msg,"%20.16f  %20.16f",xxmin,yymax);
  562.    putstring(-1,17,C_GENERAL_HI,msg);
  563.    putstring(++row,3,C_GENERAL_MED,sbottom_right);
  564.    sprintf(msg,"%20.16f  %20.16f",xxmax,yymin);
  565.    putstring(-1,17,C_GENERAL_HI,msg);
  566.    adjust_corner(); /* make bottom left exact if very near exact */
  567.    if (cvtcentermag(&Xctr, &Yctr, &Magnification)) {
  568.       putstring(row+=2,2,C_GENERAL_MED,scenter);
  569.       sprintf(msg,"%20.16f %20.16f",Xctr,Yctr);
  570.       putstring(-1,-1,C_GENERAL_HI,msg);
  571.       putstring(-1,-1,C_GENERAL_MED,smag);
  572.       if (Magnification < 1e6)
  573.      sprintf(msg,"%20.14f",Magnification);
  574.       else if (Magnification < 1e12)
  575.      sprintf(msg,"%20.8f",Magnification);
  576.       else
  577.      sprintf(msg,"%20.2f",Magnification);
  578.       putstring(-1,-1,C_GENERAL_HI,msg);
  579.       }
  580.    else if (xxmin != xx3rd || yymin != yy3rd) {
  581.       putstring(++row,3,C_GENERAL_MED,sbottom_left);
  582.       sprintf(msg,"%20.16f  %20.16f",xx3rd,yy3rd);
  583.       putstring(-1,17,C_GENERAL_HI,msg);
  584.       }
  585.    putstring(row+=2,2,C_GENERAL_MED,sparams);
  586.    for (i = 0; i < 4; i++) {
  587.       sprintf(msg,"%3d: ",i+1);
  588.       putstring(-1,-1,C_GENERAL_MED,msg);
  589.       sprintf(msg,"%12.9f",param[i]);
  590.       putstring(-1,-1,C_GENERAL_HI,msg);
  591.       }
  592.  
  593.    putstring(row+=2,2,C_GENERAL_MED,siteration_maximum);
  594.    sprintf(msg,"%d",maxit);
  595.    putstring(-1,-1,C_GENERAL_HI,msg);
  596.    putstring(-1,-1,C_GENERAL_MED,seffective_bailout);
  597.    sprintf(msg,"%f",rqlim);
  598.    putstring(-1,-1,C_GENERAL_HI,msg);
  599.  
  600.    if (fractype == PLASMA) {
  601.       putstring(++row,2,C_GENERAL_MED,scurrent_rseed);
  602.       sprintf(msg,"%d",rseed);
  603.       putstring(-1,-1,C_GENERAL_HI,msg);
  604.       }
  605.  
  606.    if(invert) {
  607.       extern double f_radius,f_xcenter,f_ycenter;
  608.       putstring(++row,2,C_GENERAL_MED,sinversion_radius);
  609.       sprintf(msg,"%12.9f",f_radius);
  610.       putstring(-1,-1,C_GENERAL_HI,msg);
  611.       putstring(-1,-1,C_GENERAL_MED,sxcenter);
  612.       sprintf(msg,"%12.9f",f_xcenter);
  613.       putstring(-1,-1,C_GENERAL_HI,msg);
  614.       putstring(-1,-1,C_GENERAL_MED,sycenter);
  615.       sprintf(msg,"%12.9f",f_ycenter);
  616.       putstring(-1,-1,C_GENERAL_HI,msg);
  617.       }
  618.  
  619.    if ((row += 2) < 23) ++row;
  620. waitforkey:
  621.    putstringcenter(row,0,80,C_GENERAL_LO,
  622.        "...Press any key to continue, F6 for area...");
  623.    movecursor(25,80);
  624. #ifdef XFRACT
  625.    while (keypressed()) {
  626.        getakey();
  627.    }
  628. #endif
  629.    key = getakeynohelp();
  630.    if (key==F6) {
  631.        unstackscreen();
  632.        area();
  633.        stackscreen();
  634. /*       goto waitforkey;*/
  635.         goto top;
  636.    }
  637.    unstackscreen();
  638.    timer_start = clock_ticks(); /* tab display was "time out" */
  639.    return(0);
  640. }
  641.  
  642. static void area()
  643. {
  644.     /* apologies to UNIX folks, we PC guys have to save near space */
  645.     static char far warning[] = {"Warning: inside may not be unique\n"};
  646.     static char far total_area[] = {".  Total area "}; 
  647.     char far *msg;
  648.     int x,y;
  649.     char buf[160];
  650.     long cnt=0;
  651.     if (inside<0) {
  652.       static char far msg[] = {"Need solid inside to compute area"};
  653.       stopmsg(0,msg);
  654.       return;
  655.     }
  656.     for (y=0;y<ydots;y++) {
  657.       for (x=0;x<xdots;x++) {
  658.           if (getcolor(x,y)==inside) {
  659.               cnt++;
  660.           }
  661.       }
  662.     }
  663.     if (inside>0 && outside<0 && maxit>inside) {
  664.       msg = warning;
  665.     } else {
  666.       msg = (char far *)"";
  667.     }
  668. #ifndef XFRACT
  669.       sprintf(buf,"%Fs%ld inside pixels of %ld%Fs%f",
  670.               msg,cnt,(long)xdots*(long)ydots,total_area,
  671.               cnt/((float)xdots*(float)ydots)*(xxmax-xxmin)*(yymax-yymin));
  672. #else
  673.       sprintf(buf,"%s%ld inside pixels of %ld%s%f",
  674.               msg,cnt,(long)xdots*(long)ydots,total_area,
  675.               cnt/((float)xdots*(float)ydots)*(xxmax-xxmin)*(yymax-yymin));
  676. #endif
  677.     stopmsg(4,buf);
  678. }
  679.  
  680. int endswithslash(char *fl)
  681. {
  682.    int len;
  683.    len = strlen(fl);
  684.    if(len)
  685.       if(fl[--len] == SLASHC)
  686.      return(1);
  687.    return(0);
  688. }
  689.  
  690. char far insufficient_ifs_mem[]={"Insufficient memory for IFS"};
  691. /* --------------------------------------------------------------------- */
  692. int numaffine;
  693. int ifsload()            /* read in IFS parameters */
  694. {
  695.    int i;
  696.    FILE *ifsfile;
  697.    char buf[201];
  698.    char *bufptr;
  699.    extern float tstack[];    /* shared temp */
  700.    int ret,rowsize;
  701.  
  702.    if (ifs_defn) { /* release prior parms */
  703.       farmemfree((char far *)ifs_defn);
  704.       ifs_defn = NULL;
  705.       }
  706.  
  707.    ifs_changed = ifs_type = 0;
  708.    rowsize = IFSPARM;
  709.    if (find_file_item(IFSFileName,IFSName,&ifsfile) < 0)
  710.       return(-1);
  711.  
  712.    fgets(buf,200,ifsfile);
  713.    strlwr(buf);
  714.    bufptr = &buf[0];
  715.    while (*bufptr) {
  716.       if (strncmp(bufptr,"(3d)",4) == 0) {
  717.      ifs_type = 1;
  718.      rowsize = IFS3DPARM;
  719.      }
  720.       ++bufptr;
  721.       }
  722.  
  723.    for (i = 0; i < (NUMIFS+1)*IFS3DPARM; ++i)
  724.       tstack[i] = 0.0;
  725.    i = ret = 0;
  726.    while (fscanf(ifsfile," %f ",&tstack[i])) {
  727.       if (++i >= NUMIFS*rowsize) {
  728.       static char far msg[]={"IFS definition has too many lines"};
  729.      stopmsg(0,msg);
  730.      ret = -1;
  731.      break;
  732.      }
  733.       }
  734.    if ((i % rowsize) != 0 || getc(ifsfile) != '}') {
  735.       static char far msg[]={"invalid IFS definition"};
  736.       stopmsg(0,msg);
  737.       ret = -1;
  738.       }
  739.    if (i == 0 && ret == 0) {
  740.       static char far msg[]={"Empty IFS definition"};
  741.       stopmsg(0,msg);
  742.       ret = -1;
  743.       }
  744.    fclose(ifsfile);
  745.  
  746.    if (ret == 0) {
  747.       numaffine = i;
  748.       if ((ifs_defn = (float far *)farmemalloc(
  749.             (long)((NUMIFS+1)*IFS3DPARM*sizeof(float)))) == NULL) {
  750.      stopmsg(0,insufficient_ifs_mem);
  751.      ret = -1;
  752.      }
  753.       else
  754.      for (i = 0; i < (NUMIFS+1)*IFS3DPARM; ++i)
  755.         ifs_defn[i] = tstack[i];
  756.    }
  757.    return(ret);
  758. }
  759.  
  760. int find_file_item(char *filename,char *itemname,FILE **infile)
  761. {
  762.    char tmpname[41];
  763.    long notepoint;
  764.    char buf[201];
  765.    int c;
  766.    if ((*infile = fopen(filename,"rt")) == NULL) {
  767.       sprintf(buf,s_cantopen,filename);
  768.       stopmsg(0,buf);
  769.       return(-1);
  770.       }
  771.  
  772.    while (1) {
  773.       while ((c = getc(*infile)) == ' ' || c == '\t' || c == '\n') { }
  774.       if (c == EOF) break;
  775.       if (c == ';') {
  776.      while ((c = fgetc(*infile)) != '\n' && c != EOF) { }
  777.      if (c == EOF) break;
  778.      continue;
  779.      }
  780.       notepoint = ftell(*infile) - 1;
  781.       ungetc(c,*infile);
  782.       if (fscanf(*infile," %40[^ \n\t({]",tmpname) == EOF) break;
  783.       while ((c = getc(*infile)) != EOF && c != '{' && c != '\n') { }
  784.       if (c == EOF) break;
  785.       if (c == '{') {
  786.      if (stricmp(tmpname,itemname) == 0) {
  787.         fseek(*infile,notepoint,SEEK_SET);
  788.         return(0);
  789.         }
  790.      while ((c = getc(*infile)) != '}' && c != EOF) { }
  791.      if (c == EOF) break;
  792.      }
  793.       }
  794.    fclose(*infile);
  795.    sprintf(buf,"'%s' definition not found",itemname);
  796.    stopmsg(0,buf);
  797.    return(-1);
  798. }
  799.  
  800. int file_gets(char *buf,int maxlen,FILE *infile)
  801. {
  802.    int len,c;
  803.    /* similar to 'fgets', but file may be in either text or binary mode */
  804.    /* returns -1 at eof, length of string otherwise */
  805.    if (feof(infile)) return -1;
  806.    len = 0;
  807.    while (len < maxlen) {
  808.       if ((c = getc(infile)) == EOF || c == '\032') {
  809.      if (len) break;
  810.      return -1;
  811.      }
  812.       if (c == '\n') break;             /* linefeed is end of line */
  813.       if (c != '\r') buf[len++] = c;    /* ignore c/r */
  814.       }
  815.    buf[len] = 0;
  816.    return len;
  817. }
  818.  
  819. int first_err = 1;
  820.  
  821. #ifndef XFRACT
  822. #ifdef WINFRACT
  823. /* call this something else to dodge the QC4WIN bullet... */
  824. int win_matherr( struct exception *except )
  825. #else
  826. int matherr( struct exception *except )
  827. #endif
  828. {
  829.     extern int debugflag;
  830.     static char far msg[]={"Math error, but we'll try to keep going"};
  831.     if(first_err)
  832.     {
  833.        if(debugflag == 4000)stopmsg(0,msg);
  834.        first_err = 0;
  835.     }
  836.     if(debugflag)
  837.     {
  838.        static int ct = 0;
  839.        static FILE *fp=NULL;
  840.        if(fp==NULL)
  841.       fp = fopen("matherr","w");
  842.        if(ct++ < 100)
  843.        {
  844.       fprintf(fp,"err:  %d\nname: %s\narg:  %le\n",
  845.           except->type, except->name, except->arg1);
  846.       fflush(fp);
  847.        }
  848.     }
  849.     if( except->type == DOMAIN )
  850.     {
  851.     char buf[40];
  852.     sprintf(buf,"%le",except->arg1);
  853.     /* This test may be unnecessary - from my experiments if the
  854.        argument is too large or small the error is TLOSS not DOMAIN */
  855.     if(strstr(buf,"IN")||strstr(buf,"NAN"))  /* trashed arg? */
  856.                /* "IND" with MSC, "INF" with BC++ */
  857.     {
  858.        if( strcmp( except->name, "sin" ) == 0 )
  859.        {
  860.           except->retval = 0.0;
  861.           return(1);
  862.        }
  863.        else if( strcmp( except->name, "cos" ) == 0 )
  864.        {
  865.           except->retval = 1.0;
  866.           return(1);
  867.        }
  868.        else if( strcmp( except->name, "log" ) == 0 )
  869.        {
  870.           except->retval = 1.0;
  871.           return(1);
  872.        }
  873.        }
  874.     }
  875.     if( except->type == TLOSS )
  876.     {
  877.        /* try valiantly to keep going */
  878.        if( strcmp( except->name, "sin" ) == 0 )
  879.        {
  880.           except->retval = 0.5;
  881.           return(1);
  882.        }
  883.        else if( strcmp( except->name, "cos" ) == 0 )
  884.        {
  885.           except->retval = 0.5;
  886.           return(1);
  887.        }
  888.     }
  889.     /* shucks, no idea what went wrong, but our motto is "keep going!" */
  890.     except->retval = 1.0;
  891.     return(1);
  892. }
  893. #endif
  894.  
  895. void roundfloatd(double *x) /* make double converted from float look ok */
  896. {
  897.    char buf[30];
  898.    sprintf(buf,"%-10.7g",*x);
  899.    *x = atof(buf);
  900. }
  901.  
  902. /* fake a keystroke, returns old pending key */
  903. int ungetakey(int key)
  904. {
  905.    int old;
  906.    extern int keybuffer;
  907.    old = keybuffer;
  908.    keybuffer = key;
  909.    return(old);
  910. }
  911.  
  912. /* use this indirect aproach so that we can put GIFVIEW.C in an overlay */
  913.  
  914. int gifview()
  915. {
  916.     return(gifview1());
  917. }
  918.