home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / colorpicker.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  40.8 KB  |  1,609 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* 
  20.  *  colorpicker.c --- Color related widgets, dialogs, and stuff.
  21.  *
  22.  *  Created: David Williams <djw@netscape.com>, Apr-20-1997
  23.  *
  24.  *  RCSID: "$Id: colorpicker.c,v 3.1 1998/03/28 03:19:56 ltabb Exp $"
  25.  */
  26.  
  27. #include "mozilla.h"
  28. #include "xfe.h"
  29. #include <XmL/Folder.h>   /* tab folder stuff */
  30. #include <Xm/Label.h> 
  31. #include <Xm/DrawnBP.h> 
  32. #include <Xm/Scale.h>
  33. #include <Xfe/XfeP.h>            /* for xfe widgets and utilities */
  34. #include <xpgetstr.h>     /* for XP_GetString() */
  35. #include "felocale.h"
  36.  
  37. #define DEFAULT_NCOLUMNS     10
  38. #define DEFAULT_NROWS        7
  39. #define DEFAULT_NCUSTOM_ROWS 2
  40. #define DEFAULT_BUTTON_SIZE  18
  41.  
  42. #define DEFAULT_SPACE_SIZE   2
  43. #define DEFAULT_MARGIN_SIZE  2
  44. /*
  45.  * NOTE: a good size seems to be something between 1 or 4...
  46.  *
  47.  */
  48.  
  49. #define XFE_COLOR_RED   (0x1)
  50. #define XFE_COLOR_GREEN (0x2)
  51. #define XFE_COLOR_BLUE  (0x4)
  52. #define XFE_COLOR_UNITS (0x8)
  53. #define XFE_COLOR_INIT  (0x10)
  54.  
  55. /*
  56.  * NOTE:  new palette per EditorSpec...
  57.  *
  58.  */
  59. static char* fe_color_picker_standard_palette[] = {
  60.  
  61.     "#FFFFFF","#FFCCCC","#FFCC99","#FFFF99","#FFFFCC","#99FF99","#99FFFF","#CCFFFF","#CCCCFF","#FFCCFF",
  62.     "#CCCCCC","#FF6666","#FFCC33","#FFFF66","#FFFF99","#66FF99","#33FFFF","#66FFFF","#9999FF","#FF99FF",
  63.     "#CCCCCC","#FF0000","#FF9900","#FFCC66","#FFFF00","#33FF33","#66CCCC","#33CCFF","#6666CC","#CC66CC",
  64.     "#999999","#CC0000","#FF6600","#FFCC33","#FFCC00","#33CC00","#00CCCC","#3366FF","#6633FF","#CC33CC",
  65.     "#666666","#990000","#CC6600","#CC9933","#999900","#009900","#339999","#3333FF","#6600CC","#993399",
  66.     "#333333","#660000","#993300","#996633","#666600","#006600","#336666","#000099","#333399","#663366",
  67.     "#000000","#330000","#663300","#663333","#333300","#003300","#003333","#000066","#330099","#330033",
  68.  
  69.     NULL
  70. };
  71.  
  72. #if 0
  73. /*
  74.  *    These colors are the above corrected to fall into the 140 HTML
  75.  *    colornames defined in lib/xp/xp_rgb.c
  76.  */
  77. static char* corrected_named_shuang_palette[] = {
  78.     "white",
  79.  
  80.     "pink",
  81.     "salmon",
  82.     "red",
  83.     "red",
  84.     "darkred",
  85.     "maroon",
  86.     "black",
  87.  
  88.     "lightgrey",
  89.  
  90.     "lemonchiffon",
  91.     "khaki",
  92.     "yellow",
  93.     "gold",
  94.     "olive",
  95.     "olive",
  96.     "darkgreen",
  97.  
  98.     "darkgray",
  99.  
  100.     "lightcyan",
  101.     "aquamarine",
  102.     "deepskyblue",
  103.     "royalblue",
  104.     "royalblue",
  105.     "darkblue",
  106.     "navy",
  107.  
  108.     "dimgray",
  109.  
  110.     "lavender",
  111.     "violet",
  112.     "orchid",
  113.     "mediumorchid",
  114.     "darkorchid",
  115.     "darkslateblue",
  116.     "midnightblue",
  117.  
  118.     "black",
  119.  
  120.     "navajowhite",
  121.     "gold",
  122.     "orange",
  123.     "orangered",
  124.     "chocolate",
  125.     "saddlebrown",
  126.     "saddlebrown",
  127.  
  128.     "black",
  129.  
  130.     "aquamarine",
  131.     "lightgreen",
  132.     "limegreen",
  133.     "limegreen",
  134.     "green",
  135.     "darkgreen",
  136.     "darkgreen",
  137.     NULL
  138. };
  139.  
  140. /*
  141.  *    These are the 16 color names specified in the HTML 3.2 spec.
  142.  */
  143. static char* html32_named_colors[] = {
  144.  
  145.     "#000000", /*Black = */ 
  146.     "#008000", /*Green = */ 
  147.     "#C0C0C0", /*Silver = */
  148.     "#00FF00", /*Lime = */
  149.     "#808080", /*Gray = */
  150.     "#808000", /*Olive = */
  151.     "#FFFFFF", /*White = */
  152.     "#FFFF00", /*Yellow = */
  153.     "#800000", /*Maroon = */
  154.     "#000080", /*Navy = */
  155.     "#FF0000", /*Red = */
  156.     "#0000FF", /*Blue = */
  157.     "#800080", /*Purple = */
  158.     "#008080", /*Teal = */
  159.     "#FF00FF", /*Fuchsia = */
  160.     "#00FFFF", /*Aqua = */
  161.     NULL
  162. };
  163. #endif /* end of unused palettes */
  164.  
  165. /*
  166.  *    This routine is used throughout this code to create a pixel
  167.  *    from an RGB value.
  168.  */
  169. static Pixel
  170. fe_color_get_pixel(Widget widget, uint8 red, uint8 green, uint8 blue)
  171. {
  172.     MWContext* context = (MWContext *)fe_WidgetToMWContext(widget);
  173.  
  174.     /*
  175.      *    Make a pixel. I'm hoping Jamie's color stuff will
  176.      *    know when to release this...djw
  177.      */
  178.     return fe_GetPixel(context, red, green, blue);
  179. }
  180.  
  181. /*
  182.  *    Code for a simple color swatch:
  183.  *
  184.  *    Widget fe_CreateSwatch(Widget parent, char* name, Arg* args, Cardinal n);
  185.  *    void   fe_SwatchSetColor(Widget widget, LO_Color* color);
  186.  */
  187. static void
  188. fe_swatch_expose_cb(Widget widget, XtPointer closure, XtPointer cbd)
  189. {
  190.     XmDrawnButtonWidget db = (XmDrawnButtonWidget)widget;
  191.     XmLabelPart*        lp = &(db->label);
  192.     GC gc;
  193.     unsigned offset = db->primitive.highlight_thickness +
  194.                       db->primitive.shadow_thickness;
  195.  
  196.     XtVaGetValues(widget, XmNuserData, &gc, 0);
  197.     
  198.     XFillRectangle(XtDisplay(widget), XtWindow(widget),
  199.                    gc,
  200.                    offset, offset,
  201.                    _XfeWidth(db) - 2 * offset, _XfeHeight(db) - 2 * offset);
  202.  
  203.     if (lp->label_type == XmSTRING && lp->_label != NULL) {
  204.         _XmStringDraw(XtDisplay(widget), XtWindow(widget),
  205.                       lp->font, lp->_label,
  206.                       lp->normal_GC,
  207.                       lp->TextRect.x, lp->TextRect.y,
  208.                       lp->TextRect.width, lp->alignment,
  209.                       lp->string_direction, NULL);
  210.     }
  211. }
  212.  
  213. static void
  214. fe_SwatchSetColor(Widget widget, LO_Color* color)
  215. {
  216.     GC        gc;
  217.     XGCValues values;
  218.     XtGCMask  valueMask;
  219.     Pixel     pixel;
  220.     Pixel     foreground;
  221.  
  222.     XtVaGetValues(widget, XmNuserData, &gc, 0);
  223.  
  224.     XtReleaseGC(widget, gc);
  225.  
  226.     pixel = fe_color_get_pixel(widget, color->red, color->green, color->blue);
  227.  
  228.     XmGetColors(XtScreen(widget), XfeColormap(widget), pixel,
  229.                 &foreground, NULL, NULL, NULL);
  230.  
  231.     valueMask = GCForeground;
  232.     values.foreground = pixel;
  233.     gc = XtGetGC(widget, valueMask, &values);
  234.  
  235.     XtVaSetValues(widget, XmNuserData, gc, XmNforeground, foreground, 0);
  236.  
  237.     if (XtIsRealized(widget))
  238.         fe_swatch_expose_cb(widget, NULL, NULL);
  239. }
  240.  
  241. static void
  242. fe_swatch_destroy_cb(Widget widget, XtPointer closure, XtPointer cbd)
  243. {
  244.     GC gc;
  245.  
  246.     XtVaGetValues(widget, XmNuserData, &gc, 0);
  247.  
  248.     if (gc != 0)
  249.         XtReleaseGC(widget, gc);
  250. }
  251.  
  252. static Widget
  253. fe_CreateSwatch(Widget parent, char* name, Arg* args, Cardinal n)
  254. {
  255.     Widget    widget;
  256.     GC        gc;
  257.     XGCValues values;
  258.     XtGCMask  valueMask;
  259.     Pixel     pixel;
  260.  
  261.     widget = XmCreateDrawnButton(parent, name, args, n);
  262.  
  263.     XtVaGetValues(parent, XmNbackground, &pixel, 0);
  264.  
  265.     valueMask = GCForeground;
  266.     values.foreground = pixel;
  267.     gc = XtGetGC(widget, valueMask, &values);
  268.  
  269.     XtVaSetValues(widget, XmNuserData, gc, 0);
  270.  
  271.     XtAddCallback(widget, XmNexposeCallback, fe_swatch_expose_cb, NULL);
  272.     XtAddCallback(widget, XmNdestroyCallback, fe_swatch_destroy_cb, NULL);
  273.  
  274.     return widget;
  275. }
  276.  
  277. /*
  278.  *    Code for a color swatch matrix:
  279.  *
  280.  *    Widget fe_CreateSwatchMatrix(Widget parent, char* name, Arg*, Cardinal);
  281.  *    use this function in a callback to get the color at x,y
  282.  *    int    fe_SwatchMatrixGetColor(Widget, Position x, Position y, XColor*);
  283.  */
  284. #if 0
  285. static char fe_ColorPickerButtonSize[] =         "colorButtonSize";
  286. #endif
  287. static char fe_ColorPickerPalette[] =            "colorPalette";
  288.  
  289. typedef struct ColorInfo {
  290.     unsigned long rgb;
  291.     Pixel         pixel;
  292. } ColorInfo;
  293.  
  294. typedef struct SwatchesInfo {
  295.     ColorInfo* colors;
  296.     unsigned   ncolors;
  297.     GC         drawing_gc;
  298. } SwatchesInfo;
  299.  
  300. static void
  301. fe_swatches_destroy_cb(Widget widget, XtPointer closure, XtPointer cbd)
  302. {
  303.     SwatchesInfo* info;
  304.  
  305.     XtVaGetValues(widget, XmNuserData, &info, 0);
  306.  
  307.     if (info != NULL) {
  308.         if (info->drawing_gc != 0)
  309.             XFreeGC(XtDisplay(widget), info->drawing_gc);
  310.  
  311.         if (info->colors != NULL)
  312.             XtFree((char*)info->colors);
  313.  
  314.         XtFree((char*)info);
  315.     }
  316. }
  317.  
  318. int
  319. fe_SwatchMatrixGetColor(Widget widget, Position p_x, Position p_y,
  320.                         XColor* color_r)
  321. {
  322.     char*    name = XtName(widget);
  323.     uint8    red;
  324.     uint8    green;
  325.     uint8    blue;
  326.         
  327.     if (name == NULL) {
  328.         red = blue = green = 0;
  329.     }
  330.     else {
  331.         if (!LO_ParseRGB(name, &red, &green, &blue)) {
  332.             red = blue = green = 0; /* black */
  333.         }
  334.     }
  335.  
  336.     /*
  337.      * NOTE:  we could also just get the background pixel from the widget
  338.      *        - something to look into if this becomes too expensive...
  339.      *
  340.      */
  341.     color_r->pixel = fe_color_get_pixel(widget, red, green, blue);
  342.  
  343.     color_r->red = red;
  344.     color_r->green = green;
  345.     color_r->blue = blue;
  346.  
  347.     return 1;
  348. }
  349.  
  350. typedef enum {
  351.     XFE_COLOR_DECIMAL,
  352.     XFE_COLOR_HEX,
  353.     XFE_COLOR_PERCENT
  354. } fe_ColorUnit;
  355.  
  356. typedef struct fe_SamplePageInfo fe_SamplePageInfo;
  357.  
  358. typedef struct fe_ColorUpdateInfo
  359. {
  360.     LO_Color     color;
  361.     Pixel        pixel;
  362.     fe_ColorUnit units;
  363.     fe_SamplePageInfo* list;
  364. } fe_ColorUpdateInfo;
  365.  
  366. typedef struct fe_SamplePart
  367. {
  368.     Widget old;
  369.     Widget new;
  370. } fe_SamplePart;
  371.  
  372. typedef void (*fe_ColorUpdateMethod_t)(void* page_info, Widget, unsigned);
  373.  
  374. struct fe_SamplePageInfo
  375. {
  376.     fe_ColorUpdateInfo*        update_info;
  377.     fe_ColorUpdateMethod_t update_method;
  378.     fe_SamplePageInfo*         next;
  379.     fe_SamplePart              sample;
  380. };
  381.  
  382. typedef struct fe_RgbPart
  383. {
  384.     Widget max;
  385.     Widget red_scale;
  386.     Widget green_scale;
  387.     Widget blue_scale;
  388.     Widget red_text;
  389.     Widget green_text;
  390.     Widget blue_text;
  391.     Widget units;
  392. } fe_RgbPart;
  393.  
  394. typedef struct fe_RgbPageInfo
  395. {
  396.     fe_ColorUpdateInfo* update_info;
  397.     fe_ColorUpdateMethod_t update_method;
  398.     fe_SamplePageInfo*         next;
  399.     fe_SamplePart       sample;
  400.     fe_RgbPart          rgb;
  401. } fe_RgbPageInfo;
  402.  
  403. typedef struct fe_SwatchesPart
  404. {
  405.     Widget matrix;
  406. } fe_SwatchesPart;
  407.  
  408. typedef struct fe_SwatchesPageInfo
  409. {
  410.     fe_ColorUpdateInfo* update_info;
  411.     fe_ColorUpdateMethod_t update_method;
  412.     fe_SamplePageInfo*         next;
  413.     fe_SamplePart       sample;
  414.     fe_SwatchesPart     swatches;
  415. } fe_SwatchesPageInfo;
  416.  
  417. static void
  418. fe_swatch_matrix_enter_eh(Widget chit, XtPointer closure, 
  419.                           XEvent* event, Boolean* keep_going)
  420. {
  421.     XtVaSetValues(chit,
  422.                   XmNshadowType, XmSHADOW_IN,
  423.                   0);
  424. }
  425.  
  426. static void
  427. fe_swatch_matrix_exit_eh(Widget chit, XtPointer closure, 
  428.                          XEvent* event, Boolean* keep_going)
  429. {
  430.     XtVaSetValues(chit,
  431.                   XmNshadowType, XmSHADOW_ETCHED_IN,
  432.                   0);
  433. }
  434.  
  435. static void
  436. fe_swatch_matrix_destroy_cb(Widget chit, XtPointer closure, XtPointer cbd)
  437. {
  438.     XtRemoveEventHandler(chit, EnterWindowMask, FALSE, 
  439.                          fe_swatch_matrix_enter_eh, NULL);
  440.  
  441.     XtRemoveEventHandler(chit, LeaveWindowMask, FALSE, 
  442.                          fe_swatch_matrix_exit_eh, NULL);
  443. }
  444.  
  445. #define MAX_ARGS 16
  446.  
  447. Widget
  448. fe_CreateSwatchMatrix(Widget parent, char* name, Arg* p_args, Cardinal p_nargs)
  449. {
  450.     Widget    matrix;
  451.     unsigned  n;
  452.     unsigned  m;
  453.     Dimension shadow;
  454.     Dimension highlight;
  455.     Arg args[MAX_ARGS];
  456.     SwatchesInfo* info;
  457.     Pixel  bg_pixel = BlackPixelOfScreen(XtScreen(parent));
  458.     Pixel  nu_pixel = NULL;
  459.     char** palette = (char**)&fe_color_picker_standard_palette;
  460.  
  461.     n = 0;
  462.     XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
  463.     XtSetArg(args[n], XmNnumColumns, DEFAULT_NROWS); n++;
  464.     XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  465.     XtSetArg(args[n], XmNspacing, DEFAULT_SPACE_SIZE); n++;
  466.     XtSetArg(args[n], XmNmarginWidth, DEFAULT_MARGIN_SIZE); n++;
  467.     XtSetArg(args[n], XmNmarginHeight, DEFAULT_MARGIN_SIZE); n++;
  468.     XtSetArg(args[n], XmNtraversalOn, False); n++;
  469.     matrix = XmCreateRowColumn(parent, name, args, n);
  470.  
  471.     /*
  472.      *    Parse args, looking for pallete or background spec
  473.      */
  474.     for (m = 0; m < p_nargs ; m++) {
  475.         if (strcmp(p_args[m].name, fe_ColorPickerPalette) == 0)
  476.             palette = (char**)p_args[m].value;
  477.         else if (strcmp(p_args[m].name, XmNbackground) == 0)
  478.             bg_pixel = (Pixel)p_args[m].value;
  479.     }
  480.  
  481.     /*
  482.      *    Make the info stuff.
  483.      */
  484.     info = XtNew(SwatchesInfo);
  485.     info->drawing_gc = 0;
  486.  
  487.     for (n = 0; palette[n] != NULL; n++)
  488.         ;
  489.  
  490.     info->ncolors = n;
  491.     info->colors = NULL;
  492.  
  493.     for (n = 0;n < info->ncolors; n++) {
  494.         uint8 red;
  495.         uint8 green;
  496.         uint8 blue;
  497.         unsigned i = 0;
  498.         Widget chit = NULL;
  499.         
  500.         if (!LO_ParseRGB(palette[n], &red, &green, &blue)) {
  501.             red = blue = green = 0; /* black */
  502.         }
  503.  
  504.         nu_pixel = fe_color_get_pixel(matrix, red, green, blue);
  505.  
  506.         i = 0;
  507.         XtSetArg(args[i], XmNbackground, nu_pixel); i++;
  508.         XtSetArg(args[i], XmNwidth, DEFAULT_BUTTON_SIZE); i++;
  509.         XtSetArg(args[i], XmNheight, DEFAULT_BUTTON_SIZE); i++;
  510.         XtSetArg(args[i], XmNshadowType, XmSHADOW_ETCHED_IN); i++;
  511.         XtSetArg(args[i], XmNhighlightThickness, 0); i++;
  512.         XtSetArg(args[i], XmNmarginWidth, DEFAULT_MARGIN_SIZE); i++;
  513.         XtSetArg(args[i], XmNmarginHeight, DEFAULT_MARGIN_SIZE); i++;
  514.         XtSetArg(args[i], XmNtraversalOn, False); i++;
  515.         XtSetArg(args[i], XmNpushButtonEnabled, False); i++;
  516.  
  517.         chit = XmCreateDrawnButton(matrix, palette[n], args, i);
  518.  
  519.         fe_WidgetAddToolTips(chit);
  520.  
  521.         XtAddEventHandler(chit, EnterWindowMask, FALSE, 
  522.                           fe_swatch_matrix_enter_eh, NULL);
  523.  
  524.         XtAddEventHandler(chit, LeaveWindowMask, FALSE, 
  525.                           fe_swatch_matrix_exit_eh, NULL);
  526.  
  527.         XtAddCallback(chit, XmNdestroyCallback, 
  528.                       fe_swatch_matrix_destroy_cb, NULL);
  529.  
  530.         XtManageChild(chit);
  531.     }
  532.  
  533.     XtVaSetValues(matrix,
  534.                   XmNuserData, info,
  535.                   0);
  536.  
  537.     XtAddCallback(matrix, XmNdestroyCallback, fe_swatches_destroy_cb,
  538.                   NULL);
  539.  
  540.     return matrix;
  541. }
  542.  
  543. void
  544. fe_AddSwatchMatrixCallback(Widget matrix, 
  545.                            char* name, XtCallbackProc proc, XtPointer data)
  546. {
  547.     WidgetList kids = NULL;
  548.     uint32  numKids = 0;
  549.     uint32        n = 0;
  550.  
  551.     XtVaGetValues(matrix,
  552.                   XmNchildren, &kids,
  553.                   XmNnumChildren, &numKids,
  554.                   0);
  555.  
  556.     if (numKids > 0) {
  557.         for (n = 0; n < numKids; n++) {
  558.             XtAddCallback(kids[n], name, proc, data);
  559.         }
  560.     }
  561. }
  562.  
  563. static void
  564. fe_color_install_page(fe_ColorUpdateInfo*    update,
  565.                       fe_ColorUpdateMethod_t update_method,
  566.                       fe_SamplePageInfo*     page)
  567. {
  568.     page->update_info = update;
  569.     page->update_method = update_method;
  570.     page->next = update->list;
  571.     update->list = page;
  572. }
  573.  
  574. static void 
  575. fe_color_sample_part_update(fe_SamplePart*      widgets,
  576.                             fe_ColorUpdateInfo* update_info,
  577.                             Widget              caller,
  578.                             unsigned            mask)
  579. {
  580.     fe_SwatchSetColor(widgets->new, &update_info->color);
  581.  
  582.     if ((mask & XFE_COLOR_INIT) != 0) {
  583.         Pixel foreground;
  584.         XmGetColors(XtScreen(widgets->old), XfeColormap(widgets->old),
  585.                     update_info->pixel,
  586.                     &foreground, NULL, NULL, NULL);
  587.         XtVaSetValues(widgets->old,
  588.                       XmNbackground, update_info->pixel,
  589.                       XmNforeground, foreground,
  590.                       0);
  591.     }
  592. }
  593.  
  594. static void 
  595. fe_color_rgb_page_update(fe_RgbPageInfo*, Widget, unsigned mask);
  596.  
  597. static void
  598. fe_color_rgb_max_update_cb(Widget widget, XtPointer closure, XtPointer cb)
  599. {
  600.     fe_ColorUpdateInfo* info = (fe_ColorUpdateInfo*)closure;
  601.     char* buf;
  602.     XmString tmp_string;
  603.     
  604.     switch (info->units) {
  605.     case XFE_COLOR_HEX:     buf = "0xFF"; break;
  606.     case XFE_COLOR_PERCENT: buf = "100%"; break;
  607.     case XFE_COLOR_DECIMAL:
  608.     default:                buf = " 255"; break;
  609.     }
  610.  
  611.     tmp_string = XmStringCreateSimple(buf);
  612.  
  613.     XtVaSetValues(widget, XmNlabelString, tmp_string, 0);
  614.  
  615.     XmStringFree(tmp_string);
  616. }
  617.  
  618. static void
  619. fe_color_rgb_text_cb(Widget widget, XtPointer closure, XtPointer cb)
  620. {
  621.     fe_RgbPageInfo*     rgb_info = (fe_RgbPageInfo*)closure;
  622.     fe_ColorUpdateInfo* info = rgb_info->update_info;
  623.     char* string = fe_GetTextField(widget);
  624.     unsigned value;
  625.     unsigned mask;
  626.     char* name = XtName(widget);
  627.  
  628.     if (info->units == XFE_COLOR_HEX) {
  629.         value = strtoul(string, NULL, 16);
  630.     } else if (info->units == XFE_COLOR_PERCENT) {
  631.         value = strtoul(string, NULL, 10);
  632.         if (value > 100)
  633.             value = 100;
  634.         value = (256 * value) / 100;
  635.     } else {
  636.         value = strtoul(string, NULL, 10);
  637.     }
  638.  
  639.     if (value > 255)
  640.         value = 255;
  641.  
  642.     if (name[0] == 'r') { /* this sucks */
  643.         info->color.red = value;
  644.         mask = XFE_COLOR_RED;
  645.     } else if (name[0] == 'g') {
  646.         info->color.green = value;
  647.         mask = XFE_COLOR_GREEN;
  648.     } else {
  649.         info->color.blue = value;
  650.         mask = XFE_COLOR_BLUE;
  651.     }
  652.  
  653.     fe_color_rgb_page_update(rgb_info, widget, mask);
  654. }
  655.  
  656. static void
  657. fe_color_rgb_text_update_cb(Widget widget, XtPointer closure, XtPointer cb)
  658. {
  659.     fe_ColorUpdateInfo* info = (fe_ColorUpdateInfo*)closure;
  660.     Widget              caller = (Widget)cb;
  661.     char                buf[32];
  662.     unsigned big;
  663.     unsigned result;
  664.     unsigned value;
  665.     char* name;
  666.  
  667.     if (caller == widget)
  668.         return;
  669.  
  670.     name = XtName(widget);
  671.  
  672.     if (name[0] == 'r') /* this sucks */
  673.         value = info->color.red;
  674.     else if (name[0] == 'g')
  675.         value = info->color.green;
  676.     else
  677.         value = info->color.blue;
  678.     
  679.     switch (info->units) {
  680.     case XFE_COLOR_HEX:     
  681.         sprintf(buf, "%02X", value);
  682.         break;
  683.     case XFE_COLOR_PERCENT: 
  684.         big = 100 * value;
  685.         result = big / 256;
  686.         if ((big % 256) > 127)
  687.             result++;
  688.         sprintf(buf, "%03d", result);
  689.         break;
  690.     case XFE_COLOR_DECIMAL:
  691.     default:
  692.         sprintf(buf, "%03d", value);
  693.         break;
  694.     }
  695.  
  696.     fe_TextFieldSetString(widget, buf, False);
  697. }
  698.  
  699. static void
  700. fe_color_rgb_scale_cb(Widget widget, XtPointer closure, XtPointer cb)
  701. {
  702.     fe_RgbPageInfo*     rgb_info = (fe_RgbPageInfo*)closure;
  703.     fe_ColorUpdateInfo* info = rgb_info->update_info;
  704.     XmScaleCallbackStruct* cd = (XmScaleCallbackStruct*)cb;
  705.     unsigned value = cd->value;
  706.     char* name = XtName(widget);
  707.     unsigned mask;
  708.     
  709.     if (value > 255)
  710.         value = 255;
  711.  
  712.     if (name[0] == 'r') { /* this sucks */
  713.         info->color.red = value;
  714.         mask = XFE_COLOR_RED;
  715.     } else if (name[0] == 'g') {
  716.         info->color.green = value;
  717.         mask = XFE_COLOR_GREEN;
  718.     } else {
  719.         info->color.blue = value;
  720.         mask = XFE_COLOR_BLUE;
  721.     }
  722.  
  723.     fe_color_rgb_page_update(rgb_info, widget, mask);
  724. }
  725.  
  726. static void
  727. fe_color_rgb_scale_update_cb(Widget widget, XtPointer closure, XtPointer cb)
  728. {
  729.     fe_ColorUpdateInfo* info = (fe_ColorUpdateInfo*)closure;
  730.     Widget caller = (Widget)cb;
  731.     unsigned value;
  732.     char* name;
  733.  
  734.     if (caller == widget)
  735.         return;
  736.  
  737.     name = XtName(widget);
  738.  
  739.     if (name[0] == 'r') /* this sucks */
  740.         value = info->color.red;
  741.     else if (name[0] == 'g')
  742.         value = info->color.green;
  743.     else
  744.         value = info->color.blue;
  745.  
  746.     XtVaSetValues(widget, XmNvalue, value, 0);
  747. }
  748.  
  749. static void
  750. fe_color_rgb_units_cb(Widget widget, XtPointer closure, XtPointer cb)
  751. {
  752.     fe_RgbPageInfo*     rgb_info = (fe_RgbPageInfo*)closure;
  753.     fe_ColorUpdateInfo* info = rgb_info->update_info;
  754.     char* name = XtName(widget);
  755.  
  756.     if (name[0] == 'p') /* percent */
  757.         info->units = XFE_COLOR_PERCENT;
  758.     else if (name[0] == 'h')
  759.         info->units = XFE_COLOR_HEX;
  760.     else
  761.         info->units = XFE_COLOR_DECIMAL;
  762.  
  763.     fe_color_rgb_page_update(rgb_info, widget, XFE_COLOR_UNITS);
  764. }
  765.  
  766. static void
  767. fe_color_rgb_page_update(fe_RgbPageInfo* rgb_info, Widget caller, unsigned mask)
  768. {
  769.     fe_ColorUpdateInfo* info = rgb_info->update_info;
  770.     fe_SamplePart*      sample_part = &rgb_info->sample;
  771.     fe_RgbPart*         rgb_part = &rgb_info->rgb;
  772.  
  773.     if ((mask & (XFE_COLOR_RED|XFE_COLOR_GREEN|XFE_COLOR_BLUE)) != 0) {
  774.  
  775.         info->pixel = fe_color_get_pixel(sample_part->new, 
  776.                                          info->color.red,
  777.                                          info->color.green,
  778.                                          info->color.blue);
  779.  
  780.         /*
  781.          *    Update the sample
  782.          */
  783.         fe_color_sample_part_update(&rgb_info->sample, info, caller, mask);
  784.     }
  785.  
  786.     if ((mask & XFE_COLOR_RED) != 0)
  787.         fe_color_rgb_scale_update_cb(rgb_part->red_scale, info, caller);
  788.  
  789.     if ((mask & XFE_COLOR_GREEN) != 0)
  790.         fe_color_rgb_scale_update_cb(rgb_part->green_scale, info, caller);
  791.  
  792.     if ((mask & XFE_COLOR_BLUE) != 0)
  793.         fe_color_rgb_scale_update_cb(rgb_part->blue_scale, info, caller);
  794.  
  795.     if ((mask & XFE_COLOR_UNITS) != 0)
  796.         fe_color_rgb_max_update_cb(rgb_part->max, info, caller);
  797.  
  798.     if ((mask & (XFE_COLOR_RED|XFE_COLOR_UNITS)) != 0)
  799.         fe_color_rgb_text_update_cb(rgb_part->red_text, info, caller);
  800.  
  801.     if ((mask & (XFE_COLOR_GREEN|XFE_COLOR_UNITS)) != 0)
  802.         fe_color_rgb_text_update_cb(rgb_part->green_text, info, caller);
  803.  
  804.     if ((mask & (XFE_COLOR_BLUE|XFE_COLOR_UNITS)) != 0)
  805.         fe_color_rgb_text_update_cb(rgb_part->blue_text, info, caller);
  806. }
  807.  
  808. static Widget
  809. fe_create_rgb_group(Widget parent, fe_RgbPageInfo* info)
  810. {
  811.     Widget rgb_frame;
  812.     Widget form;
  813.     Widget red_label;
  814.     Widget green_label;
  815.     Widget blue_label;
  816.     Widget red_scale;
  817.     Widget green_scale;
  818.     Widget blue_scale;
  819.     Widget red_text;
  820.     Widget green_text;
  821.     Widget blue_text;
  822.     Widget min_label;
  823.     Widget max_label;
  824.     Widget units;
  825.     Widget pulldown;
  826.     XmString tmp_string;
  827.     Widget bottom;
  828.     Widget text;
  829.     Widget label;
  830.     Widget scale;
  831.     Widget button;
  832.     int i;
  833.     Widget children[16];
  834.     Cardinal nchildren = 0;
  835.     Arg args[16];
  836.     Cardinal n;
  837.  
  838. #define SHOW_VALUE FALSE
  839. #define TEXT_NCOLUMNS 4
  840.  
  841.     n = 0;
  842.     rgb_frame = XmCreateFrame(parent, "rgbEditor", args, n);
  843.     XtManageChild(rgb_frame);
  844.  
  845.     n = 0;
  846.     form = XmCreateForm(rgb_frame, "rgbForm", args, n);
  847.     XtManageChild(form);
  848.  
  849.     tmp_string = XmStringCreateSimple("0");
  850.  
  851.     n = 0;
  852.     XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
  853.     XtSetArg(args[n], XmNlabelString, tmp_string); n++;
  854.     min_label = XmCreateLabelGadget(form, "minLabel", args, n);
  855.     children[nchildren++] = min_label;
  856.  
  857.     XmStringFree(tmp_string);
  858.  
  859.     tmp_string = XmStringCreateSimple("255");
  860.  
  861.     n = 0;
  862.     XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
  863.     XtSetArg(args[n], XmNlabelString, tmp_string); n++;
  864.     max_label = XmCreateLabelGadget(form, "maxLabel", args, n);
  865.     children[nchildren++] = max_label;
  866.  
  867.     XmStringFree(tmp_string);
  868.  
  869.     tmp_string = XmStringCreateSimple("R");
  870.  
  871.     n = 0;
  872.     XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
  873.     XtSetArg(args[n], XmNlabelString, tmp_string); n++;
  874.     red_label = XmCreateLabelGadget(form, "redLabel", args, n);
  875.     children[nchildren++] = red_label;
  876.  
  877.     XmStringFree(tmp_string);
  878.     
  879.     n = 0;
  880.     XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_RED); n++;
  881.     XtSetArg(args[n], XmNshowValue, SHOW_VALUE); n++;
  882.     XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  883.     XtSetArg(args[n], XmNmaximum, 256); n++;
  884.     red_scale = XmCreateScale(form, "redScale", args, n);
  885.     children[nchildren++] = red_scale;
  886.  
  887.     XtAddCallback(red_scale, XmNdragCallback,
  888.                   fe_color_rgb_scale_cb, (XtPointer)info);
  889.  
  890.     XtAddCallback(red_scale, XmNvalueChangedCallback,
  891.                   fe_color_rgb_scale_cb, (XtPointer)info);
  892.  
  893.     n = 0;
  894.     XtSetArg(args[n], XmNcolumns, TEXT_NCOLUMNS); n++;
  895.     XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_RED); n++;
  896.     red_text = fe_CreateTextField(form, "redText", args, n);
  897.     children[nchildren++] = red_text;
  898.  
  899.     XtAddCallback(red_text, XmNvalueChangedCallback,
  900.                   fe_color_rgb_text_cb, (XtPointer)info);
  901.  
  902.     tmp_string = XmStringCreateSimple("G");
  903.  
  904.     n = 0;
  905.     XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
  906.     XtSetArg(args[n], XmNlabelString, tmp_string); n++;
  907.     green_label = XmCreateLabelGadget(form, "greenLabel", args, n);
  908.     children[nchildren++] = green_label;
  909.     
  910.     XmStringFree(tmp_string);
  911.     
  912.     n = 0;
  913.     XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_GREEN); n++;
  914.     XtSetArg(args[n], XmNshowValue, SHOW_VALUE); n++;
  915.     XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  916.     XtSetArg(args[n], XmNmaximum, 256); n++;
  917.     green_scale = XmCreateScale(form, "greenScale", args, n);
  918.     children[nchildren++] = green_scale;
  919.     
  920.     XtAddCallback(green_scale, XmNdragCallback,
  921.                   fe_color_rgb_scale_cb, (XtPointer)info);
  922.  
  923.     XtAddCallback(green_scale, XmNvalueChangedCallback,
  924.                   fe_color_rgb_scale_cb, (XtPointer)info);
  925.  
  926.     n = 0;
  927.     XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_GREEN); n++;
  928.     XtSetArg(args[n], XmNcolumns, TEXT_NCOLUMNS); n++;
  929.     green_text = fe_CreateTextField(form, "greenText", args, n);
  930.     children[nchildren++] = green_text;
  931.  
  932.     XtAddCallback(green_text, XmNvalueChangedCallback,
  933.                   fe_color_rgb_text_cb, (XtPointer)info);
  934.  
  935.     tmp_string = XmStringCreateSimple("B");
  936.  
  937.     n = 0;
  938.     XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
  939.     XtSetArg(args[n], XmNlabelString, tmp_string); n++;
  940.     blue_label = XmCreateLabelGadget(form, "blueLabel", args, n);
  941.     children[nchildren++] = blue_label;
  942.     
  943.     XmStringFree(tmp_string);
  944.     
  945.     n = 0;
  946.     XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_BLUE); n++;
  947.     XtSetArg(args[n], XmNshowValue, SHOW_VALUE); n++;
  948.     XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  949.     XtSetArg(args[n], XmNmaximum, 256); n++;
  950.     blue_scale = XmCreateScale(form, "blueScale", args, n);
  951.     children[nchildren++] = blue_scale;
  952.  
  953.     XtAddCallback(blue_scale, XmNdragCallback,
  954.                   fe_color_rgb_scale_cb, (XtPointer)info);
  955.  
  956.     XtAddCallback(blue_scale, XmNvalueChangedCallback,
  957.                   fe_color_rgb_scale_cb, (XtPointer)info);
  958.  
  959.     n = 0;
  960.     XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_BLUE); n++;
  961.     XtSetArg(args[n], XmNcolumns, TEXT_NCOLUMNS); n++;
  962.     blue_text = fe_CreateTextField(form, "blueText", args, n);
  963.     children[nchildren++] = blue_text;
  964.  
  965.     XtAddCallback(blue_text, XmNvalueChangedCallback,
  966.                   fe_color_rgb_text_cb, (XtPointer)info);
  967.  
  968.     XtManageChildren(children, nchildren);
  969.  
  970.     /*
  971.      *    Do units option menu.
  972.      */
  973.     n = 0;
  974.     pulldown = fe_CreatePulldownMenu(form, "unitsMenu", args, n);
  975.  
  976.     nchildren = 0;
  977.  
  978.     n = 0;
  979.     XtSetArg(args[n], XmNuserData, (XtPointer)0); n++;
  980.     button = XmCreatePushButtonGadget(pulldown, "decimal", args, n);
  981.     XtAddCallback(button, XmNactivateCallback, fe_color_rgb_units_cb,
  982.                   (XtPointer)info);
  983.     children[nchildren++] = button;
  984.  
  985.     n = 0;
  986.     XtSetArg(args[n], XmNuserData, (XtPointer)1); n++;
  987.     button = XmCreatePushButtonGadget(pulldown, "hex", args, n);
  988.     XtAddCallback(button, XmNactivateCallback, fe_color_rgb_units_cb,
  989.                   (XtPointer)info);
  990.     children[nchildren++] = button;
  991.  
  992.     n = 0;
  993.     XtSetArg(args[n], XmNuserData, (XtPointer)2); n++;
  994.     button = XmCreatePushButtonGadget(pulldown, "percent", args, n);
  995.     XtAddCallback(button, XmNactivateCallback, fe_color_rgb_units_cb,
  996.                   (XtPointer)info);
  997.     children[nchildren++] = button;
  998.  
  999.     XtManageChildren(children, nchildren);
  1000.  
  1001.     n = 0;
  1002.     XtSetArg(args[n], XmNsubMenuId, pulldown); n++;
  1003.     units = XmCreateOptionMenu(form, "units", args, n);
  1004.     XtManageChild(units);
  1005.     
  1006.     /*
  1007.      *    Now do attachments! We actually connect up from the
  1008.      *    bottom.
  1009.      */
  1010.     n = 0;
  1011.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  1012.     XtSetArg(args[n], XmNleftWidget, red_scale); n++;
  1013.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  1014.     XtSetArg(args[n], XmNbottomWidget, red_scale); n++;
  1015.     XtSetValues(min_label, args, n);
  1016.  
  1017.     n = 0;
  1018.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  1019.     XtSetArg(args[n], XmNrightWidget, red_scale); n++;
  1020.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  1021.     XtSetArg(args[n], XmNbottomWidget, red_scale); n++;
  1022.     XtSetValues(max_label, args, n);
  1023.  
  1024.     for (i = 0; i < 3; i++) {
  1025.  
  1026.         if (i == 0) {
  1027.             bottom = green_text;
  1028.             text = red_text;
  1029.             scale = red_scale;
  1030.             label = red_label;
  1031.         } else if (i == 1) {
  1032.             bottom = blue_text;
  1033.             text = green_text;
  1034.             scale = green_scale;
  1035.             label = green_label;
  1036.         } else {
  1037.             bottom = units;
  1038.             text = blue_text;
  1039.             scale = blue_scale;
  1040.             label = blue_label;
  1041.         }
  1042.  
  1043.         n = 0;
  1044.         XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1045.         XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  1046.         XtSetArg(args[n], XmNbottomWidget, bottom); n++;
  1047.         XtSetValues(text, args, n);
  1048.  
  1049.         n = 0;
  1050.         XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1051.         XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  1052.         XtSetArg(args[n], XmNbottomWidget, bottom); n++;
  1053.         XtSetValues(label, args, n);
  1054.  
  1055.         n = 0;
  1056.         XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  1057.         XtSetArg(args[n], XmNrightWidget, text); n++;
  1058.         XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  1059.         XtSetArg(args[n], XmNleftWidget, label); n++;
  1060.         XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  1061.         XtSetArg(args[n], XmNbottomWidget, bottom); n++;
  1062.         XtSetValues(scale, args, n);
  1063.     }
  1064.  
  1065.     n = 0;
  1066.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1067.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1068.     XtSetValues(units, args, n);
  1069.  
  1070.     info->rgb.max = max_label;
  1071.     info->rgb.red_scale = red_scale;
  1072.     info->rgb.green_scale = green_scale;
  1073.     info->rgb.blue_scale = blue_scale;
  1074.  
  1075.     info->rgb.red_text = red_text;
  1076.     info->rgb.green_text = green_text;
  1077.     info->rgb.blue_text = blue_text;
  1078.  
  1079.     info->rgb.units = units;
  1080.  
  1081.     return rgb_frame;
  1082. }
  1083.  
  1084. static Widget
  1085. fe_create_sample_group(Widget parent, fe_SamplePageInfo* info)
  1086. {
  1087.     Widget frame;
  1088.     Widget row;
  1089.     Widget old_sample;
  1090.     Widget new_sample;
  1091.     Cardinal n;
  1092.     Arg args[8];
  1093.  
  1094.     n = 0;
  1095.     XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  1096.     XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
  1097.     row = XmCreateRowColumn(parent, "sample", args, n);
  1098.     XtManageChild(row);
  1099.     frame = row;
  1100.  
  1101.     n = 0;
  1102.     old_sample = XmCreateDrawnButton(row, "oldSample", args, n);
  1103.     XtManageChild(old_sample);
  1104.  
  1105.     n = 0;
  1106.     new_sample = fe_CreateSwatch(row, "newSample", args, n);
  1107.     XtManageChild(new_sample);
  1108.  
  1109.     info->sample.old = old_sample;
  1110.     info->sample.new = new_sample;
  1111.  
  1112.     return frame;
  1113. }
  1114.  
  1115. /*
  1116.  *    rgb buttons - unused.
  1117.  */
  1118. #if 0
  1119. static Widget
  1120. fe_create_rgb_buttons_group(Widget parent, fe_RgbPageInfo* info)
  1121. {
  1122.     Widget frame;
  1123.     Widget row;
  1124.     Cardinal n;
  1125.     Arg args[8];
  1126.     XmString xm_string;
  1127.     Widget grab;
  1128.     Widget match;
  1129.  
  1130.     /*
  1131.      *    Standard colors: frame with N color buttons.
  1132.      */
  1133.     n = 0;
  1134.     frame = XmCreateFrame(parent, "buttonsFrame", args, n);
  1135.     XtManageChild(frame);
  1136.  
  1137.     n = 0;
  1138.     XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
  1139.     row = XmCreateRowColumn(frame, "buttons", args, n);
  1140.     XtManageChild(row);
  1141.  
  1142.     xm_string = XmStringCreateSimple("Dropper...");
  1143.  
  1144.     n = 0;
  1145.     XtSetArg(args[n], XmNlabelString, xm_string); n++;
  1146.     grab = XmCreatePushButtonGadget(row, "grab", args, n);
  1147.     XtManageChild(grab);
  1148.  
  1149.     XmStringFree(xm_string);
  1150.  
  1151.     xm_string = XmStringCreateSimple("Match");
  1152.  
  1153.     n = 0;
  1154.     XtSetArg(args[n], XmNlabelString, xm_string); n++;
  1155.     match = XmCreatePushButtonGadget(row, "match", args, n);
  1156.     XtManageChild(match);
  1157.  
  1158.     XmStringFree(xm_string);
  1159.  
  1160. #if 0
  1161.     Widget info_label;
  1162.  
  1163.     xm_string = XmStringCreateSimple("white");
  1164.  
  1165.     n = 0;
  1166.     XtSetArg(args[n], XmNlabelString, xm_string); n++;
  1167.     info_label = XmCreateLabelGadget(row, "info", args, n);
  1168.     XtManageChild(info_label);
  1169.  
  1170.     XmStringFree(xm_string);
  1171. #endif
  1172.  
  1173.     return frame;
  1174. }
  1175. #endif
  1176.  
  1177. static void
  1178. fe_color_page_destroy_cb(Widget form, XtPointer closure, XtPointer cbd)
  1179. {
  1180. #if 0
  1181.     fprintf(stderr, "detroying page %s\n", XtName(form));
  1182. #endif
  1183.     if (closure)
  1184.         XtFree((char*)closure);
  1185. }
  1186.  
  1187. static Widget
  1188. fe_create_rgb_page(Widget folder, char* name, fe_ColorUpdateInfo* info)
  1189. {
  1190.     Widget rgb_group;
  1191.     Widget sample_group;
  1192.     Widget form;
  1193.     Arg    args[16];
  1194.     Cardinal n;
  1195.     fe_RgbPageInfo* rgb_info = XtNew(fe_RgbPageInfo);
  1196.  
  1197.     rgb_info->update_info = info;
  1198.  
  1199.     fe_color_install_page(info,
  1200.                           (fe_ColorUpdateMethod_t)fe_color_rgb_page_update,
  1201.                           (fe_SamplePageInfo*)rgb_info);
  1202.  
  1203.     n = 0;
  1204.     form = fe_CreateTabForm(folder, name, args, n);
  1205.  
  1206.     XtAddCallback(form,
  1207.                   XmNdestroyCallback, fe_color_page_destroy_cb, rgb_info);
  1208.  
  1209.     sample_group = fe_create_sample_group(form, (fe_SamplePageInfo*)rgb_info);
  1210.     rgb_group = fe_create_rgb_group(form, rgb_info);
  1211. #ifdef DO_BUTTONS
  1212.     Widget buttons_group;
  1213.     buttons_group = fe_create_rgb_buttons_group(form, rgb_info);
  1214. #endif
  1215.  
  1216.     n = 0;
  1217.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1218.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1219.     XtSetValues(sample_group, args, n);
  1220.  
  1221. #ifdef DO_BUTTONS
  1222.     n = 0;
  1223.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1224.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1225.     XtSetArg(args[n], XmNtopWidget, sample_group); n++;
  1226.     XtSetValues(buttons_group, args, n);
  1227. #endif
  1228.  
  1229.     n = 0;
  1230.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1231.     XtSetArg(args[n], XmNtopWidget, sample_group); n++;
  1232.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1233.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1234. #ifdef DO_BUTTONS
  1235.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  1236.     XtSetArg(args[n], XmNrightWidget, buttons_group); n++;
  1237. #else
  1238.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1239. #endif
  1240.     XtSetValues(rgb_group, args, n);
  1241.  
  1242.     return form;
  1243. }
  1244.  
  1245. static void
  1246. fe_color_swatches_page_update(fe_SwatchesPageInfo* page_info,
  1247.                               Widget caller, unsigned mask)
  1248. {
  1249.     fe_ColorUpdateInfo* info = page_info->update_info;
  1250.  
  1251.     if ((mask & (XFE_COLOR_RED|XFE_COLOR_GREEN|XFE_COLOR_BLUE)) != 0) {
  1252.  
  1253.         /*
  1254.          *    Update the sample
  1255.          */
  1256.         fe_color_sample_part_update(&page_info->sample, info, caller, mask);
  1257.     }
  1258. }
  1259.  
  1260. /*
  1261.  *    reset, load, save, append buttons for matrix page. unused.
  1262.  */
  1263. #if 0
  1264. static Widget
  1265. fe_create_swatch_buttons_group(Widget parent, void* notused)
  1266. {
  1267.     Widget frame;
  1268.     Widget row;
  1269.     Cardinal n;
  1270.     Arg args[8];
  1271.     XmString xm_string;
  1272.     Widget reset;
  1273.     Widget load;
  1274.     Widget save;
  1275.     Widget append;
  1276.  
  1277.     /*
  1278.      *    Standard colors: frame with N color buttons.
  1279.      */
  1280.     n = 0;
  1281.     frame = XmCreateFrame(parent, "buttonsFrame", args, n);
  1282.     XtManageChild(frame);
  1283.  
  1284.     n = 0;
  1285.     XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
  1286.     row = XmCreateRowColumn(frame, "buttons", args, n);
  1287.     XtManageChild(row);
  1288.  
  1289.     xm_string = XmStringCreateSimple("Reset");
  1290.  
  1291.     n = 0;
  1292.     XtSetArg(args[n], XmNlabelString, xm_string); n++;
  1293.     reset = XmCreatePushButtonGadget(row, "reset", args, n);
  1294.     XtManageChild(reset);
  1295.  
  1296.     XmStringFree(xm_string);
  1297.  
  1298.     xm_string = XmStringCreateSimple("Load..");
  1299.  
  1300.     n = 0;
  1301.     XtSetArg(args[n], XmNlabelString, xm_string); n++;
  1302.     load = XmCreatePushButtonGadget(row, "load", args, n);
  1303.     XtManageChild(load);
  1304.  
  1305.     XmStringFree(xm_string);
  1306.  
  1307.     xm_string = XmStringCreateSimple("Append..");
  1308.  
  1309.     n = 0;
  1310.     XtSetArg(args[n], XmNlabelString, xm_string); n++;
  1311.     append = XmCreatePushButtonGadget(row, "append", args, n);
  1312.     XtManageChild(append);
  1313.  
  1314.     XmStringFree(xm_string);
  1315.  
  1316.     xm_string = XmStringCreateSimple("Save..");
  1317.  
  1318.     n = 0;
  1319.     XtSetArg(args[n], XmNlabelString, xm_string); n++;
  1320.     save = XmCreatePushButtonGadget(row, "save", args, n);
  1321.     XtManageChild(save);
  1322.  
  1323.     XmStringFree(xm_string);
  1324.  
  1325.     return frame;
  1326. }
  1327. #endif
  1328.  
  1329. static void
  1330. fe_swatches_activate_cb(Widget widget, XtPointer closure, XtPointer cbd)
  1331. {
  1332.     fe_SwatchesPageInfo* swatches_info = (fe_SwatchesPageInfo*) closure;
  1333.     fe_ColorUpdateInfo* info = swatches_info->update_info;
  1334.     XmDrawnButtonCallbackStruct* cbs = (XmDrawnButtonCallbackStruct*)cbd;
  1335.     int    colorn;
  1336.     XColor color;
  1337.     XButtonEvent* event = (XButtonEvent*)cbs->event;
  1338.  
  1339.     fe_SwatchMatrixGetColor(widget, event->x, event->y, &color);
  1340.  
  1341.     info->color.red = color.red;
  1342.     info->color.green = color.green;
  1343.     info->color.blue = color.blue;
  1344.     info->pixel = color.pixel;
  1345.  
  1346.     fe_color_swatches_page_update(swatches_info, widget, 
  1347.                       (XFE_COLOR_RED|XFE_COLOR_GREEN|XFE_COLOR_BLUE));
  1348. }
  1349.  
  1350. static Widget
  1351. fe_create_swatch_group(Widget parent, fe_SwatchesPageInfo* info)
  1352. {
  1353.     fe_SwatchesPart* swatches = &info->swatches;
  1354.     Widget frame;
  1355.     Widget matrix;
  1356.     Arg    args[16];
  1357.     Cardinal n;
  1358.  
  1359.     n = 0;
  1360.     frame = XmCreateFrame(parent, "swatchesFrame", args, n);
  1361.     XtManageChild(frame);
  1362.  
  1363.     n = 0;
  1364.     matrix = fe_CreateSwatchMatrix(frame, "swatches", args, n);
  1365.  
  1366.     fe_AddSwatchMatrixCallback(matrix, XmNactivateCallback, 
  1367.                                fe_swatches_activate_cb, info);
  1368.  
  1369.     XtManageChild(matrix);
  1370.  
  1371.     swatches->matrix = matrix;
  1372.  
  1373.     return frame;
  1374. }
  1375.  
  1376. static Widget
  1377. fe_create_swatch_page(Widget folder, char* name, fe_ColorUpdateInfo* info)
  1378. {
  1379.     Widget sample_group;
  1380.     Widget swatch_group;
  1381.     Widget form;
  1382.     Arg    args[16];
  1383.     Cardinal n;
  1384.     fe_SwatchesPageInfo* swatches_info = XtNew(fe_SwatchesPageInfo);
  1385.  
  1386.     fe_color_install_page(info,
  1387.                       (fe_ColorUpdateMethod_t)fe_color_swatches_page_update,
  1388.                       (fe_SamplePageInfo*)swatches_info);
  1389.  
  1390.     n = 0;
  1391.     form = fe_CreateTabForm(folder, name, args, n);
  1392.  
  1393.     XtAddCallback(form,
  1394.                   XmNdestroyCallback, fe_color_page_destroy_cb, swatches_info);
  1395.  
  1396.     sample_group = fe_create_sample_group(form, (fe_SamplePageInfo*)swatches_info);
  1397.     swatch_group = fe_create_swatch_group(form, swatches_info);
  1398. #ifdef DO_BUTTONS
  1399.     Widget buttons_group;
  1400.     buttons_group = fe_create_swatch_buttons_group(form, swatches_info);
  1401. #endif
  1402.  
  1403.     n = 0;
  1404.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  1405.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1406.     XtSetValues(sample_group, args, n);
  1407.  
  1408. #ifdef DO_BUTTONS
  1409.     n = 0;
  1410.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  1411.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1412.     XtSetArg(args[n], XmNtopWidget, sample_group); n++;
  1413.     XtSetValues(buttons_group, args, n);
  1414. #endif
  1415.  
  1416.     n = 0;
  1417.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  1418.     XtSetArg(args[n], XmNtopWidget, sample_group); n++;
  1419.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  1420. #ifdef DO_BUTTONS
  1421.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  1422.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
  1423.     XtSetArg(args[n], XmNrightWidget, buttons_group); n++;
  1424. #endif
  1425.     XtSetValues(swatch_group, args, n);
  1426.  
  1427.     return form;
  1428. }
  1429.  
  1430. static void
  1431. fe_color_page_raised_cb(Widget folder, XtPointer closure, XtPointer cbd)
  1432. {
  1433.     fe_ColorUpdateInfo* info = (fe_ColorUpdateInfo*)closure;
  1434.     fe_SamplePageInfo*  page;
  1435.  
  1436.     info->pixel = fe_color_get_pixel(folder, 
  1437.                                      info->color.red,
  1438.                                      info->color.green,
  1439.                                      info->color.blue);
  1440.  
  1441.     for (page = info->list; page != NULL; page = page->next) {
  1442.         if (page->update_method != NULL)
  1443.             (page->update_method)(page, folder, ~XFE_COLOR_INIT);
  1444.     }
  1445. }
  1446.  
  1447. Widget
  1448. fe_CreateColorPicker(Widget dialog, char* name, Arg* args, Cardinal nargs)
  1449. {
  1450.     Widget folder;
  1451.     Widget swatch_form;
  1452.     Widget rgb_form;
  1453.     Cardinal n;
  1454.     fe_ColorUpdateInfo* info;
  1455.     char* units;
  1456.     Widget parent = XtParent(dialog);
  1457.  
  1458.     info = XtNew(fe_ColorUpdateInfo); /* FIXME */
  1459.     memset(info, 0, sizeof(fe_ColorUpdateInfo));
  1460.  
  1461.     info->color.red = 0;
  1462.     info->color.green = 0;
  1463.     info->color.blue = 0;
  1464.     info->pixel = 0;
  1465.     info->units = XFE_COLOR_DECIMAL;
  1466.     info->list = NULL;
  1467.  
  1468.     units = XfeSubResourceGetStringValue(parent,
  1469.                                          XtName(parent), 
  1470.                                          "XfeColorPicker",
  1471.                                          "rgbUnits",
  1472.                                          "RgbUnits",
  1473.                                          NULL);
  1474.     if (units != NULL) {
  1475.         if (strcmp(units, "percent") == 0)
  1476.             info->units = XFE_COLOR_PERCENT;
  1477.         if (strcmp(units, "hexidecimal") == 0)
  1478.             info->units = XFE_COLOR_HEX;
  1479.     }
  1480.     
  1481.     n = 0;
  1482.     folder = XtVaCreateWidget(name, xmlFolderWidgetClass, dialog,
  1483.                               XmNshadowThickness, 2,
  1484. #ifdef ALLOW_TAB_ROTATE
  1485.                               XmNtabPlacement, XmFOLDER_LEFT,
  1486.                               XmNrotateWhenLeftRight, FALSE,
  1487. #endif /* ALLOW_TAB_ROTATE */
  1488.                               XmNbottomOffset, 3,
  1489.                               XmNspacing, 1,
  1490.                               NULL);
  1491.     XtManageChild(folder);
  1492.  
  1493.     XtAddCallback(folder,
  1494.                   XmNactivateCallback, fe_color_page_raised_cb, info);
  1495.     XtAddCallback(folder,
  1496.                   XmNdestroyCallback, fe_color_page_destroy_cb, info);
  1497.  
  1498.     n = 0;
  1499.     swatch_form = fe_create_swatch_page(folder, "swatches", info);
  1500.     XtManageChild(swatch_form);
  1501.     
  1502.     n = 0;
  1503.     rgb_form = fe_create_rgb_page(folder, "rgb", info);
  1504.     XtManageChild(rgb_form);
  1505.  
  1506.     XtVaSetValues(folder, XmNuserData, info, 0);
  1507.  
  1508.     return folder;
  1509. }
  1510.  
  1511. void
  1512. fe_ColorPickerSetColor(Widget folder, LO_Color* color)
  1513. {
  1514.     fe_ColorUpdateInfo* info;
  1515.     fe_SamplePageInfo*  page;
  1516.  
  1517.     XtVaGetValues(folder, XmNuserData, &info, 0);
  1518.     
  1519.     if (info != NULL) {
  1520.         info->color.red = color->red;
  1521.         info->color.green = color->green;
  1522.         info->color.blue = color->blue;
  1523.  
  1524.         info->pixel = fe_color_get_pixel(folder, 
  1525.                                          info->color.red,
  1526.                                          info->color.green,
  1527.                                          info->color.blue);
  1528.  
  1529.         for (page = info->list; page != NULL; page = page->next) {
  1530.             if (page->update_method != NULL)
  1531.                 (page->update_method)(page, folder, ~0);
  1532.         }
  1533.     }
  1534. }
  1535.  
  1536. void
  1537. fe_ColorPickerGetColor(Widget folder, LO_Color* color)
  1538. {
  1539.     fe_ColorUpdateInfo* info;
  1540.  
  1541.     XtVaGetValues(folder, XmNuserData, &info, 0);
  1542.     
  1543.     if (info != NULL) {
  1544.         color->red = info->color.red;
  1545.         color->green = info->color.green;
  1546.         color->blue = info->color.blue;
  1547.     }
  1548. }
  1549.  
  1550. void
  1551. fe_ColorPickerSetActiveTab(Widget folder, fe_ColorPickerTabType tab_type)
  1552. {
  1553.     unsigned tab_number = 0;
  1554.  
  1555.     switch (tab_type) {
  1556.     case XFE_COLOR_PICKER_SWATCHES:
  1557.         tab_number = 0;
  1558.         break;
  1559.     case XFE_COLOR_PICKER_RGB:
  1560.         tab_number = 1;
  1561.         break;
  1562.     case XFE_COLOR_PICKER_LAST:
  1563.         tab_number = 0; /*FIXME*/
  1564.         break;
  1565.     }
  1566.     XmLFolderSetActiveTab(folder, tab_number, False);
  1567. }
  1568.  
  1569. Widget
  1570. fe_CreateColorPickerDialog(Widget parent, char* name,
  1571.                            Arg* args, Cardinal nargs)
  1572. {
  1573.     MWContext* context = (MWContext *)fe_WidgetToMWContext(parent);
  1574.     Widget dialog;
  1575.     Widget folder;
  1576.  
  1577.     /*
  1578.      *    Make prompt with ok, cancel, no apply, no separator.
  1579.      */
  1580.     dialog = fe_CreatePromptDialog(context, name,
  1581.                                    TRUE, TRUE, FALSE, FALSE, TRUE);
  1582.  
  1583.     folder = fe_CreateColorPicker(dialog, "colorPicker", args, nargs);
  1584.     XtManageChild(folder);
  1585.  
  1586.     return dialog;
  1587. }
  1588.  
  1589. void
  1590. fe_ColorPickerDialogGetColor(Widget dialog, LO_Color* color)
  1591. {
  1592.     Widget folder = XtNameToWidget(dialog, "colorPicker");
  1593.     fe_ColorPickerGetColor(folder, color);
  1594. }
  1595.  
  1596. void
  1597. fe_ColorPickerDialogSetColor(Widget dialog, LO_Color* color)
  1598. {
  1599.     Widget folder = XtNameToWidget(dialog, "colorPicker");
  1600.     fe_ColorPickerSetColor(folder, color);
  1601. }
  1602.  
  1603. void
  1604. fe_ColorPickerDialogSetActiveTab(Widget dialog, fe_ColorPickerTabType tab_type)
  1605. {
  1606.     Widget folder = XtNameToWidget(dialog, "colorPicker");
  1607.     fe_ColorPickerSetActiveTab(folder, tab_type);
  1608. }
  1609.