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