WPrefs: Removed unused Screen argument to the 'Init*' functions
[wmaker-crm.git] / WINGs / wcolorpanel.c
blobd6bd79cf047a0e49cdfaaafa33b045d491efcf5b
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 */
45 #if 0
46 # ifdef SHAPE
47 # define SHAPE_WAS_DEFINED
48 # undef SHAPE
49 # endif
50 #endif
52 #ifdef SHAPE
53 # include <X11/extensions/shape.h>
54 #endif
56 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
59 * Bitmaps for magnifying glass cursor
62 /* Cursor */
63 #define Cursor_x_hot 11
64 #define Cursor_y_hot 11
65 #define Cursor_width 32
66 #define Cursor_height 32
67 static unsigned char Cursor_bits[] = {
68 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
69 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
70 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
71 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
72 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
73 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
74 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
75 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
76 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
79 /* Cursor shape-mask */
80 #define Cursor_shape_width 32
81 #define Cursor_shape_height 32
82 static unsigned char Cursor_shape_bits[] = {
83 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
84 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
85 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
86 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
87 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
88 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
89 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
90 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
91 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
94 /* Clip-mask for magnified pixels */
95 #define Cursor_mask_width 24
96 #define Cursor_mask_height 24
97 static unsigned char Cursor_mask_bits[] = {
98 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
99 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
100 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
101 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
102 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
103 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
106 typedef struct MovingView {
107 WMView *view; /* The view this is all about */
108 XImage *image; /* What's under the view */
109 XImage *dirtyRect; /* Storage of overlapped image area */
110 Pixmap magPix; /* Magnified part of pixmap */
111 RColor color; /* Color of a pixel in the image */
112 int x, y; /* Position of view */
113 } MovingView;
115 typedef struct CPColor {
116 RColor rgb; /* The RGB values of the color */
117 RHSVColor hsv; /* The HSV values of the color */
118 enum { /* Which one was last set ? */
119 cpNone,
120 cpRGB,
121 cpHSV
122 } set;
123 } CPColor;
125 typedef struct WheelMatrix {
126 unsigned int width, height; /* Size of the colorwheel */
127 unsigned char *data[3]; /* Wheel data (R,G,B) */
128 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
129 } wheelMatrix;
131 typedef struct W_ColorPanel {
132 WMWindow *win;
133 WMFont *font8;
134 WMFont *font12;
135 void *clientData;
136 WMAction2 *action;
138 /* Common Stuff */
139 WMColorWell *colorWell;
140 WMButton *magnifyBtn;
141 WMButton *wheelBtn;
142 WMButton *slidersBtn;
143 WMButton *customPaletteBtn;
144 WMButton *colorListBtn;
146 /* Magnifying Glass */
147 MovingView *magnifyGlass;
149 /* ColorWheel Panel */
150 WMFrame *wheelFrm;
151 WMSlider *wheelBrightnessS;
152 WMView *wheelView;
154 /* Slider Panels */
155 WMFrame *slidersFrm;
156 WMFrame *seperatorFrm;
157 WMButton *grayBtn;
158 WMButton *rgbBtn;
159 WMButton *cmykBtn;
160 WMButton *hsbBtn;
161 /* Gray Scale Panel */
162 WMFrame *grayFrm;
163 WMLabel *grayMinL;
164 WMLabel *grayMaxL;
165 WMSlider *grayBrightnessS;
166 WMTextField *grayBrightnessT;
167 WMButton *grayPresetBtn[7];
169 /* RGB Panel */
170 WMFrame *rgbFrm;
171 WMLabel *rgbMinL;
172 WMLabel *rgbMaxL;
173 WMSlider *rgbRedS;
174 WMSlider *rgbGreenS;
175 WMSlider *rgbBlueS;
176 WMTextField *rgbRedT;
177 WMTextField *rgbGreenT;
178 WMTextField *rgbBlueT;
180 /* CMYK Panel */
181 WMFrame *cmykFrm;
182 WMLabel *cmykMinL;
183 WMLabel *cmykMaxL;
184 WMSlider *cmykCyanS;
185 WMSlider *cmykMagentaS;
186 WMSlider *cmykYellowS;
187 WMSlider *cmykBlackS;
188 WMTextField *cmykCyanT;
189 WMTextField *cmykMagentaT;
190 WMTextField *cmykYellowT;
191 WMTextField *cmykBlackT;
193 /* HSB Panel */
194 WMFrame *hsbFrm;
195 WMSlider *hsbHueS;
196 WMSlider *hsbSaturationS;
197 WMSlider *hsbBrightnessS;
198 WMTextField *hsbHueT;
199 WMTextField *hsbSaturationT;
200 WMTextField *hsbBrightnessT;
202 /* Custom Palette Panel */
203 WMFrame *customPaletteFrm;
204 WMPopUpButton *customPaletteHistoryBtn;
205 WMFrame *customPaletteContentFrm;
206 WMPopUpButton *customPaletteMenuBtn;
207 WMView *customPaletteContentView;
209 /* Color List Panel */
210 WMFrame *colorListFrm;
211 WMPopUpButton *colorListHistoryBtn;
212 WMList *colorListContentLst;
213 WMPopUpButton *colorListColorMenuBtn;
214 WMPopUpButton *colorListListMenuBtn;
216 /* Look-Up Tables and Images */
217 wheelMatrix *wheelMtrx;
218 Pixmap wheelImg;
219 Pixmap selectionImg;
220 Pixmap selectionBackImg;
221 RImage *customPaletteImg;
222 char *lastBrowseDir;
224 /* Common Data Fields */
225 CPColor color; /* Current color */
226 WMColorPanelMode mode; /* Current color selection mode */
227 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
228 WMColorPanelMode lastChanged; /* Panel that last changed the color */
229 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
230 int palx, paly; /* (x,y) of sel.-marker in
231 CustomPaletteMode */
232 double palXRatio, palYRatio; /* Ratios in x & y between
233 original and scaled
234 palettesize */
235 int currentPalette;
236 char *configurationPath;
238 struct {
239 unsigned int continuous:1;
240 unsigned int dragging:1;
241 } flags;
242 } W_ColorPanel;
244 enum {
245 CPmenuNewFromFile,
246 CPmenuRename,
247 CPmenuRemove,
248 CPmenuCopy,
249 CPmenuNewFromClipboard
250 } customPaletteMenuItem;
252 enum {
253 CLmenuAdd,
254 CLmenuRename,
255 CLmenuRemove
256 } colorListMenuItem;
258 #define PWIDTH 194
259 #define PHEIGHT 266
260 #define colorWheelSize 150
261 #define customPaletteWidth 182
262 #define customPaletteHeight 106
263 #define knobThickness 8
265 #define SPECTRUM_WIDTH 511
266 #define SPECTRUM_HEIGHT 360
268 #define COLORWHEEL_PART 1
269 #define CUSTOMPALETTE_PART 2
270 #define BUFSIZE 1024
272 #define MAX_LENGTH 1024
274 #ifndef M_PI
275 #define M_PI 3.14159265358979323846
276 #endif
278 static char *generateNewFilename(const char *curName);
279 static void convertCPColor(CPColor * color);
280 static RColor ulongToRColor(WMScreen * scr, unsigned long value);
281 static unsigned char getShift(unsigned char value);
283 static void modeButtonCallback(WMWidget * w, void *data);
284 static int getPickerPart(W_ColorPanel * panel, int x, int y);
285 static void readConfiguration(W_ColorPanel * panel);
286 static void readXColors(W_ColorPanel * panel);
288 static void closeWindowCallback(WMWidget * w, void *data);
290 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
291 static WMPoint magnifyInitialize(W_ColorPanel * panel);
292 static void magnifyPutCursor(WMWidget * w, void *data);
293 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
294 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
295 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
297 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
298 static void wheelDestroyMatrix(wheelMatrix * matrix);
299 static void wheelInitMatrix(W_ColorPanel * panel);
300 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
301 static void wheelRender(W_ColorPanel * panel);
302 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
303 static void wheelPaint(W_ColorPanel * panel);
305 static void wheelHandleEvents(XEvent * event, void *data);
306 static void wheelHandleActionEvents(XEvent * event, void *data);
307 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
308 static void wheelUpdateSelection(W_ColorPanel * panel);
309 static void wheelUndrawSelection(W_ColorPanel * panel);
311 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
312 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
313 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
314 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
316 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
317 static void grayPresetButtonCallback(WMWidget * w, void *data);
318 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
320 static void rgbSliderCallback(WMWidget * w, void *data);
321 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
323 static void cmykSliderCallback(WMWidget * w, void *data);
324 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
326 static void hsbSliderCallback(WMWidget * w, void *data);
327 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
328 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
329 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
330 static void hsbUpdateHueGradient(W_ColorPanel * panel);
332 static void customRenderSpectrum(W_ColorPanel * panel);
333 static void customSetPalette(W_ColorPanel * panel);
334 static void customPaletteHandleEvents(XEvent * event, void *data);
335 static void customPaletteHandleActionEvents(XEvent * event, void *data);
336 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
337 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
338 static void customPaletteMenuCallback(WMWidget * w, void *data);
339 static void customPaletteHistoryCallback(WMWidget * w, void *data);
341 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
342 static void customPaletteMenuRename(W_ColorPanel * panel);
343 static void customPaletteMenuRemove(W_ColorPanel * panel);
345 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
346 static void colorListSelect(WMWidget * w, void *data);
347 static void colorListColorMenuCallback(WMWidget * w, void *data);
348 static void colorListListMenuCallback(WMWidget * w, void *data);
349 static void colorListListMenuNew(W_ColorPanel * panel);
351 static void wheelInit(W_ColorPanel * panel);
352 static void grayInit(W_ColorPanel * panel);
353 static void rgbInit(W_ColorPanel * panel);
354 static void cmykInit(W_ColorPanel * panel);
355 static void hsbInit(W_ColorPanel * panel);
357 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
359 panel->action = action;
360 panel->clientData = data;
363 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
365 WMColorPanel *panel;
366 RImage *image;
367 WMPixmap *pixmap;
368 RColor from;
369 RColor to;
370 WMColor *textcolor, *graybuttoncolor;
371 int i;
372 GC bgc = WMColorGC(scrPtr->black);
373 GC wgc = WMColorGC(scrPtr->white);
375 panel = wmalloc(sizeof(WMColorPanel));
376 panel->color.rgb.red = 0;
377 panel->color.rgb.green = 0;
378 panel->color.rgb.blue = 0;
379 panel->color.hsv.hue = 0;
380 panel->color.hsv.saturation = 0;
381 panel->color.hsv.value = 0;
382 panel->color.set = cpNone; /* Color has not been set yet */
384 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
385 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
387 panel->win = WMCreateWindowWithStyle(scrPtr, name,
388 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
389 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
390 WMSetWindowTitle(panel->win, _("Colors"));
391 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
393 /* Set Default ColorPanel Mode(s) */
394 panel->mode = WMWheelModeColorPanel;
395 panel->lastChanged = 0;
396 panel->slidersmode = WMRGBModeColorPanel;
397 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
399 /* Some General Purpose Widgets */
400 panel->colorWell = WMCreateColorWell(panel->win);
401 WMResizeWidget(panel->colorWell, 134, 36);
402 WSetColorWellBordered(panel->colorWell, False);
403 WMMoveWidget(panel->colorWell, 56, 4);
405 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
406 WMResizeWidget(panel->magnifyBtn, 46, 36);
407 WMMoveWidget(panel->magnifyBtn, 6, 4);
408 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
409 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
410 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
412 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
413 WMResizeWidget(panel->wheelBtn, 46, 32);
414 WMMoveWidget(panel->wheelBtn, 6, 44);
415 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
416 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
417 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
419 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
420 WMResizeWidget(panel->slidersBtn, 46, 32);
421 WMMoveWidget(panel->slidersBtn, 52, 44);
422 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
423 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
424 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
426 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
427 WMResizeWidget(panel->customPaletteBtn, 46, 32);
428 WMMoveWidget(panel->customPaletteBtn, 98, 44);
429 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
430 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
431 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
433 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
434 WMResizeWidget(panel->colorListBtn, 46, 32);
435 WMMoveWidget(panel->colorListBtn, 144, 44);
436 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
437 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
438 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
440 /* Let's Group some of them together */
441 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
442 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
443 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
445 /* Widgets for the ColorWheel Panel */
446 panel->wheelFrm = WMCreateFrame(panel->win);
447 WMSetFrameRelief(panel->wheelFrm, WRFlat);
448 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
449 WMMoveWidget(panel->wheelFrm, 5, 80);
451 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
452 /* XXX Can we create a view ? */
453 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
454 W_MoveView(panel->wheelView, 0, 0);
456 /* Create an event handler to handle expose/click events in ColorWheel */
457 WMCreateEventHandler(panel->wheelView,
458 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
459 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
461 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
463 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
464 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
465 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
466 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
467 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
468 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
469 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
471 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
472 wheelInitMatrix(panel);
474 /* Widgets for the Slider Panels */
475 panel->slidersFrm = WMCreateFrame(panel->win);
476 WMSetFrameRelief(panel->slidersFrm, WRFlat);
477 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
478 WMMoveWidget(panel->slidersFrm, 4, 80);
480 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
481 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
482 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
483 WMMoveWidget(panel->seperatorFrm, 0, 1);
485 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
486 WMResizeWidget(panel->grayBtn, 46, 24);
487 WMMoveWidget(panel->grayBtn, 1, 8);
488 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
489 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
490 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
492 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
493 WMResizeWidget(panel->rgbBtn, 46, 24);
494 WMMoveWidget(panel->rgbBtn, 47, 8);
495 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
496 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
497 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
499 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
500 WMResizeWidget(panel->cmykBtn, 46, 24);
501 WMMoveWidget(panel->cmykBtn, 93, 8);
502 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
503 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
504 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
506 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
507 WMResizeWidget(panel->hsbBtn, 46, 24);
508 WMMoveWidget(panel->hsbBtn, 139, 8);
509 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
510 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
511 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
513 /* Let's Group the Slider Panel Buttons Together */
514 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
515 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
516 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
518 textcolor = WMDarkGrayColor(scrPtr);
520 /* Widgets for GrayScale Panel */
521 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
522 WMSetFrameRelief(panel->grayFrm, WRFlat);
523 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
524 WMMoveWidget(panel->grayFrm, 0, 34);
526 panel->grayMinL = WMCreateLabel(panel->grayFrm);
527 WMResizeWidget(panel->grayMinL, 20, 10);
528 WMMoveWidget(panel->grayMinL, 2, 2);
529 WMSetLabelText(panel->grayMinL, "0");
530 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
531 WMSetLabelTextColor(panel->grayMinL, textcolor);
532 WMSetLabelFont(panel->grayMinL, panel->font8);
534 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
535 WMResizeWidget(panel->grayMaxL, 40, 10);
536 WMMoveWidget(panel->grayMaxL, 104, 2);
537 WMSetLabelText(panel->grayMaxL, "100");
538 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
539 WMSetLabelTextColor(panel->grayMaxL, textcolor);
540 WMSetLabelFont(panel->grayMaxL, panel->font8);
542 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
543 WMResizeWidget(panel->grayBrightnessS, 141, 16);
544 WMMoveWidget(panel->grayBrightnessS, 2, 14);
545 WMSetSliderMinValue(panel->grayBrightnessS, 0);
546 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
547 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
548 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
550 from.red = 0;
551 from.green = 0;
552 from.blue = 0;
554 to.red = 255;
555 to.green = 255;
556 to.blue = 255;
558 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
559 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
560 RReleaseImage(image);
562 if (pixmap)
563 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
564 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
565 False, _("Brightness"), strlen(_("Brightness")));
566 else
567 wwarning(_("Color Panel: Could not allocate memory"));
569 WMSetSliderImage(panel->grayBrightnessS, pixmap);
570 WMReleasePixmap(pixmap);
572 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
573 WMResizeWidget(panel->grayBrightnessT, 40, 18);
574 WMMoveWidget(panel->grayBrightnessT, 146, 13);
575 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
576 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
577 WMTextDidEndEditingNotification, panel->grayBrightnessT);
579 for (i = 0; i < 7; i++) {
580 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
582 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
583 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
584 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
585 WMReleaseColor(graybuttoncolor);
587 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
588 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
589 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
590 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
591 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
592 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
593 WMReleasePixmap(pixmap);
597 /* End of GrayScale Panel */
599 /* Widgets for RGB Panel */
600 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
601 WMSetFrameRelief(panel->rgbFrm, WRFlat);
602 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
603 WMMoveWidget(panel->rgbFrm, 0, 34);
605 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
606 WMResizeWidget(panel->rgbMinL, 20, 10);
607 WMMoveWidget(panel->rgbMinL, 2, 2);
608 WMSetLabelText(panel->rgbMinL, "0");
609 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
610 WMSetLabelTextColor(panel->rgbMinL, textcolor);
611 WMSetLabelFont(panel->rgbMinL, panel->font8);
613 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
614 WMResizeWidget(panel->rgbMaxL, 40, 10);
615 WMMoveWidget(panel->rgbMaxL, 104, 2);
616 WMSetLabelText(panel->rgbMaxL, "255");
617 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
618 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
619 WMSetLabelFont(panel->rgbMaxL, panel->font8);
621 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
622 WMResizeWidget(panel->rgbRedS, 141, 16);
623 WMMoveWidget(panel->rgbRedS, 2, 14);
624 WMSetSliderMinValue(panel->rgbRedS, 0);
625 WMSetSliderMaxValue(panel->rgbRedS, 255);
626 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
627 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
629 to.red = 255;
630 to.green = 0;
631 to.blue = 0;
633 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
634 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
635 RReleaseImage(image);
637 if (pixmap)
638 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
639 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
640 else
641 wwarning(_("Color Panel: Could not allocate memory"));
643 WMSetSliderImage(panel->rgbRedS, pixmap);
644 WMReleasePixmap(pixmap);
646 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
647 WMResizeWidget(panel->rgbRedT, 40, 18);
648 WMMoveWidget(panel->rgbRedT, 146, 13);
649 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
650 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
652 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
653 WMResizeWidget(panel->rgbGreenS, 141, 16);
654 WMMoveWidget(panel->rgbGreenS, 2, 36);
655 WMSetSliderMinValue(panel->rgbGreenS, 0);
656 WMSetSliderMaxValue(panel->rgbGreenS, 255);
657 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
658 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
660 to.red = 0;
661 to.green = 255;
662 to.blue = 0;
664 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
665 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
666 RReleaseImage(image);
668 if (pixmap)
669 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
670 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
671 else
672 wwarning(_("Color Panel: Could not allocate memory"));
674 WMSetSliderImage(panel->rgbGreenS, pixmap);
675 WMReleasePixmap(pixmap);
677 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
678 WMResizeWidget(panel->rgbGreenT, 40, 18);
679 WMMoveWidget(panel->rgbGreenT, 146, 35);
680 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
681 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
683 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
684 WMResizeWidget(panel->rgbBlueS, 141, 16);
685 WMMoveWidget(panel->rgbBlueS, 2, 58);
686 WMSetSliderMinValue(panel->rgbBlueS, 0);
687 WMSetSliderMaxValue(panel->rgbBlueS, 255);
688 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
689 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
691 to.red = 0;
692 to.green = 0;
693 to.blue = 255;
695 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
696 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
697 RReleaseImage(image);
699 if (pixmap)
700 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
701 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
702 else
703 wwarning(_("Color Panel: Could not allocate memory"));
705 WMSetSliderImage(panel->rgbBlueS, pixmap);
706 WMReleasePixmap(pixmap);
708 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
709 WMResizeWidget(panel->rgbBlueT, 40, 18);
710 WMMoveWidget(panel->rgbBlueT, 146, 57);
711 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
712 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
713 /* End of RGB Panel */
715 /* Widgets for CMYK Panel */
716 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
717 WMSetFrameRelief(panel->cmykFrm, WRFlat);
718 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
719 WMMoveWidget(panel->cmykFrm, 0, 34);
721 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
722 WMResizeWidget(panel->cmykMinL, 20, 10);
723 WMMoveWidget(panel->cmykMinL, 2, 2);
724 WMSetLabelText(panel->cmykMinL, "0");
725 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
726 WMSetLabelTextColor(panel->cmykMinL, textcolor);
727 WMSetLabelFont(panel->cmykMinL, panel->font8);
729 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
730 WMResizeWidget(panel->cmykMaxL, 40, 10);
731 WMMoveWidget(panel->cmykMaxL, 104, 2);
732 WMSetLabelText(panel->cmykMaxL, "100");
733 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
734 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
735 WMSetLabelFont(panel->cmykMaxL, panel->font8);
737 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
738 WMResizeWidget(panel->cmykCyanS, 141, 16);
739 WMMoveWidget(panel->cmykCyanS, 2, 14);
740 WMSetSliderMinValue(panel->cmykCyanS, 0);
741 WMSetSliderMaxValue(panel->cmykCyanS, 100);
742 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
743 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
745 from.red = 255;
746 from.green = 255;
747 from.blue = 255;
749 to.red = 0;
750 to.green = 255;
751 to.blue = 255;
753 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
754 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
755 RReleaseImage(image);
757 if (pixmap)
758 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
759 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
760 else
761 wwarning(_("Color Panel: Could not allocate memory"));
763 WMSetSliderImage(panel->cmykCyanS, pixmap);
764 WMReleasePixmap(pixmap);
766 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
767 WMResizeWidget(panel->cmykCyanT, 40, 18);
768 WMMoveWidget(panel->cmykCyanT, 146, 13);
769 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
770 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
772 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
773 WMResizeWidget(panel->cmykMagentaS, 141, 16);
774 WMMoveWidget(panel->cmykMagentaS, 2, 36);
775 WMSetSliderMinValue(panel->cmykMagentaS, 0);
776 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
777 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
778 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
780 to.red = 255;
781 to.green = 0;
782 to.blue = 255;
784 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
785 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
786 RReleaseImage(image);
788 if (pixmap)
789 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
790 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
791 else
792 wwarning(_("Color Panel: Could not allocate memory"));
794 WMSetSliderImage(panel->cmykMagentaS, pixmap);
795 WMReleasePixmap(pixmap);
797 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
798 WMResizeWidget(panel->cmykMagentaT, 40, 18);
799 WMMoveWidget(panel->cmykMagentaT, 146, 35);
800 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
801 WMAddNotificationObserver(cmykTextFieldCallback, panel,
802 WMTextDidEndEditingNotification, panel->cmykMagentaT);
804 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
805 WMResizeWidget(panel->cmykYellowS, 141, 16);
806 WMMoveWidget(panel->cmykYellowS, 2, 58);
807 WMSetSliderMinValue(panel->cmykYellowS, 0);
808 WMSetSliderMaxValue(panel->cmykYellowS, 100);
809 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
810 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
812 to.red = 255;
813 to.green = 255;
814 to.blue = 0;
816 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
817 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
818 RReleaseImage(image);
820 if (pixmap)
821 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
822 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
823 else
824 wwarning(_("Color Panel: Could not allocate memory"));
826 WMSetSliderImage(panel->cmykYellowS, pixmap);
827 WMReleasePixmap(pixmap);
829 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
830 WMResizeWidget(panel->cmykYellowT, 40, 18);
831 WMMoveWidget(panel->cmykYellowT, 146, 57);
832 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
833 WMAddNotificationObserver(cmykTextFieldCallback, panel,
834 WMTextDidEndEditingNotification, panel->cmykYellowT);
836 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
837 WMResizeWidget(panel->cmykBlackS, 141, 16);
838 WMMoveWidget(panel->cmykBlackS, 2, 80);
839 WMSetSliderMinValue(panel->cmykBlackS, 0);
840 WMSetSliderMaxValue(panel->cmykBlackS, 100);
841 WMSetSliderValue(panel->cmykBlackS, 0);
842 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
843 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
845 to.red = 0;
846 to.green = 0;
847 to.blue = 0;
849 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
850 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
851 RReleaseImage(image);
853 if (pixmap)
854 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
855 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
856 else
857 wwarning(_("Color Panel: Could not allocate memory"));
859 WMSetSliderImage(panel->cmykBlackS, pixmap);
860 WMReleasePixmap(pixmap);
862 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
863 WMResizeWidget(panel->cmykBlackT, 40, 18);
864 WMMoveWidget(panel->cmykBlackT, 146, 79);
865 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
866 WMAddNotificationObserver(cmykTextFieldCallback, panel,
867 WMTextDidEndEditingNotification, panel->cmykBlackT);
868 /* End of CMYK Panel */
870 /* Widgets for HSB Panel */
871 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
872 WMSetFrameRelief(panel->hsbFrm, WRFlat);
873 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
874 WMMoveWidget(panel->hsbFrm, 0, 34);
876 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
877 WMResizeWidget(panel->hsbHueS, 141, 16);
878 WMMoveWidget(panel->hsbHueS, 2, 14);
879 WMSetSliderMinValue(panel->hsbHueS, 0);
880 WMSetSliderMaxValue(panel->hsbHueS, 359);
881 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
882 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
884 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
885 WMResizeWidget(panel->hsbHueT, 40, 18);
886 WMMoveWidget(panel->hsbHueT, 146, 13);
887 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
888 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
890 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
891 WMResizeWidget(panel->hsbSaturationS, 141, 16);
892 WMMoveWidget(panel->hsbSaturationS, 2, 36);
893 WMSetSliderMinValue(panel->hsbSaturationS, 0);
894 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
895 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
896 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
898 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
899 WMResizeWidget(panel->hsbSaturationT, 40, 18);
900 WMMoveWidget(panel->hsbSaturationT, 146, 35);
901 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
902 WMAddNotificationObserver(hsbTextFieldCallback, panel,
903 WMTextDidEndEditingNotification, panel->hsbSaturationT);
905 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
906 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
907 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
908 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
909 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
910 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
911 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
913 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
914 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
915 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
916 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
917 WMAddNotificationObserver(hsbTextFieldCallback, panel,
918 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
919 /* End of HSB Panel */
921 WMReleaseColor(textcolor);
923 /* Widgets for the CustomPalette Panel */
924 panel->customPaletteFrm = WMCreateFrame(panel->win);
925 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
926 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
927 WMMoveWidget(panel->customPaletteFrm, 5, 80);
929 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
930 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
931 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
932 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
933 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
934 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
935 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
937 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
938 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
939 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
940 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
942 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
943 /* XXX Test if we can create a view */
944 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
945 W_MoveView(panel->customPaletteContentView, 2, 2);
947 /* Create event handler to handle expose/click events in CustomPalette */
948 WMCreateEventHandler(panel->customPaletteContentView,
949 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
950 ButtonMotionMask, customPaletteHandleActionEvents, panel);
952 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
954 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
955 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
956 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
957 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
958 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
959 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
961 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
962 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
963 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
964 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
965 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
967 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
968 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
969 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
970 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
972 customRenderSpectrum(panel);
973 panel->currentPalette = 0;
974 panel->palx = customPaletteWidth / 2;
975 panel->paly = customPaletteHeight / 2;
977 /* Widgets for the ColorList Panel */
978 panel->colorListFrm = WMCreateFrame(panel->win);
979 WMSetFrameRelief(panel->colorListFrm, WRFlat);
980 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
981 WMMoveWidget(panel->colorListFrm, 5, 80);
983 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
984 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
985 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
986 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
987 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
988 * colorListHistoryCallback, panel); */
989 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
990 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
992 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
993 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
994 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
995 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
996 WMMoveWidget(panel->colorListContentLst, 0, 23);
997 WMHangData(panel->colorListContentLst, panel);
999 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1000 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1001 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1002 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1003 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1004 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1006 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1007 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1008 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1010 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1011 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1012 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1014 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1015 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1016 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1017 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1018 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1019 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1021 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1022 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1023 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1025 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1026 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1027 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1029 WMRealizeWidget(panel->win);
1030 WMMapSubwidgets(panel->win);
1032 WMMapSubwidgets(panel->wheelFrm);
1033 WMMapSubwidgets(panel->slidersFrm);
1034 WMMapSubwidgets(panel->grayFrm);
1035 WMMapSubwidgets(panel->rgbFrm);
1036 WMMapSubwidgets(panel->cmykFrm);
1037 WMMapSubwidgets(panel->hsbFrm);
1038 WMMapSubwidgets(panel->customPaletteFrm);
1039 WMMapSubwidgets(panel->customPaletteContentFrm);
1040 WMMapSubwidgets(panel->colorListFrm);
1042 /* Pixmap to indicate selection positions
1043 * wheelframe MUST be mapped.
1045 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1046 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1047 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1049 readConfiguration(panel);
1050 readXColors(panel);
1052 return panel;
1055 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1057 WMColorPanel *panel;
1059 if (scrPtr->sharedColorPanel)
1060 return scrPtr->sharedColorPanel;
1062 panel = makeColorPanel(scrPtr, "colorPanel");
1064 scrPtr->sharedColorPanel = panel;
1066 return panel;
1069 void WMFreeColorPanel(WMColorPanel * panel)
1071 W_Screen *scr = WMWidgetScreen(panel->win);
1073 if (panel == scr->sharedColorPanel) {
1074 scr->sharedColorPanel = NULL;
1077 if (!panel)
1078 return;
1080 WMRemoveNotificationObserver(panel);
1081 WMUnmapWidget(panel->win);
1083 /* fonts */
1084 WMReleaseFont(panel->font8);
1085 WMReleaseFont(panel->font12);
1087 /* pixmaps */
1088 wheelDestroyMatrix(panel->wheelMtrx);
1089 if (panel->wheelImg)
1090 XFreePixmap(scr->display, panel->wheelImg);
1091 if (panel->selectionImg)
1092 XFreePixmap(scr->display, panel->selectionImg);
1093 if (panel->selectionBackImg)
1094 XFreePixmap(scr->display, panel->selectionBackImg);
1095 RReleaseImage(panel->customPaletteImg);
1097 /* structs */
1098 if (panel->lastBrowseDir)
1099 wfree(panel->lastBrowseDir);
1100 if (panel->configurationPath)
1101 wfree(panel->configurationPath);
1103 WMDestroyWidget(panel->win);
1105 wfree(panel);
1108 void WMCloseColorPanel(WMColorPanel * panel)
1110 WMFreeColorPanel(panel);
1113 void WMShowColorPanel(WMColorPanel * panel)
1115 WMScreen *scr = WMWidgetScreen(panel->win);
1116 WMColor *white = WMWhiteColor(scr);
1118 if (panel->color.set == cpNone)
1119 WMSetColorPanelColor(panel, white);
1120 WMReleaseColor(white);
1122 if (panel->mode != WMWheelModeColorPanel)
1123 WMPerformButtonClick(panel->wheelBtn);
1125 WMMapWidget(panel->win);
1128 static void closeWindowCallback(WMWidget * w, void *data)
1130 W_ColorPanel *panel = (W_ColorPanel *) data;
1132 /* Parameter not used, but tell the compiler that it is ok */
1133 (void) w;
1135 WMCloseColorPanel(panel);
1138 static void readConfiguration(W_ColorPanel * panel)
1140 /* XXX Doesn't take care of "invalid" files */
1142 DIR *dPtr;
1143 struct dirent *dp;
1144 struct stat stat_buf;
1145 int item;
1147 if (stat(panel->configurationPath, &stat_buf) != 0) {
1148 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1149 werror(_("Color Panel: Could not create directory %s needed"
1150 " to store configurations"), panel->configurationPath);
1151 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1152 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1153 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1154 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1155 _("File Error"),
1156 _("Could not create ColorPanel configuration directory"),
1157 _("OK"), NULL, NULL);
1159 return;
1162 if (!(dPtr = opendir(panel->configurationPath))) {
1163 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1164 return;
1167 while ((dp = readdir(dPtr)) != NULL) {
1168 unsigned int perm_mask;
1169 char *path = wstrconcat(panel->configurationPath,
1170 dp->d_name);
1172 if (dp->d_name[0] != '.') {
1173 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1174 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1176 perm_mask = (access(path, R_OK) == 0);
1177 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1179 wfree(path);
1181 closedir(dPtr);
1184 static void readXColors(W_ColorPanel * panel)
1186 WMListItem *item;
1187 RGBColor *entry;
1189 for (entry = rgbColors; entry->name != NULL; entry++) {
1190 item = WMAddListItem(panel->colorListContentLst, entry->name);
1191 item->clientData = (void *)&(entry->color);
1195 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1197 W_Screen *scr = WMWidgetScreen(panel->win);
1199 if (mode != WMWheelModeColorPanel) {
1200 WMUnmapWidget(panel->wheelFrm);
1201 if (panel->selectionBackImg) {
1202 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1203 panel->selectionBackImg = None;
1206 if (mode != WMGrayModeColorPanel)
1207 WMUnmapWidget(panel->grayFrm);
1208 if (mode != WMRGBModeColorPanel)
1209 WMUnmapWidget(panel->rgbFrm);
1210 if (mode != WMCMYKModeColorPanel)
1211 WMUnmapWidget(panel->cmykFrm);
1212 if (mode != WMHSBModeColorPanel)
1213 WMUnmapWidget(panel->hsbFrm);
1214 if (mode != WMCustomPaletteModeColorPanel) {
1215 WMUnmapWidget(panel->customPaletteFrm);
1216 if (panel->selectionBackImg) {
1217 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1218 panel->selectionBackImg = None;
1221 if (mode != WMColorListModeColorPanel)
1222 WMUnmapWidget(panel->colorListFrm);
1223 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1224 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1225 WMUnmapWidget(panel->slidersFrm);
1226 else
1227 panel->slidersmode = mode;
1229 if (mode == WMWheelModeColorPanel) {
1230 WMMapWidget(panel->wheelFrm);
1231 WMSetButtonSelected(panel->wheelBtn, True);
1232 if (panel->lastChanged != WMWheelModeColorPanel)
1233 wheelInit(panel);
1234 wheelRender(panel);
1235 wheelPaint(panel);
1236 } else if (mode == WMGrayModeColorPanel) {
1237 WMMapWidget(panel->slidersFrm);
1238 WMSetButtonSelected(panel->slidersBtn, True);
1239 WMMapWidget(panel->grayFrm);
1240 WMSetButtonSelected(panel->grayBtn, True);
1241 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1242 if (panel->lastChanged != WMGrayModeColorPanel)
1243 grayInit(panel);
1244 } else if (mode == WMRGBModeColorPanel) {
1245 WMMapWidget(panel->slidersFrm);
1246 WMSetButtonSelected(panel->slidersBtn, True);
1247 WMMapWidget(panel->rgbFrm);
1248 WMSetButtonSelected(panel->rgbBtn, True);
1249 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1250 if (panel->lastChanged != WMRGBModeColorPanel)
1251 rgbInit(panel);
1252 } else if (mode == WMCMYKModeColorPanel) {
1253 WMMapWidget(panel->slidersFrm);
1254 WMSetButtonSelected(panel->slidersBtn, True);
1255 WMMapWidget(panel->cmykFrm);
1256 WMSetButtonSelected(panel->cmykBtn, True);
1257 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1258 if (panel->lastChanged != WMCMYKModeColorPanel)
1259 cmykInit(panel);
1260 } else if (mode == WMHSBModeColorPanel) {
1261 WMMapWidget(panel->slidersFrm);
1262 WMSetButtonSelected(panel->slidersBtn, True);
1263 WMMapWidget(panel->hsbFrm);
1264 WMSetButtonSelected(panel->hsbBtn, True);
1265 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1266 if (panel->lastChanged != WMHSBModeColorPanel)
1267 hsbInit(panel);
1268 } else if (mode == WMCustomPaletteModeColorPanel) {
1269 WMMapWidget(panel->customPaletteFrm);
1270 WMSetButtonSelected(panel->customPaletteBtn, True);
1271 customSetPalette(panel);
1272 } else if (mode == WMColorListModeColorPanel) {
1273 WMMapWidget(panel->colorListFrm);
1274 WMSetButtonSelected(panel->colorListBtn, True);
1277 panel->mode = mode;
1280 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1282 return WMGetColorWellColor(panel->colorWell);
1285 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1287 WMSetColorWellColor(panel->colorWell, color);
1289 panel->color.rgb.red = color->color.red >> 8;
1290 panel->color.rgb.green = color->color.green >> 8;
1291 panel->color.rgb.blue = color->color.blue >> 8;
1292 panel->color.set = cpRGB;
1294 if (panel->mode == panel->lastChanged)
1295 panel->lastChanged = 0;
1297 WMSetColorPanelPickerMode(panel, panel->mode);
1300 static void updateSwatch(WMColorPanel * panel, CPColor color)
1302 WMScreen *scr = WMWidgetScreen(panel->win);
1303 WMColor *wellcolor;
1305 if (color.set != cpRGB)
1306 convertCPColor(&color);
1308 panel->color = color;
1310 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1312 WMSetColorWellColor(panel->colorWell, wellcolor);
1313 WMReleaseColor(wellcolor);
1315 if (!panel->flags.dragging || panel->flags.continuous) {
1316 if (panel->action)
1317 (*panel->action) (panel, panel->clientData);
1319 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1323 static void modeButtonCallback(WMWidget * w, void *data)
1325 W_ColorPanel *panel = (W_ColorPanel *) (data);
1327 if (w == panel->wheelBtn)
1328 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1329 else if (w == panel->slidersBtn)
1330 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1331 else if (w == panel->customPaletteBtn)
1332 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1333 else if (w == panel->colorListBtn)
1334 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1335 else if (w == panel->grayBtn)
1336 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1337 else if (w == panel->rgbBtn)
1338 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1339 else if (w == panel->cmykBtn)
1340 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1341 else if (w == panel->hsbBtn)
1342 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1345 /****************** Magnifying Cursor Functions *******************/
1347 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1349 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1350 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1351 displayHeight = DisplayHeight(scr->display, scr->screen);
1353 if (!(image && image->data)) {
1354 /* The image in panel->magnifyGlass->image does not exist yet.
1355 * Grab one from the screen (not beyond) and use it from now on.
1357 if (!(image = XGetImage(scr->display, scr->rootWin,
1358 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1359 wwarning(_("Color Panel: X failed request"));
1361 return image;
1364 /* Coordinate correction for back pixmap
1365 * if magnifying glass is at screen-borders
1368 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1369 * Hatched area is beyond screen border.
1371 * |<-Cursor_x_hot->|
1372 * ________________|_____
1373 * |/ / / / / / /| | |
1374 * | / / / / / / |(x,y) |
1375 * |/_/_/_/_/_/_/|________|
1376 * |<----x0----->|<--w0-->|
1380 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1381 * screen borders
1382 * Hatched area is beyond screen border
1384 * |<-Cursor_x_hot->|
1385 * ________________|_______________
1386 * | | | / / / / / /|
1387 * | (x,y)|/ / / / / / |
1388 * |___________________|_/_/_/_/_/_/|
1389 * |<-------w0-------->| |
1390 * |<---------------w--|----------->|
1391 * | |
1392 * x0 Displaywidth-1
1395 if (x < Cursor_x_hot) { /* see fig. 1 */
1396 x0 = Cursor_x_hot - x;
1397 w0 = w - x0;
1400 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1401 w0 = (displayWidth) - (x - Cursor_x_hot);
1404 if (y < Cursor_y_hot) { /* see fig. 1 */
1405 y0 = Cursor_y_hot - y;
1406 h0 = h - y0;
1409 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1410 h0 = (displayHeight) - (y - Cursor_y_hot);
1412 /* end of coordinate correction */
1414 /* Grab an image from the screen, clipped if necessary,
1415 * and put it in the existing panel->magnifyGlass->image
1416 * with the corresponding clipping offset.
1418 if (!XGetSubImage(scr->display, scr->rootWin,
1419 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1420 wwarning(_("Color Panel: X failed request"));
1422 return NULL;
1425 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1427 /* (x1, y1) = topleft corner of existing rectangle
1428 * (x2, y2) = topleft corner of new position
1431 W_Screen *scr = WMWidgetScreen(panel->win);
1432 int xa = 0, ya = 0, xb = 0, yb = 0;
1433 int width, height;
1434 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1435 XImage *image;
1436 const int x_min = Cursor_x_hot,
1437 y_min = Cursor_y_hot,
1438 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1439 (Cursor_mask_width - Cursor_x_hot),
1440 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1442 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1443 return; /* No movement */
1445 if (x1 < x2)
1446 xa = dx;
1447 else
1448 xb = dx;
1450 if (y1 < y2)
1451 ya = dy;
1452 else
1453 yb = dy;
1455 width = Cursor_mask_width - dx;
1456 height = Cursor_mask_height - dy;
1458 /* If the traversed distance is larger than the size of the magnifying
1459 * glass contents, there is no need to do dirty rectangles. A whole new
1460 * rectangle can be grabbed (unless that rectangle falls partially
1461 * off screen).
1462 * Destroying the image and setting it to NULL will achieve that later on.
1464 * Of course, grabbing an XImage beyond the borders of the screen will
1465 * cause trouble, this is considdered a special case. Part of the screen
1466 * is grabbed, but there is no need for dirty rectangles.
1468 if ((width <= 0) || (height <= 0)) {
1469 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1470 if (panel->magnifyGlass->image)
1471 XDestroyImage(panel->magnifyGlass->image);
1472 panel->magnifyGlass->image = NULL;
1474 } else {
1475 if (panel->magnifyGlass->image) {
1476 /* Get dirty rectangle from panel->magnifyGlass->image */
1477 panel->magnifyGlass->dirtyRect =
1478 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1479 if (!panel->magnifyGlass->dirtyRect) {
1480 wwarning(_("Color Panel: X failed request"));
1481 return; /* X returned a NULL from XSubImage */
1486 /* Get image from screen */
1487 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1488 if (image) { /* Only reassign if a *new* image was grabbed */
1489 panel->magnifyGlass->image = image;
1490 return;
1493 /* Copy previously stored rectangle on covered part of image */
1494 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1495 int old_height;
1497 /* "width" and "height" are used as coordinates here,
1498 * and run from [0...width-1] and [0...height-1] respectively.
1500 width--;
1501 height--;
1502 old_height = height;
1504 for (; width >= 0; width--)
1505 for (height = old_height; height >= 0; height--)
1506 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1507 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1508 XDestroyImage(panel->magnifyGlass->dirtyRect);
1509 panel->magnifyGlass->dirtyRect = NULL;
1512 return;
1515 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1517 W_Screen *scr = WMWidgetScreen(panel->win);
1518 int u, v;
1519 #ifndef SHAPE
1520 Pixmap pixmap;
1521 #endif
1522 unsigned long color;
1524 if (!panel->magnifyGlass->image)
1525 return None;
1527 if (!panel->magnifyGlass->magPix)
1528 return None;
1531 * Copy an area of only 5x5 pixels from the center of the image.
1533 for (u = 0; u < 5; u++) {
1534 for (v = 0; v < 5; v++) {
1535 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1537 XSetForeground(scr->display, scr->copyGC, color);
1539 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1540 panel->magnifyGlass->color = ulongToRColor(scr, color);
1542 /* The center square must eventually be centered around the
1543 * hotspot. The image needs shifting to achieve this. The amount of
1544 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1545 * _ _ _ _ _
1546 * |_|_|_|_|_|
1547 * ^------- center of center square == Cursor_x_hot
1549 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1550 scr->copyGC,
1551 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1552 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1556 #ifdef SHAPE
1557 return panel->magnifyGlass->magPix;
1558 #else
1559 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1560 if (!pixmap)
1561 return None;
1563 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1564 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1566 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1567 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1568 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1569 /* (2,2) puts center pixel on center of glass */
1571 return pixmap;
1572 #endif
1576 static WMView *magnifyCreateView(W_ColorPanel * panel)
1578 W_Screen *scr = WMWidgetScreen(panel->win);
1579 WMView *magView;
1581 magView = W_CreateTopView(scr);
1582 if (!magView)
1583 return NULL;
1585 magView->self = panel->win;
1586 magView->flags.topLevel = 1;
1587 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1588 magView->attribs.override_redirect = True;
1589 magView->attribs.save_under = True;
1591 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1593 W_RealizeView(magView);
1595 return magView;
1598 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1600 W_Screen *scr = WMWidgetScreen(panel->win);
1601 Pixmap magPixmap, magPixmap2;
1602 Cursor magCursor;
1603 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1604 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1606 /* Cursor creation stuff */
1607 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1608 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1609 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1610 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1612 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1613 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1615 XFreePixmap(scr->display, magPixmap);
1616 XFreePixmap(scr->display, magPixmap2);
1618 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1620 /* Set up Pointer */
1621 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1622 PointerMotionMask | ButtonPressMask,
1623 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1625 return magCursor;
1628 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1630 W_Screen *scr = WMWidgetScreen(panel->win);
1631 int x, y, u, v;
1632 unsigned int mask;
1633 Pixmap pixmap, clip_mask;
1634 WMPoint point;
1635 Window root_return, child_return;
1637 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1638 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1639 1, 0, 1);
1640 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1641 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1643 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1645 panel->magnifyGlass->image = NULL;
1647 /* Clipmask to make magnified view-contents circular */
1648 #ifdef SHAPE
1649 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1650 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1651 #else
1652 /* Clip circle in glass cursor */
1653 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1654 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1655 #endif
1657 XFreePixmap(scr->display, clip_mask);
1659 /* Draw initial magnifying glass contents */
1660 magnifyGetImageStored(panel, x, y, x, y);
1662 pixmap = magnifyCreatePixmap(panel);
1663 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1664 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1665 XFlush(scr->display);
1667 #ifndef SHAPE
1668 XFreePixmap(scr->display, pixmap);
1669 #endif
1671 point.x = x;
1672 point.y = y;
1674 return point;
1677 static void magnifyPutCursor(WMWidget * w, void *data)
1679 W_ColorPanel *panel = (W_ColorPanel *) (data);
1680 W_Screen *scr = WMWidgetScreen(panel->win);
1681 Cursor magCursor;
1682 Pixmap pixmap;
1683 XEvent event;
1684 WMPoint initialPosition;
1686 /* Parameter not used, but tell the compiler that it is ok */
1687 (void) w;
1689 /* Destroy wheelBackImg, so it'll update properly */
1690 if (panel->selectionBackImg) {
1691 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1692 panel->selectionBackImg = None;
1695 /* Create magnifying glass */
1696 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1697 panel->magnifyGlass->view = magnifyCreateView(panel);
1698 if (!panel->magnifyGlass->view)
1699 return;
1701 initialPosition = magnifyInitialize(panel);
1702 panel->magnifyGlass->x = initialPosition.x;
1703 panel->magnifyGlass->y = initialPosition.y;
1705 W_MoveView(panel->magnifyGlass->view,
1706 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1707 W_MapView(panel->magnifyGlass->view);
1709 magCursor = magnifyGrabPointer(panel);
1711 while (panel->magnifyGlass->image) {
1712 WMNextEvent(scr->display, &event);
1714 /* Pack motion events */
1715 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1718 switch (event.type) {
1719 case ButtonPress:
1720 XDestroyImage(panel->magnifyGlass->image);
1721 panel->magnifyGlass->image = NULL;
1723 if (event.xbutton.button == Button1) {
1724 panel->color.rgb = panel->magnifyGlass->color;
1725 panel->color.set = cpRGB;
1726 updateSwatch(panel, panel->color);
1728 switch (panel->mode) {
1729 case WMWheelModeColorPanel:
1730 wheelInit(panel);
1731 wheelRender(panel);
1732 wheelPaint(panel);
1733 break;
1734 case WMGrayModeColorPanel:
1735 grayInit(panel);
1736 break;
1737 case WMRGBModeColorPanel:
1738 rgbInit(panel);
1739 break;
1740 case WMCMYKModeColorPanel:
1741 cmykInit(panel);
1742 break;
1743 case WMHSBModeColorPanel:
1744 hsbInit(panel);
1745 break;
1746 default:
1747 break;
1749 panel->lastChanged = panel->mode;
1751 WMSetButtonSelected(panel->magnifyBtn, False);
1752 break;
1754 case MotionNotify:
1755 while (XPending(event.xmotion.display)) {
1756 XEvent ev;
1757 XPeekEvent(event.xmotion.display, &ev);
1758 if (ev.type == MotionNotify)
1759 XNextEvent(event.xmotion.display, &event);
1760 else
1761 break;
1764 /* Get a "dirty rectangle" */
1765 magnifyGetImageStored(panel,
1766 panel->magnifyGlass->x, panel->magnifyGlass->y,
1767 event.xmotion.x_root, event.xmotion.y_root);
1769 /* Update coordinates */
1770 panel->magnifyGlass->x = event.xmotion.x_root;
1771 panel->magnifyGlass->y = event.xmotion.y_root;
1773 /* Move view */
1774 W_MoveView(panel->magnifyGlass->view,
1775 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1777 /* Put new image (with magn.) in view */
1778 pixmap = magnifyCreatePixmap(panel);
1779 if (pixmap != None) {
1780 /* Change the window background */
1781 XSetWindowBackgroundPixmap(scr->display,
1782 WMViewXID(panel->magnifyGlass->view), pixmap);
1783 /* Force an Expose (handled by X) */
1784 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1785 /* Synchronize the event queue, so the Expose is handled NOW */
1786 XFlush(scr->display);
1787 #ifndef SHAPE
1788 XFreePixmap(scr->display, pixmap);
1789 #endif
1791 break;
1793 /* Try XQueryPointer for this !!! It returns windows that the pointer
1794 * is over. Note: We found this solving the invisible donkey cap bug
1796 #if 0 /* As it is impossible to make this work in all cases,
1797 * we consider it confusing. Therefore we disabled it.
1799 case FocusOut: /* fall through */
1800 case FocusIn:
1802 * Color Panel window (panel->win) lost or received focus.
1803 * We need to update the pixmap in the magnifying glass.
1805 * BUG Doesn't work with focus switches between two windows
1806 * if none of them is the color panel.
1808 XUngrabPointer(scr->display, CurrentTime);
1809 W_UnmapView(panel->magnifyGlass->view);
1811 magnifyInitialize(panel);
1813 W_MapView(panel->magnifyGlass->view);
1814 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1815 True, PointerMotionMask | ButtonPressMask,
1816 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1817 break;
1818 #endif
1819 default:
1820 WMHandleEvent(&event);
1821 break;
1822 } /* of switch */
1825 XUngrabPointer(scr->display, CurrentTime);
1826 XFreeCursor(scr->display, magCursor);
1828 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1829 panel->magnifyGlass->magPix = None;
1831 W_UnmapView(panel->magnifyGlass->view);
1832 W_DestroyView(panel->magnifyGlass->view);
1833 panel->magnifyGlass->view = NULL;
1835 wfree(panel->magnifyGlass);
1838 /****************** ColorWheel Functions ************************/
1840 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1842 wheelMatrix *matrix = NULL;
1843 int i;
1845 assert((width > 0) && (height > 0));
1847 matrix = wmalloc(sizeof(wheelMatrix));
1848 matrix->width = width;
1849 matrix->height = height;
1851 for (i = 0; i < 3; i++) {
1852 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1855 return matrix;
1858 static void wheelDestroyMatrix(wheelMatrix * matrix)
1860 int i;
1862 if (!matrix)
1863 return;
1865 for (i = 0; i < 3; i++) {
1866 if (matrix->data[i])
1867 wfree(matrix->data[i]);
1869 wfree(matrix);
1872 static void wheelInitMatrix(W_ColorPanel * panel)
1874 int i;
1875 int x, y;
1876 unsigned char *rp, *gp, *bp;
1877 CPColor cpColor;
1878 long ofs[4];
1879 int xcor, ycor;
1880 unsigned short sat;
1881 int dhue[4];
1882 const int cw_halfsize = (colorWheelSize + 4) / 2,
1883 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1885 if (!panel->wheelMtrx)
1886 return;
1888 cpColor.hsv.value = 255;
1889 cpColor.set = cpHSV;
1891 ofs[0] = -1;
1892 ofs[1] = -(colorWheelSize + 4);
1894 /* offsets are counterclockwise (in triangles).
1896 * ofs[0] ---->
1897 * _______________________________________
1898 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1899 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1900 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1901 * o | | | | | | | | | | | | | | | | | | | | | [3]
1903 * <---- ofs[2]
1904 * ____
1905 * |\ /| <-- triangles
1906 * | \/ |
1907 * | /\ |
1908 * |/__\|
1911 for (y = 0; y < cw_halfsize; y++) {
1912 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1913 /* (xcor, ycor) is (x,y) relative to center of matrix */
1914 xcor = 2 * x - 4 - colorWheelSize;
1915 ycor = 2 * y - 4 - colorWheelSize;
1917 /* RColor.saturation is unsigned char and will wrap after 255 */
1918 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1920 cpColor.hsv.saturation = (unsigned char)sat;
1922 ofs[0]++; /* top quarter of matrix */
1923 ofs[1] += colorWheelSize + 4; /* left quarter */
1924 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1925 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1927 if (sat < 256) {
1928 if (xcor != 0)
1929 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1930 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1931 else
1932 dhue[0] = 270;
1934 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1935 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1936 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1937 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1939 for (i = 0; i < 4; i++) {
1940 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1941 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1942 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1944 cpColor.hsv.hue = dhue[i];
1945 convertCPColor(&cpColor);
1947 *rp = (unsigned char)(cpColor.rgb.red);
1948 *gp = (unsigned char)(cpColor.rgb.green);
1949 *bp = (unsigned char)(cpColor.rgb.blue);
1951 } else {
1952 for (i = 0; i < 4; i++) {
1953 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1954 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1955 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1957 *rp = (unsigned char)0;
1958 *gp = (unsigned char)0;
1959 *bp = (unsigned char)0;
1964 ofs[0] += 2 * y + 1;
1965 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1969 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1971 unsigned int i;
1972 unsigned int v;
1974 for (i = 0; i < 256; i++) {
1975 /* We divide by 128 in advance, and check whether that number divides
1976 * by 2 properly. If not, we add one to round the number correctly
1978 v = (i * maxvalue) >> 7;
1979 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
1983 static void wheelRender(W_ColorPanel * panel)
1985 W_Screen *scr = WMWidgetScreen(panel->win);
1986 int x, y;
1987 RImage *image;
1988 unsigned char *ptr;
1989 RColor gray;
1990 unsigned long ofs = 0;
1991 /*unsigned char shift = getShift(sizeof(unsigned char)); */
1993 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
1994 if (!image) {
1995 wwarning(_("Color Panel: Could not allocate memory"));
1996 return;
1999 ptr = image->data;
2001 /* TODO Make this transparent istead of gray */
2002 gray.red = gray.blue = 0xae;
2003 gray.green = 0xaa;
2005 for (y = 0; y < colorWheelSize + 4; y++) {
2006 for (x = 0; x < colorWheelSize + 4; x++) {
2007 if (wheelInsideColorWheel(panel, ofs)) {
2008 *(ptr++) =
2009 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2010 *(ptr++) =
2011 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2012 *(ptr++) =
2013 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2014 *(ptr++) = 0;
2015 } else {
2016 *(ptr++) = (unsigned char)(gray.red);
2017 *(ptr++) = (unsigned char)(gray.green);
2018 *(ptr++) = (unsigned char)(gray.blue);
2019 *(ptr++) = 255;
2021 ofs++;
2025 if (panel->wheelImg)
2026 XFreePixmap(scr->display, panel->wheelImg);
2028 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2029 RReleaseImage(image);
2031 /* Check if backimage exists. If it doesn't, allocate and fill it */
2032 if (!panel->selectionBackImg) {
2033 panel->selectionBackImg = XCreatePixmap(scr->display,
2034 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2035 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2036 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2037 /* -2 is hot spot correction */
2041 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2043 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2044 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2047 static void wheelPaint(W_ColorPanel * panel)
2049 W_Screen *scr = WMWidgetScreen(panel->win);
2051 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2052 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2054 /* Draw selection image */
2055 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2056 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2059 static void wheelHandleEvents(XEvent * event, void *data)
2061 W_ColorPanel *panel = (W_ColorPanel *) data;
2063 switch (event->type) {
2064 case Expose:
2065 if (event->xexpose.count != 0) /* TODO Improve */
2066 break;
2067 wheelPaint(panel);
2068 break;
2072 static void wheelHandleActionEvents(XEvent * event, void *data)
2074 W_ColorPanel *panel = (W_ColorPanel *) data;
2076 switch (event->type) {
2077 case ButtonPress:
2078 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2080 panel->lastChanged = WMWheelModeColorPanel;
2081 panel->flags.dragging = 1;
2083 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2085 break;
2087 case ButtonRelease:
2088 panel->flags.dragging = 0;
2089 if (!panel->flags.continuous) {
2090 if (panel->action)
2091 (*panel->action) (panel, panel->clientData);
2093 break;
2095 case MotionNotify:
2096 if (panel->flags.dragging) {
2097 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2098 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2099 } else
2100 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2102 break;
2106 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2108 int lx, ly;
2109 unsigned long ofs;
2111 lx = x;
2112 ly = y;
2114 if (panel->mode == WMWheelModeColorPanel) {
2115 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2117 ofs = ly * panel->wheelMtrx->width + lx;
2119 if (wheelInsideColorWheel(panel, ofs))
2120 return COLORWHEEL_PART;
2124 if (panel->mode == WMCustomPaletteModeColorPanel) {
2125 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2126 return CUSTOMPALETTE_PART;
2130 return 0;
2133 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2135 int value;
2137 W_ColorPanel *panel = (W_ColorPanel *) data;
2139 /* Parameter not used, but tell the compiler that it is ok */
2140 (void) w;
2142 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2144 wheelCalculateValues(panel, value);
2146 if (panel->color.set == cpRGB) {
2147 convertCPColor(&panel->color);
2148 panel->color.set = cpHSV;
2151 panel->color.hsv.value = value;
2153 wheelRender(panel);
2154 wheelPaint(panel);
2155 wheelUpdateSelection(panel);
2158 static void wheelUpdateSelection(W_ColorPanel * panel)
2160 W_Screen *scr = WMWidgetScreen(panel->win);
2162 updateSwatch(panel, panel->color);
2163 panel->lastChanged = WMWheelModeColorPanel;
2165 /* Redraw color selector (and make a backup of the part it will cover) */
2166 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2167 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2168 /* "-2" is correction for hotspot location */
2169 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2170 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2171 /* see above */
2174 static void wheelUndrawSelection(W_ColorPanel * panel)
2176 W_Screen *scr = WMWidgetScreen(panel->win);
2178 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2179 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2180 /* see above */
2183 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2185 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2187 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2189 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2191 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2192 panel->color.set = cpRGB;
2194 wheelUndrawSelection(panel);
2196 panel->colx = x;
2197 panel->coly = y;
2199 wheelUpdateSelection(panel);
2200 wheelUpdateBrightnessGradientFromLocation(panel);
2203 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2205 int hue;
2206 int xcor, ycor;
2207 CPColor cpColor;
2209 xcor = x * 2 - colorWheelSize - 4;
2210 ycor = y * 2 - colorWheelSize - 4;
2212 panel->color.hsv.saturation = 255;
2213 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2215 if (xcor != 0)
2216 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2217 else {
2218 if (ycor < 0)
2219 hue = 90;
2220 else
2221 hue = 270;
2224 if (xcor < 0)
2225 hue += 180;
2227 if ((xcor > 0) && (ycor > 0))
2228 hue += 360;
2230 panel->color.hsv.hue = hue;
2231 panel->color.set = cpHSV;
2232 convertCPColor(&panel->color);
2234 wheelUndrawSelection(panel);
2236 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2237 /* "+2" because of "colorWheelSize + 4" */
2238 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2240 wheelUpdateSelection(panel);
2241 cpColor = panel->color;
2242 wheelUpdateBrightnessGradient(panel, cpColor);
2245 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2247 CPColor from;
2248 unsigned long ofs;
2250 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2252 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2253 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2254 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2255 from.set = cpRGB;
2257 wheelUpdateBrightnessGradient(panel, from);
2260 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2262 RColor to;
2263 RImage *sliderImg;
2264 WMPixmap *sliderPxmp;
2266 to.red = to.green = to.blue = 0;
2268 if (topColor.set == cpHSV)
2269 convertCPColor(&topColor);
2271 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2272 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2273 RReleaseImage(sliderImg);
2274 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2275 WMReleasePixmap(sliderPxmp);
2278 /****************** Grayscale Panel Functions ***************/
2280 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2282 CPColor cpColor;
2283 int value;
2284 char tmp[4];
2285 W_ColorPanel *panel = (W_ColorPanel *) data;
2287 /* Parameter not used, but tell the compiler that it is ok */
2288 (void) w;
2290 value = WMGetSliderValue(panel->grayBrightnessS);
2292 sprintf(tmp, "%d", value);
2294 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2295 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2296 cpColor.set = cpRGB;
2298 updateSwatch(panel, cpColor);
2299 panel->lastChanged = WMGrayModeColorPanel;
2302 static void grayPresetButtonCallback(WMWidget * w, void *data)
2304 CPColor cpColor;
2305 char tmp[4];
2306 int value;
2307 int i = 0;
2308 W_ColorPanel *panel = (W_ColorPanel *) data;
2310 while (i < 7) {
2311 if (w == panel->grayPresetBtn[i])
2312 break;
2313 i++;
2316 value = rint((100.0 * i) / 6.0);
2317 sprintf(tmp, "%d", value);
2319 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2320 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2321 cpColor.set = cpRGB;
2323 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2325 updateSwatch(panel, cpColor);
2326 panel->lastChanged = WMGrayModeColorPanel;
2329 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2331 CPColor cpColor;
2332 char tmp[4];
2333 int value;
2334 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2336 /* Parameter not used, but tell the compiler that it is ok */
2337 (void) notification;
2339 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2340 if (value > 100)
2341 value = 100;
2342 if (value < 0)
2343 value = 0;
2345 sprintf(tmp, "%d", value);
2346 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2347 WMSetSliderValue(panel->grayBrightnessS, value);
2349 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2350 cpColor.set = cpRGB;
2352 updateSwatch(panel, cpColor);
2353 panel->lastChanged = WMGrayModeColorPanel;
2356 /******************* RGB Panel Functions *****************/
2358 static void rgbSliderCallback(WMWidget * w, void *data)
2360 CPColor cpColor;
2361 int value[3];
2362 char tmp[4];
2363 W_ColorPanel *panel = (W_ColorPanel *) data;
2365 /* Parameter not used, but tell the compiler that it is ok */
2366 (void) w;
2368 value[0] = WMGetSliderValue(panel->rgbRedS);
2369 value[1] = WMGetSliderValue(panel->rgbGreenS);
2370 value[2] = WMGetSliderValue(panel->rgbBlueS);
2372 sprintf(tmp, "%d", value[0]);
2373 WMSetTextFieldText(panel->rgbRedT, tmp);
2374 sprintf(tmp, "%d", value[1]);
2375 WMSetTextFieldText(panel->rgbGreenT, tmp);
2376 sprintf(tmp, "%d", value[2]);
2377 WMSetTextFieldText(panel->rgbBlueT, tmp);
2379 cpColor.rgb.red = value[0];
2380 cpColor.rgb.green = value[1];
2381 cpColor.rgb.blue = value[2];
2382 cpColor.set = cpRGB;
2384 updateSwatch(panel, cpColor);
2385 panel->lastChanged = WMRGBModeColorPanel;
2388 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2390 CPColor cpColor;
2391 int value[3];
2392 char tmp[4];
2393 int n;
2394 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2396 /* Parameter not used, but tell the compiler that it is ok */
2397 (void) notification;
2399 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2400 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2401 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2403 for (n = 0; n < 3; n++) {
2404 if (value[n] > 255)
2405 value[n] = 255;
2406 if (value[n] < 0)
2407 value[n] = 0;
2410 sprintf(tmp, "%d", value[0]);
2411 WMSetTextFieldText(panel->rgbRedT, tmp);
2412 sprintf(tmp, "%d", value[1]);
2413 WMSetTextFieldText(panel->rgbGreenT, tmp);
2414 sprintf(tmp, "%d", value[2]);
2415 WMSetTextFieldText(panel->rgbBlueT, tmp);
2417 WMSetSliderValue(panel->rgbRedS, value[0]);
2418 WMSetSliderValue(panel->rgbGreenS, value[1]);
2419 WMSetSliderValue(panel->rgbBlueS, value[2]);
2421 cpColor.rgb.red = value[0];
2422 cpColor.rgb.green = value[1];
2423 cpColor.rgb.blue = value[2];
2424 cpColor.set = cpRGB;
2426 updateSwatch(panel, cpColor);
2427 panel->lastChanged = WMRGBModeColorPanel;
2430 /******************* CMYK Panel Functions *****************/
2432 static void cmykSliderCallback(WMWidget * w, void *data)
2434 CPColor cpColor;
2435 int value[4];
2436 char tmp[4];
2437 W_ColorPanel *panel = (W_ColorPanel *) data;
2438 double scale;
2440 /* Parameter not used, but tell the compiler that it is ok */
2441 (void) w;
2443 value[0] = WMGetSliderValue(panel->cmykCyanS);
2444 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2445 value[2] = WMGetSliderValue(panel->cmykYellowS);
2446 value[3] = WMGetSliderValue(panel->cmykBlackS);
2448 sprintf(tmp, "%d", value[0]);
2449 WMSetTextFieldText(panel->cmykCyanT, tmp);
2450 sprintf(tmp, "%d", value[1]);
2451 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2452 sprintf(tmp, "%d", value[2]);
2453 WMSetTextFieldText(panel->cmykYellowT, tmp);
2454 sprintf(tmp, "%d", value[3]);
2455 WMSetTextFieldText(panel->cmykBlackT, tmp);
2457 scale = 2.55 * (1.0 - (value[3] / 100.0));
2458 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2459 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2460 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2461 cpColor.set = cpRGB;
2463 updateSwatch(panel, cpColor);
2464 panel->lastChanged = WMCMYKModeColorPanel;
2467 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2469 CPColor cpColor;
2470 int value[4];
2471 char tmp[4];
2472 int n;
2473 double scale;
2474 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2476 /* Parameter not used, but tell the compiler that it is ok */
2477 (void) notification;
2479 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2480 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2481 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2482 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2484 for (n = 0; n < 4; n++) {
2485 if (value[n] > 100)
2486 value[n] = 100;
2487 if (value[n] < 0)
2488 value[n] = 0;
2491 sprintf(tmp, "%d", value[0]);
2492 WMSetTextFieldText(panel->cmykCyanT, tmp);
2494 sprintf(tmp, "%d", value[1]);
2495 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2497 sprintf(tmp, "%d", value[2]);
2498 WMSetTextFieldText(panel->cmykYellowT, tmp);
2500 sprintf(tmp, "%d", value[3]);
2501 WMSetTextFieldText(panel->cmykBlackT, tmp);
2503 WMSetSliderValue(panel->cmykCyanS, value[0]);
2504 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2505 WMSetSliderValue(panel->cmykYellowS, value[2]);
2506 WMSetSliderValue(panel->cmykBlackS, value[3]);
2508 scale = 2.55 * (1.0 - (value[3] / 100.0));
2509 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2510 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2511 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2512 cpColor.set = cpRGB;
2514 updateSwatch(panel, cpColor);
2515 panel->lastChanged = WMCMYKModeColorPanel;
2518 /********************** HSB Panel Functions ***********************/
2520 static void hsbSliderCallback(WMWidget * w, void *data)
2522 CPColor cpColor;
2523 int value[3];
2524 char tmp[4];
2525 W_ColorPanel *panel = (W_ColorPanel *) data;
2527 value[0] = WMGetSliderValue(panel->hsbHueS);
2528 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2529 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2531 sprintf(tmp, "%d", value[0]);
2532 WMSetTextFieldText(panel->hsbHueT, tmp);
2533 sprintf(tmp, "%d", value[1]);
2534 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2535 sprintf(tmp, "%d", value[2]);
2536 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2538 cpColor.hsv.hue = value[0];
2539 cpColor.hsv.saturation = value[1] * 2.55;
2540 cpColor.hsv.value = value[2] * 2.55;
2541 cpColor.set = cpHSV;
2543 convertCPColor(&cpColor);
2545 panel->lastChanged = WMHSBModeColorPanel;
2546 updateSwatch(panel, cpColor);
2548 if (w != panel->hsbBrightnessS)
2549 hsbUpdateBrightnessGradient(panel);
2550 if (w != panel->hsbSaturationS)
2551 hsbUpdateSaturationGradient(panel);
2552 if (w != panel->hsbHueS)
2553 hsbUpdateHueGradient(panel);
2556 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2558 CPColor cpColor;
2559 int value[3];
2560 char tmp[4];
2561 int n;
2562 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2564 /* Parameter not used, but tell the compiler that it is ok */
2565 (void) notification;
2567 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2568 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2569 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2571 if (value[0] > 359)
2572 value[0] = 359;
2573 if (value[0] < 0)
2574 value[0] = 0;
2576 for (n = 1; n < 3; n++) {
2577 if (value[n] > 100)
2578 value[n] = 100;
2579 if (value[n] < 0)
2580 value[n] = 0;
2583 sprintf(tmp, "%d", value[0]);
2584 WMSetTextFieldText(panel->hsbHueT, tmp);
2585 sprintf(tmp, "%d", value[1]);
2586 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2587 sprintf(tmp, "%d", value[2]);
2588 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2590 WMSetSliderValue(panel->hsbHueS, value[0]);
2591 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2592 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2594 cpColor.hsv.hue = value[0];
2595 cpColor.hsv.saturation = value[1] * 2.55;
2596 cpColor.hsv.value = value[2] * 2.55;
2597 cpColor.set = cpHSV;
2599 convertCPColor(&cpColor);
2601 panel->lastChanged = WMHSBModeColorPanel;
2602 updateSwatch(panel, cpColor);
2604 hsbUpdateBrightnessGradient(panel);
2605 hsbUpdateSaturationGradient(panel);
2606 hsbUpdateHueGradient(panel);
2609 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2611 W_Screen *scr = WMWidgetScreen(panel->win);
2612 RColor from;
2613 CPColor to;
2614 RImage *sliderImg;
2615 WMPixmap *sliderPxmp;
2617 from.red = from.green = from.blue = 0;
2618 to.hsv = panel->color.hsv;
2619 to.hsv.value = 255;
2620 to.set = cpHSV;
2622 convertCPColor(&to);
2624 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2625 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2626 RReleaseImage(sliderImg);
2628 if (sliderPxmp)
2629 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2630 panel->font12, 2, 0, 100, WALeft, scr->white,
2631 False, _("Brightness"), strlen(_("Brightness")));
2632 else
2633 wwarning(_("Color Panel: Could not allocate memory"));
2635 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2636 WMReleasePixmap(sliderPxmp);
2639 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2641 W_Screen *scr = WMWidgetScreen(panel->win);
2642 CPColor from;
2643 CPColor to;
2644 RImage *sliderImg;
2645 WMPixmap *sliderPxmp;
2647 from.hsv = panel->color.hsv;
2648 from.hsv.saturation = 0;
2649 from.set = cpHSV;
2650 convertCPColor(&from);
2652 to.hsv = panel->color.hsv;
2653 to.hsv.saturation = 255;
2654 to.set = cpHSV;
2655 convertCPColor(&to);
2657 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2658 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2659 RReleaseImage(sliderImg);
2661 if (sliderPxmp)
2662 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2663 panel->font12, 2, 0, 100, WALeft,
2664 from.hsv.value < 128 ? scr->white : scr->black, False,
2665 _("Saturation"), strlen(_("Saturation")));
2666 else
2667 wwarning(_("Color Panel: Could not allocate memory"));
2669 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2670 WMReleasePixmap(sliderPxmp);
2673 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2675 W_Screen *scr = WMWidgetScreen(panel->win);
2676 RColor **colors = NULL;
2677 RHSVColor hsvcolor;
2678 RImage *sliderImg;
2679 WMPixmap *sliderPxmp;
2680 int i;
2682 hsvcolor = panel->color.hsv;
2684 colors = wmalloc(sizeof(RColor *) * (8));
2685 for (i = 0; i < 7; i++) {
2686 hsvcolor.hue = (360 * i) / 6;
2687 colors[i] = wmalloc(sizeof(RColor));
2688 RHSVtoRGB(&hsvcolor, colors[i]);
2690 colors[7] = NULL;
2692 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2693 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2694 RReleaseImage(sliderImg);
2696 if (sliderPxmp)
2697 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2698 panel->font12, 2, 0, 100, WALeft,
2699 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2700 else
2701 wwarning(_("Color Panel: Could not allocate memory"));
2703 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2704 WMReleasePixmap(sliderPxmp);
2706 for (i = 0; i < 7; i++)
2707 wfree(colors[i]);
2709 wfree(colors);
2712 /*************** Custom Palette Functions ****************/
2714 static void customRenderSpectrum(W_ColorPanel * panel)
2716 RImage *spectrum;
2717 int x, y;
2718 unsigned char *ptr;
2719 CPColor cpColor;
2721 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2723 ptr = spectrum->data;
2725 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2726 cpColor.hsv.hue = y;
2727 cpColor.hsv.saturation = 0;
2728 cpColor.hsv.value = 255;
2729 cpColor.set = cpHSV;
2731 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2732 convertCPColor(&cpColor);
2734 *(ptr++) = (unsigned char)cpColor.rgb.red;
2735 *(ptr++) = (unsigned char)cpColor.rgb.green;
2736 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2738 if (x < (SPECTRUM_WIDTH / 2))
2739 cpColor.hsv.saturation++;
2741 if (x > (SPECTRUM_WIDTH / 2))
2742 cpColor.hsv.value--;
2745 if (panel->customPaletteImg) {
2746 RReleaseImage(panel->customPaletteImg);
2747 panel->customPaletteImg = NULL;
2749 panel->customPaletteImg = spectrum;
2752 static void customSetPalette(W_ColorPanel * panel)
2754 W_Screen *scr = WMWidgetScreen(panel->win);
2755 RImage *scaledImg;
2756 Pixmap image;
2758 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2759 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2760 RConvertImage(scr->rcontext, scaledImg, &image);
2761 RReleaseImage(scaledImg);
2763 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2764 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2766 /* Check backimage exists. If it doesn't, allocate and fill it */
2767 if (!panel->selectionBackImg) {
2768 panel->selectionBackImg = XCreatePixmap(scr->display,
2769 panel->customPaletteContentView->window, 4, 4, scr->depth);
2772 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2773 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2774 XCopyArea(scr->display, panel->selectionImg,
2775 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2776 panel->palx - 2, panel->paly - 2);
2777 XFreePixmap(scr->display, image);
2779 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2780 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2782 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2785 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2787 W_Screen *scr = WMWidgetScreen(panel->win);
2788 unsigned long ofs;
2790 /* undraw selection */
2791 XCopyArea(scr->display, panel->selectionBackImg,
2792 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2793 panel->palx - 2, panel->paly - 2);
2795 panel->palx = x;
2796 panel->paly = y;
2798 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2800 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2801 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2802 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2803 panel->color.set = cpRGB;
2805 updateSwatch(panel, panel->color);
2806 panel->lastChanged = WMCustomPaletteModeColorPanel;
2808 /* Redraw color selector (and make a backup of the part it will cover) */
2809 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 */
2810 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2813 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2815 if (x < 2)
2816 x = 2;
2817 if (y < 2)
2818 y = 2;
2819 if (x >= customPaletteWidth)
2820 x = customPaletteWidth - 2;
2821 if (y >= customPaletteHeight)
2822 y = customPaletteHeight - 2;
2824 customPalettePositionSelection(panel, x, y);
2827 static void customPaletteHandleEvents(XEvent * event, void *data)
2829 W_ColorPanel *panel = (W_ColorPanel *) data;
2831 switch (event->type) {
2832 case Expose:
2833 if (event->xexpose.count != 0) /* TODO Improve. */
2834 break;
2835 customSetPalette(panel);
2836 break;
2840 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2842 W_ColorPanel *panel = (W_ColorPanel *) data;
2843 int x, y;
2845 switch (event->type) {
2846 case ButtonPress:
2847 x = event->xbutton.x;
2848 y = event->xbutton.y;
2850 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2851 panel->flags.dragging = 1;
2852 customPalettePositionSelection(panel, x, y);
2854 break;
2856 case ButtonRelease:
2857 panel->flags.dragging = 0;
2858 if (!panel->flags.continuous) {
2859 if (panel->action)
2860 (*panel->action) (panel, panel->clientData);
2862 break;
2864 case MotionNotify:
2865 x = event->xmotion.x;
2866 y = event->xmotion.y;
2868 if (panel->flags.dragging) {
2869 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2870 customPalettePositionSelection(panel, x, y);
2871 } else
2872 customPalettePositionSelectionOutBounds(panel, x, y);
2874 break;
2878 static void customPaletteMenuCallback(WMWidget * w, void *data)
2880 W_ColorPanel *panel = (W_ColorPanel *) data;
2881 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2883 /* Parameter not used, but tell the compiler that it is ok */
2884 (void) w;
2886 switch (item) {
2887 case CPmenuNewFromFile:
2888 customPaletteMenuNewFromFile(panel);
2889 break;
2890 case CPmenuRename:
2891 customPaletteMenuRename(panel);
2892 break;
2893 case CPmenuRemove:
2894 customPaletteMenuRemove(panel);
2895 break;
2896 case CPmenuCopy:
2897 break;
2898 case CPmenuNewFromClipboard:
2899 break;
2903 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2905 W_Screen *scr = WMWidgetScreen(panel->win);
2906 WMOpenPanel *browseP;
2907 char *filepath;
2908 char *filename = NULL;
2909 char *spath;
2910 char *tmp;
2911 int i;
2912 RImage *tmpImg = NULL;
2914 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
2915 spath = wexpandpath(wgethomedir());
2916 else
2917 spath = wexpandpath(panel->lastBrowseDir);
2919 browseP = WMGetOpenPanel(scr);
2920 WMSetFilePanelCanChooseDirectories(browseP, 0);
2921 WMSetFilePanelCanChooseFiles(browseP, 1);
2923 /* Get a filename */
2924 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
2925 _("Open Palette"), RSupportedFileFormats())) {
2926 filepath = WMGetFilePanelFileName(browseP);
2928 /* Get seperation position between path and filename */
2929 i = strrchr(filepath, '/') - filepath + 1;
2930 if (i > strlen(filepath))
2931 i = strlen(filepath);
2933 /* Store last browsed path */
2934 if (panel->lastBrowseDir)
2935 wfree(panel->lastBrowseDir);
2936 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
2937 strncpy(panel->lastBrowseDir, filepath, i);
2938 panel->lastBrowseDir[i] = '\0';
2940 /* Get filename from path */
2941 filename = wstrdup(filepath + i);
2943 /* Check for duplicate files, and rename it if there are any */
2944 tmp = wstrconcat(panel->configurationPath, filename);
2945 while (access(tmp, F_OK) == 0) {
2946 char *newName;
2948 wfree(tmp);
2950 newName = generateNewFilename(filename);
2951 wfree(filename);
2952 filename = newName;
2954 tmp = wstrconcat(panel->configurationPath, filename);
2956 wfree(tmp);
2958 /* Copy image to $(gnustepdir)/Library/Colors/ &
2959 * Add filename to history menu */
2960 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
2962 /* filepath is a "local" path now the file has been copied */
2963 wfree(filepath);
2964 filepath = wstrconcat(panel->configurationPath, filename);
2966 /* load the image & add menu entries */
2967 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
2968 if (tmpImg) {
2969 if (panel->customPaletteImg)
2970 RReleaseImage(panel->customPaletteImg);
2971 panel->customPaletteImg = tmpImg;
2973 customSetPalette(panel);
2974 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
2976 panel->currentPalette =
2977 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
2979 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
2980 panel->currentPalette);
2982 } else {
2983 tmp = wstrconcat(panel->configurationPath, filename);
2985 i = remove(tmp); /* Delete the file, it doesn't belong here */
2986 WMRunAlertPanel(scr, panel->win, _("File Error"),
2987 _("Invalid file format !"), _("OK"), NULL, NULL);
2988 if (i != 0) {
2989 werror(_("can't remove file %s"), tmp);
2990 WMRunAlertPanel(scr, panel->win, _("File Error"),
2991 _("Couldn't remove file from Configuration Directory !"),
2992 _("OK"), NULL, NULL);
2994 wfree(tmp);
2996 wfree(filepath);
2997 wfree(filename);
2999 WMFreeFilePanel(browseP);
3001 wfree(spath);
3004 static void customPaletteMenuRename(W_ColorPanel * panel)
3006 W_Screen *scr = WMWidgetScreen(panel->win);
3007 char *toName = NULL;
3008 char *fromName;
3009 char *toPath, *fromPath;
3010 int item;
3011 int index;
3013 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3014 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3016 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3017 fromName, _("OK"), _("Cancel"));
3019 if (toName) {
3021 /* As some people do certain stupid things... */
3022 if (strcmp(toName, fromName) == 0) {
3023 wfree(toName);
3024 return;
3027 /* For normal people */
3028 fromPath = wstrconcat(panel->configurationPath, fromName);
3029 toPath = wstrconcat(panel->configurationPath, toName);
3031 if (access(toPath, F_OK) == 0) {
3032 /* Careful, this palette exists already */
3033 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3034 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3035 NULL) == 1) {
3036 /* "No" = 0, "Yes" = 1 */
3037 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3039 remove(toPath);
3041 /* Remove from History list too */
3042 index = 1;
3043 while ((index < items)
3045 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3046 != 0))
3047 index++;
3049 if (index < items) {
3050 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3051 if (index < item)
3052 item--;
3055 } else {
3056 wfree(fromPath);
3057 wfree(toName);
3058 wfree(toPath);
3060 return;
3064 if (rename(fromPath, toPath) != 0)
3065 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3066 else {
3067 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3068 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3070 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3072 wfree(fromPath);
3073 wfree(toPath);
3074 wfree(toName);
3078 static void customPaletteMenuRemove(W_ColorPanel * panel)
3080 W_Screen *scr = WMWidgetScreen(panel->win);
3081 char *text;
3082 char *tmp;
3083 int choice;
3084 int item;
3086 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3088 tmp = wstrconcat(_("This will permanently remove the palette "),
3089 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3090 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3091 wfree(tmp);
3093 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3094 /* returns 0 (= "Yes") or 1 (="No") */
3095 wfree(text);
3097 if (choice == 0) {
3099 tmp = wstrconcat(panel->configurationPath,
3100 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3102 if (remove(tmp) == 0) {
3103 /* item-1 always exists */
3104 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3106 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3107 customSetPalette(panel);
3109 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3111 } else {
3112 werror(_("Couldn't remove palette %s"), tmp);
3115 wfree(tmp);
3119 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3121 W_ColorPanel *panel = (W_ColorPanel *) data;
3122 W_Screen *scr = WMWidgetScreen(panel->win);
3123 int item;
3124 char *filename;
3125 RImage *tmp = NULL;
3126 unsigned char perm_mask;
3128 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3129 if (item == panel->currentPalette)
3130 return;
3132 if (item == 0) {
3133 customRenderSpectrum(panel);
3135 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3136 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3137 } else {
3138 /* Load file from configpath */
3139 filename = wstrconcat(panel->configurationPath,
3140 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3142 /* If the file corresponding to the item does not exist,
3143 * remove it from the history list and select the next one.
3145 perm_mask = (access(filename, F_OK) == 0);
3146 if (!perm_mask) {
3147 /* File does not exist */
3148 wfree(filename);
3149 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3150 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3151 customPaletteHistoryCallback(w, data);
3152 return;
3155 /* Get the image */
3156 tmp = RLoadImage(scr->rcontext, filename, 0);
3157 if (tmp) {
3158 if (panel->customPaletteImg) {
3159 RReleaseImage(panel->customPaletteImg);
3160 panel->customPaletteImg = NULL;
3162 panel->customPaletteImg = tmp;
3165 /* If the image is not writable, don't allow removing/renaming */
3166 perm_mask = (access(filename, W_OK) == 0);
3167 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3168 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3170 wfree(filename);
3172 customSetPalette(panel);
3174 panel->currentPalette = item;
3177 /************************* ColorList Panel Functions **********************/
3179 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3181 WMScreen *scr = WMWidgetScreen(lPtr);
3182 Display *dpy = WMScreenDisplay(scr);
3183 WMView *view = W_VIEW(lPtr);
3184 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3185 W_ColorPanel *panel = WMGetHangedData(lPtr);
3186 int width, height, x, y;
3187 WMColor *fillColor;
3189 width = rect->size.width;
3190 height = rect->size.height;
3191 x = rect->pos.x;
3192 y = rect->pos.y;
3194 if (state & WLDSSelected)
3195 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3196 else
3197 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3199 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3201 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3202 WMReleaseColor(fillColor);
3204 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3207 static void colorListSelect(WMWidget * w, void *data)
3209 W_ColorPanel *panel = (W_ColorPanel *) data;
3210 CPColor cpColor;
3212 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3213 cpColor.set = cpRGB;
3215 panel->lastChanged = WMColorListModeColorPanel;
3216 updateSwatch(panel, cpColor);
3219 static void colorListColorMenuCallback(WMWidget * w, void *data)
3221 W_ColorPanel *panel = (W_ColorPanel *) data;
3222 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3224 /* Parameter not used, but tell the compiler that it is ok */
3225 (void) w;
3227 switch (item) {
3228 case CLmenuAdd:
3229 break;
3230 case CLmenuRename:
3231 break;
3232 case CLmenuRemove:
3233 break;
3237 static void colorListListMenuCallback(WMWidget * w, void *data)
3239 W_ColorPanel *panel = (W_ColorPanel *) data;
3240 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3242 /* Parameter not used, but tell the compiler that it is ok */
3243 (void) w;
3245 switch (item) {
3246 case CLmenuAdd:
3247 /* New Color List */
3248 colorListListMenuNew(panel);
3249 break;
3250 case CLmenuRename:
3251 break;
3252 case CLmenuRemove:
3253 break;
3257 static void colorListListMenuNew(W_ColorPanel * panel)
3262 /*************** Panel Initialisation Functions *****************/
3264 static void wheelInit(W_ColorPanel * panel)
3266 CPColor cpColor;
3268 if (panel->color.set != cpHSV)
3269 convertCPColor(&panel->color);
3271 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3273 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3274 (1 + (panel->color.hsv.saturation / 255.0) *
3275 cos(panel->color.hsv.hue * M_PI / 180.0)));
3276 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3277 (1 + (panel->color.hsv.saturation / 255.0) *
3278 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3280 wheelCalculateValues(panel, panel->color.hsv.value);
3282 cpColor = panel->color;
3283 cpColor.hsv.value = 255;
3284 cpColor.set = cpHSV;
3285 wheelUpdateBrightnessGradient(panel, cpColor);
3288 static void grayInit(W_ColorPanel * panel)
3290 int value;
3291 char tmp[4];
3293 if (panel->color.set != cpHSV)
3294 convertCPColor(&panel->color);
3296 value = rint(panel->color.hsv.value / 2.55);
3297 WMSetSliderValue(panel->grayBrightnessS, value);
3299 sprintf(tmp, "%d", value);
3300 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3303 static void rgbInit(W_ColorPanel * panel)
3305 char tmp[4];
3307 if (panel->color.set != cpRGB)
3308 convertCPColor(&panel->color);
3310 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3311 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3312 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3314 sprintf(tmp, "%d", panel->color.rgb.red);
3315 WMSetTextFieldText(panel->rgbRedT, tmp);
3316 sprintf(tmp, "%d", panel->color.rgb.green);
3317 WMSetTextFieldText(panel->rgbGreenT, tmp);
3318 sprintf(tmp, "%d", panel->color.rgb.blue);
3319 WMSetTextFieldText(panel->rgbBlueT, tmp);
3322 static void cmykInit(W_ColorPanel * panel)
3324 int value[3];
3325 char tmp[4];
3327 if (panel->color.set != cpRGB)
3328 convertCPColor(&panel->color);
3330 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3331 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3332 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3334 WMSetSliderValue(panel->cmykCyanS, value[0]);
3335 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3336 WMSetSliderValue(panel->cmykYellowS, value[2]);
3337 WMSetSliderValue(panel->cmykBlackS, 0);
3339 sprintf(tmp, "%d", value[0]);
3340 WMSetTextFieldText(panel->cmykCyanT, tmp);
3341 sprintf(tmp, "%d", value[1]);
3342 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3343 sprintf(tmp, "%d", value[2]);
3344 WMSetTextFieldText(panel->cmykYellowT, tmp);
3345 WMSetTextFieldText(panel->cmykBlackT, "0");
3348 static void hsbInit(W_ColorPanel * panel)
3350 int value[3];
3351 char tmp[4];
3353 if (panel->color.set != cpHSV)
3354 convertCPColor(&panel->color);
3356 value[0] = panel->color.hsv.hue;
3357 value[1] = rint(panel->color.hsv.saturation / 2.55);
3358 value[2] = rint(panel->color.hsv.value / 2.55);
3360 WMSetSliderValue(panel->hsbHueS, value[0]);
3361 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3362 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3364 sprintf(tmp, "%d", value[0]);
3365 WMSetTextFieldText(panel->hsbHueT, tmp);
3366 sprintf(tmp, "%d", value[1]);
3367 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3368 sprintf(tmp, "%d", value[2]);
3369 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3371 hsbUpdateBrightnessGradient(panel);
3372 hsbUpdateSaturationGradient(panel);
3373 hsbUpdateHueGradient(panel);
3376 /************************** Common utility functions ************************/
3378 static char *generateNewFilename(const char *curName)
3380 int n;
3381 char c;
3382 int baseLen;
3383 const char *ptr;
3384 char *newName;
3386 assert(curName);
3388 ptr = curName;
3390 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3391 return wstrconcat(curName, " {1}");
3393 baseLen = ptr - curName - 1;
3395 newName = wmalloc(baseLen + 16);
3396 strncpy(newName, curName, baseLen);
3398 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3400 return newName;
3403 static void convertCPColor(CPColor * color)
3405 unsigned short old_hue = 0;
3407 switch (color->set) {
3408 case cpNone:
3409 wwarning(_("Color Panel: Color unspecified"));
3410 return;
3411 case cpRGB:
3412 old_hue = color->hsv.hue;
3413 RRGBtoHSV(&(color->rgb), &(color->hsv));
3415 /* In black the hue is undefined, and may change by conversion
3416 * Same for white. */
3417 if (((color->rgb.red == 0) &&
3418 (color->rgb.green == 0) &&
3419 (color->rgb.blue == 0)) ||
3420 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3422 color->hsv.hue = old_hue;
3423 break;
3424 case cpHSV:
3425 RHSVtoRGB(&(color->hsv), &(color->rgb));
3426 break;
3430 #define ABS_SHIFT(val, shift) \
3431 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3433 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3435 RColor color;
3436 XColor *xcolor = NULL;
3438 xcolor = wmalloc(sizeof(XColor));
3439 xcolor->pixel = value;
3440 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3442 color.red = xcolor->red >> 8;
3443 color.green = xcolor->green >> 8;
3444 color.blue = xcolor->blue >> 8;
3445 color.alpha = 0;
3447 wfree(xcolor);
3449 return color;
3452 static unsigned char getShift(unsigned char value)
3454 unsigned char i = -1;
3456 if (value == 0)
3457 return 0;
3459 while (value) {
3460 value >>= 1;
3461 i++;
3464 return i;
3467 #ifdef SHAPE_WAS_DEFINED
3468 #undef SHAPE_WAS_DEFINED
3469 #define SHAPE
3470 #endif