home *** CD-ROM | disk | FTP | other *** search
/ Mega A/V / mega_av.zip / mega_av / GRAPHUTL / FRPOR172.ZIP / REALDOS.C < prev    next >
C/C++ Source or Header  |  1992-03-09  |  53KB  |  1,749 lines

  1. /*
  2.     Miscellaneous C routines used only in DOS Fractint.
  3. */
  4.  
  5. #include <string.h>
  6. #include <stdio.h>
  7. #ifndef XFRACT
  8. #include <dos.h>
  9. #endif
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <fcntl.h>
  13. #include <math.h>
  14. #include "fractint.h"
  15. #include "fractype.h"
  16. #include "helpdefs.h"
  17.  
  18. /* routines in this module    */
  19.  
  20. int  stopmsg(int,CHAR far *);
  21. int  texttempmsg(char *msgparm);
  22. int  showtempmsg(char *msgparm);
  23. void cleartempmsg(void);
  24. void blankrows(int row,int rows,int attr);
  25. void helptitle(void);
  26. int  putstringcenter(int row, int col, int width, int attr, char far *msg);
  27. void stackscreen(void);
  28. void unstackscreen(void);
  29. void discardscreen(void);
  30. int  fullscreen_choice(
  31.          int options, char *hdg, char *hdg2, char *instr, int numchoices,
  32.          char **choices, int *attributes, int boxwidth, int boxdepth,
  33.          int colwidth, int current, void (*formatitem)(),
  34.          char *speedstring, int (*speedprompt)(), int (*checkkey)());
  35. #ifndef XFRACT
  36. int  strncasecmp(char *s,char *t,int ct);
  37. #endif
  38. int  main_menu(int fullmenu);
  39. int  input_field(int options, int attr, char *fld, int len, int row, int col, int (*checkkey)(int) );
  40. int  field_prompt(int options, char *hdg, char *instr, char *fld, int len, int (*checkkey)() );
  41. int  thinking(int options, char *msg);
  42. void clear_screen(void);
  43. int  savegraphics(void);
  44. void restoregraphics(void),discardgraphics(void);
  45. int load_fractint_cfg(int options);
  46. void bad_fractint_cfg_msg(void);
  47. void load_videotable(int options);
  48. int check_vidmode_key(int option,int k);
  49. int check_vidmode_keyname(char *kname);
  50. void vidmode_keyname(int k,char *buf);
  51.  
  52. static int menu_checkkey(int curkey,int choice);
  53.  
  54. int release=1721; /* this has 2 implied decimals; increment it every synch */
  55. int xrelease=12;
  56.  
  57. /* fullscreen_choice options */
  58. #define CHOICERETURNKEY 1
  59. #define CHOICEMENU    2
  60. #define CHOICEHELP    4
  61.  
  62. extern int  xdots, ydots, sxdots, sydots, sxoffs, syoffs;
  63. extern int  colors;
  64. extern int  dotmode;
  65. extern int  oktoprint;
  66. extern char far *findfont(int);
  67. extern int  textrow, textcol, textrbase, textcbase;
  68. extern int  debugflag;
  69. extern int  fractype;
  70. extern int  calc_status;
  71. extern double param[];
  72. extern int  tabmode;
  73. extern int  color_dark,color_medium,color_bright;
  74. extern int  lookatmouse;
  75. extern int  gotrealdac;
  76. extern int  reallyega;
  77. extern int  extraseg;
  78. extern int  active_system;
  79. extern int  first_init;
  80.  
  81.  
  82. /* int stopmsg(flags,message) displays message and waits for a key:
  83.      message should be a max of 9 lines with \n's separating them;
  84.        no leading or trailing \n's in message;
  85.        no line longer than 76 chars for best appearance;
  86.      flag options:
  87.        &1 if already in text display mode, stackscreen is not called
  88.       and message is displayed at (12,0) instead of (4,0)
  89.        &2 if continue/cancel indication is to be returned;
  90.       when not set, "Any key to continue..." is displayed
  91.       when set, "Escape to cancel, any other key to continue..."
  92.       -1 is returned for cancel, 0 for continue
  93.        &4 set to suppress buzzer
  94.        &8 for Fractint for Windows & parser - use a fixed pitch font
  95.       &16 for info only message (green box instead of red in DOS vsn)
  96.    */
  97. int stopmsg (int flags, CHAR far *msg)
  98. {
  99.    int ret,toprow,color,savelookatmouse;
  100.    if (active_system == 0 /* DOS */
  101.      && first_init) {      /* & cmdfiles hasn't finished 1st try */
  102.       setvideotext();
  103.       buzzer(2);
  104.       putstring(0,0,15,"*** Error during startup:");
  105.       putstring(2,0,15,msg);
  106.       movecursor(8,0);
  107. #ifdef XFRACT
  108.       sleep(1);
  109.       UnixDone();
  110. #endif
  111.       exit(1);
  112.       }
  113.    ret = 0;
  114.    savelookatmouse = lookatmouse;
  115.    lookatmouse = -13;
  116.    if ((flags & 1))
  117.       blankrows(toprow=12,10,7);
  118.    else {
  119.       stackscreen();
  120.       toprow = 4;
  121.       movecursor(4,0);
  122.       }
  123.    textcbase = 2; /* left margin is 2 */
  124.    putstring(toprow,0,7,msg);
  125.    if (flags & 2)
  126.       putstring(textrow+2,0,7,"Escape to cancel, any other key to continue...");
  127.    else
  128.       putstring(textrow+2,0,7,"Any key to continue...");
  129.    textcbase = 0; /* back to full line */
  130.    color = (flags & 16) ? C_STOP_INFO : C_STOP_ERR;
  131.    setattr(toprow,0,color,(textrow+1-toprow)*80);
  132.    movecursor(25,80);    /* cursor off */
  133.    if ((flags & 4) == 0)
  134.       buzzer((flags & 16) ? 0 : 2);
  135.    while (keypressed()) /* flush any keyahead */
  136.       getakey();
  137.    if (getakeynohelp() == ESC)
  138.       ret = -1;
  139.    if ((flags & 1))
  140.       blankrows(toprow,10,7);
  141.    else
  142.       unstackscreen();
  143.    lookatmouse = savelookatmouse;
  144.    return ret;
  145. }
  146.  
  147.  
  148. static char far *temptextsave = NULL;
  149. static int  textxdots,textydots;
  150.  
  151. /* texttempmsg(msg) displays a text message of up to 40 characters, waits
  152.       for a key press, restores the prior display, and returns (without
  153.       eating the key).
  154.       It works in almost any video mode - does nothing in some very odd cases
  155.       (HCGA hi-res with old bios), or when there isn't 10k of temp mem free. */
  156. int texttempmsg(char *msgparm)
  157. {
  158.    if (showtempmsg(msgparm))
  159.       return(-1);
  160. #ifndef XFRACT
  161.    while (!keypressed()) {} /* wait for a keystroke but don't eat it */
  162. #else
  163.    waitkeypressed(0); /* wait for a keystroke but don't eat it */
  164. #endif
  165.    cleartempmsg();
  166.    return(0);
  167. }
  168.  
  169. int showtempmsg(char *msgparm)
  170. {
  171.    extern int color_dark,color_medium;
  172.    CHAR msg[41];
  173.    BYTE buffer[640];
  174.    char far *fartmp;
  175.    char far *fontptr;
  176.    BYTE *bufptr;
  177.    int i,j,k,xrepeat,yrepeat,fontchar,charnum;
  178.    int save_sxoffs,save_syoffs;
  179.    strncpy(msg,msgparm,40);
  180.    msg[40] = 0; /* ensure max message len of 40 chars */
  181.    if (dotmode == 11) { /* disk video, screen in text mode, easy */
  182.       dvid_status(0,msg);
  183.       return(0);
  184.       }
  185.    if ((fontptr = findfont(0)) == NULL) { /* old bios, no font table? */
  186.       if (oktoprint == 0           /* can't printf */
  187.     || sxdots > 640 || sydots > 200) /* not willing to trust char cell size */
  188.      return(-1); /* sorry, message not displayed */
  189.       textydots = 8;
  190.       textxdots = sxdots;
  191.       }
  192.    else {
  193.       xrepeat = (sxdots >= 640) ? 2 : 1;
  194.       yrepeat = (sydots >= 300) ? 2 : 1;
  195.       textxdots = strlen(msg) * xrepeat * 8;
  196.       textydots = yrepeat * 8;
  197.       }
  198.    /* worst case needs 10k */
  199.    if ((temptextsave = farmemalloc((long)textxdots * textydots)) == NULL)
  200.       return(-1); /* sorry, message not displayed */
  201.    save_sxoffs = sxoffs;
  202.    save_syoffs = syoffs;
  203.    sxoffs = syoffs = 0;
  204.    fartmp = temptextsave;
  205.    for (i = 0; i < textydots; ++i) {
  206.       get_line(i,0,textxdots-1,buffer);
  207.       for (j = 0; j < textxdots; ++j) /* copy it out to far memory */
  208.      *(fartmp++) = buffer[j];
  209.       }
  210.    if (fontptr == NULL) { /* bios must do it for us */
  211.       home();
  212.       printf(msg);
  213.       }
  214.    else { /* generate the characters */
  215.       find_special_colors(); /* get color_dark & color_medium set */
  216.       for (i = 0; i < 8; ++i) {
  217.      memset(buffer,color_dark,640);
  218.      bufptr = buffer;
  219.      charnum = -1;
  220.      while (msg[++charnum] != 0) {
  221.         fontchar = *(fontptr + msg[charnum]*8 + i);
  222.         for (j = 0; j < 8; ++j) {
  223.            for (k = 0; k < xrepeat; ++k) {
  224.           if ((fontchar & 0x80) != 0)
  225.              *bufptr = color_medium;
  226.           ++bufptr;
  227.           }
  228.            fontchar <<= 1;
  229.            }
  230.         }
  231.      for (j = 0; j < yrepeat; ++j)
  232.         put_line(i*yrepeat+j,0,textxdots-1,buffer);
  233.      }
  234.       }
  235.    sxoffs = save_sxoffs;
  236.    syoffs = save_syoffs;
  237.    return(0);
  238. }
  239.  
  240. void cleartempmsg()
  241. {
  242.    BYTE buffer[640];
  243.    char far *fartmp;
  244.    int i,j;
  245.    int save_sxoffs,save_syoffs;
  246.    if (dotmode == 11) /* disk video, easy */
  247.       dvid_status(0,"");
  248.    else if (temptextsave != NULL) {
  249.       save_sxoffs = sxoffs;
  250.       save_syoffs = syoffs;
  251.       sxoffs = syoffs = 0;
  252.       fartmp = temptextsave;
  253.       for (i = 0; i < textydots; ++i) {
  254.      for (j = 0; j < textxdots; ++j) /* copy back from far memory */
  255.         buffer[j] = *(fartmp++);
  256.      put_line(i,0,textxdots-1,buffer);
  257.      }
  258.       farmemfree(temptextsave);
  259.       temptextsave = NULL;
  260.       sxoffs = save_sxoffs;
  261.       syoffs = save_syoffs;
  262.       }
  263. }
  264.  
  265.  
  266. void blankrows(int row,int rows,int attr)
  267. {
  268.    char buf[81];
  269.    memset(buf,' ',80);
  270.    buf[80] = 0;
  271.    while (--rows >= 0)
  272.       putstring(row++,0,attr,buf);
  273.    }
  274.  
  275.  
  276. void helptitle()
  277. {
  278.    char msg[80],buf[10];
  279.    setclear(); /* clear the screen */
  280. #ifdef XFRACT
  281.    sprintf(msg,"XFRACTINT  Version %d.%02d (FRACTINT Version %d.%02d)",
  282.            xrelease/100,xrelease%100, release/100,release%100);
  283.    putstringcenter(0,0,80,C_TITLE,msg);
  284. #else
  285. #ifdef WAITE
  286.    sprintf(msg,"Special FRACTINT  Version %d.%01d",release/100,(release%100)/10);
  287. #else
  288.    sprintf(msg,"FRACTINT  Version %d.%01d",release/100,(release%100)/10);
  289. #endif
  290.    if (release%10) {
  291.       sprintf(buf,"%01d",release%10);
  292.       strcat(msg,buf);
  293.       }
  294. #ifdef WAITE /* realdos.c */
  295.    strcat(msg," for the Waite Group's Fractal Creations");
  296. #endif /* WAITE - realdos.c */
  297.    putstringcenter(0,0,80,C_TITLE,msg);
  298. #ifdef WAITE
  299.    return;
  300. #endif
  301. #endif
  302. /* uncomment next for production executable: */
  303. /* return; */
  304.    if (debugflag == 3002) return;
  305. /* putstring(0,2,C_TITLE_DEV,"Development Version"); */
  306. /* replace above by next after creating production release, for release source */
  307.    putstring(0,3,C_TITLE_DEV, "Customized Version");
  308.    putstring(0,53,C_TITLE_DEV,"Not for Public Release");
  309. }
  310.  
  311.  
  312. int putstringcenter(int row, int col, int width, int attr, char far *msg)
  313. {
  314.    char buf[81];
  315.    int i,j,k;
  316.    i = 0;
  317.    while (msg[i]) ++i; /* strlen for a far */
  318.    if (i == 0) return(-1);
  319.    j = (width - i) / 2;
  320.    j -= (width + 10 - i) / 20; /* when wide a bit left of center looks better */
  321.    memset(buf,' ',width);
  322.    buf[width] = 0;
  323.    i = 0;
  324.    k = j;
  325.    while (msg[i]) buf[k++] = msg[i++]; /* strcpy for a far */
  326.    putstring(row,col,attr,buf);
  327.    return j;
  328. }
  329.  
  330.  
  331. #ifndef XFRACT
  332. static int screenctr=-1;
  333. #else
  334. static int screenctr=0;
  335. #endif
  336. #define MAXSCREENS 3
  337. static BYTE far *savescreen[MAXSCREENS];
  338. static int saverc[MAXSCREENS+1];
  339. static FILE *savescf=NULL;
  340. static char scsvfile[]="fractscr.tmp";
  341. extern int text_type;
  342. extern int textaddr;
  343.  
  344. void stackscreen()
  345. {
  346. #ifndef XFRACT
  347.    BYTE far *vidmem;
  348.    int savebytes;
  349.    int i;
  350.    BYTE far *ptr;
  351.    char buf[100];
  352.    saverc[screenctr+1] = textrow*80 + textcol;
  353.    if (++screenctr) { /* already have some stacked */
  354.      static char far msg[]={"stackscreen overflow"};
  355.       if ((i = screenctr - 1) >= MAXSCREENS) { /* bug, missing unstack? */
  356.      stopmsg(1,msg);
  357.      exit(1);
  358.      }
  359.       vidmem = MK_FP(textaddr,0);
  360.       savebytes = (text_type == 0) ? 4000 : 16384;
  361.       if ((ptr = savescreen[i] = farmemalloc((long)savebytes)))
  362.      far_memcpy(ptr,vidmem,savebytes);
  363.       else {
  364.      if (savescf == NULL) { /* create file just once */
  365.         if ((savescf = fopen(scsvfile,"wb")) == NULL)
  366.            goto fileproblem;
  367.         if (fwrite(buf,MAXSCREENS,16384,savescf) != 16384)
  368.            goto fileproblem;
  369.         fclose(savescf);
  370.         if ((savescf = fopen(scsvfile,"r+b")) == NULL) {
  371.         static char far msg[]={"insufficient memory, aborting"};
  372. fileproblem:   stopmsg(1,msg);
  373.            exit(1);
  374.            }
  375.         }
  376.      fseek(savescf,(long)(savebytes*i),SEEK_SET);
  377.      while (--savebytes >= 0)
  378.         putc(*(vidmem++),savescf);
  379.      }
  380.       setclear();
  381.       }
  382.    else
  383.       setfortext();
  384. #else
  385.    int i;
  386.    BYTE far *ptr;
  387.    saverc[screenctr+1] = textrow*80 + textcol;
  388.    if (++screenctr) { /* already have some stacked */
  389.          static char far msg[]={"stackscreen overflow"};
  390.       if ((i = screenctr - 1) >= MAXSCREENS) { /* bug, missing unstack? */
  391.          stopmsg(1,msg);
  392.          exit(1);
  393.          }
  394.       if (ptr = savescreen[i] = farmemalloc(sizeof(int *)))
  395.          savecurses(ptr);
  396.       else {
  397.          stopmsg(1,msg);
  398.          exit(1);
  399.         }
  400.       setclear();
  401.       }
  402.    else
  403.       setfortext();
  404. #endif
  405. }
  406.  
  407. void unstackscreen()
  408. {
  409. #ifndef XFRACT
  410.    char far *vidmem;
  411.    int savebytes;
  412.    BYTE far *ptr;
  413.    textrow = saverc[screenctr] / 80;
  414.    textcol = saverc[screenctr] % 80;
  415.    if (--screenctr >= 0) { /* unstack */
  416.       vidmem = MK_FP(textaddr,0);
  417.       savebytes = (text_type == 0) ? 4000 : 16384;
  418.       if ((ptr = savescreen[screenctr])) {
  419.      far_memcpy(vidmem,ptr,savebytes);
  420.      farmemfree(ptr);
  421.      }
  422.       else {
  423.      fseek(savescf,(long)(savebytes*screenctr),SEEK_SET);
  424.      while (--savebytes >= 0)
  425.         *(vidmem++) = getc(savescf);
  426.      }
  427.       }
  428.    else
  429.       setforgraphics();
  430.    movecursor(-1,-1);
  431. #else
  432.    BYTE far *ptr;
  433.    textrow = saverc[screenctr] / 80;
  434.    textcol = saverc[screenctr] % 80;
  435.    if (--screenctr >= 0) { /* unstack */
  436.       ptr = savescreen[screenctr];
  437.       restorecurses(ptr);
  438.       farmemfree(ptr);
  439.       }
  440.    else
  441.       setforgraphics();
  442.    movecursor(-1,-1);
  443. #endif
  444. }
  445.  
  446. void discardscreen()
  447. {
  448.    if (--screenctr >= 0) { /* unstack */
  449.       if (savescreen[screenctr])
  450.      farmemfree(savescreen[screenctr]);
  451.       }
  452.    else
  453.       discardgraphics();
  454. }
  455.  
  456.  
  457. /* --------------------------------------------------------------------- */
  458.  
  459. char speed_prompt[]="Speed key string";
  460.  
  461. int fullscreen_choice(
  462.     int options,         /* &2 use menu coloring scheme           */
  463.                  /* &4 include F1 for help in instructions */
  464.                  /* &8 add caller's instr after normal set */
  465.     char *hdg,         /* heading info, \n delimited           */
  466.     char *hdg2,         /* column heading or NULL               */
  467.     char *instr,         /* instructions, \n delimited, or NULL    */
  468.     int numchoices,      /* How many choices in list           */
  469.     char **choices,      /* array of choice strings            */
  470.     int *attributes,     /* &3: 0 normal color, 1,3 highlight      */
  471.                  /* &256 marks a dummy entry           */
  472.     int boxwidth,         /* box width, 0 for calc (in items)       */
  473.     int boxdepth,         /* box depth, 0 for calc, 99 for max      */
  474.     int colwidth,         /* data width of a column, 0 for calc     */
  475.     int current,         /* start with this item               */
  476.     void (*formatitem)(),/* routine to display an item or NULL     */
  477.     char *speedstring,   /* returned speed key value, or NULL >[30]*/
  478.     int (*speedprompt)(),/* routine to display prompt or NULL      */
  479.     int (*checkkey)()    /* routine to check keystroke or NULL     */
  480. )
  481.    /* return is: n>=0 for choice n selected,
  482.          -1 for escape
  483.           k for checkkey routine return value k (if not 0 nor -1)
  484.       speedstring[0] != 0 on return if string is present
  485.       */
  486. {
  487. static char far choiceinstr1a[]="Use the cursor keys to highlight your selection";
  488. static char far choiceinstr1b[]="Use the cursor keys or type a value to make a selection";
  489. static char far choiceinstr2a[]="Press ENTER for highlighted choice, or ESCAPE to back out";
  490. static char far choiceinstr2b[]="Press ENTER for highlighted choice, ESCAPE to back out, or F1 for help";
  491. static char far choiceinstr2c[]="Press ENTER for highlighted choice, or F1 for help";
  492.  
  493.    int titlelines,titlewidth;
  494.    int reqdrows;
  495.    int topleftrow,topleftcol;
  496.    int topleftchoice;
  497.    int speedrow;  /* speed key prompt */
  498.    int boxitems;  /* boxwidth*boxdepth */
  499.    int curkey,increment,rev_increment;
  500.    int redisplay;
  501.    int i,j,k;
  502.    char *charptr;
  503.    char buf[81];
  504.    int speed_match = 0;
  505.    char curitem[81];
  506.    char *itemptr;
  507.    int ret,savelookatmouse;
  508.  
  509.    savelookatmouse = lookatmouse;
  510.    lookatmouse = 0;
  511.    ret = -1;
  512.    if (speedstring
  513.      && (i = strlen(speedstring)) > 0) { /* preset current to passed string */
  514.       current = 0;
  515.       while (current < numchoices
  516.     && (k = strncasecmp(speedstring,choices[current],i)) > 0)
  517.      ++current;
  518.       if (k < 0 && current > 0)  /* oops - overshot */
  519.      --current;
  520.       if (current >= numchoices) /* bumped end of list */
  521.      current = numchoices - 1;
  522.       }
  523.  
  524.    while (1) {
  525.       if (current >= numchoices)  /* no real choice in the list? */
  526.      goto fs_choice_end;
  527.       if ((attributes[current] & 256) == 0)
  528.      break;
  529.       ++current;          /* scan for a real choice */
  530.       }
  531.  
  532.    titlelines = titlewidth = 0;
  533.    if (hdg) {
  534.       charptr = hdg;          /* count title lines, find widest */
  535.       i = 0;
  536.       titlelines = 1;
  537.       while (*charptr) {
  538.      if (*(charptr++) == '\n') {
  539.         ++titlelines;
  540.         i = -1;
  541.         }
  542.      if (++i > titlewidth)
  543.         titlewidth = i;
  544.      }
  545.       }
  546.  
  547.    if (colwidth == 0)          /* find widest column */
  548.       for (i = 0; i < numchoices; ++i)
  549.      if (strlen(choices[i]) > colwidth)
  550.         colwidth = strlen(choices[i]);
  551.  
  552.    /* title(1), blank(1), hdg(n), blank(1), body(n), blank(1), instr(?) */
  553.    reqdrows = 3;          /* calc rows available */
  554.    if (hdg)
  555.       reqdrows += titlelines + 1;
  556.    if (instr) {           /* count instructions lines */
  557.       charptr = instr;
  558.       ++reqdrows;
  559.       while (*charptr)
  560.      if (*(charptr++) == '\n')
  561.         ++reqdrows;
  562.       if ((options & 8))      /* show std instr too */
  563.      reqdrows += 2;
  564.       }
  565.    else
  566.       reqdrows += 2;          /* standard instructions */
  567.    if (speedstring) ++reqdrows;   /* a row for speedkey prompt */
  568.    if (boxdepth > (i = 25 - reqdrows)) /* limit the depth to max */
  569.       boxdepth = i;
  570.    if (boxwidth == 0) {       /* pick box width and depth */
  571.       if (numchoices <= i - 2) {  /* single column is 1st choice if we can */
  572.      boxdepth = numchoices;
  573.      boxwidth = 1;
  574.      }
  575.       else {              /* sort-of-wide is 2nd choice */
  576.      boxwidth = 60 / (colwidth + 1);
  577.      if (boxwidth == 0
  578.        || (boxdepth = (numchoices+boxwidth-1)/boxwidth) > i - 2) {
  579.         boxwidth = 80 / (colwidth + 1); /* last gasp, full width */
  580.         if ((boxdepth = (numchoices+boxwidth-1)/boxwidth) > i)
  581.            boxdepth = i;
  582.         }
  583.      }
  584.       }
  585.    if ((i = 77 / boxwidth - colwidth) > 3) /* spaces to add @ left each choice */
  586.       i = 3;
  587.    j = boxwidth * (colwidth += i) + i;       /* overall width of box */
  588.    if (j < titlewidth+2)
  589.       j = titlewidth + 2;
  590.    if (j > 80)
  591.       j = 80;
  592.    if (j <= 70 && boxwidth == 2) {       /* special case makes menus nicer */
  593.       ++j;
  594.       ++colwidth;
  595.       }
  596.    k = (80 - j) / 2;               /* center the box */
  597.    k -= (90 - j) / 20;
  598.    topleftcol = k + i;               /* column of topleft choice */
  599.    i = (25 - reqdrows - boxdepth) / 2;
  600.    i -= i / 4;                   /* higher is better if lots extra */
  601.    topleftrow = 3 + titlelines + i;       /* row of topleft choice */
  602.  
  603.    /* now set up the overall display */
  604.    helptitle();                /* clear, display title line */
  605.    setattr(1,0,C_PROMPT_BKGRD,24*80);       /* init rest to background */
  606.    for (i = topleftrow-1-titlelines; i < topleftrow+boxdepth+1; ++i)
  607.       setattr(i,k,C_PROMPT_LO,j);       /* draw empty box */
  608.    if (hdg) {
  609.       textcbase = (80 - titlewidth) / 2;   /* set left margin for putstring */
  610.       textcbase -= (90 - titlewidth) / 20; /* put heading into box */
  611.       putstring(topleftrow-titlelines-1,0,C_PROMPT_HI,hdg);
  612.       textcbase = 0;
  613.       }
  614.    if (hdg2)                   /* display 2nd heading */
  615.       putstring(topleftrow-1,topleftcol,C_PROMPT_MED,hdg2);
  616.    i = topleftrow + boxdepth + 1;
  617.    if (instr == NULL || (options & 8)) {   /* display default instructions */
  618.       if (i < 20) ++i;
  619.       if (speedstring) {
  620.      speedrow = i;
  621.      *speedstring = 0;
  622.      if (++i < 22) ++i;
  623.      }
  624.       putstringcenter(i++,0,80,C_PROMPT_BKGRD,
  625.         (speedstring) ? choiceinstr1b : choiceinstr1a);
  626.       putstringcenter(i++,0,80,C_PROMPT_BKGRD,
  627.         (options&CHOICEMENU) ? choiceinstr2c
  628.         : ((options&CHOICEHELP) ? choiceinstr2b : choiceinstr2a));
  629.       }
  630.    if (instr) {                /* display caller's instructions */
  631.       charptr = instr;
  632.       j = -1;
  633.       while ((buf[++j] = *(charptr++)))
  634.      if (buf[j] == '\n') {
  635.         buf[j] = 0;
  636.         putstringcenter(i++,0,80,C_PROMPT_BKGRD,buf);
  637.         j = -1;
  638.         }
  639.       putstringcenter(i,0,80,C_PROMPT_BKGRD,buf);
  640.       }
  641.  
  642.    boxitems = boxwidth * boxdepth;
  643.    topleftchoice = 0;               /* pick topleft for init display */
  644.    while (current - topleftchoice >= boxitems
  645.      || (current - topleftchoice > boxitems/2
  646.      && topleftchoice + boxitems < numchoices))
  647.       topleftchoice += boxwidth;
  648.    redisplay = 1;
  649.  
  650.    while (1) { /* main loop */
  651.  
  652.       if (redisplay) {                 /* display the current choices */
  653.      if ((options & CHOICEMENU) == 0) {
  654.         memset(buf,' ',80);
  655.         buf[boxwidth*colwidth] = 0;
  656.         for (i = (hdg2) ? 0 : -1; i <= boxdepth; ++i)  /* blank the box */
  657.            putstring(topleftrow+i,topleftcol,C_PROMPT_LO,buf);
  658.         }
  659.      for (i = 0; i+topleftchoice < numchoices && i < boxitems; ++i) {
  660.         /* display the choices */
  661.         if ((k = attributes[j = i+topleftchoice] & 3) == 1)
  662.            k = C_PROMPT_LO;
  663.         else if (k == 3)
  664.            k = C_PROMPT_HI;
  665.         else
  666.            k = C_PROMPT_MED;
  667.         if (formatitem)
  668.            (*formatitem)(j,charptr=buf);
  669.         else
  670.            charptr = choices[j];
  671.         putstring(topleftrow+i/boxwidth,topleftcol+(i%boxwidth)*colwidth,
  672.               k,charptr);
  673.         }
  674.      /***
  675.      ... format differs for summary/detail, whups, force box width to
  676.      ...  be 72 when detail toggle available?  (2 grey margin each
  677.      ...  side, 1 blue margin each side)
  678.      ***/
  679.      if (topleftchoice > 0 && hdg2 == NULL)
  680.         putstring(topleftrow-1,topleftcol,C_PROMPT_LO,"(more)");
  681.      if (topleftchoice + boxitems < numchoices)
  682.         putstring(topleftrow+boxdepth,topleftcol,C_PROMPT_LO,"(more)");
  683.      redisplay = 0;
  684.      }
  685.  
  686.       i = current - topleftchoice;         /* highlight the current choice */
  687.       if (formatitem)
  688.      (*formatitem)(current,itemptr=curitem);
  689.       else
  690.      itemptr = choices[current];
  691.       putstring(topleftrow+i/boxwidth,topleftcol+(i%boxwidth)*colwidth,
  692.         C_CHOICE_CURRENT,itemptr);
  693.  
  694.       if (speedstring) {             /* show speedstring if any */
  695.      memset(buf,' ',80);
  696.      buf[80] = 0;
  697.      putstring(speedrow,0,C_PROMPT_BKGRD,buf);
  698.      if (*speedstring) {             /* got a speedstring on the go */
  699.         putstring(speedrow,15,C_CHOICE_SP_INSTR," ");
  700.         if (speedprompt)
  701.            j = speedprompt(speedrow,16,C_CHOICE_SP_INSTR,speedstring,speed_match);
  702.         else {
  703.            putstring(speedrow,16,C_CHOICE_SP_INSTR,speed_prompt);
  704.            j = strlen(speed_prompt);
  705.            }
  706.         strcpy(buf,speedstring);
  707.         i = strlen(buf);
  708.         while (i < 30)
  709.            buf[i++] = ' ';
  710.         buf[i] = 0;
  711.         putstring(speedrow,16+j,C_CHOICE_SP_INSTR," ");
  712.         putstring(speedrow,17+j,C_CHOICE_SP_KEYIN,buf);
  713.         movecursor(speedrow,17+j+strlen(speedstring));
  714.         }
  715.      else
  716.         movecursor(25,80);
  717.      }
  718.       else
  719.      movecursor(25,80);
  720.  
  721. #ifndef XFRACT
  722.       while (!keypressed()) { } /* enables help */
  723. #else
  724.       waitkeypressed(0); /* enables help */
  725. #endif
  726.       curkey = getakey();
  727.  
  728.       i = current - topleftchoice;         /* unhighlight current choice */
  729.       if ((k = attributes[current] & 3) == 1)
  730.      k = C_PROMPT_LO;
  731.       else if (k == 3)
  732.      k = C_PROMPT_HI;
  733.       else
  734.      k = C_PROMPT_MED;
  735.       putstring(topleftrow+i/boxwidth,topleftcol+(i%boxwidth)*colwidth,
  736.         k,itemptr);
  737.  
  738.       increment = 0;
  739.       switch (curkey) {              /* deal with input key */
  740.      case ENTER:
  741.      case ENTER_2:
  742.         ret = current;
  743.         goto fs_choice_end;
  744.      case ESC:
  745.         goto fs_choice_end;
  746.      case DOWN_ARROW:
  747.      case DOWN_ARROW_2:
  748.         rev_increment = 0 - (increment = boxwidth);
  749.         break;
  750.      case UP_ARROW:
  751.      case UP_ARROW_2:
  752.         increment = 0 - (rev_increment = boxwidth);
  753.         break;
  754.      case RIGHT_ARROW:
  755.      case RIGHT_ARROW_2:
  756.         if (boxwidth == 1) break;
  757.         increment = 1; rev_increment = -1;
  758.         break;
  759.      case LEFT_ARROW:
  760.      case LEFT_ARROW_2:
  761.         if (boxwidth == 1) break;
  762.         increment = -1; rev_increment = 1;
  763.         break;
  764.      case PAGE_UP:
  765.         if (numchoices > boxitems) {
  766.            topleftchoice -= boxitems;
  767.            increment = -boxitems;
  768.            rev_increment = boxwidth;
  769.            redisplay = 1;
  770.            }
  771.         break;
  772.      case PAGE_DOWN:
  773.         if (numchoices > boxitems) {
  774.            topleftchoice += boxitems;
  775.            increment = boxitems;
  776.            rev_increment = -boxwidth;
  777.            redisplay = 1;
  778.            }
  779.         break;
  780.      case CTL_HOME:
  781.         current = -1;
  782.         increment = rev_increment = 1;
  783.         break;
  784.      case CTL_END:
  785.         current = numchoices;
  786.         increment = rev_increment = -1;
  787.         break;
  788.      default:
  789.         if (checkkey) {
  790.            if ((ret = (*checkkey)(curkey,current)) < -1 || ret > 0)
  791.           goto fs_choice_end;
  792.            if (ret == -1)
  793.           redisplay = -1;
  794.            }
  795.         ret = -1;
  796.         if (speedstring) {
  797.            i = strlen(speedstring);
  798.            if (curkey == 8 && i > 0) /* backspace */
  799.           speedstring[--i] = 0;
  800. #ifndef XFRACT
  801.            if (33 <= curkey && curkey <= 126 && i < 30) {
  802.           curkey = tolower(curkey);
  803. #else
  804.                if (((33<=curkey && curkey<=64) || (96<=curkey&&curkey<=126)) 
  805.                        && i<30) {
  806. #endif
  807.           speedstring[i] = curkey;
  808.           speedstring[++i] = 0;
  809.           }
  810.            if (i > 0) {         /* locate matching type */
  811.           current = 0;
  812.           while (current < numchoices
  813.             && (speed_match = strncasecmp(speedstring,choices[current],i)) > 0)
  814.              ++current;
  815.           if (speed_match < 0 && current > 0)  /* oops - overshot */
  816.              --current;
  817.           if (current >= numchoices) /* bumped end of list */
  818.              current = numchoices - 1;
  819.           }
  820.            }
  821.         break;
  822.      }
  823.  
  824.       if (increment) {            /* apply cursor movement */
  825.      current += increment;
  826.      if (speedstring)        /* zap speedstring */
  827.         speedstring[0] = 0;
  828.      }
  829.       while (1) {            /* adjust to a non-comment choice */
  830.      if (current < 0 || current >= numchoices)
  831.          increment = rev_increment;
  832.      else if ((attributes[current] & 256) == 0)
  833.          break;
  834.      current += increment;
  835.      }
  836.       if (topleftchoice > numchoices - boxitems)
  837.      topleftchoice = ((numchoices+boxwidth-1)/boxwidth)*boxwidth - boxitems;
  838.       if (topleftchoice < 0)
  839.      topleftchoice = 0;
  840.       while (current < topleftchoice) {
  841.      topleftchoice -= boxwidth;
  842.      redisplay = 1;
  843.      }
  844.       while (current >= topleftchoice + boxitems) {
  845.      topleftchoice += boxwidth;
  846.      redisplay = 1;
  847.      }
  848.       }
  849.  
  850. fs_choice_end:
  851.    lookatmouse = savelookatmouse;
  852.    return(ret);
  853.  
  854. }
  855.  
  856.  
  857. #ifndef XFRACT
  858. /* case independent version of strncmp */
  859. int strncasecmp(char *s,char *t,int ct)
  860. {
  861.    for(; (tolower(*s) == tolower(*t)) && --ct ; s++,t++)
  862.       if(*s == '\0')
  863.      return(0);
  864.    return(tolower(*s) - tolower(*t));
  865. }
  866. #endif
  867.  
  868.  
  869. static int menutype;
  870. #define MENU_HDG 3
  871. #define MENU_ITEM 1
  872.  
  873. int main_menu(int fullmenu)
  874. {
  875.    char *choices[44]; /* 2 columns * 22 rows */
  876.    int attributes[44];
  877.    int choicekey[44];
  878.    int i;
  879.    int nextleft,nextright;
  880.    int oldtabmode,oldhelpmode;
  881.    oldtabmode = tabmode;
  882.    oldhelpmode = helpmode;
  883. top:
  884.    menutype = fullmenu;
  885.    tabmode = 0;
  886.    for (i = 0; i < 44; ++i) {
  887.       attributes[i] = 256;
  888.       choices[i] = "";
  889.       choicekey[i] = -1;
  890.       }
  891.    nextleft = -2;
  892.    nextright = -1;
  893.  
  894.    if (fullmenu) {
  895.       choices[nextleft+=2] = "      CURRENT IMAGE";
  896.       attributes[nextleft] = 256+MENU_HDG;
  897.       choicekey[nextleft+=2] = 13; /* enter */
  898.       attributes[nextleft] = MENU_ITEM;
  899.       if (calc_status == 2)
  900.      choices[nextleft] = "continue calculation";
  901.       else
  902.      choices[nextleft] = "return to image";
  903.       choicekey[nextleft+=2] = 9; /* tab */
  904.       attributes[nextleft] = MENU_ITEM;
  905.       choices[nextleft] = "info about image      <tab>";
  906.       choicekey[nextleft+=2] = -10;
  907.       attributes[nextleft] = MENU_ITEM;
  908.       choices[nextleft] = "zoom box functions...";
  909.       nextleft+=2;
  910.       }
  911.    choices[nextleft+=2] = "      NEW IMAGE";
  912.    attributes[nextleft] = 256+MENU_HDG;
  913.    choicekey[nextleft+=2] = DELETE;
  914.    attributes[nextleft] = MENU_ITEM;
  915.    choices[nextleft] = "select video mode...  <del>";
  916.    choicekey[nextleft+=2] = 't';
  917.    attributes[nextleft] = MENU_ITEM;
  918.    choices[nextleft] = "select fractal type    <t>";
  919.    if (fullmenu) {
  920.       if ((curfractalspecific->tojulia != NOFRACTAL
  921.       && param[0] == 0.0 && param[1] == 0.0)
  922.       || curfractalspecific->tomandel != NOFRACTAL) {
  923.      choicekey[nextleft+=2] = ' ';
  924.      attributes[nextleft] = MENU_ITEM;
  925.      choices[nextleft] = "toggle to/from julia <space>";
  926.      }
  927.       choicekey[nextleft+=2] = '\\';
  928.       attributes[nextleft] = MENU_ITEM;
  929.       choices[nextleft] = "return to prior image  <\\>";
  930.       }
  931.    nextleft += 2;
  932.    choices[nextleft+=2] = "      OPTIONS";
  933.    attributes[nextleft] = 256+MENU_HDG;
  934.    choicekey[nextleft+=2] = 'x';
  935.    attributes[nextleft] = MENU_ITEM;
  936.    choices[nextleft] = "basic options...       <x>";
  937.    choicekey[nextleft+=2] = 'y';
  938.    attributes[nextleft] = MENU_ITEM;
  939.    choices[nextleft] = "extended doodads...    <y>";
  940.    choicekey[nextleft+=2] = 'z';
  941.    attributes[nextleft] = MENU_ITEM;
  942.    choices[nextleft] = "type-specific parms... <z>";
  943.    choicekey[nextleft+=2] = 'v';
  944.    attributes[nextleft] = MENU_ITEM;
  945.    choices[nextleft] = "view window options... <v>";
  946.    choicekey[nextleft+=2] = 'i';
  947.    attributes[nextleft] = MENU_ITEM;
  948.    choices[nextleft] = "fractal 3D parms...    <i>";
  949.  
  950.    choices[nextright+=2] = "        FILE";
  951.    attributes[nextright] = 256+MENU_HDG;
  952.    choicekey[nextright+=2] = '@';
  953.    attributes[nextright] = MENU_ITEM;
  954.    choices[nextright] = "run saved command set... <@>";
  955.    if (fullmenu) {
  956.       choicekey[nextright+=2] = 's';
  957.       attributes[nextright] = MENU_ITEM;
  958.       choices[nextright] = "save image to file       <s>";
  959.       }
  960.    choicekey[nextright+=2] = 'r';
  961.    attributes[nextright] = MENU_ITEM;
  962.    choices[nextright] = "load image from file...  <r>";
  963.    choicekey[nextright+=2] = '3';
  964.    attributes[nextright] = MENU_ITEM;
  965.    choices[nextright] = "3d transform from file...<3>";
  966.    if (fullmenu) {
  967.       choicekey[nextright+=2] = 'o';
  968.       attributes[nextright] = MENU_ITEM;
  969.       choices[nextright] = "3d overlay from file...  <o>";
  970.       choicekey[nextright+=2] = 'b';
  971.       attributes[nextright] = MENU_ITEM;
  972.       choices[nextright] = "save current parameters..<b>";
  973.       choicekey[nextright+=2] = 'p';
  974.       attributes[nextright] = MENU_ITEM;
  975.       choices[nextright] = "print image              <p>";
  976.       }
  977.    choicekey[nextright+=2] = 'd';
  978.    attributes[nextright] = MENU_ITEM;
  979.    choices[nextright] = "shell to dos             <d>";
  980.    choicekey[nextright+=2] = ESC;
  981.    attributes[nextright] = MENU_ITEM;
  982.    choices[nextright] = "quit Fractint           <esc>";
  983.    choicekey[nextright+=2] = INSERT;
  984.    attributes[nextright] = MENU_ITEM;
  985.    choices[nextright] = "restart Fractint        <ins>";
  986.    if (fullmenu && gotrealdac && colors >= 16) {
  987.       nextright += 2;
  988.       choices[nextright+=2] = "       COLORS";
  989.       attributes[nextright] = 256+MENU_HDG;
  990.       /*** choicekey[nextright+=2] = -12;
  991.         attributes[nextright] = MENU_ITEM;
  992.         choices[nextright] = "color cycling menu...";
  993.         choicekey[nextright+=2] = -13;
  994.         attributes[nextright] = MENU_ITEM;
  995.         choices[nextright] = "palette editing menu..."; ***/
  996.       choicekey[nextright+=2] = 'c';
  997.       attributes[nextright] = MENU_ITEM;
  998.       choices[nextright] = "color cycling mode       <c>";
  999.       choicekey[nextright+=2] = '+';
  1000.       attributes[nextright] = MENU_ITEM;
  1001.       choices[nextright] = "rotate palette      <+>, <->";
  1002.       if (colors > 16) {
  1003.      if (!reallyega) {
  1004.         choicekey[nextright+=2] = 'e';
  1005.         attributes[nextright] = MENU_ITEM;
  1006.         choices[nextright] = "palette editing mode     <e>";
  1007.         }
  1008.      choicekey[nextright+=2] = 'a';
  1009.      attributes[nextright] = MENU_ITEM;
  1010.      choices[nextright] = "make starfield           <a>";
  1011.      }
  1012.       }
  1013.  
  1014.    i = (keypressed()) ? getakey() : 0;
  1015.    if (menu_checkkey(i,0) == 0) {
  1016.       helpmode = HELPMAIN;       /* switch help modes */
  1017.       if ((nextleft += 2) < nextright)
  1018.      nextleft = nextright + 1;
  1019.       i = fullscreen_choice(CHOICEMENU,
  1020.       "          MAIN MENU\n(<Esc> returns here from image)",
  1021.       NULL,NULL,nextleft,choices,attributes,
  1022.       2,nextleft/2,29,0,NULL,NULL,NULL,menu_checkkey);
  1023.       if (i == -1)     /* escape */
  1024.      i = ESC;
  1025.       else if (i < 0)
  1026.      i = 0 - i;
  1027.       else {              /* user selected a choice */
  1028.      i = choicekey[i];
  1029.      switch (i) {          /* check for special cases */
  1030.         case -10:          /* zoombox functions */
  1031.            helpmode = HELPZOOM;
  1032.            help(0);
  1033.            i = 0;
  1034.            break;
  1035.         }
  1036.      }
  1037.       }
  1038.    if (i == ESC) {           /* escape from menu exits Fractint */
  1039.       static char far s[] = "Exit from Fractint (y/n)? y";
  1040.       helptitle();
  1041.       setattr(1,0,C_GENERAL_MED,24*80);
  1042.       for (i = 9; i <= 11; ++i)
  1043.      setattr(i,18,C_GENERAL_INPUT,40);
  1044.       putstringcenter(10,18,40,C_GENERAL_INPUT,s);
  1045.       movecursor(25,80);
  1046.       while ((i = getakey()) != 'y' && i != 'Y' && i != 13) {
  1047.      if (i == 'n' || i == 'N')
  1048.         goto top;
  1049.      }
  1050.       goodbye();
  1051.       }
  1052.    if (i == TAB) {
  1053.       tab_display();
  1054.       i = 0;
  1055.       }
  1056.    if (i == ENTER || i == ENTER_2)
  1057.       i = 0;             /* don't trigger new calc */
  1058.    tabmode = oldtabmode;
  1059.    helpmode = oldhelpmode;
  1060.    return(i);
  1061. }
  1062.  
  1063. static int menu_checkkey(int curkey,int choice)
  1064. {
  1065.    int testkey;
  1066.    testkey = (curkey>='A' && curkey<='Z') ? curkey+('a'-'A') : curkey;
  1067.    if (strchr("@txyzvir3d",testkey) || testkey == INSERT
  1068.      || testkey == ESC || testkey == DELETE)
  1069.       return(0-testkey);
  1070.    if (menutype) {
  1071.       if (strchr("\\sobp",testkey) || testkey == 9)
  1072.      return(0-testkey);
  1073.       if (testkey == ' ')
  1074.      if ((curfractalspecific->tojulia != NOFRACTAL
  1075.           && param[0] == 0.0 && param[1] == 0.0)
  1076.        || curfractalspecific->tomandel != NOFRACTAL)
  1077.      return(0-testkey);
  1078.       if (gotrealdac && colors >= 16) {
  1079.      if (strchr("c+-",testkey))
  1080.         return(0-testkey);
  1081.      if (colors > 16
  1082.        && (testkey == 'a' || (!reallyega && testkey == 'e')))
  1083.         return(0-testkey);
  1084.      }
  1085.       }
  1086.    if (check_vidmode_key(0,testkey) >= 0)
  1087.       return(0-testkey);
  1088.    return(0);
  1089. }
  1090.  
  1091.  
  1092. int input_field(
  1093.     int options,          /* &1 numeric, &2 integer, &4 double */
  1094.     int attr,          /* display attribute */
  1095.     char *fld,          /* the field itself */
  1096.     int len,          /* field length (declare as 1 larger for \0) */
  1097.     int row,          /* display row */
  1098.     int col,          /* display column */
  1099.     int (*checkkey)(int)  /* routine to check non data keys, or NULL */
  1100.     )
  1101. {
  1102.    char savefld[81];
  1103.    char buf[81];
  1104.    int insert, started, offset, curkey, display;
  1105.    int i, j;
  1106.    int ret,savelookatmouse;
  1107.    savelookatmouse = lookatmouse;
  1108.    lookatmouse = 0;
  1109.    ret = -1;
  1110.    strcpy(savefld,fld);
  1111.    insert = started = offset = 0;
  1112.    display = 1;
  1113.    while (1) {
  1114.       strcpy(buf,fld);
  1115.       i = strlen(buf);
  1116.       while (i < len)
  1117.      buf[i++] = ' ';
  1118.       buf[len] = 0;
  1119.       if (display) {                    /* display current value */
  1120.      putstring(row,col,attr,buf);
  1121.      display = 0;
  1122.      }
  1123.       curkey = keycursor(row+insert,col+offset);  /* get a keystroke */
  1124.       switch (curkey) {
  1125.      case ENTER:
  1126.      case ENTER_2:
  1127.         ret = 0;
  1128.         goto inpfld_end;
  1129.      case ESC:
  1130.         goto inpfld_end;
  1131.      case RIGHT_ARROW:
  1132.      case RIGHT_ARROW_2:
  1133.         if (offset < len) ++offset;
  1134.         started = 1;
  1135.         break;
  1136.      case LEFT_ARROW:
  1137.      case LEFT_ARROW_2:
  1138.         if (offset > 0) --offset;
  1139.         started = 1;
  1140.         break;
  1141.      case HOME:
  1142.         offset = 0;
  1143.         started = 1;
  1144.         break;
  1145.      case END:
  1146.         offset = strlen(fld);
  1147.         started = 1;
  1148.         break;
  1149.      case 8:
  1150.      case 127:                /* backspace */
  1151.         if (offset > 0) {
  1152.            j = strlen(fld);
  1153.            for (i = offset-1; i < j; ++i)
  1154.           fld[i] = fld[i+1];
  1155.            --offset;
  1156.            }
  1157.         started = display = 1;
  1158.         break;
  1159.      case DELETE:                /* delete */
  1160.         j = strlen(fld);
  1161.         for (i = offset; i < j; ++i)
  1162.            fld[i] = fld[i+1];
  1163.         started = display = 1;
  1164.         break;
  1165.      case INSERT:                /* insert */
  1166.         insert ^= 0x8000;
  1167.         started = 1;
  1168.         break;
  1169.      case F5:
  1170.         strcpy(fld,savefld);
  1171.         insert = started = offset = 0;
  1172.         display = 1;
  1173.         break;
  1174.      default:
  1175.             if (nonalpha(curkey)) {
  1176.            if (checkkey && (ret = (*checkkey)(curkey)))
  1177.           goto inpfld_end;
  1178.            break;                     /* non alphanum char */
  1179.            }
  1180.         if (offset >= len) break;             /* at end of field */
  1181.         if (insert && started && strlen(fld) >= len)
  1182.            break;                     /* insert & full */
  1183.         if ((options & 1)
  1184.           && (curkey < '0' || curkey > '9')
  1185.           && curkey != '+' && curkey != '-') {
  1186.            if ((options & 2))
  1187.           break;
  1188.            /* allow scientific notation, and specials "e" and "p" */
  1189.            if ( ((curkey != 'e' && curkey != 'E') || offset >= 18)
  1190.          && ((curkey != 'p' && curkey != 'P') || offset != 0 )
  1191.          && curkey != '.')
  1192.           break;
  1193.            }
  1194.         if (started == 0) /* first char is data, zap field */
  1195.            fld[0] = 0;
  1196.         if (insert) {
  1197.            j = strlen(fld);
  1198.            while (j >= offset) {
  1199.           fld[j+1] = fld[j];
  1200.           --j;
  1201.           }
  1202.            }
  1203.         if (offset >= strlen(fld))
  1204.            fld[offset+1] = 0;
  1205.         fld[offset++] = curkey;
  1206.         /* if "e" or "p" in first col make number e or pi */
  1207.         if ((options & 3) == 1) { /* floating point */
  1208.            double tmpd;
  1209.            int specialv;
  1210.            char tmpfld[30];
  1211.            specialv = 0;
  1212.            if (*fld == 'e' || *fld == 'E') {
  1213.           tmpd = exp(1.0);
  1214.           specialv = 1;
  1215.           }
  1216.            if (*fld == 'p' || *fld == 'P') {
  1217.           tmpd = atan(1.0) * 4;
  1218.           specialv = 1;
  1219.           }
  1220.            if (specialv) {
  1221.           if ((options & 4) == 0)
  1222.              roundfloatd(&tmpd);
  1223.           sprintf(tmpfld,"%.15g",tmpd);
  1224.           tmpfld[len-1] = 0; /* safety, field should be long enough */
  1225.           strcpy(fld,tmpfld);
  1226.           offset = 0;
  1227.           }
  1228.            }
  1229.         started = display = 1;
  1230.      }
  1231.       }
  1232. inpfld_end:
  1233.    lookatmouse = savelookatmouse;
  1234.    return(ret);
  1235. }
  1236.  
  1237. int field_prompt(
  1238.     int options,        /* &1 numeric value, &2 integer */
  1239.     char *hdg,        /* heading, \n delimited lines */
  1240.     char *instr,        /* additional instructions or NULL */
  1241.     char *fld,        /* the field itself */
  1242.     int len,        /* field length (declare as 1 larger for \0) */
  1243.     int (*checkkey)()   /* routine to check non data keys, or NULL */
  1244.     )
  1245. {
  1246.    char *charptr;
  1247.    int boxwidth,titlelines,titlecol,titlerow;
  1248.    int promptcol;
  1249.    int i,j;
  1250.    char buf[81];
  1251.    helptitle();               /* clear screen, display title */
  1252.    setattr(1,0,C_PROMPT_BKGRD,24*80);      /* init rest to background */
  1253.    charptr = hdg;              /* count title lines, find widest */
  1254.    i = boxwidth = 0;
  1255.    titlelines = 1;
  1256.    while (*charptr) {
  1257.       if (*(charptr++) == '\n') {
  1258.      ++titlelines;
  1259.      i = -1;
  1260.      }
  1261.       if (++i > boxwidth)
  1262.      boxwidth = i;
  1263.       }
  1264.    if (len > boxwidth)
  1265.       boxwidth = len;
  1266.    i = titlelines + 4;              /* total rows in box */
  1267.    titlerow = (25 - i) / 2;          /* top row of it all when centered */
  1268.    titlerow -= titlerow / 4;          /* higher is better if lots extra */
  1269.    titlecol = (80 - boxwidth) / 2;      /* center the box */
  1270.    titlecol -= (90 - boxwidth) / 20;
  1271.    promptcol = titlecol - (boxwidth-len)/2;
  1272.    j = titlecol;              /* add margin at each side of box */
  1273.    if ((i = (82-boxwidth)/4) > 3)
  1274.       i = 3;
  1275.    j -= i;
  1276.    boxwidth += i * 2;
  1277.    for (i = -1; i < titlelines+3; ++i)      /* draw empty box */
  1278.       setattr(titlerow+i,j,C_PROMPT_LO,boxwidth);
  1279.    textcbase = titlecol;          /* set left margin for putstring */
  1280.    putstring(titlerow,0,C_PROMPT_HI,hdg); /* display heading */
  1281.    textcbase = 0;
  1282.    i = titlerow + titlelines + 4;
  1283.    if (instr) {               /* display caller's instructions */
  1284.       charptr = instr;
  1285.       j = -1;
  1286.       while ((buf[++j] = *(charptr++)))
  1287.      if (buf[j] == '\n') {
  1288.         buf[j] = 0;
  1289.         putstringcenter(i++,0,80,C_PROMPT_BKGRD,buf);
  1290.         j = -1;
  1291.         }
  1292.       putstringcenter(i,0,80,C_PROMPT_BKGRD,buf);
  1293.       }
  1294.    else                   /* default instructions */
  1295.       putstringcenter(i,0,80,C_PROMPT_BKGRD,
  1296.           "Press ENTER when finished (or ESCAPE to back out)");
  1297.    return(input_field(options,C_PROMPT_INPUT,fld,len,
  1298.               titlerow+titlelines+1,promptcol,checkkey));
  1299. }
  1300.  
  1301.  
  1302. /* thinking(1,message):
  1303.       if thinking message not yet on display, it is displayed;
  1304.       otherwise the wheel is updated
  1305.       returns 0 to keep going, -1 if keystroke pending
  1306.    thinking(0,NULL):
  1307.       call this when thinking phase is done
  1308.    */
  1309.  
  1310. int thinking(int options,char *msg)
  1311. {
  1312.    static int thinkstate = -1;
  1313.    static char *wheel[] = {"-","\\","|","/"};
  1314.    static int thinkcol;
  1315.    char buf[81];
  1316.    if (options == 0) {
  1317.       if (thinkstate >= 0) {
  1318.      thinkstate = -1;
  1319.      unstackscreen();
  1320.      }
  1321.       return(0);
  1322.       }
  1323.    if (thinkstate < 0) {
  1324.       stackscreen();
  1325.       thinkstate = 0;
  1326.       helptitle();
  1327.       strcpy(buf,"  ");
  1328.       strcat(buf,msg);
  1329.       strcat(buf,"    ");
  1330.       putstring(4,10,C_GENERAL_HI,buf);
  1331.       thinkcol = textcol - 3;
  1332.       }
  1333.    putstring(4,thinkcol,C_GENERAL_HI,wheel[thinkstate]);
  1334.    movecursor(25,80); /* turn off cursor */
  1335.    thinkstate = (thinkstate + 1) & 3;
  1336.    return (keypressed());
  1337. }
  1338.  
  1339.  
  1340. void clear_screen(void)  /* a stub for a windows only subroutine */
  1341. {
  1342. }
  1343.  
  1344.  
  1345. /* savegraphics/restoregraphics: video.asm subroutines */
  1346.  
  1347. static BYTE far *swapsavebuf;
  1348. static unsigned int memhandle;
  1349. unsigned long swaptotlen;
  1350. unsigned long swapoffset;
  1351. BYTE far *swapvidbuf;
  1352. int swaplength;
  1353. static int swaptype = -1;
  1354. static int swapblklen; /* must be a power of 2 */
  1355. extern void (*swapsetup)(void),swapnormread(void);
  1356. void movewords(int,BYTE far*,BYTE far*);
  1357. #ifndef XFRACT
  1358. extern BYTE suffix[4096];
  1359. #else
  1360. BYTE suffix[4096];
  1361. #endif
  1362.  
  1363. extern    unsigned int emmallocate(unsigned int),xmmallocate(unsigned int);
  1364. extern    void   emmdeallocate(unsigned int),xmmdeallocate(unsigned int);
  1365. extern    void   emmgetpage(unsigned int, unsigned int);
  1366. extern    BYTE far *emmquery(void);
  1367. extern    unsigned int *xmmquery(void);
  1368.  
  1369. int savegraphics()
  1370. {
  1371.    extern int made_dsktemp;
  1372.    int i;
  1373.    struct {
  1374.       unsigned long   len;
  1375.       unsigned int    sourcehandle;
  1376.       unsigned long   sourceptr;
  1377.       unsigned int    desthandle;
  1378.       unsigned long   destptr;
  1379.       } xmmparms;
  1380.    discardgraphics(); /* if any emm/xmm in use from prior call, release it */
  1381.    swaptotlen = (long)sxdots * sydots;
  1382.    i = colors;
  1383.    while (i <= 16) {
  1384.       swaptotlen >>= 1;
  1385.       i = i * i;
  1386.       }
  1387.    swapoffset = 0;
  1388.    if (debugflag != 420 && debugflag != 422 /* 422=xmm test, 420=disk test */
  1389.      && (swapsavebuf = emmquery()) != NULL
  1390.      && (memhandle = emmallocate((unsigned int)((swaptotlen + 16383) >> 14)))
  1391.      != 0) {
  1392.       swaptype = 0; /* use expanded memory */
  1393.       swapblklen = 16384;
  1394.       }
  1395.    else if (debugflag != 420
  1396.      && xmmquery() !=0
  1397.      && (memhandle = xmmallocate((unsigned int)((swaptotlen + 1023) >> 10)))
  1398.      != 0) {
  1399.       swaptype = 1; /* use extended memory */
  1400.       swapblklen = 16384;
  1401.       }
  1402.    else {
  1403.       swaptype = 2; /* use disk */
  1404.       swapblklen = 4096;
  1405.  
  1406.    /* MCP 7-7-91, If 'memhandle' is an 'unsigned int', how is it ever going
  1407.       to be equal to -1?
  1408.  
  1409.       if ((memhandle = open("FRACTINT.DSK",O_CREAT|O_WRONLY|O_BINARY,S_IWRITE))
  1410.      == -1) {
  1411.    */
  1412.       if ((memhandle = open("FRACTINT.DSK",O_CREAT|O_WRONLY|O_BINARY,S_IWRITE))
  1413.      == 0xffff) {
  1414.  
  1415.  
  1416. dskfile_error:
  1417.      setvideotext(); /* text mode */
  1418.      setclear();
  1419.      printf("!!! error in temp file FRACTINT.DSK (disk full?) - aborted\n\n");
  1420.      exit(1);
  1421.      }
  1422.       made_dsktemp = 1;
  1423.       }
  1424.    while (swapoffset < swaptotlen) {
  1425.       swaplength = swapblklen;
  1426.       if ((swapoffset & (swapblklen-1)) != 0)
  1427.      swaplength = swapblklen - (swapoffset & (swapblklen-1));
  1428.       if (swaplength > swaptotlen - swapoffset)
  1429.      swaplength = swaptotlen - swapoffset;
  1430.       (*swapsetup)(); /* swapoffset,swaplength -> sets swapvidbuf,swaplength */
  1431.       switch(swaptype) {
  1432.      case 0:
  1433.         emmgetpage((unsigned int)(swapoffset>>14),memhandle);
  1434.         movewords(swaplength>>1,swapvidbuf,
  1435.               swapsavebuf+(swapoffset&(swapblklen-1)));
  1436.         break;
  1437.      case 1:
  1438.         xmmparms.len = swaplength;
  1439.         xmmparms.sourcehandle = 0; /* Source is conventional memory */
  1440.         xmmparms.sourceptr = (unsigned long)swapvidbuf;
  1441.         xmmparms.desthandle = memhandle;
  1442.         xmmparms.destptr = swapoffset;
  1443.         xmmmoveextended(&xmmparms);
  1444.         break;
  1445.      default:
  1446.         movewords(swaplength>>1,swapvidbuf,(BYTE far *)suffix);
  1447.         if (write(memhandle,suffix,swaplength) == -1)
  1448.            goto dskfile_error;
  1449.      }
  1450.       swapoffset += swaplength;
  1451.       }
  1452.    if (swaptype == 2)
  1453.       close(memhandle);
  1454.    return 0;
  1455. }
  1456.  
  1457. void restoregraphics()
  1458. {
  1459.    struct {
  1460.       unsigned long   len;
  1461.       unsigned int    sourcehandle;
  1462.       unsigned long   sourceptr;
  1463.       unsigned int    desthandle;
  1464.       unsigned long   destptr;
  1465.       } xmmparms;
  1466.    swapoffset = 0;
  1467.    if (swaptype == 2)
  1468.       memhandle = open("FRACTINT.DSK",O_RDONLY|O_BINARY,S_IREAD);
  1469.    swapvidbuf = MK_FP(extraseg+0x1000,0); /* for swapnormwrite case */
  1470.    while (swapoffset < swaptotlen) {
  1471.       swaplength = swapblklen;
  1472.       if ((swapoffset & (swapblklen-1)) != 0)
  1473.      swaplength = swapblklen - (swapoffset & (swapblklen-1));
  1474.       if (swaplength > swaptotlen - swapoffset)
  1475.      swaplength = swaptotlen - swapoffset;
  1476.       if (swapsetup != swapnormread)
  1477.      (*swapsetup)(); /* swapoffset,swaplength -> sets swapvidbuf,swaplength */
  1478.       switch(swaptype) {
  1479.      case 0:
  1480.         emmgetpage((unsigned int)(swapoffset>>14),memhandle);
  1481.         movewords(swaplength>>1,swapsavebuf+(swapoffset&(swapblklen-1)),
  1482.               swapvidbuf);
  1483.         break;
  1484.      case 1:
  1485.         xmmparms.len = swaplength;
  1486.         xmmparms.sourcehandle = memhandle;
  1487.         xmmparms.sourceptr = swapoffset;
  1488.         xmmparms.desthandle = 0; /* conventional memory */
  1489.         xmmparms.destptr = (unsigned long)swapvidbuf;
  1490.         xmmmoveextended(&xmmparms);
  1491.         break;
  1492.      default:
  1493.         read(memhandle,suffix,swaplength);
  1494.         movewords(swaplength>>1,(BYTE far *)suffix,swapvidbuf);
  1495.      }
  1496.       if (swapsetup == swapnormread)
  1497.      swapnormwrite();
  1498.       swapoffset += swaplength;
  1499.       }
  1500.    if (swaptype == 2)
  1501.       close(memhandle);
  1502.    discardgraphics();
  1503. }
  1504.  
  1505. void discardgraphics() /* release expanded/extended memory if any in use */
  1506. {
  1507.    switch(swaptype) {
  1508.       case 0:
  1509.      emmdeallocate(memhandle);
  1510.      break;
  1511.       case 1:
  1512.      xmmdeallocate(memhandle);
  1513.       }
  1514.    swaptype = -1;
  1515.    }
  1516.  
  1517.  
  1518. extern int extraseg;
  1519. extern int badconfig;
  1520. extern struct videoinfo far videotable[];
  1521. struct videoinfo far *vidtbl;  /* temporarily loaded fractint.cfg info */
  1522. int vidtbllen;               /* number of entries in above           */
  1523.  
  1524. int load_fractint_cfg(int options)
  1525. {
  1526.    /* Reads fractint.cfg, loading videoinfo entries into extraseg. */
  1527.    /* Sets vidtbl pointing to the loaded table, and returns the    */
  1528.    /* number of entries (also sets vidtbllen to this).           */
  1529.    /* Past vidtbl, cfglinenums are stored for update_fractint_cfg. */
  1530.    /* If fractint.cfg is not found or invalid, issues a message    */
  1531.    /* (first time the problem occurs only, and only if options is  */
  1532.    /* zero) and uses the hard-coded table.               */
  1533.  
  1534.    FILE *cfgfile;
  1535.    struct videoinfo far *vident;
  1536.    int far *cfglinenums;
  1537.    int linenum;
  1538.    int i, j, keynum, ax, bx, cx, dx, dotmode, xdots, ydots, colors;
  1539.    int commas[10];
  1540.    int textsafe2;
  1541.    char tempstring[150];
  1542.  
  1543.    vidtbl = MK_FP(extraseg,0);
  1544.    cfglinenums = (int far *)(&vidtbl[MAXVIDEOMODES]);
  1545.  
  1546.    if (badconfig)  /* fractint.cfg already known to be missing or bad */
  1547.       goto use_resident_table;
  1548.  
  1549. #ifndef XFRACT
  1550.    findpath("fractint.cfg",tempstring);
  1551. #else
  1552.    findpath("xfracint.cfg",tempstring);
  1553. #endif
  1554.    if (tempstring[0] == 0                 /* can't find the file */
  1555.      || (cfgfile = fopen(tempstring,"r")) == NULL)   /* can't open it */
  1556.       goto bad_fractint_cfg;
  1557.  
  1558.    vidtbllen = 0;
  1559.    linenum = 0;
  1560.    vident = vidtbl;
  1561.    while (vidtbllen < MAXVIDEOMODES
  1562.      && fgets(tempstring, 120, cfgfile)) {
  1563.       ++linenum;
  1564.       if (tempstring[0] == ';') continue;   /* comment line */
  1565.       tempstring[120] = 0;
  1566.       tempstring[strlen(tempstring)-1] = 0; /* zap trailing \n */
  1567.       memset(commas,0,20);
  1568.       i = j = -1;
  1569.       while (1) {
  1570.      if (tempstring[++i] < ' ') {
  1571.         if (tempstring[i] == 0) break;
  1572.         tempstring[i] = ' '; /* convert tab (or whatever) to blank */
  1573.         }
  1574.      else if (tempstring[i] == ',' && ++j < 10) {
  1575.         commas[j] = i + 1;     /* remember start of next field */
  1576.         tempstring[i] = 0;     /* make field a separate string */
  1577.         }
  1578.      }
  1579.       keynum = check_vidmode_keyname(tempstring);
  1580.       sscanf(&tempstring[commas[1]],"%x",&ax);
  1581.       sscanf(&tempstring[commas[2]],"%x",&bx);
  1582.       sscanf(&tempstring[commas[3]],"%x",&cx);
  1583.       sscanf(&tempstring[commas[4]],"%x",&dx);
  1584.       dotmode      = atoi(&tempstring[commas[5]]);
  1585.       xdots      = atoi(&tempstring[commas[6]]);
  1586.       ydots      = atoi(&tempstring[commas[7]]);
  1587.       colors      = atoi(&tempstring[commas[8]]);
  1588.       textsafe2   = dotmode / 100;
  1589.       dotmode     %= 100;
  1590.       if (j != 9 ||
  1591.         keynum < 0 ||
  1592.         dotmode < 0 || dotmode > 30 ||
  1593.         textsafe2 < 0 || textsafe2 > 4 ||
  1594.         xdots < 160 || xdots > 2048 ||
  1595.         ydots < 160 || ydots > 2048 ||
  1596.         (colors != 0 && colors != 2 && colors != 4 && colors != 16 &&
  1597.          colors != 256)
  1598.        )
  1599.      goto bad_fractint_cfg;
  1600.       cfglinenums[vidtbllen] = linenum; /* for update_fractint_cfg */
  1601.       far_memcpy(vident->name,     (char far *)&tempstring[commas[0]],25);
  1602.       far_memcpy(vident->comment,(char far *)&tempstring[commas[9]],25);
  1603.       vident->name[25] = vident->comment[25] = 0;
  1604.       vident->keynum      = keynum;
  1605.       vident->videomodeax = ax;
  1606.       vident->videomodebx = bx;
  1607.       vident->videomodecx = cx;
  1608.       vident->videomodedx = dx;
  1609.       vident->dotmode      = textsafe2 * 100 + dotmode;
  1610.       vident->xdots      = xdots;
  1611.       vident->ydots      = ydots;
  1612.       vident->colors      = colors;
  1613.       ++vident;
  1614.       ++vidtbllen;
  1615.       }
  1616.    fclose(cfgfile);
  1617.    return (vidtbllen);
  1618.  
  1619. bad_fractint_cfg:
  1620.    badconfig = -1; /* bad, no message issued yet */
  1621.    if (options == 0)
  1622.       bad_fractint_cfg_msg();
  1623.  
  1624. use_resident_table:
  1625.    vidtbllen = 0;
  1626.    vident = vidtbl;
  1627.    for (i = 0; i < 40; ++i) {
  1628.       if (videotable[i].xdots) {
  1629.      far_memcpy((char far *)vident,(char far *)&videotable[i],
  1630.             sizeof(*vident));
  1631.      ++vident;
  1632.      ++vidtbllen;
  1633.      }
  1634.       }
  1635.    return (vidtbllen);
  1636.  
  1637. }
  1638.  
  1639. void bad_fractint_cfg_msg()
  1640. {
  1641. static char far badcfgmsg[]={"\
  1642. File FRACTINT.CFG is missing or invalid.\n\
  1643. See Hardware Support and Video Modes in the full documentation for help.\n\
  1644. I will continue with only the built-in video modes available."};
  1645.    stopmsg(0,badcfgmsg);
  1646.    badconfig = 1; /* bad, message issued */
  1647. }
  1648.  
  1649. void load_videotable(int options)
  1650. {
  1651.    /* Loads fractint.cfg and copies the video modes which are */
  1652.    /* assigned to function keys into videotable.          */
  1653.    int keyents,i;
  1654.    load_fractint_cfg(options); /* load fractint.cfg to extraseg */
  1655.    keyents = 0;
  1656.    far_memset((char far *)videotable,0,sizeof(*vidtbl)*MAXVIDEOTABLE);
  1657.    for (i = 0; i < vidtbllen; ++i) {
  1658.       if (vidtbl[i].keynum > 0) {
  1659.      far_memcpy((char far *)&videotable[keyents],(char far *)&vidtbl[i],
  1660.             sizeof(*vidtbl));
  1661.      if (++keyents >= MAXVIDEOTABLE)
  1662.         break;
  1663.      }
  1664.       }
  1665. }
  1666.  
  1667. int check_vidmode_key(int option,int k)
  1668. {
  1669.    int i;
  1670.    /* returns videotable entry number if the passed keystroke is a  */
  1671.    /* function key currently assigned to a video mode, -1 otherwise */
  1672.    if (k == 1400)           /* special value from select_vid_mode  */
  1673.       return(MAXVIDEOTABLE-1); /* for last entry with no key assigned */
  1674.    if (k != 0)
  1675.       if (option == 0) { /* check resident video mode table */
  1676.      for (i = 0; i < MAXVIDEOTABLE; ++i) {
  1677.         if (videotable[i].keynum == k)
  1678.            return(i);
  1679.         }
  1680.      }
  1681.       else { /* check full vidtbl */
  1682.      for (i = 0; i < vidtbllen; ++i) {
  1683.         if (vidtbl[i].keynum == k)
  1684.            return(i);
  1685.         }
  1686.      }
  1687.    return(-1);
  1688. }
  1689.  
  1690. int check_vidmode_keyname(char *kname)
  1691. {
  1692.    /* returns key number for the passed keyname, 0 if not a keyname */
  1693.    int i,keyset;
  1694.    keyset = 1058;
  1695.    if (*kname == 'S' || *kname == 's') {
  1696.       keyset = 1083;
  1697.       ++kname;
  1698.       }
  1699.    else if (*kname == 'C' || *kname == 'c') {
  1700.       keyset = 1093;
  1701.       ++kname;
  1702.       }
  1703.    else if (*kname == 'A' || *kname == 'a') {
  1704.       keyset = 1103;
  1705.       ++kname;
  1706.       }
  1707.    if (*kname != 'F' && *kname != 'f')
  1708.       return(0);
  1709.    if (*++kname < '1' || *kname > '9')
  1710.       return(0);
  1711.    i = *kname - '0';
  1712.    if (*++kname != 0 && *kname != ' ') {
  1713.       if (*kname != '0' || i != 1)
  1714.      return(0);
  1715.       i = 10;
  1716.       ++kname;
  1717.       }
  1718.    while (*kname)
  1719.       if (*(kname++) != ' ')
  1720.      return(0);
  1721.    if ((i += keyset) < 2)
  1722.       i = 0;
  1723.    return(i);
  1724. }
  1725.  
  1726. void vidmode_keyname(int k,char *buf)
  1727. {
  1728.    /* set buffer to name of passed key number */
  1729.    *buf = 0;
  1730.    if (k > 0) {
  1731.       if (k > 1103) {
  1732.      *(buf++) = 'A';
  1733.      k -= 1103;
  1734.      }
  1735.       else if (k > 1093) {
  1736.      *(buf++) = 'C';
  1737.      k -= 1093;
  1738.      }
  1739.       else if (k > 1083) {
  1740.      *(buf++) = 'S';
  1741.      k -= 1083;
  1742.      }
  1743.       else
  1744.      k -= 1058;
  1745.       sprintf(buf,"F%d",k);
  1746.       }
  1747. }
  1748.  
  1749.