WINGs: Added 'const' attribute to function 'WMCreateHashTable'
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob26ca1fcb82d933c5cd9625285aee94abe9c8aa53
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
17 /* TODO:
18 * - Look at further optimization of colorWheel matrix calculation.
19 * It appears to be rather symmetric in angles of 60 degrees,
20 * while it is optimized in angles of 90 degrees.
21 * - Custom color-lists and custom colors in custom color-lists.
22 * - Stored colors
23 * - Resizing
26 #include "wconfig.h"
27 #include "WINGsP.h"
28 #include "rgb.h"
30 #include <errno.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
39 #define RETRY( x ) do { \
40 x; \
41 } while (errno == EINTR);
43 /* BUG There's something fishy with shaped windows */
44 /* Whithout shape extension the magnified image is completely broken -Dan */
46 #ifdef USE_XSHAPE
47 # include <X11/extensions/shape.h>
48 #endif
50 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
53 * Bitmaps for magnifying glass cursor
56 /* Cursor */
57 #define Cursor_x_hot 11
58 #define Cursor_y_hot 11
59 #define Cursor_width 32
60 #define Cursor_height 32
61 static unsigned char Cursor_bits[] = {
62 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
63 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
64 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
65 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
66 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
67 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
68 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
69 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
70 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
73 /* Cursor shape-mask */
74 #define Cursor_shape_width 32
75 #define Cursor_shape_height 32
76 static unsigned char Cursor_shape_bits[] = {
77 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
78 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
79 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
80 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
81 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
82 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
83 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
84 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
85 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
88 /* Clip-mask for magnified pixels */
89 #define Cursor_mask_width 24
90 #define Cursor_mask_height 24
91 static unsigned char Cursor_mask_bits[] = {
92 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
93 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
94 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
95 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
96 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
97 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
100 typedef struct MovingView {
101 WMView *view; /* The view this is all about */
102 XImage *image; /* What's under the view */
103 XImage *dirtyRect; /* Storage of overlapped image area */
104 Pixmap magPix; /* Magnified part of pixmap */
105 RColor color; /* Color of a pixel in the image */
106 int x, y; /* Position of view */
107 } MovingView;
109 typedef struct CPColor {
110 RColor rgb; /* The RGB values of the color */
111 RHSVColor hsv; /* The HSV values of the color */
112 enum { /* Which one was last set ? */
113 cpNone,
114 cpRGB,
115 cpHSV
116 } set;
117 } CPColor;
119 typedef struct WheelMatrix {
120 unsigned int width, height; /* Size of the colorwheel */
121 unsigned char *data[3]; /* Wheel data (R,G,B) */
122 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
123 } wheelMatrix;
125 typedef struct W_ColorPanel {
126 WMWindow *win;
127 WMFont *font8;
128 WMFont *font12;
129 void *clientData;
130 WMAction2 *action;
132 /* Common Stuff */
133 WMColorWell *colorWell;
134 WMButton *magnifyBtn;
135 WMButton *wheelBtn;
136 WMButton *slidersBtn;
137 WMButton *customPaletteBtn;
138 WMButton *colorListBtn;
140 /* Magnifying Glass */
141 MovingView *magnifyGlass;
143 /* ColorWheel Panel */
144 WMFrame *wheelFrm;
145 WMSlider *wheelBrightnessS;
146 WMView *wheelView;
148 /* Slider Panels */
149 WMFrame *slidersFrm;
150 WMFrame *seperatorFrm;
151 WMButton *grayBtn;
152 WMButton *rgbBtn;
153 WMButton *cmykBtn;
154 WMButton *hsbBtn;
155 /* Gray Scale Panel */
156 WMFrame *grayFrm;
157 WMLabel *grayMinL;
158 WMLabel *grayMaxL;
159 WMSlider *grayBrightnessS;
160 WMTextField *grayBrightnessT;
161 WMButton *grayPresetBtn[7];
163 /* RGB Panel */
164 WMFrame *rgbFrm;
165 WMLabel *rgbMinL;
166 WMLabel *rgbMaxL;
167 WMSlider *rgbRedS;
168 WMSlider *rgbGreenS;
169 WMSlider *rgbBlueS;
170 WMTextField *rgbRedT;
171 WMTextField *rgbGreenT;
172 WMTextField *rgbBlueT;
174 /* CMYK Panel */
175 WMFrame *cmykFrm;
176 WMLabel *cmykMinL;
177 WMLabel *cmykMaxL;
178 WMSlider *cmykCyanS;
179 WMSlider *cmykMagentaS;
180 WMSlider *cmykYellowS;
181 WMSlider *cmykBlackS;
182 WMTextField *cmykCyanT;
183 WMTextField *cmykMagentaT;
184 WMTextField *cmykYellowT;
185 WMTextField *cmykBlackT;
187 /* HSB Panel */
188 WMFrame *hsbFrm;
189 WMSlider *hsbHueS;
190 WMSlider *hsbSaturationS;
191 WMSlider *hsbBrightnessS;
192 WMTextField *hsbHueT;
193 WMTextField *hsbSaturationT;
194 WMTextField *hsbBrightnessT;
196 /* Custom Palette Panel */
197 WMFrame *customPaletteFrm;
198 WMPopUpButton *customPaletteHistoryBtn;
199 WMFrame *customPaletteContentFrm;
200 WMPopUpButton *customPaletteMenuBtn;
201 WMView *customPaletteContentView;
203 /* Color List Panel */
204 WMFrame *colorListFrm;
205 WMPopUpButton *colorListHistoryBtn;
206 WMList *colorListContentLst;
207 WMPopUpButton *colorListColorMenuBtn;
208 WMPopUpButton *colorListListMenuBtn;
210 /* Look-Up Tables and Images */
211 wheelMatrix *wheelMtrx;
212 Pixmap wheelImg;
213 Pixmap selectionImg;
214 Pixmap selectionBackImg;
215 RImage *customPaletteImg;
216 char *lastBrowseDir;
218 /* Common Data Fields */
219 CPColor color; /* Current color */
220 WMColorPanelMode mode; /* Current color selection mode */
221 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
222 WMColorPanelMode lastChanged; /* Panel that last changed the color */
223 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
224 int palx, paly; /* (x,y) of sel.-marker in
225 CustomPaletteMode */
226 double palXRatio, palYRatio; /* Ratios in x & y between
227 original and scaled
228 palettesize */
229 int currentPalette;
230 char *configurationPath;
232 struct {
233 unsigned int continuous:1;
234 unsigned int dragging:1;
235 } flags;
236 } W_ColorPanel;
238 enum {
239 CPmenuNewFromFile,
240 CPmenuRename,
241 CPmenuRemove,
242 CPmenuCopy,
243 CPmenuNewFromClipboard
244 } customPaletteMenuItem;
246 enum {
247 CLmenuAdd,
248 CLmenuRename,
249 CLmenuRemove
250 } colorListMenuItem;
252 #define PWIDTH 194
253 #define PHEIGHT 266
254 #define colorWheelSize 150
255 #define customPaletteWidth 182
256 #define customPaletteHeight 106
257 #define knobThickness 8
259 #define SPECTRUM_WIDTH 511
260 #define SPECTRUM_HEIGHT 360
262 #define COLORWHEEL_PART 1
263 #define CUSTOMPALETTE_PART 2
264 #define BUFSIZE 1024
266 #define MAX_LENGTH 1024
268 #ifndef M_PI
269 #define M_PI 3.14159265358979323846
270 #endif
272 static char *generateNewFilename(const char *curName);
273 static void convertCPColor(CPColor * color);
274 static RColor ulongToRColor(WMScreen * scr, unsigned long value);
275 static unsigned char getShift(unsigned char value);
277 static void modeButtonCallback(WMWidget * w, void *data);
278 static int getPickerPart(W_ColorPanel * panel, int x, int y);
279 static void readConfiguration(W_ColorPanel * panel);
280 static void readXColors(W_ColorPanel * panel);
282 static void closeWindowCallback(WMWidget * w, void *data);
284 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
285 static WMPoint magnifyInitialize(W_ColorPanel * panel);
286 static void magnifyPutCursor(WMWidget * w, void *data);
287 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
288 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
289 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
291 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
292 static void wheelDestroyMatrix(wheelMatrix * matrix);
293 static void wheelInitMatrix(W_ColorPanel * panel);
294 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
295 static void wheelRender(W_ColorPanel * panel);
296 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
297 static void wheelPaint(W_ColorPanel * panel);
299 static void wheelHandleEvents(XEvent * event, void *data);
300 static void wheelHandleActionEvents(XEvent * event, void *data);
301 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
302 static void wheelUpdateSelection(W_ColorPanel * panel);
303 static void wheelUndrawSelection(W_ColorPanel * panel);
305 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
306 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
307 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
308 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
310 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
311 static void grayPresetButtonCallback(WMWidget * w, void *data);
312 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
314 static void rgbSliderCallback(WMWidget * w, void *data);
315 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
317 static void cmykSliderCallback(WMWidget * w, void *data);
318 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
320 static void hsbSliderCallback(WMWidget * w, void *data);
321 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
322 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
323 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
324 static void hsbUpdateHueGradient(W_ColorPanel * panel);
326 static void customRenderSpectrum(W_ColorPanel * panel);
327 static void customSetPalette(W_ColorPanel * panel);
328 static void customPaletteHandleEvents(XEvent * event, void *data);
329 static void customPaletteHandleActionEvents(XEvent * event, void *data);
330 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
331 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
332 static void customPaletteMenuCallback(WMWidget * w, void *data);
333 static void customPaletteHistoryCallback(WMWidget * w, void *data);
335 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
336 static void customPaletteMenuRename(W_ColorPanel * panel);
337 static void customPaletteMenuRemove(W_ColorPanel * panel);
339 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
340 static void colorListSelect(WMWidget * w, void *data);
341 static void colorListColorMenuCallback(WMWidget * w, void *data);
342 static void colorListListMenuCallback(WMWidget * w, void *data);
343 static void colorListListMenuNew(W_ColorPanel * panel);
345 static void wheelInit(W_ColorPanel * panel);
346 static void grayInit(W_ColorPanel * panel);
347 static void rgbInit(W_ColorPanel * panel);
348 static void cmykInit(W_ColorPanel * panel);
349 static void hsbInit(W_ColorPanel * panel);
351 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
353 panel->action = action;
354 panel->clientData = data;
357 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
359 WMColorPanel *panel;
360 RImage *image;
361 WMPixmap *pixmap;
362 RColor from;
363 RColor to;
364 WMColor *textcolor, *graybuttoncolor;
365 int i;
366 GC bgc = WMColorGC(scrPtr->black);
367 GC wgc = WMColorGC(scrPtr->white);
369 panel = wmalloc(sizeof(WMColorPanel));
370 panel->color.rgb.red = 0;
371 panel->color.rgb.green = 0;
372 panel->color.rgb.blue = 0;
373 panel->color.hsv.hue = 0;
374 panel->color.hsv.saturation = 0;
375 panel->color.hsv.value = 0;
376 panel->color.set = cpNone; /* Color has not been set yet */
378 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
379 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
381 panel->win = WMCreateWindowWithStyle(scrPtr, name,
382 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
383 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
384 WMSetWindowTitle(panel->win, _("Colors"));
385 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
387 /* Set Default ColorPanel Mode(s) */
388 panel->mode = WMWheelModeColorPanel;
389 panel->lastChanged = 0;
390 panel->slidersmode = WMRGBModeColorPanel;
391 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
393 /* Some General Purpose Widgets */
394 panel->colorWell = WMCreateColorWell(panel->win);
395 WMResizeWidget(panel->colorWell, 134, 36);
396 WSetColorWellBordered(panel->colorWell, False);
397 WMMoveWidget(panel->colorWell, 56, 4);
399 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
400 WMResizeWidget(panel->magnifyBtn, 46, 36);
401 WMMoveWidget(panel->magnifyBtn, 6, 4);
402 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
403 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
404 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
406 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
407 WMResizeWidget(panel->wheelBtn, 46, 32);
408 WMMoveWidget(panel->wheelBtn, 6, 44);
409 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
410 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
411 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
413 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
414 WMResizeWidget(panel->slidersBtn, 46, 32);
415 WMMoveWidget(panel->slidersBtn, 52, 44);
416 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
417 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
418 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
420 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
421 WMResizeWidget(panel->customPaletteBtn, 46, 32);
422 WMMoveWidget(panel->customPaletteBtn, 98, 44);
423 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
424 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
425 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
427 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
428 WMResizeWidget(panel->colorListBtn, 46, 32);
429 WMMoveWidget(panel->colorListBtn, 144, 44);
430 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
431 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
432 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
434 /* Let's Group some of them together */
435 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
436 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
437 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
439 /* Widgets for the ColorWheel Panel */
440 panel->wheelFrm = WMCreateFrame(panel->win);
441 WMSetFrameRelief(panel->wheelFrm, WRFlat);
442 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
443 WMMoveWidget(panel->wheelFrm, 5, 80);
445 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
446 /* XXX Can we create a view ? */
447 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
448 W_MoveView(panel->wheelView, 0, 0);
450 /* Create an event handler to handle expose/click events in ColorWheel */
451 WMCreateEventHandler(panel->wheelView,
452 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
453 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
455 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
457 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
458 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
459 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
460 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
461 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
462 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
463 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
465 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
466 wheelInitMatrix(panel);
468 /* Widgets for the Slider Panels */
469 panel->slidersFrm = WMCreateFrame(panel->win);
470 WMSetFrameRelief(panel->slidersFrm, WRFlat);
471 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
472 WMMoveWidget(panel->slidersFrm, 4, 80);
474 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
475 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
476 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
477 WMMoveWidget(panel->seperatorFrm, 0, 1);
479 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
480 WMResizeWidget(panel->grayBtn, 46, 24);
481 WMMoveWidget(panel->grayBtn, 1, 8);
482 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
483 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
484 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
486 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
487 WMResizeWidget(panel->rgbBtn, 46, 24);
488 WMMoveWidget(panel->rgbBtn, 47, 8);
489 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
490 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
491 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
493 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
494 WMResizeWidget(panel->cmykBtn, 46, 24);
495 WMMoveWidget(panel->cmykBtn, 93, 8);
496 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
497 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
498 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
500 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
501 WMResizeWidget(panel->hsbBtn, 46, 24);
502 WMMoveWidget(panel->hsbBtn, 139, 8);
503 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
504 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
505 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
507 /* Let's Group the Slider Panel Buttons Together */
508 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
509 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
510 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
512 textcolor = WMDarkGrayColor(scrPtr);
514 /* Widgets for GrayScale Panel */
515 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
516 WMSetFrameRelief(panel->grayFrm, WRFlat);
517 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
518 WMMoveWidget(panel->grayFrm, 0, 34);
520 panel->grayMinL = WMCreateLabel(panel->grayFrm);
521 WMResizeWidget(panel->grayMinL, 20, 10);
522 WMMoveWidget(panel->grayMinL, 2, 2);
523 WMSetLabelText(panel->grayMinL, "0");
524 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
525 WMSetLabelTextColor(panel->grayMinL, textcolor);
526 WMSetLabelFont(panel->grayMinL, panel->font8);
528 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
529 WMResizeWidget(panel->grayMaxL, 40, 10);
530 WMMoveWidget(panel->grayMaxL, 104, 2);
531 WMSetLabelText(panel->grayMaxL, "100");
532 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
533 WMSetLabelTextColor(panel->grayMaxL, textcolor);
534 WMSetLabelFont(panel->grayMaxL, panel->font8);
536 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
537 WMResizeWidget(panel->grayBrightnessS, 141, 16);
538 WMMoveWidget(panel->grayBrightnessS, 2, 14);
539 WMSetSliderMinValue(panel->grayBrightnessS, 0);
540 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
541 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
542 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
544 from.red = 0;
545 from.green = 0;
546 from.blue = 0;
548 to.red = 255;
549 to.green = 255;
550 to.blue = 255;
552 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
553 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
554 RReleaseImage(image);
556 if (pixmap)
557 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
558 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
559 False, _("Brightness"), strlen(_("Brightness")));
560 else
561 wwarning(_("Color Panel: Could not allocate memory"));
563 WMSetSliderImage(panel->grayBrightnessS, pixmap);
564 WMReleasePixmap(pixmap);
566 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
567 WMResizeWidget(panel->grayBrightnessT, 40, 18);
568 WMMoveWidget(panel->grayBrightnessT, 146, 13);
569 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
570 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
571 WMTextDidEndEditingNotification, panel->grayBrightnessT);
573 for (i = 0; i < 7; i++) {
574 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
576 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
577 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
578 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
579 WMReleaseColor(graybuttoncolor);
581 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
582 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
583 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
584 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
585 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
586 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
587 WMReleasePixmap(pixmap);
591 /* End of GrayScale Panel */
593 /* Widgets for RGB Panel */
594 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
595 WMSetFrameRelief(panel->rgbFrm, WRFlat);
596 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
597 WMMoveWidget(panel->rgbFrm, 0, 34);
599 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
600 WMResizeWidget(panel->rgbMinL, 20, 10);
601 WMMoveWidget(panel->rgbMinL, 2, 2);
602 WMSetLabelText(panel->rgbMinL, "0");
603 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
604 WMSetLabelTextColor(panel->rgbMinL, textcolor);
605 WMSetLabelFont(panel->rgbMinL, panel->font8);
607 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
608 WMResizeWidget(panel->rgbMaxL, 40, 10);
609 WMMoveWidget(panel->rgbMaxL, 104, 2);
610 WMSetLabelText(panel->rgbMaxL, "255");
611 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
612 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
613 WMSetLabelFont(panel->rgbMaxL, panel->font8);
615 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
616 WMResizeWidget(panel->rgbRedS, 141, 16);
617 WMMoveWidget(panel->rgbRedS, 2, 14);
618 WMSetSliderMinValue(panel->rgbRedS, 0);
619 WMSetSliderMaxValue(panel->rgbRedS, 255);
620 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
621 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
623 to.red = 255;
624 to.green = 0;
625 to.blue = 0;
627 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
628 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
629 RReleaseImage(image);
631 if (pixmap)
632 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
633 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
634 else
635 wwarning(_("Color Panel: Could not allocate memory"));
637 WMSetSliderImage(panel->rgbRedS, pixmap);
638 WMReleasePixmap(pixmap);
640 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
641 WMResizeWidget(panel->rgbRedT, 40, 18);
642 WMMoveWidget(panel->rgbRedT, 146, 13);
643 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
644 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
646 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
647 WMResizeWidget(panel->rgbGreenS, 141, 16);
648 WMMoveWidget(panel->rgbGreenS, 2, 36);
649 WMSetSliderMinValue(panel->rgbGreenS, 0);
650 WMSetSliderMaxValue(panel->rgbGreenS, 255);
651 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
652 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
654 to.red = 0;
655 to.green = 255;
656 to.blue = 0;
658 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
659 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
660 RReleaseImage(image);
662 if (pixmap)
663 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
664 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
665 else
666 wwarning(_("Color Panel: Could not allocate memory"));
668 WMSetSliderImage(panel->rgbGreenS, pixmap);
669 WMReleasePixmap(pixmap);
671 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
672 WMResizeWidget(panel->rgbGreenT, 40, 18);
673 WMMoveWidget(panel->rgbGreenT, 146, 35);
674 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
675 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
677 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
678 WMResizeWidget(panel->rgbBlueS, 141, 16);
679 WMMoveWidget(panel->rgbBlueS, 2, 58);
680 WMSetSliderMinValue(panel->rgbBlueS, 0);
681 WMSetSliderMaxValue(panel->rgbBlueS, 255);
682 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
683 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
685 to.red = 0;
686 to.green = 0;
687 to.blue = 255;
689 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
690 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
691 RReleaseImage(image);
693 if (pixmap)
694 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
695 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
696 else
697 wwarning(_("Color Panel: Could not allocate memory"));
699 WMSetSliderImage(panel->rgbBlueS, pixmap);
700 WMReleasePixmap(pixmap);
702 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
703 WMResizeWidget(panel->rgbBlueT, 40, 18);
704 WMMoveWidget(panel->rgbBlueT, 146, 57);
705 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
706 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
707 /* End of RGB Panel */
709 /* Widgets for CMYK Panel */
710 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
711 WMSetFrameRelief(panel->cmykFrm, WRFlat);
712 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
713 WMMoveWidget(panel->cmykFrm, 0, 34);
715 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
716 WMResizeWidget(panel->cmykMinL, 20, 10);
717 WMMoveWidget(panel->cmykMinL, 2, 2);
718 WMSetLabelText(panel->cmykMinL, "0");
719 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
720 WMSetLabelTextColor(panel->cmykMinL, textcolor);
721 WMSetLabelFont(panel->cmykMinL, panel->font8);
723 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
724 WMResizeWidget(panel->cmykMaxL, 40, 10);
725 WMMoveWidget(panel->cmykMaxL, 104, 2);
726 WMSetLabelText(panel->cmykMaxL, "100");
727 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
728 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
729 WMSetLabelFont(panel->cmykMaxL, panel->font8);
731 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
732 WMResizeWidget(panel->cmykCyanS, 141, 16);
733 WMMoveWidget(panel->cmykCyanS, 2, 14);
734 WMSetSliderMinValue(panel->cmykCyanS, 0);
735 WMSetSliderMaxValue(panel->cmykCyanS, 100);
736 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
737 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
739 from.red = 255;
740 from.green = 255;
741 from.blue = 255;
743 to.red = 0;
744 to.green = 255;
745 to.blue = 255;
747 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
748 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
749 RReleaseImage(image);
751 if (pixmap)
752 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
753 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
754 else
755 wwarning(_("Color Panel: Could not allocate memory"));
757 WMSetSliderImage(panel->cmykCyanS, pixmap);
758 WMReleasePixmap(pixmap);
760 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
761 WMResizeWidget(panel->cmykCyanT, 40, 18);
762 WMMoveWidget(panel->cmykCyanT, 146, 13);
763 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
764 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
766 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
767 WMResizeWidget(panel->cmykMagentaS, 141, 16);
768 WMMoveWidget(panel->cmykMagentaS, 2, 36);
769 WMSetSliderMinValue(panel->cmykMagentaS, 0);
770 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
771 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
772 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
774 to.red = 255;
775 to.green = 0;
776 to.blue = 255;
778 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
779 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
780 RReleaseImage(image);
782 if (pixmap)
783 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
784 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
785 else
786 wwarning(_("Color Panel: Could not allocate memory"));
788 WMSetSliderImage(panel->cmykMagentaS, pixmap);
789 WMReleasePixmap(pixmap);
791 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
792 WMResizeWidget(panel->cmykMagentaT, 40, 18);
793 WMMoveWidget(panel->cmykMagentaT, 146, 35);
794 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
795 WMAddNotificationObserver(cmykTextFieldCallback, panel,
796 WMTextDidEndEditingNotification, panel->cmykMagentaT);
798 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
799 WMResizeWidget(panel->cmykYellowS, 141, 16);
800 WMMoveWidget(panel->cmykYellowS, 2, 58);
801 WMSetSliderMinValue(panel->cmykYellowS, 0);
802 WMSetSliderMaxValue(panel->cmykYellowS, 100);
803 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
804 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
806 to.red = 255;
807 to.green = 255;
808 to.blue = 0;
810 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
811 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
812 RReleaseImage(image);
814 if (pixmap)
815 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
816 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
817 else
818 wwarning(_("Color Panel: Could not allocate memory"));
820 WMSetSliderImage(panel->cmykYellowS, pixmap);
821 WMReleasePixmap(pixmap);
823 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
824 WMResizeWidget(panel->cmykYellowT, 40, 18);
825 WMMoveWidget(panel->cmykYellowT, 146, 57);
826 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
827 WMAddNotificationObserver(cmykTextFieldCallback, panel,
828 WMTextDidEndEditingNotification, panel->cmykYellowT);
830 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
831 WMResizeWidget(panel->cmykBlackS, 141, 16);
832 WMMoveWidget(panel->cmykBlackS, 2, 80);
833 WMSetSliderMinValue(panel->cmykBlackS, 0);
834 WMSetSliderMaxValue(panel->cmykBlackS, 100);
835 WMSetSliderValue(panel->cmykBlackS, 0);
836 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
837 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
839 to.red = 0;
840 to.green = 0;
841 to.blue = 0;
843 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
844 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
845 RReleaseImage(image);
847 if (pixmap)
848 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
849 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
850 else
851 wwarning(_("Color Panel: Could not allocate memory"));
853 WMSetSliderImage(panel->cmykBlackS, pixmap);
854 WMReleasePixmap(pixmap);
856 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
857 WMResizeWidget(panel->cmykBlackT, 40, 18);
858 WMMoveWidget(panel->cmykBlackT, 146, 79);
859 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
860 WMAddNotificationObserver(cmykTextFieldCallback, panel,
861 WMTextDidEndEditingNotification, panel->cmykBlackT);
862 /* End of CMYK Panel */
864 /* Widgets for HSB Panel */
865 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
866 WMSetFrameRelief(panel->hsbFrm, WRFlat);
867 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
868 WMMoveWidget(panel->hsbFrm, 0, 34);
870 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
871 WMResizeWidget(panel->hsbHueS, 141, 16);
872 WMMoveWidget(panel->hsbHueS, 2, 14);
873 WMSetSliderMinValue(panel->hsbHueS, 0);
874 WMSetSliderMaxValue(panel->hsbHueS, 359);
875 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
876 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
878 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
879 WMResizeWidget(panel->hsbHueT, 40, 18);
880 WMMoveWidget(panel->hsbHueT, 146, 13);
881 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
882 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
884 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
885 WMResizeWidget(panel->hsbSaturationS, 141, 16);
886 WMMoveWidget(panel->hsbSaturationS, 2, 36);
887 WMSetSliderMinValue(panel->hsbSaturationS, 0);
888 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
889 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
890 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
892 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
893 WMResizeWidget(panel->hsbSaturationT, 40, 18);
894 WMMoveWidget(panel->hsbSaturationT, 146, 35);
895 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
896 WMAddNotificationObserver(hsbTextFieldCallback, panel,
897 WMTextDidEndEditingNotification, panel->hsbSaturationT);
899 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
900 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
901 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
902 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
903 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
904 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
905 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
907 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
908 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
909 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
910 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
911 WMAddNotificationObserver(hsbTextFieldCallback, panel,
912 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
913 /* End of HSB Panel */
915 WMReleaseColor(textcolor);
917 /* Widgets for the CustomPalette Panel */
918 panel->customPaletteFrm = WMCreateFrame(panel->win);
919 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
920 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
921 WMMoveWidget(panel->customPaletteFrm, 5, 80);
923 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
924 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
925 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
926 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
927 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
928 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
929 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
931 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
932 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
933 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
934 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
936 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
937 /* XXX Test if we can create a view */
938 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
939 W_MoveView(panel->customPaletteContentView, 2, 2);
941 /* Create event handler to handle expose/click events in CustomPalette */
942 WMCreateEventHandler(panel->customPaletteContentView,
943 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
944 ButtonMotionMask, customPaletteHandleActionEvents, panel);
946 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
948 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
949 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
950 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
951 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
952 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
953 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
955 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
956 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
957 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
958 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
959 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
961 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
962 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
963 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
964 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
966 customRenderSpectrum(panel);
967 panel->currentPalette = 0;
968 panel->palx = customPaletteWidth / 2;
969 panel->paly = customPaletteHeight / 2;
971 /* Widgets for the ColorList Panel */
972 panel->colorListFrm = WMCreateFrame(panel->win);
973 WMSetFrameRelief(panel->colorListFrm, WRFlat);
974 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
975 WMMoveWidget(panel->colorListFrm, 5, 80);
977 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
978 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
979 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
980 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
981 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
982 * colorListHistoryCallback, panel); */
983 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
984 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
986 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
987 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
988 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
989 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
990 WMMoveWidget(panel->colorListContentLst, 0, 23);
991 WMHangData(panel->colorListContentLst, panel);
993 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
994 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
995 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
996 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
997 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
998 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1000 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1001 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1002 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1004 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1005 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1006 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1008 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1009 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1010 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1011 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1012 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1013 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1015 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1016 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1017 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1019 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1020 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1021 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1023 WMRealizeWidget(panel->win);
1024 WMMapSubwidgets(panel->win);
1026 WMMapSubwidgets(panel->wheelFrm);
1027 WMMapSubwidgets(panel->slidersFrm);
1028 WMMapSubwidgets(panel->grayFrm);
1029 WMMapSubwidgets(panel->rgbFrm);
1030 WMMapSubwidgets(panel->cmykFrm);
1031 WMMapSubwidgets(panel->hsbFrm);
1032 WMMapSubwidgets(panel->customPaletteFrm);
1033 WMMapSubwidgets(panel->customPaletteContentFrm);
1034 WMMapSubwidgets(panel->colorListFrm);
1036 /* Pixmap to indicate selection positions
1037 * wheelframe MUST be mapped.
1039 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1040 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1041 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1043 readConfiguration(panel);
1044 readXColors(panel);
1046 return panel;
1049 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1051 WMColorPanel *panel;
1053 if (scrPtr->sharedColorPanel)
1054 return scrPtr->sharedColorPanel;
1056 panel = makeColorPanel(scrPtr, "colorPanel");
1058 scrPtr->sharedColorPanel = panel;
1060 return panel;
1063 void WMFreeColorPanel(WMColorPanel * panel)
1065 W_Screen *scr = WMWidgetScreen(panel->win);
1067 if (panel == scr->sharedColorPanel) {
1068 scr->sharedColorPanel = NULL;
1071 if (!panel)
1072 return;
1074 WMRemoveNotificationObserver(panel);
1075 WMUnmapWidget(panel->win);
1077 /* fonts */
1078 WMReleaseFont(panel->font8);
1079 WMReleaseFont(panel->font12);
1081 /* pixmaps */
1082 wheelDestroyMatrix(panel->wheelMtrx);
1083 if (panel->wheelImg)
1084 XFreePixmap(scr->display, panel->wheelImg);
1085 if (panel->selectionImg)
1086 XFreePixmap(scr->display, panel->selectionImg);
1087 if (panel->selectionBackImg)
1088 XFreePixmap(scr->display, panel->selectionBackImg);
1089 RReleaseImage(panel->customPaletteImg);
1091 /* structs */
1092 if (panel->lastBrowseDir)
1093 wfree(panel->lastBrowseDir);
1094 if (panel->configurationPath)
1095 wfree(panel->configurationPath);
1097 WMDestroyWidget(panel->win);
1099 wfree(panel);
1102 void WMCloseColorPanel(WMColorPanel * panel)
1104 WMFreeColorPanel(panel);
1107 void WMShowColorPanel(WMColorPanel * panel)
1109 WMScreen *scr = WMWidgetScreen(panel->win);
1110 WMColor *white = WMWhiteColor(scr);
1112 if (panel->color.set == cpNone)
1113 WMSetColorPanelColor(panel, white);
1114 WMReleaseColor(white);
1116 if (panel->mode != WMWheelModeColorPanel)
1117 WMPerformButtonClick(panel->wheelBtn);
1119 WMMapWidget(panel->win);
1122 static void closeWindowCallback(WMWidget * w, void *data)
1124 W_ColorPanel *panel = (W_ColorPanel *) data;
1126 /* Parameter not used, but tell the compiler that it is ok */
1127 (void) w;
1129 WMCloseColorPanel(panel);
1132 static void readConfiguration(W_ColorPanel * panel)
1134 /* XXX Doesn't take care of "invalid" files */
1136 DIR *dPtr;
1137 struct dirent *dp;
1138 struct stat stat_buf;
1139 int item;
1141 if (stat(panel->configurationPath, &stat_buf) != 0) {
1142 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1143 werror(_("Color Panel: Could not create directory %s needed"
1144 " to store configurations"), panel->configurationPath);
1145 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1146 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1147 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1148 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1149 _("File Error"),
1150 _("Could not create ColorPanel configuration directory"),
1151 _("OK"), NULL, NULL);
1153 return;
1156 if (!(dPtr = opendir(panel->configurationPath))) {
1157 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1158 return;
1161 while ((dp = readdir(dPtr)) != NULL) {
1162 unsigned int perm_mask;
1163 char *path = wstrconcat(panel->configurationPath,
1164 dp->d_name);
1166 if (dp->d_name[0] != '.') {
1167 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1168 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1170 perm_mask = (access(path, R_OK) == 0);
1171 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1173 wfree(path);
1175 closedir(dPtr);
1178 static void readXColors(W_ColorPanel * panel)
1180 WMListItem *item;
1181 const RGBColor *entry;
1183 for (entry = rgbColors; entry->name != NULL; entry++) {
1184 item = WMAddListItem(panel->colorListContentLst, entry->name);
1185 item->clientData = (void *)&(entry->color);
1189 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1191 W_Screen *scr = WMWidgetScreen(panel->win);
1193 if (mode != WMWheelModeColorPanel) {
1194 WMUnmapWidget(panel->wheelFrm);
1195 if (panel->selectionBackImg) {
1196 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1197 panel->selectionBackImg = None;
1200 if (mode != WMGrayModeColorPanel)
1201 WMUnmapWidget(panel->grayFrm);
1202 if (mode != WMRGBModeColorPanel)
1203 WMUnmapWidget(panel->rgbFrm);
1204 if (mode != WMCMYKModeColorPanel)
1205 WMUnmapWidget(panel->cmykFrm);
1206 if (mode != WMHSBModeColorPanel)
1207 WMUnmapWidget(panel->hsbFrm);
1208 if (mode != WMCustomPaletteModeColorPanel) {
1209 WMUnmapWidget(panel->customPaletteFrm);
1210 if (panel->selectionBackImg) {
1211 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1212 panel->selectionBackImg = None;
1215 if (mode != WMColorListModeColorPanel)
1216 WMUnmapWidget(panel->colorListFrm);
1217 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1218 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1219 WMUnmapWidget(panel->slidersFrm);
1220 else
1221 panel->slidersmode = mode;
1223 if (mode == WMWheelModeColorPanel) {
1224 WMMapWidget(panel->wheelFrm);
1225 WMSetButtonSelected(panel->wheelBtn, True);
1226 if (panel->lastChanged != WMWheelModeColorPanel)
1227 wheelInit(panel);
1228 wheelRender(panel);
1229 wheelPaint(panel);
1230 } else if (mode == WMGrayModeColorPanel) {
1231 WMMapWidget(panel->slidersFrm);
1232 WMSetButtonSelected(panel->slidersBtn, True);
1233 WMMapWidget(panel->grayFrm);
1234 WMSetButtonSelected(panel->grayBtn, True);
1235 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1236 if (panel->lastChanged != WMGrayModeColorPanel)
1237 grayInit(panel);
1238 } else if (mode == WMRGBModeColorPanel) {
1239 WMMapWidget(panel->slidersFrm);
1240 WMSetButtonSelected(panel->slidersBtn, True);
1241 WMMapWidget(panel->rgbFrm);
1242 WMSetButtonSelected(panel->rgbBtn, True);
1243 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1244 if (panel->lastChanged != WMRGBModeColorPanel)
1245 rgbInit(panel);
1246 } else if (mode == WMCMYKModeColorPanel) {
1247 WMMapWidget(panel->slidersFrm);
1248 WMSetButtonSelected(panel->slidersBtn, True);
1249 WMMapWidget(panel->cmykFrm);
1250 WMSetButtonSelected(panel->cmykBtn, True);
1251 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1252 if (panel->lastChanged != WMCMYKModeColorPanel)
1253 cmykInit(panel);
1254 } else if (mode == WMHSBModeColorPanel) {
1255 WMMapWidget(panel->slidersFrm);
1256 WMSetButtonSelected(panel->slidersBtn, True);
1257 WMMapWidget(panel->hsbFrm);
1258 WMSetButtonSelected(panel->hsbBtn, True);
1259 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1260 if (panel->lastChanged != WMHSBModeColorPanel)
1261 hsbInit(panel);
1262 } else if (mode == WMCustomPaletteModeColorPanel) {
1263 WMMapWidget(panel->customPaletteFrm);
1264 WMSetButtonSelected(panel->customPaletteBtn, True);
1265 customSetPalette(panel);
1266 } else if (mode == WMColorListModeColorPanel) {
1267 WMMapWidget(panel->colorListFrm);
1268 WMSetButtonSelected(panel->colorListBtn, True);
1271 panel->mode = mode;
1274 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1276 return WMGetColorWellColor(panel->colorWell);
1279 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1281 WMSetColorWellColor(panel->colorWell, color);
1283 panel->color.rgb.red = color->color.red >> 8;
1284 panel->color.rgb.green = color->color.green >> 8;
1285 panel->color.rgb.blue = color->color.blue >> 8;
1286 panel->color.set = cpRGB;
1288 if (panel->mode == panel->lastChanged)
1289 panel->lastChanged = 0;
1291 WMSetColorPanelPickerMode(panel, panel->mode);
1294 static void updateSwatch(WMColorPanel * panel, CPColor color)
1296 WMScreen *scr = WMWidgetScreen(panel->win);
1297 WMColor *wellcolor;
1299 if (color.set != cpRGB)
1300 convertCPColor(&color);
1302 panel->color = color;
1304 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1306 WMSetColorWellColor(panel->colorWell, wellcolor);
1307 WMReleaseColor(wellcolor);
1309 if (!panel->flags.dragging || panel->flags.continuous) {
1310 if (panel->action)
1311 (*panel->action) (panel, panel->clientData);
1313 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1317 static void modeButtonCallback(WMWidget * w, void *data)
1319 W_ColorPanel *panel = (W_ColorPanel *) (data);
1321 if (w == panel->wheelBtn)
1322 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1323 else if (w == panel->slidersBtn)
1324 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1325 else if (w == panel->customPaletteBtn)
1326 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1327 else if (w == panel->colorListBtn)
1328 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1329 else if (w == panel->grayBtn)
1330 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1331 else if (w == panel->rgbBtn)
1332 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1333 else if (w == panel->cmykBtn)
1334 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1335 else if (w == panel->hsbBtn)
1336 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1339 /****************** Magnifying Cursor Functions *******************/
1341 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1343 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1344 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1345 displayHeight = DisplayHeight(scr->display, scr->screen);
1347 if (!(image && image->data)) {
1348 /* The image in panel->magnifyGlass->image does not exist yet.
1349 * Grab one from the screen (not beyond) and use it from now on.
1351 if (!(image = XGetImage(scr->display, scr->rootWin,
1352 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1353 wwarning(_("Color Panel: X failed request"));
1355 return image;
1358 /* Coordinate correction for back pixmap
1359 * if magnifying glass is at screen-borders
1362 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1363 * Hatched area is beyond screen border.
1365 * |<-Cursor_x_hot->|
1366 * ________________|_____
1367 * |/ / / / / / /| | |
1368 * | / / / / / / |(x,y) |
1369 * |/_/_/_/_/_/_/|________|
1370 * |<----x0----->|<--w0-->|
1374 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1375 * screen borders
1376 * Hatched area is beyond screen border
1378 * |<-Cursor_x_hot->|
1379 * ________________|_______________
1380 * | | | / / / / / /|
1381 * | (x,y)|/ / / / / / |
1382 * |___________________|_/_/_/_/_/_/|
1383 * |<-------w0-------->| |
1384 * |<---------------w--|----------->|
1385 * | |
1386 * x0 Displaywidth-1
1389 if (x < Cursor_x_hot) { /* see fig. 1 */
1390 x0 = Cursor_x_hot - x;
1391 w0 = w - x0;
1394 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1395 w0 = (displayWidth) - (x - Cursor_x_hot);
1398 if (y < Cursor_y_hot) { /* see fig. 1 */
1399 y0 = Cursor_y_hot - y;
1400 h0 = h - y0;
1403 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1404 h0 = (displayHeight) - (y - Cursor_y_hot);
1406 /* end of coordinate correction */
1408 /* Grab an image from the screen, clipped if necessary,
1409 * and put it in the existing panel->magnifyGlass->image
1410 * with the corresponding clipping offset.
1412 if (!XGetSubImage(scr->display, scr->rootWin,
1413 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1414 wwarning(_("Color Panel: X failed request"));
1416 return NULL;
1419 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1421 /* (x1, y1) = topleft corner of existing rectangle
1422 * (x2, y2) = topleft corner of new position
1425 W_Screen *scr = WMWidgetScreen(panel->win);
1426 int xa = 0, ya = 0, xb = 0, yb = 0;
1427 int width, height;
1428 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1429 XImage *image;
1430 const int x_min = Cursor_x_hot,
1431 y_min = Cursor_y_hot,
1432 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1433 (Cursor_mask_width - Cursor_x_hot),
1434 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1436 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1437 return; /* No movement */
1439 if (x1 < x2)
1440 xa = dx;
1441 else
1442 xb = dx;
1444 if (y1 < y2)
1445 ya = dy;
1446 else
1447 yb = dy;
1449 width = Cursor_mask_width - dx;
1450 height = Cursor_mask_height - dy;
1452 /* If the traversed distance is larger than the size of the magnifying
1453 * glass contents, there is no need to do dirty rectangles. A whole new
1454 * rectangle can be grabbed (unless that rectangle falls partially
1455 * off screen).
1456 * Destroying the image and setting it to NULL will achieve that later on.
1458 * Of course, grabbing an XImage beyond the borders of the screen will
1459 * cause trouble, this is considdered a special case. Part of the screen
1460 * is grabbed, but there is no need for dirty rectangles.
1462 if ((width <= 0) || (height <= 0)) {
1463 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1464 if (panel->magnifyGlass->image)
1465 XDestroyImage(panel->magnifyGlass->image);
1466 panel->magnifyGlass->image = NULL;
1468 } else {
1469 if (panel->magnifyGlass->image) {
1470 /* Get dirty rectangle from panel->magnifyGlass->image */
1471 panel->magnifyGlass->dirtyRect =
1472 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1473 if (!panel->magnifyGlass->dirtyRect) {
1474 wwarning(_("Color Panel: X failed request"));
1475 return; /* X returned a NULL from XSubImage */
1480 /* Get image from screen */
1481 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1482 if (image) { /* Only reassign if a *new* image was grabbed */
1483 panel->magnifyGlass->image = image;
1484 return;
1487 /* Copy previously stored rectangle on covered part of image */
1488 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1489 int old_height;
1491 /* "width" and "height" are used as coordinates here,
1492 * and run from [0...width-1] and [0...height-1] respectively.
1494 width--;
1495 height--;
1496 old_height = height;
1498 for (; width >= 0; width--)
1499 for (height = old_height; height >= 0; height--)
1500 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1501 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1502 XDestroyImage(panel->magnifyGlass->dirtyRect);
1503 panel->magnifyGlass->dirtyRect = NULL;
1506 return;
1509 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1511 W_Screen *scr = WMWidgetScreen(panel->win);
1512 int u, v;
1513 #ifndef USE_XSHAPE
1514 Pixmap pixmap;
1515 #endif
1516 unsigned long color;
1518 if (!panel->magnifyGlass->image)
1519 return None;
1521 if (!panel->magnifyGlass->magPix)
1522 return None;
1525 * Copy an area of only 5x5 pixels from the center of the image.
1527 for (u = 0; u < 5; u++) {
1528 for (v = 0; v < 5; v++) {
1529 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1531 XSetForeground(scr->display, scr->copyGC, color);
1533 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1534 panel->magnifyGlass->color = ulongToRColor(scr, color);
1536 /* The center square must eventually be centered around the
1537 * hotspot. The image needs shifting to achieve this. The amount of
1538 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1539 * _ _ _ _ _
1540 * |_|_|_|_|_|
1541 * ^------- center of center square == Cursor_x_hot
1543 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1544 scr->copyGC,
1545 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1546 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1550 #ifdef USE_XSHAPE
1551 return panel->magnifyGlass->magPix;
1552 #else
1553 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1554 if (!pixmap)
1555 return None;
1557 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1558 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1560 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1561 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1562 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1563 /* (2,2) puts center pixel on center of glass */
1565 return pixmap;
1566 #endif
1570 static WMView *magnifyCreateView(W_ColorPanel * panel)
1572 W_Screen *scr = WMWidgetScreen(panel->win);
1573 WMView *magView;
1575 magView = W_CreateTopView(scr);
1576 if (!magView)
1577 return NULL;
1579 magView->self = panel->win;
1580 magView->flags.topLevel = 1;
1581 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1582 magView->attribs.override_redirect = True;
1583 magView->attribs.save_under = True;
1585 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1587 W_RealizeView(magView);
1589 return magView;
1592 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1594 W_Screen *scr = WMWidgetScreen(panel->win);
1595 Pixmap magPixmap, magPixmap2;
1596 Cursor magCursor;
1597 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1598 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1600 /* Cursor creation stuff */
1601 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1602 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1603 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1604 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1606 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1607 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1609 XFreePixmap(scr->display, magPixmap);
1610 XFreePixmap(scr->display, magPixmap2);
1612 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1614 /* Set up Pointer */
1615 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1616 PointerMotionMask | ButtonPressMask,
1617 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1619 return magCursor;
1622 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1624 W_Screen *scr = WMWidgetScreen(panel->win);
1625 int x, y, u, v;
1626 unsigned int mask;
1627 Pixmap pixmap, clip_mask;
1628 WMPoint point;
1629 Window root_return, child_return;
1631 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1632 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1633 1, 0, 1);
1634 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1635 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1637 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1639 panel->magnifyGlass->image = NULL;
1641 /* Clipmask to make magnified view-contents circular */
1642 #ifdef USE_XSHAPE
1643 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1644 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1645 #else
1646 /* Clip circle in glass cursor */
1647 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1648 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1649 #endif
1651 XFreePixmap(scr->display, clip_mask);
1653 /* Draw initial magnifying glass contents */
1654 magnifyGetImageStored(panel, x, y, x, y);
1656 pixmap = magnifyCreatePixmap(panel);
1657 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1658 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1659 XFlush(scr->display);
1661 #ifndef USE_XSHAPE
1662 XFreePixmap(scr->display, pixmap);
1663 #endif
1665 point.x = x;
1666 point.y = y;
1668 return point;
1671 static void magnifyPutCursor(WMWidget * w, void *data)
1673 W_ColorPanel *panel = (W_ColorPanel *) (data);
1674 W_Screen *scr = WMWidgetScreen(panel->win);
1675 Cursor magCursor;
1676 Pixmap pixmap;
1677 XEvent event;
1678 WMPoint initialPosition;
1680 /* Parameter not used, but tell the compiler that it is ok */
1681 (void) w;
1683 /* Destroy wheelBackImg, so it'll update properly */
1684 if (panel->selectionBackImg) {
1685 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1686 panel->selectionBackImg = None;
1689 /* Create magnifying glass */
1690 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1691 panel->magnifyGlass->view = magnifyCreateView(panel);
1692 if (!panel->magnifyGlass->view)
1693 return;
1695 initialPosition = magnifyInitialize(panel);
1696 panel->magnifyGlass->x = initialPosition.x;
1697 panel->magnifyGlass->y = initialPosition.y;
1699 W_MoveView(panel->magnifyGlass->view,
1700 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1701 W_MapView(panel->magnifyGlass->view);
1703 magCursor = magnifyGrabPointer(panel);
1705 while (panel->magnifyGlass->image) {
1706 WMNextEvent(scr->display, &event);
1708 /* Pack motion events */
1709 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1712 switch (event.type) {
1713 case ButtonPress:
1714 XDestroyImage(panel->magnifyGlass->image);
1715 panel->magnifyGlass->image = NULL;
1717 if (event.xbutton.button == Button1) {
1718 panel->color.rgb = panel->magnifyGlass->color;
1719 panel->color.set = cpRGB;
1720 updateSwatch(panel, panel->color);
1722 switch (panel->mode) {
1723 case WMWheelModeColorPanel:
1724 wheelInit(panel);
1725 wheelRender(panel);
1726 wheelPaint(panel);
1727 break;
1728 case WMGrayModeColorPanel:
1729 grayInit(panel);
1730 break;
1731 case WMRGBModeColorPanel:
1732 rgbInit(panel);
1733 break;
1734 case WMCMYKModeColorPanel:
1735 cmykInit(panel);
1736 break;
1737 case WMHSBModeColorPanel:
1738 hsbInit(panel);
1739 break;
1740 default:
1741 break;
1743 panel->lastChanged = panel->mode;
1745 WMSetButtonSelected(panel->magnifyBtn, False);
1746 break;
1748 case MotionNotify:
1749 while (XPending(event.xmotion.display)) {
1750 XEvent ev;
1751 XPeekEvent(event.xmotion.display, &ev);
1752 if (ev.type == MotionNotify)
1753 XNextEvent(event.xmotion.display, &event);
1754 else
1755 break;
1758 /* Get a "dirty rectangle" */
1759 magnifyGetImageStored(panel,
1760 panel->magnifyGlass->x, panel->magnifyGlass->y,
1761 event.xmotion.x_root, event.xmotion.y_root);
1763 /* Update coordinates */
1764 panel->magnifyGlass->x = event.xmotion.x_root;
1765 panel->magnifyGlass->y = event.xmotion.y_root;
1767 /* Move view */
1768 W_MoveView(panel->magnifyGlass->view,
1769 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1771 /* Put new image (with magn.) in view */
1772 pixmap = magnifyCreatePixmap(panel);
1773 if (pixmap != None) {
1774 /* Change the window background */
1775 XSetWindowBackgroundPixmap(scr->display,
1776 WMViewXID(panel->magnifyGlass->view), pixmap);
1777 /* Force an Expose (handled by X) */
1778 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1779 /* Synchronize the event queue, so the Expose is handled NOW */
1780 XFlush(scr->display);
1781 #ifndef USE_XSHAPE
1782 XFreePixmap(scr->display, pixmap);
1783 #endif
1785 break;
1787 /* Try XQueryPointer for this !!! It returns windows that the pointer
1788 * is over. Note: We found this solving the invisible donkey cap bug
1790 #if 0 /* As it is impossible to make this work in all cases,
1791 * we consider it confusing. Therefore we disabled it.
1793 case FocusOut: /* fall through */
1794 case FocusIn:
1796 * Color Panel window (panel->win) lost or received focus.
1797 * We need to update the pixmap in the magnifying glass.
1799 * BUG Doesn't work with focus switches between two windows
1800 * if none of them is the color panel.
1802 XUngrabPointer(scr->display, CurrentTime);
1803 W_UnmapView(panel->magnifyGlass->view);
1805 magnifyInitialize(panel);
1807 W_MapView(panel->magnifyGlass->view);
1808 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1809 True, PointerMotionMask | ButtonPressMask,
1810 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1811 break;
1812 #endif
1813 default:
1814 WMHandleEvent(&event);
1815 break;
1816 } /* of switch */
1819 XUngrabPointer(scr->display, CurrentTime);
1820 XFreeCursor(scr->display, magCursor);
1822 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1823 panel->magnifyGlass->magPix = None;
1825 W_UnmapView(panel->magnifyGlass->view);
1826 W_DestroyView(panel->magnifyGlass->view);
1827 panel->magnifyGlass->view = NULL;
1829 wfree(panel->magnifyGlass);
1832 /****************** ColorWheel Functions ************************/
1834 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1836 wheelMatrix *matrix = NULL;
1837 int i;
1839 assert((width > 0) && (height > 0));
1841 matrix = wmalloc(sizeof(wheelMatrix));
1842 matrix->width = width;
1843 matrix->height = height;
1845 for (i = 0; i < 3; i++) {
1846 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1849 return matrix;
1852 static void wheelDestroyMatrix(wheelMatrix * matrix)
1854 int i;
1856 if (!matrix)
1857 return;
1859 for (i = 0; i < 3; i++) {
1860 if (matrix->data[i])
1861 wfree(matrix->data[i]);
1863 wfree(matrix);
1866 static void wheelInitMatrix(W_ColorPanel * panel)
1868 int i;
1869 int x, y;
1870 unsigned char *rp, *gp, *bp;
1871 CPColor cpColor;
1872 long ofs[4];
1873 int xcor, ycor;
1874 unsigned short sat;
1875 int dhue[4];
1876 const int cw_halfsize = (colorWheelSize + 4) / 2,
1877 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1879 if (!panel->wheelMtrx)
1880 return;
1882 cpColor.hsv.value = 255;
1883 cpColor.set = cpHSV;
1885 ofs[0] = -1;
1886 ofs[1] = -(colorWheelSize + 4);
1888 /* offsets are counterclockwise (in triangles).
1890 * ofs[0] ---->
1891 * _______________________________________
1892 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1893 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1894 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1895 * o | | | | | | | | | | | | | | | | | | | | | [3]
1897 * <---- ofs[2]
1898 * ____
1899 * |\ /| <-- triangles
1900 * | \/ |
1901 * | /\ |
1902 * |/__\|
1905 for (y = 0; y < cw_halfsize; y++) {
1906 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1907 /* (xcor, ycor) is (x,y) relative to center of matrix */
1908 xcor = 2 * x - 4 - colorWheelSize;
1909 ycor = 2 * y - 4 - colorWheelSize;
1911 /* RColor.saturation is unsigned char and will wrap after 255 */
1912 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1914 cpColor.hsv.saturation = (unsigned char)sat;
1916 ofs[0]++; /* top quarter of matrix */
1917 ofs[1] += colorWheelSize + 4; /* left quarter */
1918 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1919 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1921 if (sat < 256) {
1922 if (xcor != 0)
1923 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1924 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1925 else
1926 dhue[0] = 270;
1928 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1929 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1930 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1931 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1933 for (i = 0; i < 4; i++) {
1934 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1935 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1936 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1938 cpColor.hsv.hue = dhue[i];
1939 convertCPColor(&cpColor);
1941 *rp = (unsigned char)(cpColor.rgb.red);
1942 *gp = (unsigned char)(cpColor.rgb.green);
1943 *bp = (unsigned char)(cpColor.rgb.blue);
1945 } else {
1946 for (i = 0; i < 4; i++) {
1947 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1948 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1949 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1951 *rp = (unsigned char)0;
1952 *gp = (unsigned char)0;
1953 *bp = (unsigned char)0;
1958 ofs[0] += 2 * y + 1;
1959 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1963 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1965 unsigned int i;
1966 unsigned int v;
1968 for (i = 0; i < 256; i++) {
1969 /* We divide by 128 in advance, and check whether that number divides
1970 * by 2 properly. If not, we add one to round the number correctly
1972 v = (i * maxvalue) >> 7;
1973 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
1977 static void wheelRender(W_ColorPanel * panel)
1979 W_Screen *scr = WMWidgetScreen(panel->win);
1980 int x, y;
1981 RImage *image;
1982 unsigned char *ptr;
1983 RColor gray;
1984 unsigned long ofs = 0;
1985 /*unsigned char shift = getShift(sizeof(unsigned char)); */
1987 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
1988 if (!image) {
1989 wwarning(_("Color Panel: Could not allocate memory"));
1990 return;
1993 ptr = image->data;
1995 /* TODO Make this transparent istead of gray */
1996 gray.red = gray.blue = 0xae;
1997 gray.green = 0xaa;
1999 for (y = 0; y < colorWheelSize + 4; y++) {
2000 for (x = 0; x < colorWheelSize + 4; x++) {
2001 if (wheelInsideColorWheel(panel, ofs)) {
2002 *(ptr++) =
2003 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2004 *(ptr++) =
2005 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2006 *(ptr++) =
2007 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2008 *(ptr++) = 0;
2009 } else {
2010 *(ptr++) = (unsigned char)(gray.red);
2011 *(ptr++) = (unsigned char)(gray.green);
2012 *(ptr++) = (unsigned char)(gray.blue);
2013 *(ptr++) = 255;
2015 ofs++;
2019 if (panel->wheelImg)
2020 XFreePixmap(scr->display, panel->wheelImg);
2022 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2023 RReleaseImage(image);
2025 /* Check if backimage exists. If it doesn't, allocate and fill it */
2026 if (!panel->selectionBackImg) {
2027 panel->selectionBackImg = XCreatePixmap(scr->display,
2028 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2029 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2030 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2031 /* -2 is hot spot correction */
2035 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2037 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2038 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2041 static void wheelPaint(W_ColorPanel * panel)
2043 W_Screen *scr = WMWidgetScreen(panel->win);
2045 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2046 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2048 /* Draw selection image */
2049 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2050 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2053 static void wheelHandleEvents(XEvent * event, void *data)
2055 W_ColorPanel *panel = (W_ColorPanel *) data;
2057 switch (event->type) {
2058 case Expose:
2059 if (event->xexpose.count != 0) /* TODO Improve */
2060 break;
2061 wheelPaint(panel);
2062 break;
2066 static void wheelHandleActionEvents(XEvent * event, void *data)
2068 W_ColorPanel *panel = (W_ColorPanel *) data;
2070 switch (event->type) {
2071 case ButtonPress:
2072 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2074 panel->lastChanged = WMWheelModeColorPanel;
2075 panel->flags.dragging = 1;
2077 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2079 break;
2081 case ButtonRelease:
2082 panel->flags.dragging = 0;
2083 if (!panel->flags.continuous) {
2084 if (panel->action)
2085 (*panel->action) (panel, panel->clientData);
2087 break;
2089 case MotionNotify:
2090 if (panel->flags.dragging) {
2091 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2092 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2093 } else
2094 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2096 break;
2100 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2102 int lx, ly;
2103 unsigned long ofs;
2105 lx = x;
2106 ly = y;
2108 if (panel->mode == WMWheelModeColorPanel) {
2109 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2111 ofs = ly * panel->wheelMtrx->width + lx;
2113 if (wheelInsideColorWheel(panel, ofs))
2114 return COLORWHEEL_PART;
2118 if (panel->mode == WMCustomPaletteModeColorPanel) {
2119 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2120 return CUSTOMPALETTE_PART;
2124 return 0;
2127 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2129 int value;
2131 W_ColorPanel *panel = (W_ColorPanel *) data;
2133 /* Parameter not used, but tell the compiler that it is ok */
2134 (void) w;
2136 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2138 wheelCalculateValues(panel, value);
2140 if (panel->color.set == cpRGB) {
2141 convertCPColor(&panel->color);
2142 panel->color.set = cpHSV;
2145 panel->color.hsv.value = value;
2147 wheelRender(panel);
2148 wheelPaint(panel);
2149 wheelUpdateSelection(panel);
2152 static void wheelUpdateSelection(W_ColorPanel * panel)
2154 W_Screen *scr = WMWidgetScreen(panel->win);
2156 updateSwatch(panel, panel->color);
2157 panel->lastChanged = WMWheelModeColorPanel;
2159 /* Redraw color selector (and make a backup of the part it will cover) */
2160 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2161 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2162 /* "-2" is correction for hotspot location */
2163 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2164 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2165 /* see above */
2168 static void wheelUndrawSelection(W_ColorPanel * panel)
2170 W_Screen *scr = WMWidgetScreen(panel->win);
2172 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2173 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2174 /* see above */
2177 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2179 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2181 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2183 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2185 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2186 panel->color.set = cpRGB;
2188 wheelUndrawSelection(panel);
2190 panel->colx = x;
2191 panel->coly = y;
2193 wheelUpdateSelection(panel);
2194 wheelUpdateBrightnessGradientFromLocation(panel);
2197 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2199 int hue;
2200 int xcor, ycor;
2201 CPColor cpColor;
2203 xcor = x * 2 - colorWheelSize - 4;
2204 ycor = y * 2 - colorWheelSize - 4;
2206 panel->color.hsv.saturation = 255;
2207 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2209 if (xcor != 0)
2210 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2211 else {
2212 if (ycor < 0)
2213 hue = 90;
2214 else
2215 hue = 270;
2218 if (xcor < 0)
2219 hue += 180;
2221 if ((xcor > 0) && (ycor > 0))
2222 hue += 360;
2224 panel->color.hsv.hue = hue;
2225 panel->color.set = cpHSV;
2226 convertCPColor(&panel->color);
2228 wheelUndrawSelection(panel);
2230 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2231 /* "+2" because of "colorWheelSize + 4" */
2232 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2234 wheelUpdateSelection(panel);
2235 cpColor = panel->color;
2236 wheelUpdateBrightnessGradient(panel, cpColor);
2239 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2241 CPColor from;
2242 unsigned long ofs;
2244 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2246 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2247 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2248 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2249 from.set = cpRGB;
2251 wheelUpdateBrightnessGradient(panel, from);
2254 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2256 RColor to;
2257 RImage *sliderImg;
2258 WMPixmap *sliderPxmp;
2260 to.red = to.green = to.blue = 0;
2262 if (topColor.set == cpHSV)
2263 convertCPColor(&topColor);
2265 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2266 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2267 RReleaseImage(sliderImg);
2268 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2269 WMReleasePixmap(sliderPxmp);
2272 /****************** Grayscale Panel Functions ***************/
2274 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2276 CPColor cpColor;
2277 int value;
2278 char tmp[4];
2279 W_ColorPanel *panel = (W_ColorPanel *) data;
2281 /* Parameter not used, but tell the compiler that it is ok */
2282 (void) w;
2284 value = WMGetSliderValue(panel->grayBrightnessS);
2286 sprintf(tmp, "%d", value);
2288 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2289 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2290 cpColor.set = cpRGB;
2292 updateSwatch(panel, cpColor);
2293 panel->lastChanged = WMGrayModeColorPanel;
2296 static void grayPresetButtonCallback(WMWidget * w, void *data)
2298 CPColor cpColor;
2299 char tmp[4];
2300 int value;
2301 int i = 0;
2302 W_ColorPanel *panel = (W_ColorPanel *) data;
2304 while (i < 7) {
2305 if (w == panel->grayPresetBtn[i])
2306 break;
2307 i++;
2310 value = rint((100.0 * i) / 6.0);
2311 sprintf(tmp, "%d", value);
2313 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2314 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2315 cpColor.set = cpRGB;
2317 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2319 updateSwatch(panel, cpColor);
2320 panel->lastChanged = WMGrayModeColorPanel;
2323 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2325 CPColor cpColor;
2326 char tmp[4];
2327 int value;
2328 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2330 /* Parameter not used, but tell the compiler that it is ok */
2331 (void) notification;
2333 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2334 if (value > 100)
2335 value = 100;
2336 if (value < 0)
2337 value = 0;
2339 sprintf(tmp, "%d", value);
2340 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2341 WMSetSliderValue(panel->grayBrightnessS, value);
2343 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2344 cpColor.set = cpRGB;
2346 updateSwatch(panel, cpColor);
2347 panel->lastChanged = WMGrayModeColorPanel;
2350 /******************* RGB Panel Functions *****************/
2352 static void rgbSliderCallback(WMWidget * w, void *data)
2354 CPColor cpColor;
2355 int value[3];
2356 char tmp[4];
2357 W_ColorPanel *panel = (W_ColorPanel *) data;
2359 /* Parameter not used, but tell the compiler that it is ok */
2360 (void) w;
2362 value[0] = WMGetSliderValue(panel->rgbRedS);
2363 value[1] = WMGetSliderValue(panel->rgbGreenS);
2364 value[2] = WMGetSliderValue(panel->rgbBlueS);
2366 sprintf(tmp, "%d", value[0]);
2367 WMSetTextFieldText(panel->rgbRedT, tmp);
2368 sprintf(tmp, "%d", value[1]);
2369 WMSetTextFieldText(panel->rgbGreenT, tmp);
2370 sprintf(tmp, "%d", value[2]);
2371 WMSetTextFieldText(panel->rgbBlueT, tmp);
2373 cpColor.rgb.red = value[0];
2374 cpColor.rgb.green = value[1];
2375 cpColor.rgb.blue = value[2];
2376 cpColor.set = cpRGB;
2378 updateSwatch(panel, cpColor);
2379 panel->lastChanged = WMRGBModeColorPanel;
2382 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2384 CPColor cpColor;
2385 int value[3];
2386 char tmp[4];
2387 int n;
2388 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2390 /* Parameter not used, but tell the compiler that it is ok */
2391 (void) notification;
2393 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2394 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2395 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2397 for (n = 0; n < 3; n++) {
2398 if (value[n] > 255)
2399 value[n] = 255;
2400 if (value[n] < 0)
2401 value[n] = 0;
2404 sprintf(tmp, "%d", value[0]);
2405 WMSetTextFieldText(panel->rgbRedT, tmp);
2406 sprintf(tmp, "%d", value[1]);
2407 WMSetTextFieldText(panel->rgbGreenT, tmp);
2408 sprintf(tmp, "%d", value[2]);
2409 WMSetTextFieldText(panel->rgbBlueT, tmp);
2411 WMSetSliderValue(panel->rgbRedS, value[0]);
2412 WMSetSliderValue(panel->rgbGreenS, value[1]);
2413 WMSetSliderValue(panel->rgbBlueS, value[2]);
2415 cpColor.rgb.red = value[0];
2416 cpColor.rgb.green = value[1];
2417 cpColor.rgb.blue = value[2];
2418 cpColor.set = cpRGB;
2420 updateSwatch(panel, cpColor);
2421 panel->lastChanged = WMRGBModeColorPanel;
2424 /******************* CMYK Panel Functions *****************/
2426 static void cmykSliderCallback(WMWidget * w, void *data)
2428 CPColor cpColor;
2429 int value[4];
2430 char tmp[4];
2431 W_ColorPanel *panel = (W_ColorPanel *) data;
2432 double scale;
2434 /* Parameter not used, but tell the compiler that it is ok */
2435 (void) w;
2437 value[0] = WMGetSliderValue(panel->cmykCyanS);
2438 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2439 value[2] = WMGetSliderValue(panel->cmykYellowS);
2440 value[3] = WMGetSliderValue(panel->cmykBlackS);
2442 sprintf(tmp, "%d", value[0]);
2443 WMSetTextFieldText(panel->cmykCyanT, tmp);
2444 sprintf(tmp, "%d", value[1]);
2445 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2446 sprintf(tmp, "%d", value[2]);
2447 WMSetTextFieldText(panel->cmykYellowT, tmp);
2448 sprintf(tmp, "%d", value[3]);
2449 WMSetTextFieldText(panel->cmykBlackT, tmp);
2451 scale = 2.55 * (1.0 - (value[3] / 100.0));
2452 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2453 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2454 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2455 cpColor.set = cpRGB;
2457 updateSwatch(panel, cpColor);
2458 panel->lastChanged = WMCMYKModeColorPanel;
2461 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2463 CPColor cpColor;
2464 int value[4];
2465 char tmp[4];
2466 int n;
2467 double scale;
2468 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2470 /* Parameter not used, but tell the compiler that it is ok */
2471 (void) notification;
2473 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2474 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2475 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2476 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2478 for (n = 0; n < 4; n++) {
2479 if (value[n] > 100)
2480 value[n] = 100;
2481 if (value[n] < 0)
2482 value[n] = 0;
2485 sprintf(tmp, "%d", value[0]);
2486 WMSetTextFieldText(panel->cmykCyanT, tmp);
2488 sprintf(tmp, "%d", value[1]);
2489 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2491 sprintf(tmp, "%d", value[2]);
2492 WMSetTextFieldText(panel->cmykYellowT, tmp);
2494 sprintf(tmp, "%d", value[3]);
2495 WMSetTextFieldText(panel->cmykBlackT, tmp);
2497 WMSetSliderValue(panel->cmykCyanS, value[0]);
2498 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2499 WMSetSliderValue(panel->cmykYellowS, value[2]);
2500 WMSetSliderValue(panel->cmykBlackS, value[3]);
2502 scale = 2.55 * (1.0 - (value[3] / 100.0));
2503 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2504 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2505 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2506 cpColor.set = cpRGB;
2508 updateSwatch(panel, cpColor);
2509 panel->lastChanged = WMCMYKModeColorPanel;
2512 /********************** HSB Panel Functions ***********************/
2514 static void hsbSliderCallback(WMWidget * w, void *data)
2516 CPColor cpColor;
2517 int value[3];
2518 char tmp[4];
2519 W_ColorPanel *panel = (W_ColorPanel *) data;
2521 value[0] = WMGetSliderValue(panel->hsbHueS);
2522 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2523 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2525 sprintf(tmp, "%d", value[0]);
2526 WMSetTextFieldText(panel->hsbHueT, tmp);
2527 sprintf(tmp, "%d", value[1]);
2528 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2529 sprintf(tmp, "%d", value[2]);
2530 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2532 cpColor.hsv.hue = value[0];
2533 cpColor.hsv.saturation = value[1] * 2.55;
2534 cpColor.hsv.value = value[2] * 2.55;
2535 cpColor.set = cpHSV;
2537 convertCPColor(&cpColor);
2539 panel->lastChanged = WMHSBModeColorPanel;
2540 updateSwatch(panel, cpColor);
2542 if (w != panel->hsbBrightnessS)
2543 hsbUpdateBrightnessGradient(panel);
2544 if (w != panel->hsbSaturationS)
2545 hsbUpdateSaturationGradient(panel);
2546 if (w != panel->hsbHueS)
2547 hsbUpdateHueGradient(panel);
2550 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2552 CPColor cpColor;
2553 int value[3];
2554 char tmp[4];
2555 int n;
2556 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2558 /* Parameter not used, but tell the compiler that it is ok */
2559 (void) notification;
2561 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2562 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2563 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2565 if (value[0] > 359)
2566 value[0] = 359;
2567 if (value[0] < 0)
2568 value[0] = 0;
2570 for (n = 1; n < 3; n++) {
2571 if (value[n] > 100)
2572 value[n] = 100;
2573 if (value[n] < 0)
2574 value[n] = 0;
2577 sprintf(tmp, "%d", value[0]);
2578 WMSetTextFieldText(panel->hsbHueT, tmp);
2579 sprintf(tmp, "%d", value[1]);
2580 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2581 sprintf(tmp, "%d", value[2]);
2582 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2584 WMSetSliderValue(panel->hsbHueS, value[0]);
2585 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2586 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2588 cpColor.hsv.hue = value[0];
2589 cpColor.hsv.saturation = value[1] * 2.55;
2590 cpColor.hsv.value = value[2] * 2.55;
2591 cpColor.set = cpHSV;
2593 convertCPColor(&cpColor);
2595 panel->lastChanged = WMHSBModeColorPanel;
2596 updateSwatch(panel, cpColor);
2598 hsbUpdateBrightnessGradient(panel);
2599 hsbUpdateSaturationGradient(panel);
2600 hsbUpdateHueGradient(panel);
2603 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2605 W_Screen *scr = WMWidgetScreen(panel->win);
2606 RColor from;
2607 CPColor to;
2608 RImage *sliderImg;
2609 WMPixmap *sliderPxmp;
2611 from.red = from.green = from.blue = 0;
2612 to.hsv = panel->color.hsv;
2613 to.hsv.value = 255;
2614 to.set = cpHSV;
2616 convertCPColor(&to);
2618 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2619 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2620 RReleaseImage(sliderImg);
2622 if (sliderPxmp)
2623 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2624 panel->font12, 2, 0, 100, WALeft, scr->white,
2625 False, _("Brightness"), strlen(_("Brightness")));
2626 else
2627 wwarning(_("Color Panel: Could not allocate memory"));
2629 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2630 WMReleasePixmap(sliderPxmp);
2633 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2635 W_Screen *scr = WMWidgetScreen(panel->win);
2636 CPColor from;
2637 CPColor to;
2638 RImage *sliderImg;
2639 WMPixmap *sliderPxmp;
2641 from.hsv = panel->color.hsv;
2642 from.hsv.saturation = 0;
2643 from.set = cpHSV;
2644 convertCPColor(&from);
2646 to.hsv = panel->color.hsv;
2647 to.hsv.saturation = 255;
2648 to.set = cpHSV;
2649 convertCPColor(&to);
2651 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2652 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2653 RReleaseImage(sliderImg);
2655 if (sliderPxmp)
2656 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2657 panel->font12, 2, 0, 100, WALeft,
2658 from.hsv.value < 128 ? scr->white : scr->black, False,
2659 _("Saturation"), strlen(_("Saturation")));
2660 else
2661 wwarning(_("Color Panel: Could not allocate memory"));
2663 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2664 WMReleasePixmap(sliderPxmp);
2667 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2669 W_Screen *scr = WMWidgetScreen(panel->win);
2670 RColor **colors = NULL;
2671 RHSVColor hsvcolor;
2672 RImage *sliderImg;
2673 WMPixmap *sliderPxmp;
2674 int i;
2676 hsvcolor = panel->color.hsv;
2678 colors = wmalloc(sizeof(RColor *) * (8));
2679 for (i = 0; i < 7; i++) {
2680 hsvcolor.hue = (360 * i) / 6;
2681 colors[i] = wmalloc(sizeof(RColor));
2682 RHSVtoRGB(&hsvcolor, colors[i]);
2684 colors[7] = NULL;
2686 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2687 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2688 RReleaseImage(sliderImg);
2690 if (sliderPxmp)
2691 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2692 panel->font12, 2, 0, 100, WALeft,
2693 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2694 else
2695 wwarning(_("Color Panel: Could not allocate memory"));
2697 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2698 WMReleasePixmap(sliderPxmp);
2700 for (i = 0; i < 7; i++)
2701 wfree(colors[i]);
2703 wfree(colors);
2706 /*************** Custom Palette Functions ****************/
2708 static void customRenderSpectrum(W_ColorPanel * panel)
2710 RImage *spectrum;
2711 int x, y;
2712 unsigned char *ptr;
2713 CPColor cpColor;
2715 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2717 ptr = spectrum->data;
2719 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2720 cpColor.hsv.hue = y;
2721 cpColor.hsv.saturation = 0;
2722 cpColor.hsv.value = 255;
2723 cpColor.set = cpHSV;
2725 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2726 convertCPColor(&cpColor);
2728 *(ptr++) = (unsigned char)cpColor.rgb.red;
2729 *(ptr++) = (unsigned char)cpColor.rgb.green;
2730 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2732 if (x < (SPECTRUM_WIDTH / 2))
2733 cpColor.hsv.saturation++;
2735 if (x > (SPECTRUM_WIDTH / 2))
2736 cpColor.hsv.value--;
2739 if (panel->customPaletteImg) {
2740 RReleaseImage(panel->customPaletteImg);
2741 panel->customPaletteImg = NULL;
2743 panel->customPaletteImg = spectrum;
2746 static void customSetPalette(W_ColorPanel * panel)
2748 W_Screen *scr = WMWidgetScreen(panel->win);
2749 RImage *scaledImg;
2750 Pixmap image;
2752 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2753 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2754 RConvertImage(scr->rcontext, scaledImg, &image);
2755 RReleaseImage(scaledImg);
2757 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2758 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2760 /* Check backimage exists. If it doesn't, allocate and fill it */
2761 if (!panel->selectionBackImg) {
2762 panel->selectionBackImg = XCreatePixmap(scr->display,
2763 panel->customPaletteContentView->window, 4, 4, scr->depth);
2766 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2767 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2768 XCopyArea(scr->display, panel->selectionImg,
2769 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2770 panel->palx - 2, panel->paly - 2);
2771 XFreePixmap(scr->display, image);
2773 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2774 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2776 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2779 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2781 W_Screen *scr = WMWidgetScreen(panel->win);
2782 unsigned long ofs;
2784 /* undraw selection */
2785 XCopyArea(scr->display, panel->selectionBackImg,
2786 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2787 panel->palx - 2, panel->paly - 2);
2789 panel->palx = x;
2790 panel->paly = y;
2792 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2794 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2795 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2796 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2797 panel->color.set = cpRGB;
2799 updateSwatch(panel, panel->color);
2800 panel->lastChanged = WMCustomPaletteModeColorPanel;
2802 /* Redraw color selector (and make a backup of the part it will cover) */
2803 XCopyArea(scr->display, panel->customPaletteContentView->window, panel->selectionBackImg, scr->copyGC, panel->palx - 2, panel->paly - 2, 4, 4, 0, 0); /* "-2" is correction for hotspot location */
2804 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2807 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2809 if (x < 2)
2810 x = 2;
2811 if (y < 2)
2812 y = 2;
2813 if (x >= customPaletteWidth)
2814 x = customPaletteWidth - 2;
2815 if (y >= customPaletteHeight)
2816 y = customPaletteHeight - 2;
2818 customPalettePositionSelection(panel, x, y);
2821 static void customPaletteHandleEvents(XEvent * event, void *data)
2823 W_ColorPanel *panel = (W_ColorPanel *) data;
2825 switch (event->type) {
2826 case Expose:
2827 if (event->xexpose.count != 0) /* TODO Improve. */
2828 break;
2829 customSetPalette(panel);
2830 break;
2834 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2836 W_ColorPanel *panel = (W_ColorPanel *) data;
2837 int x, y;
2839 switch (event->type) {
2840 case ButtonPress:
2841 x = event->xbutton.x;
2842 y = event->xbutton.y;
2844 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2845 panel->flags.dragging = 1;
2846 customPalettePositionSelection(panel, x, y);
2848 break;
2850 case ButtonRelease:
2851 panel->flags.dragging = 0;
2852 if (!panel->flags.continuous) {
2853 if (panel->action)
2854 (*panel->action) (panel, panel->clientData);
2856 break;
2858 case MotionNotify:
2859 x = event->xmotion.x;
2860 y = event->xmotion.y;
2862 if (panel->flags.dragging) {
2863 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2864 customPalettePositionSelection(panel, x, y);
2865 } else
2866 customPalettePositionSelectionOutBounds(panel, x, y);
2868 break;
2872 static void customPaletteMenuCallback(WMWidget * w, void *data)
2874 W_ColorPanel *panel = (W_ColorPanel *) data;
2875 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2877 /* Parameter not used, but tell the compiler that it is ok */
2878 (void) w;
2880 switch (item) {
2881 case CPmenuNewFromFile:
2882 customPaletteMenuNewFromFile(panel);
2883 break;
2884 case CPmenuRename:
2885 customPaletteMenuRename(panel);
2886 break;
2887 case CPmenuRemove:
2888 customPaletteMenuRemove(panel);
2889 break;
2890 case CPmenuCopy:
2891 break;
2892 case CPmenuNewFromClipboard:
2893 break;
2897 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2899 W_Screen *scr = WMWidgetScreen(panel->win);
2900 WMOpenPanel *browseP;
2901 char *filepath;
2902 char *filename = NULL;
2903 char *spath;
2904 char *tmp;
2905 int i;
2906 RImage *tmpImg = NULL;
2908 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
2909 spath = wexpandpath(wgethomedir());
2910 else
2911 spath = wexpandpath(panel->lastBrowseDir);
2913 browseP = WMGetOpenPanel(scr);
2914 WMSetFilePanelCanChooseDirectories(browseP, 0);
2915 WMSetFilePanelCanChooseFiles(browseP, 1);
2917 /* Get a filename */
2918 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
2919 _("Open Palette"), RSupportedFileFormats())) {
2920 filepath = WMGetFilePanelFileName(browseP);
2922 /* Get seperation position between path and filename */
2923 i = strrchr(filepath, '/') - filepath + 1;
2924 if (i > strlen(filepath))
2925 i = strlen(filepath);
2927 /* Store last browsed path */
2928 if (panel->lastBrowseDir)
2929 wfree(panel->lastBrowseDir);
2930 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
2931 strncpy(panel->lastBrowseDir, filepath, i);
2932 panel->lastBrowseDir[i] = '\0';
2934 /* Get filename from path */
2935 filename = wstrdup(filepath + i);
2937 /* Check for duplicate files, and rename it if there are any */
2938 tmp = wstrconcat(panel->configurationPath, filename);
2939 while (access(tmp, F_OK) == 0) {
2940 char *newName;
2942 wfree(tmp);
2944 newName = generateNewFilename(filename);
2945 wfree(filename);
2946 filename = newName;
2948 tmp = wstrconcat(panel->configurationPath, filename);
2950 wfree(tmp);
2952 /* Copy image to $(gnustepdir)/Library/Colors/ &
2953 * Add filename to history menu */
2954 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
2956 /* filepath is a "local" path now the file has been copied */
2957 wfree(filepath);
2958 filepath = wstrconcat(panel->configurationPath, filename);
2960 /* load the image & add menu entries */
2961 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
2962 if (tmpImg) {
2963 if (panel->customPaletteImg)
2964 RReleaseImage(panel->customPaletteImg);
2965 panel->customPaletteImg = tmpImg;
2967 customSetPalette(panel);
2968 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
2970 panel->currentPalette =
2971 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
2973 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
2974 panel->currentPalette);
2976 } else {
2977 tmp = wstrconcat(panel->configurationPath, filename);
2979 i = remove(tmp); /* Delete the file, it doesn't belong here */
2980 WMRunAlertPanel(scr, panel->win, _("File Error"),
2981 _("Invalid file format !"), _("OK"), NULL, NULL);
2982 if (i != 0) {
2983 werror(_("can't remove file %s"), tmp);
2984 WMRunAlertPanel(scr, panel->win, _("File Error"),
2985 _("Couldn't remove file from Configuration Directory !"),
2986 _("OK"), NULL, NULL);
2988 wfree(tmp);
2990 wfree(filepath);
2991 wfree(filename);
2993 WMFreeFilePanel(browseP);
2995 wfree(spath);
2998 static void customPaletteMenuRename(W_ColorPanel * panel)
3000 W_Screen *scr = WMWidgetScreen(panel->win);
3001 char *toName = NULL;
3002 char *fromName;
3003 char *toPath, *fromPath;
3004 int item;
3005 int index;
3007 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3008 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3010 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3011 fromName, _("OK"), _("Cancel"));
3013 if (toName) {
3015 /* As some people do certain stupid things... */
3016 if (strcmp(toName, fromName) == 0) {
3017 wfree(toName);
3018 return;
3021 /* For normal people */
3022 fromPath = wstrconcat(panel->configurationPath, fromName);
3023 toPath = wstrconcat(panel->configurationPath, toName);
3025 if (access(toPath, F_OK) == 0) {
3026 /* Careful, this palette exists already */
3027 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3028 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3029 NULL) == 1) {
3030 /* "No" = 0, "Yes" = 1 */
3031 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3033 remove(toPath);
3035 /* Remove from History list too */
3036 index = 1;
3037 while ((index < items)
3039 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3040 != 0))
3041 index++;
3043 if (index < items) {
3044 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3045 if (index < item)
3046 item--;
3049 } else {
3050 wfree(fromPath);
3051 wfree(toName);
3052 wfree(toPath);
3054 return;
3058 if (rename(fromPath, toPath) != 0)
3059 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3060 else {
3061 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3062 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3064 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3066 wfree(fromPath);
3067 wfree(toPath);
3068 wfree(toName);
3072 static void customPaletteMenuRemove(W_ColorPanel * panel)
3074 W_Screen *scr = WMWidgetScreen(panel->win);
3075 char *text;
3076 char *tmp;
3077 int choice;
3078 int item;
3080 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3082 tmp = wstrconcat(_("This will permanently remove the palette "),
3083 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3084 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3085 wfree(tmp);
3087 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3088 /* returns 0 (= "Yes") or 1 (="No") */
3089 wfree(text);
3091 if (choice == 0) {
3093 tmp = wstrconcat(panel->configurationPath,
3094 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3096 if (remove(tmp) == 0) {
3097 /* item-1 always exists */
3098 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3100 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3101 customSetPalette(panel);
3103 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3105 } else {
3106 werror(_("Couldn't remove palette %s"), tmp);
3109 wfree(tmp);
3113 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3115 W_ColorPanel *panel = (W_ColorPanel *) data;
3116 W_Screen *scr = WMWidgetScreen(panel->win);
3117 int item;
3118 char *filename;
3119 RImage *tmp = NULL;
3120 unsigned char perm_mask;
3122 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3123 if (item == panel->currentPalette)
3124 return;
3126 if (item == 0) {
3127 customRenderSpectrum(panel);
3129 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3130 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3131 } else {
3132 /* Load file from configpath */
3133 filename = wstrconcat(panel->configurationPath,
3134 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3136 /* If the file corresponding to the item does not exist,
3137 * remove it from the history list and select the next one.
3139 perm_mask = (access(filename, F_OK) == 0);
3140 if (!perm_mask) {
3141 /* File does not exist */
3142 wfree(filename);
3143 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3144 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3145 customPaletteHistoryCallback(w, data);
3146 return;
3149 /* Get the image */
3150 tmp = RLoadImage(scr->rcontext, filename, 0);
3151 if (tmp) {
3152 if (panel->customPaletteImg) {
3153 RReleaseImage(panel->customPaletteImg);
3154 panel->customPaletteImg = NULL;
3156 panel->customPaletteImg = tmp;
3159 /* If the image is not writable, don't allow removing/renaming */
3160 perm_mask = (access(filename, W_OK) == 0);
3161 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3162 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3164 wfree(filename);
3166 customSetPalette(panel);
3168 panel->currentPalette = item;
3171 /************************* ColorList Panel Functions **********************/
3173 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3175 WMScreen *scr = WMWidgetScreen(lPtr);
3176 Display *dpy = WMScreenDisplay(scr);
3177 WMView *view = W_VIEW(lPtr);
3178 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3179 W_ColorPanel *panel = WMGetHangedData(lPtr);
3180 int width, height, x, y;
3181 WMColor *fillColor;
3183 width = rect->size.width;
3184 height = rect->size.height;
3185 x = rect->pos.x;
3186 y = rect->pos.y;
3188 if (state & WLDSSelected)
3189 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3190 else
3191 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3193 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3195 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3196 WMReleaseColor(fillColor);
3198 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3201 static void colorListSelect(WMWidget * w, void *data)
3203 W_ColorPanel *panel = (W_ColorPanel *) data;
3204 CPColor cpColor;
3206 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3207 cpColor.set = cpRGB;
3209 panel->lastChanged = WMColorListModeColorPanel;
3210 updateSwatch(panel, cpColor);
3213 static void colorListColorMenuCallback(WMWidget * w, void *data)
3215 W_ColorPanel *panel = (W_ColorPanel *) data;
3216 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3218 /* Parameter not used, but tell the compiler that it is ok */
3219 (void) w;
3221 switch (item) {
3222 case CLmenuAdd:
3223 break;
3224 case CLmenuRename:
3225 break;
3226 case CLmenuRemove:
3227 break;
3231 static void colorListListMenuCallback(WMWidget * w, void *data)
3233 W_ColorPanel *panel = (W_ColorPanel *) data;
3234 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3236 /* Parameter not used, but tell the compiler that it is ok */
3237 (void) w;
3239 switch (item) {
3240 case CLmenuAdd:
3241 /* New Color List */
3242 colorListListMenuNew(panel);
3243 break;
3244 case CLmenuRename:
3245 break;
3246 case CLmenuRemove:
3247 break;
3251 static void colorListListMenuNew(W_ColorPanel * panel)
3256 /*************** Panel Initialisation Functions *****************/
3258 static void wheelInit(W_ColorPanel * panel)
3260 CPColor cpColor;
3262 if (panel->color.set != cpHSV)
3263 convertCPColor(&panel->color);
3265 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3267 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3268 (1 + (panel->color.hsv.saturation / 255.0) *
3269 cos(panel->color.hsv.hue * M_PI / 180.0)));
3270 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3271 (1 + (panel->color.hsv.saturation / 255.0) *
3272 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3274 wheelCalculateValues(panel, panel->color.hsv.value);
3276 cpColor = panel->color;
3277 cpColor.hsv.value = 255;
3278 cpColor.set = cpHSV;
3279 wheelUpdateBrightnessGradient(panel, cpColor);
3282 static void grayInit(W_ColorPanel * panel)
3284 int value;
3285 char tmp[4];
3287 if (panel->color.set != cpHSV)
3288 convertCPColor(&panel->color);
3290 value = rint(panel->color.hsv.value / 2.55);
3291 WMSetSliderValue(panel->grayBrightnessS, value);
3293 sprintf(tmp, "%d", value);
3294 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3297 static void rgbInit(W_ColorPanel * panel)
3299 char tmp[4];
3301 if (panel->color.set != cpRGB)
3302 convertCPColor(&panel->color);
3304 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3305 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3306 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3308 sprintf(tmp, "%d", panel->color.rgb.red);
3309 WMSetTextFieldText(panel->rgbRedT, tmp);
3310 sprintf(tmp, "%d", panel->color.rgb.green);
3311 WMSetTextFieldText(panel->rgbGreenT, tmp);
3312 sprintf(tmp, "%d", panel->color.rgb.blue);
3313 WMSetTextFieldText(panel->rgbBlueT, tmp);
3316 static void cmykInit(W_ColorPanel * panel)
3318 int value[3];
3319 char tmp[4];
3321 if (panel->color.set != cpRGB)
3322 convertCPColor(&panel->color);
3324 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3325 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3326 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3328 WMSetSliderValue(panel->cmykCyanS, value[0]);
3329 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3330 WMSetSliderValue(panel->cmykYellowS, value[2]);
3331 WMSetSliderValue(panel->cmykBlackS, 0);
3333 sprintf(tmp, "%d", value[0]);
3334 WMSetTextFieldText(panel->cmykCyanT, tmp);
3335 sprintf(tmp, "%d", value[1]);
3336 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3337 sprintf(tmp, "%d", value[2]);
3338 WMSetTextFieldText(panel->cmykYellowT, tmp);
3339 WMSetTextFieldText(panel->cmykBlackT, "0");
3342 static void hsbInit(W_ColorPanel * panel)
3344 int value[3];
3345 char tmp[4];
3347 if (panel->color.set != cpHSV)
3348 convertCPColor(&panel->color);
3350 value[0] = panel->color.hsv.hue;
3351 value[1] = rint(panel->color.hsv.saturation / 2.55);
3352 value[2] = rint(panel->color.hsv.value / 2.55);
3354 WMSetSliderValue(panel->hsbHueS, value[0]);
3355 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3356 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3358 sprintf(tmp, "%d", value[0]);
3359 WMSetTextFieldText(panel->hsbHueT, tmp);
3360 sprintf(tmp, "%d", value[1]);
3361 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3362 sprintf(tmp, "%d", value[2]);
3363 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3365 hsbUpdateBrightnessGradient(panel);
3366 hsbUpdateSaturationGradient(panel);
3367 hsbUpdateHueGradient(panel);
3370 /************************** Common utility functions ************************/
3372 static char *generateNewFilename(const char *curName)
3374 int n;
3375 char c;
3376 int baseLen;
3377 const char *ptr;
3378 char *newName;
3380 assert(curName);
3382 ptr = curName;
3384 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3385 return wstrconcat(curName, " {1}");
3387 baseLen = ptr - curName - 1;
3389 newName = wmalloc(baseLen + 16);
3390 strncpy(newName, curName, baseLen);
3392 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3394 return newName;
3397 static void convertCPColor(CPColor * color)
3399 unsigned short old_hue = 0;
3401 switch (color->set) {
3402 case cpNone:
3403 wwarning(_("Color Panel: Color unspecified"));
3404 return;
3405 case cpRGB:
3406 old_hue = color->hsv.hue;
3407 RRGBtoHSV(&(color->rgb), &(color->hsv));
3409 /* In black the hue is undefined, and may change by conversion
3410 * Same for white. */
3411 if (((color->rgb.red == 0) &&
3412 (color->rgb.green == 0) &&
3413 (color->rgb.blue == 0)) ||
3414 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3416 color->hsv.hue = old_hue;
3417 break;
3418 case cpHSV:
3419 RHSVtoRGB(&(color->hsv), &(color->rgb));
3420 break;
3424 #define ABS_SHIFT(val, shift) \
3425 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3427 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3429 RColor color;
3430 XColor *xcolor = NULL;
3432 xcolor = wmalloc(sizeof(XColor));
3433 xcolor->pixel = value;
3434 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3436 color.red = xcolor->red >> 8;
3437 color.green = xcolor->green >> 8;
3438 color.blue = xcolor->blue >> 8;
3439 color.alpha = 0;
3441 wfree(xcolor);
3443 return color;
3446 static unsigned char getShift(unsigned char value)
3448 unsigned char i = -1;
3450 if (value == 0)
3451 return 0;
3453 while (value) {
3454 value >>= 1;
3455 i++;
3458 return i;