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

  1. /*
  2.     Various routines that prompt for things.
  3.     This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
  4. */
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #ifndef XFRACT
  11. #include <dos.h>
  12. #elif !defined(__386BSD__)
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <sys/dir.h>
  16. #endif
  17. #ifdef __TURBOC__
  18. #include <alloc.h>
  19. #elif !defined(__386BSD__)
  20. #include <malloc.h>
  21. #endif
  22.  
  23. #ifdef __hpux
  24. #include <sys/param.h>
  25. #define getwd(a) getcwd(a,MAXPATHLEN)
  26. #endif
  27.  
  28. #include "fractint.h"
  29. #include "fractype.h"
  30. #include "helpdefs.h"
  31. #include "prototyp.h"
  32.  
  33. extern int Targa_Overlay;
  34. extern int Targa_Out;
  35. extern BYTE back_color[];
  36. extern float  screenaspect;
  37.  
  38. /* Routines defined in prompts2.c */
  39.  
  40. extern    int get_corners(void);
  41. extern    int edit_ifs_params(void );
  42. extern    int lccompare(VOIDCONSTPTR, VOIDCONSTPTR);
  43.  
  44. /* Routines used in prompts2.c */
  45.  
  46.     int prompt_checkkey(int curkey);
  47.     long get_file_entry(int,char *,char *,char *,char *);
  48.  
  49. /* Routines in this module    */
  50.  
  51. static    int prompt_valuestring(char *buf,struct fullscreenvalues *val);
  52. static    int input_field_list(int attr,char *fld,int vlen,char **list,int llen,
  53.                  int row,int col,int (*checkkey)(int));
  54. static    int select_fracttype(int t);
  55. static    int sel_fractype_help(int curkey, int choice);
  56.     int select_type_params(int newfractype,int oldfractype);
  57. static    void set_default_parms(void);
  58. static    long gfe_choose_entry(int,char *,char *,char *);
  59. static    int check_gfe_key(int curkey,int choice);
  60. static    void load_entry_text(FILE *entfile,char far *buf,int maxlines);
  61. static    void format_parmfile_line(int,char *);
  62. static    int get_light_params(void );
  63. static    int check_mapfile(void );
  64. static    int get_funny_glasses_params(void );
  65.  
  66. int julibrot;   /* flag for julibrot */
  67.  
  68. extern int numtrigfn;
  69. extern int bailout;
  70.  
  71. extern struct moreparams far moreparams[];
  72. static char funnyglasses_map_name[16];
  73. extern char temp1[256];   /* temporary strings          */
  74. extern int previewfactor;
  75. extern int xtrans, ytrans;
  76. extern int red_crop_left, red_crop_right;
  77. extern int blue_crop_left, blue_crop_right;
  78. extern int red_bright, blue_bright;
  79. extern char showbox; /* flag to show box and vector in preview */
  80. extern SEGTYPE extraseg;
  81. extern int whichimage;
  82. extern int xadjust;
  83. extern int eyeseparation;
  84. extern int glassestype;
  85. char   MAP_name[80] = "";
  86. int    mapset = 0;
  87. extern    int    overlay3d;        /* 3D overlay flag: 0 = OFF */
  88. extern    int    lookatmouse;
  89. extern    int haze;
  90. extern    int RANDOMIZE;
  91. extern    char light_name[];
  92. extern    int Ambient;
  93. extern    int RAY;
  94. extern    int BRIEF;
  95. extern    char ray_name[];
  96.  
  97. extern    int    init3d[20];    /* '3d=nn/nn/nn/...' values */
  98. extern    double    xxmin,xxmax;    /* initial corner values    */
  99. extern    double    yymin,yymax;    /* initial corner values    */
  100.  
  101. extern    double    xx3rd,yy3rd;    /* initial corner values    */
  102. extern    int    invert;     /* non-zero if inversion active */
  103. extern    double    inversion[3];    /* radius, xcenter, ycenter */
  104. extern    double    param[];        /* up to six parameters    */
  105. extern    double    potparam[3];    /* three potential parameters*/
  106. extern    int    fractype;    /* if == 0, use Mandelbrot  */
  107. extern    char    preview;    /* 3D preview mode flag */
  108. extern    int    transparent[];    /* transparency values */
  109. extern    int    usr_biomorph;    /* Biomorph flag */
  110. extern    int    viewcrop;
  111. extern    float    finalaspectratio;
  112. extern    int    textcbase;
  113. extern    char    boxy[];
  114. extern    int    display3d;
  115.  
  116. extern char LFileName[];    /* file to find the formulas in */
  117. extern char LName[];        /* Name of the Formula (if not null) */
  118. extern char FormFileName[];
  119. extern char FormName[];
  120. extern char IFSFileName[];
  121. extern char IFSName[];
  122. extern float far *ifs_defn;
  123. extern int ifs_type;
  124. extern int ifs_changed;
  125.  
  126. /* fullscreen_choice options */
  127. #define CHOICEHELP    4
  128.  
  129. #define GETFORMULA 0
  130. #define GETLSYS    1
  131. #define GETIFS       2
  132. #define GETPARM    3
  133.  
  134.  
  135. char ifsmask[13]     = {"*.ifs"};
  136. char formmask[13]    = {"*.frm"};
  137. char lsysmask[13]    = {"*.l"};
  138. char Glasses1Map[] = "glasses1.map";
  139.  
  140. void prompts1_overlay() { }    /* for restore_active_ovly */
  141.  
  142.  
  143. /* --------------------------------------------------------------------- */
  144.  
  145. int promptfkeys;
  146.  
  147. int fullscreen_prompt(    /* full-screen prompting routine */
  148.     char far *hdg,        /* heading, lines separated by \n */
  149.     int numprompts,     /* there are this many prompts (max) */
  150.     char far **prompts,     /* array of prompting pointers */
  151.     struct fullscreenvalues *values, /* array of values */
  152.     int options,        /* for future */
  153.     int fkeymask,        /* bit n on if Fn to cause return */
  154.     char far *extrainfo    /* extra info box to display, \n separated */
  155.     )
  156. {
  157.    char far *hdgscan;
  158.    int titlelines,titlewidth,titlerow;
  159.    int maxpromptwidth,maxfldwidth,maxcomment;
  160.    int boxrow,boxlines;
  161.    int boxcol,boxwidth;
  162.    int extralines,extrawidth,extrarow;
  163.    int instrrow;
  164.    int promptrow,promptcol,valuecol;
  165.    int curchoice;
  166.    int done, i, j;
  167.    int anyinput;
  168.    int savelookatmouse;
  169.    int curtype, curlen;
  170.    char buf[81];
  171. #ifndef XFRACT
  172. static char far instr1[]  = {"Use " UPARR " and " DNARR " to select values to change"};
  173. static char far instr2a[]  = {"Type in replacement value for selected field"};
  174. static char far instr2b[]  = {"Use " LTARR " or " RTARR " to change value of selected field"};
  175. #else
  176. /* Some compilers don't accept "a" "b", so we have to fill in UPARR ourself.  */
  177. static char far instr1[]  = {"Use up(K) and down(J) to select values to change"};
  178. static char far instr2a[]  = {"Type in replacement value for selected field"};
  179. static char far instr2b[]  = {"Use left(H) or right(L) to change value of selected field"};
  180. #endif
  181. static char far instr3a[] = {"Press ENTER when finished (or ESCAPE to back out)"};
  182. static char far instr3b[] = {"Press ENTER when finished, ESCAPE to back out, or F1 for help"};
  183. static char far instr0a[] = {"No changeable parameters; press ENTER to exit"};
  184. static char far instr0b[] = {"No changeable parameters; press ENTER to exit or F1 for help"};
  185.  
  186.    ENTER_OVLY(OVLY_PROMPTS1);
  187.  
  188.    if (numprompts <= 0) {    /* ?? nothing to do! */
  189.       EXIT_OVLY;
  190.       return(0);
  191.       }
  192.    
  193.    savelookatmouse = lookatmouse;
  194.    lookatmouse = 0;
  195.    promptfkeys = fkeymask;
  196.    helptitle();                /* clear screen, display title line  */
  197.    setattr(1,0,C_PROMPT_BKGRD,24*80);  /* init rest of screen to background */
  198.  
  199.    hdgscan = hdg;               /* count title lines, find widest */
  200.    i = titlewidth = 0;
  201.    titlelines = 1;
  202.    while (*hdgscan) {
  203.       if (*(hdgscan++) == '\n') {
  204.      ++titlelines;
  205.      i = -1;
  206.      }
  207.       if (++i > titlewidth)
  208.      titlewidth = i;
  209.       }
  210.    extralines = extrawidth = i = 0;
  211.    if ((hdgscan = extrainfo))
  212.       if (*hdgscan == 0)
  213.      extrainfo = NULL;
  214.       else { /* count extra lines, find widest */
  215.      extralines = 3;
  216.      while (*hdgscan) {
  217.         if (*(hdgscan++) == '\n') {
  218.            if (extralines + numprompts + titlelines >= 20) {
  219.            *hdgscan = 0; /* full screen, cut off here */
  220.            break;
  221.            }
  222.            ++extralines;
  223.            i = -1;
  224.            }
  225.         if (++i > extrawidth)
  226.            extrawidth = i;
  227.         }
  228.      }
  229.  
  230.    /* work out vertical positioning */
  231.    i = numprompts + titlelines + extralines + 3; /* total rows required */
  232.    j = (25 - i) / 2;               /* top row of it all when centered */
  233.    j -= j / 4;                   /* higher is better if lots extra */
  234.    boxlines = numprompts;
  235.    titlerow = 1 + j;
  236.    promptrow = boxrow = titlerow + titlelines;
  237.    if (titlerow > 2) {               /* room for blank between title & box? */
  238.       --titlerow;
  239.       --boxrow;
  240.       ++boxlines;
  241.       }
  242.    instrrow = boxrow+boxlines;
  243.    if (instrrow + 3 + extralines < 25) {
  244.       ++boxlines;    /* blank at bottom of box */
  245.       ++instrrow;
  246.       if (instrrow + 3 + extralines < 25)
  247.      ++instrrow; /* blank before instructions */
  248.       }
  249.    extrarow = instrrow + 2;
  250.    if (numprompts > 1) /* 3 instructions lines */
  251.       ++extrarow;
  252.    if (extrarow + extralines < 25)
  253.       ++extrarow;
  254.  
  255.    /* work out horizontal positioning */
  256.    maxfldwidth = maxpromptwidth = maxcomment = anyinput = 0;
  257.    for (i = 0; i < numprompts; i++) {
  258.       if (values[i].type == 'y') {
  259.      static char *noyes[2] = {"no","yes"};
  260.      values[i].type = 'l';
  261.      values[i].uval.ch.vlen = 3;
  262.      values[i].uval.ch.list = noyes;
  263.      values[i].uval.ch.llen = 2;
  264.      }
  265.       j = far_strlen(prompts[i]);
  266.       if (values[i].type == '*') {
  267.      if (j > maxcomment)     maxcomment = j;
  268.      }
  269.       else {
  270.          anyinput = 1;
  271.      if (j > maxpromptwidth) maxpromptwidth = j;
  272.      j = prompt_valuestring(buf,&values[i]);
  273.      if (j > maxfldwidth)     maxfldwidth = j;
  274.      }
  275.       }
  276.    boxwidth = maxpromptwidth + maxfldwidth + 2;
  277.    if (maxcomment > boxwidth) boxwidth = maxcomment;
  278.    if ((boxwidth += 4) > 80) boxwidth = 80;
  279.    boxcol = (80 - boxwidth) / 2;       /* center the box */
  280.    promptcol = boxcol + 2;
  281.    valuecol = boxcol + boxwidth - maxfldwidth - 2;
  282.    if (boxwidth <= 76) {           /* make margin a bit wider if we can */
  283.       boxwidth += 2;
  284.       --boxcol;
  285.       }
  286.    if ((j = titlewidth) < extrawidth)
  287.       j = extrawidth;
  288.    if ((i = j + 4 - boxwidth) > 0) {   /* expand box for title/extra */
  289.       if (boxwidth + i > 80)
  290.      i = 80 - boxwidth;
  291.       boxwidth += i;
  292.       boxcol -= i / 2;
  293.       }
  294.    i = (90 - boxwidth) / 20;
  295.    boxcol    -= i;
  296.    promptcol -= i;
  297.    valuecol  -= i;
  298.  
  299.    /* display box heading */
  300.    for (i = titlerow; i < boxrow; ++i)
  301.       setattr(i,boxcol,C_PROMPT_HI,boxwidth);
  302.    textcbase = boxcol + (boxwidth - titlewidth) / 2;
  303.    putstring(titlerow,0,C_PROMPT_HI,hdg);
  304.  
  305.    /* display extra info */
  306.    if (extrainfo) {
  307. #ifndef XFRACT
  308. #define S1 '\xC4'
  309. #define S2 "\xC0"
  310. #define S3 "\xD9"
  311. #define S4 "\xB3"
  312. #define S5 "\xDA"
  313. #define S6 "\xBF"
  314. #else
  315. #define S1 '-'
  316. #define S2 "+" /* ll corner */
  317. #define S3 "+" /* lr corner */
  318. #define S4 "|"
  319. #define S5 "+" /* ul corner */
  320. #define S6 "+" /* ur corner */
  321. #endif
  322.       memset(buf,S1,80); buf[boxwidth-2] = 0;
  323.       textcbase = boxcol + 1;
  324.       putstring(extrarow,0,C_PROMPT_BKGRD,buf);
  325.       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,buf);
  326.       --textcbase;
  327.       putstring(extrarow,0,C_PROMPT_BKGRD,S5);
  328.       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,S2);
  329.       textcbase += boxwidth - 1;
  330.       putstring(extrarow,0,C_PROMPT_BKGRD,S6);
  331.       putstring(extrarow+extralines-1,0,C_PROMPT_BKGRD,S3);
  332.       textcbase = boxcol;
  333.       for (i = 1; i < extralines-1; ++i) {
  334.          putstring(extrarow+i,0,C_PROMPT_BKGRD,S4);
  335.          putstring(extrarow+i,boxwidth-1,C_PROMPT_BKGRD,S4);
  336.      }
  337.       textcbase += (boxwidth - extrawidth) / 2;
  338.       putstring(extrarow+1,0,C_PROMPT_TEXT,extrainfo);
  339.       }
  340.    textcbase = 0;
  341.  
  342.    /* display empty box */
  343.    for (i = 0; i < boxlines; ++i)
  344.       setattr(boxrow+i,boxcol,C_PROMPT_LO,boxwidth);
  345.  
  346.    /* display initial values */
  347.    for (i = 0; i < numprompts; i++) {
  348.       putstring(promptrow+i, promptcol, C_PROMPT_LO, prompts[i]);
  349.       prompt_valuestring(buf,&values[i]);
  350.       putstring(promptrow+i, valuecol, C_PROMPT_LO, buf);
  351.       }
  352.  
  353.    if (!anyinput) {
  354.       putstringcenter(instrrow,0,80,C_PROMPT_BKGRD,
  355.         (helpmode > 0) ? instr0b : instr0a);
  356.       movecursor(25,80);
  357.       while (1) {
  358.         while (!keypressed()) { }
  359.         done = getakey();
  360.         switch(done) {
  361.            case ESC:
  362.               done = -1;
  363.            case ENTER:
  364.            case ENTER_2:
  365.               goto fullscreen_exit;
  366.            case F2:
  367.            case F3:
  368.            case F4:
  369.            case F5:
  370.            case F6:
  371.            case F7:
  372.            case F8:
  373.            case F9:
  374.            case F10:
  375.               if (promptfkeys & (1<<(done+1-F1)) )
  376.                  goto fullscreen_exit;
  377.            }
  378.         }
  379.       }
  380.  
  381.  
  382.    /* display footing */
  383.    if (numprompts > 1)
  384.       putstringcenter(instrrow++,0,80,C_PROMPT_BKGRD,instr1);
  385.    putstringcenter(instrrow+1,0,80,C_PROMPT_BKGRD,
  386.      (helpmode > 0) ? instr3b : instr3a);
  387.  
  388.    curchoice = done = 0;
  389.    while (values[curchoice].type == '*') ++curchoice;
  390.  
  391.    while (!done) {
  392.  
  393.       curtype = values[curchoice].type;
  394.       curlen = prompt_valuestring(buf,&values[curchoice]);
  395.       putstringcenter(instrrow,0,80,C_PROMPT_BKGRD,
  396.               (curtype == 'l') ? instr2b : instr2a);
  397.       putstring(promptrow+curchoice,promptcol,C_PROMPT_HI,prompts[curchoice]);
  398.  
  399.       if (curtype == 'l') {
  400.      i = input_field_list(
  401.         C_PROMPT_CHOOSE, buf, curlen,
  402.         values[curchoice].uval.ch.list, values[curchoice].uval.ch.llen,
  403.         promptrow+curchoice,valuecol, prompt_checkkey);
  404.      for (j = 0; j < values[curchoice].uval.ch.llen; ++j)
  405.         if (strcmp(buf,values[curchoice].uval.ch.list[j]) == 0) break;
  406.      values[curchoice].uval.ch.val = j;
  407.      }
  408.       else {
  409.      j = 0;
  410.      if (curtype == 'i') j = 3;
  411.      if (curtype == 'd') j = 5;
  412.      if (curtype == 'D') j = 7;
  413.      if (curtype == 'f') j = 1;
  414.      i = input_field(j, C_PROMPT_INPUT, buf, curlen,
  415.         promptrow+curchoice,valuecol,prompt_checkkey);
  416.      switch (values[curchoice].type) {
  417.         case 'd':
  418.         case 'D':
  419.            values[curchoice].uval.dval = atof(buf);
  420.            break;
  421.         case 'f':
  422.            values[curchoice].uval.dval = atof(buf);
  423.            roundfloatd(&values[curchoice].uval.dval);
  424.            break;
  425.         case 'i':
  426.            values[curchoice].uval.ival = atoi(buf);
  427.            break;
  428.         case 's':
  429.            strncpy(values[curchoice].uval.sval,buf,16);
  430.            break;
  431.         default: /* assume 0x100+n */
  432.            strcpy(values[curchoice].uval.sbuf,buf);
  433.         }
  434.      }
  435.  
  436.       putstring(promptrow+curchoice,promptcol,C_PROMPT_LO,prompts[curchoice]);
  437.       j = strlen(buf);
  438.       memset(&buf[j],' ',80-j); buf[curlen] = 0;
  439.       putstring(promptrow+curchoice, valuecol, C_PROMPT_LO,  buf);
  440.  
  441.       switch(i) {
  442.      case 0:  /* enter  */
  443.         done = 13;
  444.         break;
  445.      case -1: /* escape */
  446.      case F2:
  447.      case F3:
  448.      case F4:
  449.      case F5:
  450.      case F6:
  451.      case F7:
  452.      case F8:
  453.      case F9:
  454.      case F10:
  455.         done = i;
  456.         break;
  457.      case PAGE_UP:
  458.         curchoice = -1;
  459.      case DOWN_ARROW:
  460.      case DOWN_ARROW_2:
  461.         do {
  462.            if (++curchoice >= numprompts) curchoice = 0;
  463.            } while (values[curchoice].type == '*');
  464.         break;
  465.      case PAGE_DOWN:
  466.         curchoice = numprompts;
  467.      case UP_ARROW:
  468.      case UP_ARROW_2:
  469.         do {
  470.            if (--curchoice < 0) curchoice = numprompts - 1;
  471.            } while (values[curchoice].type == '*');
  472.         break;
  473.      }
  474.       }
  475.  
  476. fullscreen_exit:
  477.    movecursor(25,80);
  478.    lookatmouse = savelookatmouse;
  479.    EXIT_OVLY;
  480.    return(done);
  481. }
  482.  
  483. static int prompt_valuestring(char *buf,struct fullscreenvalues *val)
  484. {  /* format value into buf, return field width */
  485.    int i,ret;
  486.    switch (val->type) {
  487.       case 'd':
  488.      ret = 20;
  489.      i = 16;    /* cellular needs 16 (was 15)*/
  490.      while (1) {
  491.         sprintf(buf,"%.*g",i,val->uval.dval);
  492.         if (strlen(buf) <= ret) break;
  493.         --i;
  494.         }
  495.      break;
  496.       case 'D':
  497.      if (val->uval.dval<0) { /* We have to round the right way */
  498.          sprintf(buf,"%ld",(long)(val->uval.dval-.5));
  499.      }
  500.      else {
  501.          sprintf(buf,"%ld",(long)(val->uval.dval+.5));
  502.      }
  503.      ret = 20;
  504.      break;
  505.       case 'f':
  506.      sprintf(buf,"%.7g",val->uval.dval);
  507.      ret = 14;
  508.      break;
  509.       case 'i':
  510.      sprintf(buf,"%d",val->uval.ival);
  511.      ret = 6;
  512.      break;
  513.       case '*':
  514.      *buf = ret = 0;
  515.      break;
  516.       case 's':
  517.      strncpy(buf,val->uval.sval,16);
  518.      buf[15] = 0;
  519.      ret = 15;
  520.      break;
  521.       case 'l':
  522.      strcpy(buf,val->uval.ch.list[val->uval.ch.val]);
  523.      ret = val->uval.ch.vlen;
  524.      break;
  525.       default: /* assume 0x100+n */
  526.      strcpy(buf,val->uval.sbuf);
  527.      ret = val->type & 0xff;
  528.       }
  529.    return ret;
  530. }
  531.  
  532. int prompt_checkkey(int curkey)
  533. {
  534.    switch(curkey) {
  535.       case PAGE_UP:
  536.       case DOWN_ARROW:
  537.       case DOWN_ARROW_2:
  538.       case PAGE_DOWN:
  539.       case UP_ARROW:
  540.       case UP_ARROW_2:
  541.      return(curkey);
  542.       case F2:
  543.       case F3:
  544.       case F4:
  545.       case F5:
  546.       case F6:
  547.       case F7:
  548.       case F8:
  549.       case F9:
  550.       case F10:
  551.      if (promptfkeys & (1<<(curkey+1-F1)) )
  552.         return(curkey);
  553.       }
  554.    return(0);
  555. }
  556.  
  557. static int input_field_list(
  558.     int attr,          /* display attribute */
  559.     char *fld,          /* display form field value */
  560.     int vlen,          /* field length */
  561.     char **list,          /* list of values */
  562.     int llen,          /* number of entries in list */
  563.     int row,          /* display row */
  564.     int col,          /* display column */
  565.     int (*checkkey)(int)  /* routine to check non data keys, or NULL */
  566.     )
  567. {
  568.    int initval,curval;
  569.    char buf[81];
  570.    int curkey;
  571.    int i, j;
  572.    int ret,savelookatmouse;
  573.    savelookatmouse = lookatmouse;
  574.    lookatmouse = 0;
  575.    for (initval = 0; initval < llen; ++initval)
  576.       if (strcmp(fld,list[initval]) == 0) break;
  577.    if (initval >= llen) initval = 0;
  578.    curval = initval;
  579.    ret = -1;
  580.    while (1) {
  581.       strcpy(buf,list[curval]);
  582.       i = strlen(buf);
  583.       while (i < vlen)
  584.      buf[i++] = ' ';
  585.       buf[vlen] = 0;
  586.       putstring(row,col,attr,buf);
  587.       curkey = keycursor(row,col); /* get a keystroke */
  588.       switch (curkey) {
  589.      case ENTER:
  590.      case ENTER_2:
  591.         ret = 0;
  592.         goto inpfldl_end;
  593.      case ESC:
  594.         goto inpfldl_end;
  595.      case RIGHT_ARROW:
  596.      case RIGHT_ARROW_2:
  597.         if (++curval >= llen)
  598.            curval = 0;
  599.         break;
  600.      case LEFT_ARROW:
  601.      case LEFT_ARROW_2:
  602.         if (--curval < 0)
  603.            curval = llen - 1;
  604.         break;
  605.      case F5:
  606.         curval = initval;
  607.         break;
  608.      default:
  609.             if (nonalpha(curkey)) {
  610.            if (checkkey && (ret = (*checkkey)(curkey)))
  611.           goto inpfldl_end;
  612.            break;                     /* non alphanum char */
  613.            }
  614.         j = curval;
  615.         for (i = 0; i < llen; ++i) {
  616.            if (++j >= llen)
  617.           j = 0;
  618.            if ((*list[j] & 0xdf) == (curkey & 0xdf)) {
  619.           curval = j;
  620.           break;
  621.           }
  622.            }
  623.      }
  624.       }
  625. inpfldl_end:
  626.    strcpy(fld,list[curval]);
  627.    lookatmouse = savelookatmouse;
  628.    return(ret);
  629. }
  630.  
  631.  
  632. /* --------------------------------------------------------------------- */
  633.  
  634. /* MCP 7-7-91, This is static code, but not called anywhere */
  635. #ifdef DELETE_UNUSED_CODE
  636.  
  637. /* compare for sort of type table */
  638. static int compare(const VOIDPTR i, const VOIDPTR j)
  639. {
  640.    return(strcmp(fractalspecific[(int)*((BYTE*)i)].name,
  641.            fractalspecific[(int)*((BYTE*)j)].name));
  642. }
  643.  
  644. /* --------------------------------------------------------------------- */
  645.  
  646. static void clear_line(int row, int start, int stop, int color) /* clear part of a line */
  647. {
  648.    int col;
  649.    for(col=start;col<= stop;col++)
  650.       putstring(row,col,color," ");
  651. }
  652.  
  653. #endif
  654.  
  655. /* --------------------------------------------------------------------- */
  656.  
  657. int get_fracttype()        /* prompt for and select fractal type */
  658. {
  659.    int done,i,oldfractype,t;
  660.    ENTER_OVLY(OVLY_PROMPTS1);
  661.    done = -1;
  662.    oldfractype = fractype;
  663.    while (1) {
  664.       if ((t = select_fracttype(fractype)) < 0)
  665.      break;
  666.       if ((i = select_type_params(t, fractype)) == 0) { /* ok, all done */
  667.      done = 0;
  668.      break;
  669.      }
  670.       if (i > 0) /* can't return to prior image anymore */
  671.      done = 1;
  672.       }
  673.    if (done < 0)
  674.       fractype = oldfractype;
  675.    curfractalspecific = &fractalspecific[fractype];
  676.    EXIT_OVLY;
  677.    return(done);
  678. }
  679.  
  680. struct FT_CHOICE {
  681.       char name[15];
  682.       int  num;
  683.       };
  684. static struct FT_CHOICE **ft_choices; /* for sel_fractype_help subrtn */
  685.  
  686. static int select_fracttype(int t) /* subrtn of get_fracttype, separated */
  687.                    /* so that storage gets freed up     */
  688. {
  689.    static char far head1[] = {"Select a Fractal Type"};
  690.    static char far head2[] = {"Select Orbit Algorithm for Julibrot"};
  691.    static char far instr[] = {"Press F2 for a description of the highlighted type"};
  692.    char head[40];
  693.    int oldhelpmode;
  694.    int numtypes, done;
  695.    int i, j;
  696. #define MAXFTYPES 200
  697.    char tname[40];
  698.    struct FT_CHOICE *choices[MAXFTYPES];
  699.    int attributes[MAXFTYPES];
  700.  
  701.    /* steal existing array for "choices" */
  702.    choices[0] = (struct FT_CHOICE *)boxy;
  703.    attributes[0] = 1;
  704.    for (i = 1; i < MAXFTYPES; ++i) {
  705.       choices[i] = choices[i-1] + 1;
  706.       attributes[i] = 1;
  707.       }
  708.    ft_choices = &choices[0];
  709.  
  710.    /* setup context sensitive help */
  711.    oldhelpmode = helpmode;
  712.    helpmode = HELPFRACTALS;
  713.  
  714.    if(julibrot)
  715.       far_strcpy(head,head2);
  716.    else
  717.       far_strcpy(head,head1);    
  718.    if (t == IFS3D) t = IFS;
  719.    i = j = -1;
  720.    while(fractalspecific[++i].name) {
  721.       if(julibrot)
  722.       {
  723.         int isinteger;
  724.         isinteger = curfractalspecific->isinteger; 
  725.     if (!((fractalspecific[i].flags & OKJB) && *fractalspecific[i].name != '*'))
  726.        continue;
  727.       }
  728.       if (fractalspecific[i].name[0] == '*')
  729.      continue;
  730.       strcpy(choices[++j]->name,fractalspecific[i].name);
  731.       choices[j]->name[14] = 0; /* safety */
  732.       choices[j]->num = i;    /* remember where the real item is */
  733.       }
  734.    numtypes = j + 1;
  735.    qsort(choices,numtypes,sizeof(char *),lccompare); /* sort list */
  736.    j = 0;
  737.    for (i = 0; i < numtypes; ++i) /* find starting choice in sorted list */
  738.       if (choices[i]->num == t || choices[i]->num == fractalspecific[t].tofloat)
  739.      j = i;
  740.  
  741.    tname[0] = 0;
  742.    done = fullscreen_choice(CHOICEHELP+8,head,NULL,instr,numtypes,
  743.          (char **)choices,attributes,0,0,0,j,NULL,tname,NULL,sel_fractype_help);
  744.    if (done >= 0)
  745.       done = choices[done]->num;
  746.    helpmode = oldhelpmode;
  747.    return(done);
  748. }
  749.  
  750. static int sel_fractype_help(int curkey,int choice)
  751. {
  752.    int oldhelpmode;
  753.    if (curkey == F2) {
  754.       oldhelpmode = helpmode;
  755.       helpmode = fractalspecific[(*(ft_choices+choice))->num].helptext;
  756.       help(0);
  757.       helpmode = oldhelpmode;
  758.       }
  759.    return(0);
  760. }
  761.  
  762. int select_type_params(    /* prompt for new fractal type parameters */
  763.     int newfractype,    /* new fractal type */
  764.     int oldfractype     /* previous fractal type */
  765.     )
  766. {
  767.    int ret,oldhelpmode;
  768.  
  769.    oldhelpmode = helpmode;
  770.    ret = 0;
  771.    fractype = newfractype;
  772.    curfractalspecific = &fractalspecific[fractype];
  773.  
  774.    if (fractype == LSYSTEM) {
  775.       helpmode = HT_LSYS;
  776.       if (get_file_entry(GETLSYS,"L-System",lsysmask,LFileName,LName) < 0) {
  777.      ret = 1;
  778.      goto sel_type_exit;
  779.      }
  780.       }
  781.    if (fractype == FORMULA || fractype == FFORMULA) {
  782.       helpmode = HT_FORMULA;
  783.       if (get_file_entry(GETFORMULA,"Formula",formmask,FormFileName,FormName) < 0) {
  784.      ret = 1;
  785.      goto sel_type_exit;
  786.      }
  787.       }
  788.    if (fractype == IFS || fractype == IFS3D) {
  789.       static char far ifsmsg[] = {
  790. #ifndef XFRACT
  791.          "Current IFS parameters have been edited but not saved.\n"
  792.          "Continue to replace them with new selection, cancel to keep them."};
  793. #else
  794.          "Current IFS parameters have been edited but not saved.\n\
  795. Continue to replace them with new selection, cancel to keep them."};
  796. #endif
  797.       helpmode = HT_IFS;
  798.       if (!ifs_defn || !ifs_changed || !stopmsg(22,ifsmsg))
  799.      if (get_file_entry(GETIFS,"IFS",ifsmask,IFSFileName,IFSName) < 0) {
  800.         ret = 1;
  801.         goto sel_type_exit;
  802.         }
  803.       }
  804.  
  805. /* Added the following to accommodate fn bifurcations.  JCO 7/2/92 */
  806.    if(((fractype == BIFURCATION) || (fractype == LBIFURCATION)) &&
  807.      !((oldfractype == BIFURCATION) || (oldfractype == LBIFURCATION)))
  808.         set_trig_array(0,"ident");
  809.    if(((fractype == BIFSTEWART) || (fractype == LBIFSTEWART)) &&
  810.      !((oldfractype == BIFSTEWART) || (oldfractype == LBIFSTEWART)))
  811.         set_trig_array(0,"ident");
  812.    if(((fractype == BIFLAMBDA) || (fractype == LBIFLAMBDA)) &&
  813.      !((oldfractype == BIFLAMBDA) || (oldfractype == LBIFLAMBDA)))
  814.         set_trig_array(0,"ident");
  815.    if(((fractype == BIFEQSINPI) || (fractype == LBIFEQSINPI)) &&
  816.      !((oldfractype == BIFEQSINPI) || (oldfractype == LBIFEQSINPI)))
  817.         set_trig_array(0,"sin");
  818.    if(((fractype == BIFADSINPI) || (fractype == LBIFADSINPI)) &&
  819.      !((oldfractype == BIFADSINPI) || (oldfractype == LBIFADSINPI)))
  820.         set_trig_array(0,"sin");
  821.  
  822.    set_default_parms();
  823.  
  824.    if (get_fract_params(0) < 0)
  825.       ret = 1;
  826.    else {
  827.       if (newfractype != oldfractype) {
  828.      invert = 0;
  829.      inversion[0] = inversion[1] = inversion[2] = 0;
  830.      }
  831.       }
  832.  
  833. sel_type_exit:
  834.    helpmode = oldhelpmode;
  835.    return(ret);
  836.  
  837. }
  838.  
  839. static void set_default_parms()
  840. {
  841.    int i;
  842.    xxmin = curfractalspecific->xmin;
  843.    xxmax = curfractalspecific->xmax;
  844.    yymin = curfractalspecific->ymin;
  845.    yymax = curfractalspecific->ymax;
  846.    xx3rd = xxmin;
  847.    yy3rd = yymin;
  848.    if (viewcrop && finalaspectratio != screenaspect)
  849.       aspectratio_crop(screenaspect,finalaspectratio);
  850.    for (i = 0; i < 4; i++) {
  851.       param[i] = curfractalspecific->paramvalue[i];
  852.       if (fractype != CELLULAR) /* don't round cellular */
  853.          roundfloatd(¶m[i]);
  854.    }
  855.    if(curfractalspecific->flags&MORE) {
  856.       int extra;
  857.       if((extra=find_extra_param(fractype)) > -1)
  858.          for(i=0;i<MAXPARAMS-4;i++) {
  859.             param[i+4] = moreparams[extra].paramvalue[i];
  860.          }
  861.    }
  862. }
  863.  
  864. #define MAXFRACTALS 25 
  865. extern int neworbittype, num_fractal_types;
  866.  
  867. int build_fractal_list(int fractals[], int *last_val, char *nameptr[])
  868. {
  869.     int numfractals,i;
  870.  
  871.     numfractals = 0;
  872.     for (i = 0; i < num_fractal_types; i++)
  873.     {
  874.         int isinteger;
  875.         isinteger = curfractalspecific->isinteger; 
  876.     if ((fractalspecific[i].flags & OKJB) && *fractalspecific[i].name != '*')
  877.     {
  878.         fractals[numfractals] = i;
  879.         if (i == neworbittype || i == fractalspecific[neworbittype].tofloat)
  880.         *last_val = numfractals;
  881.         nameptr[numfractals] = fractalspecific[i].name;
  882.         numfractals++;
  883.         if (numfractals >= MAXFRACTALS)
  884.         break;
  885.     }
  886.     }
  887.     return (numfractals);
  888. }
  889. char far v00[] = {"Orbit Algorithm"};
  890. char far v0a[] = {"From cx (real part)"};
  891. char far v1a[] = {"From cy (imaginary part)"};
  892. char far v2a[] = {"To   cx (real part)"};
  893. char far v3a[] = {"To   cy (imaginary part)"};
  894.  
  895. /* 4D Mandelbrot */
  896. char far v0b[] = {"From cj (3rd dim)"};
  897. char far v1b[] = {"From ck (4th dim)"};
  898. char far v2b[] = {"To   cj (3rd dim)"};
  899. char far v3b[] = {"To   ck (4th dim)"};
  900.  
  901. /* 4D Julia */
  902. char far v0c[] = {"From zj (3rd dim)"};
  903. char far v1c[] = {"From zk (4th dim)"};
  904. char far v2c[] = {"To   zj (3rd dim)"};
  905. char far v3c[] = {"To   zk (4th dim)"};
  906.  
  907. char far v4[] = {"Number of z pixels"};
  908. char far v5[] = {"Location of z origin"};
  909. char far v6[] = {"Depth of z"};
  910. char far v7[] = {"Screen height"};
  911. char far v8[] = {"Screen width"};
  912. char far v9[] = {"Distance to Screen"};
  913. char far v10[] = {"Distance between eyes"};
  914. char far v11[] = {"3D Mode"};
  915. char *juli3Doptions[] = {"monocular","lefteye","righteye","red-blue"};
  916.  
  917. /* --------------------------------------------------------------------- */
  918. int get_fract_params(int caller)    /* prompt for type-specific parms */
  919. {
  920.    char far *v0 = v0a;
  921.    char far *v1 = v1a;
  922.    char far *v2 = v2a;
  923.    char far *v3 = v3a;
  924.    char far *juliorbitname = NULL;
  925.    extern double mxmaxfp, mxminfp, mymaxfp, myminfp, originfp;
  926.    extern double depthfp, heightfp, widthfp, distfp, eyesfp;
  927.    extern int zdots; 
  928.    char *nameptr[MAXFRACTALS];
  929.    int fractals[MAXFRACTALS];
  930.    int i,j,k;
  931.    int curtype,numparams,numtrig,last_val;
  932.    struct fullscreenvalues paramvalues[30];
  933.    char far *choices[30];
  934.    int oldbailout;
  935.    int extra;
  936.    int numextra;
  937.    int promptnum;
  938.    char msg[120];
  939.    char *typename, *tmpptr;
  940.    char bailoutmsg[50];
  941.    int ret = 0;
  942.    int oldhelpmode;
  943.    static char far t11[] = {"Function (if needed by orbit formula)"};
  944.    static char far t1[] = {"First Function"};
  945.    static char far t2[] = {"Second Function"};
  946.    static char far t3[] = {"Third Function"};
  947.    static char far t4[] = {"Fourth Function"};
  948.    static char far *trg[] = {t1, t2, t3, t4};
  949.    extern char tstack[4096];
  950.    char *filename,*entryname;
  951.    FILE *entryfile;
  952.    char *trignameptr[25];
  953.    extern int  juli3Dmode;
  954.    struct fractalspecificstuff far *jborbit;
  955.    struct fractalspecificstuff far *savespecific;
  956.    int firstparm;
  957.    double oldparam[MAXPARAMS];
  958.    ENTER_OVLY(OVLY_PROMPTS1);
  959.    firstparm = 0;
  960.    if(fractype==JULIBROT || fractype==JULIBROTFP)
  961.       julibrot = 1;
  962.    else
  963.       julibrot = 0;
  964.    curtype = fractype;
  965.    if (curfractalspecific->name[0] == '*'
  966.      && (i = fractalspecific->tofloat) != NOFRACTAL
  967.      && fractalspecific[i].name[0] != '*')
  968.       curtype = i;
  969.    curfractalspecific = &fractalspecific[curtype];
  970. #if 0
  971.    if (curtype == IFS || curtype == IFS3D) {
  972.       ret = ((caller) ? edit_ifs_params() : 0);
  973.       goto gfp_exit;
  974.       }
  975. #endif
  976.    tstack[0] = 0;
  977.    if ((i = curfractalspecific->helpformula) < -1) {
  978.       if (i == -2) { /* special for formula */
  979.      filename = FormFileName;
  980.      entryname = FormName;
  981.      }
  982.       else {     /* -3, special for lsystem */
  983.      filename = LFileName;
  984.      entryname = LName;
  985.      }
  986.       if (find_file_item(filename,entryname,&entryfile) == 0) {
  987.      load_entry_text(entryfile,tstack,16);
  988.      fclose(entryfile);
  989.      }
  990.       }
  991.    else if (i >= 0) {
  992.       int c,lines;
  993.       if (i = read_help_topic(i,0,2000,tstack) > 0) i = 0;
  994.       tstack[2000-i] = 0;
  995.       i = j = lines = 0; k = 1;
  996.       while ((c = tstack[i++])) {
  997.      /* stop at ctl, blank, or line with col 1 nonblank, max 16 lines */
  998.      if (k && c == ' ' && ++k <= 5) { } /* skip 4 blanks at start of line */
  999.      else {
  1000.         if (c == '\n') {
  1001.            if (k) break; /* blank line */
  1002.            if (++lines >= 16) break;
  1003.            k = 1;
  1004.            }
  1005.         else if (c < 16) /* a special help format control char */
  1006.            break;
  1007.         else {
  1008.            if (k == 1) /* line starts in column 1 */
  1009.           break;
  1010.            k = 0;
  1011.            }
  1012.         tstack[j++] = c;
  1013.         }
  1014.      }
  1015.       while (--j >= 0 && tstack[j] == '\n') { }
  1016.       tstack[j+1] = 0;
  1017.       }
  1018. gfp_top:   
  1019.    promptnum = 0;
  1020.    if (julibrot)
  1021.    {
  1022.       i = select_fracttype(neworbittype);
  1023.       if (i < 0) 
  1024.       {
  1025.          if (ret == 0)
  1026.             ret = -1;
  1027.          julibrot = 0;
  1028.          goto gfp_exit;
  1029.       }
  1030.       else
  1031.          neworbittype = i;
  1032.       jborbit = &fractalspecific[neworbittype];
  1033.       juliorbitname = jborbit->name;
  1034.    }
  1035.    promptnum = 0;
  1036.  
  1037.    if(julibrot)
  1038.    {
  1039.       savespecific = curfractalspecific;
  1040.       curfractalspecific = jborbit;
  1041.       firstparm = 2; /* in most case Julibrot does not need first two parms */
  1042.       if(neworbittype == QUATJULFP     ||   /* all parameters needed */ 
  1043.          neworbittype == HYPERCMPLXJFP)
  1044.          firstparm = 0; 
  1045.       if(neworbittype == QUATFP        ||   /* no parameters needed */
  1046.          neworbittype == HYPERCMPLXFP)
  1047.          firstparm = 4; 
  1048.    }   
  1049.    numparams = 0;
  1050.    
  1051.    for (i = firstparm; i < 4; i++) 
  1052.    {
  1053.       char tmpbuf[30];
  1054.       if (curfractalspecific->param[i][0] == 0) 
  1055.          break;
  1056.       numparams++;
  1057.       choices[promptnum] = curfractalspecific->param[i];
  1058.       paramvalues[promptnum].type = 'd';
  1059.    
  1060.       if (choices[promptnum][0] == '+') 
  1061.       {
  1062.          choices[promptnum]++;
  1063.          paramvalues[promptnum].type = 'D';
  1064.       }
  1065.       sprintf(tmpbuf,"%.17g",param[i]);
  1066.       paramvalues[promptnum].uval.dval = atof(tmpbuf);
  1067.       oldparam[i] = paramvalues[promptnum++].uval.dval;
  1068.    }
  1069.    numextra = 0;
  1070.    if(curfractalspecific->flags&MORE && !julibrot)
  1071.    {
  1072.       if((extra=find_extra_param(fractype))<-1)
  1073.       {
  1074.          char msg[30];
  1075.          sprintf(msg,"find_extra_param error");
  1076.          stopmsg(0,msg);
  1077.       }
  1078.       else
  1079.       for (i=0;i<MAXPARAMS-4;i++) 
  1080.       {
  1081.          char tmpbuf[30];
  1082.          if (moreparams[extra].param[i][0] == 0) 
  1083.             break;
  1084.          numextra++;
  1085.          choices[promptnum] = moreparams[extra].param[i];
  1086.          paramvalues[promptnum].type = 'd';
  1087.          if (choices[promptnum][0] == '+') 
  1088.          {
  1089.             choices[promptnum]++;
  1090.             paramvalues[promptnum].type = 'D';
  1091.          }
  1092.          sprintf(tmpbuf,"%.17g",param[i+4]);
  1093.          paramvalues[promptnum].uval.dval = atof(tmpbuf);
  1094.          oldparam[i+4] = paramvalues[promptnum++].uval.dval;
  1095.       }
  1096.    }
  1097.    numtrig = (curfractalspecific->flags >> 6) & 7;
  1098.    if(curtype==FORMULA || curtype==FFORMULA ) {
  1099.       extern char maxfn;
  1100.       numtrig = maxfn;
  1101.       }
  1102.  
  1103.    if ((i = numtrigfn) > 27) i = 27;
  1104.    while (--i >= 0)
  1105.       trignameptr[i] = trigfn[i].name;
  1106.    for (i = 0; i < numtrig; i++) {
  1107.       paramvalues[promptnum].type = 'l';
  1108.       paramvalues[promptnum].uval.ch.val  = trigndx[i];
  1109.       paramvalues[promptnum].uval.ch.llen = numtrigfn;
  1110.       paramvalues[promptnum].uval.ch.vlen = 6;
  1111.       paramvalues[promptnum].uval.ch.list = trignameptr;
  1112.       choices[promptnum++] = trg[i];
  1113.       }
  1114.    if (*(typename = curfractalspecific->name) == '*')
  1115.         ++typename;
  1116.  
  1117.    if (curfractalspecific->orbit_bailout)
  1118.       if (potparam[0] != 0.0 && potparam[2] != 0.0) 
  1119.       {
  1120.      paramvalues[promptnum].type = '*';
  1121.      choices[promptnum++] = "Bailout: continuous potential (Y screen) value in use";
  1122.       }
  1123.       else 
  1124.       {
  1125.          static char far bailoutstr[] = {"Bailout value (0 means use default)"};
  1126.      choices[promptnum] = bailoutstr;
  1127.      paramvalues[promptnum].type = 'i';
  1128.      paramvalues[promptnum++].uval.ival = oldbailout = bailout;
  1129.      paramvalues[promptnum].type = '*';
  1130.      i = curfractalspecific->orbit_bailout;
  1131.      tmpptr = typename;
  1132.      if (usr_biomorph != -1) 
  1133.      {
  1134.         i = 100;
  1135.         tmpptr = "biomorph";
  1136.      }
  1137.      sprintf(bailoutmsg,"    (%s default is %d)",tmpptr,i);
  1138.      choices[promptnum++] = bailoutmsg;
  1139.       }
  1140.    if (julibrot)
  1141.    {
  1142.       switch(neworbittype)
  1143.       {
  1144.       case QUATFP:
  1145.       case HYPERCMPLXFP:
  1146.           v0 = v0b; v1 = v1b; v2 = v2b; v3 = v3b;
  1147.           break;
  1148.       case QUATJULFP:
  1149.       case HYPERCMPLXJFP:
  1150.           v0 = v0c; v1 = v1c; v2 = v2c; v3 = v3c;
  1151.           break;
  1152.       default:
  1153.           v0 = v0a; v1 = v1a; v2 = v2a; v3 = v3a;
  1154.          break;
  1155.       }
  1156.  
  1157.       curfractalspecific = savespecific;
  1158.       paramvalues[promptnum].uval.dval = mxmaxfp;
  1159.       paramvalues[promptnum].type = 'f';
  1160.       choices[promptnum++] = v0;
  1161.       paramvalues[promptnum].uval.dval = mymaxfp;
  1162.       paramvalues[promptnum].type = 'f';
  1163.       choices[promptnum++] = v1;
  1164.       paramvalues[promptnum].uval.dval = mxminfp;
  1165.       paramvalues[promptnum].type = 'f';
  1166.       choices[promptnum++] = v2;
  1167.       paramvalues[promptnum].uval.dval = myminfp;
  1168.       paramvalues[promptnum].type = 'f';
  1169.       choices[promptnum++] = v3;
  1170.       paramvalues[promptnum].uval.ival = zdots;
  1171.       paramvalues[promptnum].type = 'i';
  1172.       choices[promptnum++] = v4;
  1173.  
  1174.       paramvalues[promptnum].type = 'l';
  1175.       paramvalues[promptnum].uval.ch.val  = juli3Dmode;
  1176.       paramvalues[promptnum].uval.ch.llen = 4;
  1177.       paramvalues[promptnum].uval.ch.vlen = 9;
  1178.       paramvalues[promptnum].uval.ch.list = juli3Doptions;
  1179.       choices[promptnum++] = v11;
  1180.  
  1181.       paramvalues[promptnum].uval.dval = eyesfp;
  1182.       paramvalues[promptnum].type = 'f';
  1183.       choices[promptnum++] = v10;
  1184.       paramvalues[promptnum].uval.dval = originfp;
  1185.       paramvalues[promptnum].type = 'f';
  1186.       choices[promptnum++] = v5;
  1187.       paramvalues[promptnum].uval.dval = depthfp;
  1188.       paramvalues[promptnum].type = 'f';
  1189.       choices[promptnum++] = v6;
  1190.       paramvalues[promptnum].uval.dval = heightfp;
  1191.       paramvalues[promptnum].type = 'f';
  1192.       choices[promptnum++] = v7;
  1193.       paramvalues[promptnum].uval.dval = widthfp;
  1194.       paramvalues[promptnum].type = 'f';
  1195.       choices[promptnum++] = v8;
  1196.       paramvalues[promptnum].uval.dval = distfp;
  1197.       paramvalues[promptnum].type = 'f';
  1198.       choices[promptnum++] = v9;
  1199.    }
  1200.  
  1201.    if (curtype == INVERSEJULIA || curtype == INVERSEJULIAFP)
  1202.    {
  1203.       extern int  major_method;
  1204.       extern int  minor_method;
  1205.  
  1206. #ifdef RANDOM_RUN
  1207.       static char far JIIMstr1[] =
  1208.     "Breadth first, Depth first, Random Walk, Random Run?";
  1209.       static char *JIIMmethod[] = {"Breadth", "Depth", "Walk", "Run"};
  1210. #else
  1211.       static char far JIIMstr1[] =
  1212.     "Breadth first, Depth first, Random Walk";
  1213.       static char *JIIMmethod[] = {"Breadth", "Depth", "Walk"};
  1214. #endif
  1215.       static char far JIIMstr2[] =
  1216.     "Left first or Right first?";
  1217.       static char *JIIMleftright[] = {"Left", "Right"};
  1218.  
  1219.       choices[promptnum] = JIIMstr1;
  1220.       paramvalues[promptnum].type = 'l';
  1221.       paramvalues[promptnum].uval.ch.list = JIIMmethod;
  1222.       paramvalues[promptnum].uval.ch.vlen = 7;
  1223. #ifdef RANDOM_RUN
  1224.       paramvalues[promptnum].uval.ch.llen = 4;
  1225. #else
  1226.       paramvalues[promptnum].uval.ch.llen = 3; /* disable random run */
  1227. #endif
  1228.       paramvalues[promptnum++].uval.ch.val  = major_method;
  1229.  
  1230.       choices[promptnum] = JIIMstr2;
  1231.       paramvalues[promptnum].type = 'l';
  1232.       paramvalues[promptnum].uval.ch.list = JIIMleftright;
  1233.       paramvalues[promptnum].uval.ch.vlen = 5;
  1234.       paramvalues[promptnum].uval.ch.llen = 2;
  1235.       paramvalues[promptnum++].uval.ch.val  = minor_method;
  1236.    }
  1237.  
  1238.    if (caller                /* <z> command ? */
  1239.       && (display3d > 0 || promptnum == 0))
  1240.       {
  1241.        static char far msg[]={"Current type has no type-specific parameters"};
  1242.        stopmsg(20,msg);
  1243.        goto gfp_exit;
  1244.        }
  1245.    if(julibrot)
  1246.    sprintf(msg,
  1247.        "Julibrot Parameters (orbit= %s)\n(Press F6 for corner parameters)",
  1248.        juliorbitname);
  1249.    else
  1250.    sprintf(msg,
  1251.        "Parameters for fractal type %s\n(Press F6 for corner parameters)",
  1252.        typename);
  1253.  
  1254.    while (1) 
  1255.    {
  1256.       oldhelpmode = helpmode;
  1257.       helpmode = curfractalspecific->helptext;
  1258.       i = fullscreen_prompt(msg,promptnum,choices,paramvalues,0,0x40,tstack);
  1259.       helpmode = oldhelpmode;
  1260.       if (i < 0) 
  1261.       {
  1262.          if(julibrot)
  1263.            goto gfp_top;
  1264.      if (ret == 0)
  1265.         ret = -1;
  1266.      goto gfp_exit;
  1267.       }
  1268.       if (i != F6) 
  1269.          break;
  1270.       if (get_corners() > 0)
  1271.      ret = 1;
  1272.      }
  1273.      promptnum = 0;
  1274.      for ( i = firstparm; i < numparams+firstparm; i++) 
  1275.      {
  1276.         if (oldparam[i] != paramvalues[promptnum].uval.dval) 
  1277.         {
  1278.            param[i] = paramvalues[promptnum].uval.dval;
  1279.           ret = 1;
  1280.         }
  1281.         ++promptnum;
  1282.     }
  1283.      for(i=0;i<numextra;i++)
  1284.      {
  1285.         if(oldparam[i+4] != paramvalues[promptnum].uval.dval)
  1286.         {
  1287.            param[i+4] = paramvalues[promptnum].uval.dval;
  1288.            ret = 1;
  1289.         }
  1290.         ++promptnum;
  1291.      }
  1292.  
  1293.    for ( i = 0; i < numtrig; i++) 
  1294.    {
  1295.       if (paramvalues[promptnum].uval.ch.val != trigndx[i]) 
  1296.       {
  1297.      set_trig_array(i,trigfn[paramvalues[promptnum].uval.ch.val].name);
  1298.      ret = 1;
  1299.       }
  1300.       ++promptnum;
  1301.    }
  1302.  
  1303.    if(julibrot)
  1304.    {
  1305.       savespecific = curfractalspecific;
  1306.       curfractalspecific = jborbit;
  1307.    }   
  1308.  
  1309.    if (curfractalspecific->orbit_bailout)
  1310.       if (potparam[0] != 0.0 && potparam[2] != 0.0) 
  1311.      promptnum++;
  1312.       else 
  1313.       {
  1314.          bailout = paramvalues[promptnum++].uval.ival;
  1315. #ifndef XFRACT
  1316.          if (bailout != 0 && (bailout < 4 || bailout > 32000))
  1317. #else /* We have big integers, so why not allow big bailouts? */
  1318.          if (bailout != 0 && (bailout < 4))
  1319. #endif
  1320.         bailout = oldbailout;
  1321.          if (bailout != oldbailout)
  1322.         ret = 1;
  1323.      promptnum++;
  1324.       }
  1325.  
  1326.      if (julibrot)
  1327.      {
  1328.     mxmaxfp    = paramvalues[promptnum++].uval.dval;
  1329.     mymaxfp    = paramvalues[promptnum++].uval.dval;
  1330.     mxminfp    = paramvalues[promptnum++].uval.dval;
  1331.     myminfp    = paramvalues[promptnum++].uval.dval;
  1332.     zdots      = paramvalues[promptnum++].uval.ival;
  1333.         juli3Dmode = paramvalues[promptnum++].uval.ch.val;
  1334.     eyesfp     = paramvalues[promptnum++].uval.dval;
  1335.     originfp   = paramvalues[promptnum++].uval.dval;
  1336.     depthfp    = paramvalues[promptnum++].uval.dval;
  1337.     heightfp   = paramvalues[promptnum++].uval.dval;
  1338.     widthfp    = paramvalues[promptnum++].uval.dval;
  1339.     distfp     = paramvalues[promptnum++].uval.dval;
  1340.         ret = 1;  /* force new calc since not resumable anyway */
  1341.      }
  1342.       if (curtype == INVERSEJULIA || curtype == INVERSEJULIAFP)
  1343.       {
  1344.      extern int major_method, minor_method;
  1345.  
  1346.      if (paramvalues[promptnum].uval.ch.val != major_method ||
  1347.          paramvalues[promptnum+1].uval.ch.val != minor_method)
  1348.         ret = 1;
  1349.  
  1350.      major_method = paramvalues[promptnum  ].uval.ch.val;
  1351.      minor_method = paramvalues[promptnum+1].uval.ch.val;
  1352.       }
  1353.  
  1354. gfp_exit:
  1355.    curfractalspecific = &fractalspecific[fractype];
  1356.    EXIT_OVLY;
  1357.    return(ret);
  1358. }
  1359.  
  1360. int find_extra_param(int type)
  1361. {
  1362.    int i,ret,curtyp;
  1363.    ret = -1;
  1364.    i= -1;
  1365.    while((curtyp=moreparams[++i].type) != type && curtyp != -1);
  1366.    if(curtyp == type)
  1367.      ret = i;
  1368.    return(ret);
  1369. }     
  1370.  
  1371.  
  1372. int check_orbit_name(char *orbitname)
  1373. {
  1374.    int i, numtypes, bad;
  1375.    char *nameptr[MAXFRACTALS];
  1376.    int fractals[MAXFRACTALS];
  1377.    int curtype,numparams,numtrig,last_val;
  1378.  
  1379.    ENTER_OVLY(OVLY_PROMPTS1);
  1380.    numtypes = build_fractal_list(fractals, &last_val, nameptr);
  1381.    bad = 1;
  1382.    for(i=0;i<numtypes;i++)
  1383.    {
  1384.       if(strcmp(orbitname,nameptr[i]) == 0)
  1385.       {
  1386.          neworbittype = fractals[i];
  1387.          bad = 0;
  1388.          break;
  1389.       }
  1390.    }
  1391.    EXIT_OVLY;
  1392.    return(bad);
  1393. }
  1394.  
  1395. /* --------------------------------------------------------------------- */
  1396.  
  1397.    static FILE *gfe_file;
  1398.  
  1399. long get_file_entry(int type,char *title,char *fmask,
  1400.               char *filename,char *entryname)
  1401. {
  1402.    /* Formula, LSystem, etc type structure, select from file */
  1403.    /* containing definitions in the form    name { ... }     */
  1404.    int newfile,firsttry;
  1405.    long entry_pointer;
  1406.    extern char tstack[4096];
  1407.    newfile = 0;
  1408.    while (1) {
  1409.       firsttry = 0;
  1410.       /* pb: binary mode used here - it is more work, but much faster, */
  1411.       /*     especially when ftell or fgetpos is used               */
  1412.       while (newfile || (gfe_file = fopen(filename, "rb")) == NULL) {
  1413.      char buf[60];
  1414.      newfile = 0;
  1415.      if (firsttry) {
  1416.         extern char s_cantfind[];
  1417.         sprintf(temp1,s_cantfind, filename);
  1418.         stopmsg(0,temp1);
  1419.         }
  1420.      sprintf(buf,"Select %s File",title);
  1421.      if (getafilename(buf,fmask,filename) < 0)
  1422.         return -1;
  1423.      firsttry = 1; /* if around open loop again it is an error */
  1424.      }
  1425.       setvbuf(gfe_file,tstack,_IOFBF,4096); /* improves speed when file is big */
  1426.       newfile = 0;
  1427.       if ((entry_pointer = gfe_choose_entry(type,title,filename,entryname)) == -2) {
  1428.      newfile = 1; /* go to file list, */
  1429.      continue;    /* back to getafilename */
  1430.      }
  1431.       if (entry_pointer == -1)
  1432.      return -1;
  1433.       switch (type) {
  1434.      case GETFORMULA:
  1435.         if (RunForm(entryname) == 0) return 0;
  1436.         break;
  1437.      case GETLSYS:
  1438.         if (LLoad() == 0) return 0;
  1439.         break;
  1440.      case GETIFS:
  1441.         if (ifsload() == 0) {
  1442.            fractype = (ifs_type == 0) ? IFS : IFS3D;
  1443.            curfractalspecific = &fractalspecific[fractype];
  1444.            set_default_parms(); /* to correct them if 3d */
  1445.            return 0;
  1446.            }
  1447.         break;
  1448.      case GETPARM:
  1449.         return entry_pointer;
  1450.      }
  1451.       }
  1452. }
  1453.  
  1454.    struct entryinfo {
  1455.       char name[ITEMNAMELEN+1];
  1456.       long point; /* points to the ( or the { following the name */
  1457.       };
  1458.    static struct entryinfo **gfe_choices; /* for format_getparm_line */
  1459.    static char *gfe_title;
  1460.  
  1461. static long gfe_choose_entry(int type,char *title,char *filename,char *entryname)
  1462. /* subrtn of get_file_entry, separated so that storage gets freed up */
  1463. {
  1464. #define MAXENTRIES 200
  1465.    static char far instr[]={"Press F6 to select different file, F2 for details of highlighted choice"};
  1466.    int numentries, i;
  1467.    char buf[101];
  1468.    struct entryinfo *choices[MAXENTRIES];
  1469.    int attributes[MAXENTRIES];
  1470.    void (*formatitem)();
  1471.    int boxwidth,boxdepth,colwidth;
  1472.    long file_offset,name_offset;
  1473.    extern struct entryinfo boxx[MAXENTRIES];
  1474.  
  1475.    gfe_choices = &choices[0];
  1476.    gfe_title = title;
  1477.    for (i = 0; i < MAXENTRIES; i++) {
  1478.       attributes[i] = 1;
  1479.       choices[i] = &boxx[i];
  1480.       }
  1481.    numentries = 0;
  1482.    file_offset = -1;
  1483.  
  1484.    helptitle(); /* to display a clue when file big and next is slow */
  1485.  
  1486.    while (1) { /* scan the file for entry names */
  1487.       int c,len;
  1488.       do {
  1489.      ++file_offset;
  1490.      c = getc(gfe_file);
  1491.      } while (c == ' ' /* skip white space */
  1492.            || c == '\t' || c == '\n' || c == '\r');
  1493.       if (c == ';') {
  1494.      do {
  1495.         ++file_offset;
  1496.         c = getc(gfe_file);
  1497.         } while (c != '\n' && c != EOF && c != '\032');
  1498.      if (c == EOF || c == '\032') break;
  1499.      continue;
  1500.      }
  1501.       name_offset = file_offset;
  1502.       len = 0; /* next equiv roughly to fscanf(..,"%40[^ \n\r\t({\032]",buf) */
  1503.       while (c != ' ' && c != '\t' && c != '('
  1504.     && c != '{' && c != '\n' && c != '\r' && c != EOF && c != '\032') {
  1505.      if (len < 40) buf[len++] = c;
  1506.      c = getc(gfe_file);
  1507.      ++file_offset;
  1508.      }
  1509.       buf[len] = 0;
  1510.       while (c != '{' && c != '\n' && c != '\r' && c != EOF && c != '\032') {
  1511.      c = getc(gfe_file);
  1512.      ++file_offset;
  1513.      }
  1514.       if (c == '{') {
  1515.      while (c != '}' && c != EOF && c != '\032') {
  1516.         c = getc(gfe_file);
  1517.         ++file_offset;
  1518.         }
  1519.      if (c != '}') break;
  1520.      buf[ITEMNAMELEN] = 0;
  1521.      if (buf[0] != 0 && stricmp(buf,"comment") != 0) {
  1522.         strcpy(boxx[numentries].name,buf);
  1523.         boxx[numentries].point = name_offset;
  1524.         if (++numentries >= MAXENTRIES) {
  1525.            sprintf(buf,"Too many entries in file, first %d used",MAXENTRIES);
  1526.            stopmsg(0,buf);
  1527.            break;
  1528.            }
  1529.         }
  1530.      }
  1531.       else
  1532.      if (c == EOF || c == '\032') break;
  1533.       }
  1534.  
  1535.    if (numentries == 0) {
  1536.       static char far msg[]={"File doesn't contain any valid entries"};
  1537.       stopmsg(0,msg);
  1538.       fclose(gfe_file);
  1539.       return -2; /* back to file list */
  1540.       }
  1541.  
  1542.    qsort((char **)choices,numentries,sizeof(char *),lccompare);
  1543.  
  1544.    strcpy(buf,entryname); /* preset to last choice made */
  1545.    sprintf(temp1,"%s Selection\nFile: %s",title,filename);
  1546.    formatitem = NULL;
  1547.    boxwidth = colwidth = boxdepth = 0;
  1548.    if (type == GETPARM) {
  1549.       formatitem = format_parmfile_line;
  1550.       boxwidth = 1;
  1551.       boxdepth = 16;
  1552.       colwidth = 76;
  1553.       }
  1554.    i = fullscreen_choice(8,temp1,NULL,instr,numentries,(char **)choices,
  1555.                            attributes,boxwidth,boxdepth,colwidth,0,
  1556.                formatitem,buf,NULL,check_gfe_key);
  1557.    fclose(gfe_file);
  1558.    if (i < 0) {
  1559.       if (i == 0-F6)
  1560.      return -2; /* go back to file list */
  1561.       return -1;    /* cancel */
  1562.       }
  1563.    strcpy(entryname, choices[i]->name);
  1564.    return(choices[i]->point);
  1565. }
  1566.  
  1567. static int check_gfe_key(int curkey,int choice)
  1568. {
  1569.    char infhdg[60];
  1570.    char far *infbuf;
  1571.  
  1572.    if (curkey == F6)
  1573.       return 0-F6;
  1574.    if (curkey == F2) {
  1575.       infbuf = MK_FP(extraseg,0);
  1576.       fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
  1577.       load_entry_text(gfe_file,infbuf,16);
  1578.       strcpy(infhdg,gfe_title);
  1579.       strcat(infhdg," file entry:\n\n");
  1580.  /* ... instead, call help with buffer?  heading added */
  1581.       stackscreen();
  1582.       helptitle();
  1583.       setattr(1,0,C_GENERAL_MED,24*80);
  1584.       putstring(2,1,C_GENERAL_HI,infhdg);
  1585.       textcbase = 2; /* left margin is 2 */
  1586.       putstring(-1,0,C_GENERAL_MED,infbuf);
  1587.       putstring(-1,0,C_GENERAL_LO,"\n\n\nPress any key to return to selection list");
  1588.       textcbase = 0;
  1589.       movecursor(25,80);
  1590.       getakeynohelp();
  1591.       unstackscreen();
  1592.       }
  1593.    return 0;
  1594. }
  1595.  
  1596. static void load_entry_text(FILE *entfile,char far *buf,int maxlines)
  1597. {
  1598.    int linect,linelen,c;
  1599.    linect = linelen = 0;
  1600.    while ((c = fgetc(entfile)) != EOF && c != '\032') {
  1601.       if (c != '\r') {
  1602.      if (c == '\t') {
  1603.         while ((linelen % 8) != 7 && linelen < 75) { /* 76 wide max */
  1604.            *(buf++) = ' ';
  1605.            ++linelen;
  1606.            }
  1607.         c = ' ';
  1608.         }
  1609.      if (c == '\n') {
  1610.         if (++linect > maxlines) break;
  1611.         linelen = -1;
  1612.         }
  1613.      if (++linelen > 75) {
  1614.         if (linelen == 76) *(buf++) = '\021';
  1615.         }
  1616.      else
  1617.         *(buf++) = c;
  1618.      if (c == '}') break;
  1619.      }
  1620.       }
  1621.    *buf = 0;
  1622. }
  1623.  
  1624. static void format_parmfile_line(int choice,char *buf)
  1625. {
  1626.    int c,i;
  1627.    char line[80];
  1628.    fseek(gfe_file,gfe_choices[choice]->point,SEEK_SET);
  1629.    while (getc(gfe_file) != '{') { }
  1630.    while ((c = getc(gfe_file)) == ' ' || c == '\t' || c == ';') { }
  1631.    i = 0;
  1632.    while (i < 56 && c != '\n' && c != '\r' && c != EOF && c != '\032') {
  1633.       line[i++] = (c == '\t') ? ' ' : c;
  1634.       c = getc(gfe_file);
  1635.       }
  1636.    line[i] = 0;
  1637.    sprintf(buf,"%-20s%-56s",gfe_choices[choice]->name,line);
  1638. }
  1639.  
  1640. /* --------------------------------------------------------------------- */
  1641.  
  1642. int get_fract3d_params() /* prompt for 3D fractal parameters */
  1643. {
  1644.    int i,k,ret,oldhelpmode;
  1645.    static char far hdg[] = {"3D Parameters"};
  1646.    static char far p1[] = {"X-axis rotation in degrees"};
  1647.    static char far p2[] = {"Y-axis rotation in degrees"};
  1648.    static char far p3[] = {"Z-axis rotation in degrees"};
  1649.    static char far p4[] = {"Perspective distance [1 - 999, 0 for no persp]"};
  1650.    static char far p5[] = {"X shift with perspective (positive = right)"};
  1651.    static char far p6[] = {"Y shift with perspective (positive = up   )"};
  1652.    static char far p7[] = {"Stereo (R/B 3D)? (0=no,1=alternate,2=superimpose,3=photo)"};
  1653.    static char far *ifs3d_prompts[8] = {p1, p2, p3, p4, p5, p6, p7};
  1654.    struct fullscreenvalues uvalues[20];
  1655.  
  1656.    ENTER_OVLY(OVLY_PROMPTS1);
  1657.    stackscreen();
  1658.  
  1659.    k = 0;
  1660.    uvalues[k].type = 'i';
  1661.    uvalues[k++].uval.ival = XROT;
  1662.    uvalues[k].type = 'i';
  1663.    uvalues[k++].uval.ival = YROT;
  1664.    uvalues[k].type = 'i';
  1665.    uvalues[k++].uval.ival = ZROT;
  1666.    uvalues[k].type = 'i';
  1667.    uvalues[k++].uval.ival = ZVIEWER;
  1668.    uvalues[k].type = 'i';
  1669.    uvalues[k++].uval.ival = XSHIFT;
  1670.    uvalues[k].type = 'i';
  1671.    uvalues[k++].uval.ival = YSHIFT;
  1672.    uvalues[k].type = 'i';
  1673.    uvalues[k++].uval.ival = glassestype;
  1674.  
  1675.    oldhelpmode = helpmode;
  1676.    helpmode = HELP3DFRACT;
  1677.    i = fullscreen_prompt(hdg,k,ifs3d_prompts,uvalues,0,0,NULL);
  1678.    helpmode = oldhelpmode;
  1679.    if (i < 0) {
  1680.       ret = -1;
  1681.       goto get_f3d_exit;
  1682.       }
  1683.  
  1684.    ret = k = 0;
  1685.    XROT    =  uvalues[k++].uval.ival;
  1686.    YROT    =  uvalues[k++].uval.ival;
  1687.    ZROT    =  uvalues[k++].uval.ival;
  1688.    ZVIEWER =  uvalues[k++].uval.ival;
  1689.    XSHIFT  =  uvalues[k++].uval.ival;
  1690.    YSHIFT  =  uvalues[k++].uval.ival;
  1691.    glassestype = uvalues[k++].uval.ival;
  1692.    if (glassestype < 0 || glassestype > 3) glassestype = 0;
  1693.    if (glassestype)
  1694.       if (get_funny_glasses_params() || check_mapfile())
  1695.      ret = -1;
  1696.  
  1697. get_f3d_exit:
  1698.    unstackscreen();
  1699.    EXIT_OVLY;
  1700.    return(ret);
  1701. }
  1702.  
  1703. /* --------------------------------------------------------------------- */
  1704. /* These macros streamline the "save near space" campaign */ 
  1705.  
  1706. #define LOADPROMPTS3D(X)     {\
  1707.    static char far tmp[] = { X };\
  1708.    prompts3d[++k]= tmp;\
  1709.    }
  1710.  
  1711.  
  1712. int get_3d_params()    /* prompt for 3D parameters */
  1713. {
  1714.    static char far hdg[]={"3D Mode Selection"};
  1715.    static char far hdg1[]={"Select 3D Fill Type"};
  1716.    char *choices[10];
  1717.    int attributes[21];
  1718.    int sphere;
  1719.    char far *s;
  1720.    static char far s1[] = {"              Sphere 3D Parameters\n\
  1721. Sphere is on its side; North pole to right\n\
  1722. Long. 180 is top, 0 is bottom; Lat. -90 is left, 90 is right"};
  1723.    static char s2[]={"              Planar 3D Parameters\n\
  1724. Pre-rotation X axis is screen top; Y axis is left side\n\
  1725. Pre-rotation Z axis is coming at you out of the screen!"};
  1726.    char far *prompts3d[21];
  1727.    struct fullscreenvalues uvalues[21];
  1728.    int i, k;
  1729.    int oldhelpmode;
  1730.  
  1731.    ENTER_OVLY(OVLY_PROMPTS1);
  1732.  
  1733. #ifdef WINFRACT
  1734.      {
  1735.      extern int far wintext_textmode;
  1736.     
  1737.      if (wintext_textmode != 2)  /* are we in textmode? */
  1738.          return(0);              /* no - prompts are already handled */
  1739.      }
  1740. #endif
  1741. restart_1:
  1742.     if (Targa_Out && overlay3d)
  1743.         Targa_Overlay = 1;
  1744.  
  1745.    k= -1;
  1746.  
  1747.    LOADPROMPTS3D("Preview Mode?");
  1748.    uvalues[k].type = 'y';
  1749.    uvalues[k].uval.ch.val = preview;
  1750.  
  1751.    LOADPROMPTS3D("    Show Box?");
  1752.    uvalues[k].type = 'y';
  1753.    uvalues[k].uval.ch.val = showbox;
  1754.    
  1755.    LOADPROMPTS3D("Coarseness, preview/grid/ray (in y dir)");
  1756.    uvalues[k].type = 'i';
  1757.    uvalues[k].uval.ival = previewfactor;
  1758.  
  1759.    LOADPROMPTS3D("Spherical Projection?");
  1760.    uvalues[k].type = 'y';
  1761.    uvalues[k].uval.ch.val = sphere = SPHERE;
  1762.  
  1763.    LOADPROMPTS3D("Stereo (R/B 3D)? (0=no,1=alternate,2=superimpose,3=photo)");
  1764.    uvalues[k].type = 'i';
  1765.    uvalues[k].uval.ival = glassestype;
  1766.  
  1767.    LOADPROMPTS3D("Ray trace out? (0=No, 1=DKB/POVRay, 2=VIVID, 3=RAW,");
  1768.    uvalues[k].type = 'i';
  1769.    uvalues[k].uval.ival = RAY;
  1770.  
  1771.    LOADPROMPTS3D("                4=MTV, 5=RAYSHADE, 6=ACROSPIN, 7=DXF)");
  1772.    uvalues[k].type = '*';
  1773.  
  1774.    LOADPROMPTS3D("    Brief output?");
  1775.    uvalues[k].type = 'y';
  1776.    uvalues[k].uval.ch.val = BRIEF;
  1777.  
  1778.    check_writefile(ray_name,".ray");
  1779.    LOADPROMPTS3D("    Output File Name");
  1780.    uvalues[k].type = 's';
  1781.    strcpy(uvalues[k].uval.sval,ray_name);
  1782.  
  1783.    LOADPROMPTS3D("Targa output?");
  1784.    uvalues[k].type = 'y';
  1785.    uvalues[k].uval.ch.val = Targa_Out;
  1786.  
  1787.    oldhelpmode = helpmode;
  1788.    helpmode = HELP3DMODE;
  1789.  
  1790.    k = fullscreen_prompt(hdg,k+1,prompts3d,uvalues,0,0,NULL);
  1791.    helpmode = oldhelpmode;
  1792.    if (k < 0) {
  1793.       EXIT_OVLY;
  1794.       return(-1);
  1795.       }
  1796.  
  1797.    k=0;
  1798.  
  1799.    preview = uvalues[k++].uval.ch.val;
  1800.  
  1801.    showbox = uvalues[k++].uval.ch.val;
  1802.  
  1803.    previewfactor  = uvalues[k++].uval.ival;
  1804.  
  1805.    sphere = uvalues[k++].uval.ch.val;
  1806.  
  1807.    glassestype = uvalues[k++].uval.ival;
  1808.  
  1809.    RAY = uvalues[k++].uval.ival;
  1810.    k++;
  1811.    {
  1812.       static char far msg[] = {
  1813. "DKB/POV-Ray output is obsolete but still works. See \"Ray Tracing Output\" in\n\
  1814. the online documentation."};
  1815.       if(RAY == 1)
  1816.          stopmsg(0,msg);
  1817.    }
  1818.    BRIEF = uvalues[k++].uval.ch.val;
  1819.  
  1820.    strcpy(ray_name,uvalues[k++].uval.sval);
  1821.  
  1822.    Targa_Out = uvalues[k++].uval.ch.val;
  1823.  
  1824.    /* check ranges */
  1825.    if(previewfactor < 2)
  1826.       previewfactor = 2;
  1827.    if(previewfactor > 2000)
  1828.       previewfactor = 2000;
  1829.  
  1830.    if(sphere && !SPHERE)
  1831.    {
  1832.       SPHERE = TRUE;
  1833.       set_3d_defaults();
  1834.    }
  1835.    else if(!sphere && SPHERE)
  1836.    {
  1837.       SPHERE = FALSE;
  1838.       set_3d_defaults();
  1839.    }
  1840.  
  1841.    if(glassestype < 0)
  1842.       glassestype = 0;
  1843.    if(glassestype > 3)
  1844.       glassestype = 3;
  1845.    if(glassestype)
  1846.       whichimage = 1;
  1847.  
  1848.    if (RAY < 0)
  1849.       RAY = 0;
  1850.    if (RAY > 7)
  1851.       RAY = 7;
  1852.  
  1853.    if (!RAY)
  1854.    {
  1855.       k = 0;
  1856.       choices[k++] = "make a surface grid";
  1857.       choices[k++] = "just draw the points";
  1858.       choices[k++] = "connect the dots (wire frame)";
  1859.       choices[k++] = "surface fill (colors interpolated)";
  1860.       choices[k++] = "surface fill (colors not interpolated)";
  1861.       choices[k++] = "solid fill (bars up from \"ground\")";
  1862.       if(SPHERE)
  1863.       {
  1864.          choices[k++] = "light source";
  1865.       }
  1866.       else
  1867.       {
  1868.          choices[k++] = "light source before transformation";
  1869.          choices[k++] = "light source after transformation";
  1870.       }
  1871.       for (i = 0; i < k; ++i)
  1872.      attributes[i] = 1;
  1873.       helpmode = HELP3DFILL;
  1874.       i = fullscreen_choice(CHOICEHELP,hdg1,NULL,NULL,k,choices,attributes,
  1875.                   0,0,0,FILLTYPE+1,NULL,NULL,NULL,NULL);
  1876.       helpmode = oldhelpmode;
  1877.       if (i < 0)
  1878.      goto restart_1;
  1879.       FILLTYPE = i-1;
  1880.  
  1881.       if(glassestype)
  1882.       {
  1883.      if(get_funny_glasses_params())
  1884.             goto restart_1;
  1885.          }
  1886.          if (check_mapfile())
  1887.              goto restart_1;
  1888.       }
  1889.    restart_3:
  1890.  
  1891.    if(SPHERE)
  1892.    {
  1893.       k = -1;
  1894.       LOADPROMPTS3D("Longitude start (degrees)");
  1895.       LOADPROMPTS3D("Longitude stop  (degrees)");
  1896.       LOADPROMPTS3D("Latitude start  (degrees)");
  1897.       LOADPROMPTS3D("Latitude stop   (degrees)");
  1898.       LOADPROMPTS3D("Radius scaling factor in pct");
  1899.    }
  1900.    else
  1901.    {
  1902.       k = -1;
  1903.       if (!RAY)
  1904.       {
  1905.          LOADPROMPTS3D("X-axis rotation in degrees");
  1906.          LOADPROMPTS3D("Y-axis rotation in degrees");
  1907.          LOADPROMPTS3D("Z-axis rotation in degrees");
  1908.       }
  1909.       LOADPROMPTS3D("X-axis scaling factor in pct");
  1910.       LOADPROMPTS3D("Y-axis scaling factor in pct");
  1911.    }
  1912.    k = -1;
  1913.    if (!(RAY && !SPHERE))
  1914.    {
  1915.       uvalues[++k].uval.ival   = XROT     ;
  1916.       uvalues[k].type = 'i';
  1917.       uvalues[++k].uval.ival   = YROT     ;
  1918.       uvalues[k].type = 'i';
  1919.       uvalues[++k].uval.ival   = ZROT     ;
  1920.       uvalues[k].type = 'i';
  1921.    }
  1922.    uvalues[++k].uval.ival   = XSCALE    ;
  1923.    uvalues[k].type = 'i';
  1924.  
  1925.    uvalues[++k].uval.ival   = YSCALE    ;
  1926.    uvalues[k].type = 'i';
  1927.  
  1928.    LOADPROMPTS3D("Surface Roughness scaling factor in pct");
  1929.    uvalues[k].type = 'i';
  1930.    uvalues[k].uval.ival = ROUGH     ;
  1931.  
  1932.    LOADPROMPTS3D("'Water Level' (minimum color value)");
  1933.    uvalues[k].type = 'i';
  1934.    uvalues[k].uval.ival = WATERLINE ;
  1935.  
  1936.    if(!RAY)
  1937.    {
  1938.       LOADPROMPTS3D("Perspective distance [1 - 999, 0 for no persp])");
  1939.       uvalues[k].type = 'i';
  1940.       uvalues[k].uval.ival = ZVIEWER     ;
  1941.  
  1942.       LOADPROMPTS3D("X shift with perspective (positive = right)");
  1943.       uvalues[k].type = 'i';
  1944.       uvalues[k].uval.ival = XSHIFT    ;
  1945.    
  1946.       LOADPROMPTS3D("Y shift with perspective (positive = up   )");
  1947.       uvalues[k].type = 'i';
  1948.       uvalues[k].uval.ival = YSHIFT    ;
  1949.    
  1950.       LOADPROMPTS3D("Image non-perspective X adjust (positive = right)");
  1951.       uvalues[k].type = 'i';
  1952.       uvalues[k].uval.ival = xtrans    ;
  1953.    
  1954.       LOADPROMPTS3D("Image non-perspective Y adjust (positive = up)");
  1955.       uvalues[k].type = 'i';
  1956.       uvalues[k].uval.ival = ytrans    ;
  1957.    
  1958.       LOADPROMPTS3D("First transparent color");
  1959.       uvalues[k].type = 'i';
  1960.       uvalues[k].uval.ival = transparent[0];
  1961.    
  1962.       LOADPROMPTS3D("Last transparent color");
  1963.       uvalues[k].type = 'i';
  1964.       uvalues[k].uval.ival = transparent[1];
  1965.    }
  1966.  
  1967.    LOADPROMPTS3D("Randomize Colors      (0 - 7, '0' disables)");
  1968.    uvalues[k].type = 'i';
  1969.    uvalues[k++].uval.ival = RANDOMIZE;
  1970.  
  1971.    if (SPHERE)
  1972.       s = s1;
  1973.    else
  1974.       s = s2;
  1975.  
  1976.    helpmode = HELP3DPARMS;
  1977.    k = fullscreen_prompt(s,k,prompts3d,uvalues,0,0,NULL);
  1978.    helpmode = oldhelpmode;
  1979.    if (k < 0)
  1980.       goto restart_1;
  1981.  
  1982.    k = 0;
  1983.    if (!(RAY && !SPHERE))
  1984.    {
  1985.       XROT    = uvalues[k++].uval.ival;
  1986.       YROT    = uvalues[k++].uval.ival;
  1987.       ZROT    = uvalues[k++].uval.ival;
  1988.    }
  1989.    XSCALE     = uvalues[k++].uval.ival;
  1990.    YSCALE     = uvalues[k++].uval.ival;
  1991.    ROUGH      = uvalues[k++].uval.ival;
  1992.    WATERLINE  = uvalues[k++].uval.ival;
  1993.    if (!RAY)
  1994.    {
  1995.       ZVIEWER = uvalues[k++].uval.ival;
  1996.    XSHIFT     = uvalues[k++].uval.ival;
  1997.    YSHIFT     = uvalues[k++].uval.ival;
  1998.    xtrans     = uvalues[k++].uval.ival;
  1999.    ytrans     = uvalues[k++].uval.ival;
  2000.    transparent[0] = uvalues[k++].uval.ival;
  2001.    transparent[1] = uvalues[k++].uval.ival;
  2002.    }
  2003.    RANDOMIZE  = uvalues[k++].uval.ival;
  2004.    if (RANDOMIZE >= 7) RANDOMIZE = 7;
  2005.    if (RANDOMIZE <= 0) RANDOMIZE = 0;
  2006.  
  2007.    if ((Targa_Out || ILLUMINE || RAY))
  2008.     if(get_light_params())
  2009.         goto restart_3;
  2010.  
  2011. EXIT_OVLY;
  2012. return(0);
  2013. }
  2014.  
  2015. /* --------------------------------------------------------------------- */
  2016. static int get_light_params()
  2017. {
  2018.    static char far hdg[]={"Light Source Parameters"};
  2019.    char far *prompts3d[13];
  2020.    struct fullscreenvalues uvalues[13];
  2021.  
  2022.    int k;
  2023.    int oldhelpmode;
  2024.  
  2025.    /* defaults go here */
  2026.  
  2027.    k = -1;
  2028.  
  2029.    if (ILLUMINE || RAY)
  2030.    {
  2031.    LOADPROMPTS3D("X value light vector");
  2032.    uvalues[k].type = 'i';
  2033.    uvalues[k].uval.ival = XLIGHT    ;
  2034.  
  2035.    LOADPROMPTS3D("Y value light vector");
  2036.    uvalues[k].type = 'i';
  2037.    uvalues[k].uval.ival = YLIGHT    ;
  2038.  
  2039.    LOADPROMPTS3D("Z value light vector");
  2040.    uvalues[k].type = 'i';
  2041.    uvalues[k].uval.ival = ZLIGHT    ;
  2042.  
  2043.         if (!RAY)
  2044.         {
  2045.    LOADPROMPTS3D("Light Source Smoothing Factor");
  2046.    uvalues[k].type = 'i';
  2047.    uvalues[k].uval.ival = LIGHTAVG  ;
  2048.  
  2049.    LOADPROMPTS3D("Ambient");
  2050.    uvalues[k].type = 'i';
  2051.    uvalues[k].uval.ival = Ambient;
  2052.         }
  2053.    }
  2054.  
  2055.    if (Targa_Out && !RAY)
  2056.    {
  2057.     LOADPROMPTS3D("Haze Factor        (0 - 100, '0' disables)");
  2058.     uvalues[k].type = 'i';
  2059.     uvalues[k].uval.ival= haze;
  2060.  
  2061.         if (!Targa_Overlay)
  2062.     check_writefile(light_name,".tga");
  2063.       LOADPROMPTS3D("Targa File Name  (Assume .tga)");
  2064.     uvalues[k].type = 's';
  2065.     strcpy(uvalues[k].uval.sval,light_name);
  2066.  
  2067.       LOADPROMPTS3D("Back Ground Color (0 - 255)");
  2068.       uvalues[k].type = '*';
  2069.  
  2070.       LOADPROMPTS3D("   Red");
  2071.       uvalues[k].type = 'i';
  2072.       uvalues[k].uval.ival = (int)back_color[0];
  2073.  
  2074.       LOADPROMPTS3D("   Green");
  2075.       uvalues[k].type = 'i';
  2076.       uvalues[k].uval.ival = (int)back_color[1];
  2077.  
  2078.       LOADPROMPTS3D("   Blue");
  2079.       uvalues[k].type = 'i';
  2080.       uvalues[k].uval.ival = (int)back_color[2];
  2081.  
  2082.       LOADPROMPTS3D("Overlay Targa File? (Y/N)");
  2083.       uvalues[k].type = 'y';
  2084.       uvalues[k].uval.ch.val = Targa_Overlay;
  2085.  
  2086.    }
  2087.  
  2088.    LOADPROMPTS3D("");
  2089.  
  2090.    oldhelpmode = helpmode;
  2091.    helpmode = HELP3DLIGHT;
  2092.    k = fullscreen_prompt(hdg,k,prompts3d,uvalues,0,0,NULL);
  2093.    helpmode = oldhelpmode;
  2094.    if (k < 0)
  2095.       return(-1);
  2096.  
  2097.    k = 0;
  2098.    if (ILLUMINE)
  2099.    {
  2100.       XLIGHT   = uvalues[k++].uval.ival;
  2101.       YLIGHT   = uvalues[k++].uval.ival;
  2102.       ZLIGHT   = uvalues[k++].uval.ival;
  2103.       if (!RAY)
  2104.         {
  2105.       LIGHTAVG = uvalues[k++].uval.ival;
  2106.       Ambient  = uvalues[k++].uval.ival;
  2107.       if (Ambient >= 100) Ambient = 100;
  2108.       if (Ambient <= 0) Ambient = 0;
  2109.         }
  2110.    }
  2111.  
  2112.    if (Targa_Out && !RAY)
  2113.    {
  2114.     haze  =  uvalues[k++].uval.ival;
  2115.     if (haze >= 100) haze = 100;
  2116.     if (haze <= 0) haze = 0;
  2117.         strcpy(light_name,uvalues[k++].uval.sval);
  2118.         /* In case light_name conflicts with an existing name it is checked
  2119.             again in line3d */
  2120.         k++;
  2121.         back_color[0] = (char)uvalues[k++].uval.ival % 255;
  2122.         back_color[1] = (char)uvalues[k++].uval.ival % 255;
  2123.         back_color[2] = (char)uvalues[k++].uval.ival % 255;
  2124.         Targa_Overlay = uvalues[k].uval.ch.val;
  2125.    }
  2126.    return(0);
  2127. }
  2128.  
  2129. /* --------------------------------------------------------------------- */
  2130.  
  2131.  
  2132. static int check_mapfile()
  2133. {
  2134.    extern BYTE dacbox[256][3];
  2135.    extern BYTE olddacbox[256][3];
  2136.    int askflag = 0;
  2137.    int i,oldhelpmode;
  2138.    strcpy(temp1,"*");
  2139.    if (mapset)
  2140.       strcpy(temp1,MAP_name);
  2141.    if (!(glassestype == 1 || glassestype == 2))
  2142.       askflag = 1;
  2143.    else
  2144.       strcpy(temp1,funnyglasses_map_name);
  2145.    while (TRUE) {
  2146.       if (askflag) {
  2147.      oldhelpmode = helpmode;
  2148.      helpmode = -1;
  2149.      i = field_prompt(0,"\
  2150. Enter name of .MAP file to use,\n\
  2151. or '*' to use palette from the image to be loaded.",
  2152.          NULL,temp1,60,NULL);
  2153.      helpmode = oldhelpmode;
  2154.      if (i < 0)
  2155.         return(-1);
  2156.         if (temp1[0] == '*') {
  2157.             mapset = 0;
  2158.             break;
  2159.             }
  2160.         }
  2161.         memcpy(olddacbox,dacbox,256*3); /* save the DAC */
  2162.       i = ValidateLuts(temp1);
  2163.       memcpy(dacbox,olddacbox,256*3); /* restore the DAC */
  2164.       if (i != 0) { /* Oops, somethings wrong */
  2165.          askflag = 1;
  2166.      continue;
  2167.      }
  2168.       mapset = 1;
  2169.       strcpy (MAP_name,temp1);
  2170.       break;
  2171.       }
  2172.    return(0);
  2173. }
  2174.  
  2175. static int get_funny_glasses_params()
  2176. {
  2177.    static char far hdg[]={"Funny Glasses Parameters"};
  2178.    char far *prompts3d[10];
  2179.  
  2180.    struct fullscreenvalues uvalues[10];
  2181.  
  2182.    int k;
  2183.    int oldhelpmode;
  2184.  
  2185.    /* defaults */
  2186.    if(ZVIEWER == 0)
  2187.       ZVIEWER = 150;
  2188.    if(eyeseparation == 0)
  2189.    {
  2190.       if(fractype==IFS3D || fractype==LLORENZ3D || fractype==FPLORENZ3D)
  2191.       {
  2192.      eyeseparation =  2;
  2193.      xadjust       = -2;
  2194.       }
  2195.       else
  2196.       {
  2197.      eyeseparation =  3;
  2198.      xadjust       =  0;
  2199.       }
  2200.    }
  2201.  
  2202.    if(glassestype == 1)
  2203.       strcpy(funnyglasses_map_name,Glasses1Map);
  2204.    else if(glassestype == 2)
  2205.    {
  2206.       if(FILLTYPE == -1)
  2207.      strcpy(funnyglasses_map_name,"grid.map");
  2208.       else
  2209.      strcpy(funnyglasses_map_name,"glasses2.map");
  2210.    }
  2211.  
  2212.    k = -1;
  2213.    LOADPROMPTS3D("Interocular distance (as % of screen)");
  2214.    uvalues[k].type = 'i';
  2215.    uvalues[k].uval.ival= eyeseparation;
  2216.  
  2217.    LOADPROMPTS3D("Convergence adjust (positive = spread greater)");
  2218.    uvalues[k].type = 'i';
  2219.    uvalues[k].uval.ival = xadjust;
  2220.  
  2221.    LOADPROMPTS3D("Left  red image crop (% of screen)");
  2222.    uvalues[k].type = 'i';
  2223.    uvalues[k].uval.ival = red_crop_left;
  2224.  
  2225.    LOADPROMPTS3D("Right red image crop (% of screen)");
  2226.    uvalues[k].type = 'i';
  2227.    uvalues[k].uval.ival = red_crop_right;
  2228.  
  2229.    LOADPROMPTS3D("Left  blue image crop (% of screen)");
  2230.    uvalues[k].type = 'i';
  2231.    uvalues[k].uval.ival = blue_crop_left;
  2232.  
  2233.    LOADPROMPTS3D("Right blue image crop (% of screen)");
  2234.    uvalues[k].type = 'i';
  2235.    uvalues[k].uval.ival = blue_crop_right;
  2236.  
  2237.    LOADPROMPTS3D("Red brightness factor (%)");
  2238.    uvalues[k].type = 'i';
  2239.    uvalues[k].uval.ival = red_bright;
  2240.  
  2241.    LOADPROMPTS3D("Blue brightness factor (%)");
  2242.    uvalues[k].type = 'i';
  2243.    uvalues[k].uval.ival = blue_bright;
  2244.  
  2245.    if(glassestype == 1 || glassestype == 2)
  2246.    {
  2247.       LOADPROMPTS3D("Map File name");
  2248.       uvalues[k].type = 's';
  2249.       strcpy(uvalues[k].uval.sval,funnyglasses_map_name);
  2250.    }
  2251.  
  2252.    oldhelpmode = helpmode;
  2253.    helpmode = HELP3DGLASSES;
  2254.    k = fullscreen_prompt(hdg,k+1,prompts3d,uvalues,0,0,NULL);
  2255.    helpmode = oldhelpmode;
  2256.    if (k < 0)
  2257.       return(-1);
  2258.  
  2259.    k = 0;
  2260.    eyeseparation   =  uvalues[k++].uval.ival;
  2261.    xadjust       =  uvalues[k++].uval.ival;
  2262.    red_crop_left   =  uvalues[k++].uval.ival;
  2263.    red_crop_right  =  uvalues[k++].uval.ival;
  2264.    blue_crop_left  =  uvalues[k++].uval.ival;
  2265.    blue_crop_right =  uvalues[k++].uval.ival;
  2266.    red_bright       =  uvalues[k++].uval.ival;
  2267.    blue_bright       =  uvalues[k++].uval.ival;
  2268.  
  2269.    if(glassestype == 1 || glassestype == 2)
  2270.       strcpy(funnyglasses_map_name,uvalues[k].uval.sval);
  2271.    return(0);
  2272. }
  2273.