home *** CD-ROM | disk | FTP | other *** search
/ Computerworld 1996 March / Computerworld_1996-03_cd.bin / idg_cd3 / grafika / fraktaly / wins1821 / windos2.c < prev    next >
C/C++ Source or Header  |  1996-02-13  |  33KB  |  1,142 lines

  1.  
  2. /* Windows versions of DOS functions needed by PROMPTS.C */
  3.  
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <dos.h>
  7. #include <sys\types.h>
  8. #include <sys\stat.h>
  9. #include <fcntl.h>
  10. #include <math.h>
  11. #include "fractint.h"
  12. #include "fractype.h"
  13. #include "helpdefs.h"
  14.  
  15. /* routines in this module    */
  16. void movecursor(int row, int col);
  17. void setattr(int row, int col, int attr, int count);
  18. int  putstringcenter(int row, int col, int width, int attr, char far *msg);
  19. void putstring(int row, int col, int attr, unsigned char far *buf);
  20. int  fullscreen_choice(
  21.          int options, char far *hdg, char far *hdg2, char far *instr, int numchoices,
  22.          char **choices, int *attributes, int boxwidth, int boxdepth,
  23.          int colwidth, int current, void (*formatitem)(),
  24.          char *speedstring, int (*speedprompt)(), int (*checkkey)());
  25. int  strncasecmp(char *s,char *t,int ct);
  26. int  input_field(int options, int attr, char *fld, int len, int row, int col, int (*checkkey)(int) );
  27. int  field_prompt(int options, char *hdg, char *instr, char *fld, int len, int (*checkkey)(int) );
  28. void helptitle(void);
  29. void stackscreen(void);
  30. void unstackscreen(void);
  31. void discardscreen(void);
  32. void load_palette(void);
  33. void save_palette(void);
  34. void fractint_help(void);
  35.  
  36. extern  VOIDFARPTR cdecl farmemalloc(long);
  37.  
  38. /* faked/unimplemented routines */
  39.  
  40. struct videoinfo far *vidtbl;
  41. int vidtbllen = 0;
  42. int badconfig = 0;
  43.  
  44. int in_fractint_help = 0;
  45.  
  46. int win_release = 1821;
  47. char far win_comment[] =
  48.      {" "};                /*  publicly-released version */
  49. /*   {"Test Version - Not for Release"};   /* interim test versions */
  50. /*   {"'Public Beta' Release"};   /* interim test versions */
  51.  
  52. extern int time_to_resume;         /* time to resume? */
  53.  
  54. int text_type = 0;
  55. int textrow = 0, textcol = 0;
  56. int textrbase = 0, textcbase = 0;
  57. int lookatmouse;
  58.  
  59. /* fullscreen_choice options */
  60. #define CHOICERETURNKEY 1
  61. #define CHOICEMENU    2
  62. #define CHOICEHELP    4
  63.  
  64. char speed_prompt[]="Speed key string";
  65.  
  66. int fullscreen_choice(
  67.     int options,         /* &2 use menu coloring scheme           */
  68.                  /* &4 include F1 for help in instructions */
  69.                  /* &8 add caller's instr after normal set */
  70.     char far *hdg,         /* heading info, \n delimited           */
  71.     char far *hdg2,         /* column heading or NULL               */
  72.     char far *instr,     /* instructions, \n delimited, or NULL    */
  73.     int numchoices,      /* How many choices in list           */
  74.     char **choices,      /* array of choice strings            */
  75.     int *attributes,     /* &3: 0 normal color, 1,3 highlight      */
  76.                  /* &256 marks a dummy entry           */
  77.     int boxwidth,         /* box width, 0 for calc (in items)       */
  78.     int boxdepth,         /* box depth, 0 for calc, 99 for max      */
  79.     int colwidth,         /* data width of a column, 0 for calc     */
  80.     int current,         /* start with this item               */
  81.     void (*formatitem)(),/* routine to display an item or NULL     */
  82.     char *speedstring,   /* returned speed key value, or NULL >[30]*/
  83.     int (*speedprompt)(),/* routine to display prompt or NULL      */
  84.     int (*checkkey)()    /* routine to check keystroke or NULL     */
  85. )
  86.    /* return is: n>=0 for choice n selected,
  87.          -1 for escape
  88.           k for checkkey routine return value k (if not 0 nor -1)
  89.       speedstring[0] != 0 on return if string is present
  90.       */
  91. {
  92. static char far choiceinstr1a[]="Use the cursor keys to highlight your selection";
  93. static char far choiceinstr1b[]="Use the cursor keys or type a value to make a selection";
  94. static char far choiceinstr2a[]="Press ENTER for highlighted choice, or ESCAPE to back out";
  95. static char far choiceinstr2b[]="Press ENTER for highlighted choice, ESCAPE to back out, or F1 for help";
  96. static char far choiceinstr2c[]="Press ENTER for highlighted choice, or F1 for help";
  97.  
  98.    int titlelines,titlewidth;
  99.    int reqdrows;
  100.    int topleftrow,topleftcol;
  101.    int topleftchoice;
  102.    int speedrow;  /* speed key prompt */
  103.    int boxitems;  /* boxwidth*boxdepth */
  104.    int curkey,increment,rev_increment;
  105.    int redisplay;
  106.    int i,j,k;
  107.    char far *charptr;
  108.    char buf[81];
  109.    int speed_match = 0;
  110.    char curitem[81];
  111.    char *itemptr;
  112.    int ret,savelookatmouse;
  113.  
  114.    savelookatmouse = lookatmouse;
  115.    lookatmouse = 0;
  116.    ret = -1;
  117.    if (speedstring
  118.      && (i = strlen(speedstring)) > 0) { /* preset current to passed string */
  119.       current = 0;
  120.       while (current < numchoices
  121.     && (k = strncasecmp(speedstring,choices[current],i)) > 0)
  122.      ++current;
  123.       if (k < 0 && current > 0)  /* oops - overshot */
  124.      --current;
  125.       if (current >= numchoices) /* bumped end of list */
  126.      current = numchoices - 1;
  127.       }
  128.  
  129.    while (1) {
  130.       if (current >= numchoices)  /* no real choice in the list? */
  131.      goto fs_choice_end;
  132.       if ((attributes[current] & 256) == 0)
  133.      break;
  134.       ++current;          /* scan for a real choice */
  135.       }
  136.  
  137.    titlelines = titlewidth = 0;
  138.    if (hdg) {
  139.       charptr = hdg;          /* count title lines, find widest */
  140.       i = 0;
  141.       titlelines = 1;
  142.       while (*charptr) {
  143.      if (*(charptr++) == '\n') {
  144.         ++titlelines;
  145.         i = -1;
  146.         }
  147.      if (++i > titlewidth)
  148.         titlewidth = i;
  149.      }
  150.       }
  151.  
  152.    if (colwidth == 0)          /* find widest column */
  153.       for (i = 0; i < numchoices; ++i)
  154.      if (strlen(choices[i]) > colwidth)
  155.         colwidth = strlen(choices[i]);
  156.  
  157.    /* title(1), blank(1), hdg(n), blank(1), body(n), blank(1), instr(?) */
  158.    reqdrows = 3;          /* calc rows available */
  159.    if (hdg)
  160.       reqdrows += titlelines + 1;
  161.    if (instr) {           /* count instructions lines */
  162.       charptr = instr;
  163.       ++reqdrows;
  164.       while (*charptr)
  165.      if (*(charptr++) == '\n')
  166.         ++reqdrows;
  167.       if ((options & 8))      /* show std instr too */
  168.      reqdrows += 2;
  169.       }
  170.    else
  171.       reqdrows += 2;          /* standard instructions */
  172.    if (speedstring) ++reqdrows;   /* a row for speedkey prompt */
  173.    if (boxdepth > (i = 25 - reqdrows)) /* limit the depth to max */
  174.       boxdepth = i;
  175.    if (boxwidth == 0) {       /* pick box width and depth */
  176.       if (numchoices <= i - 2) {  /* single column is 1st choice if we can */
  177.      boxdepth = numchoices;
  178.      boxwidth = 1;
  179.      }
  180.       else {              /* sort-of-wide is 2nd choice */
  181.      boxwidth = 60 / (colwidth + 1);
  182.      if (boxwidth == 0
  183.        || (boxdepth = (numchoices+boxwidth-1)/boxwidth) > i - 2) {
  184.         boxwidth = 80 / (colwidth + 1); /* last gasp, full width */
  185.         if ((boxdepth = (numchoices+boxwidth-1)/boxwidth) > i)
  186.            boxdepth = i;
  187.         }
  188.      }
  189.       }
  190.    if ((i = 77 / boxwidth - colwidth) > 3) /* spaces to add @ left each choice */
  191.       i = 3;
  192.    j = boxwidth * (colwidth += i) + i;       /* overall width of box */
  193.    if (j < titlewidth+2)
  194.       j = titlewidth + 2;
  195.    if (j > 80)
  196.       j = 80;
  197.    if (j <= 70 && boxwidth == 2) {       /* special case makes menus nicer */
  198.       ++j;
  199.       ++colwidth;
  200.       }
  201.    k = (80 - j) / 2;               /* center the box */
  202.    k -= (90 - j) / 20;
  203.    topleftcol = k + i;               /* column of topleft choice */
  204.    i = (25 - reqdrows - boxdepth) / 2;
  205.    i -= i / 4;                   /* higher is better if lots extra */
  206.    topleftrow = 3 + titlelines + i;       /* row of topleft choice */
  207.  
  208.    /* now set up the overall display */
  209.    helptitle();                /* clear, display title line */
  210.    setattr(1,0,C_PROMPT_BKGRD,24*80);       /* init rest to background */
  211.    for (i = topleftrow-1-titlelines; i < topleftrow+boxdepth+1; ++i)
  212.       setattr(i,k,C_PROMPT_LO,j);       /* draw empty box */
  213.    if (hdg) {
  214.       textcbase = (80 - titlewidth) / 2;   /* set left margin for putstring */
  215.       textcbase -= (90 - titlewidth) / 20; /* put heading into box */
  216.       putstring(topleftrow-titlelines-1,0,C_PROMPT_HI,hdg);
  217.       textcbase = 0;
  218.       }
  219.    if (hdg2)                   /* display 2nd heading */
  220.       putstring(topleftrow-1,topleftcol,C_PROMPT_MED,hdg2);
  221.    i = topleftrow + boxdepth + 1;
  222.    if (instr == NULL || (options & 8)) {   /* display default instructions */
  223.       if (i < 20) ++i;
  224.       if (speedstring) {
  225.      speedrow = i;
  226.      *speedstring = 0;
  227.      if (++i < 22) ++i;
  228.      }
  229.       putstringcenter(i++,0,80,C_PROMPT_BKGRD,
  230.         (speedstring) ? choiceinstr1b : choiceinstr1a);
  231.       putstringcenter(i++,0,80,C_PROMPT_BKGRD,
  232.         (options&CHOICEMENU) ? choiceinstr2c
  233.         : ((options&CHOICEHELP) ? choiceinstr2b : choiceinstr2a));
  234.       }
  235.    if (instr) {                /* display caller's instructions */
  236.       charptr = instr;
  237.       j = -1;
  238.       while ((buf[++j] = *(charptr++)))
  239.      if (buf[j] == '\n') {
  240.         buf[j] = 0;
  241.         putstringcenter(i++,0,80,C_PROMPT_BKGRD,buf);
  242.         j = -1;
  243.         }
  244.       putstringcenter(i,0,80,C_PROMPT_BKGRD,buf);
  245.       }
  246.  
  247.    boxitems = boxwidth * boxdepth;
  248.    topleftchoice = 0;               /* pick topleft for init display */
  249.    while (current - topleftchoice >= boxitems
  250.      || (current - topleftchoice > boxitems/2
  251.      && topleftchoice + boxitems < numchoices))
  252.       topleftchoice += boxwidth;
  253.    redisplay = 1;
  254.  
  255.    while (1) { /* main loop */
  256.  
  257.       if (redisplay) {                 /* display the current choices */
  258.      if ((options & CHOICEMENU) == 0) {
  259.         memset(buf,' ',80);
  260.         buf[boxwidth*colwidth] = 0;
  261.         for (i = (hdg2) ? 0 : -1; i <= boxdepth; ++i)  /* blank the box */
  262.            putstring(topleftrow+i,topleftcol,C_PROMPT_LO,buf);
  263.         }
  264.      for (i = 0; i+topleftchoice < numchoices && i < boxitems; ++i) {
  265.         /* display the choices */
  266.         if ((k = attributes[j = i+topleftchoice] & 3) == 1)
  267.            k = C_PROMPT_LO;
  268.         else if (k == 3)
  269.            k = C_PROMPT_HI;
  270.         else
  271.            k = C_PROMPT_MED;
  272.         if (formatitem)
  273.            (*formatitem)(j,charptr=buf);
  274.         else
  275.            charptr = choices[j];
  276.         putstring(topleftrow+i/boxwidth,topleftcol+(i%boxwidth)*colwidth,
  277.               k,charptr);
  278.         }
  279.      /***
  280.      ... format differs for summary/detail, whups, force box width to
  281.      ...  be 72 when detail toggle available?  (2 grey margin each
  282.      ...  side, 1 blue margin each side)
  283.      ***/
  284.      if (topleftchoice > 0 && hdg2 == NULL)
  285.         putstring(topleftrow-1,topleftcol,C_PROMPT_LO,"(more)");
  286.      if (topleftchoice + boxitems < numchoices)
  287.         putstring(topleftrow+boxdepth,topleftcol,C_PROMPT_LO,"(more)");
  288.      redisplay = 0;
  289.      }
  290.  
  291.       i = current - topleftchoice;         /* highlight the current choice */
  292.       if (formatitem)
  293.      (*formatitem)(current,itemptr=curitem);
  294.       else
  295.      itemptr = choices[current];
  296.       putstring(topleftrow+i/boxwidth,topleftcol+(i%boxwidth)*colwidth,
  297.         C_CHOICE_CURRENT,itemptr);
  298.  
  299.       if (speedstring) {             /* show speedstring if any */
  300.      memset(buf,' ',80);
  301.      buf[80] = 0;
  302.      putstring(speedrow,0,C_PROMPT_BKGRD,buf);
  303.      if (*speedstring) {             /* got a speedstring on the go */
  304.         putstring(speedrow,15,C_CHOICE_SP_INSTR," ");
  305.         if (speedprompt)
  306.            j = speedprompt(speedrow,16,C_CHOICE_SP_INSTR,speedstring,speed_match);
  307.         else {
  308.            putstring(speedrow,16,C_CHOICE_SP_INSTR,speed_prompt);
  309.            j = strlen(speed_prompt);
  310.            }
  311.         strcpy(buf,speedstring);
  312.         i = strlen(buf);
  313.         while (i < 30)
  314.            buf[i++] = ' ';
  315.         buf[i] = 0;
  316.         putstring(speedrow,16+j,C_CHOICE_SP_INSTR," ");
  317.         putstring(speedrow,17+j,C_CHOICE_SP_KEYIN,buf);
  318.         movecursor(speedrow,17+j+strlen(speedstring));
  319.         }
  320.      else
  321.         movecursor(25,80);
  322.      }
  323.       else
  324.      movecursor(25,80);
  325.  
  326. /*    while (!keypressed()) { } /* enables help */
  327. /*      curkey = getakey(); */
  328.       curkey = keycursor(-2,-2);
  329.  
  330.       i = current - topleftchoice;         /* unhighlight current choice */
  331.       if ((k = attributes[current] & 3) == 1)
  332.      k = C_PROMPT_LO;
  333.       else if (k == 3)
  334.      k = C_PROMPT_HI;
  335.       else
  336.      k = C_PROMPT_MED;
  337.       putstring(topleftrow+i/boxwidth,topleftcol+(i%boxwidth)*colwidth,
  338.         k,itemptr);
  339.  
  340.       increment = 0;
  341.       switch (curkey) {              /* deal with input key */
  342.      case ENTER:
  343.      case ENTER_2:
  344.         ret = current;
  345.         goto fs_choice_end;
  346.      case ESC:
  347.         goto fs_choice_end;
  348.      case DOWN_ARROW:
  349.      case DOWN_ARROW_2:
  350.         rev_increment = 0 - (increment = boxwidth);
  351.         break;
  352.      case UP_ARROW:
  353.      case UP_ARROW_2:
  354.         increment = 0 - (rev_increment = boxwidth);
  355.         break;
  356.      case RIGHT_ARROW:
  357.      case RIGHT_ARROW_2:
  358.         if (boxwidth == 1) break;
  359.         increment = 1; rev_increment = -1;
  360.         break;
  361.      case LEFT_ARROW:
  362.      case LEFT_ARROW_2:
  363.         if (boxwidth == 1) break;
  364.         increment = -1; rev_increment = 1;
  365.         break;
  366.      case PAGE_UP:
  367.         if (numchoices > boxitems) {
  368.            topleftchoice -= boxitems;
  369.            increment = -boxitems;
  370.            rev_increment = boxwidth;
  371.            redisplay = 1;
  372.            }
  373.         break;
  374.      case PAGE_DOWN:
  375.         if (numchoices > boxitems) {
  376.            topleftchoice += boxitems;
  377.            increment = boxitems;
  378.            rev_increment = -boxwidth;
  379.            redisplay = 1;
  380.            }
  381.         break;
  382.      case CTL_HOME:
  383.         current = -1;
  384.         increment = rev_increment = 1;
  385.         break;
  386.      case CTL_END:
  387.         current = numchoices;
  388.         increment = rev_increment = -1;
  389.         break;
  390.      default:
  391.         if (checkkey) {
  392.            if ((ret = (*checkkey)(curkey,current)) < -1 || ret > 0)
  393.           goto fs_choice_end;
  394.            if (ret == -1)
  395.           redisplay = -1;
  396.            }
  397.         ret = -1;
  398.         if (speedstring) {
  399.            i = strlen(speedstring);
  400.            if (curkey == 8 && i > 0) /* backspace */
  401.           speedstring[--i] = 0;
  402.            if (33 <= curkey && curkey <= 126 && i < 30) {
  403.           curkey = tolower(curkey);
  404.           speedstring[i] = curkey;
  405.           speedstring[++i] = 0;
  406.           }
  407.            if (i > 0) {         /* locate matching type */
  408.           current = 0;
  409.           while (current < numchoices
  410.             && (speed_match = strncasecmp(speedstring,choices[current],i)) > 0)
  411.              ++current;
  412.           if (speed_match < 0 && current > 0)  /* oops - overshot */
  413.              --current;
  414.           if (current >= numchoices) /* bumped end of list */
  415.              current = numchoices - 1;
  416.           }
  417.            }
  418.         break;
  419.      }
  420.  
  421.       if (increment) {            /* apply cursor movement */
  422.      current += increment;
  423.      if (speedstring)        /* zap speedstring */
  424.         speedstring[0] = 0;
  425.      }
  426.       while (1) {            /* adjust to a non-comment choice */
  427.      if (current < 0 || current >= numchoices)
  428.          increment = rev_increment;
  429.      else if ((attributes[current] & 256) == 0)
  430.          break;
  431.      current += increment;
  432.      }
  433.       if (topleftchoice > numchoices - boxitems)
  434.      topleftchoice = ((numchoices+boxwidth-1)/boxwidth)*boxwidth - boxitems;
  435.       if (topleftchoice < 0)
  436.      topleftchoice = 0;
  437.       while (current < topleftchoice) {
  438.      topleftchoice -= boxwidth;
  439.      redisplay = 1;
  440.      }
  441.       while (current >= topleftchoice + boxitems) {
  442.      topleftchoice += boxwidth;
  443.      redisplay = 1;
  444.      }
  445.       }
  446.  
  447. fs_choice_end:
  448.    lookatmouse = savelookatmouse;
  449.    return(ret);
  450.  
  451. }
  452.  
  453. int input_field(
  454.     int options,          /* &1 numeric, &2 integer, &4 double */
  455.     int attr,          /* display attribute */
  456.     char *fld,          /* the field itself */
  457.     int len,          /* field length (declare as 1 larger for \0) */
  458.     int row,          /* display row */
  459.     int col,          /* display column */
  460.     int (*checkkey)(int)  /* routine to check non data keys, or NULL */
  461.     )
  462. {
  463.    char savefld[81];
  464.    char buf[81];
  465.    int insert, started, offset, curkey, display;
  466.    int i, j;
  467.    int ret,savelookatmouse;
  468.    savelookatmouse = lookatmouse;
  469.    lookatmouse = 0;
  470.    ret = -1;
  471.    strcpy(savefld,fld);
  472.    insert = started = offset = 0;
  473.    display = 1;
  474.    while (1) {
  475.       strcpy(buf,fld);
  476.       i = strlen(buf);
  477.       while (i < len)
  478.      buf[i++] = ' ';
  479.       buf[len] = 0;
  480.       if (display) {                    /* display current value */
  481.      putstring(row,col,attr,buf);
  482.      display = 0;
  483.      }
  484.       curkey = keycursor(row+insert,col+offset);  /* get a keystroke */
  485.       switch (curkey) {
  486.      case ENTER:
  487.      case ENTER_2:
  488.         ret = 0;
  489.         goto inpfld_end;
  490.      case ESC:
  491.         goto inpfld_end;
  492.      case RIGHT_ARROW:
  493.      case RIGHT_ARROW_2:
  494.         if (offset < len) ++offset;
  495.         started = 1;
  496.         break;
  497.      case LEFT_ARROW:
  498.      case LEFT_ARROW_2:
  499.         if (offset > 0) --offset;
  500.         started = 1;
  501.         break;
  502.      case HOME:
  503.         offset = 0;
  504.         started = 1;
  505.         break;
  506.      case END:
  507.         offset = strlen(fld);
  508.         started = 1;
  509.         break;
  510.      case 8:
  511.      case 127:                /* backspace */
  512.         if (offset > 0) {
  513.            j = strlen(fld);
  514.            for (i = offset-1; i < j; ++i)
  515.           fld[i] = fld[i+1];
  516.            --offset;
  517.            }
  518.         started = display = 1;
  519.         break;
  520.      case DELETE:                /* delete */
  521.         j = strlen(fld);
  522.         for (i = offset; i < j; ++i)
  523.            fld[i] = fld[i+1];
  524.         started = display = 1;
  525.         break;
  526.      case 1082:                /* insert */
  527.         insert ^= 0x8000;
  528.         started = 1;
  529.         break;
  530.      case F5:
  531.         strcpy(fld,savefld);
  532.         insert = started = offset = 0;
  533.         display = 1;
  534.         break;
  535.      default:
  536.         if (curkey < 32 || curkey >= 127) {
  537.            if (checkkey && (ret = (*checkkey)(curkey)))
  538.           goto inpfld_end;
  539.            break;                     /* non alphanum char */
  540.            }
  541.         if (offset >= len) break;             /* at end of field */
  542.         if (insert && started && strlen(fld) >= len)
  543.            break;                     /* insert & full */
  544.         if ((options & 1)
  545.           && (curkey < '0' || curkey > '9')
  546.           && curkey != '+' && curkey != '-') {
  547.            if ((options & 2))
  548.           break;
  549.            /* allow scientific notation, and specials "e" and "p" */
  550.            if ( ((curkey != 'e' && curkey != 'E') || offset >= 18)
  551.          && ((curkey != 'p' && curkey != 'P') || offset != 0 )
  552.          && curkey != '.')
  553.           break;
  554.            }
  555.         if (started == 0) /* first char is data, zap field */
  556.            fld[0] = 0;
  557.         if (insert) {
  558.            j = strlen(fld);
  559.            while (j >= offset) {
  560.           fld[j+1] = fld[j];
  561.           --j;
  562.           }
  563.            }
  564.         if (offset >= strlen(fld))
  565.            fld[offset+1] = 0;
  566.         fld[offset++] = curkey;
  567.         /* if "e" or "p" in first col make number e or pi */
  568.         if ((options & 3) == 1) { /* floating point */
  569.            double tmpd;
  570.            int specialv;
  571.            char tmpfld[30];
  572.            specialv = 0;
  573.            if (*fld == 'e' || *fld == 'E') {
  574.           tmpd = exp(1.0);
  575.           specialv = 1;
  576.           }
  577.            if (*fld == 'p' || *fld == 'P') {
  578.           tmpd = atan(1.0) * 4;
  579.           specialv = 1;
  580.           }
  581.            if (specialv) {
  582.           if ((options & 4) == 0)
  583.              roundfloatd(&tmpd);
  584.           sprintf(tmpfld,"%.15g",tmpd);
  585.           tmpfld[len-1] = 0; /* safety, field should be long enough */
  586.           strcpy(fld,tmpfld);
  587.           offset = 0;
  588.           }
  589.            }
  590.         started = display = 1;
  591.      }
  592.       }
  593. inpfld_end:
  594.    lookatmouse = savelookatmouse;
  595.    return(ret);
  596. }
  597.  
  598. int field_prompt(
  599.     int options,        /* &1 numeric value, &2 integer */
  600.     char *hdg,        /* heading, \n delimited lines */
  601.     char *instr,        /* additional instructions or NULL */
  602.     char *fld,        /* the field itself */
  603.     int len,        /* field length (declare as 1 larger for \0) */
  604.     int (*checkkey)(int)   /* routine to check non data keys, or NULL */
  605.     )
  606. {
  607.    char *charptr;
  608.    int boxwidth,titlelines,titlecol,titlerow;
  609.    int promptcol;
  610.    int i,j;
  611.    char buf[81];
  612.    helptitle();               /* clear screen, display title */
  613.    setattr(1,0,C_PROMPT_BKGRD,24*80);      /* init rest to background */
  614.    charptr = hdg;              /* count title lines, find widest */
  615.    i = boxwidth = 0;
  616.    titlelines = 1;
  617.    while (*charptr) {
  618.       if (*(charptr++) == '\n') {
  619.      ++titlelines;
  620.      i = -1;
  621.      }
  622.       if (++i > boxwidth)
  623.      boxwidth = i;
  624.       }
  625.    if (len > boxwidth)
  626.       boxwidth = len;
  627.    i = titlelines + 4;              /* total rows in box */
  628.    titlerow = (25 - i) / 2;          /* top row of it all when centered */
  629.    titlerow -= titlerow / 4;          /* higher is better if lots extra */
  630.    titlecol = (80 - boxwidth) / 2;      /* center the box */
  631.    titlecol -= (90 - boxwidth) / 20;
  632.    promptcol = titlecol - (boxwidth-len)/2;
  633.    j = titlecol;              /* add margin at each side of box */
  634.    if ((i = (82-boxwidth)/4) > 3)
  635.       i = 3;
  636.    j -= i;
  637.    boxwidth += i * 2;
  638.    for (i = -1; i < titlelines+3; ++i)      /* draw empty box */
  639.       setattr(titlerow+i,j,C_PROMPT_LO,boxwidth);
  640.    textcbase = titlecol;          /* set left margin for putstring */
  641.    putstring(titlerow,0,C_PROMPT_HI,hdg); /* display heading */
  642.    textcbase = 0;
  643.    i = titlerow + titlelines + 4;
  644.    if (instr) {               /* display caller's instructions */
  645.       charptr = instr;
  646.       j = -1;
  647.       while ((buf[++j] = *(charptr++)))
  648.      if (buf[j] == '\n') {
  649.         buf[j] = 0;
  650.         putstringcenter(i++,0,80,C_PROMPT_BKGRD,buf);
  651.         j = -1;
  652.         }
  653.       putstringcenter(i,0,80,C_PROMPT_BKGRD,buf);
  654.       }
  655.    else                   /* default instructions */
  656.       putstringcenter(i,0,80,C_PROMPT_BKGRD,
  657.           "Press ENTER when finished (or ESCAPE to back out)");
  658.    return(input_field(options,C_PROMPT_INPUT,fld,len,
  659.               titlerow+titlelines+1,promptcol,checkkey));
  660. }
  661.  
  662. void helptitle()
  663. {
  664.    char msg[80],buf[10];
  665.    setclear(); /* clear the screen */
  666.    sprintf(msg,"WINFRACT  Version %d.%01d",win_release/100,
  667.        (win_release%100)/10);
  668.    if (win_release%10) {
  669.       sprintf(buf,"%01d",win_release%10);
  670.       strcat(msg,buf);
  671.       }
  672.    putstringcenter(0,0,80,C_TITLE,msg);
  673. /* uncomment next for production executable: */
  674. /* return; */
  675.    putstring(0,2,C_TITLE_DEV,"Development Version"); 
  676. /* putstring(0,2,C_TITLE_DEV,"'Public-Beta' Release"); */
  677. /* replace above by next after creating production release, for release source */
  678. /* putstring(0,3,C_TITLE_DEV, "Customized Version"); */
  679.    putstring(0,53,C_TITLE_DEV,"Not for Public Release");
  680. }
  681.  
  682. static int screenctr=-1;
  683. #define MAXSCREENS 3
  684. static unsigned char far *savescreen[MAXSCREENS];
  685. static int saverc[MAXSCREENS+1];
  686. static FILE *savescf=NULL;
  687. static char scsvfile[]="fractscr.tmp";
  688.  
  689. void stackscreen()
  690. {
  691.    extern unsigned char far wintext_chars[25][80];
  692.    extern unsigned char far wintext_attrs[25][80];
  693.    int savebytes;
  694.    int i;
  695.    unsigned char far *ptr;
  696.    char buf[100];
  697.    saverc[screenctr+1] = textrow*80 + textcol;
  698.    if (++screenctr) { /* already have some stacked */
  699.      static char far msg[]={"stackscreen overflow"};
  700.       if ((i = screenctr - 1) >= MAXSCREENS) { /* bug, missing unstack? */
  701.      stopmsg(1,msg);
  702.      exit(1);
  703.      }
  704.       savebytes = 25*80;
  705.       if ((ptr = savescreen[i] = farmemalloc((long)(2*savebytes)))) {
  706.      far_memcpy(ptr,wintext_chars,savebytes);
  707.      far_memcpy(ptr+savebytes,wintext_attrs,savebytes);
  708.      }
  709.       else {
  710.         static char far msg[]={"insufficient memory, aborting"};
  711. fileproblem:   stopmsg(1,msg);
  712.            exit(1);
  713.      }
  714.       setclear();
  715.       }
  716.    else
  717.       setfortext();
  718. }
  719.  
  720. void unstackscreen()
  721. {
  722.    extern unsigned char far wintext_chars[25][80];
  723.    extern unsigned char far wintext_attrs[25][80];
  724.    int savebytes;
  725.    unsigned char far *ptr;
  726.    textrow = saverc[screenctr] / 80;
  727.    textcol = saverc[screenctr] % 80;
  728.    if (--screenctr >= 0) { /* unstack */
  729.       savebytes = 25*80;
  730.       if ((ptr = savescreen[screenctr])) {
  731.      far_memcpy(wintext_chars,ptr,savebytes);
  732.      far_memcpy(wintext_attrs,ptr+savebytes,savebytes);
  733.          wintext_paintscreen(0,80,0,25);
  734.      farmemfree(ptr);
  735.      }
  736.       }
  737.    else
  738.       setforgraphics();
  739.    movecursor(-1,-1);
  740. }
  741.  
  742. void discardscreen()
  743. {
  744.    if (--screenctr >= 0) { /* unstack */
  745.       if (savescreen[screenctr])
  746.      farmemfree(savescreen[screenctr]);
  747.       }
  748.    else
  749.       discardgraphics();
  750. }
  751.  
  752. int discardgraphics()
  753. {
  754. }
  755.  
  756. setfortext()
  757. {
  758. wintext_texton();
  759. }
  760.  
  761. setforgraphics()
  762. {
  763. wintext_textoff();
  764. }
  765.  
  766. setclear()
  767. {
  768. extern int far wintext_buffer_init;
  769.  
  770.     wintext_buffer_init = 0;
  771.     wintext_paintscreen(0,80,0,25);
  772. }
  773.  
  774. int putstringcenter(int row, int col, int width, int attr, char far *msg)
  775. {
  776.    char buf[81];
  777.    int i,j,k;
  778.    i = 0;
  779.    while (msg[i]) ++i; /* strlen for a far */
  780.    if (i == 0) return(-1);
  781.    j = (width - i) / 2;
  782.    j -= (width + 10 - i) / 20; /* when wide a bit left of center looks better */
  783.    memset(buf,' ',width);
  784.    buf[width] = 0;
  785.    i = 0;
  786.    k = j;
  787.    while (msg[i]) buf[k++] = msg[i++]; /* strcpy for a far */
  788.    putstring(row,col,attr,buf);
  789.    return j;
  790. }
  791.  
  792. void putstring(int row, int col, int attr, unsigned char far *buf)
  793. {
  794.     extern unsigned char far wintext_chars[25][80];
  795.     extern unsigned char far wintext_attrs[25][80];
  796.     int i, j, k, maxrow, maxcol;
  797.     char xc, xa;
  798.  
  799.     if (row == -1) row = textrow;
  800.     if (col == -1) col = textcol;
  801.  
  802.     j = maxrow = row;
  803.     k = maxcol = col-1;
  804.  
  805.     for (i = 0; (xc = buf[i]) != 0; i++) {
  806.         if (xc == 13 || xc == 10) {
  807.             j++;
  808.             k = -1;
  809.             }
  810.         else {
  811.             if ((++k) + textcbase >= 80) {
  812.                 j++;
  813.                 k = 0;
  814.                 }
  815.             if (j+textrbase >= 25) j = 24-textrbase;
  816.             if (k+textcbase >= 80) k = 79-textcbase;
  817.             if (maxrow < j) maxrow = j;
  818.             if (maxcol < k) maxcol = k;
  819.             xa = (attr & 0x0ff);
  820.             wintext_chars[j+textrbase][k+textcbase] = xc;
  821.             wintext_attrs[j+textrbase][k+textcbase] = xa;
  822.             }
  823.         }
  824.     if (i > 0) {
  825.         textrow = j;
  826.         textcol = k + 1;
  827.         wintext_paintscreen(
  828.             col+textcbase, maxcol+textcbase,
  829.             row+textrbase, maxrow+textrbase);
  830.         }
  831. }
  832.  
  833. void setattr(int row, int col, int attr, int count)
  834. {
  835. extern unsigned char far wintext_attrs[25][80];
  836.     int i, j, k, maxrow, maxcol;
  837.     char xc, xa;
  838.  
  839.     j = maxrow = row;
  840.     k = maxcol = col-1;
  841.  
  842.     xa = (attr & 0x0ff);
  843.     for (i = 0; i < count; i++) {
  844.         if ((++k + textcbase) >= 80) {
  845.             j++;
  846.             k = 0;
  847.             }
  848.         if (j+textrbase >= 25) j = 24-textrbase;
  849.         if (k+textcbase >= 80) k = 79-textcbase;
  850.         if (maxrow < j) maxrow = j;
  851.         if (maxcol < k) maxcol = k;
  852.         wintext_attrs[j+textrbase][k+textcbase] = xa;
  853.         }
  854.     if (count > 0)
  855.         wintext_paintscreen(
  856.             col+textcbase, maxcol+textcbase,
  857.             row+textrbase, maxrow+textrbase);
  858. }
  859.  
  860. void movecursor(int row, int col)
  861. {
  862. int cursor_type;
  863.  
  864.     cursor_type = -1;
  865.     if (row >= 25 || col >= 80) {
  866.         row=1;
  867.         col=1;
  868.         cursor_type = 0;
  869.         }
  870.     if (row >= 0)
  871.         textrow = row;
  872.     if (col >= 0)
  873.         textcol = col;
  874.     wintext_cursor(col, row, -1);
  875. }
  876.  
  877. int keycursor(int row, int col)
  878. {
  879. int i, cursor_style;
  880.  
  881. if (row == -2 && col == -2) 
  882.     return(fractint_getkeypress(1));
  883.  
  884. if (row == -1)
  885.     row = textrow;
  886. if (col == -1)
  887.     col = textcol;
  888.  
  889. cursor_style = 1;
  890. if (row < 0) {
  891.     cursor_style = 2;
  892.     row = row & 0x7fff;
  893.     }
  894.  
  895. i = fractint_getkeypress(0);
  896. if (i == 0)
  897.     wintext_cursor(col, row, cursor_style);
  898. i = fractint_getkeypress(1);
  899. wintext_cursor(col, row, 0);
  900.  
  901. return(i);
  902.  
  903. }
  904.  
  905. /* get a "fractint-style" keystroke, with "help" sensitivity */
  906. int fractint_getkeypress(int option)
  907. {
  908. int i;
  909.  
  910. restart:
  911.     i = wintext_getkeypress(option);
  912.     if (i == 0)
  913.         return(i);
  914.     /* "fractint-i-size" the keystroke */
  915.     if (i != 0 && (i & 255) == 0)  /* function key? */
  916.         i = (i >> 8) + 1000;
  917.     else
  918.         i = (i & 255);
  919.     if (i == F1) {    /* F1  - bring up Windows-style help */
  920.         if (option == 0) wintext_getkeypress(1);
  921.         winfract_help();
  922.         goto restart;
  923.         }
  924.     if (i == (F1+35)) {  /* Control-F1  - bring up Fractint-style help */
  925.         if (option == 0) wintext_getkeypress(1);
  926.         if (! in_fractint_help) {
  927.             fractint_help();
  928.             goto restart;
  929.             }
  930.         }
  931.  
  932. return(i);
  933.  
  934. }
  935.  
  936. int getakeynohelp() {
  937. return(fractint_getkeypress(1));
  938. }
  939.  
  940. int strncasecmp(char *s,char *t,int ct)
  941. {
  942.    for(; (tolower(*s) == tolower(*t)) && --ct ; s++,t++)
  943.       if(*s == '\0')
  944.      return(0);
  945.    return(tolower(*s) - tolower(*t));
  946. }
  947.  
  948. extern char temp1[];
  949. extern    int    colors;
  950. extern unsigned char dacbox[256][3];
  951. extern unsigned char olddacbox[256][3];
  952. extern int colorstate;
  953. extern char    colorfile[];
  954. char mapmask[13] = {"*.map"};
  955.  
  956. void save_palette()
  957. {
  958.    FILE *dacfile;
  959.    int i,oldhelpmode;
  960.    oldhelpmode = helpmode;
  961.    stackscreen();
  962.    temp1[0] = 0;
  963.    helpmode = HELPCOLORMAP;
  964.    i = field_prompt(0,"Name of map file to write",NULL,temp1,60,NULL);
  965.    unstackscreen();
  966.    if (i != -1 && temp1[0]) {
  967.       if (strchr(temp1,'.') == NULL)
  968.      strcat(temp1,".map");
  969.       dacfile = fopen(temp1,"w");
  970.       if (dacfile == NULL)
  971.      buzzer(2);
  972.       else {
  973.      for (i = 0; i < colors; i++)
  974.         fprintf(dacfile, "%3d %3d %3d\n",
  975.             dacbox[i][0] << 2,
  976.             dacbox[i][1] << 2,
  977.             dacbox[i][2] << 2);
  978.      memcpy(olddacbox,dacbox,256*3);
  979.      colorstate = 2;
  980.      strcpy(colorfile,temp1);
  981.      }
  982.       fclose(dacfile);
  983.       }
  984.    helpmode = oldhelpmode;
  985. }
  986.  
  987.  
  988. void load_palette(void)
  989. {
  990.    int i,oldhelpmode;
  991.    char filename[80];
  992.    oldhelpmode = helpmode;
  993.    strcpy(filename,colorfile);
  994.    stackscreen();
  995.    helpmode = HELPCOLORMAP;
  996.    i = getafilename("Select a MAP File",mapmask,filename);
  997.    unstackscreen();
  998.    if (i >= 0)
  999.       if (ValidateLuts(filename) == 0) {
  1000.      memcpy(olddacbox,dacbox,256*3);
  1001.      colorstate = 2;
  1002.      strcpy(colorfile,filename);
  1003.      }
  1004.    helpmode = oldhelpmode;
  1005. }
  1006.  
  1007. void fractint_help()
  1008. {
  1009.    int i,oldhelpmode;
  1010.  
  1011.    in_fractint_help = 1;
  1012.    oldhelpmode = helpmode;
  1013.    helpmode = HELP_INDEX;
  1014.    help(0);
  1015.    in_fractint_help = 0;
  1016.    helpmode = oldhelpmode;
  1017. }
  1018.  
  1019. extern FILE *parmfile;
  1020.  
  1021. int win_make_batch_file()
  1022. {
  1023.    int i,numparms;
  1024.    int gotinfile;
  1025.    char outname[81],buf[256],buf2[128];
  1026.    FILE *infile;
  1027.    char colorspec[14];
  1028.    int maxcolor;
  1029.    char *sptr,*sptr2;
  1030.    extern char CommandFile[];
  1031.    extern char CommandName[];
  1032.    extern char far CommandComment1[];
  1033.    extern char far CommandComment2[];
  1034.    extern int  colorstate;
  1035.    extern int win_temp1, win_temp2;
  1036.    extern char colorfile[];
  1037.    extern int  mapset;
  1038.    extern char MAP_name[];
  1039.  
  1040. #ifdef WINFRACT
  1041. extern char suffix[4096];
  1042. #else
  1043. extern char dstack[4096];
  1044. #endif
  1045.    extern char boxx[8192];
  1046.    extern char s_cantopen[];
  1047.    extern char s_cantwrite[];
  1048.    extern char s_cantcreate[];
  1049.    extern char s_cantunderstand[];
  1050.    extern char s_cantfind[];
  1051.  
  1052.       if (strchr(CommandFile,'.') == NULL)
  1053.          strcat(CommandFile,".par"); /* default extension .par */
  1054.       if (win_temp2 > 0 && win_temp2 <= 256)
  1055.         maxcolor = win_temp2;
  1056.       strcpy(colorspec,"n");
  1057.       if (win_temp1 == 0) {      /* default colors */
  1058.      }
  1059.       else if (win_temp1 == 2) { /* colors match colorfile */
  1060.      colorspec[0] = '@';
  1061.      sptr = colorfile;
  1062.      }
  1063.       else              /* colors match no .map that we know of */
  1064.      colorspec[0] = 'y';
  1065.       if (colorspec[0] == '@') {
  1066.      if ((sptr2 = strrchr(sptr,'\\'))) sptr = sptr2 + 1;
  1067.      if ((sptr2 = strrchr(sptr,':')))  sptr = sptr2 + 1;
  1068.      strncpy(&colorspec[1],sptr,12);
  1069.      colorspec[13] = 0;
  1070.      }
  1071.  
  1072.       strcpy(outname,CommandFile);
  1073.       gotinfile = 0;
  1074.       if (access(CommandFile,0) == 0) { /* file exists */
  1075.      gotinfile = 1;
  1076.      if (access(CommandFile,6)) {
  1077.         sprintf(buf,s_cantwrite,CommandFile);
  1078.         stopmsg(0,buf);
  1079.         return(0);
  1080.         }
  1081.      i = strlen(outname);
  1082.      while (--i >= 0 && outname[i] != '\\')
  1083.      outname[i] = 0;
  1084.      strcat(outname,"fractint.tmp");
  1085.      infile = fopen(CommandFile,"rt");
  1086.      setvbuf(infile,suffix,_IOFBF,4096); /* improves speed */
  1087.      }
  1088.       if ((parmfile = fopen(outname,"wt")) == NULL) {
  1089.      sprintf(buf,s_cantcreate,outname);
  1090.      stopmsg(0,buf);
  1091.      if (gotinfile) fclose(infile);
  1092.      return(0);
  1093.      }
  1094.  
  1095.       if (gotinfile) {
  1096.      while (file_gets(buf,255,infile) >= 0) {
  1097.         if (strchr(buf,'{')                    /* entry heading? */
  1098.           && sscanf(buf," %40[^ \t({]",buf2)
  1099.           && stricmp(buf2,CommandName) == 0) { /* entry with same name */
  1100.            sprintf(buf2,"File already has an entry named %s\n\
  1101. Continue to replace it, Cancel to back out",CommandName);
  1102.            if (stopmsg(18,buf2) < 0) {        /* cancel */
  1103.           fclose(infile);
  1104.           fclose(parmfile);
  1105.           unlink(outname);
  1106.           return(0);
  1107.           }
  1108.            while (strchr(buf,'}') == NULL
  1109.          && file_gets(buf,255,infile) > 0 ) { } /* skip to end of set */
  1110.            break;
  1111.            }
  1112.         fputs(buf,parmfile);
  1113.         fputc('\n',parmfile);
  1114.         }
  1115.      }
  1116.  
  1117.       fprintf(parmfile,"%-19s{",CommandName);
  1118.       if (CommandComment1[0]) fprintf(parmfile," ; %Fs",CommandComment1);
  1119.       fputc('\n',parmfile);
  1120.       if (CommandComment2[0])
  1121.      fprintf(parmfile,"                     ; %Fs\n",CommandComment2);
  1122.       write_batch_parms(parmfile,colorspec,maxcolor); /* write the parameters */
  1123.       fprintf(parmfile,"  }\n\n");
  1124.  
  1125.       if (gotinfile) {    /* copy the rest of the file */
  1126.      while ((i = file_gets(buf,255,infile)) == 0) { } /* skip blanks */
  1127.      while (i >= 0) {
  1128.         fputs(buf,parmfile);
  1129.         fputc('\n',parmfile);
  1130.         i = file_gets(buf,255,infile);
  1131.         }
  1132.      fclose(infile);
  1133.      }
  1134.       fclose(parmfile);
  1135.       if (gotinfile) {    /* replace the original file with the new */
  1136.      unlink(CommandFile);          /* success assumed on these lines       */
  1137.      rename(outname,CommandFile); /* since we checked earlier with access */
  1138.      }
  1139.  
  1140. return(1);
  1141. }
  1142.