home *** CD-ROM | disk | FTP | other *** search
/ Mega A/V / mega_av.zip / mega_av / GRAPHUTL / FRASR172.ZIP / EDITPAL.C < prev    next >
C/C++ Source or Header  |  1991-12-03  |  67KB  |  2,809 lines

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