changed indentation to use spaces only
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob0da49fbea27452b13da82790bb370f28954aaef6
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 /* Whithout shape extension the magnified image is completely broken -Dan */
40 #if 0
41 # ifdef SHAPE
42 # define SHAPE_WAS_DEFINED
43 # undef SHAPE
44 # endif
45 #endif
48 #ifdef SHAPE
49 # include <X11/extensions/shape.h>
50 #endif
53 #ifndef PATH_MAX
54 # define PATH_MAX 1024
55 #endif
58 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
62 * Bitmaps for magnifying glass cursor
65 /* Cursor */
66 #define Cursor_x_hot 11
67 #define Cursor_y_hot 11
68 #define Cursor_width 32
69 #define Cursor_height 32
70 static unsigned char Cursor_bits[] = {
71 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
72 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
73 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
74 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
75 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
76 0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
77 0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
78 0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
79 0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
81 /* Cursor shape-mask */
82 #define Cursor_shape_width 32
83 #define Cursor_shape_height 32
84 static unsigned char Cursor_shape_bits[] = {
85 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
86 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
87 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
88 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
89 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
90 0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
91 0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
92 0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
93 0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70};
95 /* Clip-mask for magnified pixels */
96 #define Cursor_mask_width 24
97 #define Cursor_mask_height 24
98 static unsigned char Cursor_mask_bits[] = {
99 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
100 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
101 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
102 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
103 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
104 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00};
107 typedef struct MovingView {
108 WMView *view; /* The view this is all about */
109 XImage *image; /* What's under the view */
110 XImage *dirtyRect; /* Storage of overlapped image area */
111 Pixmap magPix; /* Magnified part of pixmap */
112 RColor color; /* Color of a pixel in the image */
113 int x, y; /* Position of view */
114 } MovingView;
116 typedef struct CPColor {
117 RColor rgb; /* The RGB values of the color */
118 RHSVColor hsv; /* The HSV values of the color */
119 enum { /* Which one was last set ? */
120 cpNone,
121 cpRGB,
122 cpHSV
123 } set;
124 } CPColor;
127 typedef struct WheelMatrix {
128 unsigned int width, height; /* Size of the colorwheel */
129 unsigned char *data[3]; /* Wheel data (R,G,B) */
130 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
131 } wheelMatrix;
133 typedef struct W_ColorPanel {
134 WMWindow *win;
135 WMFont *font8;
136 WMFont *font12;
137 void *clientData;
138 WMAction2 *action;
140 /* Common Stuff */
141 WMColorWell *colorWell;
142 WMButton *magnifyBtn;
143 WMButton *wheelBtn;
144 WMButton *slidersBtn;
145 WMButton *customPaletteBtn;
146 WMButton *colorListBtn;
148 /* Magnifying Glass */
149 MovingView *magnifyGlass;
151 /* ColorWheel Panel */
152 WMFrame *wheelFrm;
153 WMSlider *wheelBrightnessS;
154 WMView *wheelView;
156 /* Slider Panels */
157 WMFrame *slidersFrm;
158 WMFrame *seperatorFrm;
159 WMButton *grayBtn;
160 WMButton *rgbBtn;
161 WMButton *cmykBtn;
162 WMButton *hsbBtn;
163 /* Gray Scale Panel */
164 WMFrame *grayFrm;
165 WMLabel *grayMinL;
166 WMLabel *grayMaxL;
167 WMSlider *grayBrightnessS;
168 WMTextField *grayBrightnessT;
169 WMButton *grayPresetBtn[7];
171 /* RGB Panel */
172 WMFrame *rgbFrm;
173 WMLabel *rgbMinL;
174 WMLabel *rgbMaxL;
175 WMSlider *rgbRedS;
176 WMSlider *rgbGreenS;
177 WMSlider *rgbBlueS;
178 WMTextField *rgbRedT;
179 WMTextField *rgbGreenT;
180 WMTextField *rgbBlueT;
182 /* CMYK Panel */
183 WMFrame *cmykFrm;
184 WMLabel *cmykMinL;
185 WMLabel *cmykMaxL;
186 WMSlider *cmykCyanS;
187 WMSlider *cmykMagentaS;
188 WMSlider *cmykYellowS;
189 WMSlider *cmykBlackS;
190 WMTextField *cmykCyanT;
191 WMTextField *cmykMagentaT;
192 WMTextField *cmykYellowT;
193 WMTextField *cmykBlackT;
195 /* HSB Panel */
196 WMFrame *hsbFrm;
197 WMSlider *hsbHueS;
198 WMSlider *hsbSaturationS;
199 WMSlider *hsbBrightnessS;
200 WMTextField *hsbHueT;
201 WMTextField *hsbSaturationT;
202 WMTextField *hsbBrightnessT;
204 /* Custom Palette Panel*/
205 WMFrame *customPaletteFrm;
206 WMPopUpButton *customPaletteHistoryBtn;
207 WMFrame *customPaletteContentFrm;
208 WMPopUpButton *customPaletteMenuBtn;
209 WMView *customPaletteContentView;
211 /* Color List Panel */
212 WMFrame *colorListFrm;
213 WMPopUpButton *colorListHistoryBtn;
214 WMList *colorListContentLst;
215 WMPopUpButton *colorListColorMenuBtn;
216 WMPopUpButton *colorListListMenuBtn;
218 /* Look-Up Tables and Images */
219 wheelMatrix *wheelMtrx;
220 Pixmap wheelImg;
221 Pixmap selectionImg;
222 Pixmap selectionBackImg;
223 RImage *customPaletteImg;
224 char *lastBrowseDir;
226 /* Common Data Fields */
227 CPColor color; /* Current color */
228 WMColorPanelMode mode; /* Current color selection mode */
229 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
230 WMColorPanelMode lastChanged; /* Panel that last changed the color */
231 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
232 int palx, paly; /* (x,y) of sel.-marker in
233 CustomPaletteMode */
234 double palXRatio, palYRatio; /* Ratios in x & y between
235 original and scaled
236 palettesize */
237 int currentPalette;
238 char *configurationPath;
240 struct {
241 unsigned int continuous:1;
242 unsigned int dragging:1;
243 } flags;
244 } W_ColorPanel;
246 enum {
247 CPmenuNewFromFile,
248 CPmenuRename,
249 CPmenuRemove,
250 CPmenuCopy,
251 CPmenuNewFromClipboard
252 } customPaletteMenuItem;
254 enum {
255 CLmenuAdd,
256 CLmenuRename,
257 CLmenuRemove
258 } colorListMenuItem;
261 #define PWIDTH 194
262 #define PHEIGHT 266
263 #define colorWheelSize 150
264 #define customPaletteWidth 182
265 #define customPaletteHeight 106
266 #define knobThickness 8
268 #define SPECTRUM_WIDTH 511
269 #define SPECTRUM_HEIGHT 360
271 #define COLORWHEEL_PART 1
272 #define CUSTOMPALETTE_PART 2
273 #define BUFSIZE 1024
275 #ifndef RGBTXT
276 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
277 #endif
279 #define MAX_LENGTH 1024
282 #ifndef M_PI
283 #define M_PI 3.14159265358979323846
284 #endif
286 /* Silly hack for Windows systems with cygwin */
287 #ifndef O_BINARY
288 # define O_BINARY 0
289 #endif
291 static int fetchFile(char* toPath, char *imageSrcFile,
292 char *imageDestFileName);
293 char *generateNewFilename(char *curName);
294 void convertCPColor(CPColor *color);
295 RColor ulongToRColor(WMScreen *scr, unsigned long value);
296 unsigned char getShift(unsigned char value);
298 static void modeButtonCallback(WMWidget *w, void *data);
299 static int getPickerPart(W_ColorPanel *panel, int x, int y);
300 static void readConfiguration(W_ColorPanel *panel);
301 static void readXColors(W_ColorPanel *panel);
303 static void closeWindowCallback(WMWidget *w, void *data);
305 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
306 static WMPoint magnifyInitialize(W_ColorPanel *panel);
307 static void magnifyPutCursor(WMWidget *w, void *data);
308 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
309 static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1,
310 int x2, int y2);
311 static XImage* magnifyGetImage(WMScreen *scr, XImage *image, int x, int y,
312 int w, int h);
314 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
315 static void wheelDestroyMatrix(wheelMatrix *matrix);
316 static void wheelInitMatrix(W_ColorPanel *panel);
317 static void wheelCalculateValues(W_ColorPanel *panel, int maxvalue);
318 static void wheelRender(W_ColorPanel *panel);
319 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
320 static void wheelPaint(W_ColorPanel *panel);
322 static void wheelHandleEvents(XEvent *event, void *data);
323 static void wheelHandleActionEvents(XEvent *event, void *data);
324 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
325 static void wheelUpdateSelection(W_ColorPanel *panel);
326 static void wheelUndrawSelection(W_ColorPanel *panel);
328 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
329 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
330 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
331 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor);
333 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
334 static void grayPresetButtonCallback(WMWidget *w, void *data);
335 static void grayBrightnessTextFieldCallback(void *observerData,
336 WMNotification *notification);
338 static void rgbSliderCallback(WMWidget *w, void *data);
339 static void rgbTextFieldCallback(void *observerData,
340 WMNotification *notification);
342 static void cmykSliderCallback(WMWidget *w, void *data);
343 static void cmykTextFieldCallback(void *observerData,
344 WMNotification *notification);
346 static void hsbSliderCallback(WMWidget *w, void *data);
347 static void hsbTextFieldCallback(void *observerData,
348 WMNotification *notification);
349 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
350 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
351 static void hsbUpdateHueGradient(W_ColorPanel *panel);
353 static void customRenderSpectrum(W_ColorPanel *panel);
354 static void customSetPalette(W_ColorPanel *panel);
355 static void customPaletteHandleEvents(XEvent *event, void *data);
356 static void customPaletteHandleActionEvents(XEvent *event, void *data);
357 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
358 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
359 int x, int y);
360 static void customPaletteMenuCallback(WMWidget *w, void *data);
361 static void customPaletteHistoryCallback(WMWidget *w, void *data);
363 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
364 static void customPaletteMenuRename(W_ColorPanel *panel);
365 static void customPaletteMenuRemove(W_ColorPanel *panel);
367 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
368 int state, WMRect *rect);
369 static void colorListSelect(WMWidget *w, void *data);
370 static void colorListColorMenuCallback(WMWidget *w, void *data);
371 static void colorListListMenuCallback(WMWidget *w, void *data);
372 static void colorListListMenuNew(W_ColorPanel *panel);
374 static void wheelInit(W_ColorPanel *panel);
375 static void grayInit(W_ColorPanel *panel);
376 static void rgbInit(W_ColorPanel *panel);
377 static void cmykInit(W_ColorPanel *panel);
378 static void hsbInit(W_ColorPanel *panel);
382 void
383 WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
385 panel->action = action;
386 panel->clientData = data;
389 static WMColorPanel*
390 makeColorPanel(WMScreen *scrPtr, char *name)
392 WMColorPanel *panel;
393 RImage *image;
394 WMPixmap *pixmap;
395 RColor from;
396 RColor to;
397 WMColor *textcolor, *graybuttoncolor;
398 int i;
399 GC bgc = WMColorGC(scrPtr->black);
400 GC wgc = WMColorGC(scrPtr->white);
403 panel = wmalloc(sizeof(WMColorPanel));
404 memset(panel, 0, sizeof(WMColorPanel));
406 panel->color.rgb.red = 0;
407 panel->color.rgb.green = 0;
408 panel->color.rgb.blue = 0;
409 panel->color.hsv.hue = 0;
410 panel->color.hsv.saturation = 0;
411 panel->color.hsv.value = 0;
412 panel->color.set = cpNone; /* Color has not been set yet */
414 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
415 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
417 panel->win = WMCreateWindowWithStyle(scrPtr, name,
418 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
419 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
420 WMSetWindowTitle(panel->win, _("Colors"));
421 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
424 /* Set Default ColorPanel Mode(s) */
425 panel->mode = WMWheelModeColorPanel;
426 panel->lastChanged = 0;
427 panel->slidersmode = WMRGBModeColorPanel;
428 panel->configurationPath = wstrconcat(wusergnusteppath(),
429 "/Library/Colors/");
431 /* Some General Purpose Widgets */
432 panel->colorWell = WMCreateColorWell(panel->win);
433 WMResizeWidget(panel->colorWell, 134, 36);
434 WSetColorWellBordered(panel->colorWell, False);
435 WMMoveWidget(panel->colorWell, 56, 4);
437 panel->magnifyBtn = WMCreateCustomButton(panel->win,
438 WBBStateLightMask|WBBStateChangeMask);
439 WMResizeWidget(panel->magnifyBtn, 46, 36);
440 WMMoveWidget(panel->magnifyBtn, 6,4);
441 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
442 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
443 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
445 panel->wheelBtn = WMCreateCustomButton(panel->win,
446 WBBStateLightMask|WBBStateChangeMask);
447 WMResizeWidget(panel->wheelBtn, 46, 32);
448 WMMoveWidget(panel->wheelBtn, 6, 44);
449 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
450 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
451 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
453 panel->slidersBtn = WMCreateCustomButton(panel->win,
454 WBBStateLightMask|WBBStateChangeMask);
455 WMResizeWidget(panel->slidersBtn, 46, 32);
456 WMMoveWidget(panel->slidersBtn, 52, 44);
457 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
458 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
459 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
461 panel->customPaletteBtn = WMCreateCustomButton(panel->win,
462 WBBStateLightMask|WBBStateChangeMask);
463 WMResizeWidget(panel->customPaletteBtn, 46, 32);
464 WMMoveWidget(panel->customPaletteBtn, 98, 44);
465 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
466 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
467 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
469 panel->colorListBtn = WMCreateCustomButton(panel->win,
470 WBBStateLightMask|WBBStateChangeMask);
471 WMResizeWidget(panel->colorListBtn, 46, 32);
472 WMMoveWidget(panel->colorListBtn, 144, 44);
473 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
474 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
475 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
477 /* Let's Group some of them together */
478 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
479 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
480 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
482 /* Widgets for the ColorWheel Panel */
483 panel->wheelFrm = WMCreateFrame(panel->win);
484 WMSetFrameRelief(panel->wheelFrm, WRFlat);
485 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
486 WMMoveWidget(panel->wheelFrm, 5, 80);
488 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
489 /* XXX Can we create a view ? */
490 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
491 W_MoveView(panel->wheelView, 0, 0);
493 /* Create an event handler to handle expose/click events in ColorWheel */
494 WMCreateEventHandler(panel->wheelView,
495 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
496 LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
498 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
499 panel);
501 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
502 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
503 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
504 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
505 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
506 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
507 panel);
508 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
510 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
511 wheelInitMatrix(panel);
514 /* Widgets for the Slider Panels */
515 panel->slidersFrm = WMCreateFrame(panel->win);
516 WMSetFrameRelief(panel->slidersFrm, WRFlat);
517 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
518 WMMoveWidget(panel->slidersFrm, 4, 80);
520 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
521 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
522 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
523 WMMoveWidget(panel->seperatorFrm, 0, 1);
525 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
526 WBBStateLightMask|WBBStateChangeMask);
527 WMResizeWidget(panel->grayBtn, 46, 24);
528 WMMoveWidget(panel->grayBtn, 1, 8);
529 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
530 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
531 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
533 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
534 WBBStateLightMask|WBBStateChangeMask);
535 WMResizeWidget(panel->rgbBtn, 46, 24);
536 WMMoveWidget(panel->rgbBtn, 47, 8);
537 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
538 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
539 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
541 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
542 WBBStateLightMask|WBBStateChangeMask);
543 WMResizeWidget(panel->cmykBtn, 46, 24);
544 WMMoveWidget(panel->cmykBtn, 93, 8);
545 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
546 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
547 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
549 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
550 WBBStateLightMask|WBBStateChangeMask);
551 WMResizeWidget(panel->hsbBtn, 46, 24);
552 WMMoveWidget(panel->hsbBtn, 139, 8);
553 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
554 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
555 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
557 /* Let's Group the Slider Panel Buttons Together */
558 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
559 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
560 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
562 textcolor = WMDarkGrayColor(scrPtr);
564 /* Widgets for GrayScale Panel */
565 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
566 WMSetFrameRelief(panel->grayFrm, WRFlat);
567 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
568 WMMoveWidget(panel->grayFrm, 0, 34);
570 panel->grayMinL = WMCreateLabel(panel->grayFrm);
571 WMResizeWidget(panel->grayMinL, 20, 10);
572 WMMoveWidget(panel->grayMinL, 2, 2);
573 WMSetLabelText(panel->grayMinL, "0");
574 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
575 WMSetLabelTextColor(panel->grayMinL, textcolor);
576 WMSetLabelFont(panel->grayMinL, panel->font8);
578 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
579 WMResizeWidget(panel->grayMaxL, 40, 10);
580 WMMoveWidget(panel->grayMaxL, 104, 2);
581 WMSetLabelText(panel->grayMaxL, "100");
582 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
583 WMSetLabelTextColor(panel->grayMaxL, textcolor);
584 WMSetLabelFont(panel->grayMaxL, panel->font8);
586 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
587 WMResizeWidget(panel->grayBrightnessS, 141, 16);
588 WMMoveWidget(panel->grayBrightnessS, 2, 14);
589 WMSetSliderMinValue(panel->grayBrightnessS, 0);
590 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
591 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
592 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
593 panel);
595 from.red = 0;
596 from.green = 0;
597 from.blue = 0;
599 to.red = 255;
600 to.green = 255;
601 to.blue = 255;
603 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
604 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
605 RReleaseImage(image);
607 if (pixmap)
608 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
609 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
610 False, _("Brightness"), strlen(_("Brightness")));
611 else
612 wwarning(_("Color Panel: Could not allocate memory"));
614 WMSetSliderImage(panel->grayBrightnessS, pixmap);
615 WMReleasePixmap(pixmap);
617 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
618 WMResizeWidget(panel->grayBrightnessT, 40, 18);
619 WMMoveWidget(panel->grayBrightnessT, 146, 13);
620 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
621 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
622 WMTextDidEndEditingNotification, panel->grayBrightnessT);
624 for (i=0; i < 7; i++) {
625 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
627 graybuttoncolor = WMCreateRGBColor(scrPtr, (255/6)*i << 8,
628 (255/6)*i << 8, (255/6)*i << 8, True);
629 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
630 WMReleaseColor(graybuttoncolor);
632 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
633 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
634 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
635 WMSetButtonAction(panel->grayPresetBtn[i],
636 grayPresetButtonCallback, panel);
637 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
638 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
639 WMReleasePixmap(pixmap);
643 /* End of GrayScale Panel */
645 /* Widgets for RGB Panel */
646 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
647 WMSetFrameRelief(panel->rgbFrm, WRFlat);
648 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
649 WMMoveWidget(panel->rgbFrm, 0, 34);
651 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
652 WMResizeWidget(panel->rgbMinL, 20, 10);
653 WMMoveWidget(panel->rgbMinL, 2, 2);
654 WMSetLabelText(panel->rgbMinL, "0");
655 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
656 WMSetLabelTextColor(panel->rgbMinL, textcolor);
657 WMSetLabelFont(panel->rgbMinL, panel->font8);
659 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
660 WMResizeWidget(panel->rgbMaxL, 40, 10);
661 WMMoveWidget(panel->rgbMaxL, 104, 2);
662 WMSetLabelText(panel->rgbMaxL, "255");
663 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
664 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
665 WMSetLabelFont(panel->rgbMaxL, panel->font8);
667 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
668 WMResizeWidget(panel->rgbRedS, 141, 16);
669 WMMoveWidget(panel->rgbRedS, 2, 14);
670 WMSetSliderMinValue(panel->rgbRedS, 0);
671 WMSetSliderMaxValue(panel->rgbRedS, 255);
672 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
673 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
675 to.red = 255;
676 to.green = 0;
677 to.blue = 0;
679 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
680 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
681 RReleaseImage(image);
683 if (pixmap)
684 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
685 2, 0, 100, WALeft, scrPtr->white, False, _("Red"),
686 strlen(_("Red")));
687 else
688 wwarning(_("Color Panel: Could not allocate memory"));
690 WMSetSliderImage(panel->rgbRedS, pixmap);
691 WMReleasePixmap(pixmap);
693 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
694 WMResizeWidget(panel->rgbRedT, 40, 18);
695 WMMoveWidget(panel->rgbRedT, 146, 13);
696 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
697 WMAddNotificationObserver(rgbTextFieldCallback, panel,
698 WMTextDidEndEditingNotification, panel->rgbRedT);
700 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
701 WMResizeWidget(panel->rgbGreenS, 141, 16);
702 WMMoveWidget(panel->rgbGreenS, 2, 36);
703 WMSetSliderMinValue(panel->rgbGreenS, 0);
704 WMSetSliderMaxValue(panel->rgbGreenS, 255);
705 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
706 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
708 to.red = 0;
709 to.green = 255;
710 to.blue = 0;
712 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
713 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
714 RReleaseImage(image);
716 if (pixmap)
717 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
718 2, 0, 100, WALeft, scrPtr->white, False, _("Green"),
719 strlen(_("Green")));
720 else
721 wwarning(_("Color Panel: Could not allocate memory"));
723 WMSetSliderImage(panel->rgbGreenS, pixmap);
724 WMReleasePixmap(pixmap);
726 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
727 WMResizeWidget(panel->rgbGreenT, 40, 18);
728 WMMoveWidget(panel->rgbGreenT, 146, 35);
729 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
730 WMAddNotificationObserver(rgbTextFieldCallback, panel,
731 WMTextDidEndEditingNotification, panel->rgbGreenT);
734 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
735 WMResizeWidget(panel->rgbBlueS, 141, 16);
736 WMMoveWidget(panel->rgbBlueS, 2, 58);
737 WMSetSliderMinValue(panel->rgbBlueS, 0);
738 WMSetSliderMaxValue(panel->rgbBlueS, 255);
739 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
740 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
742 to.red = 0;
743 to.green = 0;
744 to.blue = 255;
746 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
747 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
748 RReleaseImage(image);
750 if (pixmap)
751 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
752 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"),
753 strlen(_("Blue")));
754 else
755 wwarning(_("Color Panel: Could not allocate memory"));
757 WMSetSliderImage(panel->rgbBlueS, pixmap);
758 WMReleasePixmap(pixmap);
760 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
761 WMResizeWidget(panel->rgbBlueT, 40, 18);
762 WMMoveWidget(panel->rgbBlueT, 146, 57);
763 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
764 WMAddNotificationObserver(rgbTextFieldCallback, panel,
765 WMTextDidEndEditingNotification, panel->rgbBlueT);
766 /* End of RGB Panel */
768 /* Widgets for CMYK Panel */
769 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
770 WMSetFrameRelief(panel->cmykFrm, WRFlat);
771 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
772 WMMoveWidget(panel->cmykFrm, 0, 34);
774 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
775 WMResizeWidget(panel->cmykMinL, 20, 10);
776 WMMoveWidget(panel->cmykMinL, 2, 2);
777 WMSetLabelText(panel->cmykMinL, "0");
778 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
779 WMSetLabelTextColor(panel->cmykMinL, textcolor);
780 WMSetLabelFont(panel->cmykMinL, panel->font8);
782 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
783 WMResizeWidget(panel->cmykMaxL, 40, 10);
784 WMMoveWidget(panel->cmykMaxL, 104, 2);
785 WMSetLabelText(panel->cmykMaxL, "100");
786 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
787 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
788 WMSetLabelFont(panel->cmykMaxL, panel->font8);
790 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
791 WMResizeWidget(panel->cmykCyanS, 141, 16);
792 WMMoveWidget(panel->cmykCyanS, 2, 14);
793 WMSetSliderMinValue(panel->cmykCyanS, 0);
794 WMSetSliderMaxValue(panel->cmykCyanS, 100);
795 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
796 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
798 from.red = 255;
799 from.green = 255;
800 from.blue = 255;
802 to.red = 0;
803 to.green = 255;
804 to.blue = 255;
806 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
807 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
808 RReleaseImage(image);
810 if (pixmap)
811 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
812 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"),
813 strlen(_("Cyan")));
814 else
815 wwarning(_("Color Panel: Could not allocate memory"));
817 WMSetSliderImage(panel->cmykCyanS, pixmap);
818 WMReleasePixmap(pixmap);
820 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
821 WMResizeWidget(panel->cmykCyanT, 40, 18);
822 WMMoveWidget(panel->cmykCyanT, 146, 13);
823 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
824 WMAddNotificationObserver(cmykTextFieldCallback, panel,
825 WMTextDidEndEditingNotification, panel->cmykCyanT);
828 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
829 WMResizeWidget(panel->cmykMagentaS, 141, 16);
830 WMMoveWidget(panel->cmykMagentaS, 2, 36);
831 WMSetSliderMinValue(panel->cmykMagentaS, 0);
832 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
833 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
834 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
836 to.red = 255;
837 to.green = 0;
838 to.blue = 255;
840 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
841 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
842 RReleaseImage(image);
844 if (pixmap)
845 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
846 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"),
847 strlen(_("Magenta")));
848 else
849 wwarning(_("Color Panel: Could not allocate memory"));
851 WMSetSliderImage(panel->cmykMagentaS, pixmap);
852 WMReleasePixmap(pixmap);
854 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
855 WMResizeWidget(panel->cmykMagentaT, 40, 18);
856 WMMoveWidget(panel->cmykMagentaT, 146, 35);
857 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
858 WMAddNotificationObserver(cmykTextFieldCallback, panel,
859 WMTextDidEndEditingNotification, panel->cmykMagentaT);
862 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
863 WMResizeWidget(panel->cmykYellowS, 141, 16);
864 WMMoveWidget(panel->cmykYellowS, 2, 58);
865 WMSetSliderMinValue(panel->cmykYellowS, 0);
866 WMSetSliderMaxValue(panel->cmykYellowS, 100);
867 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
868 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
870 to.red = 255;
871 to.green = 255;
872 to.blue = 0;
874 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
875 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
876 RReleaseImage(image);
878 if (pixmap)
879 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
880 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"),
881 strlen(_("Yellow")));
882 else
883 wwarning(_("Color Panel: Could not allocate memory"));
885 WMSetSliderImage(panel->cmykYellowS, pixmap);
886 WMReleasePixmap(pixmap);
888 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
889 WMResizeWidget(panel->cmykYellowT, 40, 18);
890 WMMoveWidget(panel->cmykYellowT, 146, 57);
891 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
892 WMAddNotificationObserver(cmykTextFieldCallback, panel,
893 WMTextDidEndEditingNotification, panel->cmykYellowT);
896 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
897 WMResizeWidget(panel->cmykBlackS, 141, 16);
898 WMMoveWidget(panel->cmykBlackS, 2, 80);
899 WMSetSliderMinValue(panel->cmykBlackS, 0);
900 WMSetSliderMaxValue(panel->cmykBlackS, 100);
901 WMSetSliderValue(panel->cmykBlackS, 0);
902 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
903 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
905 to.red = 0;
906 to.green = 0;
907 to.blue = 0;
909 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
910 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
911 RReleaseImage(image);
913 if (pixmap)
914 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
915 2, 0, 100, WALeft, scrPtr->black, False, _("Black"),
916 strlen(_("Black")));
917 else
918 wwarning(_("Color Panel: Could not allocate memory"));
920 WMSetSliderImage(panel->cmykBlackS, pixmap);
921 WMReleasePixmap(pixmap);
923 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
924 WMResizeWidget(panel->cmykBlackT, 40, 18);
925 WMMoveWidget(panel->cmykBlackT, 146, 79);
926 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
927 WMAddNotificationObserver(cmykTextFieldCallback, panel,
928 WMTextDidEndEditingNotification, panel->cmykBlackT);
929 /* End of CMYK Panel */
931 /* Widgets for HSB Panel */
932 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
933 WMSetFrameRelief(panel->hsbFrm, WRFlat);
934 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
935 WMMoveWidget(panel->hsbFrm, 0, 34);
937 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
938 WMResizeWidget(panel->hsbHueS, 141, 16);
939 WMMoveWidget(panel->hsbHueS, 2, 14);
940 WMSetSliderMinValue(panel->hsbHueS, 0);
941 WMSetSliderMaxValue(panel->hsbHueS, 359);
942 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
943 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
945 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
946 WMResizeWidget(panel->hsbHueT, 40, 18);
947 WMMoveWidget(panel->hsbHueT, 146, 13);
948 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
949 WMAddNotificationObserver(hsbTextFieldCallback, panel,
950 WMTextDidEndEditingNotification, panel->hsbHueT);
953 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
954 WMResizeWidget(panel->hsbSaturationS, 141, 16);
955 WMMoveWidget(panel->hsbSaturationS, 2, 36);
956 WMSetSliderMinValue(panel->hsbSaturationS, 0);
957 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
958 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
959 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
961 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
962 WMResizeWidget(panel->hsbSaturationT, 40, 18);
963 WMMoveWidget(panel->hsbSaturationT, 146, 35);
964 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
965 WMAddNotificationObserver(hsbTextFieldCallback, panel,
966 WMTextDidEndEditingNotification, panel->hsbSaturationT);
969 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
970 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
971 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
972 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
973 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
974 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
975 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
977 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
978 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
979 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
980 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
981 WMAddNotificationObserver(hsbTextFieldCallback, panel,
982 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
983 /* End of HSB Panel */
986 WMReleaseColor(textcolor);
988 /* Widgets for the CustomPalette Panel */
989 panel->customPaletteFrm = WMCreateFrame(panel->win);
990 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
991 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
992 WMMoveWidget(panel->customPaletteFrm, 5, 80);
994 panel->customPaletteHistoryBtn = WMCreatePopUpButton(
995 panel->customPaletteFrm);
996 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
997 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
998 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
999 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
1000 customPaletteHistoryCallback, panel);
1001 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
1002 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
1004 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
1005 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
1006 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
1007 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
1009 panel->customPaletteContentView = W_CreateView(
1010 W_VIEW(panel->customPaletteContentFrm));
1011 /* XXX Test if we can create a view */
1012 W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
1013 customPaletteHeight);
1014 W_MoveView(panel->customPaletteContentView, 2, 2);
1016 /* Create event handler to handle expose/click events in CustomPalette */
1017 WMCreateEventHandler(panel->customPaletteContentView,
1018 ButtonPressMask|ButtonReleaseMask|EnterWindowMask| LeaveWindowMask |
1019 ButtonMotionMask, customPaletteHandleActionEvents, panel);
1021 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
1022 customPaletteHandleEvents, panel);
1024 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
1025 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
1026 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
1027 WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
1028 customPaletteMenuCallback, panel);
1029 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
1030 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
1032 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
1033 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
1034 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
1035 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
1036 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
1038 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
1039 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
1040 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
1041 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
1042 CPmenuNewFromClipboard, 0);
1044 customRenderSpectrum(panel);
1045 panel->currentPalette = 0;
1046 panel->palx = customPaletteWidth/2;
1047 panel->paly = customPaletteHeight/2;
1050 /* Widgets for the ColorList Panel */
1051 panel->colorListFrm = WMCreateFrame(panel->win);
1052 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1053 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1054 WMMoveWidget(panel->colorListFrm, 5, 80);
1056 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1057 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1058 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1059 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
1060 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1061 * colorListHistoryCallback, panel); */
1062 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1063 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1065 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1066 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1067 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1068 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1069 WMMoveWidget(panel->colorListContentLst, 0, 23);
1070 WMHangData(panel->colorListContentLst, panel);
1072 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1073 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1074 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1075 WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
1076 colorListColorMenuCallback, panel);
1077 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
1078 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1080 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1081 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1082 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1084 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1085 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1086 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1088 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1089 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1090 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1091 WMSetPopUpButtonAction(panel->colorListListMenuBtn,
1092 colorListListMenuCallback, panel);
1093 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
1094 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
1095 PHEIGHT - 130);
1097 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1098 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1099 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1101 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1102 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1103 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1105 WMRealizeWidget(panel->win);
1106 WMMapSubwidgets(panel->win);
1108 WMMapSubwidgets(panel->wheelFrm);
1109 WMMapSubwidgets(panel->slidersFrm);
1110 WMMapSubwidgets(panel->grayFrm);
1111 WMMapSubwidgets(panel->rgbFrm);
1112 WMMapSubwidgets(panel->cmykFrm);
1113 WMMapSubwidgets(panel->hsbFrm);
1114 WMMapSubwidgets(panel->customPaletteFrm);
1115 WMMapSubwidgets(panel->customPaletteContentFrm);
1116 WMMapSubwidgets(panel->colorListFrm);
1118 /* Pixmap to indicate selection positions
1119 * wheelframe MUST be mapped.
1121 panel->selectionImg = XCreatePixmap(scrPtr->display,
1122 WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1123 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1124 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1126 readConfiguration(panel);
1127 readXColors(panel);
1129 return panel;
1133 WMColorPanel*
1134 WMGetColorPanel(WMScreen *scrPtr)
1136 WMColorPanel *panel;
1138 if (scrPtr->sharedColorPanel)
1139 return scrPtr->sharedColorPanel;
1141 panel = makeColorPanel(scrPtr, "colorPanel");
1143 scrPtr->sharedColorPanel = panel;
1145 return panel;
1149 void
1150 WMFreeColorPanel(WMColorPanel *panel)
1152 W_Screen *scr = WMWidgetScreen(panel->win);
1154 if (panel == scr->sharedColorPanel) {
1155 scr->sharedColorPanel = NULL;
1158 if (!panel)
1159 return;
1161 WMRemoveNotificationObserver(panel);
1162 WMUnmapWidget(panel->win);
1164 /* fonts */
1165 WMReleaseFont(panel->font8);
1166 WMReleaseFont(panel->font12);
1168 /* pixmaps */
1169 wheelDestroyMatrix(panel->wheelMtrx);
1170 if (panel->wheelImg)
1171 XFreePixmap(scr->display, panel->wheelImg);
1172 if (panel->selectionImg)
1173 XFreePixmap(scr->display, panel->selectionImg);
1174 if (panel->selectionBackImg)
1175 XFreePixmap(scr->display, panel->selectionBackImg);
1176 RReleaseImage(panel->customPaletteImg);
1178 /* structs */
1179 if (panel->lastBrowseDir)
1180 wfree(panel->lastBrowseDir);
1181 if (panel->configurationPath)
1182 wfree(panel->configurationPath);
1184 WMDestroyWidget(panel->win);
1186 wfree(panel);
1190 void
1191 WMCloseColorPanel(WMColorPanel *panel)
1193 WMFreeColorPanel(panel);
1197 void
1198 WMShowColorPanel(WMColorPanel *panel)
1200 WMScreen *scr = WMWidgetScreen(panel->win);
1201 WMColor *white = WMWhiteColor(scr);
1203 if (panel->color.set == cpNone)
1204 WMSetColorPanelColor(panel, white);
1205 WMReleaseColor(white);
1207 if (panel->mode != WMWheelModeColorPanel)
1208 WMPerformButtonClick(panel->wheelBtn);
1210 WMMapWidget(panel->win);
1214 static void
1215 closeWindowCallback(WMWidget *w, void *data)
1217 W_ColorPanel *panel = (W_ColorPanel*)data;
1219 WMCloseColorPanel(panel);
1223 static void
1224 readConfiguration(W_ColorPanel *panel)
1226 /* XXX Doesn't take care of "invalid" files */
1228 DIR *dPtr;
1229 struct dirent *dp;
1230 struct stat stat_buf;
1231 int item;
1233 if (stat(panel->configurationPath, &stat_buf)!=0) {
1234 if (mkdir(panel->configurationPath,
1235 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1236 wsyserror(_("Color Panel: Could not create directory %s needed"
1237 " to store configurations"), panel->configurationPath);
1238 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1239 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1240 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1241 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1242 _("File Error"),
1243 _("Could not create ColorPanel configuration directory"),
1244 _("OK"), NULL, NULL);
1246 return;
1249 if (!(dPtr = opendir(panel->configurationPath))) {
1250 wwarning(_("Color Panel: Could not find file"), "%s", panel->configurationPath);
1251 return;
1254 while ((dp = readdir(dPtr)) != NULL) {
1255 unsigned int perm_mask;
1256 char *path = wstrconcat(panel->configurationPath,
1257 dp->d_name);
1259 if (dp->d_name[0] != '.') {
1260 item = WMGetPopUpButtonNumberOfItems(
1261 panel->customPaletteHistoryBtn);
1262 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1264 perm_mask = (access(path, R_OK) == 0);
1265 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn,
1266 item, perm_mask);
1268 wfree(path);
1270 (void)closedir(dPtr);
1274 static void
1275 readXColors(W_ColorPanel *panel)
1277 struct stat stat_buf;
1278 FILE *rgbtxt;
1279 char line[MAX_LENGTH];
1280 int red, green, blue;
1281 char name[48];
1282 RColor *color;
1283 WMListItem *item;
1285 if (stat(RGBTXT, &stat_buf) != 0) {
1286 wsyserror(_("Color Panel: Could not find file"), " %s", RGBTXT);
1287 return;
1289 else {
1290 if ((rgbtxt = fopen(RGBTXT, "rb"))) {
1291 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1292 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1293 color = wmalloc(sizeof(RColor));
1294 color->red = (unsigned char)red;
1295 color->green = (unsigned char)green;
1296 color->blue = (unsigned char)blue;
1297 item = WMAddListItem(panel->colorListContentLst, name);
1298 item->clientData = (void *)color;
1301 fclose(rgbtxt);
1303 else {
1304 wsyserror(_("Color Panel: Could not find file"), "%s", RGBTXT);
1310 void
1311 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1313 W_Screen *scr = WMWidgetScreen(panel->win);
1315 if (mode != WMWheelModeColorPanel) {
1316 WMUnmapWidget(panel->wheelFrm);
1317 if (panel->selectionBackImg) {
1318 XFreePixmap(WMWidgetScreen(panel->win)->display,
1319 panel->selectionBackImg);
1320 panel->selectionBackImg = None;
1323 if (mode != WMGrayModeColorPanel)
1324 WMUnmapWidget(panel->grayFrm);
1325 if (mode != WMRGBModeColorPanel)
1326 WMUnmapWidget(panel->rgbFrm);
1327 if (mode != WMCMYKModeColorPanel)
1328 WMUnmapWidget(panel->cmykFrm);
1329 if (mode != WMHSBModeColorPanel)
1330 WMUnmapWidget(panel->hsbFrm);
1331 if (mode != WMCustomPaletteModeColorPanel) {
1332 WMUnmapWidget(panel->customPaletteFrm);
1333 if (panel->selectionBackImg) {
1334 XFreePixmap(WMWidgetScreen(panel->win)->display,
1335 panel->selectionBackImg);
1336 panel->selectionBackImg = None;
1339 if (mode != WMColorListModeColorPanel)
1340 WMUnmapWidget(panel->colorListFrm);
1341 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1342 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1343 WMUnmapWidget(panel->slidersFrm);
1344 else
1345 panel->slidersmode = mode;
1347 if (mode == WMWheelModeColorPanel) {
1348 WMMapWidget(panel->wheelFrm);
1349 WMSetButtonSelected(panel->wheelBtn, True);
1350 if (panel->lastChanged != WMWheelModeColorPanel)
1351 wheelInit(panel);
1352 wheelRender(panel);
1353 wheelPaint(panel);
1354 } else if (mode == WMGrayModeColorPanel) {
1355 WMMapWidget(panel->slidersFrm);
1356 WMSetButtonSelected(panel->slidersBtn, True);
1357 WMMapWidget(panel->grayFrm);
1358 WMSetButtonSelected(panel->grayBtn, True);
1359 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1360 if (panel->lastChanged != WMGrayModeColorPanel)
1361 grayInit(panel);
1362 } else if (mode == WMRGBModeColorPanel) {
1363 WMMapWidget(panel->slidersFrm);
1364 WMSetButtonSelected(panel->slidersBtn, True);
1365 WMMapWidget(panel->rgbFrm);
1366 WMSetButtonSelected(panel->rgbBtn, True);
1367 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1368 if (panel->lastChanged != WMRGBModeColorPanel)
1369 rgbInit(panel);
1370 } else if (mode == WMCMYKModeColorPanel) {
1371 WMMapWidget(panel->slidersFrm);
1372 WMSetButtonSelected(panel->slidersBtn, True);
1373 WMMapWidget(panel->cmykFrm);
1374 WMSetButtonSelected(panel->cmykBtn, True);
1375 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1376 if (panel->lastChanged != WMCMYKModeColorPanel)
1377 cmykInit(panel);
1378 } else if (mode == WMHSBModeColorPanel) {
1379 WMMapWidget(panel->slidersFrm);
1380 WMSetButtonSelected(panel->slidersBtn, True);
1381 WMMapWidget(panel->hsbFrm);
1382 WMSetButtonSelected(panel->hsbBtn, True);
1383 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1384 if (panel->lastChanged != WMHSBModeColorPanel)
1385 hsbInit(panel);
1386 } else if (mode == WMCustomPaletteModeColorPanel) {
1387 WMMapWidget(panel->customPaletteFrm);
1388 WMSetButtonSelected(panel->customPaletteBtn, True);
1389 customSetPalette(panel);
1390 } else if (mode == WMColorListModeColorPanel) {
1391 WMMapWidget(panel->colorListFrm);
1392 WMSetButtonSelected(panel->colorListBtn, True);
1395 panel->mode = mode;
1399 WMColor*
1400 WMGetColorPanelColor(WMColorPanel *panel)
1402 return WMGetColorWellColor(panel->colorWell);
1406 void
1407 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1409 WMSetColorWellColor(panel->colorWell, color);
1411 panel->color.rgb.red = color->color.red >> 8;
1412 panel->color.rgb.green = color->color.green >> 8;
1413 panel->color.rgb.blue = color->color.blue >> 8;
1414 panel->color.set = cpRGB;
1416 if (panel->mode == panel->lastChanged)
1417 panel->lastChanged = 0;
1419 WMSetColorPanelPickerMode(panel, panel->mode);
1423 static void
1424 updateSwatch(WMColorPanel *panel, CPColor color)
1426 WMScreen *scr = WMWidgetScreen(panel->win);
1427 WMColor *wellcolor;
1429 if (color.set != cpRGB)
1430 convertCPColor(&color);
1432 panel->color = color;
1434 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8,
1435 color.rgb.green << 8,
1436 color.rgb.blue << 8, True);
1438 WMSetColorWellColor(panel->colorWell, wellcolor);
1439 WMReleaseColor(wellcolor);
1441 if (!panel->flags.dragging || panel->flags.continuous) {
1442 if (panel->action)
1443 (*panel->action)(panel, panel->clientData);
1445 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1446 NULL);
1450 static void
1451 modeButtonCallback(WMWidget *w, void *data)
1453 W_ColorPanel *panel = (W_ColorPanel*)(data);
1455 if (w == panel->wheelBtn)
1456 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1457 else if (w == panel->slidersBtn)
1458 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1459 else if (w == panel->customPaletteBtn)
1460 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1461 else if (w == panel->colorListBtn)
1462 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1463 else if (w == panel->grayBtn)
1464 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1465 else if (w == panel->rgbBtn)
1466 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1467 else if (w == panel->cmykBtn)
1468 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1469 else if (w == panel->hsbBtn)
1470 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1474 /****************** Magnifying Cursor Functions *******************/
1476 static XImage*
1477 magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
1479 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1480 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1481 displayHeight = DisplayHeight(scr->display, scr->screen);
1483 if (!(image && image->data)) {
1484 /* The image in panel->magnifyGlass->image does not exist yet.
1485 * Grab one from the screen (not beyond) and use it from now on.
1487 if (!(image = XGetImage(scr->display, scr->rootWin,
1488 x - Cursor_x_hot,
1489 y - Cursor_y_hot,
1490 w, h, AllPlanes, ZPixmap)))
1491 wwarning(_("Color Panel: X failed request"));
1493 return image;
1496 /* Coordinate correction for back pixmap
1497 * if magnifying glass is at screen-borders
1500 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1501 * Hatched area is beyond screen border.
1503 * |<-Cursor_x_hot->|
1504 * ________________|_____
1505 * |/ / / / / / /| | |
1506 * | / / / / / / |(x,y) |
1507 * |/_/_/_/_/_/_/|________|
1508 * |<----x0----->|<--w0-->|
1512 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1513 * screen borders
1514 * Hatched area is beyond screen border
1516 * |<-Cursor_x_hot->|
1517 * ________________|_______________
1518 * | | | / / / / / /|
1519 * | (x,y)|/ / / / / / |
1520 * |___________________|_/_/_/_/_/_/|
1521 * |<-------w0-------->| |
1522 * |<---------------w--|----------->|
1523 * | |
1524 * x0 Displaywidth-1
1527 if (x < Cursor_x_hot) { /* see fig. 1 */
1528 x0 = Cursor_x_hot - x;
1529 w0 = w - x0;
1532 if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1533 w0 = (displayWidth) - (x - Cursor_x_hot);
1536 if (y < Cursor_y_hot) { /* see fig. 1 */
1537 y0 = Cursor_y_hot - y;
1538 h0 = h - y0;
1541 if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1542 h0 = (displayHeight) - (y - Cursor_y_hot);
1544 /* end of coordinate correction */
1547 /* Grab an image from the screen, clipped if necessary,
1548 * and put it in the existing panel->magnifyGlass->image
1549 * with the corresponding clipping offset.
1551 if (!XGetSubImage(scr->display, scr->rootWin,
1552 x - Cursor_x_hot + x0,
1553 y - Cursor_y_hot + y0,
1554 w0, h0, AllPlanes, ZPixmap,
1555 image, x0, y0))
1556 wwarning(_("Color Panel: X failed request"));
1558 return NULL;
1562 static void
1563 magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1565 /* (x1, y1) = topleft corner of existing rectangle
1566 * (x2, y2) = topleft corner of new position
1569 W_Screen *scr = WMWidgetScreen(panel->win);
1570 int xa = 0, ya = 0, xb = 0, yb = 0;
1571 int width, height;
1572 const int dx = abs(x2 - x1),
1573 dy = abs(y2 - y1);
1574 XImage *image;
1575 const int x_min = Cursor_x_hot,
1576 y_min = Cursor_y_hot,
1577 x_max = DisplayWidth(scr->display, scr->screen) -1 -
1578 (Cursor_mask_width - Cursor_x_hot),
1579 y_max = DisplayHeight(scr->display, scr->screen) -1 -
1580 (Cursor_mask_height - Cursor_y_hot);
1582 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1583 return; /* No movement */
1585 if (x1 < x2)
1586 xa = dx;
1587 else
1588 xb = dx;
1590 if (y1 < y2)
1591 ya = dy;
1592 else
1593 yb = dy;
1595 width = Cursor_mask_width - dx;
1596 height = Cursor_mask_height - dy;
1598 /* If the traversed distance is larger than the size of the magnifying
1599 * glass contents, there is no need to do dirty rectangles. A whole new
1600 * rectangle can be grabbed (unless that rectangle falls partially
1601 * off screen).
1602 * Destroying the image and setting it to NULL will achieve that later on.
1604 * Of course, grabbing an XImage beyond the borders of the screen will
1605 * cause trouble, this is considdered a special case. Part of the screen
1606 * is grabbed, but there is no need for dirty rectangles.
1608 if ((width <= 0) || (height <= 0)) {
1609 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1610 if (panel->magnifyGlass->image)
1611 XDestroyImage(panel->magnifyGlass->image);
1612 panel->magnifyGlass->image = NULL;
1614 } else {
1615 if (panel->magnifyGlass->image) {
1616 /* Get dirty rectangle from panel->magnifyGlass->image */
1617 panel->magnifyGlass->dirtyRect =
1618 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1619 if (!panel->magnifyGlass->dirtyRect) {
1620 wwarning(_("Color Panel: X failed request"));
1621 return; /* X returned a NULL from XSubImage */
1626 /* Get image from screen */
1627 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
1628 Cursor_mask_width, Cursor_mask_height);
1629 if (image) { /* Only reassign if a *new* image was grabbed */
1630 panel->magnifyGlass->image = image;
1631 return;
1634 /* Copy previously stored rectangle on covered part of image */
1635 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1636 int old_height;
1638 /* "width" and "height" are used as coordinates here,
1639 * and run from [0...width-1] and [0...height-1] respectively.
1641 width--;
1642 height--;
1643 old_height = height;
1645 for (; width >= 0; width--)
1646 for (height = old_height; height >= 0; height--)
1647 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1648 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1649 XDestroyImage(panel->magnifyGlass->dirtyRect);
1650 panel->magnifyGlass->dirtyRect = NULL;
1653 return;
1657 static Pixmap
1658 magnifyCreatePixmap(WMColorPanel *panel)
1660 W_Screen *scr = WMWidgetScreen(panel->win);
1661 int u, v;
1662 #ifndef SHAPE
1663 Pixmap pixmap;
1664 #endif
1665 unsigned long color;
1667 if (!panel->magnifyGlass->image)
1668 return None;
1670 if (!panel->magnifyGlass->magPix)
1671 return None;
1674 * Copy an area of only 5x5 pixels from the center of the image.
1676 for (u = 0; u < 5; u++) {
1677 for (v = 0; v < 5; v++) {
1678 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1680 XSetForeground(scr->display, scr->copyGC, color);
1682 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1683 panel->magnifyGlass->color = ulongToRColor(scr, color);
1685 /* The center square must eventually be centered around the
1686 * hotspot. The image needs shifting to achieve this. The amount of
1687 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1688 * _ _ _ _ _
1689 * |_|_|_|_|_|
1690 * ^------- center of center square == Cursor_x_hot
1692 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1693 scr->copyGC,
1694 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1695 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1699 #ifdef SHAPE
1700 return panel->magnifyGlass->magPix;
1701 #else
1702 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1703 Cursor_mask_height, scr->depth);
1704 if (!pixmap)
1705 return None;
1707 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1708 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1710 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1711 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1712 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1713 /* (2,2) puts center pixel on center of glass */
1715 return pixmap;
1716 #endif
1721 static WMView*
1722 magnifyCreateView(W_ColorPanel *panel)
1724 W_Screen *scr = WMWidgetScreen(panel->win);
1725 WMView *magView;
1727 magView = W_CreateTopView(scr);
1728 if (!magView)
1729 return NULL;
1731 magView->self = panel->win;
1732 magView->flags.topLevel = 1;
1733 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1734 magView->attribs.override_redirect = True;
1735 magView->attribs.save_under = True;
1737 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1739 W_RealizeView(magView);
1741 return magView;
1745 static Cursor
1746 magnifyGrabPointer(W_ColorPanel *panel)
1748 W_Screen *scr = WMWidgetScreen(panel->win);
1749 Pixmap magPixmap, magPixmap2;
1750 Cursor magCursor;
1751 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1752 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1754 /* Cursor creation stuff */
1755 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1756 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1757 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1758 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1760 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1761 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1763 XFreePixmap(scr->display, magPixmap);
1764 XFreePixmap(scr->display, magPixmap2);
1766 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1768 /* Set up Pointer */
1769 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1770 PointerMotionMask | ButtonPressMask,
1771 GrabModeAsync, GrabModeAsync,
1772 scr->rootWin, magCursor, CurrentTime);
1774 return magCursor;
1778 static WMPoint
1779 magnifyInitialize(W_ColorPanel *panel)
1781 W_Screen *scr = WMWidgetScreen(panel->win);
1782 int x, y, u, v;
1783 unsigned int mask;
1784 Pixmap pixmap, clip_mask;
1785 WMPoint point;
1786 Window root_return, child_return;
1788 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1789 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1790 1, 0, 1);
1791 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1792 5*5 -1, 5*5 -1, scr->depth);
1794 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
1795 &x, &y, &u, &v, &mask);
1797 panel->magnifyGlass->image = NULL;
1799 /* Clipmask to make magnified view-contents circular */
1800 #ifdef SHAPE
1801 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1802 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1803 #else
1804 /* Clip circle in glass cursor */
1805 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1806 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1807 #endif
1809 XFreePixmap(scr->display, clip_mask);
1811 /* Draw initial magnifying glass contents */
1812 magnifyGetImageStored(panel, x, y, x, y);
1814 pixmap = magnifyCreatePixmap(panel);
1815 XSetWindowBackgroundPixmap(scr->display,
1816 WMViewXID(panel->magnifyGlass->view),
1817 pixmap);
1818 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1819 XFlush(scr->display);
1821 #ifndef SHAPE
1822 XFreePixmap(scr->display, pixmap);
1823 #endif
1825 point.x = x;
1826 point.y = y;
1828 return point;
1832 static void
1833 magnifyPutCursor(WMWidget *w, void *data)
1835 W_ColorPanel *panel = (W_ColorPanel*)(data);
1836 W_Screen *scr = WMWidgetScreen(panel->win);
1837 Cursor magCursor;
1838 Pixmap pixmap;
1839 XEvent event;
1840 WMPoint initialPosition;
1842 /* Destroy wheelBackImg, so it'll update properly */
1843 if (panel->selectionBackImg) {
1844 XFreePixmap(WMWidgetScreen(panel->win)->display,
1845 panel->selectionBackImg);
1846 panel->selectionBackImg = None;
1849 /* Create magnifying glass */
1850 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1851 panel->magnifyGlass->view = magnifyCreateView(panel);
1852 if (!panel->magnifyGlass->view)
1853 return;
1855 initialPosition = magnifyInitialize(panel);
1856 panel->magnifyGlass->x = initialPosition.x;
1857 panel->magnifyGlass->y = initialPosition.y;
1859 W_MoveView(panel->magnifyGlass->view,
1860 panel->magnifyGlass->x - Cursor_x_hot,
1861 panel->magnifyGlass->y - Cursor_y_hot);
1862 W_MapView(panel->magnifyGlass->view);
1864 magCursor = magnifyGrabPointer(panel);
1866 while (panel->magnifyGlass->image)
1868 WMNextEvent(scr->display, &event);
1870 /* Pack motion events */
1871 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1874 switch (event.type)
1876 case ButtonPress:
1877 XDestroyImage(panel->magnifyGlass->image);
1878 panel->magnifyGlass->image = NULL;
1880 if (event.xbutton.button == Button1) {
1881 panel->color.rgb = panel->magnifyGlass->color;
1882 panel->color.set = cpRGB;
1883 updateSwatch(panel, panel->color);
1885 switch (panel->mode) {
1886 case WMWheelModeColorPanel:
1887 wheelInit(panel);
1888 wheelRender(panel);
1889 wheelPaint(panel);
1890 break;
1891 case WMGrayModeColorPanel:
1892 grayInit(panel);
1893 break;
1894 case WMRGBModeColorPanel:
1895 rgbInit(panel);
1896 break;
1897 case WMCMYKModeColorPanel:
1898 cmykInit(panel);
1899 break;
1900 case WMHSBModeColorPanel:
1901 hsbInit(panel);
1902 break;
1903 default:
1904 break;
1906 panel->lastChanged = panel->mode;
1908 WMSetButtonSelected(panel->magnifyBtn, False);
1909 break;
1911 case MotionNotify:
1912 while (XPending(event.xmotion.display)) {
1913 XEvent ev;
1914 XPeekEvent(event.xmotion.display, &ev);
1915 if (ev.type == MotionNotify)
1916 XNextEvent(event.xmotion.display, &event);
1917 else
1918 break;
1921 /* Get a "dirty rectangle" */
1922 magnifyGetImageStored( panel,
1923 panel->magnifyGlass->x, panel->magnifyGlass->y,
1924 event.xmotion.x_root, event.xmotion.y_root);
1926 /* Update coordinates */
1927 panel->magnifyGlass->x = event.xmotion.x_root;
1928 panel->magnifyGlass->y = event.xmotion.y_root;
1930 /* Move view */
1931 W_MoveView(panel->magnifyGlass->view,
1932 panel->magnifyGlass->x - Cursor_x_hot,
1933 panel->magnifyGlass->y - Cursor_y_hot);
1935 /* Put new image (with magn.) in view */
1936 pixmap = magnifyCreatePixmap(panel);
1937 if (pixmap != None) {
1938 /* Change the window background */
1939 XSetWindowBackgroundPixmap(scr->display,
1940 WMViewXID(panel->magnifyGlass->view), pixmap);
1941 /* Force an Expose (handled by X) */
1942 XClearWindow(scr->display,
1943 WMViewXID(panel->magnifyGlass->view));
1944 /* Synchronize the event queue, so the Expose is handled NOW */
1945 XFlush(scr->display);
1946 #ifndef SHAPE
1947 XFreePixmap(scr->display, pixmap);
1948 #endif
1950 break;
1952 /* Try XQueryPointer for this !!! It returns windows that the pointer
1953 * is over. Note: We found this solving the invisible donkey cap bug
1955 #if 0 /* As it is impossible to make this work in all cases,
1956 * we consider it confusing. Therefore we disabled it.
1958 case FocusOut: /* fall through */
1959 case FocusIn:
1961 * Color Panel window (panel->win) lost or received focus.
1962 * We need to update the pixmap in the magnifying glass.
1964 * BUG Doesn't work with focus switches between two windows
1965 * if none of them is the color panel.
1967 XUngrabPointer(scr->display, CurrentTime);
1968 W_UnmapView(panel->magnifyGlass->view);
1970 magnifyInitialize(panel);
1972 W_MapView(panel->magnifyGlass->view);
1973 XGrabPointer (scr->display, panel->magnifyGlass->view->window,
1974 True, PointerMotionMask | ButtonPressMask,
1975 GrabModeAsync, GrabModeAsync,
1976 scr->rootWin, magCursor, CurrentTime);
1977 break;
1978 #endif
1979 default:
1980 WMHandleEvent(&event);
1981 break;
1982 } /* of switch */
1985 XUngrabPointer(scr->display, CurrentTime);
1986 XFreeCursor(scr->display, magCursor);
1988 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1989 panel->magnifyGlass->magPix = None;
1991 W_UnmapView(panel->magnifyGlass->view);
1992 W_DestroyView(panel->magnifyGlass->view);
1993 panel->magnifyGlass->view = NULL;
1995 wfree(panel->magnifyGlass);
2000 /****************** ColorWheel Functions ************************/
2002 static wheelMatrix*
2003 wheelCreateMatrix(unsigned int width, unsigned int height)
2005 wheelMatrix *matrix = NULL;
2006 int i;
2008 assert((width > 0) && (height > 0));
2010 matrix = wmalloc(sizeof(wheelMatrix));
2011 memset(matrix, 0, sizeof(wheelMatrix));
2012 matrix->width = width;
2013 matrix->height = height;
2015 for (i = 0; i < 3; i++) {
2016 matrix->data[i] = wmalloc(width*height*sizeof(unsigned char));
2019 return matrix;
2023 static void
2024 wheelDestroyMatrix(wheelMatrix *matrix)
2026 int i;
2028 if (!matrix)
2029 return;
2031 for (i = 0; i < 3; i++) {
2032 if (matrix->data[i])
2033 wfree(matrix->data[i]);
2035 wfree(matrix);
2039 static void
2040 wheelInitMatrix(W_ColorPanel *panel)
2042 int i;
2043 int x,y;
2044 unsigned char *rp, *gp, *bp;
2045 CPColor cpColor;
2046 long ofs[4];
2047 int xcor, ycor;
2048 unsigned short sat;
2049 int dhue[4];
2050 const int cw_halfsize = (colorWheelSize + 4)/2,
2051 cw_sqsize = (colorWheelSize +4) * (colorWheelSize +4),
2052 uchar_shift = getShift(sizeof(unsigned char));
2054 if (!panel->wheelMtrx)
2055 return;
2057 cpColor.hsv.value = 255;
2058 cpColor.set = cpHSV;
2060 ofs[0] = -1;
2061 ofs[1] = -(colorWheelSize + 4);
2063 /* offsets are counterclockwise (in triangles).
2065 * ofs[0] ---->
2066 * _______________________________________
2067 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
2068 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
2069 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
2070 * o | | | | | | | | | | | | | | | | | | | | | [3]
2072 * <---- ofs[2]
2073 * ____
2074 * |\ /| <-- triangles
2075 * | \/ |
2076 * | /\ |
2077 * |/__\|
2080 for (y = 0; y < cw_halfsize; y++) {
2081 for (x = y; x < (colorWheelSize+4-y); x++) {
2082 /* (xcor, ycor) is (x,y) relative to center of matrix */
2083 xcor = 2 * x - 4 - colorWheelSize;
2084 ycor = 2 * y - 4 - colorWheelSize;
2086 /* RColor.saturation is unsigned char and will wrap after 255 */
2087 sat = rint(255.0 * sqrt(xcor*xcor + ycor*ycor) / colorWheelSize);
2089 cpColor.hsv.saturation = (unsigned char)sat;
2091 ofs[0]++; /* top quarter of matrix*/
2092 ofs[1] += colorWheelSize + 4; /* left quarter */
2093 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
2094 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
2096 if (sat < 256) {
2097 if (xcor != 0)
2098 dhue[0] = rint(atan((double)ycor / (double)xcor) *
2099 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
2100 else
2101 dhue[0] = 270;
2103 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
2104 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
2105 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
2106 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
2108 for (i = 0; i < 4; i++) {
2109 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2110 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2111 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2113 cpColor.hsv.hue = dhue[i];
2114 convertCPColor(&cpColor);
2116 *rp = (unsigned char)(cpColor.rgb.red);
2117 *gp = (unsigned char)(cpColor.rgb.green);
2118 *bp = (unsigned char)(cpColor.rgb.blue);
2121 else {
2122 for (i = 0; i < 4; i++) {
2123 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2124 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2125 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2127 *rp = (unsigned char)0;
2128 *gp = (unsigned char)0;
2129 *bp = (unsigned char)0;
2134 ofs[0] += 2*y+1;
2135 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
2140 static void
2141 wheelCalculateValues(W_ColorPanel *panel, int maxvalue)
2143 unsigned int i;
2144 unsigned int v;
2146 for (i = 0; i < 256; i++) {
2147 /* We divide by 128 in advance, and check whether that number divides
2148 * by 2 properly. If not, we add one to round the number correctly
2150 v = (i*maxvalue) >> 7;
2151 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2156 static void
2157 wheelRender(W_ColorPanel *panel)
2159 W_Screen *scr = WMWidgetScreen(panel->win);
2160 int x,y;
2161 RImage *image;
2162 unsigned char *ptr;
2163 RColor gray;
2164 unsigned long ofs = 0;
2165 /*unsigned char shift = getShift(sizeof(unsigned char));*/
2167 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, True);
2168 if (!image) {
2169 wwarning(_("Color Panel: Could not allocate memory"));
2170 return;
2173 ptr = image->data;
2175 /* TODO Make this transparent istead of gray */
2176 gray.red = gray.blue = 0xae; gray.green = 0xaa;
2178 for (y = 0; y < colorWheelSize+4; y++) {
2179 for (x = 0; x < colorWheelSize+4; x++) {
2180 if (wheelInsideColorWheel(panel, ofs)) {
2181 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2182 panel->wheelMtrx->data[0][ofs] ]);
2183 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2184 panel->wheelMtrx->data[1][ofs] ]);
2185 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2186 panel->wheelMtrx->data[2][ofs] ]);
2187 *(ptr++) = 0;
2189 else {
2190 *(ptr++) = (unsigned char)(gray.red);
2191 *(ptr++) = (unsigned char)(gray.green);
2192 *(ptr++) = (unsigned char)(gray.blue);
2193 *(ptr++) = 255;
2195 ofs++;
2199 if (panel->wheelImg)
2200 XFreePixmap(scr->display, panel->wheelImg);
2202 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2203 RReleaseImage(image);
2205 /* Check if backimage exists. If it doesn't, allocate and fill it */
2206 if (!panel->selectionBackImg) {
2207 panel->selectionBackImg = XCreatePixmap(scr->display,
2208 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2209 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2210 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2211 /* -2 is hot spot correction */
2216 static Bool
2217 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2219 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2220 (panel->wheelMtrx->data[1][ofs] != 0) &&
2221 (panel->wheelMtrx->data[2][ofs] != 0));
2225 static void
2226 wheelPaint (W_ColorPanel *panel)
2228 W_Screen *scr = WMWidgetScreen(panel->win);
2230 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2231 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2233 /* Draw selection image */
2234 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2235 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2239 static void
2240 wheelHandleEvents(XEvent *event, void *data)
2242 W_ColorPanel *panel = (W_ColorPanel*)data;
2244 switch (event->type) {
2245 case Expose:
2246 if (event->xexpose.count != 0) /* TODO Improve */
2247 break;
2248 wheelPaint(panel);
2249 break;
2254 static void
2255 wheelHandleActionEvents(XEvent *event, void *data)
2257 W_ColorPanel *panel = (W_ColorPanel*)data;
2259 switch (event->type) {
2260 case ButtonPress:
2261 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2262 COLORWHEEL_PART) {
2264 panel->lastChanged = WMWheelModeColorPanel;
2265 panel->flags.dragging = 1;
2267 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2269 break;
2271 case ButtonRelease:
2272 panel->flags.dragging = 0;
2273 if (!panel->flags.continuous) {
2274 if (panel->action)
2275 (*panel->action)(panel, panel->clientData);
2277 break;
2279 case MotionNotify:
2280 if (panel->flags.dragging) {
2281 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2282 COLORWHEEL_PART) {
2283 wheelPositionSelection(panel, event->xmotion.x,
2284 event->xmotion.y);
2286 else
2287 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2288 event->xmotion.y);
2290 break;
2295 static int
2296 getPickerPart(W_ColorPanel *panel, int x, int y)
2298 int lx, ly;
2299 unsigned long ofs;
2301 lx = x;
2302 ly = y;
2304 if (panel->mode == WMWheelModeColorPanel) {
2305 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2306 (ly <= 2+colorWheelSize)) {
2308 ofs = ly*panel->wheelMtrx->width+lx;
2310 if (wheelInsideColorWheel(panel, ofs))
2311 return COLORWHEEL_PART;
2315 if (panel->mode == WMCustomPaletteModeColorPanel) {
2316 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2317 (ly < customPaletteHeight-2)) {
2318 return CUSTOMPALETTE_PART;
2322 return 0;
2326 static void
2327 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2329 int value;
2331 W_ColorPanel *panel = (W_ColorPanel*)data;
2333 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2335 wheelCalculateValues(panel, value);
2337 if (panel->color.set == cpRGB) {
2338 convertCPColor(&panel->color);
2339 panel->color.set = cpHSV;
2342 panel->color.hsv.value = value;
2344 wheelRender(panel);
2345 wheelPaint(panel);
2346 wheelUpdateSelection(panel);
2350 static void
2351 wheelUpdateSelection(W_ColorPanel *panel)
2353 W_Screen *scr = WMWidgetScreen(panel->win);
2355 updateSwatch(panel, panel->color);
2356 panel->lastChanged = WMWheelModeColorPanel;
2358 /* Redraw color selector (and make a backup of the part it will cover) */
2359 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2360 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2361 /* "-2" is correction for hotspot location */
2362 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2363 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2364 /* see above */
2368 static void
2369 wheelUndrawSelection(W_ColorPanel *panel)
2371 W_Screen *scr = WMWidgetScreen(panel->win);
2373 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2374 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2375 /* see above */
2378 static void
2379 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2381 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2383 panel->color.rgb.red = panel->wheelMtrx->values[
2384 panel->wheelMtrx->data[0][ofs] ];
2386 panel->color.rgb.green = panel->wheelMtrx->values[
2387 panel->wheelMtrx->data[1][ofs] ];
2389 panel->color.rgb.blue = panel->wheelMtrx->values[
2390 panel->wheelMtrx->data[2][ofs] ];
2391 panel->color.set = cpRGB;
2393 wheelUndrawSelection(panel);
2395 panel->colx = x;
2396 panel->coly = y;
2398 wheelUpdateSelection(panel);
2399 wheelUpdateBrightnessGradientFromLocation(panel);
2402 static void
2403 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2405 int hue;
2406 int xcor, ycor;
2407 CPColor cpColor;
2409 xcor = x * 2 - colorWheelSize - 4;
2410 ycor = y * 2 - colorWheelSize - 4;
2412 panel->color.hsv.saturation = 255;
2413 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2415 if (xcor != 0)
2416 hue = rint(atan(- (double)ycor / (double)xcor) * (180.0/M_PI));
2417 else {
2418 if (ycor < 0)
2419 hue = 90;
2420 else
2421 hue = 270;
2424 if (xcor < 0)
2425 hue += 180;
2427 if ((xcor > 0) && (ycor > 0))
2428 hue += 360;
2430 panel->color.hsv.hue = hue;
2431 panel->color.set = cpHSV;
2432 convertCPColor(&panel->color);
2434 wheelUndrawSelection(panel);
2436 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2437 cos( panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2438 /* "+2" because of "colorWheelSize + 4" */
2439 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2440 sin(- panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2442 wheelUpdateSelection(panel);
2443 cpColor = panel->color;
2444 wheelUpdateBrightnessGradient(panel, cpColor);
2447 static void
2448 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2450 CPColor from;
2451 unsigned long ofs;
2453 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2455 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2456 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2457 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2458 from.set = cpRGB;
2460 wheelUpdateBrightnessGradient(panel, from);
2463 static void
2464 wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor)
2466 RColor to;
2467 RImage *sliderImg;
2468 WMPixmap *sliderPxmp;
2470 to.red = to.green = to.blue = 0;
2472 if (topColor.set == cpHSV)
2473 convertCPColor(&topColor);
2475 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2476 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2477 sliderImg, 0);
2478 RReleaseImage(sliderImg);
2479 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2480 WMReleasePixmap(sliderPxmp);
2483 /****************** Grayscale Panel Functions ***************/
2485 static void
2486 grayBrightnessSliderCallback(WMWidget *w, void *data)
2488 CPColor cpColor;
2489 int value;
2490 char tmp[4];
2491 W_ColorPanel *panel = (W_ColorPanel*)data;
2493 value = WMGetSliderValue(panel->grayBrightnessS);
2495 sprintf(tmp, "%d", value);
2497 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2498 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55*value);
2499 cpColor.set = cpRGB;
2501 updateSwatch(panel, cpColor);
2502 panel->lastChanged = WMGrayModeColorPanel;
2505 static void
2506 grayPresetButtonCallback(WMWidget *w, void *data)
2508 CPColor cpColor;
2509 char tmp[4];
2510 int value;
2511 int i=0;
2512 W_ColorPanel *panel = (W_ColorPanel*)data;
2514 while (i < 7) {
2515 if (w == panel->grayPresetBtn[i])
2516 break;
2517 i++;
2520 value = rint((100.0*i)/6.0);
2521 sprintf(tmp, "%d", value);
2523 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2524 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2525 rint((255.0*i)/6.0);
2526 cpColor.set = cpRGB;
2528 WMSetSliderValue(panel->grayBrightnessS, rint((100.0*i)/6.0));
2530 updateSwatch(panel, cpColor);
2531 panel->lastChanged = WMGrayModeColorPanel;
2534 static void
2535 grayBrightnessTextFieldCallback(void *observerData,
2536 WMNotification *notification)
2538 CPColor cpColor;
2539 char tmp[4];
2540 int value;
2541 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2543 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2544 if (value > 100)
2545 value = 100;
2546 if (value < 0)
2547 value = 0;
2549 sprintf(tmp, "%d", value);
2550 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2551 WMSetSliderValue(panel->grayBrightnessS, value);
2553 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2554 rint((255.0*value)/100.0);
2555 cpColor.set = cpRGB;
2557 updateSwatch(panel, cpColor);
2558 panel->lastChanged = WMGrayModeColorPanel;
2561 /******************* RGB Panel Functions *****************/
2563 static void
2564 rgbSliderCallback(WMWidget *w, void *data)
2566 CPColor cpColor;
2567 int value[3];
2568 char tmp[4];
2569 W_ColorPanel *panel = (W_ColorPanel*)data;
2571 value[0] = WMGetSliderValue(panel->rgbRedS);
2572 value[1] = WMGetSliderValue(panel->rgbGreenS);
2573 value[2] = WMGetSliderValue(panel->rgbBlueS);
2575 sprintf(tmp, "%d", value[0]);
2576 WMSetTextFieldText(panel->rgbRedT, tmp);
2577 sprintf(tmp, "%d", value[1]);
2578 WMSetTextFieldText(panel->rgbGreenT, tmp);
2579 sprintf(tmp, "%d", value[2]);
2580 WMSetTextFieldText(panel->rgbBlueT, tmp);
2582 cpColor.rgb.red = value[0];
2583 cpColor.rgb.green = value[1];
2584 cpColor.rgb.blue = value[2];
2585 cpColor.set = cpRGB;
2587 updateSwatch(panel, cpColor);
2588 panel->lastChanged = WMRGBModeColorPanel;
2591 static void
2592 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2594 CPColor cpColor;
2595 int value[3];
2596 char tmp[4];
2597 int n;
2598 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2600 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2601 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2602 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2604 for (n=0; n < 3; n++) {
2605 if (value[n] > 255)
2606 value[n] = 255;
2607 if (value[n] < 0)
2608 value[n] = 0;
2611 sprintf(tmp, "%d", value[0]);
2612 WMSetTextFieldText(panel->rgbRedT, tmp);
2613 sprintf(tmp, "%d", value[1]);
2614 WMSetTextFieldText(panel->rgbGreenT, tmp);
2615 sprintf(tmp, "%d", value[2]);
2616 WMSetTextFieldText(panel->rgbBlueT, tmp);
2618 WMSetSliderValue(panel->rgbRedS, value[0]);
2619 WMSetSliderValue(panel->rgbGreenS, value[1]);
2620 WMSetSliderValue(panel->rgbBlueS, value[2]);
2622 cpColor.rgb.red = value[0];
2623 cpColor.rgb.green = value[1];
2624 cpColor.rgb.blue = value[2];
2625 cpColor.set = cpRGB;
2627 updateSwatch(panel, cpColor);
2628 panel->lastChanged = WMRGBModeColorPanel;
2632 /******************* CMYK Panel Functions *****************/
2634 static void
2635 cmykSliderCallback(WMWidget *w, void *data)
2637 CPColor cpColor;
2638 int value[4];
2639 char tmp[4];
2640 W_ColorPanel *panel = (W_ColorPanel*)data;
2641 double scale;
2643 value[0] = WMGetSliderValue(panel->cmykCyanS);
2644 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2645 value[2] = WMGetSliderValue(panel->cmykYellowS);
2646 value[3] = WMGetSliderValue(panel->cmykBlackS);
2648 sprintf(tmp, "%d", value[0]);
2649 WMSetTextFieldText(panel->cmykCyanT, tmp);
2650 sprintf(tmp, "%d", value[1]);
2651 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2652 sprintf(tmp, "%d", value[2]);
2653 WMSetTextFieldText(panel->cmykYellowT, tmp);
2654 sprintf(tmp, "%d", value[3]);
2655 WMSetTextFieldText(panel->cmykBlackT, tmp);
2657 scale = 2.55 * (1.0 - (value[3] / 100.0));
2658 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2659 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2660 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2661 cpColor.set = cpRGB;
2663 updateSwatch(panel, cpColor);
2664 panel->lastChanged = WMCMYKModeColorPanel;
2667 static void
2668 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2670 CPColor cpColor;
2671 int value[4];
2672 char tmp[4];
2673 int n;
2674 double scale;
2675 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2677 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2678 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2679 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2680 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2682 for (n=0; n < 4; n++) {
2683 if (value[n] > 100)
2684 value[n] = 100;
2685 if (value[n] < 0)
2686 value[n] = 0;
2689 sprintf(tmp, "%d", value[0]);
2690 WMSetTextFieldText(panel->cmykCyanT, tmp);
2692 sprintf(tmp, "%d", value[1]);
2693 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2695 sprintf(tmp, "%d", value[2]);
2696 WMSetTextFieldText(panel->cmykYellowT, tmp);
2698 sprintf(tmp, "%d", value[3]);
2699 WMSetTextFieldText(panel->cmykBlackT, tmp);
2701 WMSetSliderValue(panel->cmykCyanS, value[0]);
2702 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2703 WMSetSliderValue(panel->cmykYellowS, value[2]);
2704 WMSetSliderValue(panel->cmykBlackS, value[3]);
2706 scale = 2.55 * (1.0 - (value[3] / 100.0));
2707 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2708 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2709 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2710 cpColor.set = cpRGB;
2712 updateSwatch(panel, cpColor);
2713 panel->lastChanged = WMCMYKModeColorPanel;
2716 /********************** HSB Panel Functions ***********************/
2718 static void
2719 hsbSliderCallback(WMWidget *w, void *data)
2721 CPColor cpColor;
2722 int value[3];
2723 char tmp[4];
2724 W_ColorPanel *panel = (W_ColorPanel*)data;
2726 value[0] = WMGetSliderValue(panel->hsbHueS);
2727 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2728 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2730 sprintf(tmp, "%d", value[0]);
2731 WMSetTextFieldText(panel->hsbHueT, tmp);
2732 sprintf(tmp, "%d", value[1]);
2733 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2734 sprintf(tmp, "%d", value[2]);
2735 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2737 cpColor.hsv.hue = value[0];
2738 cpColor.hsv.saturation = value[1]*2.55;
2739 cpColor.hsv.value = value[2]*2.55;
2740 cpColor.set = cpHSV;
2742 convertCPColor(&cpColor);
2744 panel->lastChanged = WMHSBModeColorPanel;
2745 updateSwatch(panel, cpColor);
2747 if (w != panel->hsbBrightnessS)
2748 hsbUpdateBrightnessGradient(panel);
2749 if (w != panel->hsbSaturationS)
2750 hsbUpdateSaturationGradient(panel);
2751 if (w != panel->hsbHueS)
2752 hsbUpdateHueGradient(panel);
2755 static void
2756 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2758 CPColor cpColor;
2759 int value[3];
2760 char tmp[4];
2761 int n;
2762 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2764 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2765 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2766 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2768 if (value[0] > 359)
2769 value[0] = 359;
2770 if (value[0] < 0)
2771 value[0] = 0;
2773 for (n=1; n < 3; n++) {
2774 if (value[n] > 100)
2775 value[n] = 100;
2776 if (value[n] < 0)
2777 value[n] = 0;
2780 sprintf(tmp, "%d", value[0]);
2781 WMSetTextFieldText(panel->hsbHueT, tmp);
2782 sprintf(tmp, "%d", value[1]);
2783 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2784 sprintf(tmp, "%d", value[2]);
2785 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2787 WMSetSliderValue(panel->hsbHueS, value[0]);
2788 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2789 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2791 cpColor.hsv.hue = value[0];
2792 cpColor.hsv.saturation = value[1]*2.55;
2793 cpColor.hsv.value = value[2]*2.55;
2794 cpColor.set = cpHSV;
2796 convertCPColor(&cpColor);
2798 panel->lastChanged = WMHSBModeColorPanel;
2799 updateSwatch(panel, cpColor);
2801 hsbUpdateBrightnessGradient(panel);
2802 hsbUpdateSaturationGradient(panel);
2803 hsbUpdateHueGradient(panel);
2806 static void
2807 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2809 W_Screen *scr = WMWidgetScreen(panel->win);
2810 RColor from;
2811 CPColor to;
2812 RImage *sliderImg;
2813 WMPixmap *sliderPxmp;
2815 from.red = from.green = from.blue = 0;
2816 to.hsv = panel->color.hsv;
2817 to.hsv.value = 255;
2818 to.set = cpHSV;
2820 convertCPColor(&to);
2822 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2823 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2824 RReleaseImage(sliderImg);
2826 if (sliderPxmp)
2827 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2828 panel->font12, 2, 0, 100, WALeft, scr->white,
2829 False, _("Brightness"), strlen(_("Brightness")));
2830 else
2831 wwarning(_("Color Panel: Could not allocate memory"));
2833 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2834 WMReleasePixmap(sliderPxmp);
2837 static void
2838 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2840 W_Screen *scr = WMWidgetScreen(panel->win);
2841 CPColor from;
2842 CPColor to;
2843 RImage *sliderImg;
2844 WMPixmap *sliderPxmp;
2846 from.hsv = panel->color.hsv;
2847 from.hsv.saturation = 0;
2848 from.set = cpHSV;
2849 convertCPColor(&from);
2851 to.hsv = panel->color.hsv;
2852 to.hsv.saturation = 255;
2853 to.set = cpHSV;
2854 convertCPColor(&to);
2856 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb),
2857 RGRD_HORIZONTAL);
2858 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2859 RReleaseImage(sliderImg);
2861 if (sliderPxmp)
2862 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2863 panel->font12, 2, 0, 100, WALeft,
2864 from.hsv.value < 128 ? scr->white : scr->black, False,
2865 _("Saturation"), strlen(_("Saturation")));
2866 else
2867 wwarning(_("Color Panel: Could not allocate memory"));
2869 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2870 WMReleasePixmap(sliderPxmp);
2873 static void
2874 hsbUpdateHueGradient(W_ColorPanel *panel)
2876 W_Screen *scr = WMWidgetScreen(panel->win);
2877 RColor **colors = NULL;
2878 RHSVColor hsvcolor;
2879 RImage *sliderImg;
2880 WMPixmap *sliderPxmp;
2881 int i;
2883 hsvcolor = panel->color.hsv;
2885 colors = wmalloc(sizeof(RColor*)*(8));
2886 for (i=0; i<7; i++) {
2887 hsvcolor.hue = (360*i)/6;
2888 colors[i] = wmalloc(sizeof(RColor));
2889 RHSVtoRGB(&hsvcolor, colors[i]);
2891 colors[7] = NULL;
2893 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2894 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2895 RReleaseImage(sliderImg);
2897 if (sliderPxmp)
2898 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2899 panel->font12, 2, 0, 100, WALeft,
2900 hsvcolor.value < 128 ? scr->white : scr->black, False,
2901 _("Hue"), strlen(_("Hue")));
2902 else
2903 wwarning(_("Color Panel: Could not allocate memory"));
2905 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2906 WMReleasePixmap(sliderPxmp);
2908 for (i=0; i<7; i++)
2909 wfree(colors[i]);
2911 wfree(colors);
2914 /*************** Custom Palette Functions ****************/
2916 static void
2917 customRenderSpectrum(W_ColorPanel *panel)
2919 RImage *spectrum;
2920 int x,y;
2921 unsigned char *ptr;
2922 CPColor cpColor;
2924 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2926 ptr = spectrum->data;
2928 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2929 cpColor.hsv.hue = y;
2930 cpColor.hsv.saturation = 0;
2931 cpColor.hsv.value = 255;
2932 cpColor.set = cpHSV;
2934 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2935 convertCPColor(&cpColor);
2937 *(ptr++) = (unsigned char)cpColor.rgb.red;
2938 *(ptr++) = (unsigned char)cpColor.rgb.green;
2939 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2941 if (x < (SPECTRUM_WIDTH/2))
2942 cpColor.hsv.saturation++;
2944 if (x > (SPECTRUM_WIDTH/2))
2945 cpColor.hsv.value--;
2948 if (panel->customPaletteImg) {
2949 RReleaseImage(panel->customPaletteImg);
2950 panel->customPaletteImg = NULL;
2952 panel->customPaletteImg = spectrum;
2957 static void
2958 customSetPalette(W_ColorPanel *panel)
2960 W_Screen *scr = WMWidgetScreen(panel->win);
2961 RImage *scaledImg;
2962 Pixmap image;
2963 int item;
2965 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2966 customPaletteHeight, scr->depth);
2967 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2968 customPaletteHeight);
2969 RConvertImage(scr->rcontext, scaledImg, &image);
2970 RReleaseImage(scaledImg);
2972 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2973 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2975 /* Check backimage exists. If it doesn't, allocate and fill it */
2976 if (!panel->selectionBackImg) {
2977 panel->selectionBackImg = XCreatePixmap(scr->display,
2978 panel->customPaletteContentView->window, 4, 4, scr->depth);
2981 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2982 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2983 XCopyArea(scr->display, panel->selectionImg,
2984 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2985 panel->palx-2, panel->paly-2);
2986 XFreePixmap(scr->display, image);
2988 panel->palXRatio = (double)(panel->customPaletteImg->width) /
2989 (double)(customPaletteWidth);
2990 panel->palYRatio = (double)(panel->customPaletteImg->height) /
2991 (double)(customPaletteHeight);
2993 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2997 static void
2998 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
3000 W_Screen *scr = WMWidgetScreen(panel->win);
3001 unsigned long ofs;
3004 /* undraw selection */
3005 XCopyArea(scr->display, panel->selectionBackImg,
3006 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3007 panel->palx-2, panel->paly-2);
3009 panel->palx = x;
3010 panel->paly = y;
3012 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
3013 panel->customPaletteImg->width) * 3;
3015 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
3016 panel->color.rgb.green = panel->customPaletteImg->data[ofs+1];
3017 panel->color.rgb.blue = panel->customPaletteImg->data[ofs+2];
3018 panel->color.set = cpRGB;
3020 updateSwatch(panel, panel->color);
3021 panel->lastChanged = WMCustomPaletteModeColorPanel;
3023 /* Redraw color selector (and make a backup of the part it will cover) */
3024 XCopyArea(scr->display, panel->customPaletteContentView->window,
3025 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
3026 4, 4, 0, 0); /* "-2" is correction for hotspot location */
3027 XCopyArea(scr->display, panel->selectionImg,
3028 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3029 panel->palx-2, panel->paly-2); /* see above */
3033 static void
3034 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
3036 if (x < 2)
3037 x = 2;
3038 if (y < 2)
3039 y = 2;
3040 if (x >= customPaletteWidth)
3041 x = customPaletteWidth -2;
3042 if (y >= customPaletteHeight)
3043 y = customPaletteHeight -2;
3045 customPalettePositionSelection(panel, x, y);
3049 static void
3050 customPaletteHandleEvents(XEvent *event, void *data)
3052 W_ColorPanel *panel = (W_ColorPanel*)data;
3054 switch (event->type) {
3055 case Expose:
3056 if (event->xexpose.count != 0) /* TODO Improve. */
3057 break;
3058 customSetPalette(panel);
3059 break;
3063 static void
3064 customPaletteHandleActionEvents(XEvent *event, void *data)
3066 W_ColorPanel *panel = (W_ColorPanel*)data;
3067 int x, y;
3069 switch (event->type) {
3070 case ButtonPress:
3071 x = event->xbutton.x;
3072 y = event->xbutton.y;
3074 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3075 panel->flags.dragging = 1;
3076 customPalettePositionSelection(panel, x, y);
3078 break;
3080 case ButtonRelease:
3081 panel->flags.dragging = 0;
3082 if (!panel->flags.continuous) {
3083 if (panel->action)
3084 (*panel->action)(panel, panel->clientData);
3086 break;
3088 case MotionNotify:
3089 x = event->xmotion.x;
3090 y = event->xmotion.y;
3092 if (panel->flags.dragging) {
3093 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3094 customPalettePositionSelection(panel, x, y);
3096 else
3097 customPalettePositionSelectionOutBounds(panel, x, y);
3099 break;
3104 static void
3105 customPaletteMenuCallback(WMWidget *w, void *data)
3107 W_ColorPanel *panel = (W_ColorPanel*)data;
3108 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
3110 switch (item) {
3111 case CPmenuNewFromFile:
3112 customPaletteMenuNewFromFile(panel);
3113 break;
3114 case CPmenuRename:
3115 customPaletteMenuRename(panel);
3116 break;
3117 case CPmenuRemove:
3118 customPaletteMenuRemove(panel);
3119 break;
3120 case CPmenuCopy:
3121 break;
3122 case CPmenuNewFromClipboard:
3123 break;
3128 static void
3129 customPaletteMenuNewFromFile(W_ColorPanel *panel)
3131 W_Screen *scr = WMWidgetScreen(panel->win);
3132 WMOpenPanel *browseP;
3133 char *filepath;
3134 char *filename = NULL;
3135 char *spath;
3136 char *tmp;
3137 int i;
3138 RImage *tmpImg = NULL;
3140 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3141 spath = wexpandpath(wgethomedir());
3142 else
3143 spath = wexpandpath(panel->lastBrowseDir);
3145 browseP = WMGetOpenPanel(scr);
3146 WMSetFilePanelCanChooseDirectories(browseP, 0);
3147 WMSetFilePanelCanChooseFiles(browseP, 1);
3149 /* Get a filename */
3150 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3151 _("Open Palette"), RSupportedFileFormats()) ) {
3152 filepath = WMGetFilePanelFileName(browseP);
3154 /* Get seperation position between path and filename */
3155 i = strrchr(filepath, '/') - filepath + 1;
3156 if (i > strlen(filepath))
3157 i = strlen(filepath);
3159 /* Store last browsed path */
3160 if (panel->lastBrowseDir)
3161 wfree(panel->lastBrowseDir);
3162 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3163 strncpy(panel->lastBrowseDir, filepath, i);
3164 panel->lastBrowseDir[i] = '\0';
3166 /* Get filename from path */
3167 filename = wstrdup(filepath + i);
3169 /* Check for duplicate files, and rename it if there are any */
3170 tmp = wstrconcat(panel->configurationPath, filename);
3171 while (access (tmp, F_OK) == 0) {
3172 char *newName;
3174 wfree(tmp);
3176 newName = generateNewFilename(filename);
3177 wfree(filename);
3178 filename = newName;
3180 tmp = wstrconcat(panel->configurationPath, filename);
3182 wfree(tmp);
3184 /* Copy image to $(gnustepdir)/Library/Colors/ &
3185 * Add filename to history menu */
3186 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3188 /* filepath is a "local" path now the file has been copied */
3189 wfree(filepath);
3190 filepath = wstrconcat(panel->configurationPath, filename);
3192 /* load the image & add menu entries */
3193 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3194 if (tmpImg) {
3195 if (panel->customPaletteImg)
3196 RReleaseImage(panel->customPaletteImg);
3197 panel->customPaletteImg = tmpImg;
3199 customSetPalette(panel);
3200 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3202 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3203 panel->customPaletteHistoryBtn)-1;
3205 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3206 panel->currentPalette);
3208 } else {
3209 tmp = wstrconcat(panel->configurationPath, filename);
3211 i = remove(tmp); /* Delete the file, it doesn't belong here */
3212 WMRunAlertPanel(scr, panel->win, _("File Error"),
3213 _("Invalid file format !"), _("OK"), NULL, NULL);
3214 if (i != 0) {
3215 wsyserror(_("can't remove file %s"), tmp);
3216 WMRunAlertPanel(scr, panel->win, _("File Error"),
3217 _("Couldn't remove file from Configuration Directory !"),
3218 _("OK"), NULL, NULL);
3220 wfree(tmp);
3222 wfree(filepath);
3223 wfree(filename);
3225 WMFreeFilePanel(browseP);
3227 wfree(spath);
3231 static void
3232 customPaletteMenuRename(W_ColorPanel *panel)
3234 W_Screen *scr = WMWidgetScreen(panel->win);
3235 char *toName = NULL;
3236 char *fromName;
3237 char *toPath, *fromPath;
3238 int item;
3239 int index;
3241 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3242 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3244 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3245 fromName, _("OK"), _("Cancel"));
3247 if (toName) {
3249 /* As some people do certain stupid things... */
3250 if (strcmp(toName, fromName) == 0) {
3251 wfree(toName);
3252 return;
3255 /* For normal people */
3256 fromPath = wstrconcat(panel->configurationPath, fromName);
3257 toPath = wstrconcat(panel->configurationPath, toName);
3259 if (access (toPath, F_OK) == 0) {
3260 /* Careful, this palette exists already */
3261 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3262 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3263 NULL) == 1) {
3264 /* "No" = 0, "Yes" = 1 */
3265 int items = WMGetPopUpButtonNumberOfItems(
3266 panel->customPaletteHistoryBtn);
3268 remove(toPath);
3270 /* Remove from History list too */
3271 index = 1;
3272 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3273 panel->customPaletteHistoryBtn, index),
3274 toName) != 0 ))
3275 index++;
3277 if (index < items) {
3278 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3279 index);
3280 if (index < item)
3281 item--;
3284 } else {
3285 wfree(fromPath);
3286 wfree(toName);
3287 wfree(toPath);
3289 return;
3293 if ( rename(fromPath, toPath) != 0)
3294 wsyserror(_("Couldn't rename palette %s to %s\n"), fromName, toName);
3295 else {
3296 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3297 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3298 toName);
3300 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3302 wfree(fromPath);
3303 wfree(toPath);
3304 wfree(toName);
3309 static void
3310 customPaletteMenuRemove(W_ColorPanel *panel)
3312 W_Screen *scr = WMWidgetScreen(panel->win);
3313 char *text;
3314 char *tmp;
3315 int choice;
3316 int item;
3318 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3320 tmp = wstrconcat( _("This will permanently remove the palette "),
3321 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3322 text = wstrconcat( tmp,
3323 _(".\n\nAre you sure you want to remove this palette ?"));
3324 wfree(tmp);
3326 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"),
3327 NULL);
3328 /* returns 0 (= "Yes") or 1 (="No") */
3329 wfree(text);
3331 if (choice == 0) {
3333 tmp = wstrconcat(panel->configurationPath,
3334 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3336 if ( remove(tmp) == 0) {
3337 /* item-1 always exists */
3338 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3339 item-1);
3341 customPaletteHistoryCallback(panel->customPaletteHistoryBtn,
3342 panel);
3343 customSetPalette(panel);
3345 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3347 } else {
3348 wsyserror(_("Couldn't remove palette %s\n"), tmp);
3351 wfree(tmp);
3356 static void
3357 customPaletteHistoryCallback(WMWidget *w, void *data)
3359 W_ColorPanel *panel = (W_ColorPanel*)data;
3360 W_Screen *scr = WMWidgetScreen(panel->win);
3361 int item;
3362 char *filename;
3363 RImage *tmp = NULL;
3364 unsigned char perm_mask;
3366 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3367 if (item == panel->currentPalette)
3368 return;
3370 if (item == 0) {
3371 customRenderSpectrum(panel);
3373 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3374 False );
3375 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3376 False );
3377 } else {
3378 /* Load file from configpath */
3379 filename = wstrconcat( panel->configurationPath,
3380 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3382 /* If the file corresponding to the item does not exist,
3383 * remove it from the history list and select the next one.
3385 perm_mask = (access(filename, F_OK) == 0);
3386 if (!perm_mask) {
3387 /* File does not exist */
3388 wfree(filename);
3389 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3390 item-1);
3391 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3392 customPaletteHistoryCallback(w, data);
3393 return;
3396 /* Get the image */
3397 tmp = RLoadImage(scr->rcontext, filename, 0);
3398 if (tmp) {
3399 if (panel->customPaletteImg) {
3400 RReleaseImage(panel->customPaletteImg);
3401 panel->customPaletteImg = NULL;
3403 panel->customPaletteImg = tmp;
3406 /* If the image is not writable, don't allow removing/renaming */
3407 perm_mask = (access(filename, W_OK) == 0);
3408 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3409 perm_mask);
3410 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3411 perm_mask);
3413 wfree(filename);
3415 customSetPalette(panel);
3417 panel->currentPalette = item;
3420 /************************* ColorList Panel Functions **********************/
3422 static void
3423 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3424 int state, WMRect *rect)
3426 WMScreen *scr = WMWidgetScreen(lPtr);
3427 Display *dpy = WMScreenDisplay(scr);
3428 WMView *view = W_VIEW(lPtr);
3429 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3430 W_ColorPanel *panel = WMGetHangedData(lPtr);
3431 int width, height, x, y;
3432 WMColor *fillColor;
3434 width = rect->size.width;
3435 height = rect->size.height;
3436 x = rect->pos.x;
3437 y = rect->pos.y;
3439 if (state & WLDSSelected)
3440 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3441 else
3442 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3444 fillColor = WMCreateRGBColor(scr, color.red<<8, color.green<<8,
3445 color.blue<<8, True);
3447 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3448 WMReleaseColor(fillColor);
3450 WMDrawString(scr, d, scr->black, panel->font12, x+18, y, text, strlen(text));
3454 static void
3455 colorListSelect(WMWidget *w, void *data)
3457 W_ColorPanel *panel = (W_ColorPanel *)data;
3458 CPColor cpColor;
3460 cpColor.rgb = *((RColor *)WMGetListSelectedItem(w)->clientData);
3461 cpColor.set = cpRGB;
3463 panel->lastChanged = WMColorListModeColorPanel;
3464 updateSwatch(panel, cpColor);
3468 static void
3469 colorListColorMenuCallback(WMWidget *w, void *data)
3471 W_ColorPanel *panel = (W_ColorPanel *)data;
3472 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3474 switch (item) {
3475 case CLmenuAdd:
3476 break;
3477 case CLmenuRename:
3478 break;
3479 case CLmenuRemove:
3480 break;
3485 static void
3486 colorListListMenuCallback(WMWidget *w, void *data)
3488 W_ColorPanel *panel = (W_ColorPanel *)data;
3489 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3491 switch (item) {
3492 case CLmenuAdd:
3493 /* New Color List */
3494 colorListListMenuNew(panel);
3495 break;
3496 case CLmenuRename:
3497 break;
3498 case CLmenuRemove:
3499 break;
3504 static void
3505 colorListListMenuNew(W_ColorPanel *panel)
3511 /*************** Panel Initialisation Functions *****************/
3513 static void
3514 wheelInit(W_ColorPanel *panel)
3516 CPColor cpColor;
3518 if (panel->color.set != cpHSV)
3519 convertCPColor(&panel->color);
3521 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3523 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3524 (1 + ( panel->color.hsv.saturation/255.0) *
3525 cos( panel->color.hsv.hue * M_PI/180.0)));
3526 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3527 (1 + ( panel->color.hsv.saturation/255.0) *
3528 sin(- panel->color.hsv.hue*M_PI/180.0)));
3530 wheelCalculateValues(panel, panel->color.hsv.value);
3532 cpColor = panel->color;
3533 cpColor.hsv.value = 255;
3534 cpColor.set = cpHSV;
3535 wheelUpdateBrightnessGradient(panel, cpColor);
3539 static void
3540 grayInit(W_ColorPanel *panel)
3542 int value;
3543 char tmp[4];
3545 if (panel->color.set != cpHSV)
3546 convertCPColor(&panel->color);
3548 value = rint(panel->color.hsv.value/2.55);
3549 WMSetSliderValue(panel->grayBrightnessS, value);
3551 sprintf(tmp, "%d", value);
3552 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3556 static void
3557 rgbInit(W_ColorPanel *panel)
3559 char tmp[4];
3561 if (panel->color.set != cpRGB)
3562 convertCPColor(&panel->color);
3564 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3565 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3566 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3568 sprintf(tmp, "%d", panel->color.rgb.red);
3569 WMSetTextFieldText(panel->rgbRedT, tmp);
3570 sprintf(tmp, "%d", panel->color.rgb.green);
3571 WMSetTextFieldText(panel->rgbGreenT, tmp);
3572 sprintf(tmp, "%d", panel->color.rgb.blue);
3573 WMSetTextFieldText(panel->rgbBlueT, tmp);
3577 static void
3578 cmykInit(W_ColorPanel *panel)
3580 int value[3];
3581 char tmp[4];
3583 if (panel->color.set != cpRGB)
3584 convertCPColor(&panel->color);
3586 value[0] = rint((255-panel->color.rgb.red)/2.55);
3587 value[1] = rint((255-panel->color.rgb.green)/2.55);
3588 value[2] = rint((255-panel->color.rgb.blue)/2.55);
3590 WMSetSliderValue(panel->cmykCyanS, value[0]);
3591 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3592 WMSetSliderValue(panel->cmykYellowS, value[2]);
3593 WMSetSliderValue(panel->cmykBlackS, 0);
3595 sprintf(tmp, "%d", value[0]);
3596 WMSetTextFieldText(panel->cmykCyanT, tmp);
3597 sprintf(tmp, "%d", value[1]);
3598 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3599 sprintf(tmp, "%d", value[2]);
3600 WMSetTextFieldText(panel->cmykYellowT, tmp);
3601 WMSetTextFieldText(panel->cmykBlackT, "0");
3605 static void
3606 hsbInit(W_ColorPanel *panel)
3608 int value[3];
3609 char tmp[4];
3611 if (panel->color.set != cpHSV)
3612 convertCPColor(&panel->color);
3614 value[0] = panel->color.hsv.hue;
3615 value[1] = rint(panel->color.hsv.saturation/2.55);
3616 value[2] = rint(panel->color.hsv.value/2.55);
3618 WMSetSliderValue(panel->hsbHueS,value[0]);
3619 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3620 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3622 sprintf(tmp, "%d", value[0]);
3623 WMSetTextFieldText(panel->hsbHueT, tmp);
3624 sprintf(tmp, "%d", value[1]);
3625 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3626 sprintf(tmp, "%d", value[2]);
3627 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3629 hsbUpdateBrightnessGradient(panel);
3630 hsbUpdateSaturationGradient(panel);
3631 hsbUpdateHueGradient(panel);
3636 /************************** Common utility functions ************************/
3638 static int
3639 fetchFile(char *toPath, char *srcFile, char *destFile)
3641 int src, dest;
3642 int n;
3643 char *tmp;
3644 char buf[BUFSIZE];
3646 if ((src = open(srcFile, O_RDONLY|O_BINARY)) == 0) {
3647 wsyserror(_("Could not open %s"), srcFile);
3648 return -1;
3651 tmp = wstrconcat(toPath, destFile);
3652 if ((dest = open( tmp, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3653 == 0) {
3654 wsyserror(_("Could not create %s"), tmp);
3655 wfree(tmp);
3656 return -1;
3658 wfree(tmp);
3661 /* Copy the file */
3662 while ((n = read(src, buf, BUFSIZE)) > 0)
3664 if (write (dest, buf, n) != n) {
3665 wsyserror(_("Write error on file %s"), destFile);
3666 return -1;
3670 return 0;
3674 char*
3675 generateNewFilename(char *curName)
3677 int n;
3678 char c;
3679 int baseLen;
3680 char *ptr;
3681 char *newName;
3684 assert(curName);
3686 ptr = curName;
3688 if (((ptr = strrchr(ptr, '{'))==0) || sscanf(ptr, "{%i}%c", &n, &c)!=1)
3689 return wstrconcat(curName, " {1}");
3691 baseLen = ptr - curName -1;
3693 newName = wmalloc(baseLen + 16);
3694 strncpy(newName, curName, baseLen);
3695 newName[baseLen] = 0;
3697 sprintf(&newName[baseLen], " {%i}", n+1);
3699 return newName;
3703 void
3704 convertCPColor(CPColor *color)
3706 unsigned short old_hue = 0;
3708 switch (color->set) {
3709 case cpNone:
3710 wwarning(_("Color Panel: Color unspecified"));
3711 return;
3712 case cpRGB:
3713 old_hue = color->hsv.hue;
3714 RRGBtoHSV(&(color->rgb), &(color->hsv));
3716 /* In black the hue is undefined, and may change by conversion
3717 * Same for white. */
3718 if (
3719 ((color->rgb.red == 0) &&
3720 (color->rgb.green == 0) &&
3721 (color->rgb.blue == 0)) ||
3722 ((color->rgb.red == 0) &&
3723 (color->rgb.green == 0) &&
3724 (color->rgb.blue == 255))
3726 color->hsv.hue = old_hue;
3727 break;
3728 case cpHSV:
3729 RHSVtoRGB(&(color->hsv), &(color->rgb));
3730 break;
3735 #define ABS_SHIFT(val, shift) \
3736 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3738 RColor
3739 ulongToRColor(WMScreen *scr, unsigned long value)
3741 RColor color;
3742 XColor *xcolor = NULL;
3744 if (!(xcolor = wmalloc(sizeof(XColor)) )) {
3745 wwarning(_("Color Panel: Could not allocate memory"));
3746 color.red = 0;
3747 color.green = 0;
3748 color.blue = 0;
3749 return color;
3752 xcolor->pixel = value;
3753 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3755 color.red = xcolor->red >> 8;
3756 color.green = xcolor->green >> 8;
3757 color.blue = xcolor->blue >> 8;
3759 wfree(xcolor);
3761 return color;
3765 unsigned char
3766 getShift(unsigned char value)
3768 unsigned char i = -1;
3770 if (value == 0)
3771 return 0;
3773 while (value) {
3774 value >>= 1;
3775 i++;
3778 return i;
3783 #ifdef SHAPE_WAS_DEFINED
3784 #undef SHAPE_WAS_DEFINED
3785 #define SHAPE
3786 #endif