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