home *** CD-ROM | disk | FTP | other *** search
/ Computerworld 1996 March / Computerworld_1996-03_cd.bin / idg_cd3 / grafika / fraktaly / frasr192 / prompts1.c < prev    next >
C/C++ Source or Header  |  1995-04-08  |  71KB  |  2,396 lines

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