home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / fractint / fras1611.zip / MISCOVL.C < prev    next >
Text File  |  1991-07-08  |  34KB  |  1,129 lines

  1. /*
  2.     Overlayed odds and ends that don't fit anywhere else.
  3. */
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <process.h>
  9. #include <dos.h>
  10. #include <stdarg.h>
  11. #include "fractint.h"
  12. #include "fractype.h"
  13. #include "helpdefs.h"
  14.  
  15. /* routines in this module    */
  16.  
  17. void miscovl_overlay(void);
  18. void make_batch_file(void);
  19. void shell_to_dos(void);
  20. void showfreemem(void);
  21. int  select_video_mode(int);
  22.  
  23. static void write_batch_parms(FILE *,char *,int);
  24. static void put_parm(char *parm,...);
  25.  
  26. static void put_parm_line(void);
  27. static int getprec(double,double,double);
  28. static void put_float(int,double,int);
  29. static void put_filename(char *keyword,char *fname);
  30. static void format_item(int choice,char *buf);
  31. static int check_modekey(int curkey,int choice);
  32. static int entcompare(void const *p1,void const *p2);
  33. static void update_fractint_cfg(void);
  34.  
  35. extern int  cpu;        /* cpu type            */
  36. extern int  fpu;        /* fpu type            */
  37. extern int  iit;        /* iit fpu?            */
  38. extern int  video_type;
  39. extern int  askvideo;
  40. extern char overwrite;        /* 1 means ok to overwrite */
  41. extern int  inside;        /* inside color: 1=blue     */
  42. extern int  outside;        /* outside color, if set    */
  43. extern double xxmin,xxmax,yymin,yymax,xx3rd,yy3rd; /* selected screen corners */
  44. extern double param[4];     /* up to four parameters    */
  45. extern int  finattract;     /* finite attractor option  */
  46. extern int  forcesymmetry;
  47. extern int  LogFlag;        /* non-zero if logarithmic palettes */
  48. extern int  rflag, rseed;
  49. extern int  periodicitycheck;
  50. extern int  potflag;        /* continuous potential flag */
  51. extern int  pot16bit;        /* save 16 bit values for continuous potential */
  52. extern double potparam[3];    /* three potential parameters*/
  53. extern int  fractype;        /* if == 0, use Mandelbrot  */
  54. extern unsigned char usemag;
  55. extern long delmin;
  56. extern int  maxit;        /* try this many iterations */
  57. extern int  invert;        /* non-zero if inversion active */
  58. extern double inversion[];
  59. extern int  decomp[];
  60. extern int  distest;        /* non-zero if distance estimator   */
  61. extern int  distestwidth;
  62. extern int  init3d[20];     /* '3d=nn/nn/nn/...' values */
  63. extern char floatflag;        /* floating-point fractals? */
  64. extern int  usr_biomorph;
  65. extern char FormFileName[];    /* file to find (type=)formulas in */
  66. extern char FormName[];     /* Name of the Formula (if not null) */
  67. extern char LFileName[];
  68. extern char LName[];
  69. extern char IFSFileName[];
  70. extern char IFSName[];
  71. extern int  bailout;        /* user input bailout value */
  72. extern char useinitorbit;
  73. extern struct complex initorbit;
  74. extern int  display3d;        /* 3D display flag: 0 = OFF */
  75. extern int  loaded3d;
  76. extern char readname[];     /* name of fractal input file */
  77. extern int  showfile;        /* has file been displayed yet? */
  78. extern int  transparent[];
  79. extern char preview;        /* 3D preview mode flag */
  80. extern char showbox;        /* flag to show box and vector in preview */
  81. extern int  RANDOMIZE;        /* Color randomizing factor */
  82. extern int  full_color;     /* Selects full color with light source fills */
  83. extern int  Ambient;        /* Darkness of shadows in light source */
  84. extern int  haze;        /* Amount of haze to factor in in full color */
  85. extern char light_name[];    /* Name of full color .TGA file */
  86. extern int previewfactor;
  87. extern int BRIEF;
  88. extern int RAY;
  89. extern int xtrans;
  90. extern int ytrans;
  91. extern int red_crop_left;
  92. extern int red_crop_right;
  93. extern int blue_crop_left;
  94. extern int blue_crop_right;
  95. extern int red_bright;
  96. extern int blue_bright;
  97. extern int xadjust;
  98. extern int eyeseparation;
  99. extern int glassestype;
  100. extern unsigned char trigndx[];
  101. extern int rotate_lo,rotate_hi;
  102. extern int far *ranges;
  103. extern int rangeslen;
  104. extern char CommandFile[80];
  105. extern char CommandName[ITEMNAMELEN+1];
  106. extern char CommandComment1[57];
  107. extern char CommandComment2[57];
  108. extern char usr_stdcalcmode;
  109.  
  110. extern int  colorstate;     /* comments in cmdfiles */
  111. extern int  colors;
  112. extern int  gotrealdac;
  113. extern int  reallyega;
  114. extern char colorfile[];
  115. extern int  mapset;
  116. extern char MAP_name[];
  117. extern unsigned char dacbox[256][3];
  118. extern char far *mapdacbox;
  119.  
  120. extern char dstack[4096];
  121. extern char boxx[8192];
  122.  
  123. extern int fullscreen_prompt(char *hdg,int numprompts,char * far *prompts,
  124.            struct fullscreenvalues values[],int options,int fkeymask,
  125.            char far *extrainfo);
  126.  
  127. /* fullscreen_choice options */
  128. #define CHOICERETURNKEY 1
  129. #define CHOICEMENU    2
  130. #define CHOICEHELP    4
  131. int  fullscreen_choice(
  132.          int options, char *hdg, char *hdg2, char *instr, int numchoices,
  133.          char **choices, int *attributes, int boxwidth, int boxdepth,
  134.          int colwidth, int current, void (*formatitem)(),
  135.          char *speedstring, int (*speedprompt)(), int (*checkkey)());
  136.  
  137.  
  138. void miscovl_overlay() { }    /* for restore_active_ovly */
  139.  
  140. extern char s_real[];
  141. extern char s_imag[];
  142. extern char s_mult[];
  143. extern char s_sum[];
  144. extern char s_zmag[];
  145. extern char s_bof60[];
  146. extern char s_bof61[];
  147. extern char s_maxiter[];
  148.  
  149. static FILE *parmfile;
  150.  
  151. #ifdef C6
  152. #pragma optimize("e",off)  /* MSC 6.00A messes up next rtn with "e" on */
  153. #endif
  154. void make_batch_file()
  155. {
  156.    int i,numparms;
  157.    char inpcommandfile[80],inpcommandname[ITEMNAMELEN+1];
  158.    char inpcomment1[57],inpcomment2[57];
  159.    struct fullscreenvalues paramvalues[8];
  160.    char *choices[8];
  161.    int gotinfile;
  162.    char outname[81],buf[256],buf2[128];
  163.    FILE *infile;
  164.    char colorspec[14];
  165.    int maxcolor;
  166.    char *sptr,*sptr2;
  167.    int oldhelpmode;
  168.  
  169.    ENTER_OVLY(OVLY_MISCOVL);
  170.    stackscreen();
  171.    oldhelpmode = helpmode;
  172.    helpmode = HELPPARMFILE;
  173.  
  174.    strcpy(colorspec,"n");
  175.    maxcolor = colors;
  176.    if (gotrealdac && !reallyega) {
  177.       --maxcolor;
  178.       if (maxit < maxcolor) maxcolor = maxit;
  179.       if (inside  > 0 && inside    > maxcolor) maxcolor = inside;
  180.       if (outside > 0 && outside   > maxcolor) maxcolor = outside;
  181.       if (distest < 0 && 0-distest > maxcolor) maxcolor = 0-distest;
  182.       if (decomp[0] > maxcolor) maxcolor = decomp[0] - 1;
  183.       if (potflag && potparam[0] >= maxcolor) maxcolor = potparam[0];
  184.       if (++maxcolor > 256) maxcolor = 256;
  185.       if (colorstate == 0) {      /* default colors */
  186.      if (mapdacbox) {
  187.         colorspec[0] = '@';
  188.         sptr = MAP_name;
  189.         }
  190.      }
  191.       else if (colorstate == 2) { /* colors match colorfile */
  192.      colorspec[0] = '@';
  193.      sptr = colorfile;
  194.      }
  195.       else              /* colors match no .map that we know of */
  196.      colorspec[0] = 'y';
  197.       if (colorspec[0] == '@') {
  198.      if ((sptr2 = strrchr(sptr,'\\'))) sptr = sptr2 + 1;
  199.      if ((sptr2 = strrchr(sptr,':')))  sptr = sptr2 + 1;
  200.      strncpy(&colorspec[1],sptr,12);
  201.      colorspec[13] = 0;
  202.      }
  203.       }
  204.    strcpy(inpcommandfile,CommandFile);
  205.    strcpy(inpcommandname,CommandName);
  206.    strcpy(inpcomment1,CommandComment1);
  207.    strcpy(inpcomment2,CommandComment2);
  208.    if (CommandName[0] == 0)
  209.       strcpy(inpcommandname,"test");
  210.  
  211.    while (1) {
  212.  
  213. prompt_user:
  214.       choices[0] = "Parameter file";
  215.       paramvalues[0].type = 0x100+56;
  216.       paramvalues[0].uval.sbuf = inpcommandfile;
  217.       choices[1] = "Name";
  218.       paramvalues[1].type = 0x100+ITEMNAMELEN;
  219.       paramvalues[1].uval.sbuf = inpcommandname;
  220.       choices[2] = "Main comment";
  221.       paramvalues[2].type = 0x100+56;
  222.       paramvalues[2].uval.sbuf = inpcomment1;
  223.       choices[3] = "Second comment";
  224.       paramvalues[3].type = 0x100+56;;
  225.       paramvalues[3].uval.sbuf = inpcomment2;
  226.       numparms = 4;
  227.       if (gotrealdac && !reallyega) {
  228.      choices[4] = "Record colors?";
  229.      paramvalues[4].type = 0x100+13;
  230.      paramvalues[4].uval.sbuf = colorspec;
  231.      choices[5] = "    (no | yes for full info | @filename to point to a map file)";
  232.      paramvalues[5].type = '*';
  233.      choices[6] = "# of colors";
  234.      paramvalues[6].type = 'i';
  235.      paramvalues[6].uval.ival = maxcolor;
  236.      choices[7] = "    (if recording full color info)";
  237.      paramvalues[7].type = '*';
  238.      numparms = 8;
  239.      }
  240.  
  241.       if (fullscreen_prompt("Save Current Parameters",
  242.                 numparms,choices,paramvalues,0,0,NULL) < 0)
  243.      break;
  244.  
  245.       strcpy(CommandFile,inpcommandfile);
  246.       if (strchr(CommandFile,'.') == NULL)
  247.      strcat(CommandFile,".par"); /* default extension .par */
  248.       strcpy(CommandName,inpcommandname);
  249.       strcpy(CommandComment1,inpcomment1);
  250.       strcpy(CommandComment2,inpcomment2);
  251.       if (paramvalues[6].uval.ival > 0 && paramvalues[6].uval.ival <= 256)
  252.      maxcolor = paramvalues[6].uval.ival;
  253.  
  254.       strcpy(outname,CommandFile);
  255.       gotinfile = 0;
  256.       if (access(CommandFile,0) == 0) { /* file exists */
  257.      gotinfile = 1;
  258.      if (access(CommandFile,6)) {
  259.         sprintf(buf,"Can't write %s",CommandFile);
  260.         stopmsg(0,buf);
  261.         continue;
  262.         }
  263.      i = strlen(outname);
  264.      while (--i >= 0 && outname[i] != '\\')
  265.      outname[i] = 0;
  266.      strcat(outname,"fractint.tmp");
  267.      infile = fopen(CommandFile,"rt");
  268.      setvbuf(infile,dstack,_IOFBF,4096); /* improves speed */
  269.      }
  270.       if ((parmfile = fopen(outname,"wt")) == NULL) {
  271.      sprintf(buf,"Can't create %s ",outname);
  272.      stopmsg(0,buf);
  273.      if (gotinfile) fclose(infile);
  274.      continue;
  275.      }
  276.       setvbuf(infile,boxx,_IOFBF,8192); /* improves speed */
  277.  
  278.       if (gotinfile) {
  279.      while (file_gets(buf,255,infile) >= 0) {
  280.         if (strchr(buf,'{')                    /* entry heading? */
  281.           && sscanf(buf," %40[^ \t({]",buf2)
  282.           && stricmp(buf2,CommandName) == 0) { /* entry with same name */
  283.            sprintf(buf2,"File already has an entry named %s\n\
  284. Continue to replace it, Cancel to back out",CommandName);
  285.            if (stopmsg(18,buf2) < 0) {        /* cancel */
  286.           fclose(infile);
  287.           fclose(parmfile);
  288.           unlink(outname);
  289.           goto prompt_user;
  290.           }
  291.            while (strchr(buf,'}') == NULL
  292.          && file_gets(buf,255,infile) > 0 ) { } /* skip to end of set */
  293.            break;
  294.            }
  295.         fputs(buf,parmfile);
  296.         fputc('\n',parmfile);
  297.         }
  298.      }
  299.  
  300.       fprintf(parmfile,"%-19s{",CommandName);
  301.       if (CommandComment1[0]) fprintf(parmfile," ; %s",CommandComment1);
  302.       fputc('\n',parmfile);
  303.       if (CommandComment2[0])
  304.      fprintf(parmfile,"                     ; %s\n",CommandComment2);
  305.       write_batch_parms(parmfile,colorspec,maxcolor); /* write the parameters */
  306.       fprintf(parmfile,"  }\n\n");
  307.  
  308.       if (gotinfile) {    /* copy the rest of the file */
  309.      while ((i = file_gets(buf,255,infile)) == 0) { } /* skip blanks */
  310.      while (i >= 0) {
  311.         fputs(buf,parmfile);
  312.         fputc('\n',parmfile);
  313.         i = file_gets(buf,255,infile);
  314.         }
  315.      fclose(infile);
  316.      }
  317.       fclose(parmfile);
  318.       if (gotinfile) {    /* replace the original file with the new */
  319.      unlink(CommandFile);          /* success assumed on these lines       */
  320.      rename(outname,CommandFile); /* since we checked earlier with access */
  321.      }
  322.  
  323.       break;
  324.       }
  325.  
  326.    helpmode = oldhelpmode;
  327.    unstackscreen();
  328.    EXIT_OVLY;
  329. }
  330. #ifdef C6
  331. #pragma optimize("e",on)  /* back to normal */
  332. #endif
  333.  
  334. static struct write_batch_data { /* buffer for parms to break lines nicely */
  335.    int len;
  336.    char buf[513];
  337.    } *wbdata;
  338.  
  339. static void write_batch_parms(FILE *batch,char *colorinf,int maxcolor)
  340. {
  341.    int i,j,k;
  342.    double Xctr, Yctr, Magnification;
  343.    struct write_batch_data wb_data;
  344.    char *sptr;
  345.    char buf[81];
  346.  
  347.    wbdata = &wb_data;
  348.    wb_data.len = 0; /* force first parm to start on new line */
  349.  
  350.    if (display3d <= 0) { /* a fractal was generated */
  351.  
  352.       /****** fractal only parameters in this section *******/
  353.       put_parm(" reset");
  354.  
  355.       if (*(sptr = curfractalspecific->name) == '*') ++sptr;
  356.       put_parm( " type=%s",sptr);
  357.  
  358.       if (fractype == FORMULA || fractype == FFORMULA)
  359.      put_parm( " formulafile=%s formulaname=%s",FormFileName,FormName);
  360.       if (fractype == LSYSTEM)
  361.     put_parm( " lfile=%s lname=%s",LFileName,LName);
  362.       if (fractype == IFS || fractype == IFS3D)
  363.     put_parm( " ifsfile=%s ifs=%s",IFSFileName,IFSName);
  364.  
  365.       showtrig(buf); /* this function is in miscres.c */
  366.       if (buf[0])
  367.      put_parm(buf);
  368.  
  369.       if (usr_stdcalcmode != 'g')
  370.      put_parm(" passes=%c",usr_stdcalcmode);
  371.  
  372.       if (usemag && cvtcentermag(&Xctr, &Yctr, &Magnification)) {
  373.      put_parm(" center-mag=");
  374.      put_parm((delmin > 1000) ? "%g/%g/%g"
  375.                   : "%+20.17lf/%+20.17lf/%+20.17lf",
  376.           Xctr,Yctr,Magnification);
  377.      }
  378.       else {
  379.      int xdigits,ydigits;
  380.      put_parm( " corners=");
  381.      xdigits = getprec(xxmin,xxmax,xx3rd);
  382.      ydigits = getprec(yymin,yymax,yy3rd);
  383.      put_float(0,xxmin,xdigits);
  384.      put_float(1,xxmax,xdigits);
  385.      put_float(1,yymin,ydigits);
  386.      put_float(1,yymax,ydigits);
  387.      if (xx3rd != xxmin || yy3rd != yymin) {
  388.         put_float(1,xx3rd,xdigits);
  389.         put_float(1,yy3rd,ydigits);
  390.         }
  391.      }
  392.  
  393.       for (i = 3; i >= 0; --i)
  394.      if (param[i] != 0.0) break;
  395.       if (i >= 0) {
  396.      put_parm(" params=%.15g",param[0]);
  397.      for (j = 1; j <= i; ++j)
  398.         put_parm("/%.15g",param[j]);
  399.      }
  400.  
  401.       if(useinitorbit == 2)
  402.      put_parm( " initorbit=pixel");
  403.       else if(useinitorbit == 1)
  404.      put_parm( " initorbit=%.15g/%.15g",initorbit.x,initorbit.y);
  405.  
  406.       if (floatflag)
  407.      put_parm( " float=y");
  408.  
  409.       if (maxit != 150)
  410.      put_parm(" maxiter=%d",maxit);
  411.  
  412.       if(bailout && (potflag == 0 || potparam[2] == 0.0))
  413.      put_parm( " bailout=%d",bailout);
  414.  
  415.       if (inside != 1) {
  416.      put_parm(" inside=");
  417.      if (inside == -1)
  418.         put_parm( s_maxiter);
  419.      else if (inside == -59)
  420.         put_parm(s_zmag);
  421.      else if (inside == -60)
  422.         put_parm(s_bof60);
  423.      else if (inside == -61)
  424.         put_parm(s_bof61);
  425.      else
  426.         put_parm( "%d",inside);
  427.      }
  428.       if (outside != -1)
  429.       {
  430.      put_parm(" outside=");
  431.      if (outside == -2)
  432.         put_parm(s_real);
  433.      else if (outside == -3)
  434.         put_parm(s_imag);
  435.      else if (outside == -4)
  436.         put_parm(s_mult);
  437.      else if (outside == -5)
  438.         put_parm(s_sum);
  439.      else
  440.         put_parm( "%d",outside);
  441.       }
  442.  
  443.       if(LogFlag) {
  444.      put_parm( " logmap=");
  445.      if(LogFlag == -1)
  446.         put_parm( "old");
  447.      else if(LogFlag == 1)
  448.         put_parm( "yes");
  449.      else
  450.         put_parm( "%d", LogFlag);
  451.      }
  452.  
  453.       if (potflag) {
  454.      put_parm( " potential=%d/%d/%d",
  455.          (int)potparam[0],(int)potparam[1],(int)potparam[2]);
  456.      if(pot16bit)
  457.         put_parm( "/16bit");
  458.      }
  459.       if (invert)
  460.      put_parm( " invert=%g/%g/%g",
  461.          inversion[0], inversion[1], inversion[2]);
  462.       if (decomp[0])
  463.      put_parm( " decomp=%d", decomp[0]);
  464.       if (distest)
  465.      put_parm( " distest=%d/%d", distest, distestwidth);
  466.       if (usr_biomorph != -1)
  467.      put_parm( " biomorph=%d", usr_biomorph);
  468.       if (finattract)
  469.      put_parm(" finattract=y");
  470.  
  471.       if (forcesymmetry != 999) {
  472.      put_parm( " symmetry=");
  473.      if (forcesymmetry==XAXIS)
  474.         put_parm("xaxis");
  475.      else if(forcesymmetry==YAXIS)
  476.         put_parm("yaxis");
  477.      else if(forcesymmetry==XYAXIS)
  478.         put_parm("xyaxis");
  479.      else if(forcesymmetry==ORIGIN)
  480.         put_parm("origin");
  481.      else if(forcesymmetry==PI_SYM)
  482.         put_parm("pi");
  483.      else
  484.         put_parm("none");
  485.      }
  486.  
  487.       if (periodicitycheck != 1)
  488.      put_parm( " periodicity=%d",periodicitycheck);
  489.  
  490.       if (rflag)
  491.      put_parm( " rseed=%d",rseed);
  492.  
  493.       if (rangeslen) {
  494.      put_parm(" ranges=");
  495.      i = 0;
  496.      while (i < rangeslen) {
  497.         if (i)
  498.            put_parm("/");
  499.         if (ranges[i] == -1) {
  500.            put_parm("-%d/",ranges[++i]);
  501.            ++i;
  502.            }
  503.         put_parm("%d",ranges[i++]);
  504.         }
  505.      }
  506.       }
  507.  
  508.    if (display3d >= 1) {
  509.       /***** 3d transform only parameters in this section *****/
  510.       put_parm( " 3d=yes");
  511.       if (loaded3d == 0)
  512.      put_filename("filename",readname);
  513.       if (SPHERE) {
  514.      put_parm( " sphere=y");
  515.      put_parm( " latitude=%d/%d", THETA1, THETA2);
  516.      put_parm( " longitude=%d/%d", PHI1, PHI2);
  517.      put_parm( " radius=%d", RADIUS);
  518.      }
  519.       put_parm( " scalexyz=%d/%d", XSCALE, YSCALE);
  520.       put_parm( " roughness=%d", ROUGH);
  521.       put_parm( " waterline=%d", WATERLINE);
  522.       if (FILLTYPE)
  523.      put_parm( " filltype=%d", FILLTYPE);
  524.       if (transparent[0] || transparent[1])
  525.      put_parm( " transparent=%d/%d", transparent[0],transparent[1]);
  526.       if (preview) {
  527.      put_parm( " preview=y");
  528.      if (showbox)
  529.         put_parm( " showbox=y");
  530.      put_parm( " coarse=%d",previewfactor);
  531.      }
  532.       if (RAY) {
  533.      put_parm( " ray=%d",RAY);
  534.      if (BRIEF)
  535.         put_parm(" brief=y");
  536.      }
  537.       if (FILLTYPE > 4) {
  538.      put_parm( " lightsource=%d/%d/%d", XLIGHT, YLIGHT, ZLIGHT);
  539.      if (LIGHTAVG)
  540.         put_parm( " smoothing=%d", LIGHTAVG);
  541.      }
  542.       if (RANDOMIZE)
  543.      put_parm( " randomize=%d",RANDOMIZE);
  544.       if (full_color)
  545.      put_parm( " fullcolor=y");
  546.       if (Ambient)
  547.      put_parm( " ambient=%d",Ambient);
  548.       if (haze)
  549.      put_parm( " haze=%d",haze);
  550.       }
  551.  
  552.    if (display3d) {        /* universal 3d */
  553.       /***** common (fractal & transform) 3d parameters in this section *****/
  554.       if (!SPHERE || display3d < 0)
  555.      put_parm( " rotation=%d/%d/%d", XROT, YROT, ZROT);
  556.       put_parm( " perspective=%d", ZVIEWER);
  557.       put_parm( " xyshift=%d/%d", XSHIFT, YSHIFT);
  558.       if(xtrans || ytrans)
  559.      put_parm( " xyadjust=%d/%d",xtrans,ytrans);
  560.       if(glassestype) {
  561.      put_parm( " stereo=%d",glassestype);
  562.      put_parm( " interocular=%d",eyeseparation);
  563.      put_parm( " converge=%d",xadjust);
  564.      put_parm( " crop=%d/%d/%d/%d",
  565.          red_crop_left,red_crop_right,blue_crop_left,blue_crop_right);
  566.      put_parm( " bright=%d/%d",
  567.          red_bright,blue_bright);
  568.      }
  569.       }
  570.  
  571.    /***** universal parameters in this section *****/
  572.  
  573.    if (*colorinf != 'n') {
  574.       put_parm(" colors=");
  575.       if (*colorinf == '@')
  576.      put_parm(colorinf);
  577.       else {
  578.      int curc,scanc,force,diffmag;
  579.      int delta,diff1[4][3],diff2[4][3];
  580.      curc = force = 0;
  581.      while (1) {
  582.         /* emit color in rgb 3 char encoded form */
  583.         for (j = 0; j < 3; ++j) {
  584.            if ((k = dacbox[curc][j]) < 10) k += '0';
  585.            else if (k < 36)            k += ('A' - 10);
  586.            else                   k += ('_' - 36);
  587.            buf[j] = k;
  588.            }
  589.         buf[3] = 0;
  590.         put_parm(buf);
  591.         if (++curc >= maxcolor)     /* quit if done last color */
  592.            break;
  593.         /* Next a P Branderhorst special, a tricky scan for smooth-shaded
  594.            ranges which can be written as <nn> to compress .par file entry.
  595.            Method used is to check net change in each color value over
  596.            spans of 2 to 5 color numbers.  First time for each span size
  597.            the value change is noted.  After first time the change is
  598.            checked against noted change.  First time it differs, a
  599.            a difference of 1 is tolerated and noted as an alternate
  600.            acceptable change.  When change is not one of the tolerated
  601.            values, loop exits. */
  602.         if (force) {
  603.            --force;
  604.            continue;
  605.            }
  606.         scanc = curc;
  607.         while (scanc < maxcolor) {     /* scan while same diff to next */
  608.            if ((i = scanc - curc) > 3) /* check spans up to 4 steps */
  609.           i = 3;
  610.            for (k = 0; k <= i; ++k) {
  611.           for (j = 0; j < 3; ++j) { /* check pattern of chg per color */
  612.              delta = (int)dacbox[scanc][j] - (int)dacbox[scanc-k-1][j];
  613.              if (k == scanc - curc)
  614.             diff1[k][j] = diff2[k][j] = delta;
  615.              else
  616.             if (delta != diff1[k][j] && delta != diff2[k][j]) {
  617.                diffmag = abs(delta - diff1[k][j]);
  618.                if (diff1[k][j] != diff2[k][j] || diffmag != 1)
  619.                   break;
  620.                diff2[k][j] = delta;
  621.                }
  622.              }
  623.           if (j < 3) break; /* must've exited from inner loop above */
  624.           }
  625.            if (k <= i) break;   /* must've exited from inner loop above */
  626.            ++scanc;
  627.            }
  628.         /* now scanc-1 is next color which must be written explicitly */
  629.         if (scanc - curc > 2) { /* good, we have a shaded range */
  630.            if (scanc != maxcolor) {
  631.           if (diffmag < 3) {  /* not a sharp slope change? */
  632.              force = 2;       /* force more between ranges, to stop  */
  633.              --scanc;          /* "drift" when load/store/load/store/ */
  634.              }
  635.           if (k) {          /* more of the same             */
  636.              force += k;
  637.              --scanc;
  638.              }
  639.           }
  640.            if (--scanc - curc > 1) {
  641.           put_parm("<%d>",scanc-curc);
  642.           curc = scanc;
  643.           }
  644.            else           /* changed our mind */
  645.           force = 0;
  646.            }
  647.         }
  648.      }
  649.       }
  650.  
  651.    if (rotate_lo != 1 || rotate_hi != 255)
  652.       put_parm( " cyclerange=%d/%d",rotate_lo,rotate_hi);
  653.  
  654.    while (wbdata->len) /* flush the buffer */
  655.       put_parm_line();
  656. }
  657.  
  658. static void put_filename(char *keyword,char *fname)
  659. {
  660.    char *p;
  661.    if (*fname && !endswithslash(fname)) {
  662.       if ((p = strrchr(fname,'\\')))
  663.      if (*(fname = p+1) == 0) return;
  664.       put_parm(" %s=%s",keyword,fname);
  665.       }
  666. }
  667.  
  668. static void put_parm(char *parm,...)
  669. {
  670.    char *bufptr;
  671.    va_list args;
  672.    va_start(args,parm);
  673.    if (*parm == ' '             /* starting a new parm */
  674.      && wbdata->len == 0)    /* skip leading space */
  675.       ++parm;
  676.    bufptr = wbdata->buf + wbdata->len;
  677.    vsprintf(bufptr,parm,args);
  678.    while (*(bufptr++))
  679.       ++wbdata->len;
  680.    while (wbdata->len > 200)
  681.       put_parm_line();
  682. }
  683.  
  684. #define NICELINELEN 72
  685. #define MAXLINELEN  76
  686.  
  687. static void put_parm_line()
  688. {
  689.    int len,c;
  690.    if ((len = wbdata->len) > NICELINELEN) {
  691.       len = NICELINELEN+1;
  692.       while (--len != 0 && wbdata->buf[len] != ' ') { }
  693.       if (len == 0) {
  694.      len = NICELINELEN-1;
  695.      while (++len < MAXLINELEN
  696.        && wbdata->buf[len] && wbdata->buf[len] != ' ') { }
  697.      }
  698.       }
  699.    c = wbdata->buf[len];
  700.    wbdata->buf[len] = 0;
  701.    fputs("  ",parmfile);
  702.    fputs(wbdata->buf,parmfile);
  703.    if (c && c != ' ')
  704.       fputc('\\',parmfile);
  705.    fputc('\n',parmfile);
  706.    if ((wbdata->buf[len] = c) == ' ')
  707.       ++len;
  708.    wbdata->len -= len;
  709.    strcpy(wbdata->buf,wbdata->buf+len);
  710. }
  711.  
  712. static int getprec(double a,double b,double c)
  713. {
  714.    double diff,temp;
  715.    int digits;
  716.    double highv = 1.0E20;
  717.    if ((diff = fabs(a - b)) == 0.0) diff = highv;
  718.    if ((temp = fabs(a - c)) == 0.0) temp = highv;
  719.    if (temp < diff) diff = temp;
  720.    if ((temp = fabs(b - c)) == 0.0) temp = highv;
  721.    if (temp < diff) diff = temp;
  722.    digits = 5;
  723.    while (diff < 1.0 && digits < 17) {
  724.       diff *= 10;
  725.       ++digits;
  726.       }
  727.    return((digits < 6) ? 6 : digits);
  728. }
  729.  
  730. static void put_float(int slash,double fnum,int prec)
  731. {  char buf[40];
  732.    char *bptr, *dptr;
  733.    bptr = buf;
  734.    if (slash)
  735.       *(bptr++) = '/';
  736.    sprintf(bptr,"%1.*f",prec,fnum);
  737.    if ((dptr = strchr(bptr,'.'))) {
  738.       ++dptr;
  739.       bptr = buf + strlen(buf);
  740.       while (--bptr > dptr && *bptr == '0')
  741.      *bptr = 0;
  742.       }
  743.    put_parm(buf);
  744. }
  745.  
  746. void shell_to_dos()
  747. {
  748.    char *comspec;
  749.    /* from fractint.c & calls no ovlys, doesn't need ENTER_OVLY */
  750.    if ((comspec = getenv("COMSPEC")) == NULL)
  751.       printf("Cannot find COMMAND.COM.\n");
  752.    else {
  753.       putenv("PROMPT='EXIT' returns to FRACTINT.$_$p$g");
  754.       spawnl(P_WAIT, comspec, NULL);
  755.       }
  756. }
  757.  
  758.  
  759. void showfreemem()
  760. {
  761.    char *tempptr;
  762.    unsigned char huge *fartempptr;
  763.    unsigned i,i2;
  764.    long j,j2;
  765.    ENTER_OVLY(OVLY_MISCOVL);
  766.    printf("\n CPU type: %d  FPU type: %d  IIT FPU: %d  Video: %d\n\n",
  767.       cpu, fpu, iit, video_type);
  768.    i = j = 0;
  769.    i2 = 0x8000;
  770.    while ((i2 >>= 1) != 0)
  771.       if ((tempptr = malloc(i+i2)) != NULL) {
  772.      free(tempptr);
  773.      i += i2;
  774.      }
  775.    printf(" %d NEAR bytes free \n", i);
  776.    j2 = 0x80000;
  777.    while ((j2 >>= 1) != 0)
  778.       if ((fartempptr = (unsigned char huge *)farmemalloc(j+j2)) != NULL) {
  779.      farmemfree((void far*)fartempptr);
  780.      j += j2;
  781.      }
  782.    printf(" %ld FAR bytes free \n\n press any key to continue...\n", j);
  783.    getakey();
  784.    EXIT_OVLY;
  785. }
  786.  
  787.  
  788. edit_text_colors()
  789. {
  790.    extern int debugflag;
  791.    extern int lookatmouse;
  792.    int save_debugflag,save_lookatmouse;
  793.    int row,col,bkgrd;
  794.    int rowf,colf,rowt,colt;
  795.    char far *vidmem;
  796.    char far *savescreen;
  797.    char far *farp1; char far *farp2;
  798.    int i,j,k;
  799.    ENTER_OVLY(OVLY_MISCOVL);
  800.    save_debugflag = debugflag;
  801.    save_lookatmouse = lookatmouse;
  802.    debugflag = 0;   /* don't get called recursively */
  803.    lookatmouse = 2; /* text mouse sensitivity */
  804.    row = col = bkgrd = rowt = rowf = colt = colf = 0;
  805.    vidmem = MK_FP(0xB800,0);
  806.    while (1) {
  807.       if (row < 0)  row = 0;
  808.       if (row > 24) row = 24;
  809.       if (col < 0)  col = 0;
  810.       if (col > 79) col = 79;
  811.       movecursor(row,col);
  812.       i = getakey();
  813.       if (i >= 'a' && i <= 'z') i -= 32; /* uppercase */
  814.       switch (i) {
  815.      case 27: /* esc */
  816.         debugflag = save_debugflag;
  817.         lookatmouse = save_lookatmouse;
  818.         movecursor(25,80);
  819.         EXIT_OVLY;
  820.         return 0;
  821.      case '/':
  822.         farp1 = savescreen = farmemalloc(4000L);
  823.         farp2 = vidmem;
  824.         for (i = 0; i < 4000; ++i) { /* save and blank */
  825.            *(farp1++) = *farp2;
  826.            *(farp2++) = 0;
  827.            }
  828.         for (i = 0; i < 8; ++i)      /* 8 bkgrd attrs */
  829.            for (j = 0; j < 16; ++j) { /* 16 fgrd attrs */
  830.           k = i*16 + j;
  831.           farp1 = vidmem + i*320 + j*10;
  832.           *(farp1++) = ' '; *(farp1++) = k;
  833.           *(farp1++) = i+'0'; *(farp1++) = k;
  834.           *(farp1++) = (j < 10) ? j+'0' : j+'A'-10; *(farp1++) = k;
  835.           *(farp1++) = ' '; *(farp1++) = k;
  836.           }
  837.         getakey();
  838.         farp1 = vidmem;
  839.         farp2 = savescreen;
  840.         for (i = 0; i < 4000; ++i) /* restore */
  841.            *(farp1++) = *(farp2++);
  842.         farmemfree(savescreen);
  843.         break;
  844.      case ',':
  845.         rowf = row; colf = col; break;
  846.      case '.':
  847.         rowt = row; colt = col; break;
  848.      case ' ': /* next color is background */
  849.         bkgrd = 1; break;
  850.      case 1075: /* cursor left  */
  851.         --col; break;
  852.      case 1077: /* cursor right */
  853.         ++col; break;
  854.      case 1072: /* cursor up    */
  855.         --row; break;
  856.      case 1080: /* cursor down  */
  857.         ++row; break;
  858.      case 13:   /* enter */
  859.         *(vidmem + row*160 + col*2) = getakey();
  860.         break;
  861.      default:
  862.         if (i >= '0' && i <= '9')      i -= '0';
  863.         else if (i >= 'A' && i <= 'F') i -= 'A'-10;
  864.         else break;
  865.         for (j = rowf; j <= rowt; ++j)
  866.            for (k = colf; k <= colt; ++k) {
  867.           farp1 = vidmem + j*160 + k*2 + 1;
  868.           if (bkgrd) *farp1 = (*farp1 & 15) + i * 16;
  869.           else         *farp1 = (*farp1 & 0xf0) + i;
  870.           }
  871.         bkgrd = 0;
  872.      }
  873.       }
  874. }
  875.  
  876.  
  877. extern int badconfig;
  878. extern struct videoinfo far videotable[];
  879. extern struct videoinfo far *vidtbl;
  880. extern int vidtbllen;
  881. extern int tabmode;
  882. extern int adapter;
  883. static int *entsptr;
  884. static int modes_changed;
  885. extern int mode7text;
  886.  
  887. int select_video_mode(int curmode)
  888. {
  889.    int entnums[MAXVIDEOMODES];
  890.    int attributes[MAXVIDEOMODES];
  891.    int i,j,k,ret;
  892.    int oldtabmode,oldhelpmode;
  893.  
  894.    ENTER_OVLY(OVLY_MISCOVL);
  895.  
  896.    load_fractint_cfg(0);    /* load fractint.cfg to extraseg */
  897.  
  898.    for (i = 0; i < vidtbllen; ++i) { /* init tables */
  899.       entnums[i] = i;
  900.       attributes[i] = 1;
  901.       }
  902.    entsptr = entnums;        /* for indirectly called subroutines */
  903.  
  904.    qsort(entnums,vidtbllen,sizeof(entnums[0]),entcompare); /* sort modes */
  905.  
  906.    /* pick default mode */
  907.    if (curmode < 0) {
  908.       switch (video_type) { /* set up a reasonable default (we hope) */
  909.      case 1:  videoentry.videomodeax = 8;    /* hgc */
  910.           videoentry.colors = 2;
  911.           break;
  912.      case 2:  videoentry.videomodeax = 4;    /* cga */
  913.           videoentry.colors = 4;
  914.           break;
  915.      case 3:  videoentry.videomodeax = 16;    /* ega */
  916.           videoentry.colors = 16;
  917.           if (mode7text) {        /* egamono */
  918.              videoentry.videomodeax = 15;
  919.              videoentry.colors = 2;
  920.              }
  921.           break;
  922.      default: videoentry.videomodeax = 19;    /* mcga/vga? */
  923.           videoentry.colors = 256;
  924.           break;
  925.      }
  926.       }
  927.    else
  928.       far_memcpy((char far *)&videoentry,(char far *)&videotable[curmode],
  929.          sizeof(videoentry));
  930.    for (i = 0; i < vidtbllen; ++i) { /* find default mode */
  931.       if ( videoentry.videomodeax == vidtbl[entnums[i]].videomodeax
  932.     && videoentry.colors      == vidtbl[entnums[i]].colors
  933.     && (curmode < 0
  934.         || far_memcmp((char far *)&videoentry,(char far *)&vidtbl[entnums[i]],
  935.               sizeof(videoentry)) == 0))
  936.      break;
  937.       }
  938.    if (i >= vidtbllen) /* no match, default to first entry */
  939.       i = 0;
  940.  
  941.    oldtabmode = tabmode;
  942.    oldhelpmode = helpmode;
  943.    modes_changed = 0;
  944.    tabmode = 0;
  945.    helpmode = HELPVIDSEL;
  946.    i = fullscreen_choice(CHOICEHELP,"Select Video Mode",
  947.  "key...name......................xdot.ydot.colr.comment..................",
  948.           NULL,vidtbllen,NULL,attributes,
  949.           1,16,72,i,format_item,NULL,NULL,check_modekey);
  950.    tabmode = oldtabmode;
  951.    helpmode = oldhelpmode;
  952.    if (i == -1) {
  953.    static char far msg[]={"Save new function key assignments or cancel changes?"};
  954.       if (modes_changed /* update fractint.cfg for new key assignments */
  955.     && badconfig == 0
  956.     && stopmsg(22,msg) == 0)
  957.      update_fractint_cfg();
  958.       EXIT_OVLY;
  959.       return(-1);
  960.       }
  961.    if (i < 0)    /* picked by function key */
  962.       i = -1 - i;
  963.    else     /* picked by Enter key */
  964.       i = entnums[i];
  965.    far_memcpy((char far *)&videoentry,(char far *)&vidtbl[i],
  966.           sizeof(videoentry));  /* the selected entry now in videoentry */
  967.  
  968.    /* copy fractint.cfg table to resident table, note selected entry */
  969.    j = k = 0;
  970.    far_memset((char far *)videotable,0,sizeof(*vidtbl)*MAXVIDEOTABLE);
  971.    for (i = 0; i < vidtbllen; ++i) {
  972.       if (vidtbl[i].keynum > 0) {
  973.      far_memcpy((char far *)&videotable[j],(char far *)&vidtbl[i],
  974.             sizeof(*vidtbl));
  975.      if (far_memcmp((char far *)&videoentry,(char far *)&vidtbl[i],
  976.             sizeof(videoentry)) == 0)
  977.         k = vidtbl[i].keynum;
  978.      if (++j >= MAXVIDEOTABLE-1)
  979.         break;
  980.      }
  981.       }
  982.    if ((ret = k) == 0) { /* selected entry not a copied (assigned to key) one */
  983.       far_memcpy((char far *)&videotable[MAXVIDEOTABLE-1],
  984.          (char far *)&videoentry,sizeof(*vidtbl));
  985.       ret = 1400; /* special value for check_vidmode_key */
  986.       }
  987.  
  988.    if (modes_changed /* update fractint.cfg for new key assignments */
  989.      && badconfig == 0)
  990.       update_fractint_cfg();
  991.  
  992.    EXIT_OVLY;
  993.    return(ret);
  994. }
  995.  
  996. static void format_item(int choice,char *buf)
  997. {
  998.    char kname[5];
  999.    char biosflag;
  1000.    far_memcpy((char far *)&videoentry,(char far *)&vidtbl[entsptr[choice]],
  1001.           sizeof(videoentry));
  1002.    vidmode_keyname(videoentry.keynum,kname);
  1003.    biosflag = (videoentry.dotmode % 100 == 1) ? 'B' : ' ';
  1004.    sprintf(buf,"%-5s %-25s %4d %4d %3d%c %-25s",  /* 72 chars */
  1005.        kname, videoentry.name, videoentry.xdots, videoentry.ydots,
  1006.        videoentry.colors, biosflag, videoentry.comment);
  1007. }
  1008.  
  1009. static int check_modekey(int curkey,int choice)
  1010. {
  1011.    int i,j,k,ret;
  1012.    if ((i = check_vidmode_key(1,curkey)) >= 0)
  1013.       return(-1-i);
  1014.    i = entsptr[choice];
  1015.    ret = 0;
  1016.    if ( (curkey == '-' || curkey == '+')
  1017.      && (vidtbl[i].keynum == 0 || vidtbl[i].keynum >= 1084)) {
  1018.       static char far msg[]={"Missing or bad FRACTINT.CFG file. Can't reassign keys."};
  1019.       if (badconfig)
  1020.      stopmsg(0,msg);
  1021.       else {
  1022.      if (curkey == '-') {                   /* deassign key? */
  1023.         if (vidtbl[i].keynum >= 1084) {
  1024.            vidtbl[i].keynum = 0;
  1025.            modes_changed = 1;
  1026.            }
  1027.         }
  1028.      else {                 /* assign key? */
  1029.         j = getakeynohelp();
  1030.         if (j >= 1084 && j <= 1113) {
  1031.            for (k = 0; k < vidtbllen; ++k) {
  1032.           if (vidtbl[k].keynum == j) {
  1033.              vidtbl[k].keynum = 0;
  1034.              ret = -1; /* force redisplay */
  1035.              }
  1036.           }
  1037.            vidtbl[i].keynum = j;
  1038.            modes_changed = 1;
  1039.            }
  1040.         }
  1041.      }
  1042.       }
  1043.    return(ret);
  1044. }
  1045.  
  1046. static int entcompare(void const *p1,void const *p2)
  1047. {
  1048.    int i,j;
  1049.    if ((i = vidtbl[*((int *)p1)].keynum) == 0) i = 9999;
  1050.    if ((j = vidtbl[*((int *)p2)].keynum) == 0) j = 9999;
  1051.    if (i < j || (i == j && *((int *)p1) < *((int *)p2)))
  1052.       return(-1);
  1053.    return(1);
  1054. }
  1055.  
  1056. static void update_fractint_cfg()
  1057. {
  1058.    char cfgname[100],outname[100],buf[121],kname[5];
  1059.    FILE *cfgfile,*outfile;
  1060.    int far *cfglinenums;
  1061.    int i,j,linenum,nextlinenum,nextmode;
  1062.    struct videoinfo vident;
  1063.  
  1064.    findpath("fractint.cfg",cfgname);
  1065.    if (access(cfgname,6)) {
  1066.       sprintf(buf,"Can't write %s",cfgname);
  1067.       stopmsg(0,buf);
  1068.       return;
  1069.       }
  1070.    strcpy(outname,cfgname);
  1071.    i = strlen(outname);
  1072.    while (--i >= 0 && outname[i] != '\\')
  1073.    outname[i] = 0;
  1074.    strcat(outname,"fractint.tmp");
  1075.    if ((outfile = fopen(outname,"w")) == NULL) {
  1076.       sprintf(buf,"Can't create %s ",outname);
  1077.       stopmsg(0,buf);
  1078.       return;
  1079.       }
  1080.    cfgfile = fopen(cfgname,"r");
  1081.  
  1082.    cfglinenums = (int far *)(&vidtbl[MAXVIDEOMODES]);
  1083.    linenum = nextmode = 0;
  1084.    nextlinenum = cfglinenums[0];
  1085.    while (fgets(buf,120,cfgfile)) {
  1086.       ++linenum;
  1087.       if (linenum == nextlinenum) { /* replace this line */
  1088.      far_memcpy((char far *)&vident,(char far *)&vidtbl[nextmode],
  1089.             sizeof(videoentry));
  1090.      vidmode_keyname(vident.keynum,kname);
  1091.      strcpy(buf,vident.name);
  1092.      i = strlen(buf);
  1093.      while (i && buf[i-1] == ' ') /* strip trailing spaces to compress */
  1094.         --i;
  1095.      j = i + 5;
  1096.      while (j < 32) {        /* tab to column 33 */
  1097.         buf[i++] = '\t';
  1098.         j += 8;
  1099.         }
  1100.      buf[i] = 0;
  1101.      fprintf(outfile,"%-4s,%s,%4x,%4x,%4x,%4x,%4d,%4d,%4d,%3d,%s\n",
  1102.         kname,
  1103.         buf,
  1104.         vident.videomodeax,
  1105.         vident.videomodebx,
  1106.         vident.videomodecx,
  1107.         vident.videomodedx,
  1108.         vident.dotmode,
  1109.         vident.xdots,
  1110.         vident.ydots,
  1111.         vident.colors,
  1112.         vident.comment);
  1113.      if (++nextmode >= vidtbllen)
  1114.         nextlinenum = 32767;
  1115.      else
  1116.         nextlinenum = cfglinenums[nextmode];
  1117.      }
  1118.       else
  1119.      fputs(buf,outfile);
  1120.       }
  1121.  
  1122.    fclose(cfgfile);
  1123.    fclose(outfile);
  1124.    unlink(cfgname);        /* success assumed on these lines        */
  1125.    rename(outname,cfgname); /* since we checked earlier with access */
  1126. }
  1127.  
  1128.  
  1129.