- added strcasecmp() to WINGs (only on systems that don't have it)
[wmaker-crm.git] / WINGs / wcolorpanel.c
blobb51f6a52a103e376fb8751e89266fbaa3c403be7
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 ;-)
18 /* TODO:
19 * - Look at further optimization of colorWheel matrix calculation.
20 * It appears to be rather symmetric in angles of 60 degrees,
21 * while it is optimized in angles of 90 degrees.
22 * - Custom color-lists and custom colors in custom color-lists.
23 * - Stored colors
24 * - Resizing
27 #include "wconfig.h"
28 #include "WINGsP.h"
29 #include <math.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36 #include <errno.h>
38 /* BUG There's something fishy with shaped windows */
39 #if 1
40 #ifdef SHAPE
41 #define SHAPE_WAS_DEFINED
42 #undef SHAPE
43 #endif
44 #endif
47 #ifdef SHAPE
48 #include <X11/extensions/shape.h>
49 #endif
52 #ifndef PATH_MAX
53 # define PATH_MAX 1024
54 #endif
57 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
61 * Bitmaps for magnifying glass cursor
64 /* Cursor */
65 #define Cursor_x_hot 11
66 #define Cursor_y_hot 11
67 #define Cursor_width 32
68 #define Cursor_height 32
69 static unsigned char Cursor_bits[] = {
70 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
71 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
72 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
73 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
74 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
75 0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
76 0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
77 0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
78 0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
80 /* Cursor shape-mask */
81 #define Cursor_shape_width 32
82 #define Cursor_shape_height 32
83 static unsigned char Cursor_shape_bits[] = {
84 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
85 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
86 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
87 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
88 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
89 0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
90 0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
91 0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
92 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;
126 typedef struct WheelMatrix {
127 unsigned int width, height; /* Size of the colorwheel */
128 unsigned char *data[3]; /* Wheel data (R,G,B) */
129 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
130 } wheelMatrix;
132 typedef struct W_ColorPanel {
133 WMWindow *win;
134 WMFont *font8;
135 WMFont *font12;
136 void *clientData;
137 WMAction2 *action;
139 /* Common Stuff */
140 WMColorWell *colorWell;
141 WMButton *magnifyBtn;
142 WMButton *wheelBtn;
143 WMButton *slidersBtn;
144 WMButton *customPaletteBtn;
145 WMButton *colorListBtn;
147 /* Magnifying Glass */
148 MovingView *magnifyGlass;
150 /* ColorWheel Panel */
151 WMFrame *wheelFrm;
152 WMSlider *wheelBrightnessS;
153 WMView *wheelView;
155 /* Slider Panels */
156 WMFrame *slidersFrm;
157 WMFrame *seperatorFrm;
158 WMButton *grayBtn;
159 WMButton *rgbBtn;
160 WMButton *cmykBtn;
161 WMButton *hsbBtn;
162 /* Gray Scale Panel */
163 WMFrame *grayFrm;
164 WMLabel *grayMinL;
165 WMLabel *grayMaxL;
166 WMSlider *grayBrightnessS;
167 WMTextField *grayBrightnessT;
168 WMButton *grayPresetBtn[7];
170 /* RGB Panel */
171 WMFrame *rgbFrm;
172 WMLabel *rgbMinL;
173 WMLabel *rgbMaxL;
174 WMSlider *rgbRedS;
175 WMSlider *rgbGreenS;
176 WMSlider *rgbBlueS;
177 WMTextField *rgbRedT;
178 WMTextField *rgbGreenT;
179 WMTextField *rgbBlueT;
181 /* CMYK Panel */
182 WMFrame *cmykFrm;
183 WMLabel *cmykMinL;
184 WMLabel *cmykMaxL;
185 WMSlider *cmykCyanS;
186 WMSlider *cmykMagentaS;
187 WMSlider *cmykYellowS;
188 WMSlider *cmykBlackS;
189 WMTextField *cmykCyanT;
190 WMTextField *cmykMagentaT;
191 WMTextField *cmykYellowT;
192 WMTextField *cmykBlackT;
194 /* HSB Panel */
195 WMFrame *hsbFrm;
196 WMSlider *hsbHueS;
197 WMSlider *hsbSaturationS;
198 WMSlider *hsbBrightnessS;
199 WMTextField *hsbHueT;
200 WMTextField *hsbSaturationT;
201 WMTextField *hsbBrightnessT;
203 /* Custom Palette Panel*/
204 WMFrame *customPaletteFrm;
205 WMPopUpButton *customPaletteHistoryBtn;
206 WMFrame *customPaletteContentFrm;
207 WMPopUpButton *customPaletteMenuBtn;
208 WMView *customPaletteContentView;
210 /* Color List Panel */
211 WMFrame *colorListFrm;
212 WMPopUpButton *colorListHistoryBtn;
213 WMList *colorListContentLst;
214 WMPopUpButton *colorListColorMenuBtn;
215 WMPopUpButton *colorListListMenuBtn;
217 /* Look-Up Tables and Images */
218 wheelMatrix *wheelMtrx;
219 Pixmap wheelImg;
220 Pixmap selectionImg;
221 Pixmap selectionBackImg;
222 RImage *customPaletteImg;
223 char *lastBrowseDir;
225 /* Common Data Fields */
226 CPColor color; /* Current color */
227 WMColorPanelMode mode; /* Current color selection mode */
228 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
229 WMColorPanelMode lastChanged; /* Panel that last changed the color */
230 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
231 int palx, paly; /* (x,y) of sel.-marker in
232 CustomPaletteMode */
233 double palXRatio, palYRatio; /* Ratios in x & y between
234 original and scaled
235 palettesize */
236 int currentPalette;
237 char *configurationPath;
239 struct {
240 unsigned int continuous:1;
241 unsigned int dragging:1;
242 } flags;
243 } W_ColorPanel;
245 enum {
246 CPmenuNewFromFile,
247 CPmenuRename,
248 CPmenuRemove,
249 CPmenuCopy,
250 CPmenuNewFromClipboard
251 } customPaletteMenuItem;
253 enum {
254 CLmenuAdd,
255 CLmenuRename,
256 CLmenuRemove
257 } colorListMenuItem;
260 #define PWIDTH 194
261 #define PHEIGHT 266
262 #define colorWheelSize 150
263 #define customPaletteWidth 182
264 #define customPaletteHeight 106
265 #define knobThickness 8
267 #define SPECTRUM_WIDTH 511
268 #define SPECTRUM_HEIGHT 360
270 #define COLORWHEEL_PART 1
271 #define CUSTOMPALETTE_PART 2
272 #define BUFSIZE 1024
274 #ifndef RGBTXT
275 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
276 #endif
278 #define MAX_LENGTH 1024
281 #ifndef M_PI
282 #define M_PI 3.14159265358979323846
283 #endif
286 static int fetchFile(char* toPath, char *imageSrcFile,
287 char *imageDestFileName);
288 char *generateNewFilename(char *curName);
289 void convertCPColor(CPColor *color);
290 RColor ulongToRColor(WMScreen *scr, unsigned long value);
291 unsigned char getShift(unsigned char value);
293 static void modeButtonCallback(WMWidget *w, void *data);
294 static int getPickerPart(W_ColorPanel *panel, int x, int y);
295 static void readConfiguration(W_ColorPanel *panel);
296 static void readXColors(W_ColorPanel *panel);
298 static void closeWindowCallback(WMWidget *w, void *data);
300 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
301 static WMPoint magnifyInitialize(W_ColorPanel *panel);
302 static void magnifyPutCursor(WMWidget *w, void *data);
303 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
304 static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1,
305 int x2, int y2);
306 static XImage* magnifyGetImage(WMScreen *scr, XImage *image, int x, int y,
307 int w, int h);
309 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
310 static void wheelDestroyMatrix(wheelMatrix *matrix);
311 static void wheelInitMatrix(W_ColorPanel *panel);
312 static void wheelCalculateValues(W_ColorPanel *panel, int maxvalue);
313 static void wheelRender(W_ColorPanel *panel);
314 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
315 static void wheelPaint(W_ColorPanel *panel);
317 static void wheelHandleEvents(XEvent *event, void *data);
318 static void wheelHandleActionEvents(XEvent *event, void *data);
319 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
320 static void wheelUpdateSelection(W_ColorPanel *panel);
321 static void wheelUndrawSelection(W_ColorPanel *panel);
323 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
324 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
325 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
326 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor);
328 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
329 static void grayPresetButtonCallback(WMWidget *w, void *data);
330 static void grayBrightnessTextFieldCallback(void *observerData,
331 WMNotification *notification);
333 static void rgbSliderCallback(WMWidget *w, void *data);
334 static void rgbTextFieldCallback(void *observerData,
335 WMNotification *notification);
337 static void cmykSliderCallback(WMWidget *w, void *data);
338 static void cmykTextFieldCallback(void *observerData,
339 WMNotification *notification);
341 static void hsbSliderCallback(WMWidget *w, void *data);
342 static void hsbTextFieldCallback(void *observerData,
343 WMNotification *notification);
344 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
345 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
346 static void hsbUpdateHueGradient(W_ColorPanel *panel);
348 static void customRenderSpectrum(W_ColorPanel *panel);
349 static void customSetPalette(W_ColorPanel *panel);
350 static void customPaletteHandleEvents(XEvent *event, void *data);
351 static void customPaletteHandleActionEvents(XEvent *event, void *data);
352 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
353 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
354 int x, int y);
355 static void customPaletteMenuCallback(WMWidget *w, void *data);
356 static void customPaletteHistoryCallback(WMWidget *w, void *data);
358 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
359 static void customPaletteMenuRename(W_ColorPanel *panel);
360 static void customPaletteMenuRemove(W_ColorPanel *panel);
362 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
363 int state, WMRect *rect);
364 static void colorListSelect(WMWidget *w, void *data);
365 static void colorListColorMenuCallback(WMWidget *w, void *data);
366 static void colorListListMenuCallback(WMWidget *w, void *data);
367 static void colorListListMenuNew(W_ColorPanel *panel);
369 static void wheelInit(W_ColorPanel *panel);
370 static void grayInit(W_ColorPanel *panel);
371 static void rgbInit(W_ColorPanel *panel);
372 static void cmykInit(W_ColorPanel *panel);
373 static void hsbInit(W_ColorPanel *panel);
377 void
378 WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
380 panel->action = action;
381 panel->clientData = data;
384 static WMColorPanel*
385 makeColorPanel(WMScreen *scrPtr, char *name)
387 WMColorPanel *panel;
388 RImage *image;
389 WMPixmap *pixmap;
390 RColor from;
391 RColor to;
392 WMColor *textcolor, *graybuttoncolor;
393 int i;
394 GC bgc = WMColorGC(scrPtr->black);
395 GC wgc = WMColorGC(scrPtr->white);
398 panel = wmalloc(sizeof(WMColorPanel));
399 memset(panel, 0, sizeof(WMColorPanel));
401 panel->color.rgb.red = 0;
402 panel->color.rgb.green = 0;
403 panel->color.rgb.blue = 0;
404 panel->color.hsv.hue = 0;
405 panel->color.hsv.saturation = 0;
406 panel->color.hsv.value = 0;
407 panel->color.set = cpNone; /* Color has not been set yet */
409 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
410 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
412 panel->win = WMCreateWindowWithStyle(scrPtr, name,
413 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
414 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
415 WMSetWindowTitle(panel->win, _("Colors"));
416 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
419 /* Set Default ColorPanel Mode(s) */
420 panel->mode = WMWheelModeColorPanel;
421 panel->lastChanged = 0;
422 panel->slidersmode = WMRGBModeColorPanel;
423 panel->configurationPath = wstrconcat(wusergnusteppath(),
424 "/Library/Colors/");
426 /* Some General Purpose Widgets */
427 panel->colorWell = WMCreateColorWell(panel->win);
428 WMResizeWidget(panel->colorWell, 134, 36);
429 WSetColorWellBordered(panel->colorWell, False);
430 WMMoveWidget(panel->colorWell, 56, 4);
432 panel->magnifyBtn = WMCreateCustomButton(panel->win,
433 WBBStateLightMask|WBBStateChangeMask);
434 WMResizeWidget(panel->magnifyBtn, 46, 36);
435 WMMoveWidget(panel->magnifyBtn, 6,4);
436 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
437 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
438 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
440 panel->wheelBtn = WMCreateCustomButton(panel->win,
441 WBBStateLightMask|WBBStateChangeMask);
442 WMResizeWidget(panel->wheelBtn, 46, 32);
443 WMMoveWidget(panel->wheelBtn, 6, 44);
444 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
445 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
446 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
448 panel->slidersBtn = WMCreateCustomButton(panel->win,
449 WBBStateLightMask|WBBStateChangeMask);
450 WMResizeWidget(panel->slidersBtn, 46, 32);
451 WMMoveWidget(panel->slidersBtn, 52, 44);
452 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
453 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
454 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
456 panel->customPaletteBtn = WMCreateCustomButton(panel->win,
457 WBBStateLightMask|WBBStateChangeMask);
458 WMResizeWidget(panel->customPaletteBtn, 46, 32);
459 WMMoveWidget(panel->customPaletteBtn, 98, 44);
460 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
461 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
462 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
464 panel->colorListBtn = WMCreateCustomButton(panel->win,
465 WBBStateLightMask|WBBStateChangeMask);
466 WMResizeWidget(panel->colorListBtn, 46, 32);
467 WMMoveWidget(panel->colorListBtn, 144, 44);
468 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
469 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
470 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
472 /* Let's Group some of them together */
473 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
474 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
475 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
477 /* Widgets for the ColorWheel Panel */
478 panel->wheelFrm = WMCreateFrame(panel->win);
479 WMSetFrameRelief(panel->wheelFrm, WRFlat);
480 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
481 WMMoveWidget(panel->wheelFrm, 5, 80);
483 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
484 /* XXX Can we create a view ? */
485 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
486 W_MoveView(panel->wheelView, 0, 0);
488 /* Create an event handler to handle expose/click events in ColorWheel */
489 WMCreateEventHandler(panel->wheelView,
490 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
491 LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
493 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
494 panel);
496 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
497 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
498 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
499 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
500 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
501 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
502 panel);
503 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
505 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
506 wheelInitMatrix(panel);
509 /* Widgets for the Slider Panels */
510 panel->slidersFrm = WMCreateFrame(panel->win);
511 WMSetFrameRelief(panel->slidersFrm, WRFlat);
512 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
513 WMMoveWidget(panel->slidersFrm, 4, 80);
515 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
516 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
517 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
518 WMMoveWidget(panel->seperatorFrm, 0, 1);
520 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
521 WBBStateLightMask|WBBStateChangeMask);
522 WMResizeWidget(panel->grayBtn, 46, 24);
523 WMMoveWidget(panel->grayBtn, 1, 8);
524 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
525 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
526 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
528 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
529 WBBStateLightMask|WBBStateChangeMask);
530 WMResizeWidget(panel->rgbBtn, 46, 24);
531 WMMoveWidget(panel->rgbBtn, 47, 8);
532 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
533 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
534 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
536 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
537 WBBStateLightMask|WBBStateChangeMask);
538 WMResizeWidget(panel->cmykBtn, 46, 24);
539 WMMoveWidget(panel->cmykBtn, 93, 8);
540 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
541 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
542 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
544 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
545 WBBStateLightMask|WBBStateChangeMask);
546 WMResizeWidget(panel->hsbBtn, 46, 24);
547 WMMoveWidget(panel->hsbBtn, 139, 8);
548 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
549 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
550 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
552 /* Let's Group the Slider Panel Buttons Together */
553 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
554 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
555 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
557 textcolor = WMDarkGrayColor(scrPtr);
559 /* Widgets for GrayScale Panel */
560 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
561 WMSetFrameRelief(panel->grayFrm, WRFlat);
562 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
563 WMMoveWidget(panel->grayFrm, 0, 34);
565 panel->grayMinL = WMCreateLabel(panel->grayFrm);
566 WMResizeWidget(panel->grayMinL, 20, 10);
567 WMMoveWidget(panel->grayMinL, 2, 2);
568 WMSetLabelText(panel->grayMinL, "0");
569 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
570 WMSetLabelTextColor(panel->grayMinL, textcolor);
571 WMSetLabelFont(panel->grayMinL, panel->font8);
573 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
574 WMResizeWidget(panel->grayMaxL, 40, 10);
575 WMMoveWidget(panel->grayMaxL, 104, 2);
576 WMSetLabelText(panel->grayMaxL, "100");
577 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
578 WMSetLabelTextColor(panel->grayMaxL, textcolor);
579 WMSetLabelFont(panel->grayMaxL, panel->font8);
581 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
582 WMResizeWidget(panel->grayBrightnessS, 141, 16);
583 WMMoveWidget(panel->grayBrightnessS, 2, 14);
584 WMSetSliderMinValue(panel->grayBrightnessS, 0);
585 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
586 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
587 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
588 panel);
590 from.red = 0;
591 from.green = 0;
592 from.blue = 0;
594 to.red = 255;
595 to.green = 255;
596 to.blue = 255;
598 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
599 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
600 RReleaseImage(image);
602 if (pixmap)
603 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
604 panel->font12, 2, 0, 100, WALeft, WMColorGC(scrPtr->white),
605 False, _("Brightness"), strlen(_("Brightness")));
606 else
607 wwarning(_("Color Panel: Could not allocate memory"));
609 WMSetSliderImage(panel->grayBrightnessS, pixmap);
610 WMReleasePixmap(pixmap);
612 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
613 WMResizeWidget(panel->grayBrightnessT, 40, 18);
614 WMMoveWidget(panel->grayBrightnessT, 146, 13);
615 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
616 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
617 WMTextDidEndEditingNotification, panel->grayBrightnessT);
619 for (i=0; i < 7; i++) {
620 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
622 graybuttoncolor = WMCreateRGBColor(scrPtr, (255/6)*i << 8,
623 (255/6)*i << 8, (255/6)*i << 8, True);
624 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
625 WMReleaseColor(graybuttoncolor);
627 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
628 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
629 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
630 WMSetButtonAction(panel->grayPresetBtn[i],
631 grayPresetButtonCallback, panel);
632 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
633 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
634 WMReleasePixmap(pixmap);
638 /* End of GrayScale Panel */
640 /* Widgets for RGB Panel */
641 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
642 WMSetFrameRelief(panel->rgbFrm, WRFlat);
643 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
644 WMMoveWidget(panel->rgbFrm, 0, 34);
646 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
647 WMResizeWidget(panel->rgbMinL, 20, 10);
648 WMMoveWidget(panel->rgbMinL, 2, 2);
649 WMSetLabelText(panel->rgbMinL, "0");
650 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
651 WMSetLabelTextColor(panel->rgbMinL, textcolor);
652 WMSetLabelFont(panel->rgbMinL, panel->font8);
654 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
655 WMResizeWidget(panel->rgbMaxL, 40, 10);
656 WMMoveWidget(panel->rgbMaxL, 104, 2);
657 WMSetLabelText(panel->rgbMaxL, "255");
658 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
659 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
660 WMSetLabelFont(panel->rgbMaxL, panel->font8);
662 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
663 WMResizeWidget(panel->rgbRedS, 141, 16);
664 WMMoveWidget(panel->rgbRedS, 2, 14);
665 WMSetSliderMinValue(panel->rgbRedS, 0);
666 WMSetSliderMaxValue(panel->rgbRedS, 255);
667 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
668 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
670 to.red = 255;
671 to.green = 0;
672 to.blue = 0;
674 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
675 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
676 RReleaseImage(image);
678 if (pixmap)
679 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
680 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, _("Red"),
681 strlen(_("Red")));
682 else
683 wwarning(_("Color Panel: Could not allocate memory"));
685 WMSetSliderImage(panel->rgbRedS, pixmap);
686 WMReleasePixmap(pixmap);
688 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
689 WMResizeWidget(panel->rgbRedT, 40, 18);
690 WMMoveWidget(panel->rgbRedT, 146, 13);
691 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
692 WMAddNotificationObserver(rgbTextFieldCallback, panel,
693 WMTextDidEndEditingNotification, panel->rgbRedT);
695 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
696 WMResizeWidget(panel->rgbGreenS, 141, 16);
697 WMMoveWidget(panel->rgbGreenS, 2, 36);
698 WMSetSliderMinValue(panel->rgbGreenS, 0);
699 WMSetSliderMaxValue(panel->rgbGreenS, 255);
700 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
701 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
703 to.red = 0;
704 to.green = 255;
705 to.blue = 0;
707 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
708 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
709 RReleaseImage(image);
711 if (pixmap)
712 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
713 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, _("Green"),
714 strlen(_("Green")));
715 else
716 wwarning(_("Color Panel: Could not allocate memory"));
718 WMSetSliderImage(panel->rgbGreenS, pixmap);
719 WMReleasePixmap(pixmap);
721 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
722 WMResizeWidget(panel->rgbGreenT, 40, 18);
723 WMMoveWidget(panel->rgbGreenT, 146, 35);
724 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
725 WMAddNotificationObserver(rgbTextFieldCallback, panel,
726 WMTextDidEndEditingNotification, panel->rgbGreenT);
729 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
730 WMResizeWidget(panel->rgbBlueS, 141, 16);
731 WMMoveWidget(panel->rgbBlueS, 2, 58);
732 WMSetSliderMinValue(panel->rgbBlueS, 0);
733 WMSetSliderMaxValue(panel->rgbBlueS, 255);
734 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
735 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
737 to.red = 0;
738 to.green = 0;
739 to.blue = 255;
741 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
742 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
743 RReleaseImage(image);
745 if (pixmap)
746 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
747 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, _("Blue"),
748 strlen(_("Blue")));
749 else
750 wwarning(_("Color Panel: Could not allocate memory"));
752 WMSetSliderImage(panel->rgbBlueS, pixmap);
753 WMReleasePixmap(pixmap);
755 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
756 WMResizeWidget(panel->rgbBlueT, 40, 18);
757 WMMoveWidget(panel->rgbBlueT, 146, 57);
758 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
759 WMAddNotificationObserver(rgbTextFieldCallback, panel,
760 WMTextDidEndEditingNotification, panel->rgbBlueT);
761 /* End of RGB Panel */
763 /* Widgets for CMYK Panel */
764 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
765 WMSetFrameRelief(panel->cmykFrm, WRFlat);
766 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
767 WMMoveWidget(panel->cmykFrm, 0, 34);
769 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
770 WMResizeWidget(panel->cmykMinL, 20, 10);
771 WMMoveWidget(panel->cmykMinL, 2, 2);
772 WMSetLabelText(panel->cmykMinL, "0");
773 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
774 WMSetLabelTextColor(panel->cmykMinL, textcolor);
775 WMSetLabelFont(panel->cmykMinL, panel->font8);
777 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
778 WMResizeWidget(panel->cmykMaxL, 40, 10);
779 WMMoveWidget(panel->cmykMaxL, 104, 2);
780 WMSetLabelText(panel->cmykMaxL, "100");
781 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
782 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
783 WMSetLabelFont(panel->cmykMaxL, panel->font8);
785 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
786 WMResizeWidget(panel->cmykCyanS, 141, 16);
787 WMMoveWidget(panel->cmykCyanS, 2, 14);
788 WMSetSliderMinValue(panel->cmykCyanS, 0);
789 WMSetSliderMaxValue(panel->cmykCyanS, 100);
790 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
791 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
793 from.red = 255;
794 from.green = 255;
795 from.blue = 255;
797 to.red = 0;
798 to.green = 255;
799 to.blue = 255;
801 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
802 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
803 RReleaseImage(image);
805 if (pixmap)
806 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
807 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, _("Cyan"),
808 strlen(_("Cyan")));
809 else
810 wwarning(_("Color Panel: Could not allocate memory"));
812 WMSetSliderImage(panel->cmykCyanS, pixmap);
813 WMReleasePixmap(pixmap);
815 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
816 WMResizeWidget(panel->cmykCyanT, 40, 18);
817 WMMoveWidget(panel->cmykCyanT, 146, 13);
818 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
819 WMAddNotificationObserver(cmykTextFieldCallback, panel,
820 WMTextDidEndEditingNotification, panel->cmykCyanT);
823 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
824 WMResizeWidget(panel->cmykMagentaS, 141, 16);
825 WMMoveWidget(panel->cmykMagentaS, 2, 36);
826 WMSetSliderMinValue(panel->cmykMagentaS, 0);
827 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
828 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
829 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
831 to.red = 255;
832 to.green = 0;
833 to.blue = 255;
835 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
836 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
837 RReleaseImage(image);
839 if (pixmap)
840 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
841 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, _("Magenta"),
842 strlen(_("Magenta")));
843 else
844 wwarning(_("Color Panel: Could not allocate memory"));
846 WMSetSliderImage(panel->cmykMagentaS, pixmap);
847 WMReleasePixmap(pixmap);
849 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
850 WMResizeWidget(panel->cmykMagentaT, 40, 18);
851 WMMoveWidget(panel->cmykMagentaT, 146, 35);
852 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
853 WMAddNotificationObserver(cmykTextFieldCallback, panel,
854 WMTextDidEndEditingNotification, panel->cmykMagentaT);
857 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
858 WMResizeWidget(panel->cmykYellowS, 141, 16);
859 WMMoveWidget(panel->cmykYellowS, 2, 58);
860 WMSetSliderMinValue(panel->cmykYellowS, 0);
861 WMSetSliderMaxValue(panel->cmykYellowS, 100);
862 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
863 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
865 to.red = 255;
866 to.green = 255;
867 to.blue = 0;
869 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
870 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
871 RReleaseImage(image);
873 if (pixmap)
874 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
875 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, _("Yellow"),
876 strlen(_("Yellow")));
877 else
878 wwarning(_("Color Panel: Could not allocate memory"));
880 WMSetSliderImage(panel->cmykYellowS, pixmap);
881 WMReleasePixmap(pixmap);
883 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
884 WMResizeWidget(panel->cmykYellowT, 40, 18);
885 WMMoveWidget(panel->cmykYellowT, 146, 57);
886 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
887 WMAddNotificationObserver(cmykTextFieldCallback, panel,
888 WMTextDidEndEditingNotification, panel->cmykYellowT);
891 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
892 WMResizeWidget(panel->cmykBlackS, 141, 16);
893 WMMoveWidget(panel->cmykBlackS, 2, 80);
894 WMSetSliderMinValue(panel->cmykBlackS, 0);
895 WMSetSliderMaxValue(panel->cmykBlackS, 100);
896 WMSetSliderValue(panel->cmykBlackS, 0);
897 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
898 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
900 to.red = 0;
901 to.green = 0;
902 to.blue = 0;
904 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
905 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
906 RReleaseImage(image);
908 if (pixmap)
909 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
910 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, _("Black"),
911 strlen(_("Black")));
912 else
913 wwarning(_("Color Panel: Could not allocate memory"));
915 WMSetSliderImage(panel->cmykBlackS, pixmap);
916 WMReleasePixmap(pixmap);
918 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
919 WMResizeWidget(panel->cmykBlackT, 40, 18);
920 WMMoveWidget(panel->cmykBlackT, 146, 79);
921 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
922 WMAddNotificationObserver(cmykTextFieldCallback, panel,
923 WMTextDidEndEditingNotification, panel->cmykBlackT);
924 /* End of CMYK Panel */
926 /* Widgets for HSB Panel */
927 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
928 WMSetFrameRelief(panel->hsbFrm, WRFlat);
929 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
930 WMMoveWidget(panel->hsbFrm, 0, 34);
932 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
933 WMResizeWidget(panel->hsbHueS, 141, 16);
934 WMMoveWidget(panel->hsbHueS, 2, 14);
935 WMSetSliderMinValue(panel->hsbHueS, 0);
936 WMSetSliderMaxValue(panel->hsbHueS, 359);
937 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
938 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
940 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
941 WMResizeWidget(panel->hsbHueT, 40, 18);
942 WMMoveWidget(panel->hsbHueT, 146, 13);
943 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
944 WMAddNotificationObserver(hsbTextFieldCallback, panel,
945 WMTextDidEndEditingNotification, panel->hsbHueT);
948 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
949 WMResizeWidget(panel->hsbSaturationS, 141, 16);
950 WMMoveWidget(panel->hsbSaturationS, 2, 36);
951 WMSetSliderMinValue(panel->hsbSaturationS, 0);
952 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
953 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
954 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
956 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
957 WMResizeWidget(panel->hsbSaturationT, 40, 18);
958 WMMoveWidget(panel->hsbSaturationT, 146, 35);
959 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
960 WMAddNotificationObserver(hsbTextFieldCallback, panel,
961 WMTextDidEndEditingNotification, panel->hsbSaturationT);
964 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
965 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
966 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
967 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
968 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
969 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
970 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
972 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
973 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
974 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
975 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
976 WMAddNotificationObserver(hsbTextFieldCallback, panel,
977 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
978 /* End of HSB Panel */
981 WMReleaseColor(textcolor);
983 /* Widgets for the CustomPalette Panel */
984 panel->customPaletteFrm = WMCreateFrame(panel->win);
985 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
986 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
987 WMMoveWidget(panel->customPaletteFrm, 5, 80);
989 panel->customPaletteHistoryBtn = WMCreatePopUpButton(
990 panel->customPaletteFrm);
991 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
992 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
993 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
994 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
995 customPaletteHistoryCallback, panel);
996 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
997 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
999 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
1000 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
1001 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
1002 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
1004 panel->customPaletteContentView = W_CreateView(
1005 W_VIEW(panel->customPaletteContentFrm));
1006 /* XXX Test if we can create a view */
1007 W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
1008 customPaletteHeight);
1009 W_MoveView(panel->customPaletteContentView, 2, 2);
1011 /* Create event handler to handle expose/click events in CustomPalette */
1012 WMCreateEventHandler(panel->customPaletteContentView,
1013 ButtonPressMask|ButtonReleaseMask|EnterWindowMask| LeaveWindowMask |
1014 ButtonMotionMask, customPaletteHandleActionEvents, panel);
1016 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
1017 customPaletteHandleEvents, panel);
1019 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
1020 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
1021 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
1022 WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
1023 customPaletteMenuCallback, panel);
1024 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
1025 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
1027 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
1028 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
1029 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
1030 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
1031 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
1033 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
1034 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
1035 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
1036 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
1037 CPmenuNewFromClipboard, 0);
1039 customRenderSpectrum(panel);
1040 panel->currentPalette = 0;
1041 panel->palx = customPaletteWidth/2;
1042 panel->paly = customPaletteHeight/2;
1045 /* Widgets for the ColorList Panel */
1046 panel->colorListFrm = WMCreateFrame(panel->win);
1047 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1048 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1049 WMMoveWidget(panel->colorListFrm, 5, 80);
1051 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1052 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1053 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1054 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
1055 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1056 * colorListHistoryCallback, panel); */
1057 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1058 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1060 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1061 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1062 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1063 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1064 WMMoveWidget(panel->colorListContentLst, 0, 23);
1065 WMHangData(panel->colorListContentLst, panel);
1067 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1068 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1069 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1070 WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
1071 colorListColorMenuCallback, panel);
1072 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
1073 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1075 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1076 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1077 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1079 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1080 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1081 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1083 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1084 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1085 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1086 WMSetPopUpButtonAction(panel->colorListListMenuBtn,
1087 colorListListMenuCallback, panel);
1088 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
1089 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
1090 PHEIGHT - 130);
1092 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1093 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1094 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1096 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1097 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1098 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1100 WMRealizeWidget(panel->win);
1101 WMMapSubwidgets(panel->win);
1103 WMMapSubwidgets(panel->wheelFrm);
1104 WMMapSubwidgets(panel->slidersFrm);
1105 WMMapSubwidgets(panel->grayFrm);
1106 WMMapSubwidgets(panel->rgbFrm);
1107 WMMapSubwidgets(panel->cmykFrm);
1108 WMMapSubwidgets(panel->hsbFrm);
1109 WMMapSubwidgets(panel->customPaletteFrm);
1110 WMMapSubwidgets(panel->customPaletteContentFrm);
1111 WMMapSubwidgets(panel->colorListFrm);
1113 /* Pixmap to indicate selection positions
1114 * wheelframe MUST be mapped.
1116 panel->selectionImg = XCreatePixmap(scrPtr->display,
1117 WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1118 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1119 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1121 readConfiguration(panel);
1122 readXColors(panel);
1124 return panel;
1128 WMColorPanel*
1129 WMGetColorPanel(WMScreen *scrPtr)
1131 WMColorPanel *panel;
1133 if (scrPtr->sharedColorPanel)
1134 return scrPtr->sharedColorPanel;
1136 panel = makeColorPanel(scrPtr, "colorPanel");
1138 scrPtr->sharedColorPanel = panel;
1140 return panel;
1144 void
1145 WMFreeColorPanel(WMColorPanel *panel)
1147 W_Screen *scr = WMWidgetScreen(panel->win);
1149 if (panel == scr->sharedColorPanel) {
1150 scr->sharedColorPanel = NULL;
1153 if (!panel)
1154 return;
1156 WMRemoveNotificationObserver(panel);
1157 WMUnmapWidget(panel->win);
1159 /* fonts */
1160 WMReleaseFont(panel->font8);
1161 WMReleaseFont(panel->font12);
1163 /* pixmaps */
1164 wheelDestroyMatrix(panel->wheelMtrx);
1165 if (panel->wheelImg)
1166 XFreePixmap(scr->display, panel->wheelImg);
1167 if (panel->selectionImg)
1168 XFreePixmap(scr->display, panel->selectionImg);
1169 if (panel->selectionBackImg)
1170 XFreePixmap(scr->display, panel->selectionBackImg);
1171 RReleaseImage(panel->customPaletteImg);
1173 /* structs */
1174 if (panel->lastBrowseDir)
1175 wfree(panel->lastBrowseDir);
1176 if (panel->configurationPath)
1177 wfree(panel->configurationPath);
1179 WMDestroyWidget(panel->win);
1181 wfree(panel);
1185 void
1186 WMCloseColorPanel(WMColorPanel *panel)
1188 WMFreeColorPanel(panel);
1192 void
1193 WMShowColorPanel(WMColorPanel *panel)
1195 WMScreen *scr = WMWidgetScreen(panel->win);
1196 WMColor *white = WMWhiteColor(scr);
1198 if (panel->color.set == cpNone)
1199 WMSetColorPanelColor(panel, white);
1200 WMReleaseColor(white);
1202 if (panel->mode != WMWheelModeColorPanel)
1203 WMPerformButtonClick(panel->wheelBtn);
1205 WMMapWidget(panel->win);
1209 static void
1210 closeWindowCallback(WMWidget *w, void *data)
1212 W_ColorPanel *panel = (W_ColorPanel*)data;
1214 WMCloseColorPanel(panel);
1218 static void
1219 readConfiguration(W_ColorPanel *panel)
1221 /* XXX Doesn't take care of "invalid" files */
1223 DIR *dPtr;
1224 struct dirent *dp;
1225 struct stat stat_buf;
1226 int item;
1228 if (stat(panel->configurationPath, &stat_buf)!=0) {
1229 if (mkdir(panel->configurationPath,
1230 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1231 wsyserror(_("Color Panel: Could not create directory %s needed"
1232 " to store configurations"), panel->configurationPath);
1233 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1234 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1235 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1236 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1237 _("File Error"),
1238 _("Could not create ColorPanel configuration directory"),
1239 _("OK"), NULL, NULL);
1241 return;
1244 if (!(dPtr = opendir(panel->configurationPath))) {
1245 wwarning(_("Color Panel: Could not find file"), "%s", panel->configurationPath);
1246 return;
1249 while ((dp = readdir(dPtr)) != NULL) {
1250 unsigned int perm_mask;
1251 char *path = wstrconcat(panel->configurationPath,
1252 dp->d_name);
1254 if (dp->d_name[0] != '.') {
1255 item = WMGetPopUpButtonNumberOfItems(
1256 panel->customPaletteHistoryBtn);
1257 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1259 perm_mask = (access(path, R_OK) == 0);
1260 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn,
1261 item, perm_mask);
1263 wfree(path);
1265 (void)closedir(dPtr);
1269 static void
1270 readXColors(W_ColorPanel *panel)
1272 struct stat stat_buf;
1273 FILE *rgbtxt;
1274 char line[MAX_LENGTH];
1275 int red, green, blue;
1276 char name[48];
1277 RColor *color;
1278 WMListItem *item;
1280 if (stat(RGBTXT, &stat_buf) != 0) {
1281 wsyserror(_("Color Panel: Could not find file"), " %s", RGBTXT);
1282 return;
1284 else {
1285 if ((rgbtxt = fopen(RGBTXT, "r"))) {
1286 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1287 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1288 color = wmalloc(sizeof(RColor));
1289 color->red = (unsigned char)red;
1290 color->green = (unsigned char)green;
1291 color->blue = (unsigned char)blue;
1292 item = WMAddListItem(panel->colorListContentLst, name);
1293 item->clientData = (void *)color;
1296 fclose(rgbtxt);
1298 else {
1299 wsyserror(_("Color Panel: Could not find file"), "%s", RGBTXT);
1305 void
1306 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1308 W_Screen *scr = WMWidgetScreen(panel->win);
1310 if (mode != WMWheelModeColorPanel) {
1311 WMUnmapWidget(panel->wheelFrm);
1312 if (panel->selectionBackImg) {
1313 XFreePixmap(WMWidgetScreen(panel->win)->display,
1314 panel->selectionBackImg);
1315 panel->selectionBackImg = None;
1318 if (mode != WMGrayModeColorPanel)
1319 WMUnmapWidget(panel->grayFrm);
1320 if (mode != WMRGBModeColorPanel)
1321 WMUnmapWidget(panel->rgbFrm);
1322 if (mode != WMCMYKModeColorPanel)
1323 WMUnmapWidget(panel->cmykFrm);
1324 if (mode != WMHSBModeColorPanel)
1325 WMUnmapWidget(panel->hsbFrm);
1326 if (mode != WMCustomPaletteModeColorPanel) {
1327 WMUnmapWidget(panel->customPaletteFrm);
1328 if (panel->selectionBackImg) {
1329 XFreePixmap(WMWidgetScreen(panel->win)->display,
1330 panel->selectionBackImg);
1331 panel->selectionBackImg = None;
1334 if (mode != WMColorListModeColorPanel)
1335 WMUnmapWidget(panel->colorListFrm);
1336 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1337 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1338 WMUnmapWidget(panel->slidersFrm);
1339 else
1340 panel->slidersmode = mode;
1342 if (mode == WMWheelModeColorPanel) {
1343 WMMapWidget(panel->wheelFrm);
1344 WMSetButtonSelected(panel->wheelBtn, True);
1345 if (panel->lastChanged != WMWheelModeColorPanel)
1346 wheelInit(panel);
1347 wheelRender(panel);
1348 wheelPaint(panel);
1349 } else if (mode == WMGrayModeColorPanel) {
1350 WMMapWidget(panel->slidersFrm);
1351 WMSetButtonSelected(panel->slidersBtn, True);
1352 WMMapWidget(panel->grayFrm);
1353 WMSetButtonSelected(panel->grayBtn, True);
1354 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1355 if (panel->lastChanged != WMGrayModeColorPanel)
1356 grayInit(panel);
1357 } else if (mode == WMRGBModeColorPanel) {
1358 WMMapWidget(panel->slidersFrm);
1359 WMSetButtonSelected(panel->slidersBtn, True);
1360 WMMapWidget(panel->rgbFrm);
1361 WMSetButtonSelected(panel->rgbBtn, True);
1362 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1363 if (panel->lastChanged != WMRGBModeColorPanel)
1364 rgbInit(panel);
1365 } else if (mode == WMCMYKModeColorPanel) {
1366 WMMapWidget(panel->slidersFrm);
1367 WMSetButtonSelected(panel->slidersBtn, True);
1368 WMMapWidget(panel->cmykFrm);
1369 WMSetButtonSelected(panel->cmykBtn, True);
1370 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1371 if (panel->lastChanged != WMCMYKModeColorPanel)
1372 cmykInit(panel);
1373 } else if (mode == WMHSBModeColorPanel) {
1374 WMMapWidget(panel->slidersFrm);
1375 WMSetButtonSelected(panel->slidersBtn, True);
1376 WMMapWidget(panel->hsbFrm);
1377 WMSetButtonSelected(panel->hsbBtn, True);
1378 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1379 if (panel->lastChanged != WMHSBModeColorPanel)
1380 hsbInit(panel);
1381 } else if (mode == WMCustomPaletteModeColorPanel) {
1382 WMMapWidget(panel->customPaletteFrm);
1383 WMSetButtonSelected(panel->customPaletteBtn, True);
1384 customSetPalette(panel);
1385 } else if (mode == WMColorListModeColorPanel) {
1386 WMMapWidget(panel->colorListFrm);
1387 WMSetButtonSelected(panel->colorListBtn, True);
1390 panel->mode = mode;
1394 WMColor*
1395 WMGetColorPanelColor(WMColorPanel *panel)
1397 return WMGetColorWellColor(panel->colorWell);
1401 void
1402 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1404 WMSetColorWellColor(panel->colorWell, color);
1406 panel->color.rgb.red = color->color.red >> 8;
1407 panel->color.rgb.green = color->color.green >> 8;
1408 panel->color.rgb.blue = color->color.blue >> 8;
1409 panel->color.set = cpRGB;
1411 if (panel->mode == panel->lastChanged)
1412 panel->lastChanged = 0;
1414 WMSetColorPanelPickerMode(panel, panel->mode);
1418 static void
1419 updateSwatch(WMColorPanel *panel, CPColor color)
1421 WMScreen *scr = WMWidgetScreen(panel->win);
1422 WMColor *wellcolor;
1424 if (color.set != cpRGB)
1425 convertCPColor(&color);
1427 panel->color = color;
1429 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8,
1430 color.rgb.green << 8,
1431 color.rgb.blue << 8, True);
1433 WMSetColorWellColor(panel->colorWell, wellcolor);
1434 WMReleaseColor(wellcolor);
1436 if (!panel->flags.dragging || panel->flags.continuous) {
1437 if (panel->action)
1438 (*panel->action)(panel, panel->clientData);
1440 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1441 NULL);
1445 static void
1446 modeButtonCallback(WMWidget *w, void *data)
1448 W_ColorPanel *panel = (W_ColorPanel*)(data);
1450 if (w == panel->wheelBtn)
1451 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1452 else if (w == panel->slidersBtn)
1453 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1454 else if (w == panel->customPaletteBtn)
1455 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1456 else if (w == panel->colorListBtn)
1457 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1458 else if (w == panel->grayBtn)
1459 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1460 else if (w == panel->rgbBtn)
1461 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1462 else if (w == panel->cmykBtn)
1463 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1464 else if (w == panel->hsbBtn)
1465 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1469 /****************** Magnifying Cursor Functions *******************/
1471 static XImage*
1472 magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
1474 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1475 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1476 displayHeight = DisplayHeight(scr->display, scr->screen);
1478 if (!(image && image->data)) {
1479 /* The image in panel->magnifyGlass->image does not exist yet.
1480 * Grab one from the screen (not beyond) and use it from now on.
1482 if (!(image = XGetImage(scr->display, scr->rootWin,
1483 x - Cursor_x_hot,
1484 y - Cursor_y_hot,
1485 w, h, AllPlanes, ZPixmap)))
1486 wwarning(_("Color Panel: X failed request"));
1488 return image;
1491 /* Coordinate correction for back pixmap
1492 * if magnifying glass is at screen-borders
1495 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1496 * Hatched area is beyond screen border.
1498 * |<-Cursor_x_hot->|
1499 * ________________|_____
1500 * |/ / / / / / /| | |
1501 * | / / / / / / |(x,y) |
1502 * |/_/_/_/_/_/_/|________|
1503 * |<----x0----->|<--w0-->|
1507 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1508 * screen borders
1509 * Hatched area is beyond screen border
1511 * |<-Cursor_x_hot->|
1512 * ________________|_______________
1513 * | | | / / / / / /|
1514 * | (x,y)|/ / / / / / |
1515 * |___________________|_/_/_/_/_/_/|
1516 * |<-------w0-------->| |
1517 * |<---------------w--|----------->|
1518 * | |
1519 * x0 Displaywidth-1
1522 if (x < Cursor_x_hot) { /* see fig. 1 */
1523 x0 = Cursor_x_hot - x;
1524 w0 = w - x0;
1527 if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1528 w0 = (displayWidth) - (x - Cursor_x_hot);
1531 if (y < Cursor_y_hot) { /* see fig. 1 */
1532 y0 = Cursor_y_hot - y;
1533 h0 = h - y0;
1536 if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1537 h0 = (displayHeight) - (y - Cursor_y_hot);
1539 /* end of coordinate correction */
1542 /* Grab an image from the screen, clipped if necessary,
1543 * and put it in the existing panel->magnifyGlass->image
1544 * with the corresponding clipping offset.
1546 if (!XGetSubImage(scr->display, scr->rootWin,
1547 x - Cursor_x_hot + x0,
1548 y - Cursor_y_hot + y0,
1549 w0, h0, AllPlanes, ZPixmap,
1550 image, x0, y0))
1551 wwarning(_("Color Panel: X failed request"));
1553 return NULL;
1557 static void
1558 magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1560 /* (x1, y1) = topleft corner of existing rectangle
1561 * (x2, y2) = topleft corner of new position
1564 W_Screen *scr = WMWidgetScreen(panel->win);
1565 int xa = 0, ya = 0, xb = 0, yb = 0;
1566 int width, height;
1567 const int dx = abs(x2 - x1),
1568 dy = abs(y2 - y1);
1569 XImage *image;
1570 const int x_min = Cursor_x_hot,
1571 y_min = Cursor_y_hot,
1572 x_max = DisplayWidth(scr->display, scr->screen) -1 -
1573 (Cursor_mask_width - Cursor_x_hot),
1574 y_max = DisplayHeight(scr->display, scr->screen) -1 -
1575 (Cursor_mask_height - Cursor_y_hot);
1577 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1578 return; /* No movement */
1580 if (x1 < x2)
1581 xa = dx;
1582 else
1583 xb = dx;
1585 if (y1 < y2)
1586 ya = dy;
1587 else
1588 yb = dy;
1590 width = Cursor_mask_width - dx;
1591 height = Cursor_mask_height - dy;
1593 /* If the traversed distance is larger than the size of the magnifying
1594 * glass contents, there is no need to do dirty rectangles. A whole new
1595 * rectangle can be grabbed (unless that rectangle falls partially
1596 * off screen).
1597 * Destroying the image and setting it to NULL will achieve that later on.
1599 * Of course, grabbing an XImage beyond the borders of the screen will
1600 * cause trouble, this is considdered a special case. Part of the screen
1601 * is grabbed, but there is no need for dirty rectangles.
1603 if ((width <= 0) || (height <= 0)) {
1604 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1605 if (panel->magnifyGlass->image)
1606 XDestroyImage(panel->magnifyGlass->image);
1607 panel->magnifyGlass->image = NULL;
1609 } else {
1610 if (panel->magnifyGlass->image) {
1611 /* Get dirty rectangle from panel->magnifyGlass->image */
1612 panel->magnifyGlass->dirtyRect =
1613 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1614 if (!panel->magnifyGlass->dirtyRect) {
1615 wwarning(_("Color Panel: X failed request"));
1616 return; /* X returned a NULL from XSubImage */
1621 /* Get image from screen */
1622 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
1623 Cursor_mask_width, Cursor_mask_height);
1624 if (image) { /* Only reassign if a *new* image was grabbed */
1625 panel->magnifyGlass->image = image;
1626 return;
1629 /* Copy previously stored rectangle on covered part of image */
1630 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1631 int old_height;
1633 /* "width" and "height" are used as coordinates here,
1634 * and run from [0...width-1] and [0...height-1] respectively.
1636 width--;
1637 height--;
1638 old_height = height;
1640 for (; width >= 0; width--)
1641 for (height = old_height; height >= 0; height--)
1642 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1643 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1644 XDestroyImage(panel->magnifyGlass->dirtyRect);
1645 panel->magnifyGlass->dirtyRect = NULL;
1648 return;
1652 static Pixmap
1653 magnifyCreatePixmap(WMColorPanel *panel)
1655 W_Screen *scr = WMWidgetScreen(panel->win);
1656 int u, v;
1657 #ifndef SHAPE
1658 Pixmap pixmap;
1659 #endif
1660 unsigned long color;
1662 if (!panel->magnifyGlass->image)
1663 return None;
1665 if (!panel->magnifyGlass->magPix)
1666 return None;
1669 * Copy an area of only 5x5 pixels from the center of the image.
1671 for (u = 0; u < 5; u++) {
1672 for (v = 0; v < 5; v++) {
1673 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1675 XSetForeground(scr->display, scr->copyGC, color);
1677 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1678 panel->magnifyGlass->color = ulongToRColor(scr, color);
1680 /* The center square must eventually be centered around the
1681 * hotspot. The image needs shifting to achieve this. The amount of
1682 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1683 * _ _ _ _ _
1684 * |_|_|_|_|_|
1685 * ^------- center of center square == Cursor_x_hot
1687 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1688 scr->copyGC,
1689 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1690 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1694 #ifdef SHAPE
1695 return panel->magnifyGlass->magPix;
1696 #else
1697 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1698 Cursor_mask_height, scr->depth);
1699 if (!pixmap)
1700 return None;
1702 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1703 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1705 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1706 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1707 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1708 /* (2,2) puts center pixel on center of glass */
1710 return pixmap;
1711 #endif
1716 static WMView*
1717 magnifyCreateView(W_ColorPanel *panel)
1719 W_Screen *scr = WMWidgetScreen(panel->win);
1720 WMView *magView;
1722 magView = W_CreateTopView(scr);
1723 if (!magView)
1724 return NULL;
1726 magView->self = panel->win;
1727 magView->flags.topLevel = 1;
1728 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1729 magView->attribs.override_redirect = True;
1730 magView->attribs.save_under = True;
1732 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1734 W_RealizeView(magView);
1736 return magView;
1740 static Cursor
1741 magnifyGrabPointer(W_ColorPanel *panel)
1743 W_Screen *scr = WMWidgetScreen(panel->win);
1744 Pixmap magPixmap, magPixmap2;
1745 Cursor magCursor;
1746 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1747 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1749 /* Cursor creation stuff */
1750 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1751 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1752 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1753 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1755 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1756 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1758 XFreePixmap(scr->display, magPixmap);
1759 XFreePixmap(scr->display, magPixmap2);
1761 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1763 /* Set up Pointer */
1764 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1765 PointerMotionMask | ButtonPressMask,
1766 GrabModeAsync, GrabModeAsync,
1767 scr->rootWin, magCursor, CurrentTime);
1769 return magCursor;
1773 static WMPoint
1774 magnifyInitialize(W_ColorPanel *panel)
1776 W_Screen *scr = WMWidgetScreen(panel->win);
1777 int x, y, u, v;
1778 unsigned int mask;
1779 Pixmap pixmap, clip_mask;
1780 WMPoint point;
1781 Window root_return, child_return;
1783 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1784 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1785 1, 0, 1);
1786 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1787 5*5 -1, 5*5 -1, scr->depth);
1789 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
1790 &x, &y, &u, &v, &mask);
1792 panel->magnifyGlass->image = NULL;
1794 /* Clipmask to make magnified view-contents circular */
1795 #ifdef SHAPE
1796 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1797 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1798 #else
1799 /* Clip circle in glass cursor */
1800 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1801 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1802 #endif
1804 XFreePixmap(scr->display, clip_mask);
1806 /* Draw initial magnifying glass contents */
1807 magnifyGetImageStored(panel, x, y, x, y);
1809 pixmap = magnifyCreatePixmap(panel);
1810 XSetWindowBackgroundPixmap(scr->display,
1811 WMViewXID(panel->magnifyGlass->view),
1812 pixmap);
1813 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1814 XFlush(scr->display);
1816 #ifndef SHAPE
1817 XFreePixmap(scr->display, pixmap);
1818 #endif
1820 point.x = x;
1821 point.y = y;
1823 return point;
1827 static void
1828 magnifyPutCursor(WMWidget *w, void *data)
1830 W_ColorPanel *panel = (W_ColorPanel*)(data);
1831 W_Screen *scr = WMWidgetScreen(panel->win);
1832 Cursor magCursor;
1833 Pixmap pixmap;
1834 XEvent event;
1835 WMPoint initialPosition;
1837 /* Destroy wheelBackImg, so it'll update properly */
1838 if (panel->selectionBackImg) {
1839 XFreePixmap(WMWidgetScreen(panel->win)->display,
1840 panel->selectionBackImg);
1841 panel->selectionBackImg = None;
1844 /* Create magnifying glass */
1845 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1846 panel->magnifyGlass->view = magnifyCreateView(panel);
1847 if (!panel->magnifyGlass->view)
1848 return;
1850 initialPosition = magnifyInitialize(panel);
1851 panel->magnifyGlass->x = initialPosition.x;
1852 panel->magnifyGlass->y = initialPosition.y;
1854 W_MoveView(panel->magnifyGlass->view,
1855 panel->magnifyGlass->x - Cursor_x_hot,
1856 panel->magnifyGlass->y - Cursor_y_hot);
1857 W_MapView(panel->magnifyGlass->view);
1859 magCursor = magnifyGrabPointer(panel);
1861 while (panel->magnifyGlass->image)
1863 WMNextEvent(scr->display, &event);
1865 /* Pack motion events */
1866 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1869 switch (event.type)
1871 case ButtonPress:
1872 XDestroyImage(panel->magnifyGlass->image);
1873 panel->magnifyGlass->image = NULL;
1875 if (event.xbutton.button == Button1) {
1876 panel->color.rgb = panel->magnifyGlass->color;
1877 panel->color.set = cpRGB;
1878 updateSwatch(panel, panel->color);
1880 switch (panel->mode) {
1881 case WMWheelModeColorPanel:
1882 wheelInit(panel);
1883 wheelRender(panel);
1884 wheelPaint(panel);
1885 break;
1886 case WMGrayModeColorPanel:
1887 grayInit(panel);
1888 break;
1889 case WMRGBModeColorPanel:
1890 rgbInit(panel);
1891 break;
1892 case WMCMYKModeColorPanel:
1893 cmykInit(panel);
1894 break;
1895 case WMHSBModeColorPanel:
1896 hsbInit(panel);
1897 break;
1898 default:
1899 break;
1901 panel->lastChanged = panel->mode;
1903 WMSetButtonSelected(panel->magnifyBtn, False);
1904 break;
1906 case MotionNotify:
1907 while (XPending(event.xmotion.display)) {
1908 XEvent ev;
1909 XPeekEvent(event.xmotion.display, &ev);
1910 if (ev.type == MotionNotify)
1911 XNextEvent(event.xmotion.display, &event);
1912 else
1913 break;
1916 /* Get a "dirty rectangle" */
1917 magnifyGetImageStored( panel,
1918 panel->magnifyGlass->x, panel->magnifyGlass->y,
1919 event.xmotion.x_root, event.xmotion.y_root);
1921 /* Update coordinates */
1922 panel->magnifyGlass->x = event.xmotion.x_root;
1923 panel->magnifyGlass->y = event.xmotion.y_root;
1925 /* Move view */
1926 W_MoveView(panel->magnifyGlass->view,
1927 panel->magnifyGlass->x - Cursor_x_hot,
1928 panel->magnifyGlass->y - Cursor_y_hot);
1930 /* Put new image (with magn.) in view */
1931 pixmap = magnifyCreatePixmap(panel);
1932 if (pixmap != None) {
1933 /* Change the window background */
1934 XSetWindowBackgroundPixmap(scr->display,
1935 WMViewXID(panel->magnifyGlass->view), pixmap);
1936 /* Force an Expose (handled by X) */
1937 XClearWindow(scr->display,
1938 WMViewXID(panel->magnifyGlass->view));
1939 /* Synchronize the event queue, so the Expose is handled NOW */
1940 XFlush(scr->display);
1941 #ifndef SHAPE
1942 XFreePixmap(scr->display, pixmap);
1943 #endif
1945 break;
1947 /* Try XQueryPointer for this !!! It returns windows that the pointer
1948 * is over. Note: We found this solving the invisible donkey cap bug
1950 #if 0 /* As it is impossible to make this work in all cases,
1951 * we consider it confusing. Therefore we disabled it.
1953 case FocusOut: /* fall through */
1954 case FocusIn:
1956 * Color Panel window (panel->win) lost or received focus.
1957 * We need to update the pixmap in the magnifying glass.
1959 * BUG Doesn't work with focus switches between two windows
1960 * if none of them is the color panel.
1962 XUngrabPointer(scr->display, CurrentTime);
1963 W_UnmapView(panel->magnifyGlass->view);
1965 magnifyInitialize(panel);
1967 W_MapView(panel->magnifyGlass->view);
1968 XGrabPointer (scr->display, panel->magnifyGlass->view->window,
1969 True, PointerMotionMask | ButtonPressMask,
1970 GrabModeAsync, GrabModeAsync,
1971 scr->rootWin, magCursor, CurrentTime);
1972 break;
1973 #endif
1974 default:
1975 WMHandleEvent(&event);
1976 break;
1977 } /* of switch */
1980 XUngrabPointer(scr->display, CurrentTime);
1981 XFreeCursor(scr->display, magCursor);
1983 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1984 panel->magnifyGlass->magPix = None;
1986 W_UnmapView(panel->magnifyGlass->view);
1987 W_DestroyView(panel->magnifyGlass->view);
1988 panel->magnifyGlass->view = NULL;
1990 wfree(panel->magnifyGlass);
1995 /****************** ColorWheel Functions ************************/
1997 static wheelMatrix*
1998 wheelCreateMatrix(unsigned int width, unsigned int height)
2000 wheelMatrix *matrix = NULL;
2001 int i;
2003 assert((width > 0) && (height > 0));
2005 matrix = wmalloc(sizeof(wheelMatrix));
2006 memset(matrix, 0, sizeof(wheelMatrix));
2007 matrix->width = width;
2008 matrix->height = height;
2010 for (i = 0; i < 3; i++) {
2011 matrix->data[i] = wmalloc(width*height*sizeof(unsigned char));
2014 return matrix;
2018 static void
2019 wheelDestroyMatrix(wheelMatrix *matrix)
2021 int i;
2023 if (!matrix)
2024 return;
2026 for (i = 0; i < 3; i++) {
2027 if (matrix->data[i])
2028 wfree(matrix->data[i]);
2030 wfree(matrix);
2034 static void
2035 wheelInitMatrix(W_ColorPanel *panel)
2037 int i;
2038 int x,y;
2039 unsigned char *rp, *gp, *bp;
2040 CPColor cpColor;
2041 long ofs[4];
2042 int xcor, ycor;
2043 unsigned short sat;
2044 int dhue[4];
2045 const int cw_halfsize = (colorWheelSize + 4)/2,
2046 cw_sqsize = (colorWheelSize +4) * (colorWheelSize +4),
2047 uchar_shift = getShift(sizeof(unsigned char));
2049 if (!panel->wheelMtrx)
2050 return;
2052 cpColor.hsv.value = 255;
2053 cpColor.set = cpHSV;
2055 ofs[0] = -1;
2056 ofs[1] = -(colorWheelSize + 4);
2058 /* offsets are counterclockwise (in triangles).
2060 * ofs[0] ---->
2061 * _______________________________________
2062 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
2063 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
2064 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
2065 * o | | | | | | | | | | | | | | | | | | | | | [3]
2067 * <---- ofs[2]
2068 * ____
2069 * |\ /| <-- triangles
2070 * | \/ |
2071 * | /\ |
2072 * |/__\|
2075 for (y = 0; y < cw_halfsize; y++) {
2076 for (x = y; x < (colorWheelSize+4-y); x++) {
2077 /* (xcor, ycor) is (x,y) relative to center of matrix */
2078 xcor = 2 * x - 4 - colorWheelSize;
2079 ycor = 2 * y - 4 - colorWheelSize;
2081 /* RColor.saturation is unsigned char and will wrap after 255 */
2082 sat = rint(255.0 * sqrt(xcor*xcor + ycor*ycor) / colorWheelSize);
2084 cpColor.hsv.saturation = (unsigned char)sat;
2086 ofs[0]++; /* top quarter of matrix*/
2087 ofs[1] += colorWheelSize + 4; /* left quarter */
2088 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
2089 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
2091 if (sat < 256) {
2092 if (xcor != 0)
2093 dhue[0] = rint(atan((double)ycor / (double)xcor) *
2094 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
2095 else
2096 dhue[0] = 270;
2098 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
2099 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
2100 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
2101 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
2103 for (i = 0; i < 4; i++) {
2104 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2105 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2106 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2108 cpColor.hsv.hue = dhue[i];
2109 convertCPColor(&cpColor);
2111 *rp = (unsigned char)(cpColor.rgb.red);
2112 *gp = (unsigned char)(cpColor.rgb.green);
2113 *bp = (unsigned char)(cpColor.rgb.blue);
2116 else {
2117 for (i = 0; i < 4; i++) {
2118 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2119 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2120 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2122 *rp = (unsigned char)0;
2123 *gp = (unsigned char)0;
2124 *bp = (unsigned char)0;
2129 ofs[0] += 2*y+1;
2130 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
2135 static void
2136 wheelCalculateValues(W_ColorPanel *panel, int maxvalue)
2138 unsigned int i;
2139 unsigned int v;
2141 for (i = 0; i < 256; i++) {
2142 /* We divide by 128 in advance, and check whether that number divides
2143 * by 2 properly. If not, we add one to round the number correctly
2145 v = (i*maxvalue) >> 7;
2146 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2151 static void
2152 wheelRender(W_ColorPanel *panel)
2154 W_Screen *scr = WMWidgetScreen(panel->win);
2155 int x,y;
2156 RImage *image;
2157 unsigned char *ptr;
2158 RColor gray;
2159 unsigned long ofs = 0;
2160 /*unsigned char shift = getShift(sizeof(unsigned char));*/
2162 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, True);
2163 if (!image) {
2164 wwarning(_("Color Panel: Could not allocate memory"));
2165 return;
2168 ptr = image->data;
2170 /* TODO Make this transparent istead of gray */
2171 gray.red = gray.blue = 0xae; gray.green = 0xaa;
2173 for (y = 0; y < colorWheelSize+4; y++) {
2174 for (x = 0; x < colorWheelSize+4; x++) {
2175 if (wheelInsideColorWheel(panel, ofs)) {
2176 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2177 panel->wheelMtrx->data[0][ofs] ]);
2178 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2179 panel->wheelMtrx->data[1][ofs] ]);
2180 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2181 panel->wheelMtrx->data[2][ofs] ]);
2182 *(ptr++) = 0;
2184 else {
2185 *(ptr++) = (unsigned char)(gray.red);
2186 *(ptr++) = (unsigned char)(gray.green);
2187 *(ptr++) = (unsigned char)(gray.blue);
2188 *(ptr++) = 255;
2190 ofs++;
2194 if (panel->wheelImg)
2195 XFreePixmap(scr->display, panel->wheelImg);
2197 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2198 RReleaseImage(image);
2200 /* Check if backimage exists. If it doesn't, allocate and fill it */
2201 if (!panel->selectionBackImg) {
2202 panel->selectionBackImg = XCreatePixmap(scr->display,
2203 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2204 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2205 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2206 /* -2 is hot spot correction */
2211 static Bool
2212 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2214 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2215 (panel->wheelMtrx->data[1][ofs] != 0) &&
2216 (panel->wheelMtrx->data[2][ofs] != 0));
2220 static void
2221 wheelPaint (W_ColorPanel *panel)
2223 W_Screen *scr = WMWidgetScreen(panel->win);
2225 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2226 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2228 /* Draw selection image */
2229 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2230 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2234 static void
2235 wheelHandleEvents(XEvent *event, void *data)
2237 W_ColorPanel *panel = (W_ColorPanel*)data;
2239 switch (event->type) {
2240 case Expose:
2241 if (event->xexpose.count != 0) /* TODO Improve */
2242 break;
2243 wheelPaint(panel);
2244 break;
2249 static void
2250 wheelHandleActionEvents(XEvent *event, void *data)
2252 W_ColorPanel *panel = (W_ColorPanel*)data;
2254 switch (event->type) {
2255 case ButtonPress:
2256 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2257 COLORWHEEL_PART) {
2259 panel->lastChanged = WMWheelModeColorPanel;
2260 panel->flags.dragging = 1;
2262 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2264 break;
2266 case ButtonRelease:
2267 panel->flags.dragging = 0;
2268 if (!panel->flags.continuous) {
2269 if (panel->action)
2270 (*panel->action)(panel, panel->clientData);
2272 break;
2274 case MotionNotify:
2275 if (panel->flags.dragging) {
2276 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2277 COLORWHEEL_PART) {
2278 wheelPositionSelection(panel, event->xmotion.x,
2279 event->xmotion.y);
2281 else
2282 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2283 event->xmotion.y);
2285 break;
2290 static int
2291 getPickerPart(W_ColorPanel *panel, int x, int y)
2293 int lx, ly;
2294 unsigned long ofs;
2296 lx = x;
2297 ly = y;
2299 if (panel->mode == WMWheelModeColorPanel) {
2300 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2301 (ly <= 2+colorWheelSize)) {
2303 ofs = ly*panel->wheelMtrx->width+lx;
2305 if (wheelInsideColorWheel(panel, ofs))
2306 return COLORWHEEL_PART;
2310 if (panel->mode == WMCustomPaletteModeColorPanel) {
2311 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2312 (ly < customPaletteHeight-2)) {
2313 return CUSTOMPALETTE_PART;
2317 return 0;
2321 static void
2322 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2324 int value;
2326 W_ColorPanel *panel = (W_ColorPanel*)data;
2328 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2330 wheelCalculateValues(panel, value);
2332 if (panel->color.set == cpRGB) {
2333 convertCPColor(&panel->color);
2334 panel->color.set = cpHSV;
2337 panel->color.hsv.value = value;
2339 wheelRender(panel);
2340 wheelPaint(panel);
2341 wheelUpdateSelection(panel);
2345 static void
2346 wheelUpdateSelection(W_ColorPanel *panel)
2348 W_Screen *scr = WMWidgetScreen(panel->win);
2350 updateSwatch(panel, panel->color);
2351 panel->lastChanged = WMWheelModeColorPanel;
2353 /* Redraw color selector (and make a backup of the part it will cover) */
2354 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2355 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2356 /* "-2" is correction for hotspot location */
2357 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2358 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2359 /* see above */
2363 static void
2364 wheelUndrawSelection(W_ColorPanel *panel)
2366 W_Screen *scr = WMWidgetScreen(panel->win);
2368 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2369 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2370 /* see above */
2373 static void
2374 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2376 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2378 panel->color.rgb.red = panel->wheelMtrx->values[
2379 panel->wheelMtrx->data[0][ofs] ];
2381 panel->color.rgb.green = panel->wheelMtrx->values[
2382 panel->wheelMtrx->data[1][ofs] ];
2384 panel->color.rgb.blue = panel->wheelMtrx->values[
2385 panel->wheelMtrx->data[2][ofs] ];
2386 panel->color.set = cpRGB;
2388 wheelUndrawSelection(panel);
2390 panel->colx = x;
2391 panel->coly = y;
2393 wheelUpdateSelection(panel);
2394 wheelUpdateBrightnessGradientFromLocation(panel);
2397 static void
2398 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2400 int hue;
2401 int xcor, ycor;
2402 CPColor cpColor;
2404 xcor = x * 2 - colorWheelSize - 4;
2405 ycor = y * 2 - colorWheelSize - 4;
2407 panel->color.hsv.saturation = 255;
2408 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2410 if (xcor != 0)
2411 hue = rint(atan(- (double)ycor / (double)xcor) * (180.0/M_PI));
2412 else {
2413 if (ycor < 0)
2414 hue = 90;
2415 else
2416 hue = 270;
2419 if (xcor < 0)
2420 hue += 180;
2422 if ((xcor > 0) && (ycor > 0))
2423 hue += 360;
2425 panel->color.hsv.hue = hue;
2426 panel->color.set = cpHSV;
2427 convertCPColor(&panel->color);
2429 wheelUndrawSelection(panel);
2431 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2432 cos( panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2433 /* "+2" because of "colorWheelSize + 4" */
2434 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2435 sin(- panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2437 wheelUpdateSelection(panel);
2438 cpColor = panel->color;
2439 wheelUpdateBrightnessGradient(panel, cpColor);
2442 static void
2443 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2445 CPColor from;
2446 unsigned long ofs;
2448 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2450 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2451 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2452 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2453 from.set = cpRGB;
2455 wheelUpdateBrightnessGradient(panel, from);
2458 static void
2459 wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor)
2461 RColor to;
2462 RImage *sliderImg;
2463 WMPixmap *sliderPxmp;
2465 to.red = to.green = to.blue = 0;
2467 if (topColor.set == cpHSV)
2468 convertCPColor(&topColor);
2470 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2471 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2472 sliderImg, 0);
2473 RReleaseImage(sliderImg);
2474 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2475 WMReleasePixmap(sliderPxmp);
2478 /****************** Grayscale Panel Functions ***************/
2480 static void
2481 grayBrightnessSliderCallback(WMWidget *w, void *data)
2483 CPColor cpColor;
2484 int value;
2485 char tmp[4];
2486 W_ColorPanel *panel = (W_ColorPanel*)data;
2488 value = WMGetSliderValue(panel->grayBrightnessS);
2490 sprintf(tmp, "%d", value);
2492 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2493 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55*value);
2494 cpColor.set = cpRGB;
2496 updateSwatch(panel, cpColor);
2497 panel->lastChanged = WMGrayModeColorPanel;
2500 static void
2501 grayPresetButtonCallback(WMWidget *w, void *data)
2503 CPColor cpColor;
2504 char tmp[4];
2505 int value;
2506 int i=0;
2507 W_ColorPanel *panel = (W_ColorPanel*)data;
2509 while (i < 7) {
2510 if (w == panel->grayPresetBtn[i])
2511 break;
2512 i++;
2515 value = rint((100.0*i)/6.0);
2516 sprintf(tmp, "%d", value);
2518 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2519 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2520 rint((255.0*i)/6.0);
2521 cpColor.set = cpRGB;
2523 WMSetSliderValue(panel->grayBrightnessS, rint((100.0*i)/6.0));
2525 updateSwatch(panel, cpColor);
2526 panel->lastChanged = WMGrayModeColorPanel;
2529 static void
2530 grayBrightnessTextFieldCallback(void *observerData,
2531 WMNotification *notification)
2533 CPColor cpColor;
2534 char tmp[4];
2535 int value;
2536 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2538 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2539 if (value > 100)
2540 value = 100;
2541 if (value < 0)
2542 value = 0;
2544 sprintf(tmp, "%d", value);
2545 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2546 WMSetSliderValue(panel->grayBrightnessS, value);
2548 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2549 rint((255.0*value)/100.0);
2550 cpColor.set = cpRGB;
2552 updateSwatch(panel, cpColor);
2553 panel->lastChanged = WMGrayModeColorPanel;
2556 /******************* RGB Panel Functions *****************/
2558 static void
2559 rgbSliderCallback(WMWidget *w, void *data)
2561 CPColor cpColor;
2562 int value[3];
2563 char tmp[4];
2564 W_ColorPanel *panel = (W_ColorPanel*)data;
2566 value[0] = WMGetSliderValue(panel->rgbRedS);
2567 value[1] = WMGetSliderValue(panel->rgbGreenS);
2568 value[2] = WMGetSliderValue(panel->rgbBlueS);
2570 sprintf(tmp, "%d", value[0]);
2571 WMSetTextFieldText(panel->rgbRedT, tmp);
2572 sprintf(tmp, "%d", value[1]);
2573 WMSetTextFieldText(panel->rgbGreenT, tmp);
2574 sprintf(tmp, "%d", value[2]);
2575 WMSetTextFieldText(panel->rgbBlueT, tmp);
2577 cpColor.rgb.red = value[0];
2578 cpColor.rgb.green = value[1];
2579 cpColor.rgb.blue = value[2];
2580 cpColor.set = cpRGB;
2582 updateSwatch(panel, cpColor);
2583 panel->lastChanged = WMRGBModeColorPanel;
2586 static void
2587 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2589 CPColor cpColor;
2590 int value[3];
2591 char tmp[4];
2592 int n;
2593 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2595 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2596 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2597 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2599 for (n=0; n < 3; n++) {
2600 if (value[n] > 255)
2601 value[n] = 255;
2602 if (value[n] < 0)
2603 value[n] = 0;
2606 sprintf(tmp, "%d", value[0]);
2607 WMSetTextFieldText(panel->rgbRedT, tmp);
2608 sprintf(tmp, "%d", value[1]);
2609 WMSetTextFieldText(panel->rgbGreenT, tmp);
2610 sprintf(tmp, "%d", value[2]);
2611 WMSetTextFieldText(panel->rgbBlueT, tmp);
2613 WMSetSliderValue(panel->rgbRedS, value[0]);
2614 WMSetSliderValue(panel->rgbGreenS, value[1]);
2615 WMSetSliderValue(panel->rgbBlueS, value[2]);
2617 cpColor.rgb.red = value[0];
2618 cpColor.rgb.green = value[1];
2619 cpColor.rgb.blue = value[2];
2620 cpColor.set = cpRGB;
2622 updateSwatch(panel, cpColor);
2623 panel->lastChanged = WMRGBModeColorPanel;
2627 /******************* CMYK Panel Functions *****************/
2629 static void
2630 cmykSliderCallback(WMWidget *w, void *data)
2632 CPColor cpColor;
2633 int value[4];
2634 char tmp[4];
2635 W_ColorPanel *panel = (W_ColorPanel*)data;
2636 double scale;
2638 value[0] = WMGetSliderValue(panel->cmykCyanS);
2639 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2640 value[2] = WMGetSliderValue(panel->cmykYellowS);
2641 value[3] = WMGetSliderValue(panel->cmykBlackS);
2643 sprintf(tmp, "%d", value[0]);
2644 WMSetTextFieldText(panel->cmykCyanT, tmp);
2645 sprintf(tmp, "%d", value[1]);
2646 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2647 sprintf(tmp, "%d", value[2]);
2648 WMSetTextFieldText(panel->cmykYellowT, tmp);
2649 sprintf(tmp, "%d", value[3]);
2650 WMSetTextFieldText(panel->cmykBlackT, tmp);
2652 scale = 2.55 * (1.0 - (value[3] / 100.0));
2653 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2654 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2655 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2656 cpColor.set = cpRGB;
2658 updateSwatch(panel, cpColor);
2659 panel->lastChanged = WMCMYKModeColorPanel;
2662 static void
2663 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2665 CPColor cpColor;
2666 int value[4];
2667 char tmp[4];
2668 int n;
2669 double scale;
2670 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2672 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2673 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2674 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2675 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2677 for (n=0; n < 4; n++) {
2678 if (value[n] > 100)
2679 value[n] = 100;
2680 if (value[n] < 0)
2681 value[n] = 0;
2684 sprintf(tmp, "%d", value[0]);
2685 WMSetTextFieldText(panel->cmykCyanT, tmp);
2687 sprintf(tmp, "%d", value[1]);
2688 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2690 sprintf(tmp, "%d", value[2]);
2691 WMSetTextFieldText(panel->cmykYellowT, tmp);
2693 sprintf(tmp, "%d", value[3]);
2694 WMSetTextFieldText(panel->cmykBlackT, tmp);
2696 WMSetSliderValue(panel->cmykCyanS, value[0]);
2697 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2698 WMSetSliderValue(panel->cmykYellowS, value[2]);
2699 WMSetSliderValue(panel->cmykBlackS, value[3]);
2701 scale = 2.55 * (1.0 - (value[3] / 100.0));
2702 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2703 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2704 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2705 cpColor.set = cpRGB;
2707 updateSwatch(panel, cpColor);
2708 panel->lastChanged = WMCMYKModeColorPanel;
2711 /********************** HSB Panel Functions ***********************/
2713 static void
2714 hsbSliderCallback(WMWidget *w, void *data)
2716 CPColor cpColor;
2717 int value[3];
2718 char tmp[4];
2719 W_ColorPanel *panel = (W_ColorPanel*)data;
2721 value[0] = WMGetSliderValue(panel->hsbHueS);
2722 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2723 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2725 sprintf(tmp, "%d", value[0]);
2726 WMSetTextFieldText(panel->hsbHueT, tmp);
2727 sprintf(tmp, "%d", value[1]);
2728 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2729 sprintf(tmp, "%d", value[2]);
2730 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2732 cpColor.hsv.hue = value[0];
2733 cpColor.hsv.saturation = value[1]*2.55;
2734 cpColor.hsv.value = value[2]*2.55;
2735 cpColor.set = cpHSV;
2737 convertCPColor(&cpColor);
2739 panel->lastChanged = WMHSBModeColorPanel;
2740 updateSwatch(panel, cpColor);
2742 if (w != panel->hsbBrightnessS)
2743 hsbUpdateBrightnessGradient(panel);
2744 if (w != panel->hsbSaturationS)
2745 hsbUpdateSaturationGradient(panel);
2746 if (w != panel->hsbHueS)
2747 hsbUpdateHueGradient(panel);
2750 static void
2751 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2753 CPColor cpColor;
2754 int value[3];
2755 char tmp[4];
2756 int n;
2757 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2759 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2760 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2761 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2763 if (value[0] > 359)
2764 value[0] = 359;
2765 if (value[0] < 0)
2766 value[0] = 0;
2768 for (n=1; n < 3; n++) {
2769 if (value[n] > 100)
2770 value[n] = 100;
2771 if (value[n] < 0)
2772 value[n] = 0;
2775 sprintf(tmp, "%d", value[0]);
2776 WMSetTextFieldText(panel->hsbHueT, tmp);
2777 sprintf(tmp, "%d", value[1]);
2778 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2779 sprintf(tmp, "%d", value[2]);
2780 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2782 WMSetSliderValue(panel->hsbHueS, value[0]);
2783 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2784 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2786 cpColor.hsv.hue = value[0];
2787 cpColor.hsv.saturation = value[1]*2.55;
2788 cpColor.hsv.value = value[2]*2.55;
2789 cpColor.set = cpHSV;
2791 convertCPColor(&cpColor);
2793 panel->lastChanged = WMHSBModeColorPanel;
2794 updateSwatch(panel, cpColor);
2796 hsbUpdateBrightnessGradient(panel);
2797 hsbUpdateSaturationGradient(panel);
2798 hsbUpdateHueGradient(panel);
2801 static void
2802 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2804 W_Screen *scr = WMWidgetScreen(panel->win);
2805 RColor from;
2806 CPColor to;
2807 RImage *sliderImg;
2808 WMPixmap *sliderPxmp;
2810 from.red = from.green = from.blue = 0;
2811 to.hsv = panel->color.hsv;
2812 to.hsv.value = 255;
2813 to.set = cpHSV;
2815 convertCPColor(&to);
2817 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2818 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2819 RReleaseImage(sliderImg);
2821 if (sliderPxmp)
2822 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2823 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white),
2824 False, _("Brightness"), strlen(_("Brightness")));
2825 else
2826 wwarning(_("Color Panel: Could not allocate memory"));
2828 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2829 WMReleasePixmap(sliderPxmp);
2832 static void
2833 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2835 W_Screen *scr = WMWidgetScreen(panel->win);
2836 CPColor from;
2837 CPColor to;
2838 RImage *sliderImg;
2839 WMPixmap *sliderPxmp;
2841 from.hsv = panel->color.hsv;
2842 from.hsv.saturation = 0;
2843 from.set = cpHSV;
2844 convertCPColor(&from);
2846 to.hsv = panel->color.hsv;
2847 to.hsv.saturation = 255;
2848 to.set = cpHSV;
2849 convertCPColor(&to);
2851 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb),
2852 RGRD_HORIZONTAL);
2853 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2854 RReleaseImage(sliderImg);
2856 if (sliderPxmp)
2857 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2858 panel->font12, 2, 0, 100, WALeft,
2859 WMColorGC(from.hsv.value < 128 ? scr->white : scr->black), False,
2860 _("Saturation"), strlen(_("Saturation")));
2861 else
2862 wwarning(_("Color Panel: Could not allocate memory"));
2864 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2865 WMReleasePixmap(sliderPxmp);
2868 static void
2869 hsbUpdateHueGradient(W_ColorPanel *panel)
2871 W_Screen *scr = WMWidgetScreen(panel->win);
2872 RColor **colors = NULL;
2873 RHSVColor hsvcolor;
2874 RImage *sliderImg;
2875 WMPixmap *sliderPxmp;
2876 int i;
2878 hsvcolor = panel->color.hsv;
2880 colors = wmalloc(sizeof(RColor*)*(8));
2881 for (i=0; i<7; i++) {
2882 hsvcolor.hue = (360*i)/6;
2883 colors[i] = wmalloc(sizeof(RColor));
2884 RHSVtoRGB(&hsvcolor, colors[i]);
2886 colors[7] = NULL;
2888 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2889 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2890 RReleaseImage(sliderImg);
2892 if (sliderPxmp)
2893 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2894 panel->font12, 2, 0, 100, WALeft,
2895 WMColorGC(hsvcolor.value < 128 ? scr->white : scr->black), False,
2896 _("Hue"), strlen(_("Hue")));
2897 else
2898 wwarning(_("Color Panel: Could not allocate memory"));
2900 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2901 WMReleasePixmap(sliderPxmp);
2903 for (i=0; i<7; i++)
2904 wfree(colors[i]);
2906 wfree(colors);
2909 /*************** Custom Palette Functions ****************/
2911 static void
2912 customRenderSpectrum(W_ColorPanel *panel)
2914 RImage *spectrum;
2915 int x,y;
2916 unsigned char *ptr;
2917 CPColor cpColor;
2919 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2921 ptr = spectrum->data;
2923 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2924 cpColor.hsv.hue = y;
2925 cpColor.hsv.saturation = 0;
2926 cpColor.hsv.value = 255;
2927 cpColor.set = cpHSV;
2929 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2930 convertCPColor(&cpColor);
2932 *(ptr++) = (unsigned char)cpColor.rgb.red;
2933 *(ptr++) = (unsigned char)cpColor.rgb.green;
2934 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2936 if (x < (SPECTRUM_WIDTH/2))
2937 cpColor.hsv.saturation++;
2939 if (x > (SPECTRUM_WIDTH/2))
2940 cpColor.hsv.value--;
2943 if (panel->customPaletteImg) {
2944 RReleaseImage(panel->customPaletteImg);
2945 panel->customPaletteImg = NULL;
2947 panel->customPaletteImg = spectrum;
2952 static void
2953 customSetPalette(W_ColorPanel *panel)
2955 W_Screen *scr = WMWidgetScreen(panel->win);
2956 RImage *scaledImg;
2957 Pixmap image;
2958 int item;
2960 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2961 customPaletteHeight, scr->depth);
2962 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2963 customPaletteHeight);
2964 RConvertImage(scr->rcontext, scaledImg, &image);
2965 RReleaseImage(scaledImg);
2967 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2968 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2970 /* Check backimage exists. If it doesn't, allocate and fill it */
2971 if (!panel->selectionBackImg) {
2972 panel->selectionBackImg = XCreatePixmap(scr->display,
2973 panel->customPaletteContentView->window, 4, 4, scr->depth);
2976 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2977 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2978 XCopyArea(scr->display, panel->selectionImg,
2979 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2980 panel->palx-2, panel->paly-2);
2981 XFreePixmap(scr->display, image);
2983 panel->palXRatio = (double)(panel->customPaletteImg->width) /
2984 (double)(customPaletteWidth);
2985 panel->palYRatio = (double)(panel->customPaletteImg->height) /
2986 (double)(customPaletteHeight);
2988 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2992 static void
2993 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2995 W_Screen *scr = WMWidgetScreen(panel->win);
2996 unsigned long ofs;
2999 /* undraw selection */
3000 XCopyArea(scr->display, panel->selectionBackImg,
3001 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3002 panel->palx-2, panel->paly-2);
3004 panel->palx = x;
3005 panel->paly = y;
3007 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
3008 panel->customPaletteImg->width) * 3;
3010 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
3011 panel->color.rgb.green = panel->customPaletteImg->data[ofs+1];
3012 panel->color.rgb.blue = panel->customPaletteImg->data[ofs+2];
3013 panel->color.set = cpRGB;
3015 updateSwatch(panel, panel->color);
3016 panel->lastChanged = WMCustomPaletteModeColorPanel;
3018 /* Redraw color selector (and make a backup of the part it will cover) */
3019 XCopyArea(scr->display, panel->customPaletteContentView->window,
3020 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
3021 4, 4, 0, 0); /* "-2" is correction for hotspot location */
3022 XCopyArea(scr->display, panel->selectionImg,
3023 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3024 panel->palx-2, panel->paly-2); /* see above */
3028 static void
3029 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
3031 if (x < 2)
3032 x = 2;
3033 if (y < 2)
3034 y = 2;
3035 if (x >= customPaletteWidth)
3036 x = customPaletteWidth -2;
3037 if (y >= customPaletteHeight)
3038 y = customPaletteHeight -2;
3040 customPalettePositionSelection(panel, x, y);
3044 static void
3045 customPaletteHandleEvents(XEvent *event, void *data)
3047 W_ColorPanel *panel = (W_ColorPanel*)data;
3049 switch (event->type) {
3050 case Expose:
3051 if (event->xexpose.count != 0) /* TODO Improve. */
3052 break;
3053 customSetPalette(panel);
3054 break;
3058 static void
3059 customPaletteHandleActionEvents(XEvent *event, void *data)
3061 W_ColorPanel *panel = (W_ColorPanel*)data;
3062 int x, y;
3064 switch (event->type) {
3065 case ButtonPress:
3066 x = event->xbutton.x;
3067 y = event->xbutton.y;
3069 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3070 panel->flags.dragging = 1;
3071 customPalettePositionSelection(panel, x, y);
3073 break;
3075 case ButtonRelease:
3076 panel->flags.dragging = 0;
3077 if (!panel->flags.continuous) {
3078 if (panel->action)
3079 (*panel->action)(panel, panel->clientData);
3081 break;
3083 case MotionNotify:
3084 x = event->xmotion.x;
3085 y = event->xmotion.y;
3087 if (panel->flags.dragging) {
3088 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3089 customPalettePositionSelection(panel, x, y);
3091 else
3092 customPalettePositionSelectionOutBounds(panel, x, y);
3094 break;
3099 static void
3100 customPaletteMenuCallback(WMWidget *w, void *data)
3102 W_ColorPanel *panel = (W_ColorPanel*)data;
3103 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
3105 switch (item) {
3106 case CPmenuNewFromFile:
3107 customPaletteMenuNewFromFile(panel);
3108 break;
3109 case CPmenuRename:
3110 customPaletteMenuRename(panel);
3111 break;
3112 case CPmenuRemove:
3113 customPaletteMenuRemove(panel);
3114 break;
3115 case CPmenuCopy:
3116 break;
3117 case CPmenuNewFromClipboard:
3118 break;
3123 static void
3124 customPaletteMenuNewFromFile(W_ColorPanel *panel)
3126 W_Screen *scr = WMWidgetScreen(panel->win);
3127 WMOpenPanel *browseP;
3128 char *filepath;
3129 char *filename = NULL;
3130 char *spath;
3131 char *tmp;
3132 int i;
3133 RImage *tmpImg = NULL;
3135 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3136 spath = wexpandpath(wgethomedir());
3137 else
3138 spath = wexpandpath(panel->lastBrowseDir);
3140 browseP = WMGetOpenPanel(scr);
3141 WMSetFilePanelCanChooseDirectories(browseP, 0);
3142 WMSetFilePanelCanChooseFiles(browseP, 1);
3144 /* Get a filename */
3145 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3146 _("Open Palette"), RSupportedFileFormats()) ) {
3147 filepath = WMGetFilePanelFileName(browseP);
3149 /* Get seperation position between path and filename */
3150 i = strrchr(filepath, '/') - filepath + 1;
3151 if (i > strlen(filepath))
3152 i = strlen(filepath);
3154 /* Store last browsed path */
3155 if (panel->lastBrowseDir)
3156 wfree(panel->lastBrowseDir);
3157 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3158 strncpy(panel->lastBrowseDir, filepath, i);
3159 panel->lastBrowseDir[i] = '\0';
3161 /* Get filename from path */
3162 filename = wstrdup(filepath + i);
3164 /* Check for duplicate files, and rename it if there are any */
3165 tmp = wstrconcat(panel->configurationPath, filename);
3166 while (access (tmp, F_OK) == 0) {
3167 char *newName;
3169 wfree(tmp);
3171 newName = generateNewFilename(filename);
3172 wfree(filename);
3173 filename = newName;
3175 tmp = wstrconcat(panel->configurationPath, filename);
3177 wfree(tmp);
3179 /* Copy image to $(gnustepdir)/Library/Colors/ &
3180 * Add filename to history menu */
3181 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3183 /* filepath is a "local" path now the file has been copied */
3184 wfree(filepath);
3185 filepath = wstrconcat(panel->configurationPath, filename);
3187 /* load the image & add menu entries */
3188 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3189 if (tmpImg) {
3190 if (panel->customPaletteImg)
3191 RReleaseImage(panel->customPaletteImg);
3192 panel->customPaletteImg = tmpImg;
3194 customSetPalette(panel);
3195 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3197 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3198 panel->customPaletteHistoryBtn)-1;
3200 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3201 panel->currentPalette);
3203 } else {
3204 tmp = wstrconcat(panel->configurationPath, filename);
3206 i = remove(tmp); /* Delete the file, it doesn't belong here */
3207 WMRunAlertPanel(scr, panel->win, _("File Error"),
3208 _("Invalid file format !"), _("OK"), NULL, NULL);
3209 if (i != 0) {
3210 wsyserror(_("can't remove file %s"), tmp);
3211 WMRunAlertPanel(scr, panel->win, _("File Error"),
3212 _("Couldn't remove file from Configuration Directory !"),
3213 _("OK"), NULL, NULL);
3215 wfree(tmp);
3217 wfree(filepath);
3218 wfree(filename);
3220 WMFreeFilePanel(browseP);
3222 wfree(spath);
3226 static void
3227 customPaletteMenuRename(W_ColorPanel *panel)
3229 W_Screen *scr = WMWidgetScreen(panel->win);
3230 char *toName = NULL;
3231 char *fromName;
3232 char *toPath, *fromPath;
3233 int item;
3234 int index;
3236 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3237 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3239 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3240 fromName, _("OK"), _("Cancel"));
3242 if (toName) {
3244 /* As some people do certain stupid things... */
3245 if (strcmp(toName, fromName) == 0) {
3246 wfree(toName);
3247 return;
3250 /* For normal people */
3251 fromPath = wstrconcat(panel->configurationPath, fromName);
3252 toPath = wstrconcat(panel->configurationPath, toName);
3254 if (access (toPath, F_OK) == 0) {
3255 /* Careful, this palette exists already */
3256 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3257 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3258 NULL) == 1) {
3259 /* "No" = 0, "Yes" = 1 */
3260 int items = WMGetPopUpButtonNumberOfItems(
3261 panel->customPaletteHistoryBtn);
3263 remove(toPath);
3265 /* Remove from History list too */
3266 index = 1;
3267 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3268 panel->customPaletteHistoryBtn, index),
3269 toName) != 0 ))
3270 index++;
3272 if (index < items) {
3273 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3274 index);
3275 if (index < item)
3276 item--;
3279 } else {
3280 wfree(fromPath);
3281 wfree(toName);
3282 wfree(toPath);
3284 return;
3288 if ( rename(fromPath, toPath) != 0)
3289 wsyserror(_("Couldn't rename palette %s to %s\n"), fromName, toName);
3290 else {
3291 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3292 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3293 toName);
3295 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3297 wfree(fromPath);
3298 wfree(toPath);
3299 wfree(toName);
3304 static void
3305 customPaletteMenuRemove(W_ColorPanel *panel)
3307 W_Screen *scr = WMWidgetScreen(panel->win);
3308 char *text;
3309 char *tmp;
3310 int choice;
3311 int item;
3313 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3315 tmp = wstrconcat( _("This will permanently remove the palette "),
3316 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3317 text = wstrconcat( tmp,
3318 _(".\n\nAre you sure you want to remove this palette ?"));
3319 wfree(tmp);
3321 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"),
3322 NULL);
3323 /* returns 0 (= "Yes") or 1 (="No") */
3324 wfree(text);
3326 if (choice == 0) {
3328 tmp = wstrconcat(panel->configurationPath,
3329 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3331 if ( remove(tmp) == 0) {
3332 /* item-1 always exists */
3333 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3334 item-1);
3336 customPaletteHistoryCallback(panel->customPaletteHistoryBtn,
3337 panel);
3338 customSetPalette(panel);
3340 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3342 } else {
3343 wsyserror(_("Couldn't remove palette %s\n"), tmp);
3346 wfree(tmp);
3351 static void
3352 customPaletteHistoryCallback(WMWidget *w, void *data)
3354 W_ColorPanel *panel = (W_ColorPanel*)data;
3355 W_Screen *scr = WMWidgetScreen(panel->win);
3356 int item;
3357 char *filename;
3358 RImage *tmp = NULL;
3359 unsigned char perm_mask;
3361 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3362 if (item == panel->currentPalette)
3363 return;
3365 if (item == 0) {
3366 customRenderSpectrum(panel);
3368 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3369 False );
3370 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3371 False );
3372 } else {
3373 /* Load file from configpath */
3374 filename = wstrconcat( panel->configurationPath,
3375 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3377 /* If the file corresponding to the item does not exist,
3378 * remove it from the history list and select the next one.
3380 perm_mask = (access(filename, F_OK) == 0);
3381 if (!perm_mask) {
3382 /* File does not exist */
3383 wfree(filename);
3384 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3385 item-1);
3386 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3387 customPaletteHistoryCallback(w, data);
3388 return;
3391 /* Get the image */
3392 tmp = RLoadImage(scr->rcontext, filename, 0);
3393 if (tmp) {
3394 if (panel->customPaletteImg) {
3395 RReleaseImage(panel->customPaletteImg);
3396 panel->customPaletteImg = NULL;
3398 panel->customPaletteImg = tmp;
3401 /* If the image is not writable, don't allow removing/renaming */
3402 perm_mask = (access(filename, W_OK) == 0);
3403 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3404 perm_mask);
3405 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3406 perm_mask);
3408 wfree(filename);
3410 customSetPalette(panel);
3412 panel->currentPalette = item;
3415 /************************* ColorList Panel Functions **********************/
3417 static void
3418 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3419 int state, WMRect *rect)
3421 int width, height, x, y;
3422 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3423 WMScreen *scr = WMWidgetScreen(lPtr);
3424 Display *dpy = WMScreenDisplay(scr);
3425 W_ColorPanel *panel = WMGetHangedData(lPtr);
3426 WMColor *white = WMWhiteColor(scr);
3427 WMColor *black = WMBlackColor(scr);
3428 WMColor *fillColor;
3430 width = rect->size.width;
3431 height = rect->size.height;
3432 x = rect->pos.x;
3433 y = rect->pos.y;
3435 if (state & WLDSSelected)
3436 WMPaintColorSwatch(white, d, x +15, y, width -15, height);
3437 else
3438 XClearArea(dpy, d, x +15, y, width -15, height, False);
3440 fillColor = WMCreateRGBColor(scr, color.red*256, color.green*256,
3441 color.blue*256, False);
3443 WMSetColorInGC(fillColor, WMColorGC(fillColor));
3444 WMPaintColorSwatch(fillColor, d, x, y, 15, 15);
3445 WMReleaseColor(fillColor);
3447 WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
3448 strlen(text));
3450 WMReleaseColor(white);
3451 WMReleaseColor(black);
3455 static void
3456 colorListSelect(WMWidget *w, void *data)
3458 W_ColorPanel *panel = (W_ColorPanel *)data;
3459 CPColor cpColor;
3461 cpColor.rgb = *((RColor *)WMGetListSelectedItem(w)->clientData);
3462 cpColor.set = cpRGB;
3464 panel->lastChanged = WMColorListModeColorPanel;
3465 updateSwatch(panel, cpColor);
3469 static void
3470 colorListColorMenuCallback(WMWidget *w, void *data)
3472 W_ColorPanel *panel = (W_ColorPanel *)data;
3473 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3475 switch (item) {
3476 case CLmenuAdd:
3477 break;
3478 case CLmenuRename:
3479 break;
3480 case CLmenuRemove:
3481 break;
3486 static void
3487 colorListListMenuCallback(WMWidget *w, void *data)
3489 W_ColorPanel *panel = (W_ColorPanel *)data;
3490 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3492 switch (item) {
3493 case CLmenuAdd:
3494 /* New Color List */
3495 colorListListMenuNew(panel);
3496 break;
3497 case CLmenuRename:
3498 break;
3499 case CLmenuRemove:
3500 break;
3505 static void
3506 colorListListMenuNew(W_ColorPanel *panel)
3512 /*************** Panel Initialisation Functions *****************/
3514 static void
3515 wheelInit(W_ColorPanel *panel)
3517 CPColor cpColor;
3519 if (panel->color.set != cpHSV)
3520 convertCPColor(&panel->color);
3522 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3524 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3525 (1 + ( panel->color.hsv.saturation/255.0) *
3526 cos( panel->color.hsv.hue * M_PI/180.0)));
3527 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3528 (1 + ( panel->color.hsv.saturation/255.0) *
3529 sin(- panel->color.hsv.hue*M_PI/180.0)));
3531 wheelCalculateValues(panel, panel->color.hsv.value);
3533 cpColor = panel->color;
3534 cpColor.hsv.value = 255;
3535 cpColor.set = cpHSV;
3536 wheelUpdateBrightnessGradient(panel, cpColor);
3540 static void
3541 grayInit(W_ColorPanel *panel)
3543 int value;
3544 char tmp[4];
3546 if (panel->color.set != cpHSV)
3547 convertCPColor(&panel->color);
3549 value = rint(panel->color.hsv.value/2.55);
3550 WMSetSliderValue(panel->grayBrightnessS, value);
3552 sprintf(tmp, "%d", value);
3553 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3557 static void
3558 rgbInit(W_ColorPanel *panel)
3560 char tmp[4];
3562 if (panel->color.set != cpRGB)
3563 convertCPColor(&panel->color);
3565 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3566 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3567 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3569 sprintf(tmp, "%d", panel->color.rgb.red);
3570 WMSetTextFieldText(panel->rgbRedT, tmp);
3571 sprintf(tmp, "%d", panel->color.rgb.green);
3572 WMSetTextFieldText(panel->rgbGreenT, tmp);
3573 sprintf(tmp, "%d", panel->color.rgb.blue);
3574 WMSetTextFieldText(panel->rgbBlueT, tmp);
3578 static void
3579 cmykInit(W_ColorPanel *panel)
3581 int value[3];
3582 char tmp[4];
3584 if (panel->color.set != cpRGB)
3585 convertCPColor(&panel->color);
3587 value[0] = rint((255-panel->color.rgb.red)/2.55);
3588 value[1] = rint((255-panel->color.rgb.green)/2.55);
3589 value[2] = rint((255-panel->color.rgb.blue)/2.55);
3591 WMSetSliderValue(panel->cmykCyanS, value[0]);
3592 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3593 WMSetSliderValue(panel->cmykYellowS, value[2]);
3594 WMSetSliderValue(panel->cmykBlackS, 0);
3596 sprintf(tmp, "%d", value[0]);
3597 WMSetTextFieldText(panel->cmykCyanT, tmp);
3598 sprintf(tmp, "%d", value[1]);
3599 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3600 sprintf(tmp, "%d", value[2]);
3601 WMSetTextFieldText(panel->cmykYellowT, tmp);
3602 WMSetTextFieldText(panel->cmykBlackT, "0");
3606 static void
3607 hsbInit(W_ColorPanel *panel)
3609 int value[3];
3610 char tmp[4];
3612 if (panel->color.set != cpHSV)
3613 convertCPColor(&panel->color);
3615 value[0] = panel->color.hsv.hue;
3616 value[1] = rint(panel->color.hsv.saturation/2.55);
3617 value[2] = rint(panel->color.hsv.value/2.55);
3619 WMSetSliderValue(panel->hsbHueS,value[0]);
3620 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3621 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3623 sprintf(tmp, "%d", value[0]);
3624 WMSetTextFieldText(panel->hsbHueT, tmp);
3625 sprintf(tmp, "%d", value[1]);
3626 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3627 sprintf(tmp, "%d", value[2]);
3628 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3630 hsbUpdateBrightnessGradient(panel);
3631 hsbUpdateSaturationGradient(panel);
3632 hsbUpdateHueGradient(panel);
3637 /************************** Common utility functions ************************/
3639 static int
3640 fetchFile(char *toPath, char *srcFile, char *destFile)
3642 int src, dest;
3643 int n;
3644 char *tmp;
3645 char buf[BUFSIZE];
3647 if ((src = open(srcFile, O_RDONLY)) == 0) {
3648 wsyserror(_("Could not open %s"), srcFile);
3649 return -1;
3652 tmp = wstrconcat(toPath, destFile);
3653 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3654 == 0) {
3655 wsyserror(_("Could not create %s"), tmp);
3656 wfree(tmp);
3657 return -1;
3659 wfree(tmp);
3662 /* Copy the file */
3663 while ((n = read(src, buf, BUFSIZE)) > 0)
3665 if (write (dest, buf, n) != n) {
3666 wsyserror(_("Write error on file %s"), destFile);
3667 return -1;
3671 return 0;
3675 char*
3676 generateNewFilename(char *curName)
3678 int n;
3679 char c;
3680 int baseLen;
3681 char *ptr;
3682 char *newName;
3685 assert(curName);
3687 ptr = curName;
3689 if (((ptr = strrchr(ptr, '{'))==0) || sscanf(ptr, "{%i}%c", &n, &c)!=1)
3690 return wstrconcat(curName, " {1}");
3692 baseLen = ptr - curName -1;
3694 newName = wmalloc(baseLen + 16);
3695 strncpy(newName, curName, baseLen);
3696 newName[baseLen] = 0;
3698 sprintf(&newName[baseLen], " {%i}", n+1);
3700 return newName;
3704 void
3705 convertCPColor(CPColor *color)
3707 unsigned short old_hue = 0;
3709 switch (color->set) {
3710 case cpNone:
3711 wwarning(_("Color Panel: Color unspecified"));
3712 return;
3713 case cpRGB:
3714 old_hue = color->hsv.hue;
3715 RRGBtoHSV(&(color->rgb), &(color->hsv));
3717 /* In black the hue is undefined, and may change by conversion
3718 * Same for white. */
3719 if (
3720 ((color->rgb.red == 0) &&
3721 (color->rgb.green == 0) &&
3722 (color->rgb.blue == 0)) ||
3723 ((color->rgb.red == 0) &&
3724 (color->rgb.green == 0) &&
3725 (color->rgb.blue == 255))
3727 color->hsv.hue = old_hue;
3728 break;
3729 case cpHSV:
3730 RHSVtoRGB(&(color->hsv), &(color->rgb));
3731 break;
3736 #define ABS_SHIFT(val, shift) \
3737 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3739 RColor
3740 ulongToRColor(WMScreen *scr, unsigned long value)
3742 RColor color;
3743 XColor *xcolor = NULL;
3745 if (!(xcolor = wmalloc(sizeof(XColor)) )) {
3746 wwarning(_("Color Panel: Could not allocate memory"));
3747 color.red = 0;
3748 color.green = 0;
3749 color.blue = 0;
3750 return color;
3753 xcolor->pixel = value;
3754 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3756 color.red = xcolor->red >> 8;
3757 color.green = xcolor->green >> 8;
3758 color.blue = xcolor->blue >> 8;
3760 wfree(xcolor);
3762 return color;
3766 unsigned char
3767 getShift(unsigned char value)
3769 unsigned char i = -1;
3771 if (value == 0)
3772 return 0;
3774 while (value) {
3775 value >>= 1;
3776 i++;
3779 return i;
3784 #ifdef SHAPE_WAS_DEFINED
3785 #undef SHAPE_WAS_DEFINED
3786 #define SHAPE
3787 #endif