Fix possible missing NUL at end of string
[wmaker-crm.git] / WINGs / wcolorpanel.c
blobc86dfdd796a30479d60728f2b30ebb0153318b63
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 int fetchFile(char *toPath, char *imageSrcFile, char *imageDestFileName);
279 char *generateNewFilename(char *curName);
280 void convertCPColor(CPColor * color);
281 RColor ulongToRColor(WMScreen * scr, unsigned long value);
282 unsigned char getShift(unsigned char value);
284 static void modeButtonCallback(WMWidget * w, void *data);
285 static int getPickerPart(W_ColorPanel * panel, int x, int y);
286 static void readConfiguration(W_ColorPanel * panel);
287 static void readXColors(W_ColorPanel * panel);
289 static void closeWindowCallback(WMWidget * w, void *data);
291 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
292 static WMPoint magnifyInitialize(W_ColorPanel * panel);
293 static void magnifyPutCursor(WMWidget * w, void *data);
294 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
295 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
296 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
298 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
299 static void wheelDestroyMatrix(wheelMatrix * matrix);
300 static void wheelInitMatrix(W_ColorPanel * panel);
301 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
302 static void wheelRender(W_ColorPanel * panel);
303 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
304 static void wheelPaint(W_ColorPanel * panel);
306 static void wheelHandleEvents(XEvent * event, void *data);
307 static void wheelHandleActionEvents(XEvent * event, void *data);
308 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
309 static void wheelUpdateSelection(W_ColorPanel * panel);
310 static void wheelUndrawSelection(W_ColorPanel * panel);
312 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
313 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
314 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
315 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
317 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
318 static void grayPresetButtonCallback(WMWidget * w, void *data);
319 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
321 static void rgbSliderCallback(WMWidget * w, void *data);
322 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
324 static void cmykSliderCallback(WMWidget * w, void *data);
325 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
327 static void hsbSliderCallback(WMWidget * w, void *data);
328 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
329 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
330 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
331 static void hsbUpdateHueGradient(W_ColorPanel * panel);
333 static void customRenderSpectrum(W_ColorPanel * panel);
334 static void customSetPalette(W_ColorPanel * panel);
335 static void customPaletteHandleEvents(XEvent * event, void *data);
336 static void customPaletteHandleActionEvents(XEvent * event, void *data);
337 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
338 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
339 static void customPaletteMenuCallback(WMWidget * w, void *data);
340 static void customPaletteHistoryCallback(WMWidget * w, void *data);
342 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
343 static void customPaletteMenuRename(W_ColorPanel * panel);
344 static void customPaletteMenuRemove(W_ColorPanel * panel);
346 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
347 static void colorListSelect(WMWidget * w, void *data);
348 static void colorListColorMenuCallback(WMWidget * w, void *data);
349 static void colorListListMenuCallback(WMWidget * w, void *data);
350 static void colorListListMenuNew(W_ColorPanel * panel);
352 static void wheelInit(W_ColorPanel * panel);
353 static void grayInit(W_ColorPanel * panel);
354 static void rgbInit(W_ColorPanel * panel);
355 static void cmykInit(W_ColorPanel * panel);
356 static void hsbInit(W_ColorPanel * panel);
358 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
360 panel->action = action;
361 panel->clientData = data;
364 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, char *name)
366 WMColorPanel *panel;
367 RImage *image;
368 WMPixmap *pixmap;
369 RColor from;
370 RColor to;
371 WMColor *textcolor, *graybuttoncolor;
372 int i;
373 GC bgc = WMColorGC(scrPtr->black);
374 GC wgc = WMColorGC(scrPtr->white);
376 panel = wmalloc(sizeof(WMColorPanel));
377 panel->color.rgb.red = 0;
378 panel->color.rgb.green = 0;
379 panel->color.rgb.blue = 0;
380 panel->color.hsv.hue = 0;
381 panel->color.hsv.saturation = 0;
382 panel->color.hsv.value = 0;
383 panel->color.set = cpNone; /* Color has not been set yet */
385 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
386 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
388 panel->win = WMCreateWindowWithStyle(scrPtr, name,
389 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
390 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
391 WMSetWindowTitle(panel->win, _("Colors"));
392 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
394 /* Set Default ColorPanel Mode(s) */
395 panel->mode = WMWheelModeColorPanel;
396 panel->lastChanged = 0;
397 panel->slidersmode = WMRGBModeColorPanel;
398 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
400 /* Some General Purpose Widgets */
401 panel->colorWell = WMCreateColorWell(panel->win);
402 WMResizeWidget(panel->colorWell, 134, 36);
403 WSetColorWellBordered(panel->colorWell, False);
404 WMMoveWidget(panel->colorWell, 56, 4);
406 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
407 WMResizeWidget(panel->magnifyBtn, 46, 36);
408 WMMoveWidget(panel->magnifyBtn, 6, 4);
409 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
410 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
411 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
413 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
414 WMResizeWidget(panel->wheelBtn, 46, 32);
415 WMMoveWidget(panel->wheelBtn, 6, 44);
416 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
417 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
418 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
420 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
421 WMResizeWidget(panel->slidersBtn, 46, 32);
422 WMMoveWidget(panel->slidersBtn, 52, 44);
423 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
424 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
425 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
427 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
428 WMResizeWidget(panel->customPaletteBtn, 46, 32);
429 WMMoveWidget(panel->customPaletteBtn, 98, 44);
430 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
431 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
432 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
434 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
435 WMResizeWidget(panel->colorListBtn, 46, 32);
436 WMMoveWidget(panel->colorListBtn, 144, 44);
437 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
438 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
439 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
441 /* Let's Group some of them together */
442 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
443 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
444 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
446 /* Widgets for the ColorWheel Panel */
447 panel->wheelFrm = WMCreateFrame(panel->win);
448 WMSetFrameRelief(panel->wheelFrm, WRFlat);
449 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
450 WMMoveWidget(panel->wheelFrm, 5, 80);
452 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
453 /* XXX Can we create a view ? */
454 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
455 W_MoveView(panel->wheelView, 0, 0);
457 /* Create an event handler to handle expose/click events in ColorWheel */
458 WMCreateEventHandler(panel->wheelView,
459 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
460 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
462 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
464 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
465 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
466 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
467 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
468 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
469 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
470 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
472 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
473 wheelInitMatrix(panel);
475 /* Widgets for the Slider Panels */
476 panel->slidersFrm = WMCreateFrame(panel->win);
477 WMSetFrameRelief(panel->slidersFrm, WRFlat);
478 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
479 WMMoveWidget(panel->slidersFrm, 4, 80);
481 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
482 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
483 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
484 WMMoveWidget(panel->seperatorFrm, 0, 1);
486 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
487 WMResizeWidget(panel->grayBtn, 46, 24);
488 WMMoveWidget(panel->grayBtn, 1, 8);
489 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
490 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
491 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
493 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
494 WMResizeWidget(panel->rgbBtn, 46, 24);
495 WMMoveWidget(panel->rgbBtn, 47, 8);
496 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
497 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
498 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
500 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
501 WMResizeWidget(panel->cmykBtn, 46, 24);
502 WMMoveWidget(panel->cmykBtn, 93, 8);
503 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
504 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
505 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
507 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
508 WMResizeWidget(panel->hsbBtn, 46, 24);
509 WMMoveWidget(panel->hsbBtn, 139, 8);
510 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
511 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
512 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
514 /* Let's Group the Slider Panel Buttons Together */
515 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
516 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
517 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
519 textcolor = WMDarkGrayColor(scrPtr);
521 /* Widgets for GrayScale Panel */
522 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
523 WMSetFrameRelief(panel->grayFrm, WRFlat);
524 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
525 WMMoveWidget(panel->grayFrm, 0, 34);
527 panel->grayMinL = WMCreateLabel(panel->grayFrm);
528 WMResizeWidget(panel->grayMinL, 20, 10);
529 WMMoveWidget(panel->grayMinL, 2, 2);
530 WMSetLabelText(panel->grayMinL, "0");
531 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
532 WMSetLabelTextColor(panel->grayMinL, textcolor);
533 WMSetLabelFont(panel->grayMinL, panel->font8);
535 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
536 WMResizeWidget(panel->grayMaxL, 40, 10);
537 WMMoveWidget(panel->grayMaxL, 104, 2);
538 WMSetLabelText(panel->grayMaxL, "100");
539 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
540 WMSetLabelTextColor(panel->grayMaxL, textcolor);
541 WMSetLabelFont(panel->grayMaxL, panel->font8);
543 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
544 WMResizeWidget(panel->grayBrightnessS, 141, 16);
545 WMMoveWidget(panel->grayBrightnessS, 2, 14);
546 WMSetSliderMinValue(panel->grayBrightnessS, 0);
547 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
548 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
549 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
551 from.red = 0;
552 from.green = 0;
553 from.blue = 0;
555 to.red = 255;
556 to.green = 255;
557 to.blue = 255;
559 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
560 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
561 RReleaseImage(image);
563 if (pixmap)
564 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
565 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
566 False, _("Brightness"), strlen(_("Brightness")));
567 else
568 wwarning(_("Color Panel: Could not allocate memory"));
570 WMSetSliderImage(panel->grayBrightnessS, pixmap);
571 WMReleasePixmap(pixmap);
573 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
574 WMResizeWidget(panel->grayBrightnessT, 40, 18);
575 WMMoveWidget(panel->grayBrightnessT, 146, 13);
576 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
577 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
578 WMTextDidEndEditingNotification, panel->grayBrightnessT);
580 for (i = 0; i < 7; i++) {
581 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
583 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
584 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
585 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
586 WMReleaseColor(graybuttoncolor);
588 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
589 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
590 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
591 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
592 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
593 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
594 WMReleasePixmap(pixmap);
598 /* End of GrayScale Panel */
600 /* Widgets for RGB Panel */
601 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
602 WMSetFrameRelief(panel->rgbFrm, WRFlat);
603 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
604 WMMoveWidget(panel->rgbFrm, 0, 34);
606 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
607 WMResizeWidget(panel->rgbMinL, 20, 10);
608 WMMoveWidget(panel->rgbMinL, 2, 2);
609 WMSetLabelText(panel->rgbMinL, "0");
610 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
611 WMSetLabelTextColor(panel->rgbMinL, textcolor);
612 WMSetLabelFont(panel->rgbMinL, panel->font8);
614 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
615 WMResizeWidget(panel->rgbMaxL, 40, 10);
616 WMMoveWidget(panel->rgbMaxL, 104, 2);
617 WMSetLabelText(panel->rgbMaxL, "255");
618 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
619 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
620 WMSetLabelFont(panel->rgbMaxL, panel->font8);
622 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
623 WMResizeWidget(panel->rgbRedS, 141, 16);
624 WMMoveWidget(panel->rgbRedS, 2, 14);
625 WMSetSliderMinValue(panel->rgbRedS, 0);
626 WMSetSliderMaxValue(panel->rgbRedS, 255);
627 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
628 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
630 to.red = 255;
631 to.green = 0;
632 to.blue = 0;
634 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
635 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
636 RReleaseImage(image);
638 if (pixmap)
639 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
640 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
641 else
642 wwarning(_("Color Panel: Could not allocate memory"));
644 WMSetSliderImage(panel->rgbRedS, pixmap);
645 WMReleasePixmap(pixmap);
647 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
648 WMResizeWidget(panel->rgbRedT, 40, 18);
649 WMMoveWidget(panel->rgbRedT, 146, 13);
650 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
651 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
653 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
654 WMResizeWidget(panel->rgbGreenS, 141, 16);
655 WMMoveWidget(panel->rgbGreenS, 2, 36);
656 WMSetSliderMinValue(panel->rgbGreenS, 0);
657 WMSetSliderMaxValue(panel->rgbGreenS, 255);
658 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
659 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
661 to.red = 0;
662 to.green = 255;
663 to.blue = 0;
665 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
666 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
667 RReleaseImage(image);
669 if (pixmap)
670 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
671 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
672 else
673 wwarning(_("Color Panel: Could not allocate memory"));
675 WMSetSliderImage(panel->rgbGreenS, pixmap);
676 WMReleasePixmap(pixmap);
678 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
679 WMResizeWidget(panel->rgbGreenT, 40, 18);
680 WMMoveWidget(panel->rgbGreenT, 146, 35);
681 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
682 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
684 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
685 WMResizeWidget(panel->rgbBlueS, 141, 16);
686 WMMoveWidget(panel->rgbBlueS, 2, 58);
687 WMSetSliderMinValue(panel->rgbBlueS, 0);
688 WMSetSliderMaxValue(panel->rgbBlueS, 255);
689 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
690 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
692 to.red = 0;
693 to.green = 0;
694 to.blue = 255;
696 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
697 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
698 RReleaseImage(image);
700 if (pixmap)
701 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
702 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
703 else
704 wwarning(_("Color Panel: Could not allocate memory"));
706 WMSetSliderImage(panel->rgbBlueS, pixmap);
707 WMReleasePixmap(pixmap);
709 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
710 WMResizeWidget(panel->rgbBlueT, 40, 18);
711 WMMoveWidget(panel->rgbBlueT, 146, 57);
712 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
713 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
714 /* End of RGB Panel */
716 /* Widgets for CMYK Panel */
717 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
718 WMSetFrameRelief(panel->cmykFrm, WRFlat);
719 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
720 WMMoveWidget(panel->cmykFrm, 0, 34);
722 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
723 WMResizeWidget(panel->cmykMinL, 20, 10);
724 WMMoveWidget(panel->cmykMinL, 2, 2);
725 WMSetLabelText(panel->cmykMinL, "0");
726 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
727 WMSetLabelTextColor(panel->cmykMinL, textcolor);
728 WMSetLabelFont(panel->cmykMinL, panel->font8);
730 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
731 WMResizeWidget(panel->cmykMaxL, 40, 10);
732 WMMoveWidget(panel->cmykMaxL, 104, 2);
733 WMSetLabelText(panel->cmykMaxL, "100");
734 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
735 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
736 WMSetLabelFont(panel->cmykMaxL, panel->font8);
738 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
739 WMResizeWidget(panel->cmykCyanS, 141, 16);
740 WMMoveWidget(panel->cmykCyanS, 2, 14);
741 WMSetSliderMinValue(panel->cmykCyanS, 0);
742 WMSetSliderMaxValue(panel->cmykCyanS, 100);
743 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
744 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
746 from.red = 255;
747 from.green = 255;
748 from.blue = 255;
750 to.red = 0;
751 to.green = 255;
752 to.blue = 255;
754 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
755 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
756 RReleaseImage(image);
758 if (pixmap)
759 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
760 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
761 else
762 wwarning(_("Color Panel: Could not allocate memory"));
764 WMSetSliderImage(panel->cmykCyanS, pixmap);
765 WMReleasePixmap(pixmap);
767 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
768 WMResizeWidget(panel->cmykCyanT, 40, 18);
769 WMMoveWidget(panel->cmykCyanT, 146, 13);
770 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
771 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
773 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
774 WMResizeWidget(panel->cmykMagentaS, 141, 16);
775 WMMoveWidget(panel->cmykMagentaS, 2, 36);
776 WMSetSliderMinValue(panel->cmykMagentaS, 0);
777 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
778 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
779 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
781 to.red = 255;
782 to.green = 0;
783 to.blue = 255;
785 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
786 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
787 RReleaseImage(image);
789 if (pixmap)
790 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
791 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
792 else
793 wwarning(_("Color Panel: Could not allocate memory"));
795 WMSetSliderImage(panel->cmykMagentaS, pixmap);
796 WMReleasePixmap(pixmap);
798 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
799 WMResizeWidget(panel->cmykMagentaT, 40, 18);
800 WMMoveWidget(panel->cmykMagentaT, 146, 35);
801 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
802 WMAddNotificationObserver(cmykTextFieldCallback, panel,
803 WMTextDidEndEditingNotification, panel->cmykMagentaT);
805 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
806 WMResizeWidget(panel->cmykYellowS, 141, 16);
807 WMMoveWidget(panel->cmykYellowS, 2, 58);
808 WMSetSliderMinValue(panel->cmykYellowS, 0);
809 WMSetSliderMaxValue(panel->cmykYellowS, 100);
810 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
811 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
813 to.red = 255;
814 to.green = 255;
815 to.blue = 0;
817 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
818 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
819 RReleaseImage(image);
821 if (pixmap)
822 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
823 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
824 else
825 wwarning(_("Color Panel: Could not allocate memory"));
827 WMSetSliderImage(panel->cmykYellowS, pixmap);
828 WMReleasePixmap(pixmap);
830 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
831 WMResizeWidget(panel->cmykYellowT, 40, 18);
832 WMMoveWidget(panel->cmykYellowT, 146, 57);
833 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
834 WMAddNotificationObserver(cmykTextFieldCallback, panel,
835 WMTextDidEndEditingNotification, panel->cmykYellowT);
837 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
838 WMResizeWidget(panel->cmykBlackS, 141, 16);
839 WMMoveWidget(panel->cmykBlackS, 2, 80);
840 WMSetSliderMinValue(panel->cmykBlackS, 0);
841 WMSetSliderMaxValue(panel->cmykBlackS, 100);
842 WMSetSliderValue(panel->cmykBlackS, 0);
843 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
844 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
846 to.red = 0;
847 to.green = 0;
848 to.blue = 0;
850 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
851 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
852 RReleaseImage(image);
854 if (pixmap)
855 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
856 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
857 else
858 wwarning(_("Color Panel: Could not allocate memory"));
860 WMSetSliderImage(panel->cmykBlackS, pixmap);
861 WMReleasePixmap(pixmap);
863 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
864 WMResizeWidget(panel->cmykBlackT, 40, 18);
865 WMMoveWidget(panel->cmykBlackT, 146, 79);
866 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
867 WMAddNotificationObserver(cmykTextFieldCallback, panel,
868 WMTextDidEndEditingNotification, panel->cmykBlackT);
869 /* End of CMYK Panel */
871 /* Widgets for HSB Panel */
872 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
873 WMSetFrameRelief(panel->hsbFrm, WRFlat);
874 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
875 WMMoveWidget(panel->hsbFrm, 0, 34);
877 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
878 WMResizeWidget(panel->hsbHueS, 141, 16);
879 WMMoveWidget(panel->hsbHueS, 2, 14);
880 WMSetSliderMinValue(panel->hsbHueS, 0);
881 WMSetSliderMaxValue(panel->hsbHueS, 359);
882 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
883 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
885 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
886 WMResizeWidget(panel->hsbHueT, 40, 18);
887 WMMoveWidget(panel->hsbHueT, 146, 13);
888 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
889 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
891 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
892 WMResizeWidget(panel->hsbSaturationS, 141, 16);
893 WMMoveWidget(panel->hsbSaturationS, 2, 36);
894 WMSetSliderMinValue(panel->hsbSaturationS, 0);
895 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
896 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
897 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
899 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
900 WMResizeWidget(panel->hsbSaturationT, 40, 18);
901 WMMoveWidget(panel->hsbSaturationT, 146, 35);
902 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
903 WMAddNotificationObserver(hsbTextFieldCallback, panel,
904 WMTextDidEndEditingNotification, panel->hsbSaturationT);
906 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
907 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
908 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
909 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
910 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
911 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
912 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
914 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
915 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
916 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
917 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
918 WMAddNotificationObserver(hsbTextFieldCallback, panel,
919 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
920 /* End of HSB Panel */
922 WMReleaseColor(textcolor);
924 /* Widgets for the CustomPalette Panel */
925 panel->customPaletteFrm = WMCreateFrame(panel->win);
926 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
927 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
928 WMMoveWidget(panel->customPaletteFrm, 5, 80);
930 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
931 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
932 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
933 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
934 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
935 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
936 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
938 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
939 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
940 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
941 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
943 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
944 /* XXX Test if we can create a view */
945 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
946 W_MoveView(panel->customPaletteContentView, 2, 2);
948 /* Create event handler to handle expose/click events in CustomPalette */
949 WMCreateEventHandler(panel->customPaletteContentView,
950 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
951 ButtonMotionMask, customPaletteHandleActionEvents, panel);
953 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
955 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
956 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
957 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
958 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
959 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
960 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
962 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
963 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
964 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
965 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
966 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
968 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
969 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
970 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
971 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
973 customRenderSpectrum(panel);
974 panel->currentPalette = 0;
975 panel->palx = customPaletteWidth / 2;
976 panel->paly = customPaletteHeight / 2;
978 /* Widgets for the ColorList Panel */
979 panel->colorListFrm = WMCreateFrame(panel->win);
980 WMSetFrameRelief(panel->colorListFrm, WRFlat);
981 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
982 WMMoveWidget(panel->colorListFrm, 5, 80);
984 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
985 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
986 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
987 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
988 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
989 * colorListHistoryCallback, panel); */
990 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
991 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
993 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
994 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
995 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
996 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
997 WMMoveWidget(panel->colorListContentLst, 0, 23);
998 WMHangData(panel->colorListContentLst, panel);
1000 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1001 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1002 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1003 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1004 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1005 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1007 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1008 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1009 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1011 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1012 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1013 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1015 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1016 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1017 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1018 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1019 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1020 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1022 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1023 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1024 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1026 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1027 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1028 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1030 WMRealizeWidget(panel->win);
1031 WMMapSubwidgets(panel->win);
1033 WMMapSubwidgets(panel->wheelFrm);
1034 WMMapSubwidgets(panel->slidersFrm);
1035 WMMapSubwidgets(panel->grayFrm);
1036 WMMapSubwidgets(panel->rgbFrm);
1037 WMMapSubwidgets(panel->cmykFrm);
1038 WMMapSubwidgets(panel->hsbFrm);
1039 WMMapSubwidgets(panel->customPaletteFrm);
1040 WMMapSubwidgets(panel->customPaletteContentFrm);
1041 WMMapSubwidgets(panel->colorListFrm);
1043 /* Pixmap to indicate selection positions
1044 * wheelframe MUST be mapped.
1046 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1047 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1048 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1050 readConfiguration(panel);
1051 readXColors(panel);
1053 return panel;
1056 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1058 WMColorPanel *panel;
1060 if (scrPtr->sharedColorPanel)
1061 return scrPtr->sharedColorPanel;
1063 panel = makeColorPanel(scrPtr, "colorPanel");
1065 scrPtr->sharedColorPanel = panel;
1067 return panel;
1070 void WMFreeColorPanel(WMColorPanel * panel)
1072 W_Screen *scr = WMWidgetScreen(panel->win);
1074 if (panel == scr->sharedColorPanel) {
1075 scr->sharedColorPanel = NULL;
1078 if (!panel)
1079 return;
1081 WMRemoveNotificationObserver(panel);
1082 WMUnmapWidget(panel->win);
1084 /* fonts */
1085 WMReleaseFont(panel->font8);
1086 WMReleaseFont(panel->font12);
1088 /* pixmaps */
1089 wheelDestroyMatrix(panel->wheelMtrx);
1090 if (panel->wheelImg)
1091 XFreePixmap(scr->display, panel->wheelImg);
1092 if (panel->selectionImg)
1093 XFreePixmap(scr->display, panel->selectionImg);
1094 if (panel->selectionBackImg)
1095 XFreePixmap(scr->display, panel->selectionBackImg);
1096 RReleaseImage(panel->customPaletteImg);
1098 /* structs */
1099 if (panel->lastBrowseDir)
1100 wfree(panel->lastBrowseDir);
1101 if (panel->configurationPath)
1102 wfree(panel->configurationPath);
1104 WMDestroyWidget(panel->win);
1106 wfree(panel);
1109 void WMCloseColorPanel(WMColorPanel * panel)
1111 WMFreeColorPanel(panel);
1114 void WMShowColorPanel(WMColorPanel * panel)
1116 WMScreen *scr = WMWidgetScreen(panel->win);
1117 WMColor *white = WMWhiteColor(scr);
1119 if (panel->color.set == cpNone)
1120 WMSetColorPanelColor(panel, white);
1121 WMReleaseColor(white);
1123 if (panel->mode != WMWheelModeColorPanel)
1124 WMPerformButtonClick(panel->wheelBtn);
1126 WMMapWidget(panel->win);
1129 static void closeWindowCallback(WMWidget * w, void *data)
1131 W_ColorPanel *panel = (W_ColorPanel *) data;
1133 WMCloseColorPanel(panel);
1136 static void readConfiguration(W_ColorPanel * panel)
1138 /* XXX Doesn't take care of "invalid" files */
1140 DIR *dPtr;
1141 struct dirent *dp;
1142 struct stat stat_buf;
1143 int item;
1145 if (stat(panel->configurationPath, &stat_buf) != 0) {
1146 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1147 werror(_("Color Panel: Could not create directory %s needed"
1148 " to store configurations"), panel->configurationPath);
1149 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1150 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1151 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1152 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1153 _("File Error"),
1154 _("Could not create ColorPanel configuration directory"),
1155 _("OK"), NULL, NULL);
1157 return;
1160 if (!(dPtr = opendir(panel->configurationPath))) {
1161 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1162 return;
1165 while ((dp = readdir(dPtr)) != NULL) {
1166 unsigned int perm_mask;
1167 char *path = wstrconcat(panel->configurationPath,
1168 dp->d_name);
1170 if (dp->d_name[0] != '.') {
1171 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1172 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1174 perm_mask = (access(path, R_OK) == 0);
1175 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1177 wfree(path);
1179 closedir(dPtr);
1182 static void readXColors(W_ColorPanel * panel)
1184 WMListItem *item;
1185 RGBColor *entry;
1187 for (entry = rgbColors; entry->name != NULL; entry++) {
1188 item = WMAddListItem(panel->colorListContentLst, entry->name);
1189 item->clientData = (void *)&(entry->color);
1193 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1195 W_Screen *scr = WMWidgetScreen(panel->win);
1197 if (mode != WMWheelModeColorPanel) {
1198 WMUnmapWidget(panel->wheelFrm);
1199 if (panel->selectionBackImg) {
1200 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1201 panel->selectionBackImg = None;
1204 if (mode != WMGrayModeColorPanel)
1205 WMUnmapWidget(panel->grayFrm);
1206 if (mode != WMRGBModeColorPanel)
1207 WMUnmapWidget(panel->rgbFrm);
1208 if (mode != WMCMYKModeColorPanel)
1209 WMUnmapWidget(panel->cmykFrm);
1210 if (mode != WMHSBModeColorPanel)
1211 WMUnmapWidget(panel->hsbFrm);
1212 if (mode != WMCustomPaletteModeColorPanel) {
1213 WMUnmapWidget(panel->customPaletteFrm);
1214 if (panel->selectionBackImg) {
1215 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1216 panel->selectionBackImg = None;
1219 if (mode != WMColorListModeColorPanel)
1220 WMUnmapWidget(panel->colorListFrm);
1221 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1222 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1223 WMUnmapWidget(panel->slidersFrm);
1224 else
1225 panel->slidersmode = mode;
1227 if (mode == WMWheelModeColorPanel) {
1228 WMMapWidget(panel->wheelFrm);
1229 WMSetButtonSelected(panel->wheelBtn, True);
1230 if (panel->lastChanged != WMWheelModeColorPanel)
1231 wheelInit(panel);
1232 wheelRender(panel);
1233 wheelPaint(panel);
1234 } else if (mode == WMGrayModeColorPanel) {
1235 WMMapWidget(panel->slidersFrm);
1236 WMSetButtonSelected(panel->slidersBtn, True);
1237 WMMapWidget(panel->grayFrm);
1238 WMSetButtonSelected(panel->grayBtn, True);
1239 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1240 if (panel->lastChanged != WMGrayModeColorPanel)
1241 grayInit(panel);
1242 } else if (mode == WMRGBModeColorPanel) {
1243 WMMapWidget(panel->slidersFrm);
1244 WMSetButtonSelected(panel->slidersBtn, True);
1245 WMMapWidget(panel->rgbFrm);
1246 WMSetButtonSelected(panel->rgbBtn, True);
1247 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1248 if (panel->lastChanged != WMRGBModeColorPanel)
1249 rgbInit(panel);
1250 } else if (mode == WMCMYKModeColorPanel) {
1251 WMMapWidget(panel->slidersFrm);
1252 WMSetButtonSelected(panel->slidersBtn, True);
1253 WMMapWidget(panel->cmykFrm);
1254 WMSetButtonSelected(panel->cmykBtn, True);
1255 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1256 if (panel->lastChanged != WMCMYKModeColorPanel)
1257 cmykInit(panel);
1258 } else if (mode == WMHSBModeColorPanel) {
1259 WMMapWidget(panel->slidersFrm);
1260 WMSetButtonSelected(panel->slidersBtn, True);
1261 WMMapWidget(panel->hsbFrm);
1262 WMSetButtonSelected(panel->hsbBtn, True);
1263 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1264 if (panel->lastChanged != WMHSBModeColorPanel)
1265 hsbInit(panel);
1266 } else if (mode == WMCustomPaletteModeColorPanel) {
1267 WMMapWidget(panel->customPaletteFrm);
1268 WMSetButtonSelected(panel->customPaletteBtn, True);
1269 customSetPalette(panel);
1270 } else if (mode == WMColorListModeColorPanel) {
1271 WMMapWidget(panel->colorListFrm);
1272 WMSetButtonSelected(panel->colorListBtn, True);
1275 panel->mode = mode;
1278 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1280 return WMGetColorWellColor(panel->colorWell);
1283 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1285 WMSetColorWellColor(panel->colorWell, color);
1287 panel->color.rgb.red = color->color.red >> 8;
1288 panel->color.rgb.green = color->color.green >> 8;
1289 panel->color.rgb.blue = color->color.blue >> 8;
1290 panel->color.set = cpRGB;
1292 if (panel->mode == panel->lastChanged)
1293 panel->lastChanged = 0;
1295 WMSetColorPanelPickerMode(panel, panel->mode);
1298 static void updateSwatch(WMColorPanel * panel, CPColor color)
1300 WMScreen *scr = WMWidgetScreen(panel->win);
1301 WMColor *wellcolor;
1303 if (color.set != cpRGB)
1304 convertCPColor(&color);
1306 panel->color = color;
1308 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1310 WMSetColorWellColor(panel->colorWell, wellcolor);
1311 WMReleaseColor(wellcolor);
1313 if (!panel->flags.dragging || panel->flags.continuous) {
1314 if (panel->action)
1315 (*panel->action) (panel, panel->clientData);
1317 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1321 static void modeButtonCallback(WMWidget * w, void *data)
1323 W_ColorPanel *panel = (W_ColorPanel *) (data);
1325 if (w == panel->wheelBtn)
1326 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1327 else if (w == panel->slidersBtn)
1328 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1329 else if (w == panel->customPaletteBtn)
1330 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1331 else if (w == panel->colorListBtn)
1332 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1333 else if (w == panel->grayBtn)
1334 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1335 else if (w == panel->rgbBtn)
1336 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1337 else if (w == panel->cmykBtn)
1338 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1339 else if (w == panel->hsbBtn)
1340 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1343 /****************** Magnifying Cursor Functions *******************/
1345 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1347 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1348 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1349 displayHeight = DisplayHeight(scr->display, scr->screen);
1351 if (!(image && image->data)) {
1352 /* The image in panel->magnifyGlass->image does not exist yet.
1353 * Grab one from the screen (not beyond) and use it from now on.
1355 if (!(image = XGetImage(scr->display, scr->rootWin,
1356 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1357 wwarning(_("Color Panel: X failed request"));
1359 return image;
1362 /* Coordinate correction for back pixmap
1363 * if magnifying glass is at screen-borders
1366 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1367 * Hatched area is beyond screen border.
1369 * |<-Cursor_x_hot->|
1370 * ________________|_____
1371 * |/ / / / / / /| | |
1372 * | / / / / / / |(x,y) |
1373 * |/_/_/_/_/_/_/|________|
1374 * |<----x0----->|<--w0-->|
1378 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1379 * screen borders
1380 * Hatched area is beyond screen border
1382 * |<-Cursor_x_hot->|
1383 * ________________|_______________
1384 * | | | / / / / / /|
1385 * | (x,y)|/ / / / / / |
1386 * |___________________|_/_/_/_/_/_/|
1387 * |<-------w0-------->| |
1388 * |<---------------w--|----------->|
1389 * | |
1390 * x0 Displaywidth-1
1393 if (x < Cursor_x_hot) { /* see fig. 1 */
1394 x0 = Cursor_x_hot - x;
1395 w0 = w - x0;
1398 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1399 w0 = (displayWidth) - (x - Cursor_x_hot);
1402 if (y < Cursor_y_hot) { /* see fig. 1 */
1403 y0 = Cursor_y_hot - y;
1404 h0 = h - y0;
1407 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1408 h0 = (displayHeight) - (y - Cursor_y_hot);
1410 /* end of coordinate correction */
1412 /* Grab an image from the screen, clipped if necessary,
1413 * and put it in the existing panel->magnifyGlass->image
1414 * with the corresponding clipping offset.
1416 if (!XGetSubImage(scr->display, scr->rootWin,
1417 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1418 wwarning(_("Color Panel: X failed request"));
1420 return NULL;
1423 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1425 /* (x1, y1) = topleft corner of existing rectangle
1426 * (x2, y2) = topleft corner of new position
1429 W_Screen *scr = WMWidgetScreen(panel->win);
1430 int xa = 0, ya = 0, xb = 0, yb = 0;
1431 int width, height;
1432 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1433 XImage *image;
1434 const int x_min = Cursor_x_hot,
1435 y_min = Cursor_y_hot,
1436 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1437 (Cursor_mask_width - Cursor_x_hot),
1438 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1440 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1441 return; /* No movement */
1443 if (x1 < x2)
1444 xa = dx;
1445 else
1446 xb = dx;
1448 if (y1 < y2)
1449 ya = dy;
1450 else
1451 yb = dy;
1453 width = Cursor_mask_width - dx;
1454 height = Cursor_mask_height - dy;
1456 /* If the traversed distance is larger than the size of the magnifying
1457 * glass contents, there is no need to do dirty rectangles. A whole new
1458 * rectangle can be grabbed (unless that rectangle falls partially
1459 * off screen).
1460 * Destroying the image and setting it to NULL will achieve that later on.
1462 * Of course, grabbing an XImage beyond the borders of the screen will
1463 * cause trouble, this is considdered a special case. Part of the screen
1464 * is grabbed, but there is no need for dirty rectangles.
1466 if ((width <= 0) || (height <= 0)) {
1467 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1468 if (panel->magnifyGlass->image)
1469 XDestroyImage(panel->magnifyGlass->image);
1470 panel->magnifyGlass->image = NULL;
1472 } else {
1473 if (panel->magnifyGlass->image) {
1474 /* Get dirty rectangle from panel->magnifyGlass->image */
1475 panel->magnifyGlass->dirtyRect =
1476 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1477 if (!panel->magnifyGlass->dirtyRect) {
1478 wwarning(_("Color Panel: X failed request"));
1479 return; /* X returned a NULL from XSubImage */
1484 /* Get image from screen */
1485 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1486 if (image) { /* Only reassign if a *new* image was grabbed */
1487 panel->magnifyGlass->image = image;
1488 return;
1491 /* Copy previously stored rectangle on covered part of image */
1492 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1493 int old_height;
1495 /* "width" and "height" are used as coordinates here,
1496 * and run from [0...width-1] and [0...height-1] respectively.
1498 width--;
1499 height--;
1500 old_height = height;
1502 for (; width >= 0; width--)
1503 for (height = old_height; height >= 0; height--)
1504 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1505 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1506 XDestroyImage(panel->magnifyGlass->dirtyRect);
1507 panel->magnifyGlass->dirtyRect = NULL;
1510 return;
1513 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1515 W_Screen *scr = WMWidgetScreen(panel->win);
1516 int u, v;
1517 #ifndef SHAPE
1518 Pixmap pixmap;
1519 #endif
1520 unsigned long color;
1522 if (!panel->magnifyGlass->image)
1523 return None;
1525 if (!panel->magnifyGlass->magPix)
1526 return None;
1529 * Copy an area of only 5x5 pixels from the center of the image.
1531 for (u = 0; u < 5; u++) {
1532 for (v = 0; v < 5; v++) {
1533 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1535 XSetForeground(scr->display, scr->copyGC, color);
1537 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1538 panel->magnifyGlass->color = ulongToRColor(scr, color);
1540 /* The center square must eventually be centered around the
1541 * hotspot. The image needs shifting to achieve this. The amount of
1542 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1543 * _ _ _ _ _
1544 * |_|_|_|_|_|
1545 * ^------- center of center square == Cursor_x_hot
1547 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1548 scr->copyGC,
1549 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1550 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1554 #ifdef SHAPE
1555 return panel->magnifyGlass->magPix;
1556 #else
1557 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1558 if (!pixmap)
1559 return None;
1561 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1562 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1564 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1565 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1566 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1567 /* (2,2) puts center pixel on center of glass */
1569 return pixmap;
1570 #endif
1574 static WMView *magnifyCreateView(W_ColorPanel * panel)
1576 W_Screen *scr = WMWidgetScreen(panel->win);
1577 WMView *magView;
1579 magView = W_CreateTopView(scr);
1580 if (!magView)
1581 return NULL;
1583 magView->self = panel->win;
1584 magView->flags.topLevel = 1;
1585 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1586 magView->attribs.override_redirect = True;
1587 magView->attribs.save_under = True;
1589 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1591 W_RealizeView(magView);
1593 return magView;
1596 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1598 W_Screen *scr = WMWidgetScreen(panel->win);
1599 Pixmap magPixmap, magPixmap2;
1600 Cursor magCursor;
1601 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1602 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1604 /* Cursor creation stuff */
1605 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1606 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1607 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1608 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1610 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1611 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1613 XFreePixmap(scr->display, magPixmap);
1614 XFreePixmap(scr->display, magPixmap2);
1616 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1618 /* Set up Pointer */
1619 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1620 PointerMotionMask | ButtonPressMask,
1621 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1623 return magCursor;
1626 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1628 W_Screen *scr = WMWidgetScreen(panel->win);
1629 int x, y, u, v;
1630 unsigned int mask;
1631 Pixmap pixmap, clip_mask;
1632 WMPoint point;
1633 Window root_return, child_return;
1635 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1636 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1637 1, 0, 1);
1638 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1639 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1641 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1643 panel->magnifyGlass->image = NULL;
1645 /* Clipmask to make magnified view-contents circular */
1646 #ifdef SHAPE
1647 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1648 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1649 #else
1650 /* Clip circle in glass cursor */
1651 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1652 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1653 #endif
1655 XFreePixmap(scr->display, clip_mask);
1657 /* Draw initial magnifying glass contents */
1658 magnifyGetImageStored(panel, x, y, x, y);
1660 pixmap = magnifyCreatePixmap(panel);
1661 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1662 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1663 XFlush(scr->display);
1665 #ifndef SHAPE
1666 XFreePixmap(scr->display, pixmap);
1667 #endif
1669 point.x = x;
1670 point.y = y;
1672 return point;
1675 static void magnifyPutCursor(WMWidget * w, void *data)
1677 W_ColorPanel *panel = (W_ColorPanel *) (data);
1678 W_Screen *scr = WMWidgetScreen(panel->win);
1679 Cursor magCursor;
1680 Pixmap pixmap;
1681 XEvent event;
1682 WMPoint initialPosition;
1684 /* Destroy wheelBackImg, so it'll update properly */
1685 if (panel->selectionBackImg) {
1686 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1687 panel->selectionBackImg = None;
1690 /* Create magnifying glass */
1691 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1692 panel->magnifyGlass->view = magnifyCreateView(panel);
1693 if (!panel->magnifyGlass->view)
1694 return;
1696 initialPosition = magnifyInitialize(panel);
1697 panel->magnifyGlass->x = initialPosition.x;
1698 panel->magnifyGlass->y = initialPosition.y;
1700 W_MoveView(panel->magnifyGlass->view,
1701 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1702 W_MapView(panel->magnifyGlass->view);
1704 magCursor = magnifyGrabPointer(panel);
1706 while (panel->magnifyGlass->image) {
1707 WMNextEvent(scr->display, &event);
1709 /* Pack motion events */
1710 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1713 switch (event.type) {
1714 case ButtonPress:
1715 XDestroyImage(panel->magnifyGlass->image);
1716 panel->magnifyGlass->image = NULL;
1718 if (event.xbutton.button == Button1) {
1719 panel->color.rgb = panel->magnifyGlass->color;
1720 panel->color.set = cpRGB;
1721 updateSwatch(panel, panel->color);
1723 switch (panel->mode) {
1724 case WMWheelModeColorPanel:
1725 wheelInit(panel);
1726 wheelRender(panel);
1727 wheelPaint(panel);
1728 break;
1729 case WMGrayModeColorPanel:
1730 grayInit(panel);
1731 break;
1732 case WMRGBModeColorPanel:
1733 rgbInit(panel);
1734 break;
1735 case WMCMYKModeColorPanel:
1736 cmykInit(panel);
1737 break;
1738 case WMHSBModeColorPanel:
1739 hsbInit(panel);
1740 break;
1741 default:
1742 break;
1744 panel->lastChanged = panel->mode;
1746 WMSetButtonSelected(panel->magnifyBtn, False);
1747 break;
1749 case MotionNotify:
1750 while (XPending(event.xmotion.display)) {
1751 XEvent ev;
1752 XPeekEvent(event.xmotion.display, &ev);
1753 if (ev.type == MotionNotify)
1754 XNextEvent(event.xmotion.display, &event);
1755 else
1756 break;
1759 /* Get a "dirty rectangle" */
1760 magnifyGetImageStored(panel,
1761 panel->magnifyGlass->x, panel->magnifyGlass->y,
1762 event.xmotion.x_root, event.xmotion.y_root);
1764 /* Update coordinates */
1765 panel->magnifyGlass->x = event.xmotion.x_root;
1766 panel->magnifyGlass->y = event.xmotion.y_root;
1768 /* Move view */
1769 W_MoveView(panel->magnifyGlass->view,
1770 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1772 /* Put new image (with magn.) in view */
1773 pixmap = magnifyCreatePixmap(panel);
1774 if (pixmap != None) {
1775 /* Change the window background */
1776 XSetWindowBackgroundPixmap(scr->display,
1777 WMViewXID(panel->magnifyGlass->view), pixmap);
1778 /* Force an Expose (handled by X) */
1779 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1780 /* Synchronize the event queue, so the Expose is handled NOW */
1781 XFlush(scr->display);
1782 #ifndef SHAPE
1783 XFreePixmap(scr->display, pixmap);
1784 #endif
1786 break;
1788 /* Try XQueryPointer for this !!! It returns windows that the pointer
1789 * is over. Note: We found this solving the invisible donkey cap bug
1791 #if 0 /* As it is impossible to make this work in all cases,
1792 * we consider it confusing. Therefore we disabled it.
1794 case FocusOut: /* fall through */
1795 case FocusIn:
1797 * Color Panel window (panel->win) lost or received focus.
1798 * We need to update the pixmap in the magnifying glass.
1800 * BUG Doesn't work with focus switches between two windows
1801 * if none of them is the color panel.
1803 XUngrabPointer(scr->display, CurrentTime);
1804 W_UnmapView(panel->magnifyGlass->view);
1806 magnifyInitialize(panel);
1808 W_MapView(panel->magnifyGlass->view);
1809 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1810 True, PointerMotionMask | ButtonPressMask,
1811 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1812 break;
1813 #endif
1814 default:
1815 WMHandleEvent(&event);
1816 break;
1817 } /* of switch */
1820 XUngrabPointer(scr->display, CurrentTime);
1821 XFreeCursor(scr->display, magCursor);
1823 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1824 panel->magnifyGlass->magPix = None;
1826 W_UnmapView(panel->magnifyGlass->view);
1827 W_DestroyView(panel->magnifyGlass->view);
1828 panel->magnifyGlass->view = NULL;
1830 wfree(panel->magnifyGlass);
1833 /****************** ColorWheel Functions ************************/
1835 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1837 wheelMatrix *matrix = NULL;
1838 int i;
1840 assert((width > 0) && (height > 0));
1842 matrix = wmalloc(sizeof(wheelMatrix));
1843 matrix->width = width;
1844 matrix->height = height;
1846 for (i = 0; i < 3; i++) {
1847 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1850 return matrix;
1853 static void wheelDestroyMatrix(wheelMatrix * matrix)
1855 int i;
1857 if (!matrix)
1858 return;
1860 for (i = 0; i < 3; i++) {
1861 if (matrix->data[i])
1862 wfree(matrix->data[i]);
1864 wfree(matrix);
1867 static void wheelInitMatrix(W_ColorPanel * panel)
1869 int i;
1870 int x, y;
1871 unsigned char *rp, *gp, *bp;
1872 CPColor cpColor;
1873 long ofs[4];
1874 int xcor, ycor;
1875 unsigned short sat;
1876 int dhue[4];
1877 const int cw_halfsize = (colorWheelSize + 4) / 2,
1878 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1880 if (!panel->wheelMtrx)
1881 return;
1883 cpColor.hsv.value = 255;
1884 cpColor.set = cpHSV;
1886 ofs[0] = -1;
1887 ofs[1] = -(colorWheelSize + 4);
1889 /* offsets are counterclockwise (in triangles).
1891 * ofs[0] ---->
1892 * _______________________________________
1893 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1894 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1895 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1896 * o | | | | | | | | | | | | | | | | | | | | | [3]
1898 * <---- ofs[2]
1899 * ____
1900 * |\ /| <-- triangles
1901 * | \/ |
1902 * | /\ |
1903 * |/__\|
1906 for (y = 0; y < cw_halfsize; y++) {
1907 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1908 /* (xcor, ycor) is (x,y) relative to center of matrix */
1909 xcor = 2 * x - 4 - colorWheelSize;
1910 ycor = 2 * y - 4 - colorWheelSize;
1912 /* RColor.saturation is unsigned char and will wrap after 255 */
1913 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1915 cpColor.hsv.saturation = (unsigned char)sat;
1917 ofs[0]++; /* top quarter of matrix */
1918 ofs[1] += colorWheelSize + 4; /* left quarter */
1919 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1920 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1922 if (sat < 256) {
1923 if (xcor != 0)
1924 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1925 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1926 else
1927 dhue[0] = 270;
1929 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1930 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1931 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1932 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1934 for (i = 0; i < 4; i++) {
1935 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1936 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1937 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1939 cpColor.hsv.hue = dhue[i];
1940 convertCPColor(&cpColor);
1942 *rp = (unsigned char)(cpColor.rgb.red);
1943 *gp = (unsigned char)(cpColor.rgb.green);
1944 *bp = (unsigned char)(cpColor.rgb.blue);
1946 } else {
1947 for (i = 0; i < 4; i++) {
1948 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1949 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1950 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1952 *rp = (unsigned char)0;
1953 *gp = (unsigned char)0;
1954 *bp = (unsigned char)0;
1959 ofs[0] += 2 * y + 1;
1960 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1964 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1966 unsigned int i;
1967 unsigned int v;
1969 for (i = 0; i < 256; i++) {
1970 /* We divide by 128 in advance, and check whether that number divides
1971 * by 2 properly. If not, we add one to round the number correctly
1973 v = (i * maxvalue) >> 7;
1974 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
1978 static void wheelRender(W_ColorPanel * panel)
1980 W_Screen *scr = WMWidgetScreen(panel->win);
1981 int x, y;
1982 RImage *image;
1983 unsigned char *ptr;
1984 RColor gray;
1985 unsigned long ofs = 0;
1986 /*unsigned char shift = getShift(sizeof(unsigned char)); */
1988 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
1989 if (!image) {
1990 wwarning(_("Color Panel: Could not allocate memory"));
1991 return;
1994 ptr = image->data;
1996 /* TODO Make this transparent istead of gray */
1997 gray.red = gray.blue = 0xae;
1998 gray.green = 0xaa;
2000 for (y = 0; y < colorWheelSize + 4; y++) {
2001 for (x = 0; x < colorWheelSize + 4; x++) {
2002 if (wheelInsideColorWheel(panel, ofs)) {
2003 *(ptr++) =
2004 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2005 *(ptr++) =
2006 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2007 *(ptr++) =
2008 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2009 *(ptr++) = 0;
2010 } else {
2011 *(ptr++) = (unsigned char)(gray.red);
2012 *(ptr++) = (unsigned char)(gray.green);
2013 *(ptr++) = (unsigned char)(gray.blue);
2014 *(ptr++) = 255;
2016 ofs++;
2020 if (panel->wheelImg)
2021 XFreePixmap(scr->display, panel->wheelImg);
2023 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2024 RReleaseImage(image);
2026 /* Check if backimage exists. If it doesn't, allocate and fill it */
2027 if (!panel->selectionBackImg) {
2028 panel->selectionBackImg = XCreatePixmap(scr->display,
2029 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2030 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2031 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2032 /* -2 is hot spot correction */
2036 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2038 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2039 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2042 static void wheelPaint(W_ColorPanel * panel)
2044 W_Screen *scr = WMWidgetScreen(panel->win);
2046 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2047 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2049 /* Draw selection image */
2050 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2051 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2054 static void wheelHandleEvents(XEvent * event, void *data)
2056 W_ColorPanel *panel = (W_ColorPanel *) data;
2058 switch (event->type) {
2059 case Expose:
2060 if (event->xexpose.count != 0) /* TODO Improve */
2061 break;
2062 wheelPaint(panel);
2063 break;
2067 static void wheelHandleActionEvents(XEvent * event, void *data)
2069 W_ColorPanel *panel = (W_ColorPanel *) data;
2071 switch (event->type) {
2072 case ButtonPress:
2073 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2075 panel->lastChanged = WMWheelModeColorPanel;
2076 panel->flags.dragging = 1;
2078 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2080 break;
2082 case ButtonRelease:
2083 panel->flags.dragging = 0;
2084 if (!panel->flags.continuous) {
2085 if (panel->action)
2086 (*panel->action) (panel, panel->clientData);
2088 break;
2090 case MotionNotify:
2091 if (panel->flags.dragging) {
2092 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2093 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2094 } else
2095 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2097 break;
2101 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2103 int lx, ly;
2104 unsigned long ofs;
2106 lx = x;
2107 ly = y;
2109 if (panel->mode == WMWheelModeColorPanel) {
2110 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2112 ofs = ly * panel->wheelMtrx->width + lx;
2114 if (wheelInsideColorWheel(panel, ofs))
2115 return COLORWHEEL_PART;
2119 if (panel->mode == WMCustomPaletteModeColorPanel) {
2120 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2121 return CUSTOMPALETTE_PART;
2125 return 0;
2128 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2130 int value;
2132 W_ColorPanel *panel = (W_ColorPanel *) data;
2134 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2136 wheelCalculateValues(panel, value);
2138 if (panel->color.set == cpRGB) {
2139 convertCPColor(&panel->color);
2140 panel->color.set = cpHSV;
2143 panel->color.hsv.value = value;
2145 wheelRender(panel);
2146 wheelPaint(panel);
2147 wheelUpdateSelection(panel);
2150 static void wheelUpdateSelection(W_ColorPanel * panel)
2152 W_Screen *scr = WMWidgetScreen(panel->win);
2154 updateSwatch(panel, panel->color);
2155 panel->lastChanged = WMWheelModeColorPanel;
2157 /* Redraw color selector (and make a backup of the part it will cover) */
2158 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2159 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2160 /* "-2" is correction for hotspot location */
2161 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2162 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2163 /* see above */
2166 static void wheelUndrawSelection(W_ColorPanel * panel)
2168 W_Screen *scr = WMWidgetScreen(panel->win);
2170 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2171 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2172 /* see above */
2175 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2177 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2179 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2181 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2183 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2184 panel->color.set = cpRGB;
2186 wheelUndrawSelection(panel);
2188 panel->colx = x;
2189 panel->coly = y;
2191 wheelUpdateSelection(panel);
2192 wheelUpdateBrightnessGradientFromLocation(panel);
2195 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2197 int hue;
2198 int xcor, ycor;
2199 CPColor cpColor;
2201 xcor = x * 2 - colorWheelSize - 4;
2202 ycor = y * 2 - colorWheelSize - 4;
2204 panel->color.hsv.saturation = 255;
2205 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2207 if (xcor != 0)
2208 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2209 else {
2210 if (ycor < 0)
2211 hue = 90;
2212 else
2213 hue = 270;
2216 if (xcor < 0)
2217 hue += 180;
2219 if ((xcor > 0) && (ycor > 0))
2220 hue += 360;
2222 panel->color.hsv.hue = hue;
2223 panel->color.set = cpHSV;
2224 convertCPColor(&panel->color);
2226 wheelUndrawSelection(panel);
2228 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2229 /* "+2" because of "colorWheelSize + 4" */
2230 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2232 wheelUpdateSelection(panel);
2233 cpColor = panel->color;
2234 wheelUpdateBrightnessGradient(panel, cpColor);
2237 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2239 CPColor from;
2240 unsigned long ofs;
2242 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2244 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2245 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2246 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2247 from.set = cpRGB;
2249 wheelUpdateBrightnessGradient(panel, from);
2252 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2254 RColor to;
2255 RImage *sliderImg;
2256 WMPixmap *sliderPxmp;
2258 to.red = to.green = to.blue = 0;
2260 if (topColor.set == cpHSV)
2261 convertCPColor(&topColor);
2263 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2264 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2265 RReleaseImage(sliderImg);
2266 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2267 WMReleasePixmap(sliderPxmp);
2270 /****************** Grayscale Panel Functions ***************/
2272 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2274 CPColor cpColor;
2275 int value;
2276 char tmp[4];
2277 W_ColorPanel *panel = (W_ColorPanel *) data;
2279 value = WMGetSliderValue(panel->grayBrightnessS);
2281 sprintf(tmp, "%d", value);
2283 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2284 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2285 cpColor.set = cpRGB;
2287 updateSwatch(panel, cpColor);
2288 panel->lastChanged = WMGrayModeColorPanel;
2291 static void grayPresetButtonCallback(WMWidget * w, void *data)
2293 CPColor cpColor;
2294 char tmp[4];
2295 int value;
2296 int i = 0;
2297 W_ColorPanel *panel = (W_ColorPanel *) data;
2299 while (i < 7) {
2300 if (w == panel->grayPresetBtn[i])
2301 break;
2302 i++;
2305 value = rint((100.0 * i) / 6.0);
2306 sprintf(tmp, "%d", value);
2308 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2309 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2310 cpColor.set = cpRGB;
2312 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2314 updateSwatch(panel, cpColor);
2315 panel->lastChanged = WMGrayModeColorPanel;
2318 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2320 CPColor cpColor;
2321 char tmp[4];
2322 int value;
2323 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2325 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2326 if (value > 100)
2327 value = 100;
2328 if (value < 0)
2329 value = 0;
2331 sprintf(tmp, "%d", value);
2332 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2333 WMSetSliderValue(panel->grayBrightnessS, value);
2335 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2336 cpColor.set = cpRGB;
2338 updateSwatch(panel, cpColor);
2339 panel->lastChanged = WMGrayModeColorPanel;
2342 /******************* RGB Panel Functions *****************/
2344 static void rgbSliderCallback(WMWidget * w, void *data)
2346 CPColor cpColor;
2347 int value[3];
2348 char tmp[4];
2349 W_ColorPanel *panel = (W_ColorPanel *) data;
2351 value[0] = WMGetSliderValue(panel->rgbRedS);
2352 value[1] = WMGetSliderValue(panel->rgbGreenS);
2353 value[2] = WMGetSliderValue(panel->rgbBlueS);
2355 sprintf(tmp, "%d", value[0]);
2356 WMSetTextFieldText(panel->rgbRedT, tmp);
2357 sprintf(tmp, "%d", value[1]);
2358 WMSetTextFieldText(panel->rgbGreenT, tmp);
2359 sprintf(tmp, "%d", value[2]);
2360 WMSetTextFieldText(panel->rgbBlueT, tmp);
2362 cpColor.rgb.red = value[0];
2363 cpColor.rgb.green = value[1];
2364 cpColor.rgb.blue = value[2];
2365 cpColor.set = cpRGB;
2367 updateSwatch(panel, cpColor);
2368 panel->lastChanged = WMRGBModeColorPanel;
2371 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2373 CPColor cpColor;
2374 int value[3];
2375 char tmp[4];
2376 int n;
2377 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2379 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2380 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2381 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2383 for (n = 0; n < 3; n++) {
2384 if (value[n] > 255)
2385 value[n] = 255;
2386 if (value[n] < 0)
2387 value[n] = 0;
2390 sprintf(tmp, "%d", value[0]);
2391 WMSetTextFieldText(panel->rgbRedT, tmp);
2392 sprintf(tmp, "%d", value[1]);
2393 WMSetTextFieldText(panel->rgbGreenT, tmp);
2394 sprintf(tmp, "%d", value[2]);
2395 WMSetTextFieldText(panel->rgbBlueT, tmp);
2397 WMSetSliderValue(panel->rgbRedS, value[0]);
2398 WMSetSliderValue(panel->rgbGreenS, value[1]);
2399 WMSetSliderValue(panel->rgbBlueS, value[2]);
2401 cpColor.rgb.red = value[0];
2402 cpColor.rgb.green = value[1];
2403 cpColor.rgb.blue = value[2];
2404 cpColor.set = cpRGB;
2406 updateSwatch(panel, cpColor);
2407 panel->lastChanged = WMRGBModeColorPanel;
2410 /******************* CMYK Panel Functions *****************/
2412 static void cmykSliderCallback(WMWidget * w, void *data)
2414 CPColor cpColor;
2415 int value[4];
2416 char tmp[4];
2417 W_ColorPanel *panel = (W_ColorPanel *) data;
2418 double scale;
2420 value[0] = WMGetSliderValue(panel->cmykCyanS);
2421 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2422 value[2] = WMGetSliderValue(panel->cmykYellowS);
2423 value[3] = WMGetSliderValue(panel->cmykBlackS);
2425 sprintf(tmp, "%d", value[0]);
2426 WMSetTextFieldText(panel->cmykCyanT, tmp);
2427 sprintf(tmp, "%d", value[1]);
2428 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2429 sprintf(tmp, "%d", value[2]);
2430 WMSetTextFieldText(panel->cmykYellowT, tmp);
2431 sprintf(tmp, "%d", value[3]);
2432 WMSetTextFieldText(panel->cmykBlackT, tmp);
2434 scale = 2.55 * (1.0 - (value[3] / 100.0));
2435 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2436 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2437 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2438 cpColor.set = cpRGB;
2440 updateSwatch(panel, cpColor);
2441 panel->lastChanged = WMCMYKModeColorPanel;
2444 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2446 CPColor cpColor;
2447 int value[4];
2448 char tmp[4];
2449 int n;
2450 double scale;
2451 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2453 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2454 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2455 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2456 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2458 for (n = 0; n < 4; n++) {
2459 if (value[n] > 100)
2460 value[n] = 100;
2461 if (value[n] < 0)
2462 value[n] = 0;
2465 sprintf(tmp, "%d", value[0]);
2466 WMSetTextFieldText(panel->cmykCyanT, tmp);
2468 sprintf(tmp, "%d", value[1]);
2469 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2471 sprintf(tmp, "%d", value[2]);
2472 WMSetTextFieldText(panel->cmykYellowT, tmp);
2474 sprintf(tmp, "%d", value[3]);
2475 WMSetTextFieldText(panel->cmykBlackT, tmp);
2477 WMSetSliderValue(panel->cmykCyanS, value[0]);
2478 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2479 WMSetSliderValue(panel->cmykYellowS, value[2]);
2480 WMSetSliderValue(panel->cmykBlackS, value[3]);
2482 scale = 2.55 * (1.0 - (value[3] / 100.0));
2483 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2484 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2485 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2486 cpColor.set = cpRGB;
2488 updateSwatch(panel, cpColor);
2489 panel->lastChanged = WMCMYKModeColorPanel;
2492 /********************** HSB Panel Functions ***********************/
2494 static void hsbSliderCallback(WMWidget * w, void *data)
2496 CPColor cpColor;
2497 int value[3];
2498 char tmp[4];
2499 W_ColorPanel *panel = (W_ColorPanel *) data;
2501 value[0] = WMGetSliderValue(panel->hsbHueS);
2502 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2503 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2505 sprintf(tmp, "%d", value[0]);
2506 WMSetTextFieldText(panel->hsbHueT, tmp);
2507 sprintf(tmp, "%d", value[1]);
2508 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2509 sprintf(tmp, "%d", value[2]);
2510 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2512 cpColor.hsv.hue = value[0];
2513 cpColor.hsv.saturation = value[1] * 2.55;
2514 cpColor.hsv.value = value[2] * 2.55;
2515 cpColor.set = cpHSV;
2517 convertCPColor(&cpColor);
2519 panel->lastChanged = WMHSBModeColorPanel;
2520 updateSwatch(panel, cpColor);
2522 if (w != panel->hsbBrightnessS)
2523 hsbUpdateBrightnessGradient(panel);
2524 if (w != panel->hsbSaturationS)
2525 hsbUpdateSaturationGradient(panel);
2526 if (w != panel->hsbHueS)
2527 hsbUpdateHueGradient(panel);
2530 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2532 CPColor cpColor;
2533 int value[3];
2534 char tmp[4];
2535 int n;
2536 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2538 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2539 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2540 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2542 if (value[0] > 359)
2543 value[0] = 359;
2544 if (value[0] < 0)
2545 value[0] = 0;
2547 for (n = 1; n < 3; n++) {
2548 if (value[n] > 100)
2549 value[n] = 100;
2550 if (value[n] < 0)
2551 value[n] = 0;
2554 sprintf(tmp, "%d", value[0]);
2555 WMSetTextFieldText(panel->hsbHueT, tmp);
2556 sprintf(tmp, "%d", value[1]);
2557 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2558 sprintf(tmp, "%d", value[2]);
2559 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2561 WMSetSliderValue(panel->hsbHueS, value[0]);
2562 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2563 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2565 cpColor.hsv.hue = value[0];
2566 cpColor.hsv.saturation = value[1] * 2.55;
2567 cpColor.hsv.value = value[2] * 2.55;
2568 cpColor.set = cpHSV;
2570 convertCPColor(&cpColor);
2572 panel->lastChanged = WMHSBModeColorPanel;
2573 updateSwatch(panel, cpColor);
2575 hsbUpdateBrightnessGradient(panel);
2576 hsbUpdateSaturationGradient(panel);
2577 hsbUpdateHueGradient(panel);
2580 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2582 W_Screen *scr = WMWidgetScreen(panel->win);
2583 RColor from;
2584 CPColor to;
2585 RImage *sliderImg;
2586 WMPixmap *sliderPxmp;
2588 from.red = from.green = from.blue = 0;
2589 to.hsv = panel->color.hsv;
2590 to.hsv.value = 255;
2591 to.set = cpHSV;
2593 convertCPColor(&to);
2595 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2596 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2597 RReleaseImage(sliderImg);
2599 if (sliderPxmp)
2600 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2601 panel->font12, 2, 0, 100, WALeft, scr->white,
2602 False, _("Brightness"), strlen(_("Brightness")));
2603 else
2604 wwarning(_("Color Panel: Could not allocate memory"));
2606 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2607 WMReleasePixmap(sliderPxmp);
2610 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2612 W_Screen *scr = WMWidgetScreen(panel->win);
2613 CPColor from;
2614 CPColor to;
2615 RImage *sliderImg;
2616 WMPixmap *sliderPxmp;
2618 from.hsv = panel->color.hsv;
2619 from.hsv.saturation = 0;
2620 from.set = cpHSV;
2621 convertCPColor(&from);
2623 to.hsv = panel->color.hsv;
2624 to.hsv.saturation = 255;
2625 to.set = cpHSV;
2626 convertCPColor(&to);
2628 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2629 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2630 RReleaseImage(sliderImg);
2632 if (sliderPxmp)
2633 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2634 panel->font12, 2, 0, 100, WALeft,
2635 from.hsv.value < 128 ? scr->white : scr->black, False,
2636 _("Saturation"), strlen(_("Saturation")));
2637 else
2638 wwarning(_("Color Panel: Could not allocate memory"));
2640 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2641 WMReleasePixmap(sliderPxmp);
2644 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2646 W_Screen *scr = WMWidgetScreen(panel->win);
2647 RColor **colors = NULL;
2648 RHSVColor hsvcolor;
2649 RImage *sliderImg;
2650 WMPixmap *sliderPxmp;
2651 int i;
2653 hsvcolor = panel->color.hsv;
2655 colors = wmalloc(sizeof(RColor *) * (8));
2656 for (i = 0; i < 7; i++) {
2657 hsvcolor.hue = (360 * i) / 6;
2658 colors[i] = wmalloc(sizeof(RColor));
2659 RHSVtoRGB(&hsvcolor, colors[i]);
2661 colors[7] = NULL;
2663 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2664 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2665 RReleaseImage(sliderImg);
2667 if (sliderPxmp)
2668 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2669 panel->font12, 2, 0, 100, WALeft,
2670 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2671 else
2672 wwarning(_("Color Panel: Could not allocate memory"));
2674 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2675 WMReleasePixmap(sliderPxmp);
2677 for (i = 0; i < 7; i++)
2678 wfree(colors[i]);
2680 wfree(colors);
2683 /*************** Custom Palette Functions ****************/
2685 static void customRenderSpectrum(W_ColorPanel * panel)
2687 RImage *spectrum;
2688 int x, y;
2689 unsigned char *ptr;
2690 CPColor cpColor;
2692 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2694 ptr = spectrum->data;
2696 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2697 cpColor.hsv.hue = y;
2698 cpColor.hsv.saturation = 0;
2699 cpColor.hsv.value = 255;
2700 cpColor.set = cpHSV;
2702 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2703 convertCPColor(&cpColor);
2705 *(ptr++) = (unsigned char)cpColor.rgb.red;
2706 *(ptr++) = (unsigned char)cpColor.rgb.green;
2707 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2709 if (x < (SPECTRUM_WIDTH / 2))
2710 cpColor.hsv.saturation++;
2712 if (x > (SPECTRUM_WIDTH / 2))
2713 cpColor.hsv.value--;
2716 if (panel->customPaletteImg) {
2717 RReleaseImage(panel->customPaletteImg);
2718 panel->customPaletteImg = NULL;
2720 panel->customPaletteImg = spectrum;
2723 static void customSetPalette(W_ColorPanel * panel)
2725 W_Screen *scr = WMWidgetScreen(panel->win);
2726 RImage *scaledImg;
2727 Pixmap image;
2729 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2730 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2731 RConvertImage(scr->rcontext, scaledImg, &image);
2732 RReleaseImage(scaledImg);
2734 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2735 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2737 /* Check backimage exists. If it doesn't, allocate and fill it */
2738 if (!panel->selectionBackImg) {
2739 panel->selectionBackImg = XCreatePixmap(scr->display,
2740 panel->customPaletteContentView->window, 4, 4, scr->depth);
2743 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2744 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2745 XCopyArea(scr->display, panel->selectionImg,
2746 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2747 panel->palx - 2, panel->paly - 2);
2748 XFreePixmap(scr->display, image);
2750 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2751 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2753 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2756 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2758 W_Screen *scr = WMWidgetScreen(panel->win);
2759 unsigned long ofs;
2761 /* undraw selection */
2762 XCopyArea(scr->display, panel->selectionBackImg,
2763 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2764 panel->palx - 2, panel->paly - 2);
2766 panel->palx = x;
2767 panel->paly = y;
2769 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2771 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2772 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2773 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2774 panel->color.set = cpRGB;
2776 updateSwatch(panel, panel->color);
2777 panel->lastChanged = WMCustomPaletteModeColorPanel;
2779 /* Redraw color selector (and make a backup of the part it will cover) */
2780 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 */
2781 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2784 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2786 if (x < 2)
2787 x = 2;
2788 if (y < 2)
2789 y = 2;
2790 if (x >= customPaletteWidth)
2791 x = customPaletteWidth - 2;
2792 if (y >= customPaletteHeight)
2793 y = customPaletteHeight - 2;
2795 customPalettePositionSelection(panel, x, y);
2798 static void customPaletteHandleEvents(XEvent * event, void *data)
2800 W_ColorPanel *panel = (W_ColorPanel *) data;
2802 switch (event->type) {
2803 case Expose:
2804 if (event->xexpose.count != 0) /* TODO Improve. */
2805 break;
2806 customSetPalette(panel);
2807 break;
2811 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2813 W_ColorPanel *panel = (W_ColorPanel *) data;
2814 int x, y;
2816 switch (event->type) {
2817 case ButtonPress:
2818 x = event->xbutton.x;
2819 y = event->xbutton.y;
2821 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2822 panel->flags.dragging = 1;
2823 customPalettePositionSelection(panel, x, y);
2825 break;
2827 case ButtonRelease:
2828 panel->flags.dragging = 0;
2829 if (!panel->flags.continuous) {
2830 if (panel->action)
2831 (*panel->action) (panel, panel->clientData);
2833 break;
2835 case MotionNotify:
2836 x = event->xmotion.x;
2837 y = event->xmotion.y;
2839 if (panel->flags.dragging) {
2840 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2841 customPalettePositionSelection(panel, x, y);
2842 } else
2843 customPalettePositionSelectionOutBounds(panel, x, y);
2845 break;
2849 static void customPaletteMenuCallback(WMWidget * w, void *data)
2851 W_ColorPanel *panel = (W_ColorPanel *) data;
2852 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2854 switch (item) {
2855 case CPmenuNewFromFile:
2856 customPaletteMenuNewFromFile(panel);
2857 break;
2858 case CPmenuRename:
2859 customPaletteMenuRename(panel);
2860 break;
2861 case CPmenuRemove:
2862 customPaletteMenuRemove(panel);
2863 break;
2864 case CPmenuCopy:
2865 break;
2866 case CPmenuNewFromClipboard:
2867 break;
2871 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2873 W_Screen *scr = WMWidgetScreen(panel->win);
2874 WMOpenPanel *browseP;
2875 char *filepath;
2876 char *filename = NULL;
2877 char *spath;
2878 char *tmp;
2879 int i;
2880 RImage *tmpImg = NULL;
2882 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
2883 spath = wexpandpath(wgethomedir());
2884 else
2885 spath = wexpandpath(panel->lastBrowseDir);
2887 browseP = WMGetOpenPanel(scr);
2888 WMSetFilePanelCanChooseDirectories(browseP, 0);
2889 WMSetFilePanelCanChooseFiles(browseP, 1);
2891 /* Get a filename */
2892 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
2893 _("Open Palette"), RSupportedFileFormats())) {
2894 filepath = WMGetFilePanelFileName(browseP);
2896 /* Get seperation position between path and filename */
2897 i = strrchr(filepath, '/') - filepath + 1;
2898 if (i > strlen(filepath))
2899 i = strlen(filepath);
2901 /* Store last browsed path */
2902 if (panel->lastBrowseDir)
2903 wfree(panel->lastBrowseDir);
2904 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
2905 strncpy(panel->lastBrowseDir, filepath, i);
2906 panel->lastBrowseDir[i] = '\0';
2908 /* Get filename from path */
2909 filename = wstrdup(filepath + i);
2911 /* Check for duplicate files, and rename it if there are any */
2912 tmp = wstrconcat(panel->configurationPath, filename);
2913 while (access(tmp, F_OK) == 0) {
2914 char *newName;
2916 wfree(tmp);
2918 newName = generateNewFilename(filename);
2919 wfree(filename);
2920 filename = newName;
2922 tmp = wstrconcat(panel->configurationPath, filename);
2924 wfree(tmp);
2926 /* Copy image to $(gnustepdir)/Library/Colors/ &
2927 * Add filename to history menu */
2928 if (fetchFile(panel->configurationPath, filepath, filename) == 0) {
2930 /* filepath is a "local" path now the file has been copied */
2931 wfree(filepath);
2932 filepath = wstrconcat(panel->configurationPath, filename);
2934 /* load the image & add menu entries */
2935 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
2936 if (tmpImg) {
2937 if (panel->customPaletteImg)
2938 RReleaseImage(panel->customPaletteImg);
2939 panel->customPaletteImg = tmpImg;
2941 customSetPalette(panel);
2942 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
2944 panel->currentPalette =
2945 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
2947 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
2948 panel->currentPalette);
2950 } else {
2951 tmp = wstrconcat(panel->configurationPath, filename);
2953 i = remove(tmp); /* Delete the file, it doesn't belong here */
2954 WMRunAlertPanel(scr, panel->win, _("File Error"),
2955 _("Invalid file format !"), _("OK"), NULL, NULL);
2956 if (i != 0) {
2957 werror(_("can't remove file %s"), tmp);
2958 WMRunAlertPanel(scr, panel->win, _("File Error"),
2959 _("Couldn't remove file from Configuration Directory !"),
2960 _("OK"), NULL, NULL);
2962 wfree(tmp);
2964 wfree(filepath);
2965 wfree(filename);
2967 WMFreeFilePanel(browseP);
2969 wfree(spath);
2972 static void customPaletteMenuRename(W_ColorPanel * panel)
2974 W_Screen *scr = WMWidgetScreen(panel->win);
2975 char *toName = NULL;
2976 char *fromName;
2977 char *toPath, *fromPath;
2978 int item;
2979 int index;
2981 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2982 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
2984 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
2985 fromName, _("OK"), _("Cancel"));
2987 if (toName) {
2989 /* As some people do certain stupid things... */
2990 if (strcmp(toName, fromName) == 0) {
2991 wfree(toName);
2992 return;
2995 /* For normal people */
2996 fromPath = wstrconcat(panel->configurationPath, fromName);
2997 toPath = wstrconcat(panel->configurationPath, toName);
2999 if (access(toPath, F_OK) == 0) {
3000 /* Careful, this palette exists already */
3001 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3002 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3003 NULL) == 1) {
3004 /* "No" = 0, "Yes" = 1 */
3005 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3007 remove(toPath);
3009 /* Remove from History list too */
3010 index = 1;
3011 while ((index < items)
3013 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3014 != 0))
3015 index++;
3017 if (index < items) {
3018 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3019 if (index < item)
3020 item--;
3023 } else {
3024 wfree(fromPath);
3025 wfree(toName);
3026 wfree(toPath);
3028 return;
3032 if (rename(fromPath, toPath) != 0)
3033 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3034 else {
3035 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3036 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3038 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3040 wfree(fromPath);
3041 wfree(toPath);
3042 wfree(toName);
3046 static void customPaletteMenuRemove(W_ColorPanel * panel)
3048 W_Screen *scr = WMWidgetScreen(panel->win);
3049 char *text;
3050 char *tmp;
3051 int choice;
3052 int item;
3054 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3056 tmp = wstrconcat(_("This will permanently remove the palette "),
3057 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3058 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3059 wfree(tmp);
3061 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3062 /* returns 0 (= "Yes") or 1 (="No") */
3063 wfree(text);
3065 if (choice == 0) {
3067 tmp = wstrconcat(panel->configurationPath,
3068 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3070 if (remove(tmp) == 0) {
3071 /* item-1 always exists */
3072 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3074 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3075 customSetPalette(panel);
3077 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3079 } else {
3080 werror(_("Couldn't remove palette %s"), tmp);
3083 wfree(tmp);
3087 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3089 W_ColorPanel *panel = (W_ColorPanel *) data;
3090 W_Screen *scr = WMWidgetScreen(panel->win);
3091 int item;
3092 char *filename;
3093 RImage *tmp = NULL;
3094 unsigned char perm_mask;
3096 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3097 if (item == panel->currentPalette)
3098 return;
3100 if (item == 0) {
3101 customRenderSpectrum(panel);
3103 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3104 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3105 } else {
3106 /* Load file from configpath */
3107 filename = wstrconcat(panel->configurationPath,
3108 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3110 /* If the file corresponding to the item does not exist,
3111 * remove it from the history list and select the next one.
3113 perm_mask = (access(filename, F_OK) == 0);
3114 if (!perm_mask) {
3115 /* File does not exist */
3116 wfree(filename);
3117 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3118 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3119 customPaletteHistoryCallback(w, data);
3120 return;
3123 /* Get the image */
3124 tmp = RLoadImage(scr->rcontext, filename, 0);
3125 if (tmp) {
3126 if (panel->customPaletteImg) {
3127 RReleaseImage(panel->customPaletteImg);
3128 panel->customPaletteImg = NULL;
3130 panel->customPaletteImg = tmp;
3133 /* If the image is not writable, don't allow removing/renaming */
3134 perm_mask = (access(filename, W_OK) == 0);
3135 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3136 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3138 wfree(filename);
3140 customSetPalette(panel);
3142 panel->currentPalette = item;
3145 /************************* ColorList Panel Functions **********************/
3147 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3149 WMScreen *scr = WMWidgetScreen(lPtr);
3150 Display *dpy = WMScreenDisplay(scr);
3151 WMView *view = W_VIEW(lPtr);
3152 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3153 W_ColorPanel *panel = WMGetHangedData(lPtr);
3154 int width, height, x, y;
3155 WMColor *fillColor;
3157 width = rect->size.width;
3158 height = rect->size.height;
3159 x = rect->pos.x;
3160 y = rect->pos.y;
3162 if (state & WLDSSelected)
3163 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3164 else
3165 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3167 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3169 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3170 WMReleaseColor(fillColor);
3172 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3175 static void colorListSelect(WMWidget * w, void *data)
3177 W_ColorPanel *panel = (W_ColorPanel *) data;
3178 CPColor cpColor;
3180 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3181 cpColor.set = cpRGB;
3183 panel->lastChanged = WMColorListModeColorPanel;
3184 updateSwatch(panel, cpColor);
3187 static void colorListColorMenuCallback(WMWidget * w, void *data)
3189 W_ColorPanel *panel = (W_ColorPanel *) data;
3190 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3192 switch (item) {
3193 case CLmenuAdd:
3194 break;
3195 case CLmenuRename:
3196 break;
3197 case CLmenuRemove:
3198 break;
3202 static void colorListListMenuCallback(WMWidget * w, void *data)
3204 W_ColorPanel *panel = (W_ColorPanel *) data;
3205 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3207 switch (item) {
3208 case CLmenuAdd:
3209 /* New Color List */
3210 colorListListMenuNew(panel);
3211 break;
3212 case CLmenuRename:
3213 break;
3214 case CLmenuRemove:
3215 break;
3219 static void colorListListMenuNew(W_ColorPanel * panel)
3224 /*************** Panel Initialisation Functions *****************/
3226 static void wheelInit(W_ColorPanel * panel)
3228 CPColor cpColor;
3230 if (panel->color.set != cpHSV)
3231 convertCPColor(&panel->color);
3233 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3235 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3236 (1 + (panel->color.hsv.saturation / 255.0) *
3237 cos(panel->color.hsv.hue * M_PI / 180.0)));
3238 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3239 (1 + (panel->color.hsv.saturation / 255.0) *
3240 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3242 wheelCalculateValues(panel, panel->color.hsv.value);
3244 cpColor = panel->color;
3245 cpColor.hsv.value = 255;
3246 cpColor.set = cpHSV;
3247 wheelUpdateBrightnessGradient(panel, cpColor);
3250 static void grayInit(W_ColorPanel * panel)
3252 int value;
3253 char tmp[4];
3255 if (panel->color.set != cpHSV)
3256 convertCPColor(&panel->color);
3258 value = rint(panel->color.hsv.value / 2.55);
3259 WMSetSliderValue(panel->grayBrightnessS, value);
3261 sprintf(tmp, "%d", value);
3262 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3265 static void rgbInit(W_ColorPanel * panel)
3267 char tmp[4];
3269 if (panel->color.set != cpRGB)
3270 convertCPColor(&panel->color);
3272 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3273 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3274 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3276 sprintf(tmp, "%d", panel->color.rgb.red);
3277 WMSetTextFieldText(panel->rgbRedT, tmp);
3278 sprintf(tmp, "%d", panel->color.rgb.green);
3279 WMSetTextFieldText(panel->rgbGreenT, tmp);
3280 sprintf(tmp, "%d", panel->color.rgb.blue);
3281 WMSetTextFieldText(panel->rgbBlueT, tmp);
3284 static void cmykInit(W_ColorPanel * panel)
3286 int value[3];
3287 char tmp[4];
3289 if (panel->color.set != cpRGB)
3290 convertCPColor(&panel->color);
3292 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3293 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3294 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3296 WMSetSliderValue(panel->cmykCyanS, value[0]);
3297 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3298 WMSetSliderValue(panel->cmykYellowS, value[2]);
3299 WMSetSliderValue(panel->cmykBlackS, 0);
3301 sprintf(tmp, "%d", value[0]);
3302 WMSetTextFieldText(panel->cmykCyanT, tmp);
3303 sprintf(tmp, "%d", value[1]);
3304 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3305 sprintf(tmp, "%d", value[2]);
3306 WMSetTextFieldText(panel->cmykYellowT, tmp);
3307 WMSetTextFieldText(panel->cmykBlackT, "0");
3310 static void hsbInit(W_ColorPanel * panel)
3312 int value[3];
3313 char tmp[4];
3315 if (panel->color.set != cpHSV)
3316 convertCPColor(&panel->color);
3318 value[0] = panel->color.hsv.hue;
3319 value[1] = rint(panel->color.hsv.saturation / 2.55);
3320 value[2] = rint(panel->color.hsv.value / 2.55);
3322 WMSetSliderValue(panel->hsbHueS, value[0]);
3323 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3324 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3326 sprintf(tmp, "%d", value[0]);
3327 WMSetTextFieldText(panel->hsbHueT, tmp);
3328 sprintf(tmp, "%d", value[1]);
3329 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3330 sprintf(tmp, "%d", value[2]);
3331 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3333 hsbUpdateBrightnessGradient(panel);
3334 hsbUpdateSaturationGradient(panel);
3335 hsbUpdateHueGradient(panel);
3338 /************************** Common utility functions ************************/
3340 static int fetchFile(char *toPath, char *srcFile, char *destFile)
3342 FILE *src, *dst;
3343 size_t nread, nwritten;
3344 char *dstpath;
3345 char buf[BUFSIZE];
3347 RETRY( src = fopen(srcFile, "rb") )
3348 if (src == NULL) {
3349 werror(_("Could not open %s"), srcFile);
3350 return -1;
3353 dstpath = wstrconcat(toPath, destFile);
3354 RETRY( dst = fopen(dstpath, "wb") )
3355 if (dst == NULL) {
3356 werror(_("Could not create %s"), dstpath);
3357 wfree(dstpath);
3358 RETRY( fclose(src) )
3359 return -1;
3362 do {
3363 RETRY( nread = fread(buf, 1, sizeof(buf), src) )
3364 if (ferror(src))
3365 break;
3367 RETRY( nwritten = fwrite(buf, 1, nread, dst) )
3368 if (ferror(dst) || feof(src) || nread != nwritten)
3369 break;
3371 } while (1);
3373 if (ferror(src) || ferror(dst))
3374 unlink(dstpath);
3376 RETRY( fclose(src) )
3377 fsync(fileno(dst));
3378 RETRY( fclose(dst) )
3380 wfree(dstpath);
3381 return 0;
3384 char *generateNewFilename(char *curName)
3386 int n;
3387 char c;
3388 int baseLen;
3389 char *ptr;
3390 char *newName;
3392 assert(curName);
3394 ptr = curName;
3396 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3397 return wstrconcat(curName, " {1}");
3399 baseLen = ptr - curName - 1;
3401 newName = wmalloc(baseLen + 16);
3402 strncpy(newName, curName, baseLen);
3404 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3406 return newName;
3409 void convertCPColor(CPColor * color)
3411 unsigned short old_hue = 0;
3413 switch (color->set) {
3414 case cpNone:
3415 wwarning(_("Color Panel: Color unspecified"));
3416 return;
3417 case cpRGB:
3418 old_hue = color->hsv.hue;
3419 RRGBtoHSV(&(color->rgb), &(color->hsv));
3421 /* In black the hue is undefined, and may change by conversion
3422 * Same for white. */
3423 if (((color->rgb.red == 0) &&
3424 (color->rgb.green == 0) &&
3425 (color->rgb.blue == 0)) ||
3426 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3428 color->hsv.hue = old_hue;
3429 break;
3430 case cpHSV:
3431 RHSVtoRGB(&(color->hsv), &(color->rgb));
3432 break;
3436 #define ABS_SHIFT(val, shift) \
3437 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3439 RColor ulongToRColor(WMScreen * scr, unsigned long value)
3441 RColor color;
3442 XColor *xcolor = NULL;
3444 xcolor = wmalloc(sizeof(XColor));
3445 xcolor->pixel = value;
3446 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3448 color.red = xcolor->red >> 8;
3449 color.green = xcolor->green >> 8;
3450 color.blue = xcolor->blue >> 8;
3451 color.alpha = 0;
3453 wfree(xcolor);
3455 return color;
3458 unsigned char getShift(unsigned char value)
3460 unsigned char i = -1;
3462 if (value == 0)
3463 return 0;
3465 while (value) {
3466 value >>= 1;
3467 i++;
3470 return i;
3473 #ifdef SHAPE_WAS_DEFINED
3474 #undef SHAPE_WAS_DEFINED
3475 #define SHAPE
3476 #endif