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

  1. /*
  2.  * editpal.c
  3.  *
  4.  * Edits VGA 256-color palettes.
  5.  *
  6.  * This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
  7.  *
  8.  *
  9.  * Key to initials:
  10.  *
  11.  *    EAN - Ethan Nagel [70022,2552]
  12.  *
  13.  *    JJB - Juan J. Buhler [jbuhler@gidef.edu.ar]
  14.  *
  15.  *    TIW - Tim Wegner
  16.  *
  17.  * Revision History:
  18.  *
  19.  *   10-22-90 EAN     Initial release.
  20.  *
  21.  *   10-23-90 EAN     "Discovered" get_line/put_line functions, integrated
  22.  *                them in (instead of only getcolor/putcolor). Much
  23.  *                faster!
  24.  *              Redesigned color editors (now at top of palette) and
  25.  *                re-assigned some keys.
  26.  *              Added (A)uto option.
  27.  *              Fixed memory allocation problem.  Now uses shared
  28.  *                FRACTINT data area (strlocn).  Uses 6 bytes DS.
  29.  *
  30.  *   10-27-90 EAN     Added save to memory option - will save screen image to
  31.  *                memory, if enough mem avail.  (disk otherwise).
  32.  *              Added s(T)ripe mode - works like (S)hade except only
  33.  *                changes every n'th entry.
  34.  *              Added temporary palette save/restore.  (Can work like
  35.  *                an undo feature.)  Thanks to Pieter Branderhorst for
  36.  *                idea.
  37.  *
  38.  *   10-28-90 EAN     The (H)ide function now makes the palette invisible,
  39.  *                while allowing any other operations (except '\\' -
  40.  *                move/resize) to continue.
  41.  *
  42.  *   10-29-90 PB (in EAN's absence, <grin>)
  43.  *              Change 'c' to 'd' and 's' to '=' for below.
  44.  *              Add 'l' to load palette from .map, 's' to store .map.
  45.  *              Add 'c' to invoke color cycling.
  46.  *              Change cursor to use whatever colors it can from
  47.  *              the palette (not fixed 0 and 255).
  48.  *              Restore colors 0 and 255 to real values whenever
  49.  *              palette is not on display.
  50.  *              Rotate 255 colors instead of 254.
  51.  *              Reduce cursor blink rate.
  52.  *
  53.  *   11-15-90 EAN     Minor "bug" fixes.  Continuous rotation now at a fixed
  54.  *                rate - once every timer tick (18.2 sec);  Blanks out
  55.  *                color samples when rotating; Editors no longer rotate
  56.  *                with the colors in color rotation mode;  Eliminated
  57.  *                (Z)oom mode; other minor fixes.
  58.  *
  59.  *   01-05-91 PB      Add 'w' function to convert to greyscale.
  60.  *
  61.  *   01-16-91 PB      Change rotate function to use new cyclerange stuff.
  62.  *
  63.  *   01-29-91 EAN     Made all colors editable.  The two reserved colors are
  64.  *             X'ed out.  They can be edited but the color is not
  65.  *             visible.  (There is an X over the sample instead.)
  66.  *              Changed default reserved colors to 254 & 255.
  67.  *              Added 'v' command to set the reserved colors to those
  68.  *             under the editors.
  69.  *              Added 'o' command to set the rotate range to between
  70.  *                the two editors.
  71.  *              Modified 'w' function:
  72.  *                uses internal function to do conversion (not BIOS)
  73.  *                will convert only current color if in 'x' mode or
  74.  *              range between editors in 'y' mode or entire palette
  75.  *              if in "normal" mode.
  76.  *
  77.  *   02-08-91 EAN     Improved 16 color support.  In 16 color mode, colors
  78.  *                16-255 have a dot over them and are editable but not
  79.  *                visible (like the two reserved colors).
  80.  *
  81.  *   09-08-91 SWT     Added 'n' command to make a negative color palette:
  82.  *                      will convert only current color if in 'x' mode or
  83.  *                      range between editors in 'y' mode or entire palette
  84.  *                      if in "normal" mode.
  85.  *
  86.  *   03-03-92 JJB     Added '!', '@' and '#' commands to swap RG, GB and
  87.  *                      RB columns (sorry, I didn't find better keys)
  88.  *
  89.  *  10-03-92 TIW      Minor changes for Jiim support, primarily changing
  90.  *                    variables from static to global.
  91.  *
  92.  *   2-11-93 EAN      Added full Undo ('U' key) and Redo ('E' key)
  93.  *                      capability.  Works pretty much as you'd expect
  94.  *                      it to.
  95.  *
  96.  *    3-6-93 EAN      Modified "freestyle" mode, written by RB, to integrate
  97.  *                      into palette editor more completely and work with
  98.  *                      undo logic.
  99.  *                    Added status area under the "fractint" message to
  100.  *                      display current state of editor.  A = Auto mode,
  101.  *                      X, Y = exclusion modes, F = freesyle mode, T = stripe
  102.  *                      mode is waiting for #.
  103.  *
  104.  */
  105.  
  106.  
  107.  
  108. #ifdef DEBUG_UNDO
  109. #include "mdisp.h"   /* EAN 930211 *** Debug Only *** */
  110. #endif
  111.  
  112.  
  113. #include <stdio.h>
  114. #include <stdlib.h>
  115. #include <string.h>
  116. #ifndef XFRACT
  117. #include <stdarg.h>
  118. #include <dos.h>     /* for FP_SEG & FP_OFF */
  119. #else
  120. #include <varargs.h>
  121. #endif
  122. #include <math.h>
  123.  
  124. #ifdef __TURBOC__
  125. #   include <mem.h>   /* to get mem...() declarations */
  126. #endif
  127.  
  128. #include "fractint.h" /* for overlay stuff */
  129. #include "prototyp.h"
  130.  
  131.  
  132. /*
  133.  * misc. #defines
  134.  */
  135.  
  136. #define FONT_DEPTH        8      /* font size */
  137.  
  138. #define CSIZE_MIN        8      /* csize cannot be smaller than this */
  139.  
  140. #define CURSOR_SIZE        5      /* length of one side of the x-hair cursor */
  141.  
  142. #ifndef XFRACT
  143. #define CURSOR_BLINK_RATE   3      /* timer ticks between cursor blinks */
  144. #else
  145. #define CURSOR_BLINK_RATE   300      /* timer ticks between cursor blinks */
  146. #endif
  147.  
  148. #define FAR_RESERVE     8192L      /* amount of far mem we will leave avail. */
  149.  
  150. #define MAX_WIDTH     1024      /* palette editor cannot be wider than this */
  151.  
  152. char scrnfile[] = "FRACTINT.$$1";  /* file where screen portion is */
  153.                    /* stored */
  154. char undofile[] = "FRACTINT.$$2";  /* file where undo list is stored */
  155. #define TITLE   "FRACTINT"
  156.  
  157. #define TITLE_LEN (8)
  158.  
  159.  
  160. #define newx(size)     mem_alloc(size)
  161. #define new(class)     (class *)(mem_alloc(sizeof(class)))
  162. #define delete(block)
  163.  
  164. #ifdef XFRACT
  165. int editpal_cursor = 0;
  166. #endif
  167.  
  168.  
  169. /*
  170.  * Stuff from fractint
  171.  */
  172.  
  173. extern BYTE dacbox[256][3];     /* DAC spindac() will use         */
  174. extern int         sxdots;         /* width of physical screen         */
  175. extern int         sydots;         /* depth of physical screen         */
  176. extern int         sxoffs;         /* start of logical screen         */
  177. extern int         syoffs;         /* start of logical screen         */
  178. extern int         lookatmouse;     /* mouse mode for getakey(), etc    */
  179. extern int         strlocn[];      /* 10K buffer to store classes in   */
  180. extern int         colors;         /* # colors avail.             */
  181. extern int         color_bright;     /* brightest color in palette         */
  182. extern int         color_dark;     /* darkest color in palette         */
  183. extern int         color_medium;     /* nearest to medbright gray color  */
  184. extern int         rotate_lo, rotate_hi;
  185. extern int         debugflag;
  186. int using_jiim = 0;
  187.  
  188. /*
  189.  * basic data types
  190.  */
  191.  
  192.  
  193. typedef struct
  194.    {
  195.    BYTE red,
  196.          green,
  197.          blue;
  198.    } PALENTRY;
  199.  
  200.  
  201.  
  202. /*
  203.  * static data
  204.  */
  205.  
  206.  
  207. static BYTE far *font8x8 = NULL;
  208. BYTE     *line_buff;   /* must be alloced!!! */
  209. static BYTE      fg_color,
  210.               bg_color;
  211. static BOOLEAN          reserve_colors;
  212. static BOOLEAN          inverse;
  213.  
  214. static float    gamma_val = 1.0;
  215.  
  216.  
  217. /*
  218.  * Interface to FRACTINT's graphics stuff
  219.  */
  220.  
  221.  
  222. static void setpal(int pal, int r, int g, int b)
  223.    {
  224.    dacbox[pal][0] = r;
  225.    dacbox[pal][1] = g;
  226.    dacbox[pal][2] = b;
  227.    spindac(0,1);
  228.    }
  229.  
  230.  
  231. static void setpalrange(int first, int how_many, PALENTRY *pal)
  232.    {
  233.    memmove(dacbox+first, pal, how_many*3);
  234.    spindac(0,1);
  235.    }
  236.  
  237.  
  238. static void getpalrange(int first, int how_many, PALENTRY *pal)
  239.    {
  240.    memmove(pal, dacbox+first, how_many*3);
  241.    }
  242.  
  243.  
  244. static void rotatepal(PALENTRY *pal, int dir, int lo, int hi)
  245.    {             /* rotate in either direction */
  246.    PALENTRY hold;
  247.    int        size;
  248.  
  249.    size  = 1 + (hi-lo);
  250.  
  251.    if ( dir > 0 )
  252.       {
  253.       while ( dir-- > 0 )
  254.          {
  255.          memmove(&hold, &pal[hi],  3);
  256.          memmove(&pal[lo+1], &pal[lo], 3*(size-1));
  257.          memmove(&pal[lo], &hold, 3);
  258.          }
  259.       }
  260.  
  261.    else if ( dir < 0 )
  262.       {
  263.       while ( dir++ < 0 )
  264.          {
  265.          memmove(&hold, &pal[lo], 3);
  266.          memmove(&pal[lo], &pal[lo+1], 3*(size-1));
  267.          memmove(&pal[hi], &hold,  3);
  268.          }
  269.       }
  270.    }
  271.  
  272.  
  273. static void clip_put_line(int row, int start, int stop, BYTE *pixels)
  274.    {
  275.    if ( row < 0 || row >= sydots || start > sxdots || stop < 0 )
  276.       return ;
  277.  
  278.    if ( start < 0 )
  279.       {
  280.       pixels += -start;
  281.       start = 0;
  282.       }
  283.  
  284.    if ( stop >= sxdots )
  285.       stop = sxdots - 1;
  286.  
  287.    if ( start > stop )
  288.       return ;
  289.  
  290.    put_line(row, start, stop, pixels);
  291.    }
  292.  
  293.  
  294. static void clip_get_line(int row, int start, int stop, BYTE *pixels)
  295.    {
  296.    if ( row < 0 || row >= sydots || start > sxdots || stop < 0 )
  297.       return ;
  298.  
  299.    if ( start < 0 )
  300.       {
  301.       pixels += -start;
  302.       start = 0;
  303.       }
  304.  
  305.    if ( stop >= sxdots )
  306.       stop = sxdots - 1;
  307.  
  308.    if ( start > stop )
  309.       return ;
  310.  
  311.    get_line(row, start, stop, pixels);
  312.    }
  313.  
  314.  
  315. void clip_putcolor(int x, int y, int color)
  316.    {
  317.    if ( x < 0 || y < 0 || x >= sxdots || y >= sydots )
  318.       return ;
  319.  
  320.    putcolor(x, y, color);
  321.    }
  322.  
  323.  
  324. int clip_getcolor(int x, int y)
  325.    {
  326.    if ( x < 0 || y < 0 || x >= sxdots || y >= sydots )
  327.       return (0);
  328.  
  329.    return ( getcolor(x, y) );
  330.    }
  331.  
  332.  
  333. void hline(int x, int y, int width, int color)
  334.    {
  335.    memset(line_buff, color, width);
  336.    clip_put_line(y, x, x+width-1, line_buff);
  337.    }
  338.  
  339.  
  340. void vline(int x, int y, int depth, int color)
  341.    {
  342.    while (depth-- > 0)
  343.       clip_putcolor(x, y++, color);
  344.    }
  345.  
  346.  
  347. void getrow(int x, int y, int width, char *buff)
  348.    {
  349.    clip_get_line(y, x, x+width-1, (BYTE *)buff);
  350.    }
  351.  
  352.  
  353. void putrow(int x, int y, int width, char *buff)
  354.    {
  355.    clip_put_line(y, x, x+width-1, (BYTE *)buff);
  356.    }
  357.  
  358.  
  359. static void vgetrow(int x, int y, int depth, char *buff)
  360.    {
  361.    while (depth-- > 0)
  362.       *buff++ = clip_getcolor(x, y++);
  363.    }
  364.  
  365.  
  366. static void vputrow(int x, int y, int depth, char *buff)
  367.    {
  368.    while (depth-- > 0)
  369.       clip_putcolor(x, y++, (BYTE)(*buff++));
  370.    }
  371.  
  372.  
  373. static void fillrect(int x, int y, int width, int depth, int color)
  374.    {
  375.    while (depth-- > 0)
  376.       hline(x, y++, width, color);
  377.    }
  378.  
  379.  
  380. static void rect(int x, int y, int width, int depth, int color)
  381.    {
  382.    hline(x, y, width, color);
  383.    hline(x, y+depth-1, width, color);
  384.  
  385.    vline(x, y, depth, color);
  386.    vline(x+width-1, y, depth, color);
  387.    }
  388.  
  389.  
  390. void displayc(int x, int y, int fg, int bg, int ch)
  391.    {
  392.    int              xc, yc;
  393.    BYTE      t;
  394.    BYTE far *ptr;
  395.  
  396.    if( font8x8 == NULL)
  397.       if ( (font8x8 = findfont(0)) == NULL )
  398.          return ;
  399.  
  400.    ptr = ((BYTE far *)font8x8) + ch*FONT_DEPTH;
  401.  
  402.    for (yc=0; yc<FONT_DEPTH; yc++, y++, ++ptr)
  403.       {
  404.       for (xc=0, t= *ptr; xc<8; xc++, t<<=1)
  405.      line_buff[xc] = (t&0x80) ? (unsigned)fg : (unsigned)bg;
  406.       putrow(x, y, 8, (char *)line_buff);
  407.       }
  408.    }
  409.  
  410.  
  411. #ifndef XFRACT
  412. static void displayf(int x, int y, int fg, int bg, char *format, ...)
  413. #else
  414. static void displayf(va_alist)
  415. va_dcl
  416. #endif
  417.    {
  418.    char buff[81];
  419.    int  ctr;
  420.  
  421.    va_list arg_list;
  422.  
  423. #ifndef XFRACT
  424.    va_start(arg_list, format);
  425. #else
  426.    int x,y,fg,bg;
  427.    char *format;
  428.  
  429.    va_start(arg_list);
  430.    x = va_arg(arg_list,int);
  431.    y = va_arg(arg_list,int);
  432.    fg = va_arg(arg_list,int);
  433.    bg = va_arg(arg_list,int);
  434.    format = va_arg(arg_list,char *);
  435. #endif
  436.    vsprintf(buff, format, arg_list);
  437.    va_end(arg_list);
  438.  
  439.    for(ctr=0; buff[ctr]!='\0'; ctr++, x+=8)
  440.       displayc(x, y, fg, bg, buff[ctr]);
  441.    }
  442.  
  443.  
  444. /*
  445.  * create smooth shades between two colors
  446.  */
  447.  
  448.  
  449. static void mkpalrange(PALENTRY *p1, PALENTRY *p2, PALENTRY pal[], int num, int skip)
  450.    {
  451.    int      curr;
  452.    double rm = (double)((int) p2->red   - (int) p1->red  ) / num,
  453.       gm = (double)((int) p2->green - (int) p1->green) / num,
  454.       bm = (double)((int) p2->blue  - (int) p1->blue ) / num;
  455.  
  456.    for (curr=0; curr<num; curr+=skip)
  457.       {
  458.       if (gamma_val == 1)
  459.           {
  460.       pal[curr].red   = (p1->red   == p2->red  ) ? p1->red   :
  461.           (int) p1->red   + (int) ( rm * curr );
  462.       pal[curr].green = (p1->green == p2->green) ? p1->green :
  463.           (int) p1->green + (int) ( gm * curr );
  464.       pal[curr].blue  = (p1->blue  == p2->blue ) ? p1->blue  :
  465.           (int) p1->blue  + (int) ( bm * curr );
  466.       }
  467.       else
  468.       {
  469.       pal[curr].red   = (p1->red   == p2->red  ) ? p1->red   :
  470.           (int) p1->red   + pow(curr/(double)(num-1),gamma_val)*num*rm;
  471.       pal[curr].green = (p1->green == p2->green) ? p1->green :
  472.           (int) p1->green + pow(curr/(double)(num-1),gamma_val)*num*gm;
  473.       pal[curr].blue  = (p1->blue  == p2->blue ) ? p1->blue  :
  474.           (int) p1->blue  + pow(curr/(double)(num-1),gamma_val)*num*bm;
  475.       }
  476.       }
  477.    }
  478.  
  479.  
  480.  
  481. /*  Swap RG GB & RB columns */
  482.  
  483. static void rotcolrg(PALENTRY pal[], int num)
  484.    {
  485.    int      curr;
  486.    int    dummy;
  487.  
  488.     for (curr=0; curr<=num; curr++)
  489.       {
  490.       dummy = pal[curr].red;
  491.       pal[curr].red = pal[curr].green;
  492.       pal[curr].green = dummy;
  493.       }
  494.    }
  495.  
  496.  
  497. static void rotcolgb(PALENTRY pal[], int num)
  498.    {
  499.    int      curr;
  500.    int    dummy;
  501.  
  502.     for (curr=0; curr<=num; curr++)
  503.       {
  504.       dummy = pal[curr].green;
  505.       pal[curr].green = pal[curr].blue;
  506.       pal[curr].blue = dummy;
  507.       }
  508.    }
  509.  
  510. static void rotcolbr(PALENTRY pal[], int num)
  511.    {
  512.    int      curr;
  513.    int    dummy;
  514.  
  515.     for (curr=0; curr<=num; curr++)
  516.       {
  517.       dummy = pal[curr].red;
  518.       pal[curr].red = pal[curr].blue;
  519.       pal[curr].blue = dummy;
  520.       }
  521.    }
  522.  
  523.  
  524. /*
  525.  * convert a range of colors to grey scale
  526.  */
  527.  
  528.  
  529. static void palrangetogrey(PALENTRY pal[], int first, int how_many)
  530.    {
  531.    PALENTRY      *curr;
  532.    BYTE  val;
  533.  
  534.  
  535.    for (curr = &pal[first]; how_many>0; how_many--, curr++)
  536.       {
  537.       val = (BYTE) ( ((int)curr->red*30 + (int)curr->green*59 + (int)curr->blue*11) / 100 );
  538.       curr->red = curr->green = curr->blue = (BYTE)val;
  539.       }
  540.    }
  541.  
  542. /*
  543.  * convert a range of colors to their inverse
  544.  */
  545.  
  546.  
  547. static void palrangetonegative(PALENTRY pal[], int first, int how_many)
  548.    {
  549.    PALENTRY      *curr;
  550.  
  551.    for (curr = &pal[first]; how_many>0; how_many--, curr++)
  552.       {
  553.       curr->red   = 63 - curr->red;
  554.       curr->green = 63 - curr->green;
  555.       curr->blue  = 63 - curr->blue;
  556.       }
  557.    }
  558.  
  559.  
  560. /*
  561.  * draw and horizontal/vertical dotted lines
  562.  */
  563.  
  564.  
  565. static void hdline(int x, int y, int width)
  566.    {
  567.    int ctr;
  568.    BYTE *ptr;
  569.  
  570.    for (ctr=0, ptr=line_buff; ctr<width; ctr++, ptr++)
  571.       *ptr = (ctr&2) ? bg_color : fg_color;
  572.  
  573.    putrow(x, y, width, (char *)line_buff);
  574.    }
  575.  
  576.  
  577. static void vdline(int x, int y, int depth)
  578.    {
  579.    int ctr;
  580.  
  581.    for (ctr=0; ctr<depth; ctr++, y++)
  582.       clip_putcolor(x, y, (ctr&2) ? bg_color : fg_color);
  583.    }
  584.  
  585.  
  586. static void drect(int x, int y, int width, int depth)
  587.    {
  588.    hdline(x, y, width);
  589.    hdline(x, y+depth-1, width);
  590.  
  591.    vdline(x, y, depth);
  592.    vdline(x+width-1, y, depth);
  593.    }
  594.  
  595.  
  596. /*
  597.  * A very simple memory "allocator".
  598.  *
  599.  * Each call to mem_alloc() returns size bytes from the array mem_block.
  600.  *
  601.  * Be sure to call mem_init() before using mem_alloc()!
  602.  *
  603.  */
  604.  
  605. static char     *mem_block;
  606. static unsigned  mem_avail;
  607.  
  608.  
  609. void mem_init(VOIDPTR block, unsigned size)
  610.    {
  611.    mem_block = (char *)block;
  612.    mem_avail = size;
  613.    }
  614.  
  615.  
  616. VOIDPTR mem_alloc(unsigned size)
  617.    {
  618.    VOIDPTR block;
  619.  
  620. #ifndef XFRACT
  621.    if (size & 1)
  622.       ++size;   /* allocate even sizes */
  623. #else
  624.    size = (size+3)&~3; /* allocate word-aligned memory */
  625. #endif
  626.  
  627.    if (mem_avail < size)   /* don't let this happen! */
  628.       {
  629.       static char far msg[] = "editpal.c: Out of memory!\n";
  630.  
  631.       stopmsg(0, msg);
  632.       exit(1);
  633.       }
  634.  
  635.    block = mem_block;
  636.    mem_avail -= size;
  637.    mem_block += size;
  638.  
  639.    return(block);
  640.    }
  641.  
  642.  
  643.  
  644. /*
  645.  * misc. routines
  646.  *
  647.  */
  648.  
  649.  
  650. static BOOLEAN is_reserved(int color)
  651.    {
  652.    return ( (reserve_colors && (color==fg_color || color==bg_color) ) ? TRUE : FALSE );
  653.    }
  654.  
  655.  
  656.  
  657. static BOOLEAN is_in_box(int x, int y, int bx, int by, int bw, int bd)
  658.    {
  659.    return ( (x >= bx) && (y >= by) && (x < bx+bw) && (y < by+bd) );
  660.    }
  661.  
  662.  
  663.  
  664. static void draw_diamond(int x, int y, int color)
  665.    {
  666.    putcolor (x+2, y+0,      color);
  667.    hline    (x+1, y+1, 3, color);
  668.    hline    (x+0, y+2, 5, color);
  669.    hline    (x+1, y+3, 3, color);
  670.    putcolor (x+2, y+4,      color);
  671.    }
  672.  
  673.  
  674.  
  675. /*
  676.  * Class:     Cursor
  677.  *
  678.  * Purpose:   Draw the blinking cross-hair cursor.
  679.  *
  680.  * Note:      Only one Cursor can exist (referenced through the_cursor).
  681.  *          IMPORTANT: Call Cursor_Construct before you use any other
  682.  *          Cursor_ function!  Call Cursor_Destroy before exiting to
  683.  *          deallocate memory.
  684.  */
  685.  
  686. struct _Cursor
  687.    {
  688.  
  689.    int       x, y;
  690.    int       hidden;     /* >0 if mouse hidden */
  691.    long    last_blink;
  692.    BOOLEAN blink;
  693.    char    t[CURSOR_SIZE],      /* save line segments here */
  694.        b[CURSOR_SIZE],
  695.        l[CURSOR_SIZE],
  696.        r[CURSOR_SIZE];
  697.    } ;
  698.  
  699. #define Cursor struct _Cursor
  700.  
  701. /* private: */
  702.  
  703.    static  void    Cursor__Draw      (void);
  704.    static  void    Cursor__Save      (void);
  705.    static  void    Cursor__Restore   (void);
  706.  
  707. /* public: */
  708. #ifdef NOT_USED
  709.    static  BOOLEAN Cursor_IsHidden  (void);
  710. #endif
  711.  
  712.  
  713.  
  714. static Cursor *the_cursor = NULL;
  715.  
  716.  
  717. BOOLEAN Cursor_Construct(void)
  718.    {
  719.    if (the_cursor != NULL)
  720.       return(FALSE);
  721.  
  722.    the_cursor = new(Cursor);
  723.  
  724.    the_cursor->x      = sxdots/2;
  725.    the_cursor->y      = sydots/2;
  726.    the_cursor->hidden      = 1;
  727.    the_cursor->blink      = FALSE;
  728.    the_cursor->last_blink = 0;
  729.  
  730.    return (TRUE);
  731.    }
  732.  
  733.  
  734. void Cursor_Destroy(void)
  735.    {
  736.    if (the_cursor != NULL)
  737.       delete(the_cursor);
  738.  
  739.    the_cursor = NULL;
  740.    }
  741.  
  742.  
  743.  
  744. static void Cursor__Draw(void)
  745.    {
  746.    int color;
  747.  
  748.    find_special_colors();
  749.    color = (the_cursor->blink) ? color_medium : color_dark;
  750.  
  751.    vline(the_cursor->x, the_cursor->y-CURSOR_SIZE-1, CURSOR_SIZE, color);
  752.    vline(the_cursor->x, the_cursor->y+2,         CURSOR_SIZE, color);
  753.  
  754.    hline(the_cursor->x-CURSOR_SIZE-1, the_cursor->y, CURSOR_SIZE, color);
  755.    hline(the_cursor->x+2,          the_cursor->y, CURSOR_SIZE, color);
  756.    }
  757.  
  758.  
  759. static void Cursor__Save(void)
  760.    {
  761.    vgetrow(the_cursor->x, the_cursor->y-CURSOR_SIZE-1, CURSOR_SIZE, the_cursor->t);
  762.    vgetrow(the_cursor->x, the_cursor->y+2,           CURSOR_SIZE, the_cursor->b);
  763.  
  764.    getrow(the_cursor->x-CURSOR_SIZE-1, the_cursor->y,  CURSOR_SIZE, the_cursor->l);
  765.    getrow(the_cursor->x+2,           the_cursor->y,  CURSOR_SIZE, the_cursor->r);
  766.    }
  767.  
  768.  
  769. static void Cursor__Restore(void)
  770.    {
  771.    vputrow(the_cursor->x, the_cursor->y-CURSOR_SIZE-1, CURSOR_SIZE, the_cursor->t);
  772.    vputrow(the_cursor->x, the_cursor->y+2,           CURSOR_SIZE, the_cursor->b);
  773.  
  774.    putrow(the_cursor->x-CURSOR_SIZE-1, the_cursor->y,  CURSOR_SIZE, the_cursor->l);
  775.    putrow(the_cursor->x+2,           the_cursor->y,  CURSOR_SIZE, the_cursor->r);
  776.    }
  777.  
  778.  
  779.  
  780. void Cursor_SetPos(int x, int y)
  781.    {
  782.    if (!the_cursor->hidden)
  783.       Cursor__Restore();
  784.  
  785.    the_cursor->x = x;
  786.    the_cursor->y = y;
  787.  
  788.    if (!the_cursor->hidden)
  789.       {
  790.       Cursor__Save();
  791.       Cursor__Draw();
  792.       }
  793.    }
  794.  
  795. #ifdef NOT_USED
  796.  
  797. static int Cursor_IsHidden(void)
  798.    {
  799.    return ( the_cursor->hidden );
  800.    }
  801.  
  802.  
  803. #endif
  804.  
  805.  
  806. void Cursor_Move(int xoff, int yoff)
  807.    {
  808.    if ( !the_cursor->hidden )
  809.       Cursor__Restore();
  810.  
  811.    the_cursor->x += xoff;
  812.    the_cursor->y += yoff;
  813.  
  814.    if (the_cursor->x < 0)       the_cursor->x = 0;
  815.    if (the_cursor->y < 0)       the_cursor->y = 0;
  816.    if (the_cursor->x >= sxdots) the_cursor->x = sxdots-1;
  817.    if (the_cursor->y >= sydots) the_cursor->y = sydots-1;
  818.  
  819.    if ( !the_cursor->hidden )
  820.       {
  821.       Cursor__Save();
  822.       Cursor__Draw();
  823.       }
  824.    }
  825.  
  826.  
  827. int Cursor_GetX(void)   { return(the_cursor->x); }
  828.  
  829. int Cursor_GetY(void)   { return(the_cursor->y); }
  830.  
  831.  
  832. void Cursor_Hide(void)
  833.    {
  834.    if ( the_cursor->hidden++ == 0 )
  835.       Cursor__Restore();
  836.    }
  837.  
  838.  
  839. void Cursor_Show(void)
  840.    {
  841.    if ( --the_cursor->hidden == 0)
  842.       {
  843.       Cursor__Save();
  844.       Cursor__Draw();
  845.       }
  846.    }
  847.  
  848. #ifdef XFRACT
  849. void Cursor_StartMouseTracking()
  850. {
  851.     editpal_cursor = 1;
  852. }
  853.  
  854. void Cursor_EndMouseTracking()
  855. {
  856.     editpal_cursor = 0;
  857. }
  858. #endif
  859.  
  860. /* See if the cursor should blink yet, and blink it if so */
  861. void Cursor_CheckBlink(void)
  862. {
  863.    long tick;
  864.    tick = readticker();
  865.  
  866.    if ( (tick - the_cursor->last_blink) > CURSOR_BLINK_RATE )
  867.       {
  868.       the_cursor->blink = (the_cursor->blink) ? FALSE : TRUE;
  869.       the_cursor->last_blink = tick;
  870.       if ( !the_cursor->hidden )
  871.      Cursor__Draw();
  872.       }
  873.    else if ( tick < the_cursor->last_blink )
  874.       the_cursor->last_blink = tick;
  875. }
  876.  
  877. int Cursor_WaitKey(void)   /* blink cursor while waiting for a key */
  878.    {
  879.  
  880. #ifndef XFRACT
  881.    while ( !keypressed() ) {
  882.        Cursor_CheckBlink();
  883.    }
  884. #else
  885.    while ( !waitkeypressed(1) ) {
  886.        Cursor_CheckBlink();
  887.    }
  888. #endif
  889.  
  890.    return( keypressed() );
  891.    }
  892.  
  893.  
  894.  
  895. /*
  896.  * Class:     MoveBox
  897.  *
  898.  * Purpose:   Handles the rectangular move/resize box.
  899.  */
  900.  
  901. struct _MoveBox
  902.    {
  903.    int        x, y;
  904.    int        base_width,
  905.         base_depth;
  906.    int        csize;
  907.    BOOLEAN  moved;
  908.    BOOLEAN  should_hide;
  909.    char    *t, *b,
  910.        *l, *r;
  911.    } ;
  912.  
  913. #define MoveBox struct _MoveBox
  914.  
  915. /* private: */
  916.  
  917.    static void       MoveBox__Draw     (MoveBox *this);
  918.    static void       MoveBox__Erase    (MoveBox *this);
  919.    static void       MoveBox__Move     (MoveBox *this, int key);
  920.  
  921. /* public: */
  922.  
  923.    static MoveBox *MoveBox_Construct  (int x, int y, int csize, int base_width,
  924.                       int base_depth);
  925.    static void       MoveBox_Destroy    (MoveBox *this);
  926.    static BOOLEAN  MoveBox_Process    (MoveBox *this); /* returns FALSE if ESCAPED */
  927.    static BOOLEAN  MoveBox_Moved      (MoveBox *this);
  928.    static BOOLEAN  MoveBox_ShouldHide (MoveBox *this);
  929.    static int       MoveBox_X          (MoveBox *this);
  930.    static int       MoveBox_Y          (MoveBox *this);
  931.    static int       MoveBox_CSize      (MoveBox *this);
  932.  
  933.    static void       MoveBox_SetPos     (MoveBox *this, int x, int y);
  934.    static void       MoveBox_SetCSize   (MoveBox *this, int csize);
  935.  
  936.  
  937.  
  938. static MoveBox *MoveBox_Construct(int x, int y, int csize, int base_width, int base_depth)
  939.    {
  940.    MoveBox *this = new(MoveBox);
  941.  
  942.    this->x         = x;
  943.    this->y         = y;
  944.    this->csize         = csize;
  945.    this->base_width  = base_width;
  946.    this->base_depth  = base_depth;
  947.    this->moved         = FALSE;
  948.    this->should_hide = FALSE;
  949.    this->t         = newx(sxdots);
  950.    this->b         = newx(sxdots);
  951.    this->l         = newx(sydots);
  952.    this->r         = newx(sydots);
  953.  
  954.    return(this);
  955.    }
  956.  
  957.  
  958. static void MoveBox_Destroy(MoveBox *this)
  959.    {
  960.    delete(this->t);
  961.    delete(this->b);
  962.    delete(this->l);
  963.    delete(this->r);
  964.    delete(this);
  965.    }
  966.  
  967.  
  968. static BOOLEAN MoveBox_Moved(MoveBox *this) { return(this->moved); }
  969.  
  970. static BOOLEAN MoveBox_ShouldHide(MoveBox *this) { return(this->should_hide); }
  971.  
  972. static int MoveBox_X(MoveBox *this)     { return(this->x); }
  973.  
  974. static int MoveBox_Y(MoveBox *this)     { return(this->y); }
  975.  
  976. static int MoveBox_CSize(MoveBox *this)  { return(this->csize); }
  977.  
  978.  
  979. static void MoveBox_SetPos(MoveBox *this, int x, int y)
  980.    {
  981.    this->x = x;
  982.    this->y = y;
  983.    }
  984.  
  985.  
  986. static void MoveBox_SetCSize(MoveBox *this, int csize)
  987.    {
  988.    this->csize = csize;
  989.    }
  990.  
  991.  
  992. static void MoveBox__Draw(MoveBox *this)  /* private */
  993.    {
  994.    int width = this->base_width + this->csize*16+1,
  995.        depth = this->base_depth + this->csize*16+1;
  996.    int x     = this->x,
  997.        y     = this->y;
  998.  
  999.  
  1000.    getrow (x, y,     width, this->t);
  1001.    getrow (x, y+depth-1, width, this->b);
  1002.  
  1003.    vgetrow(x,          y, depth, this->l);
  1004.    vgetrow(x+width-1, y, depth, this->r);
  1005.  
  1006.    hdline(x, y,         width);
  1007.    hdline(x, y+depth-1, width);
  1008.  
  1009.    vdline(x,         y, depth);
  1010.    vdline(x+width-1, y, depth);
  1011.    }
  1012.  
  1013.  
  1014. static void MoveBox__Erase(MoveBox *this)   /* private */
  1015.    {
  1016.    int width = this->base_width + this->csize*16+1,
  1017.        depth = this->base_depth + this->csize*16+1;
  1018.  
  1019.    vputrow(this->x,        this->y, depth, this->l);
  1020.    vputrow(this->x+width-1, this->y, depth, this->r);
  1021.  
  1022.    putrow(this->x, this->y,        width, this->t);
  1023.    putrow(this->x, this->y+depth-1, width, this->b);
  1024.    }
  1025.  
  1026.  
  1027. #define BOX_INC     1
  1028. #define CSIZE_INC   2
  1029.  
  1030. static void MoveBox__Move(MoveBox *this, int key)
  1031.    {
  1032.    BOOLEAN done  = FALSE;
  1033.    BOOLEAN first = TRUE;
  1034.    int       xoff  = 0,
  1035.        yoff  = 0;
  1036.  
  1037.    while ( !done )
  1038.       {
  1039.       switch(key)
  1040.      {
  1041.      case RIGHT_ARROW_2:     xoff += BOX_INC*4;   break;
  1042.      case RIGHT_ARROW:     xoff += BOX_INC;     break;
  1043.      case LEFT_ARROW_2:     xoff -= BOX_INC*4;   break;
  1044.      case LEFT_ARROW:     xoff -= BOX_INC;     break;
  1045.      case DOWN_ARROW_2:     yoff += BOX_INC*4;   break;
  1046.      case DOWN_ARROW:     yoff += BOX_INC;     break;
  1047.      case UP_ARROW_2:     yoff -= BOX_INC*4;   break;
  1048.      case UP_ARROW:      yoff -= BOX_INC;     break;
  1049.  
  1050.      default:
  1051.         done = TRUE;
  1052.      }
  1053.  
  1054.       if (!done)
  1055.      {
  1056.      if (!first)
  1057.         getakey();         /* delete key from buffer */
  1058.      else
  1059.         first = FALSE;
  1060.      key = keypressed();   /* peek at the next one... */
  1061.      }
  1062.       }
  1063.  
  1064.    xoff += this->x;
  1065.    yoff += this->y;   /* (xoff,yoff) = new position */
  1066.  
  1067.    if (xoff < 0) xoff = 0;
  1068.    if (yoff < 0) yoff = 0;
  1069.  
  1070.    if (xoff+this->base_width+this->csize*16+1 > sxdots)
  1071.        xoff = sxdots - (this->base_width+this->csize*16+1);
  1072.  
  1073.    if (yoff+this->base_depth+this->csize*16+1 > sydots)
  1074.       yoff = sydots - (this->base_depth+this->csize*16+1);
  1075.  
  1076.    if ( xoff!=this->x || yoff!=this->y )
  1077.       {
  1078.       MoveBox__Erase(this);
  1079.       this->y = yoff;
  1080.       this->x = xoff;
  1081.       MoveBox__Draw(this);
  1082.       }
  1083.    }
  1084.  
  1085.  
  1086. static BOOLEAN MoveBox_Process(MoveBox *this)
  1087.    {
  1088.    int       key;
  1089.    int       orig_x     = this->x,
  1090.        orig_y     = this->y,
  1091.        orig_csize = this->csize;
  1092.  
  1093.    MoveBox__Draw(this);
  1094.  
  1095. #ifdef XFRACT
  1096.    Cursor_StartMouseTracking();
  1097. #endif
  1098.    while (1)
  1099.       {
  1100.       Cursor_WaitKey();
  1101.       key = getakey();
  1102.  
  1103.       if (key==ENTER || key==ENTER_2 || key==ESC || key=='H' || key=='h')
  1104.      {
  1105.      if (this->x != orig_x || this->y != orig_y || this->csize != orig_csize)
  1106.         this->moved = TRUE;
  1107.      else
  1108.        this->moved = FALSE;
  1109.      break;
  1110.      }
  1111.  
  1112.       switch(key)
  1113.      {
  1114.      case UP_ARROW:
  1115.      case DOWN_ARROW:
  1116.      case LEFT_ARROW:
  1117.      case RIGHT_ARROW:
  1118.      case UP_ARROW_2:
  1119.      case DOWN_ARROW_2:
  1120.      case LEFT_ARROW_2:
  1121.      case RIGHT_ARROW_2:
  1122.         MoveBox__Move(this, key);
  1123.         break;
  1124.  
  1125.      case PAGE_UP:     /* shrink */
  1126.         if (this->csize > CSIZE_MIN)
  1127.            {
  1128.            int t = this->csize - CSIZE_INC;
  1129.            int change;
  1130.  
  1131.            if (t < CSIZE_MIN)
  1132.           t = CSIZE_MIN;
  1133.  
  1134.            MoveBox__Erase(this);
  1135.  
  1136.            change = this->csize - t;
  1137.            this->csize = t;
  1138.            this->x += (change*16) / 2;
  1139.            this->y += (change*16) / 2;
  1140.            MoveBox__Draw(this);
  1141.            }
  1142.         break;
  1143.  
  1144.      case PAGE_DOWN:   /* grow */
  1145.         {
  1146.         int max_width = min(sxdots, MAX_WIDTH);
  1147.  
  1148.         if (this->base_depth+(this->csize+CSIZE_INC)*16+1 < sydots  &&
  1149.             this->base_width+(this->csize+CSIZE_INC)*16+1 < max_width )
  1150.            {
  1151.            MoveBox__Erase(this);
  1152.            this->x -= (CSIZE_INC*16) / 2;
  1153.            this->y -= (CSIZE_INC*16) / 2;
  1154.            this->csize += CSIZE_INC;
  1155.            if (this->y+this->base_depth+this->csize*16+1 > sydots)
  1156.           this->y = sydots - (this->base_depth+this->csize*16+1);
  1157.            if (this->x+this->base_width+this->csize*16+1 > max_width)
  1158.           this->x = max_width - (this->base_width+this->csize*16+1);
  1159.            if (this->y < 0)
  1160.           this->y = 0;
  1161.            if (this->x < 0)
  1162.           this->x = 0;
  1163.            MoveBox__Draw(this);
  1164.            }
  1165.         }
  1166.         break;
  1167.      }
  1168.       }
  1169.  
  1170. #ifdef XFRACT
  1171.    Cursor_EndMouseTracking();
  1172. #endif
  1173.  
  1174.    MoveBox__Erase(this);
  1175.  
  1176.    this->should_hide = (key == 'H' || key == 'h') ? TRUE : FALSE;
  1177.  
  1178.    return( (key==ESC) ? FALSE : TRUE );
  1179.    }
  1180.  
  1181.  
  1182.  
  1183. /*
  1184.  * Class:     CEditor
  1185.  *
  1186.  * Purpose:   Edits a single color component (R, G or B)
  1187.  *
  1188.  * Note:      Calls the "other_key" function to process keys it doesn't use.
  1189.  *          The "change" function is called whenever the value is changed
  1190.  *          by the CEditor.
  1191.  */
  1192.  
  1193. struct _CEditor
  1194.    {
  1195.    int         x, y;
  1196.    char      letter;
  1197.    int         val;
  1198.    BOOLEAN   done;
  1199.    BOOLEAN   hidden;
  1200. #ifndef XFRACT
  1201.    void    (*other_key)(int key, struct _CEditor *ce, VOIDPTR info);
  1202.    void    (*change)(struct _CEditor *ce, VOIDPTR info);
  1203. #else
  1204.    void    (*other_key)();
  1205.    void    (*change)();
  1206. #endif
  1207.    void     *info;
  1208.  
  1209.    } ;
  1210.  
  1211. #define CEditor struct _CEditor
  1212.  
  1213. /* public: */
  1214.  
  1215. #ifndef XFRACT
  1216.    static CEditor *CEditor_Construct( int x, int y, char letter,
  1217.                       void (*other_key)(int,CEditor*,void*),
  1218.                                       void (*change)(CEditor*,void*), VOIDPTR info);
  1219.    static void CEditor_Destroy     (CEditor *this);
  1220.    static void CEditor_Draw     (CEditor *this);
  1221.    static void CEditor_SetPos     (CEditor *this, int x, int y);
  1222.    static void CEditor_SetVal     (CEditor *this, int val);
  1223.    static int  CEditor_GetVal     (CEditor *this);
  1224.    static void CEditor_SetDone     (CEditor *this, BOOLEAN done);
  1225.    static void CEditor_SetHidden (CEditor *this, BOOLEAN hidden);
  1226.    static int  CEditor_Edit     (CEditor *this);
  1227. #else
  1228.    static CEditor *CEditor_Construct( int , int , char ,
  1229.                                     void (*other_key)(),
  1230.                                     void (*change)(), VOIDPTR );
  1231.    static void CEditor_Destroy         (CEditor *);
  1232.    static void CEditor_Draw    (CEditor *);
  1233.    static void CEditor_SetPos  (CEditor *, int , int );
  1234.    static void CEditor_SetVal  (CEditor *, int );
  1235.    static int  CEditor_GetVal  (CEditor *);
  1236.    static void CEditor_SetDone         (CEditor *, BOOLEAN );
  1237.    static void CEditor_SetHidden (CEditor *, BOOLEAN );
  1238.    static int  CEditor_Edit    (CEditor *);
  1239. #endif
  1240.  
  1241. #define CEditor_WIDTH (8*3+4)
  1242. #define CEditor_DEPTH (8+4)
  1243.  
  1244.  
  1245.  
  1246. #ifndef XFRACT
  1247. static CEditor *CEditor_Construct( int x, int y, char letter,
  1248.                    void (*other_key)(int,CEditor*,VOIDPTR),
  1249.                    void (*change)(CEditor*, VOIDPTR), VOIDPTR info)
  1250. #else
  1251. static CEditor *CEditor_Construct( int x, int y, char letter,
  1252.                                    void (*other_key)(),
  1253.                                    void (*change)(), VOIDPTR info)
  1254. #endif
  1255.    {
  1256.    CEditor *this = new(CEditor);
  1257.  
  1258.    this->x       = x;
  1259.    this->y       = y;
  1260.    this->letter    = letter;
  1261.    this->val       = 0;
  1262.    this->other_key = other_key;
  1263.    this->hidden    = FALSE;
  1264.    this->change    = change;
  1265.    this->info       = info;
  1266.  
  1267.    return(this);
  1268.    }
  1269.  
  1270.  
  1271. static void CEditor_Destroy(CEditor *this)
  1272.    {
  1273.    delete(this);
  1274.    }
  1275.  
  1276.  
  1277. static void CEditor_Draw(CEditor *this)
  1278.    {
  1279.    if (this->hidden)
  1280.       return;
  1281.  
  1282.    Cursor_Hide();
  1283.    displayf(this->x+2, this->y+2, fg_color, bg_color, "%c%02d", this->letter, this->val);
  1284.    Cursor_Show();
  1285.    }
  1286.  
  1287.  
  1288. static void CEditor_SetPos(CEditor *this, int x, int y)
  1289.    {
  1290.    this->x = x;
  1291.    this->y = y;
  1292.    }
  1293.  
  1294.  
  1295. static void CEditor_SetVal(CEditor *this, int val)
  1296.    {
  1297.    this->val = val;
  1298.    }
  1299.  
  1300.  
  1301. static int CEditor_GetVal(CEditor *this)
  1302.    {
  1303.    return(this->val);
  1304.    }
  1305.  
  1306.  
  1307. static void CEditor_SetDone(CEditor *this, BOOLEAN done)
  1308.    {
  1309.    this->done = done;
  1310.    }
  1311.  
  1312.  
  1313. static void CEditor_SetHidden(CEditor *this, BOOLEAN hidden)
  1314.    {
  1315.    this->hidden = hidden;
  1316.    }
  1317.  
  1318.  
  1319. static int CEditor_Edit(CEditor *this)
  1320.    {
  1321.    int key;
  1322.    int diff;
  1323.  
  1324.    this->done = FALSE;
  1325.  
  1326.    if (!this->hidden)
  1327.       {
  1328.       Cursor_Hide();
  1329.       rect(this->x, this->y, CEditor_WIDTH, CEditor_DEPTH, fg_color);
  1330.       Cursor_Show();
  1331.       }
  1332.  
  1333. #ifdef XFRACT
  1334.    Cursor_StartMouseTracking();
  1335. #endif
  1336.    while ( !this->done )
  1337.       {
  1338.       Cursor_WaitKey();
  1339.       key = getakey();
  1340.  
  1341.       switch( key )
  1342.      {
  1343.      case PAGE_UP:
  1344.         if (this->val < 63)
  1345.            {
  1346.            this->val += 5;
  1347.            if (this->val > 63)
  1348.           this->val = 63;
  1349.            CEditor_Draw(this);
  1350.            this->change(this, this->info);
  1351.            }
  1352.         break;
  1353.  
  1354.      case '+':
  1355.         diff = 1;
  1356.         while ( keypressed() == key )
  1357.            {
  1358.            getakey();
  1359.            ++diff;
  1360.            }
  1361.         if (this->val < 63)
  1362.            {
  1363.            this->val += diff;
  1364.            if (this->val > 63)
  1365.           this->val = 63;
  1366.            CEditor_Draw(this);
  1367.            this->change(this, this->info);
  1368.            }
  1369.         break;
  1370.  
  1371.      case PAGE_DOWN:
  1372.         if (this->val > 0)
  1373.            {
  1374.            this->val -= 5;
  1375.            if (this->val < 0)
  1376.           this->val = 0;
  1377.            CEditor_Draw(this);
  1378.            this->change(this, this->info);
  1379.            } break;
  1380.  
  1381.      case '-':
  1382.         diff = 1;
  1383.         while ( keypressed() == key )
  1384.            {
  1385.            getakey();
  1386.            ++diff;
  1387.            }
  1388.         if (this->val > 0)
  1389.            {
  1390.            this->val -= diff;
  1391.            if (this->val < 0)
  1392.           this->val = 0;
  1393.            CEditor_Draw(this);
  1394.            this->change(this, this->info);
  1395.            }
  1396.         break;
  1397.  
  1398.      case '0':
  1399.      case '1':
  1400.      case '2':
  1401.      case '3':
  1402.      case '4':
  1403.      case '5':
  1404.      case '6':
  1405.      case '7':
  1406.      case '8':
  1407.      case '9':
  1408.         this->val = (key - '0') * 10;
  1409.         if (this->val > 63)
  1410.            this->val = 63;
  1411.         CEditor_Draw(this);
  1412.         this->change(this, this->info);
  1413.         break;
  1414.  
  1415.      default:
  1416.         this->other_key(key, this, this->info);
  1417.         break;
  1418.      } /* switch */
  1419.       } /* while */
  1420. #ifdef XFRACT
  1421.    Cursor_EndMouseTracking();
  1422. #endif
  1423.  
  1424.    if (!this->hidden)
  1425.       {
  1426.       Cursor_Hide();
  1427.       rect(this->x, this->y, CEditor_WIDTH, CEditor_DEPTH, bg_color);
  1428.       Cursor_Show();
  1429.       }
  1430.  
  1431.    return(key);
  1432.    }
  1433.  
  1434.  
  1435.  
  1436. /*
  1437.  * Class:     RGBEditor
  1438.  *
  1439.  * Purpose:   Edits a complete color using three CEditors for R, G and B
  1440.  */
  1441.  
  1442. struct _RGBEditor
  1443.    {
  1444.    int         x, y;          /* position */
  1445.    int         curr;          /* 0=r, 1=g, 2=b */
  1446.    int         pal;          /* palette number */
  1447.    BOOLEAN   done;
  1448.    BOOLEAN   hidden;
  1449.    CEditor  *color[3];          /* color editors 0=r, 1=g, 2=b */
  1450. #ifndef XFRACT
  1451.    void    (*other_key)(int key, struct _RGBEditor *e, VOIDPTR info);
  1452.    void    (*change)(struct _RGBEditor *e, VOIDPTR info);
  1453. #else
  1454.    void    (*other_key)();
  1455.    void    (*change)();
  1456. #endif
  1457.    void     *info;
  1458.    } ;
  1459.  
  1460. #define RGBEditor struct _RGBEditor
  1461.  
  1462. /* private: */
  1463.  
  1464.    static void      RGBEditor__other_key (int key, CEditor *ceditor, VOIDPTR info);
  1465.    static void      RGBEditor__change    (CEditor *ceditor, VOIDPTR info);
  1466.  
  1467. /* public: */
  1468.  
  1469. #ifndef XFRACT
  1470.    static RGBEditor *RGBEditor_Construct(int x, int y,
  1471.              void (*other_key)(int,RGBEditor*,void*),
  1472.              void (*change)(RGBEditor*,void*), VOIDPTR info);
  1473. #else
  1474.    static RGBEditor *RGBEditor_Construct(int x, int y,
  1475.                      void (*other_key)(),
  1476.                      void (*change)(), VOIDPTR info);
  1477. #endif
  1478.  
  1479.    static void       RGBEditor_Destroy  (RGBEditor *this);
  1480.    static void       RGBEditor_SetPos   (RGBEditor *this, int x, int y);
  1481.    static void       RGBEditor_SetDone  (RGBEditor *this, BOOLEAN done);
  1482.    static void       RGBEditor_SetHidden(RGBEditor *this, BOOLEAN hidden);
  1483.    static void       RGBEditor_BlankSampleBox(RGBEditor *this);
  1484.    static void       RGBEditor_Update   (RGBEditor *this);
  1485.    static void       RGBEditor_Draw     (RGBEditor *this);
  1486.    static int       RGBEditor_Edit     (RGBEditor *this);
  1487.    static void       RGBEditor_SetRGB   (RGBEditor *this, int pal, PALENTRY *rgb);
  1488.    static PALENTRY RGBEditor_GetRGB   (RGBEditor *this);
  1489.  
  1490. #define RGBEditor_WIDTH 62
  1491. #define RGBEditor_DEPTH (1+1+CEditor_DEPTH*3-2+2)
  1492.  
  1493. #define RGBEditor_BWIDTH ( RGBEditor_WIDTH - (2+CEditor_WIDTH+1 + 2) )
  1494. #define RGBEditor_BDEPTH ( RGBEditor_DEPTH - 4 )
  1495.  
  1496.  
  1497.  
  1498. #ifndef XFRACT
  1499. static RGBEditor *RGBEditor_Construct(int x, int y, void (*other_key)(int,RGBEditor*,void*),
  1500.                       void (*change)(RGBEditor*,void*), VOIDPTR info)
  1501. #else
  1502. static RGBEditor *RGBEditor_Construct(int x, int y, void (*other_key)(),
  1503.                                       void (*change)(), VOIDPTR info)
  1504. #endif
  1505.    {
  1506.    RGBEditor      *this     = new(RGBEditor);
  1507.    static char far letter[] = "RGB";
  1508.    int           ctr;
  1509.  
  1510.    for (ctr=0; ctr<3; ctr++)
  1511.       this->color[ctr] = CEditor_Construct(0, 0, letter[ctr], RGBEditor__other_key,
  1512.                        RGBEditor__change, this);
  1513.  
  1514.    RGBEditor_SetPos(this, x, y);
  1515.    this->curr       = 0;
  1516.    this->pal       = 1;
  1517.    this->hidden    = FALSE;
  1518.    this->other_key = other_key;
  1519.    this->change    = change;
  1520.    this->info       = info;
  1521.  
  1522.    return(this);
  1523.    }
  1524.  
  1525.  
  1526. static void RGBEditor_Destroy(RGBEditor *this)
  1527.    {
  1528.    CEditor_Destroy(this->color[0]);
  1529.    CEditor_Destroy(this->color[1]);
  1530.    CEditor_Destroy(this->color[2]);
  1531.    delete(this);
  1532.    }
  1533.  
  1534.  
  1535. static void RGBEditor_SetDone(RGBEditor *this, BOOLEAN done)
  1536.    {
  1537.    this->done = done;
  1538.    }
  1539.  
  1540.  
  1541. static void RGBEditor_SetHidden(RGBEditor *this, BOOLEAN hidden)
  1542.    {
  1543.    this->hidden = hidden;
  1544.    CEditor_SetHidden(this->color[0], hidden);
  1545.    CEditor_SetHidden(this->color[1], hidden);
  1546.    CEditor_SetHidden(this->color[2], hidden);
  1547.    }
  1548.  
  1549.  
  1550. static void RGBEditor__other_key(int key, CEditor *ceditor, VOIDPTR info) /* private */
  1551.    {
  1552.    RGBEditor *this = (RGBEditor *)info;
  1553.  
  1554.    switch( key )
  1555.       {
  1556.       case 'R':
  1557.       case 'r':
  1558.      if (this->curr != 0)
  1559.         {
  1560.         this->curr = 0;
  1561.         CEditor_SetDone(ceditor, TRUE);
  1562.         }
  1563.      break;
  1564.  
  1565.       case 'G':
  1566.       case 'g':
  1567.      if (this->curr != 1)
  1568.         {
  1569.         this->curr = 1;
  1570.         CEditor_SetDone(ceditor, TRUE);
  1571.         }
  1572.      break;
  1573.  
  1574.       case 'B':
  1575.       case 'b':
  1576.      if (this->curr != 2)
  1577.         {
  1578.         this->curr = 2;
  1579.         CEditor_SetDone(ceditor, TRUE);
  1580.         }
  1581.      break;
  1582.  
  1583.       case DELETE:   /* move to next CEditor */
  1584.      if ( ++this->curr > 2)
  1585.         this->curr = 0;
  1586.      CEditor_SetDone(ceditor, TRUE);
  1587.      break;
  1588.  
  1589.       case INSERT:   /* move to prev CEditor */
  1590.      if ( --this->curr < 0)
  1591.         this->curr = 2;
  1592.      CEditor_SetDone(ceditor, TRUE);
  1593.      break;
  1594.  
  1595.       default:
  1596.      this->other_key(key, this, this->info);
  1597.      if (this->done)
  1598.         CEditor_SetDone(ceditor, TRUE);
  1599.      break;
  1600.       }
  1601.    }
  1602.  
  1603.  
  1604.  
  1605. #ifdef __TURBOC__
  1606. #   pragma argsused   /* kills "arg not used" warning */
  1607. #endif
  1608.  
  1609. static void RGBEditor__change(CEditor *ceditor, VOIDPTR info) /* private */
  1610.    {
  1611.    RGBEditor *this = (RGBEditor *)info;
  1612.  
  1613.    if ( this->pal < colors && !is_reserved(this->pal) )
  1614.       setpal(this->pal, CEditor_GetVal(this->color[0]),
  1615.       CEditor_GetVal(this->color[1]), CEditor_GetVal(this->color[2]));
  1616.  
  1617.    this->change(this, this->info);
  1618.    }
  1619.  
  1620.  
  1621. static void RGBEditor_SetPos(RGBEditor *this, int x, int y)
  1622.    {
  1623.    this->x = x;
  1624.    this->y = y;
  1625.  
  1626.    CEditor_SetPos(this->color[0], x+2, y+2);
  1627.    CEditor_SetPos(this->color[1], x+2, y+2+CEditor_DEPTH-1);
  1628.    CEditor_SetPos(this->color[2], x+2, y+2+CEditor_DEPTH-1+CEditor_DEPTH-1);
  1629.    }
  1630.  
  1631.  
  1632. static void RGBEditor_BlankSampleBox(RGBEditor *this)
  1633.    {
  1634.    if (this->hidden)
  1635.       return ;
  1636.  
  1637.    Cursor_Hide();
  1638.    fillrect(this->x+2+CEditor_WIDTH+1+1, this->y+2+1, RGBEditor_BWIDTH-2, RGBEditor_BDEPTH-2, bg_color);
  1639.    Cursor_Show();
  1640.    }
  1641.  
  1642.  
  1643. static void RGBEditor_Update(RGBEditor *this)
  1644.    {
  1645.    int x1 = this->x+2+CEditor_WIDTH+1+1,
  1646.        y1 = this->y+2+1;
  1647.  
  1648.    if (this->hidden)
  1649.       return ;
  1650.  
  1651.    Cursor_Hide();
  1652.  
  1653.    if ( this->pal >= colors )
  1654.       {
  1655.       fillrect(x1, y1, RGBEditor_BWIDTH-2, RGBEditor_BDEPTH-2, bg_color);
  1656.       draw_diamond(x1+(RGBEditor_BWIDTH-5)/2, y1+(RGBEditor_BDEPTH-5)/2, fg_color);
  1657.       }
  1658.  
  1659.    else if ( is_reserved(this->pal) )
  1660.       {
  1661.       int x2 = x1+RGBEditor_BWIDTH-3,
  1662.       y2 = y1+RGBEditor_BDEPTH-3;
  1663.  
  1664.       fillrect(x1, y1, RGBEditor_BWIDTH-2, RGBEditor_BDEPTH-2, bg_color);
  1665.       draw_line(x1, y1, x2, y2, fg_color);
  1666.       draw_line(x1, y2, x2, y1, fg_color);
  1667.       }
  1668.    else
  1669.       fillrect(x1, y1, RGBEditor_BWIDTH-2, RGBEditor_BDEPTH-2, this->pal);
  1670.  
  1671.    CEditor_Draw(this->color[0]);
  1672.    CEditor_Draw(this->color[1]);
  1673.    CEditor_Draw(this->color[2]);
  1674.    Cursor_Show();
  1675.    }
  1676.  
  1677.  
  1678. static void RGBEditor_Draw(RGBEditor *this)
  1679.    {
  1680.    if (this->hidden)
  1681.       return ;
  1682.  
  1683.    Cursor_Hide();
  1684.    drect(this->x, this->y, RGBEditor_WIDTH, RGBEditor_DEPTH);
  1685.    fillrect(this->x+1, this->y+1, RGBEditor_WIDTH-2, RGBEditor_DEPTH-2, bg_color);
  1686.    rect(this->x+1+CEditor_WIDTH+2, this->y+2, RGBEditor_BWIDTH, RGBEditor_BDEPTH, fg_color);
  1687.    RGBEditor_Update(this);
  1688.    Cursor_Show();
  1689.    }
  1690.  
  1691.  
  1692. static int RGBEditor_Edit(RGBEditor *this)
  1693.    {
  1694.    int key;
  1695.  
  1696.    this->done = FALSE;
  1697.  
  1698.    if (!this->hidden)
  1699.       {
  1700.       Cursor_Hide();
  1701.       rect(this->x, this->y, RGBEditor_WIDTH, RGBEditor_DEPTH, fg_color);
  1702.       Cursor_Show();
  1703.       }
  1704.  
  1705.    while ( !this->done )
  1706.       key = CEditor_Edit( this->color[this->curr] );
  1707.  
  1708.    if (!this->hidden)
  1709.       {
  1710.       Cursor_Hide();
  1711.       drect(this->x, this->y, RGBEditor_WIDTH, RGBEditor_DEPTH);
  1712.       Cursor_Show();
  1713.       }
  1714.  
  1715.    return (key);
  1716.    }
  1717.  
  1718.  
  1719. static void RGBEditor_SetRGB(RGBEditor *this, int pal, PALENTRY *rgb)
  1720.    {
  1721.    this->pal = pal;
  1722.    CEditor_SetVal(this->color[0], rgb->red);
  1723.    CEditor_SetVal(this->color[1], rgb->green);
  1724.    CEditor_SetVal(this->color[2], rgb->blue);
  1725.    }
  1726.  
  1727.  
  1728. static PALENTRY RGBEditor_GetRGB(RGBEditor *this)
  1729.    {
  1730.    PALENTRY pal;
  1731.  
  1732.    pal.red   = CEditor_GetVal(this->color[0]);
  1733.    pal.green = CEditor_GetVal(this->color[1]);
  1734.    pal.blue  = CEditor_GetVal(this->color[2]);
  1735.  
  1736.    return(pal);
  1737.    }
  1738.  
  1739.  
  1740.  
  1741. /*
  1742.  * Class:     PalTable
  1743.  *
  1744.  * Purpose:   This is where it all comes together.  Creates the two RGBEditors
  1745.  *          and the palette. Moves the cursor, hides/restores the screen,
  1746.  *          handles (S)hading, (C)opying, e(X)clude mode, the "Y" exclusion
  1747.  *          mode, (Z)oom option, (H)ide palette, rotation, etc.
  1748.  *
  1749.  */
  1750.  
  1751. enum stored_at_values
  1752.    {
  1753.    NOWHERE,
  1754.    DISK,
  1755.    MEMORY
  1756.    } ;
  1757.  
  1758. /*
  1759.  
  1760. Modes:
  1761.    Auto:          "A", " "
  1762.    Exclusion:     "X", "Y", " "
  1763.    Freestyle:     "F", " "
  1764.    S(t)ripe mode: "T", " "
  1765.  
  1766. */
  1767.  
  1768.  
  1769.  
  1770. struct  _PalTable
  1771.    {
  1772.    int         x, y;
  1773.    int         csize;
  1774.    int         active;   /* which RGBEditor is active (0,1) */
  1775.    int         curr[2];
  1776.    RGBEditor    *rgb[2];
  1777.    MoveBox      *movebox;
  1778.    BOOLEAN     done;
  1779.    BOOLEAN     exclude;
  1780.    BOOLEAN     auto_select;
  1781.    PALENTRY     pal[256];
  1782.    FILE         *undo_file;
  1783.    BOOLEAN       curr_changed;
  1784.    int           num_redo;
  1785.    int         hidden;
  1786.    int         stored_at;
  1787.    FILE         *file;
  1788.    char far     *memory;
  1789.  
  1790.    PALENTRY far *save_pal[8];
  1791.  
  1792.    PALENTRY      fs_color;
  1793.    int           top,bottom; /* top and bottom colours of freestyle band */
  1794.    int           bandwidth; /*size of freestyle colour band */
  1795.    BOOLEAN       freestyle;
  1796.    } ;
  1797.  
  1798. #define PalTable struct _PalTable
  1799.  
  1800. /* private: */
  1801.  
  1802.    static void    PalTable__DrawStatus  (PalTable *this, BOOLEAN stripe_mode);
  1803.    static void      PalTable__HlPal       (PalTable *this, int pnum, int color);
  1804.    static void      PalTable__Draw        (PalTable *this);
  1805.    static BOOLEAN PalTable__SetCurr     (PalTable *this, int which, int curr);
  1806.    static BOOLEAN PalTable__MemoryAlloc (PalTable *this, long size);
  1807.    static void      PalTable__SaveRect    (PalTable *this);
  1808.    static void      PalTable__RestoreRect (PalTable *this);
  1809.    static void      PalTable__SetPos      (PalTable *this, int x, int y);
  1810.    static void      PalTable__SetCSize    (PalTable *this, int csize);
  1811.    static int      PalTable__GetCursorColor(PalTable *this);
  1812.    static void      PalTable__DoCurs      (PalTable *this, int key);
  1813.    static void      PalTable__Rotate      (PalTable *this, int dir, int lo, int hi);
  1814.    static void      PalTable__UpdateDAC   (PalTable *this);
  1815.    static void    PalTable__other_key   (int key, RGBEditor *rgb, VOIDPTR info);
  1816.    static void    PalTable__SaveUndoData(PalTable *this, int first, int last);
  1817.    static void    PalTable__SaveUndoRotate(PalTable *this, int dir, int first, int last);
  1818.    static void    PalTable__UndoProcess (PalTable *this, int delta);
  1819.    static void    PalTable__Undo        (PalTable *this);
  1820.    static void    PalTable__Redo        (PalTable *this);
  1821.    static void    PalTable__change      (RGBEditor *rgb, VOIDPTR info);
  1822.  
  1823. /* public: */
  1824.  
  1825.    static PalTable *PalTable_Construct (void);
  1826.    static void        PalTable_Destroy   (PalTable *this);
  1827.    static void        PalTable_Process   (PalTable *this);
  1828.    static void        PalTable_SetHidden (PalTable *this, BOOLEAN hidden);
  1829.    static void        PalTable_Hide      (PalTable *this, RGBEditor *rgb, BOOLEAN hidden);
  1830.  
  1831.  
  1832. #define PalTable_PALX (1)
  1833. #define PalTable_PALY (2+RGBEditor_DEPTH+2)
  1834.  
  1835. #define UNDO_DATA        (1)
  1836. #define UNDO_DATA_SINGLE (2)
  1837. #define UNDO_ROTATE      (3)
  1838.  
  1839.  
  1840.  
  1841. /*  - Freestyle code - */
  1842.  
  1843.  
  1844. void PalTable__CalcTopBottom(PalTable *this)
  1845.    {
  1846.    if (this->curr[this->active] < this->bandwidth )
  1847.       this->bottom = 0;
  1848.    else
  1849.       this->bottom = (this->curr[this->active]) - this->bandwidth;
  1850.  
  1851.    if (this->curr[this->active] > (255-this->bandwidth) )
  1852.       this->top = 255;
  1853.    else
  1854.       this->top = (this->curr[this->active]) + this->bandwidth;
  1855.    }
  1856.  
  1857.  
  1858. void PalTable__PutBand(PalTable *this, PALENTRY *pal)
  1859.    {
  1860.    int r,b,a;
  1861.  
  1862.   /* clip top and bottom values to stop them running off the end of the DAC */
  1863.  
  1864.    PalTable__CalcTopBottom(this);
  1865.  
  1866.   /* put bands either side of current colour */
  1867.  
  1868.    a = this->curr[this->active];
  1869.    b = this->bottom;
  1870.    r = this->top;
  1871.  
  1872.    pal[a] = this->fs_color;
  1873.  
  1874.    if (r != a && a != b)
  1875.       {
  1876.       mkpalrange(&pal[a], &pal[r], &pal[a], r-a, 1);
  1877.       mkpalrange(&pal[b], &pal[a], &pal[b], a-b, 1);
  1878.       }
  1879.  
  1880.    }
  1881.  
  1882.  
  1883. /* - Undo.Redo code - */
  1884.  
  1885.  
  1886. static void PalTable__SaveUndoData(PalTable *this, int first, int last)
  1887.    {
  1888.    int num;
  1889.  
  1890.    if ( this->undo_file == NULL )
  1891.       return ;
  1892.  
  1893.    num = (last - first) + 1;
  1894.  
  1895. #ifdef DEBUG_UNDO
  1896.    mprintf("%6ld Writing Undo DATA from %d to %d (%d)", ftell(this->undo_file), first, last, num);
  1897. #endif
  1898.  
  1899.    fseek(this->undo_file, 0, SEEK_CUR);
  1900.    if ( num == 1 )
  1901.       {
  1902.       putc(UNDO_DATA_SINGLE, this->undo_file);
  1903.       putc(first, this->undo_file);
  1904.       fwrite(this->pal+first, 3, 1, this->undo_file);
  1905.       putw( 1 + 1 + 3 + sizeof(int), this->undo_file);
  1906.       }
  1907.    else
  1908.       {
  1909.       putc(UNDO_DATA, this->undo_file);
  1910.       putc(first, this->undo_file);
  1911.       putc(last,  this->undo_file);
  1912.       fwrite(this->pal+first, 3, num, this->undo_file);
  1913.       putw(1 + 2 + (num*3) + sizeof(int), this->undo_file);
  1914.       }
  1915.  
  1916.    this->num_redo = 0;
  1917.    }
  1918.  
  1919.  
  1920. static void PalTable__SaveUndoRotate(PalTable *this, int dir, int first, int last)
  1921.    {
  1922.    if ( this->undo_file == NULL )
  1923.       return ;
  1924.  
  1925. #ifdef DEBUG_UNDO
  1926.    mprintf("%6ld Writing Undo ROTATE of %d from %d to %d", ftell(this->undo_file), dir, first, last);
  1927. #endif
  1928.  
  1929.    fseek(this->undo_file, 0, SEEK_CUR);
  1930.    putc(UNDO_ROTATE, this->undo_file);
  1931.    putc(first, this->undo_file);
  1932.    putc(last,  this->undo_file);
  1933.    putw(dir, this->undo_file);
  1934.    putw(1 + 2 + sizeof(int), this->undo_file);
  1935.  
  1936.    this->num_redo = 0;
  1937.    }
  1938.  
  1939.  
  1940. static void PalTable__UndoProcess(PalTable *this, int delta)   /* undo/redo common code */
  1941.    {              /* delta = -1 for undo, +1 for redo */
  1942.    int cmd = getc(this->undo_file);
  1943.  
  1944.    switch( cmd )
  1945.       {
  1946.       case UNDO_DATA:
  1947.       case UNDO_DATA_SINGLE:
  1948.          {
  1949.          int      first, last, num;
  1950.          PALENTRY temp[256];
  1951.  
  1952.          if ( cmd == UNDO_DATA )
  1953.             {
  1954.             first = (unsigned char)getc(this->undo_file);
  1955.             last  = (unsigned char)getc(this->undo_file);
  1956.             }
  1957.          else  /* UNDO_DATA_SINGLE */
  1958.             first = last = (unsigned char)getc(this->undo_file);
  1959.  
  1960.          num = (last - first) + 1;
  1961.  
  1962. #ifdef DEBUG_UNDO
  1963.          mprintf("          Reading DATA from %d to %d", first, last);
  1964. #endif
  1965.  
  1966.          fread(temp, 3, num, this->undo_file);
  1967.  
  1968.          fseek(this->undo_file, -(num*3), SEEK_CUR);  /* go to start of undo/redo data */
  1969.          fwrite(this->pal+first, 3, num, this->undo_file);  /* write redo/undo data */
  1970.  
  1971.          memmove(this->pal+first, temp, num*3);
  1972.  
  1973.          PalTable__UpdateDAC(this);
  1974.  
  1975.          RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  1976.          RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  1977.          RGBEditor_Update(this->rgb[0]);
  1978.          RGBEditor_Update(this->rgb[1]);
  1979.          break;
  1980.          }
  1981.  
  1982.       case UNDO_ROTATE:
  1983.          {
  1984.          int first = (unsigned char)getc(this->undo_file);
  1985.          int last  = (unsigned char)getc(this->undo_file);
  1986.          int dir   = getw(this->undo_file);
  1987.  
  1988. #ifdef DEBUG_UNDO
  1989.          mprintf("          Reading ROTATE of %d from %d to %d", dir, first, last);
  1990. #endif
  1991.          PalTable__Rotate(this, delta*dir, first, last);
  1992.          break;
  1993.          }
  1994.  
  1995.       default:
  1996. #ifdef DEBUG_UNDO
  1997.          mprintf("          Unknown command: %d", cmd);
  1998. #endif
  1999.          break;
  2000.       }
  2001.  
  2002.    fseek(this->undo_file, 0, SEEK_CUR);  /* to put us in read mode */
  2003.    getw(this->undo_file);  /* read size */
  2004.    }
  2005.  
  2006.  
  2007. static void PalTable__Undo(PalTable *this)
  2008.    {
  2009.    int  size;
  2010.    long pos;
  2011.  
  2012.    if ( ftell(this->undo_file) <= 0  )   /* at beginning of file? */
  2013.       {                                  /*   nothing to undo -- exit */
  2014.       return ;
  2015.       }
  2016.  
  2017.    fseek(this->undo_file, -(int)sizeof(int), SEEK_CUR);  /* go back to get size */
  2018.  
  2019.    size = getw(this->undo_file);
  2020.    fseek(this->undo_file, -size, SEEK_CUR);   /* go to start of undo */
  2021.  
  2022. #ifdef DEBUG_UNDO
  2023.    mprintf("%6ld Undo:", ftell(this->undo_file));
  2024. #endif
  2025.  
  2026.    pos = ftell(this->undo_file);
  2027.  
  2028.    PalTable__UndoProcess(this, -1);
  2029.  
  2030.    fseek(this->undo_file, pos, SEEK_SET);   /* go to start of this block */
  2031.  
  2032.    ++this->num_redo;
  2033.    }
  2034.  
  2035.  
  2036. static void PalTable__Redo(PalTable *this)
  2037.    {
  2038.    if ( this->num_redo <= 0 )
  2039.       return ;
  2040.  
  2041. #ifdef DEBUG_UNDO
  2042.    mprintf("%6ld Redo:", ftell(this->undo_file));
  2043. #endif
  2044.  
  2045.    fseek(this->undo_file, 0, SEEK_CUR);  /* to make sure we are in "read" mode */
  2046.    PalTable__UndoProcess(this, 1);
  2047.  
  2048.    --this->num_redo;
  2049.    }
  2050.  
  2051.  
  2052. /* - everything else - */
  2053.  
  2054.  
  2055. #define STATUS_LEN (4)
  2056.  
  2057. static void PalTable__DrawStatus(PalTable *this, BOOLEAN stripe_mode)
  2058.    {
  2059.    int width = 1+(this->csize*16)+1+1;
  2060.  
  2061.    if ( !this->hidden && ( width - (RGBEditor_WIDTH*2+4) >= STATUS_LEN*8 ) )
  2062.       {
  2063.       int x = this->x + 2 + RGBEditor_WIDTH,
  2064.           y = this->y + PalTable_PALY - 10;
  2065.  
  2066.       Cursor_Hide();
  2067.  
  2068.       displayc(x+(0*8), y, fg_color, bg_color, (this->auto_select) ? 'A' : 254);
  2069.       displayc(x+(1*8), y, fg_color, bg_color, (this->exclude==1)  ? 'X' :
  2070.                                                (this->exclude==2)  ? 'Y' : 254);
  2071.       displayc(x+(2*8), y, fg_color, bg_color, (this->freestyle)   ? 'F' : 254);
  2072.       displayc(x+(3*8), y, fg_color, bg_color, (stripe_mode)       ? 'T' : 254);
  2073.  
  2074.       Cursor_Show();
  2075.       }
  2076.    }
  2077.  
  2078.  
  2079. static void PalTable__HlPal(PalTable *this, int pnum, int color)
  2080.    {
  2081.    int x    = this->x + PalTable_PALX + (pnum%16)*this->csize,
  2082.        y    = this->y + PalTable_PALY + (pnum/16)*this->csize,
  2083.        size = this->csize;
  2084.  
  2085.    if (this->hidden)
  2086.       return ;
  2087.  
  2088.    Cursor_Hide();
  2089.  
  2090.    if (color < 0)
  2091.       drect(x, y, size+1, size+1);
  2092.    else
  2093.       rect(x, y, size+1, size+1, color);
  2094.  
  2095.    Cursor_Show();
  2096.    }
  2097.  
  2098.  
  2099. static void PalTable__Draw(PalTable *this)
  2100.    {
  2101.    int pal;
  2102.    int xoff, yoff;
  2103.    int width;
  2104.  
  2105.    if (this->hidden)
  2106.       return ;
  2107.  
  2108.    Cursor_Hide();
  2109.  
  2110.    width = 1+(this->csize*16)+1+1;
  2111.  
  2112.    rect(this->x, this->y, width, 2+RGBEditor_DEPTH+2+(this->csize*16)+1+1, fg_color);
  2113.  
  2114.    fillrect(this->x+1, this->y+1, width-2, 2+RGBEditor_DEPTH+2+(this->csize*16)+1+1-2, bg_color);
  2115.  
  2116.    hline(this->x, this->y+PalTable_PALY-1, width, fg_color);
  2117.  
  2118.    if ( width - (RGBEditor_WIDTH*2+4) >= TITLE_LEN*8 )
  2119.       {
  2120.       int center = (width - TITLE_LEN*8) / 2;
  2121.  
  2122.       displayf(this->x+center, this->y+2+RGBEditor_DEPTH/2-4, fg_color, bg_color, TITLE);
  2123.       }
  2124.  
  2125.    RGBEditor_Draw(this->rgb[0]);
  2126.    RGBEditor_Draw(this->rgb[1]);
  2127.  
  2128.    for (pal=0; pal<256; pal++)
  2129.       {
  2130.       xoff = PalTable_PALX + (pal%16) * this->csize;
  2131.       yoff = PalTable_PALY + (pal/16) * this->csize;
  2132.  
  2133.       if ( pal >= colors )
  2134.      {
  2135.      fillrect(this->x + xoff + 1, this->y + yoff + 1, this->csize-1, this->csize-1, bg_color);
  2136.      draw_diamond(this->x + xoff + this->csize/2 - 1, this->y + yoff + this->csize/2 - 1, fg_color);
  2137.      }
  2138.  
  2139.       else if ( is_reserved(pal) )
  2140.      {
  2141.      int x1 = this->x + xoff + 1,
  2142.          y1 = this->y + yoff + 1,
  2143.          x2 = x1 + this->csize - 2,
  2144.          y2 = y1 + this->csize - 2;
  2145.      fillrect(this->x + xoff + 1, this->y + yoff + 1, this->csize-1, this->csize-1, bg_color);
  2146.      draw_line(x1, y1, x2, y2, fg_color);
  2147.      draw_line(x1, y2, x2, y1, fg_color);
  2148.      }
  2149.       else
  2150.      fillrect(this->x + xoff + 1, this->y + yoff + 1, this->csize-1, this->csize-1, pal);
  2151.  
  2152.       }
  2153.  
  2154.    if (this->active == 0)
  2155.       {
  2156.       PalTable__HlPal(this, this->curr[1], -1);
  2157.       PalTable__HlPal(this, this->curr[0], fg_color);
  2158.       }
  2159.    else
  2160.       {
  2161.       PalTable__HlPal(this, this->curr[0], -1);
  2162.       PalTable__HlPal(this, this->curr[1], fg_color);
  2163.       }
  2164.  
  2165.    PalTable__DrawStatus(this, FALSE);
  2166.  
  2167.    Cursor_Show();
  2168.    }
  2169.  
  2170.  
  2171.  
  2172. static BOOLEAN PalTable__SetCurr(PalTable *this, int which, int curr)
  2173.    {
  2174.    BOOLEAN redraw = (which < 0) ? TRUE : FALSE;
  2175.  
  2176.    if ( redraw )
  2177.       {
  2178.       which = this->active;
  2179.       curr = this->curr[which];
  2180.       }
  2181.    else
  2182.       if ( curr == this->curr[which] || curr < 0 )
  2183.      return (FALSE);
  2184.  
  2185.    Cursor_Hide();
  2186.  
  2187.    PalTable__HlPal(this, this->curr[0], bg_color);
  2188.    PalTable__HlPal(this, this->curr[1], bg_color);
  2189.    PalTable__HlPal(this, this->top,     bg_color);
  2190.    PalTable__HlPal(this, this->bottom,  bg_color);
  2191.  
  2192.    if ( this->freestyle )
  2193.       {
  2194.       this->curr[which] = curr;
  2195.  
  2196.       PalTable__CalcTopBottom(this);
  2197.  
  2198.       PalTable__HlPal(this, this->top,    -1);
  2199.       PalTable__HlPal(this, this->bottom, -1);
  2200.       PalTable__HlPal(this, this->curr[this->active], fg_color);
  2201.  
  2202.       RGBEditor_SetRGB(this->rgb[which], this->curr[which], &this->fs_color);
  2203.       RGBEditor_Update(this->rgb[which]);
  2204.  
  2205.       PalTable__UpdateDAC(this);
  2206.  
  2207.       Cursor_Show();
  2208.  
  2209.       return (TRUE);
  2210.       }
  2211.  
  2212.    this->curr[which] = curr;
  2213.  
  2214.    if (this->curr[0] != this->curr[1])
  2215.       PalTable__HlPal(this, this->curr[this->active==0?1:0], -1);
  2216.    PalTable__HlPal(this, this->curr[this->active], fg_color);
  2217.  
  2218.    RGBEditor_SetRGB(this->rgb[which], this->curr[which], &(this->pal[this->curr[which]]));
  2219.  
  2220.    if (redraw)
  2221.       {
  2222.       int other = (which==0) ? 1 : 0;
  2223.       RGBEditor_SetRGB(this->rgb[other], this->curr[other], &(this->pal[this->curr[other]]));
  2224.       RGBEditor_Update(this->rgb[0]);
  2225.       RGBEditor_Update(this->rgb[1]);
  2226.       }
  2227.    else
  2228.       RGBEditor_Update(this->rgb[which]);
  2229.  
  2230.    if (this->exclude)
  2231.       PalTable__UpdateDAC(this);
  2232.  
  2233.    Cursor_Show();
  2234.  
  2235.    this->curr_changed = FALSE;
  2236.  
  2237.    return(TRUE);
  2238.    }
  2239.  
  2240.  
  2241. static BOOLEAN PalTable__MemoryAlloc(PalTable *this, long size)
  2242.    {
  2243.    char far *temp;
  2244.  
  2245.    if (debugflag = 420)
  2246.       {
  2247.       this->stored_at = NOWHERE;
  2248.       return (FALSE);   /* can't do it */
  2249.       }
  2250.    temp = farmemalloc(FAR_RESERVE);   /* minimum free space */
  2251.  
  2252.    if (temp == NULL)
  2253.       {
  2254.       this->stored_at = NOWHERE;
  2255.       return (FALSE);   /* can't do it */
  2256.       }
  2257.  
  2258.    this->memory = farmemalloc( size );
  2259.  
  2260.    farmemfree(temp);
  2261.  
  2262.    if ( this->memory == NULL )
  2263.       {
  2264.       this->stored_at = NOWHERE;
  2265.       return (FALSE);
  2266.       }
  2267.    else
  2268.       {
  2269.       this->stored_at = MEMORY;
  2270.       return (TRUE);
  2271.       }
  2272.    }
  2273.  
  2274.  
  2275. static void PalTable__SaveRect(PalTable *this)
  2276.    {
  2277.    char buff[MAX_WIDTH];
  2278.    int  width = PalTable_PALX + this->csize*16 + 1 + 1,
  2279.         depth = PalTable_PALY + this->csize*16 + 1 + 1;
  2280.    int  yoff;
  2281.  
  2282.  
  2283.    /* first, do any de-allocationg */
  2284.  
  2285.    switch( this->stored_at )
  2286.       {
  2287.       case NOWHERE:
  2288.      break;
  2289.  
  2290.       case DISK:
  2291.      break;
  2292.  
  2293.       case MEMORY:
  2294.      if (this->memory != NULL)
  2295.         farmemfree(this->memory);
  2296.      this->memory = NULL;
  2297.      break;
  2298.       } ;
  2299.  
  2300.    /* allocate space and store the rect */
  2301.  
  2302.    if ( PalTable__MemoryAlloc(this, (long)width*depth) )
  2303.       {
  2304.       char far  *ptr = this->memory;
  2305.       char far  *bufptr = buff; /* MSC needs this indirection to get it right */
  2306.  
  2307.       Cursor_Hide();
  2308.       for (yoff=0; yoff<depth; yoff++)
  2309.      {
  2310.      getrow(this->x, this->y+yoff, width, buff);
  2311.      hline (this->x, this->y+yoff, width, bg_color);
  2312.      movedata(FP_SEG(bufptr), FP_OFF(bufptr), FP_SEG(ptr), FP_OFF(ptr), width);
  2313.      ptr = (char far *)normalize(ptr+width);
  2314.      }
  2315.       Cursor_Show();
  2316.       }
  2317.  
  2318.    else /* to disk */
  2319.       {
  2320.       this->stored_at = DISK;
  2321.  
  2322.       if ( this->file == NULL )
  2323.      {
  2324.      this->file = fopen(scrnfile, "w+b");
  2325.      if (this->file == NULL)
  2326.         {
  2327.         this->stored_at = NOWHERE;
  2328.         buzzer(3);
  2329.         return ;
  2330.         }
  2331.      }
  2332.  
  2333.       rewind(this->file);
  2334.       Cursor_Hide();
  2335.       for (yoff=0; yoff<depth; yoff++)
  2336.      {
  2337.      getrow(this->x, this->y+yoff, width, buff);
  2338.      hline (this->x, this->y+yoff, width, bg_color);
  2339.      if ( fwrite(buff, width, 1, this->file) != 1 )
  2340.         {
  2341.         buzzer(3);
  2342.         break;
  2343.         }
  2344.      }
  2345.       Cursor_Show();
  2346.       }
  2347.  
  2348.    }
  2349.  
  2350.  
  2351. static void PalTable__RestoreRect(PalTable *this)
  2352.    {
  2353.    char buff[MAX_WIDTH];
  2354.    int  width = PalTable_PALX + this->csize*16 + 1 + 1,
  2355.         depth = PalTable_PALY + this->csize*16 + 1 + 1;
  2356.    int  yoff;
  2357.  
  2358.    if (this->hidden)
  2359.       return;
  2360.  
  2361.    switch ( this->stored_at )
  2362.       {
  2363.       case DISK:
  2364.      rewind(this->file);
  2365.      Cursor_Hide();
  2366.      for (yoff=0; yoff<depth; yoff++)
  2367.         {
  2368.         if ( fread(buff, width, 1, this->file) != 1 )
  2369.            {
  2370.            buzzer(3);
  2371.            break;
  2372.            }
  2373.         putrow(this->x, this->y+yoff, width, buff);
  2374.         }
  2375.      Cursor_Show();
  2376.      break;
  2377.  
  2378.       case MEMORY:
  2379.      {
  2380.      char far  *ptr = this->memory;
  2381.      char far  *bufptr = buff; /* MSC needs this indirection to get it right */
  2382.  
  2383.      Cursor_Hide();
  2384.      for (yoff=0; yoff<depth; yoff++)
  2385.         {
  2386.         movedata(FP_SEG(ptr), FP_OFF(ptr), FP_SEG(bufptr), FP_OFF(bufptr), width);
  2387.         putrow(this->x, this->y+yoff, width, buff);
  2388.         ptr = (char far *)normalize(ptr+width);
  2389.         }
  2390.      Cursor_Show();
  2391.      break;
  2392.      }
  2393.  
  2394.       case NOWHERE:
  2395.      break;
  2396.       } /* switch */
  2397.    }
  2398.  
  2399.  
  2400. static void PalTable__SetPos(PalTable *this, int x, int y)
  2401.    {
  2402.    int width = PalTable_PALX + this->csize*16 + 1 + 1;
  2403.  
  2404.    this->x = x;
  2405.    this->y = y;
  2406.  
  2407.    RGBEditor_SetPos(this->rgb[0], x+2, y+2);
  2408.    RGBEditor_SetPos(this->rgb[1], x+width-2-RGBEditor_WIDTH, y+2);
  2409.    }
  2410.  
  2411.  
  2412. static void PalTable__SetCSize(PalTable *this, int csize)
  2413.    {
  2414.    this->csize = csize;
  2415.    PalTable__SetPos(this, this->x, this->y);
  2416.    }
  2417.  
  2418.  
  2419. static int PalTable__GetCursorColor(PalTable *this)
  2420.    {
  2421.    int x     = Cursor_GetX(),
  2422.        y     = Cursor_GetY(),
  2423.        size;
  2424.    int color = getcolor(x, y);
  2425.  
  2426.    if ( is_reserved(color) )
  2427.       {
  2428.       if ( is_in_box(x, y, this->x, this->y, 1+(this->csize*16)+1+1, 2+RGBEditor_DEPTH+2+(this->csize*16)+1+1) )
  2429.      {  /* is the cursor over the editor? */
  2430.      x -= this->x + PalTable_PALX;
  2431.      y -= this->y + PalTable_PALY;
  2432.      size = this->csize;
  2433.  
  2434.      if (x < 0 || y < 0 || x > size*16 || y > size*16)
  2435.         return (-1);
  2436.  
  2437.      if ( x == size*16 )
  2438.         --x;
  2439.      if ( y == size*16 )
  2440.         --y;
  2441.  
  2442.      return ( (y/size)*16 + x/size );
  2443.      }
  2444.       else
  2445.      return (color);
  2446.       }
  2447.  
  2448.    return (color);
  2449.    }
  2450.  
  2451.  
  2452.  
  2453. #define CURS_INC 1
  2454.  
  2455. static void PalTable__DoCurs(PalTable *this, int key)
  2456.    {
  2457.    BOOLEAN done  = FALSE;
  2458.    BOOLEAN first = TRUE;
  2459.    int       xoff  = 0,
  2460.        yoff  = 0;
  2461.  
  2462.    while ( !done )
  2463.       {
  2464.       switch(key)
  2465.      {
  2466.      case RIGHT_ARROW_2:     xoff += CURS_INC*4;   break;
  2467.      case RIGHT_ARROW:     xoff += CURS_INC;     break;
  2468.      case LEFT_ARROW_2:     xoff -= CURS_INC*4;   break;
  2469.      case LEFT_ARROW:     xoff -= CURS_INC;     break;
  2470.      case DOWN_ARROW_2:     yoff += CURS_INC*4;   break;
  2471.      case DOWN_ARROW:     yoff += CURS_INC;     break;
  2472.      case UP_ARROW_2:     yoff -= CURS_INC*4;   break;
  2473.      case UP_ARROW:      yoff -= CURS_INC;     break;
  2474.  
  2475.      default:
  2476.         done = TRUE;
  2477.      }
  2478.  
  2479.       if (!done)
  2480.      {
  2481.      if (!first)
  2482.         getakey();         /* delete key from buffer */
  2483.      else
  2484.         first = FALSE;
  2485.      key = keypressed();   /* peek at the next one... */
  2486.      }
  2487.       }
  2488.  
  2489.    Cursor_Move(xoff, yoff);
  2490.  
  2491.    if (this->auto_select)
  2492.       PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2493.    }
  2494.  
  2495.  
  2496. #ifdef __TURBOC__
  2497. #   pragma argsused
  2498. #endif
  2499.  
  2500. static void PalTable__change(RGBEditor *rgb, VOIDPTR info)
  2501.    {
  2502.    PalTable *this = (PalTable *)info;
  2503.    int       pnum = this->curr[this->active];
  2504.  
  2505.    if ( this->freestyle )
  2506.       {
  2507.       this->fs_color = RGBEditor_GetRGB(rgb);
  2508.       PalTable__UpdateDAC(this);
  2509.       return ;
  2510.       }
  2511.  
  2512.    if ( !this->curr_changed )
  2513.       {
  2514.       PalTable__SaveUndoData(this, pnum, pnum);
  2515.       this->curr_changed = TRUE;
  2516.       }
  2517.  
  2518.    this->pal[pnum] = RGBEditor_GetRGB(rgb);
  2519.  
  2520.    if (this->curr[0] == this->curr[1])
  2521.       {
  2522.       int      other = this->active==0 ? 1 : 0;
  2523.       PALENTRY color;
  2524.  
  2525.       color = RGBEditor_GetRGB(this->rgb[this->active]);
  2526.       RGBEditor_SetRGB(this->rgb[other], this->curr[other], &color);
  2527.  
  2528.       Cursor_Hide();
  2529.       RGBEditor_Update(this->rgb[other]);
  2530.       Cursor_Show();
  2531.       }
  2532.  
  2533.    }
  2534.  
  2535.  
  2536. static void PalTable__UpdateDAC(PalTable *this)
  2537.    {
  2538.    if ( this->exclude )
  2539.       {
  2540.       memset(dacbox, 0, 256*3);
  2541.       if (this->exclude == 1)
  2542.      {
  2543.      int a = this->curr[this->active];
  2544.      memmove(dacbox[a], &this->pal[a], 3);
  2545.      }
  2546.       else
  2547.      {
  2548.      int a = this->curr[0],
  2549.          b = this->curr[1];
  2550.  
  2551.      if (a>b)
  2552.         {
  2553.         int t=a;
  2554.         a=b;
  2555.         b=t;
  2556.         }
  2557.  
  2558.      memmove(dacbox[a], &this->pal[a], 3*(1+(b-a)));
  2559.      }
  2560.       }
  2561.    else
  2562.       {
  2563.       memmove(dacbox[0], this->pal, 3*colors);
  2564.  
  2565.       if ( this->freestyle )
  2566.          PalTable__PutBand(this, (PALENTRY *)dacbox);   /* apply band to dacbox */
  2567.       }
  2568.  
  2569.    if ( !this->hidden )
  2570.       {
  2571.       if (inverse)
  2572.      {
  2573.      memset(dacbox[fg_color], 0, 3);     /* dacbox[fg] = (0,0,0) */
  2574.      memset(dacbox[bg_color], 48, 3);     /* dacbox[bg] = (48,48,48) */
  2575.      }
  2576.       else
  2577.      {
  2578.      memset(dacbox[bg_color], 0, 3);     /* dacbox[bg] = (0,0,0) */
  2579.      memset(dacbox[fg_color], 48, 3);     /* dacbox[fg] = (48,48,48) */
  2580.      }
  2581.       }
  2582.  
  2583.    spindac(0,1);
  2584.    }
  2585.  
  2586.  
  2587. static void PalTable__Rotate(PalTable *this, int dir, int lo, int hi)
  2588.    {
  2589.  
  2590.    rotatepal(this->pal, dir, lo, hi);
  2591.  
  2592.    Cursor_Hide();
  2593.  
  2594.    /* update the DAC.  */
  2595.  
  2596.    PalTable__UpdateDAC(this);
  2597.  
  2598.    /* update the editors. */
  2599.  
  2600.    RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  2601.    RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  2602.    RGBEditor_Update(this->rgb[0]);
  2603.    RGBEditor_Update(this->rgb[1]);
  2604.  
  2605.    Cursor_Show();
  2606.    }
  2607.  
  2608.  
  2609. static void PalTable__other_key(int key, RGBEditor *rgb, VOIDPTR info)
  2610.    {
  2611.    PalTable *this = (PalTable *)info;
  2612.  
  2613.    switch(key)
  2614.       {
  2615.       case '\\':    /* move/resize */
  2616.      {
  2617.      if (this->hidden)
  2618.         break;         /* cannot move a hidden pal */
  2619.      Cursor_Hide();
  2620.      PalTable__RestoreRect(this);
  2621.      MoveBox_SetPos(this->movebox, this->x, this->y);
  2622.      MoveBox_SetCSize(this->movebox, this->csize);
  2623.      if ( MoveBox_Process(this->movebox) )
  2624.         {
  2625.         if ( MoveBox_ShouldHide(this->movebox) )
  2626.            PalTable_SetHidden(this, TRUE);
  2627.         else if ( MoveBox_Moved(this->movebox) )
  2628.            {
  2629.            PalTable__SetPos(this, MoveBox_X(this->movebox), MoveBox_Y(this->movebox));
  2630.            PalTable__SetCSize(this, MoveBox_CSize(this->movebox));
  2631.            PalTable__SaveRect(this);
  2632.            }
  2633.         }
  2634.      PalTable__Draw(this);
  2635.      Cursor_Show();
  2636.  
  2637.      RGBEditor_SetDone(this->rgb[this->active], TRUE);
  2638.  
  2639.      if (this->auto_select)
  2640.         PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2641.      break;
  2642.      }
  2643.  
  2644.       case 'Y':    /* exclude range */
  2645.       case 'y':
  2646.      if ( this->exclude==2 )
  2647.         this->exclude = 0;
  2648.      else
  2649.         this->exclude = 2;
  2650.      PalTable__UpdateDAC(this);
  2651.          PalTable__DrawStatus(this, FALSE);
  2652.      break;
  2653.  
  2654.       case 'X':
  2655.       case 'x':     /* exclude current entry */
  2656.      if ( this->exclude==1 )
  2657.         this->exclude = 0;
  2658.      else
  2659.         this->exclude = 1;
  2660.      PalTable__UpdateDAC(this);
  2661.          PalTable__DrawStatus(this, FALSE);
  2662.      break;
  2663.  
  2664.       case RIGHT_ARROW:
  2665.       case LEFT_ARROW:
  2666.       case UP_ARROW:
  2667.       case DOWN_ARROW:
  2668.       case RIGHT_ARROW_2:
  2669.       case LEFT_ARROW_2:
  2670.       case UP_ARROW_2:
  2671.       case DOWN_ARROW_2:
  2672.      PalTable__DoCurs(this, key);
  2673.      break;
  2674.  
  2675.       case ESC:
  2676.      this->done = TRUE;
  2677.      RGBEditor_SetDone(rgb, TRUE);
  2678.      break;
  2679.  
  2680.       case ' ':     /* select the other palette register */
  2681.      this->active = (this->active==0) ? 1 : 0;
  2682.      if (this->auto_select)
  2683.         PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2684.       else
  2685.         PalTable__SetCurr(this, -1, 0);
  2686.  
  2687.      if (this->exclude || this->freestyle)
  2688.         PalTable__UpdateDAC(this);
  2689.  
  2690.      RGBEditor_SetDone(rgb, TRUE);
  2691.      break;
  2692.  
  2693.       case ENTER:    /* set register to color under cursor.  useful when not */
  2694.       case ENTER_2:  /* in auto_select mode */
  2695.  
  2696.          if ( this->freestyle )
  2697.             {
  2698.             PalTable__SaveUndoData(this, this->bottom, this->top);
  2699.             PalTable__PutBand(this, this->pal);
  2700.             }
  2701.  
  2702.      PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2703.  
  2704.      if (this->exclude || this->freestyle )
  2705.         PalTable__UpdateDAC(this);
  2706.  
  2707.      RGBEditor_SetDone(rgb, TRUE);
  2708.      break;
  2709.  
  2710.       case 'D':    /* copy (Duplicate?) color in inactive to color in active */
  2711.       case 'd':
  2712.      {
  2713.      int   a = this->active,
  2714.           b = (a==0) ? 1 : 0;
  2715.      PALENTRY t;
  2716.  
  2717.      t = RGBEditor_GetRGB(this->rgb[b]);
  2718.      Cursor_Hide();
  2719.  
  2720.      RGBEditor_SetRGB(this->rgb[a], this->curr[a], &t);
  2721.      RGBEditor_Update(this->rgb[a]);
  2722.      PalTable__change(this->rgb[a], this);
  2723.      PalTable__UpdateDAC(this);
  2724.  
  2725.      Cursor_Show();
  2726.      break;
  2727.      }
  2728.  
  2729.       case '=':    /* create a shade range between the two entries */
  2730.      {
  2731.      int a = this->curr[0],
  2732.          b = this->curr[1];
  2733.  
  2734.      if (a > b)
  2735.         {
  2736.         int t = a;
  2737.         a = b;
  2738.         b = t;
  2739.         }
  2740.  
  2741.          PalTable__SaveUndoData(this, a, b);
  2742.  
  2743.      if (a != b)
  2744.         {
  2745.         mkpalrange(&this->pal[a], &this->pal[b], &this->pal[a], b-a, 1);
  2746.         PalTable__UpdateDAC(this);
  2747.         }
  2748.  
  2749.      break;
  2750.      }
  2751.  
  2752.       case '!':    /* swap r<->g */
  2753.      {
  2754.      int a = this->curr[0],
  2755.          b = this->curr[1];
  2756.  
  2757.      if (a > b)
  2758.         {
  2759.         int t = a;
  2760.         a = b;
  2761.         b = t;
  2762.         }
  2763.  
  2764.          PalTable__SaveUndoData(this, a, b);
  2765.  
  2766.      if (a != b)
  2767.         {
  2768.         rotcolrg(&this->pal[a], b-a);
  2769.         PalTable__UpdateDAC(this);
  2770.         }
  2771.  
  2772.  
  2773.      break;
  2774.      }
  2775.  
  2776.       case '@':    /* swap g<->b */
  2777.      {
  2778.      int a = this->curr[0],
  2779.          b = this->curr[1];
  2780.  
  2781.      if (a > b)
  2782.         {
  2783.         int t = a;
  2784.         a = b;
  2785.         b = t;
  2786.         }
  2787.  
  2788.          PalTable__SaveUndoData(this, a, b);
  2789.  
  2790.      if (a != b)
  2791.         {
  2792.         rotcolgb(&this->pal[a], b-a);
  2793.         PalTable__UpdateDAC(this);
  2794.         }
  2795.  
  2796.      break;
  2797.      }
  2798.  
  2799.       case '#':    /* swap r<->b */
  2800.      {
  2801.      int a = this->curr[0],
  2802.          b = this->curr[1];
  2803.  
  2804.      if (a > b)
  2805.         {
  2806.         int t = a;
  2807.         a = b;
  2808.         b = t;
  2809.         }
  2810.  
  2811.          PalTable__SaveUndoData(this, a, b);
  2812.  
  2813.      if (a != b)
  2814.         {
  2815.         rotcolbr(&this->pal[a], b-a);
  2816.         PalTable__UpdateDAC(this);
  2817.         }
  2818.  
  2819.      break;
  2820.      }
  2821.  
  2822.  
  2823.       case 'T':
  2824.       case 't':   /* s(T)ripe mode */
  2825.      {
  2826.      int key;
  2827.  
  2828.      Cursor_Hide();
  2829.          PalTable__DrawStatus(this, TRUE);
  2830.      key = getakeynohelp();
  2831.          PalTable__DrawStatus(this, FALSE);
  2832.      Cursor_Show();
  2833.  
  2834.      if (key >= '1' && key <= '9')
  2835.         {
  2836.         int a = this->curr[0],
  2837.         b = this->curr[1];
  2838.  
  2839.         if (a > b)
  2840.            {
  2841.            int t = a;
  2842.            a = b;
  2843.            b = t;
  2844.            }
  2845.  
  2846.             PalTable__SaveUndoData(this, a, b);
  2847.  
  2848.         if (a != b)
  2849.            {
  2850.            mkpalrange(&this->pal[a], &this->pal[b], &this->pal[a], b-a, key-'0');
  2851.            PalTable__UpdateDAC(this);
  2852.            }
  2853.         }
  2854.  
  2855.      break;
  2856.      }
  2857.  
  2858.       case 'M':   /* set gamma */
  2859.       case 'm':
  2860.       {
  2861.           int i;
  2862.           char buf[20];
  2863.           sprintf(buf,"%.3f",1./gamma_val);
  2864.           stackscreen();
  2865.           i = field_prompt(0,"Enter gamma value",NULL,buf,20,NULL);
  2866.           unstackscreen();
  2867.           if (i != -1) {
  2868.           sscanf(buf,"%f",&gamma_val);
  2869.           if (gamma_val==0) {
  2870.               gamma_val = 0.0000000001;
  2871.           }
  2872.           gamma_val = 1./gamma_val;
  2873.           }
  2874.       }
  2875.       break;
  2876.       case 'A':   /* toggle auto-select mode */
  2877.       case 'a':
  2878.      this->auto_select = (this->auto_select) ? FALSE : TRUE;
  2879.      if (this->auto_select)
  2880.         {
  2881.         PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2882.         if (this->exclude)
  2883.            PalTable__UpdateDAC(this);
  2884.         }
  2885.          PalTable__DrawStatus(this, FALSE);
  2886.      break;
  2887.  
  2888.       case 'H':
  2889.       case 'h': /* toggle hide/display of palette editor */
  2890.      Cursor_Hide();
  2891.      PalTable_Hide(this, rgb, (BOOLEAN)((this->hidden) ? FALSE : TRUE));
  2892.      Cursor_Show();
  2893.      break;
  2894.  
  2895.       case '.':   /* rotate once */
  2896.       case ',':
  2897.      {
  2898.          int dir = (key=='.') ? 1 : -1;
  2899.  
  2900.          PalTable__SaveUndoRotate(this, dir, rotate_lo, rotate_hi);
  2901.      PalTable__Rotate(this, dir, rotate_lo, rotate_hi);
  2902.      break;
  2903.      }
  2904.  
  2905.       case '>':   /* continuous rotation (until a key is pressed) */
  2906.       case '<':
  2907.      {
  2908.          int  dir;
  2909.      long tick;
  2910.          int  diff = 0;
  2911.  
  2912.      Cursor_Hide();
  2913.  
  2914.      if ( !this->hidden )
  2915.         {
  2916.         RGBEditor_BlankSampleBox(this->rgb[0]);
  2917.         RGBEditor_BlankSampleBox(this->rgb[1]);
  2918.         RGBEditor_SetHidden(this->rgb[0], TRUE);
  2919.         RGBEditor_SetHidden(this->rgb[1], TRUE);
  2920.         }
  2921.  
  2922.          do
  2923.             {
  2924.             dir = (key=='>') ? 1 : -1;
  2925.  
  2926.            while ( !keypressed() )
  2927.            {
  2928.            tick = readticker();
  2929.            PalTable__Rotate(this, dir, rotate_lo, rotate_hi);
  2930.                diff += dir;
  2931.            while (readticker() == tick) ;   /* wait until a tick passes */
  2932.            }
  2933.  
  2934.           key = getakey();
  2935.             }
  2936.          while (key=='<' || key=='>');
  2937.  
  2938.      if ( !this->hidden )
  2939.         {
  2940.         RGBEditor_SetHidden(this->rgb[0], FALSE);
  2941.         RGBEditor_SetHidden(this->rgb[1], FALSE);
  2942.         RGBEditor_Update(this->rgb[0]);
  2943.         RGBEditor_Update(this->rgb[1]);
  2944.         }
  2945.  
  2946.          if ( diff != 0 )
  2947.             PalTable__SaveUndoRotate(this, diff, rotate_lo, rotate_hi);
  2948.  
  2949.      Cursor_Show();
  2950.      break;
  2951.      }
  2952.  
  2953.       case 'I':     /* invert the fg & bg colors */
  2954.       case 'i':
  2955.     inverse = !inverse;
  2956.     PalTable__UpdateDAC(this);
  2957.     break;
  2958.  
  2959.       case 'V':
  2960.       case 'v':     /* set the reserved colors to the editor colors */
  2961.      if ( this->curr[0] >= colors || this->curr[1] >= colors ||
  2962.           this->curr[0] == this->curr[1] )
  2963.         {
  2964.         buzzer(2);
  2965.         break;
  2966.         }
  2967.  
  2968.      fg_color = this->curr[0];
  2969.      bg_color = this->curr[1];
  2970.  
  2971.      if ( !this->hidden )
  2972.         {
  2973.         Cursor_Hide();
  2974.         PalTable__UpdateDAC(this);
  2975.         PalTable__Draw(this);
  2976.         Cursor_Show();
  2977.         }
  2978.  
  2979.      RGBEditor_SetDone(this->rgb[this->active], TRUE);
  2980.      break;
  2981.  
  2982.       case 'O':    /* set rotate_lo and rotate_hi to editors */
  2983.       case 'o':
  2984.      if (this->curr[0] > this->curr[1])
  2985.         {
  2986.         rotate_lo = this->curr[1];
  2987.         rotate_hi = this->curr[0];
  2988.         }
  2989.      else
  2990.         {
  2991.         rotate_lo = this->curr[0];
  2992.         rotate_hi = this->curr[1];
  2993.         }
  2994.      break;
  2995.  
  2996.       case F2:      /* restore a palette */
  2997.       case F3:
  2998.       case F4:
  2999.       case F5:
  3000.       case F6:
  3001.       case F7:
  3002.       case F8:
  3003.       case F9:
  3004.      {
  3005.      int which = key - F2;
  3006.  
  3007.      if ( this->save_pal[which] != NULL )
  3008.         {
  3009.         struct SREGS seg;
  3010.  
  3011.         Cursor_Hide();
  3012.  
  3013.             PalTable__SaveUndoData(this, 0, 255);
  3014.  
  3015.         segread(&seg);
  3016.         movedata(FP_SEG(this->save_pal[which]), FP_OFF(this->save_pal[which]),
  3017.              seg.ds, (USEGTYPE)(this->pal), 256*3);
  3018.  
  3019.         PalTable__UpdateDAC(this);
  3020.  
  3021.         PalTable__SetCurr(this, -1, 0);
  3022.         Cursor_Show();
  3023.         RGBEditor_SetDone(this->rgb[this->active], TRUE);
  3024.         }
  3025.      else
  3026.         buzzer(3);     /* error buzz */
  3027.      break;
  3028.      }
  3029.  
  3030.       case SF2:   /* save a palette */
  3031.       case SF3:
  3032.       case SF4:
  3033.       case SF5:
  3034.       case SF6:
  3035.       case SF7:
  3036.       case SF8:
  3037.       case SF9:
  3038.      {
  3039.      int which = key - SF2;
  3040.  
  3041.      if ( this->save_pal[which] != NULL )
  3042.         {
  3043.         struct SREGS seg;
  3044.  
  3045.         segread(&seg);
  3046.         movedata(seg.ds, (USEGTYPE)(this->pal), FP_SEG(this->save_pal[which]),
  3047.             FP_OFF(this->save_pal[which]), 256*3);
  3048.         }
  3049.      else
  3050.         buzzer(3); /* oops! short on memory! */
  3051.      break;
  3052.      }
  3053.  
  3054.       case 'L':     /* load a .map palette */
  3055.       case 'l':
  3056.      {
  3057.          PalTable__SaveUndoData(this, 0, 255);
  3058.  
  3059.      load_palette();
  3060. #ifndef XFRACT
  3061.      getpalrange(0, colors, this->pal);
  3062. #else
  3063.      getpalrange(0, 256, this->pal);
  3064. #endif
  3065.      PalTable__UpdateDAC(this);
  3066.      RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  3067.      RGBEditor_Update(this->rgb[0]);
  3068.      RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  3069.      RGBEditor_Update(this->rgb[1]);
  3070.      break;
  3071.      }
  3072.  
  3073.       case 'S':     /* save a .map palette */
  3074.       case 's':
  3075.      {
  3076. #ifndef XFRACT
  3077.      setpalrange(0, colors, this->pal);
  3078. #else
  3079.      setpalrange(0, 256, this->pal);
  3080. #endif
  3081.      save_palette();
  3082.      PalTable__UpdateDAC(this);
  3083.      break;
  3084.      }
  3085.  
  3086.       case 'C':     /* color cycling sub-mode */
  3087.       case 'c':
  3088.      {
  3089.      BOOLEAN oldhidden = this->hidden;
  3090.  
  3091.          PalTable__SaveUndoData(this, 0, 255);
  3092.  
  3093.      Cursor_Hide();
  3094.      if ( !oldhidden )
  3095.         PalTable_Hide(this, rgb, TRUE);
  3096.      setpalrange(0, colors, this->pal);
  3097.      rotate(0);
  3098.      getpalrange(0, colors, this->pal);
  3099.      PalTable__UpdateDAC(this);
  3100.      if ( !oldhidden )
  3101.         {
  3102.         RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  3103.         RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  3104.         PalTable_Hide(this, rgb, FALSE);
  3105.         }
  3106.      Cursor_Show();
  3107.      break;
  3108.      }
  3109.  
  3110.       case 'F':
  3111.       case 'f':    /* toggle freestyle palette edit mode */
  3112.          this->freestyle= (this->freestyle) ? FALSE :TRUE;
  3113.  
  3114.          PalTable__SetCurr(this, -1, 0);
  3115.  
  3116.          if ( !this->freestyle )   /* if turning off... */
  3117.             PalTable__UpdateDAC(this);
  3118.  
  3119.          PalTable__DrawStatus(this, FALSE);
  3120.          break;
  3121.  
  3122.       case CTL_DEL:  /* rt plus down */
  3123.          if (this->bandwidth >0 )
  3124.             this->bandwidth  --;
  3125.          else
  3126.             this->bandwidth=0;
  3127.          PalTable__SetCurr(this, -1, 0);
  3128.          break;
  3129.  
  3130.       case CTL_INSERT: /* rt plus up */
  3131.          if (this->bandwidth <255 )
  3132.            this->bandwidth ++;
  3133.          else
  3134.             this->bandwidth = 255;
  3135.          PalTable__SetCurr(this, -1, 0);
  3136.          break;
  3137.  
  3138.       case 'W':   /* convert to greyscale */
  3139.       case 'w':
  3140.      {
  3141.      switch ( this->exclude )
  3142.         {
  3143.         case 0:   /* normal mode.  convert all colors to grey scale */
  3144.                PalTable__SaveUndoData(this, 0, 255);
  3145.            palrangetogrey(this->pal, 0, 256);
  3146.            break;
  3147.  
  3148.         case 1:   /* 'x' mode. convert current color to grey scale.  */
  3149.                PalTable__SaveUndoData(this, this->curr[this->active], this->curr[this->active]);
  3150.            palrangetogrey(this->pal, this->curr[this->active], 1);
  3151.            break;
  3152.  
  3153.         case 2:  /* 'y' mode.  convert range between editors to grey. */
  3154.            {
  3155.            int a = this->curr[0],
  3156.            b = this->curr[1];
  3157.  
  3158.            if (a > b)
  3159.           {
  3160.           int t = a;
  3161.           a = b;
  3162.           b = t;
  3163.           }
  3164.  
  3165.                PalTable__SaveUndoData(this, a, b);
  3166.            palrangetogrey(this->pal, a, 1+(b-a));
  3167.            break;
  3168.            }
  3169.         }
  3170.  
  3171.      PalTable__UpdateDAC(this);
  3172.      RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  3173.      RGBEditor_Update(this->rgb[0]);
  3174.      RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  3175.      RGBEditor_Update(this->rgb[1]);
  3176.      break;
  3177.      }
  3178.  
  3179.       case 'N':   /* convert to negative color */
  3180.       case 'n':
  3181.      {
  3182.      switch ( this->exclude )
  3183.         {
  3184.         case 0:     /* normal mode.  convert all colors to grey scale */
  3185.                PalTable__SaveUndoData(this, 0, 255);
  3186.            palrangetonegative(this->pal, 0, 256);
  3187.            break;
  3188.  
  3189.         case 1:     /* 'x' mode. convert current color to grey scale.  */
  3190.                PalTable__SaveUndoData(this, this->curr[this->active], this->curr[this->active]);
  3191.            palrangetonegative(this->pal, this->curr[this->active], 1);
  3192.            break;
  3193.  
  3194.         case 2:  /* 'y' mode.  convert range between editors to grey. */
  3195.            {
  3196.            int a = this->curr[0],
  3197.            b = this->curr[1];
  3198.  
  3199.            if (a > b)
  3200.           {
  3201.           int t = a;
  3202.           a = b;
  3203.           b = t;
  3204.           }
  3205.  
  3206.                PalTable__SaveUndoData(this, a, b);
  3207.            palrangetonegative(this->pal, a, 1+(b-a));
  3208.            break;
  3209.            }
  3210.         }
  3211.  
  3212.      PalTable__UpdateDAC(this);
  3213.      RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  3214.      RGBEditor_Update(this->rgb[0]);
  3215.      RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  3216.      RGBEditor_Update(this->rgb[1]);
  3217.      break;
  3218.      }
  3219.  
  3220.       case 'U':     /* Undo */
  3221.       case 'u':
  3222.          PalTable__Undo(this);
  3223.          break;
  3224.  
  3225.       case 'e':    /* Redo */
  3226.       case 'E':
  3227.          PalTable__Redo(this);
  3228.          break;
  3229.  
  3230.       } /* switch */
  3231.    }
  3232.  
  3233.  
  3234. static void PalTable__MkDefaultPalettes(PalTable *this)  /* creates default Fkey palettes */
  3235.    {
  3236.    PALENTRY     black,
  3237.             white;
  3238.    PALENTRY     temp[256];
  3239.    int            ctr;
  3240.    struct SREGS seg;
  3241.  
  3242.    black.red = black.green = black.blue = 0;
  3243.    white.red = white.green = white.blue = 63;
  3244.    mkpalrange(&black, &white, temp, 256, 1); /* boring! */
  3245.  
  3246.    segread(&seg);
  3247.  
  3248.    for (ctr=0; ctr<8; ctr++)   /* copy temp into all fkey saves */
  3249.       movedata(seg.ss, (USEGTYPE)(temp), FP_SEG(this->save_pal[ctr]),
  3250.            FP_OFF(this->save_pal[ctr]), 256*3);
  3251.    }
  3252.  
  3253.  
  3254.  
  3255. static PalTable *PalTable_Construct(void)
  3256.    {
  3257.    PalTable     *this = new(PalTable);
  3258.    int         csize;
  3259.    int         ctr;
  3260.    PALENTRY far *mem_block;
  3261.    void far     *temp;
  3262.  
  3263.    temp = farmemalloc(FAR_RESERVE);
  3264.  
  3265.    if ( temp != NULL )
  3266.       {
  3267.       mem_block = (PALENTRY far *)farmemalloc(256L*3 * 8);
  3268.  
  3269.       if ( mem_block == NULL )
  3270.      {
  3271.      for (ctr=0; ctr<8; ctr++)
  3272.         this->save_pal[ctr] = NULL;
  3273.      }
  3274.       else
  3275.      {
  3276.      for (ctr=0; ctr<8; ctr++)
  3277.         this->save_pal[ctr] = mem_block + (256*ctr);
  3278.  
  3279.      PalTable__MkDefaultPalettes(this);
  3280.      }
  3281.       farmemfree(temp);
  3282.       }
  3283.  
  3284.    this->rgb[0] = RGBEditor_Construct(0, 0, PalTable__other_key,
  3285.           PalTable__change, this);
  3286.    this->rgb[1] = RGBEditor_Construct(0, 0, PalTable__other_key,
  3287.           PalTable__change, this);
  3288.  
  3289.    this->movebox = MoveBox_Construct(0,0,0, PalTable_PALX+1, PalTable_PALY+1);
  3290.  
  3291.    this->active      = 0;
  3292.    this->curr[0]     = 1;
  3293.    this->curr[1]     = 1;
  3294.    this->auto_select = TRUE;
  3295.    this->exclude     = FALSE;
  3296.    this->hidden      = FALSE;
  3297.    this->stored_at   = NOWHERE;
  3298.    this->file         = NULL;
  3299.    this->memory      = NULL;
  3300.  
  3301.    this->fs_color.red   = 42;
  3302.    this->fs_color.green = 42;
  3303.    this->fs_color.blue  = 42;
  3304.    this->freestyle      = FALSE;
  3305.    this->bandwidth      = 15;
  3306.    this->top            = 255;
  3307.    this->bottom         = 0 ;
  3308.  
  3309.    this->undo_file    = fopen(undofile, "w+b");
  3310.    this->curr_changed = FALSE;
  3311.    this->num_redo     = 0;
  3312.  
  3313.    RGBEditor_SetRGB(this->rgb[0], this->curr[0], &this->pal[this->curr[0]]);
  3314.    RGBEditor_SetRGB(this->rgb[1], this->curr[1], &this->pal[this->curr[0]]);
  3315.  
  3316.    PalTable__SetPos(this, 0, 0);
  3317.  
  3318.    csize = ( (sydots-(PalTable_PALY+1+1)) / 2 ) / 16;
  3319.    if (csize<CSIZE_MIN)
  3320.       csize = CSIZE_MIN;
  3321.    PalTable__SetCSize(this, csize);
  3322.  
  3323.    return(this);
  3324.    }
  3325.  
  3326.  
  3327. static void PalTable_SetHidden(PalTable *this, BOOLEAN hidden)
  3328.    {
  3329.    this->hidden = hidden;
  3330.    RGBEditor_SetHidden(this->rgb[0], hidden);
  3331.    RGBEditor_SetHidden(this->rgb[1], hidden);
  3332.    PalTable__UpdateDAC(this);
  3333.    }
  3334.  
  3335.  
  3336.  
  3337. static void PalTable_Hide(PalTable *this, RGBEditor *rgb, BOOLEAN hidden)
  3338.    {
  3339.    if (hidden)
  3340.       {
  3341.       PalTable__RestoreRect(this);
  3342.       PalTable_SetHidden(this, TRUE);
  3343.       reserve_colors = FALSE;
  3344.       if (this->auto_select)
  3345.      PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  3346.       }
  3347.    else
  3348.       {
  3349.       PalTable_SetHidden(this, FALSE);
  3350.       reserve_colors = TRUE;
  3351.       if (this->stored_at == NOWHERE)  /* do we need to save screen? */
  3352.      PalTable__SaveRect(this);
  3353.       PalTable__Draw(this);
  3354.       if (this->auto_select)
  3355.      PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  3356.       RGBEditor_SetDone(rgb, TRUE);
  3357.       }
  3358.    }
  3359.  
  3360.  
  3361. static void PalTable_Destroy(PalTable *this)
  3362.    {
  3363.  
  3364.    if (this->file != NULL)
  3365.       {
  3366.       fclose(this->file);
  3367.       remove(scrnfile);
  3368.       }
  3369.  
  3370.    if (this->undo_file != NULL)
  3371.       {
  3372.       fclose(this->undo_file);
  3373.       remove(undofile);
  3374.       }
  3375.  
  3376.    if (this->memory != NULL)
  3377.       farmemfree(this->memory);
  3378.  
  3379.    if (this->save_pal[0] != NULL)
  3380.       farmemfree((BYTE far *)this->save_pal[0]);
  3381.  
  3382.    RGBEditor_Destroy(this->rgb[0]);
  3383.    RGBEditor_Destroy(this->rgb[1]);
  3384.    MoveBox_Destroy(this->movebox);
  3385.    delete(this);
  3386.    }
  3387.  
  3388.  
  3389. static void PalTable_Process(PalTable *this)
  3390.    {
  3391.    int ctr;
  3392.  
  3393.    getpalrange(0, colors, this->pal);
  3394.  
  3395.    /* Make sure all palette entries are 0-63 */
  3396.  
  3397.    for(ctr=0; ctr<768; ctr++)
  3398.       ((char *)this->pal)[ctr] &= 63;
  3399.  
  3400.    PalTable__UpdateDAC(this);
  3401.  
  3402.    RGBEditor_SetRGB(this->rgb[0], this->curr[0], &this->pal[this->curr[0]]);
  3403.    RGBEditor_SetRGB(this->rgb[1], this->curr[1], &this->pal[this->curr[0]]);
  3404.  
  3405.    if (!this->hidden)
  3406.       {
  3407.       MoveBox_SetPos(this->movebox, this->x, this->y);
  3408.       MoveBox_SetCSize(this->movebox, this->csize);
  3409.       if ( !MoveBox_Process(this->movebox) )
  3410.      {
  3411.      setpalrange(0, colors, this->pal);
  3412.      return ;
  3413.      }
  3414.  
  3415.       PalTable__SetPos(this, MoveBox_X(this->movebox), MoveBox_Y(this->movebox));
  3416.       PalTable__SetCSize(this, MoveBox_CSize(this->movebox));
  3417.  
  3418.       if ( MoveBox_ShouldHide(this->movebox) )
  3419.      {
  3420.      PalTable_SetHidden(this, TRUE);
  3421.      reserve_colors = FALSE;   /* <EAN> */
  3422.      }
  3423.       else
  3424.      {
  3425.      reserve_colors = TRUE;    /* <EAN> */
  3426.      PalTable__SaveRect(this);
  3427.      PalTable__Draw(this);
  3428.      }
  3429.       }
  3430.  
  3431.    PalTable__SetCurr(this, this->active,      PalTable__GetCursorColor(this));
  3432.    PalTable__SetCurr(this, (this->active==1)?0:1, PalTable__GetCursorColor(this));
  3433.    Cursor_Show();
  3434.  
  3435.    this->done = FALSE;
  3436.  
  3437.    while ( !this->done )
  3438.       RGBEditor_Edit(this->rgb[this->active]);
  3439.  
  3440.    Cursor_Hide();
  3441.    PalTable__RestoreRect(this);
  3442.    setpalrange(0, colors, this->pal);
  3443.    }
  3444.  
  3445.  
  3446. /*
  3447.  * interface to FRACTINT
  3448.  */
  3449.  
  3450.  
  3451.  
  3452. void EditPalette(void)         /* called by fractint */
  3453.    {
  3454.    int         oldlookatmouse = lookatmouse;
  3455.    int         oldsxoffs        = sxoffs;
  3456.    int         oldsyoffs        = syoffs;
  3457.    PalTable *pt;
  3458.  
  3459.    ENTER_OVLY(OVLY_ROTATE);
  3460.  
  3461.    mem_init(strlocn, 10*1024);
  3462.  
  3463.    if ( (font8x8 = findfont(0)) == NULL )
  3464.       return ;
  3465.  
  3466.    plot = putcolor;
  3467.  
  3468.    line_buff = newx(max(sxdots,sydots));
  3469.  
  3470.    lookatmouse = 3;
  3471.    sxoffs = syoffs = 0;
  3472.  
  3473.    reserve_colors = TRUE;
  3474.    inverse = FALSE;
  3475.    fg_color = 255%colors;
  3476.    bg_color = fg_color-1;
  3477.  
  3478.    Cursor_Construct();
  3479.    pt = PalTable_Construct();
  3480.    PalTable_Process(pt);
  3481.    PalTable_Destroy(pt);
  3482.    Cursor_Destroy();
  3483.  
  3484.    lookatmouse = oldlookatmouse;
  3485.    sxoffs = oldsxoffs;
  3486.    syoffs = oldsyoffs;
  3487.    delete(line_buff);
  3488.    EXIT_OVLY;
  3489.    }
  3490.  
  3491.