home *** CD-ROM | disk | FTP | other *** search
/ Mega A/V / mega_av.zip / mega_av / GRAPHUTL / FRPOR172.ZIP / MISCRES.C < prev    next >
C/C++ Source or Header  |  1992-02-19  |  25KB  |  873 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. #else
  13. #include <varargs.h>
  14. #endif
  15. #include <math.h>
  16. #ifdef __TURBOC__
  17. #include <dir.h>
  18. #endif
  19. #include "fractint.h"
  20. #include "fractype.h"
  21. #include "helpdefs.h"
  22.  
  23. /* routines in this module    */
  24.  
  25. extern    void restore_active_ovly(void );
  26. extern    void findpath(char *filename,char *fullpathname);
  27. extern    void notdiskmsg(void );
  28. extern    int cvtcentermag(double *Xctr,double *Yctr,double *Magnification);
  29. extern    void updatesavename(char *name);
  30. extern    int check_writefile(char *name,char *ext);
  31. extern    int check_key(void );
  32. #ifndef XFRACT
  33. extern    int timer(int timertype,int(*subrtn)(),...);
  34. #else
  35. extern  int timer();
  36. #endif
  37. extern    void showtrig(char *buf);
  38. extern    int set_trig_array(int k,char *name);
  39. extern    void set_trig_pointers(int which);
  40. extern    int tab_display(void );
  41. extern    int endswithslash(char *fl);
  42. extern    int ifsload(void);
  43. extern    int find_file_item(char *filename,char *itemname,FILE **infile);
  44. extern    int file_gets(char *buf,int maxlen,FILE *infile);
  45. extern    void roundfloatd(double *);
  46.  
  47. static    void trigdetails(char *);
  48.  
  49. int active_ovly = -1;
  50. long timer_start,timer_interval;    /* timer(...) start & total */
  51.  
  52. extern char IFSFileName[80];
  53. extern char IFSName[40];
  54. extern float far *ifs_defn;
  55. extern int  ifs_changed;
  56. extern int  ifs_type;
  57.  
  58. extern char temp[], temp1[256];   /* temporary strings          */
  59.  
  60. extern int  active_ovly;
  61. extern int  xdots, ydots;
  62. extern int  dotmode;
  63. extern int  show_orbit;
  64. extern int  timerflag;
  65. extern int  debugflag;
  66. extern int  maxit;
  67. extern int  fractype;
  68. extern int  got_status,curpass,totpasses,currow,curcol;
  69. extern int  fileydots;
  70. extern int  xxstart,xxstop,yystart,yystop;
  71. extern int  display3d;
  72. extern char overwrite;
  73.  
  74.  
  75. /* TW's static string consolidation campaign to help brain-dead compilers */
  76. char s_cantopen[]       = {"Can't open %s"};
  77. char s_cantwrite[]      = {"Can't write %s"};
  78. char s_cantcreate[]     = {"Can't create %s"};
  79. char s_cantunderstand[] = {"Can't understand %s"};
  80. char s_cantfind[]       = {"Can't find %s"};
  81.  
  82. /* call next when returning from resident routine and unsure whether
  83.    caller is an overlay which has been displaced */
  84. void restore_active_ovly()
  85. {
  86.    switch (active_ovly) {
  87.       case OVLY_MISCOVL:  miscovl_overlay();  break;
  88.       case OVLY_CMDFILES: cmdfiles_overlay(); break;
  89.       case OVLY_HELP:      help_overlay();     break;
  90.       case OVLY_PROMPTS:  prompts_overlay();  break;
  91.       case OVLY_LOADFILE: loadfile_overlay(); break;
  92.       case OVLY_ROTATE:   rotate_overlay();   break;
  93.       case OVLY_PRINTER:  printer_overlay();  break;
  94.       case OVLY_LINE3D:   line3d_overlay();   break;
  95.       case OVLY_ENCODER:  encoder_overlay();  break;
  96.       case OVLY_CALCFRAC: calcfrac_overlay(); break;
  97.       case OVLY_INTRO:      intro_overlay();    break;
  98.       }
  99. }
  100.  
  101.  
  102. #ifndef XFRACT
  103. void findpath(char *filename, char *fullpathname) /* return full pathnames */
  104. {
  105.    if (filename[0] == SLASHC
  106.      || (filename[0] && filename[1] == ':')) {
  107.       strcpy(fullpathname,filename);
  108.       return;
  109.       }
  110.    fullpathname[0] = 0;             /* indicate none found */
  111. #ifdef __TURBOC__                /* look for the file */
  112.    strcpy(fullpathname,searchpath(filename));
  113. #else
  114.    _searchenv(filename,"PATH",fullpathname);
  115. #endif
  116.    if (fullpathname[0] != 0)            /* found it! */
  117.       if (strncmp(&fullpathname[2],SLASHSLASH,2) == 0) /* stupid klooge! */
  118.      strcpy(&fullpathname[3],filename);
  119. }
  120. #endif
  121.  
  122.  
  123. void notdiskmsg()
  124. {
  125. static char far sorrymsg[]={
  126. "I'm sorry, but because of its random-screen-access algorithms, this\n\
  127. type cannot be created using a real-disk based 'video' mode."};
  128.    stopmsg(1,sorrymsg);
  129. }
  130.  
  131.  
  132. /* convert corners to center/mag */
  133. int cvtcentermag(double *Xctr, double *Yctr, double *Magnification)
  134. {
  135.    extern double xxmax,xxmin,yymax,yymin,xx3rd,yy3rd;
  136.    double Width, Height, Radius, Ratio;
  137.    Width  = xxmax - xxmin;
  138.    Height = yymax - yymin;
  139.    Ratio = Height / Width;
  140.    if(xx3rd != xxmin || yy3rd != yymin || Width < 0
  141.      || (Width > 1e-8 && (Ratio <= 0.74 || Ratio >= 0.76))
  142.      || Ratio < 0.66 || Ratio > 0.84)
  143.       return(0);
  144.    /* calculate center and magnification */
  145.    Radius = Height / 2.0;
  146.    *Xctr = xxmin + (Width / 2.0);
  147.    *Yctr = yymin + Radius;
  148.    *Magnification = 1.0 / Radius;
  149.    return(1);
  150. }
  151.  
  152.  
  153. void updatesavename(char *filename) /* go to the next file name */
  154. {
  155.    char *save, *hold;
  156.    char name[80],suffix[80];
  157.    char *dotptr;
  158.  
  159.    strcpy(name,filename);
  160.    suffix[0] = 0;
  161.    if ((dotptr = strrchr(name,'.')) != NULL
  162.      && dotptr > strrchr(name,SLASHC)) {
  163.       strcpy(suffix,dotptr);
  164.       *dotptr = 0;
  165.       }
  166.  
  167.    hold = name + strlen(name) - 1; /* start at the end */
  168.    while(hold >= name && (*hold == ' ' || isdigit(*hold))) /* skip backwards */
  169.       hold--;
  170.    hold++;            /* recover first digit */
  171.    while (*hold == '0')         /* skip leading zeros */
  172.       hold++;
  173.    save = hold;
  174.    while (*save) {        /* check for all nines */
  175.       if (*save != '9')
  176.      break;
  177.       save++;
  178.       }
  179.    if (!*save)            /* if the whole thing is nines then back */
  180.       save = hold - 1;        /* up one place. Note that this will eat */
  181.                 /* your last letter if you go to far.     */
  182.    else
  183.       save = hold;
  184.    sprintf(save,"%d",atoi(hold)+1); /* increment the number */
  185.    strcpy(filename,name);
  186.    strcat(filename,suffix);
  187. }
  188.  
  189. int check_writefile(char *name,char *ext)
  190. {
  191.  /* after v16 release, change encoder.c to also use this routine */
  192.    char openfile[80];
  193.    char opentype[20];
  194.    int i;
  195. nextname:
  196.    strcpy(openfile,name);
  197.    strcpy(opentype,ext);
  198.    for (i = 0; i < strlen(openfile); i++)
  199.       if (openfile[i] == '.') {
  200.      strcpy(opentype,&openfile[i]);
  201.      openfile[i] = 0;
  202.      }
  203.    strcat(openfile,opentype);
  204.    if (access(openfile,0) != 0) /* file doesn't exist */
  205.    {
  206.       strcpy(name,openfile);
  207.       return 0;
  208.     }
  209.    /* file already exists */
  210.    if (overwrite == 0) {
  211.       updatesavename(name);
  212.       goto nextname;
  213.       }
  214.    return 1;
  215. }
  216.  
  217.  
  218. int check_key()
  219. {
  220.    int key;
  221.    if((key = keypressed()) != 0) {
  222.       if(key != 'o' && key != 'O') {
  223.      fflush(stdout);
  224.      return(-1);
  225.       }
  226.       getakey();
  227.       if (dotmode != 11)
  228.      show_orbit = 1 - show_orbit;
  229.    }
  230.    return(0);
  231. }
  232.  
  233.  
  234. /* timer function:
  235.      timer(0,(*fractal)())        fractal engine
  236.      timer(1,NULL,int width)        decoder
  237.      timer(2)                encoder
  238.   */
  239. #ifndef XFRACT
  240. int timer(int timertype,int(*subrtn)(),...)
  241. #else
  242. int timer(va_alist)
  243. va_dcl
  244. #endif
  245. {
  246.    va_list arg_marker;    /* variable arg list */
  247.    char *timestring;
  248.    time_t ltime;
  249.    FILE *fp;
  250.    int out;
  251.    int i;
  252.    int do_bench;
  253.  
  254. #ifndef XFRACT
  255.    va_start(arg_marker,subrtn);
  256. #else
  257.    int timertype;
  258.    int (*subrtn)();
  259.    va_start(arg_marker);
  260.    timertype = va_arg(arg_marker, int);
  261.    subrtn = ( int (*)()) va_arg(arg_marker, int);
  262. #endif
  263.  
  264.    do_bench = timerflag; /* record time? */
  265.    if (timertype == 2)     /* encoder, record time only if debug=200 */
  266.       do_bench = (debugflag == 200);
  267.    if(do_bench)
  268.       fp=fopen("bench","a");
  269.    timer_start = clock();
  270.    switch(timertype) {
  271.       case 0:
  272.      out = (*subrtn)();
  273.      break;
  274.       case 1:
  275.      i = va_arg(arg_marker,int);
  276.      out = decoder(i);         /* not indirect, safer with overlays */
  277.      break;
  278.       case 2:
  279.      out = encoder();         /* not indirect, safer with overlays */
  280.      break;
  281.       }
  282.    /* next assumes CLK_TCK is 10^n, n>=2 */
  283.    timer_interval = (clock() - timer_start) / (CLK_TCK/100);
  284.  
  285.    if(do_bench) {
  286.       time(<ime);
  287.       timestring = ctime(<ime);
  288.       timestring[24] = 0; /*clobber newline in time string */
  289.       switch(timertype) {
  290.      case 1:
  291.         fprintf(fp,"decode ");
  292.         break;
  293.      case 2:
  294.         fprintf(fp,"encode ");
  295.         break;
  296.      }
  297.       fprintf(fp,"%s type=%s resolution = %dx%d maxiter=%d",
  298.       timestring,
  299.       curfractalspecific->name,
  300.       xdots,
  301.       ydots,
  302.       maxit);
  303.       fprintf(fp," time= %ld.%02ld secs\n",timer_interval/100,timer_interval%100);
  304.       if(fp != NULL)
  305.      fclose(fp);
  306.       }
  307.    return(out);
  308. }
  309.  
  310.  
  311. extern void lStkSin(void) ,dStkSin(void) ,mStkSin(void) ;
  312. extern void lStkCos(void) ,dStkCos(void) ,mStkCos(void) ;
  313. extern void lStkSinh(void),dStkSinh(void),mStkSinh(void);
  314. extern void lStkCosh(void),dStkCosh(void),mStkCosh(void);
  315. extern void lStkExp(void) ,dStkExp(void) ,mStkExp(void) ;
  316. extern void lStkLog(void) ,dStkLog(void) ,mStkLog(void) ;
  317. extern void lStkSqr(void) ,dStkSqr(void) ,mStkSqr(void) ;
  318. extern void lStkRecip(void) ,dStkRecip(void) ,mStkRecip(void) ;
  319. extern void StkIdent(void);
  320. extern void lStkTan(void) ,dStkTan(void) ,mStkTan(void) ;
  321. extern void lStkTanh(void),dStkTanh(void),mStkTanh(void);
  322. extern void lStkCoTan(void),dStkCoTan(void),mStkCoTan(void);
  323. extern void lStkCoTanh(void),dStkCoTanh(void),mStkCoTanh(void);
  324. extern void lStkCosXX(void) ,dStkCosXX(void) ,mStkCosXX(void) ;
  325.  
  326. BYTE trigndx[] = {SIN,SQR,SINH,COSH};
  327. void (*ltrig0)() = lStkSin;
  328. void (*ltrig1)() = lStkSqr;
  329. void (*ltrig2)() = lStkSinh;
  330. void (*ltrig3)() = lStkCosh;
  331. void (*dtrig0)() = dStkSin;
  332. void (*dtrig1)() = dStkSqr;
  333. void (*dtrig2)() = dStkSinh;
  334. void (*dtrig3)() = dStkCosh;
  335. void (*mtrig0)() = mStkSin;
  336. void (*mtrig1)() = mStkSqr;
  337. void (*mtrig2)() = mStkSinh;
  338. void (*mtrig3)() = mStkCosh;
  339.  
  340. struct trig_funct_lst trigfn[] =
  341. /* changing the order of these alters meaning of *.fra file */
  342. /* maximum 6 characters in function names or recheck all related code */
  343. {
  344.    {"sin",   lStkSin,   dStkSin,   mStkSin   },
  345.    {"cosxx", lStkCosXX, dStkCosXX, mStkCosXX },
  346.    {"sinh",  lStkSinh,  dStkSinh,  mStkSinh  },
  347.    {"cosh",  lStkCosh,  dStkCosh,  mStkCosh  },
  348.    {"exp",   lStkExp,   dStkExp,   mStkExp   },
  349.    {"log",   lStkLog,   dStkLog,   mStkLog   },
  350.    {"sqr",   lStkSqr,   dStkSqr,   mStkSqr   },
  351.    {"recip", lStkRecip, dStkRecip, mStkRecip }, /* from recip on new in v16 */
  352.    {"ident", StkIdent,  StkIdent,  StkIdent  },
  353.    {"cos",   lStkCos,   dStkCos,   mStkCos   },
  354.    {"tan",   lStkTan,   dStkTan,   mStkTan   },
  355.    {"tanh",  lStkTanh,  dStkTanh,  mStkTanh  },
  356.    {"cotan", lStkCoTan, dStkCoTan, mStkCoTan },
  357.    {"cotanh",lStkCoTanh,dStkCoTanh,mStkCoTanh},
  358. };
  359. int numtrigfn = sizeof(trigfn)/sizeof(struct trig_funct_lst);
  360.  
  361. void showtrig(char *buf) /* return display form of active trig functions */
  362. {
  363.    char tmpbuf[30];
  364.    *buf = 0; /* null string if none */
  365.    trigdetails(tmpbuf);
  366.    if (tmpbuf[0])
  367.       sprintf(buf," function=%s",tmpbuf);
  368. }
  369.  
  370. static void trigdetails(char *buf)
  371. {
  372.    extern char maxfn;
  373.    int i, numfn;
  374.    char tmpbuf[20];
  375.    numfn = (curfractalspecific->flags >> 6) & 7;
  376.    if(curfractalspecific == &fractalspecific[FORMULA] ||
  377.       curfractalspecific == &fractalspecific[FFORMULA]    )
  378.       numfn = maxfn;
  379.    *buf = 0; /* null string if none */
  380.    if (numfn>0) {
  381.       strcpy(buf,trigfn[trigndx[0]].name);
  382.       i = 0;
  383.       while(++i < numfn) {
  384.      sprintf(tmpbuf,"/%s",trigfn[trigndx[i]].name);
  385.      strcat(buf,tmpbuf);
  386.      }
  387.       }
  388. }
  389.  
  390. /* set array of trig function indices according to "function=" command */
  391. int set_trig_array(int k, char *name)
  392. {
  393.    char trigname[10];
  394.    int i;
  395.    char *slash;
  396.    strncpy(trigname,name,6);
  397.    trigname[6] = 0; /* safety first */
  398.  
  399.    if ((slash = strchr(trigname,'/')))
  400.       *slash = 0;
  401.  
  402.    strlwr(trigname);
  403.  
  404.    for(i=0;i<numtrigfn;i++)
  405.    {
  406.       if(strcmp(trigname,trigfn[i].name)==0)
  407.       {
  408.      trigndx[k] = i;
  409.      set_trig_pointers(k);
  410.      break;
  411.       }
  412.    }
  413.    return(0);
  414. }
  415. void set_trig_pointers(int which)
  416. {
  417.   /* set trig variable functions to avoid array lookup time */
  418.    int i;
  419.    switch(which)
  420.    {
  421.    case 0:
  422.       ltrig0 = trigfn[trigndx[0]].lfunct;
  423.       dtrig0 = trigfn[trigndx[0]].dfunct;
  424.       mtrig0 = trigfn[trigndx[0]].mfunct;
  425.       break;
  426.    case 1:
  427.       ltrig1 = trigfn[trigndx[1]].lfunct;
  428.       dtrig1 = trigfn[trigndx[1]].dfunct;
  429.       mtrig1 = trigfn[trigndx[1]].mfunct;
  430.       break;
  431.    case 2:
  432.       ltrig2 = trigfn[trigndx[2]].lfunct;
  433.       dtrig2 = trigfn[trigndx[2]].dfunct;
  434.       mtrig2 = trigfn[trigndx[2]].mfunct;
  435.       break;
  436.    case 3:
  437.       ltrig3 = trigfn[trigndx[3]].lfunct;
  438.       dtrig3 = trigfn[trigndx[3]].dfunct;
  439.       mtrig3 = trigfn[trigndx[3]].mfunct;
  440.       break;
  441.    default: /* do 'em all */
  442.       for(i=0;i<4;i++)
  443.      set_trig_pointers(i);
  444.       break;
  445.    }
  446. }
  447.  
  448.  
  449. int tab_display()    /* display the status of the current image */
  450. {
  451.    extern char floatflag;
  452.    extern char usr_floatflag;
  453.    extern double xxmin, xxmax, xx3rd, yymin, yymax, yy3rd;
  454.    extern double param[4];
  455.    extern double rqlim;
  456.    extern long calctime, timer_start;
  457.    extern int  calc_status;
  458.    extern char FormName[];
  459.    extern char LName[];
  460.    extern char IFSName[];
  461.    extern int  rseed;
  462.    extern int  invert;
  463.    int row, i, j;
  464.    double Xctr, Yctr, Magnification;
  465.    char msg[81];
  466.    char *msgptr;
  467.  
  468.    if (calc_status < 0)     /* no active fractal image */
  469.       return(0);        /* (no TAB on the credits screen) */
  470.    if (calc_status == 1)    /* next assumes CLK_TCK is 10^n, n>=2 */
  471.       calctime += (clock() - timer_start) / (CLK_TCK/100);
  472.    stackscreen();
  473.    helptitle();
  474.    setattr(1,0,C_GENERAL_MED,24*80); /* init rest to background */
  475.  
  476.    row = 2;
  477.    putstring(row,2,C_GENERAL_MED,"Fractal type:");
  478.    if (display3d > 0)
  479.       putstring(row,16,C_GENERAL_HI,"3D Transform");
  480.    else {
  481.       putstring(row,16,C_GENERAL_HI,
  482.        curfractalspecific->name[0] == '*' ?
  483.          &curfractalspecific->name[1] :
  484.          curfractalspecific->name);
  485.       i = 0;
  486.       if (fractype == FORMULA || fractype == FFORMULA)
  487.       {
  488.      putstring(row+1,16,C_GENERAL_HI,FormName);
  489.       i = strlen(FormName)+1;
  490.       }
  491.       trigdetails(msg);
  492.       putstring(row+1,16+i,C_GENERAL_HI,msg);
  493.       if (fractype == LSYSTEM)
  494.      putstring(row+1,16,C_GENERAL_HI,LName);
  495.       if (fractype == IFS || fractype == IFS3D)
  496.      putstring(row+1,16,C_GENERAL_HI,IFSName);
  497.       }
  498.    switch (calc_status) {
  499.       case 0:  msgptr = "Parms chgd since generated";
  500.            break;
  501.       case 1:  msgptr = "Still being generated";
  502.            break;
  503.       case 2:  msgptr = "Interrupted, resumable";
  504.            break;
  505.       case 3:  msgptr = "Interrupted, non-resumable";
  506.            break;
  507.       case 4:  msgptr = "Image completed";
  508.            break;
  509.       default: msgptr = "";
  510.       }
  511.    putstring(row,45,C_GENERAL_HI,msgptr);
  512.    if (helpmode == HELPCYCLING)
  513.       putstring(row+1,45,C_GENERAL_HI,"You are in color-cycling mode");
  514.    row += 2;
  515.  
  516.     i = j = 0;
  517.     if (display3d > 0) {
  518.        if (usr_floatflag)
  519.       j = 1;
  520.        }
  521.     else
  522.        if (floatflag)
  523.       j = (usr_floatflag) ? 1 : 2;
  524.     if (j) {
  525.        putstring(row,45,C_GENERAL_HI,"Floating-point");
  526.        putstring(-1,-1,C_GENERAL_HI,(j == 1) ? " flag is activated"
  527.                          : " in use (required)");
  528.       i = 1;
  529.       }
  530.    if (calc_status == 1 || calc_status == 2)
  531.       if (curfractalspecific->flags&INFCALC) {
  532.      putstring(row,2,C_GENERAL_HI,"Note: this type runs forever.");
  533.      i = 1;
  534.      }
  535.    row += i;
  536.  
  537.    if (calc_status == 1 || calc_status == 2)
  538.       if (curfractalspecific->flags&NORESUME)
  539.       {
  540.      static char far msg[] = {"Note: can't resume this type after interrupts other than <tab> and <F1>"};
  541.      putstring(row++,2,C_GENERAL_HI,msg);
  542.       }
  543.    ++row;
  544.  
  545.    if (got_status >= 0 && (calc_status == 1 || calc_status == 2)) {
  546.       switch (got_status) {
  547.      case 0:
  548.         sprintf(msg,"%d Pass Mode",totpasses);
  549.         putstring(row,2,C_GENERAL_HI,msg);
  550.         break;
  551.      case 1:
  552.         putstring(row,2,C_GENERAL_HI,"Solid Guessing");
  553.         break;
  554.      case 2:
  555.         putstring(row,2,C_GENERAL_HI,"Boundary Tracing");
  556.         break;
  557.      case 3:
  558.         sprintf(msg,"Processing row %d (of %d) of input image",currow,fileydots);
  559.         putstring(row,2,C_GENERAL_HI,msg);
  560.         break;
  561.      case 4:
  562.         putstring(row,2,C_GENERAL_HI,"Tesseral");
  563.         break;
  564.      }
  565.       ++row;
  566.       if (got_status != 3) {
  567.      sprintf(msg,"Working on block (y,x) [%d,%d]...[%d,%d], ",
  568.         yystart,xxstart,yystop,xxstop);
  569.      putstring(row,2,C_GENERAL_MED,msg);
  570.      if (got_status == 2 || got_status == 4) { /* btm or tesseral */
  571.         putstring(-1,-1,C_GENERAL_MED,"at ");
  572.         sprintf(msg,"[%d,%d]",currow,curcol);
  573.         putstring(-1,-1,C_GENERAL_HI,msg);
  574.         }
  575.      else {
  576.         if (totpasses > 1) {
  577.            putstring(-1,-1,C_GENERAL_MED,"pass ");
  578.            sprintf(msg,"%d",curpass);
  579.            putstring(-1,-1,C_GENERAL_HI,msg);
  580.            putstring(-1,-1,C_GENERAL_MED," of ");
  581.            sprintf(msg,"%d",totpasses);
  582.            putstring(-1,-1,C_GENERAL_HI,msg);
  583.            putstring(-1,-1,C_GENERAL_MED,", ");
  584.            }
  585.         putstring(-1,-1,C_GENERAL_MED,"at row ");
  586.         sprintf(msg,"%d",currow);
  587.         putstring(-1,-1,C_GENERAL_HI,msg);
  588.         }
  589.      ++row;
  590.      }
  591.       }
  592.    putstring(row,2,C_GENERAL_MED,"Calculation time:");
  593.    sprintf(msg,"%3ld:%02ld:%02ld.%02ld", calctime/360000,
  594.       (calctime%360000)/6000, (calctime%6000)/100, calctime%100);
  595.    putstring(-1,-1,C_GENERAL_HI,msg);
  596.    row += 2;
  597.  
  598.    if (videoentry.xdots) {
  599.       sprintf(msg,"Video: %dx%dx%d %s %s",
  600.           videoentry.xdots, videoentry.ydots, videoentry.colors,
  601.           videoentry.name, videoentry.comment);
  602.       putstring(row,2,C_GENERAL_MED,msg);
  603.       }
  604.    ++row;
  605.  
  606.    putstring(row,2,C_GENERAL_MED,"Corners:                X                     Y");
  607.    putstring(++row,3,C_GENERAL_MED,"top-left");
  608.    sprintf(msg,"%20.16f  %20.16f",xxmin,yymax);
  609.    putstring(-1,17,C_GENERAL_HI,msg);
  610.    putstring(++row,3,C_GENERAL_MED,"bottom-right");
  611.    sprintf(msg,"%20.16f  %20.16f",xxmax,yymin);
  612.    putstring(-1,17,C_GENERAL_HI,msg);
  613.    adjust_corner(); /* make bottom left exact if very near exact */
  614.    if (cvtcentermag(&Xctr, &Yctr, &Magnification)) {
  615.       putstring(row+=2,2,C_GENERAL_MED,"Center: ");
  616.       sprintf(msg,"%20.16f %20.16f",Xctr,Yctr);
  617.       putstring(-1,-1,C_GENERAL_HI,msg);
  618.       putstring(-1,-1,C_GENERAL_MED,"  Mag: ");
  619.       if (Magnification < 1e6)
  620.      sprintf(msg,"%20.14f",Magnification);
  621.       else if (Magnification < 1e12)
  622.      sprintf(msg,"%20.8f",Magnification);
  623.       else
  624.      sprintf(msg,"%20.2f",Magnification);
  625.       putstring(-1,-1,C_GENERAL_HI,msg);
  626.       }
  627.    else if (xxmin != xx3rd || yymin != yy3rd) {
  628.       putstring(++row,3,C_GENERAL_MED,"bottom-left");
  629.       sprintf(msg,"%20.16f  %20.16f",xx3rd,yy3rd);
  630.       putstring(-1,17,C_GENERAL_HI,msg);
  631.       }
  632.    putstring(row+=2,2,C_GENERAL_MED,"Params,");
  633.    for (i = 0; i < 4; i++) {
  634.       sprintf(msg,"%3d: ",i+1);
  635.       putstring(-1,-1,C_GENERAL_MED,msg);
  636.       sprintf(msg,"%12.9f",param[i]);
  637.       putstring(-1,-1,C_GENERAL_HI,msg);
  638.       }
  639.  
  640.    putstring(row+=2,2,C_GENERAL_MED,"Iteration maximum: ");
  641.    sprintf(msg,"%d",maxit);
  642.    putstring(-1,-1,C_GENERAL_HI,msg);
  643.    putstring(-1,-1,C_GENERAL_MED,"     Effective bailout: ");
  644.    sprintf(msg,"%f",rqlim);
  645.    putstring(-1,-1,C_GENERAL_HI,msg);
  646.  
  647.    if (fractype == PLASMA) {
  648.       putstring(++row,2,C_GENERAL_MED,"Current 'rseed': ");
  649.       sprintf(msg,"%d",rseed);
  650.       putstring(-1,-1,C_GENERAL_HI,msg);
  651.       }
  652.  
  653.    if(invert) {
  654.       extern double f_radius,f_xcenter,f_ycenter;
  655.       putstring(++row,2,C_GENERAL_MED,"Inversion radius: ");
  656.       sprintf(msg,"%12.9f",f_radius);
  657.       putstring(-1,-1,C_GENERAL_HI,msg);
  658.       putstring(-1,-1,C_GENERAL_MED,"  xcenter: ");
  659.       sprintf(msg,"%12.9f",f_xcenter);
  660.       putstring(-1,-1,C_GENERAL_HI,msg);
  661.       putstring(-1,-1,C_GENERAL_MED,"  ycenter: ");
  662.       sprintf(msg,"%12.9f",f_ycenter);
  663.       putstring(-1,-1,C_GENERAL_HI,msg);
  664.       }
  665.  
  666.    if ((row += 2) < 23) ++row;
  667.    putstringcenter(row,0,80,C_GENERAL_LO,"...Press any key to continue...");
  668.    movecursor(25,80);
  669. #ifdef XFRACT
  670.    while (keypressed()) {
  671.        getakey();
  672.    }
  673. #endif
  674.    getakeynohelp();
  675.    unstackscreen();
  676.    timer_start = clock(); /* tab display was "time out" */
  677.    return(0);
  678. }
  679.  
  680.  
  681. int endswithslash(char *fl)
  682. {
  683.    int len;
  684.    len = strlen(fl);
  685.    if(len)
  686.       if(fl[--len] == SLASHC)
  687.      return(1);
  688.    return(0);
  689. }
  690.  
  691. /* --------------------------------------------------------------------- */
  692.  
  693. int ifsload()            /* read in IFS parameters */
  694. {
  695.    int i;
  696.    FILE *ifsfile;
  697.    char buf[201];
  698.    char *bufptr;
  699.    extern float dstack[];    /* 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.       dstack[i] = 0.0;
  725.    i = ret = 0;
  726.    while (fscanf(ifsfile," %f ",&dstack[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.       if ((ifs_defn = (float far *)farmemalloc(
  748.             (long)((NUMIFS+1)*IFS3DPARM*sizeof(float)))) == NULL) {
  749.      static char far msg[]={"Insufficient memory for IFS"};
  750.      stopmsg(0,msg);
  751.      ret = -1;
  752.      }
  753.       else
  754.      for (i = 0; i < (NUMIFS+1)*IFS3DPARM; ++i)
  755.         ifs_defn[i] = dstack[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. #ifndef XFRACT
  820. #ifdef WINFRACT
  821. /* call this something else to dodge the QC4WIN bullet... */
  822. int win_matherr( struct exception *except )
  823. #else
  824. int matherr( struct exception *except )
  825. #endif
  826. {
  827.     extern int debugflag;
  828.     if(debugflag)
  829.     {
  830.        static int ct = 0;
  831.        static FILE *fp=NULL;
  832.        if(fp==NULL)
  833.       fp = fopen("matherr","w");
  834.        if(ct++ < 100)
  835.        {
  836.       fprintf(fp,"err:  %d\nname: %s\narg:  %le\n",
  837.           except->type, except->name, except->arg1);
  838.       fflush(fp);
  839.        }
  840.     }
  841.     if( except->type == DOMAIN )
  842.     {
  843.     char buf[40];
  844.     sprintf(buf,"%le",except->arg1);
  845.     /* This test may be unnecessary - from my experiments if the
  846.        argument is too large or small the error is TLOSS not DOMAIN */
  847.     if(strstr(buf,"IN")||strstr(buf,"NAN"))  /* trashed arg? */
  848.                /* "IND" with MSC, "INF" with BC++ */
  849.     {
  850.        if( strcmp( except->name, "sin" ) == 0 )
  851.        {
  852.           except->retval = 0.0;
  853.           return(1);
  854.        }
  855.        else if( strcmp( except->name, "cos" ) == 0 )
  856.        {
  857.           except->retval = 1.0;
  858.           return(1);
  859.        }
  860.        }
  861.     }
  862.     return (0);
  863. }
  864. #endif
  865.  
  866. void roundfloatd(double *x) /* make double converted from float look ok */
  867. {
  868.    char buf[30];
  869.    sprintf(buf,"%-10.7g",*x);
  870.    *x = atof(buf);
  871. }
  872.  
  873.