Fixed big memory leak in color panel code (patch from Pascal).
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob49e212fb64a9344b9ce9c132d6c86dc61347159f
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 "../src/config.h"
28 #include "WINGsP.h"
29 #include <math.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36 #include <errno.h>
38 /* BUG There's something fishy with shaped windows */
39 #if 1
40 #ifdef SHAPE
41 #define SHAPE_WAS_DEFINED
42 #undef SHAPE
43 #endif
44 #endif
47 #ifdef SHAPE
48 #include <X11/extensions/shape.h>
49 #endif
52 #ifndef PATH_MAX
53 # define PATH_MAX 1024
54 #endif
57 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
60 * Error Messages
62 #define NO_MEMORY_ERR "Color Panel: Could not allocate memory"
63 #define NO_FILE_ERR "Color Panel: Could not find file"
64 #define X_ERR "Color Panel: X failed request"
68 * Bitmaps for magnifying glass cursor
71 /* Cursor */
72 #define Cursor_x_hot 11
73 #define Cursor_y_hot 11
74 #define Cursor_width 32
75 #define Cursor_height 32
76 static unsigned char Cursor_bits[] = {
77 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
78 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
79 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
80 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
81 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
82 0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
83 0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
84 0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
85 0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
87 /* Cursor shape-mask */
88 #define Cursor_shape_width 32
89 #define Cursor_shape_height 32
90 static unsigned char Cursor_shape_bits[] = {
91 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
92 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
93 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
94 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
95 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
96 0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
97 0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
98 0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
99 0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70};
101 /* Clip-mask for magnified pixels */
102 #define Cursor_mask_width 24
103 #define Cursor_mask_height 24
104 static unsigned char Cursor_mask_bits[] = {
105 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
106 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
107 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
108 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
109 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
110 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00};
113 typedef struct MovingView {
114 WMView *view; /* The view this is all about */
115 XImage *image; /* What's under the view */
116 XImage *dirtyRect; /* Storage of overlapped image area */
117 Pixmap magPix; /* Magnified part of pixmap */
118 RColor color; /* Color of a pixel in the image */
119 int x, y; /* Position of view */
120 } MovingView;
122 typedef struct CPColor {
123 RColor rgb; /* The RGB values of the color */
124 RHSVColor hsv; /* The HSV values of the color */
125 enum { /* Which one was last set ? */
126 cpNone,
127 cpRGB,
128 cpHSV
129 } set;
130 } CPColor;
133 typedef struct WheelMatrix {
134 unsigned int width, height; /* Size of the colorwheel */
135 unsigned char *data[3]; /* Wheel data (R,G,B) */
136 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
137 } wheelMatrix;
139 typedef struct W_ColorPanel {
140 WMWindow *win;
141 WMFont *font8;
142 WMFont *font12;
143 void *clientData;
144 WMAction2 *action;
146 /* Common Stuff */
147 WMColorWell *colorWell;
148 WMButton *magnifyBtn;
149 WMButton *wheelBtn;
150 WMButton *slidersBtn;
151 WMButton *customPaletteBtn;
152 WMButton *colorListBtn;
154 /* Magnifying Glass */
155 MovingView *magnifyGlass;
157 /* ColorWheel Panel */
158 WMFrame *wheelFrm;
159 WMSlider *wheelBrightnessS;
160 WMView *wheelView;
162 /* Slider Panels */
163 WMFrame *slidersFrm;
164 WMFrame *seperatorFrm;
165 WMButton *grayBtn;
166 WMButton *rgbBtn;
167 WMButton *cmykBtn;
168 WMButton *hsbBtn;
169 /* Gray Scale Panel */
170 WMFrame *grayFrm;
171 WMLabel *grayMinL;
172 WMLabel *grayMaxL;
173 WMSlider *grayBrightnessS;
174 WMTextField *grayBrightnessT;
175 WMButton *grayPresetBtn[7];
177 /* RGB Panel */
178 WMFrame *rgbFrm;
179 WMLabel *rgbMinL;
180 WMLabel *rgbMaxL;
181 WMSlider *rgbRedS;
182 WMSlider *rgbGreenS;
183 WMSlider *rgbBlueS;
184 WMTextField *rgbRedT;
185 WMTextField *rgbGreenT;
186 WMTextField *rgbBlueT;
188 /* CMYK Panel */
189 WMFrame *cmykFrm;
190 WMLabel *cmykMinL;
191 WMLabel *cmykMaxL;
192 WMSlider *cmykCyanS;
193 WMSlider *cmykMagentaS;
194 WMSlider *cmykYellowS;
195 WMSlider *cmykBlackS;
196 WMTextField *cmykCyanT;
197 WMTextField *cmykMagentaT;
198 WMTextField *cmykYellowT;
199 WMTextField *cmykBlackT;
201 /* HSB Panel */
202 WMFrame *hsbFrm;
203 WMSlider *hsbHueS;
204 WMSlider *hsbSaturationS;
205 WMSlider *hsbBrightnessS;
206 WMTextField *hsbHueT;
207 WMTextField *hsbSaturationT;
208 WMTextField *hsbBrightnessT;
210 /* Custom Palette Panel*/
211 WMFrame *customPaletteFrm;
212 WMPopUpButton *customPaletteHistoryBtn;
213 WMFrame *customPaletteContentFrm;
214 WMPopUpButton *customPaletteMenuBtn;
215 WMView *customPaletteContentView;
217 /* Color List Panel */
218 WMFrame *colorListFrm;
219 WMPopUpButton *colorListHistoryBtn;
220 WMList *colorListContentLst;
221 WMPopUpButton *colorListColorMenuBtn;
222 WMPopUpButton *colorListListMenuBtn;
224 /* Look-Up Tables and Images */
225 wheelMatrix *wheelMtrx;
226 Pixmap wheelImg;
227 Pixmap selectionImg;
228 Pixmap selectionBackImg;
229 RImage *customPaletteImg;
230 char *lastBrowseDir;
232 /* Common Data Fields */
233 CPColor color; /* Current color */
234 WMColorPanelMode mode; /* Current color selection mode */
235 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
236 WMColorPanelMode lastChanged; /* Panel that last changed the color */
237 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
238 int palx, paly; /* (x,y) of sel.-marker in
239 CustomPaletteMode */
240 float palXRatio, palYRatio; /* Ratios in x & y between
241 original and scaled
242 palettesize */
243 int currentPalette;
244 char *configurationPath;
246 struct {
247 unsigned int continuous:1;
248 unsigned int dragging:1;
249 } flags;
250 } W_ColorPanel;
252 enum {
253 CPmenuNewFromFile,
254 CPmenuRename,
255 CPmenuRemove,
256 CPmenuCopy,
257 CPmenuNewFromClipboard
258 } customPaletteMenuItem;
260 enum {
261 CLmenuAdd,
262 CLmenuRename,
263 CLmenuRemove
264 } colorListMenuItem;
267 #define PWIDTH 194
268 #define PHEIGHT 266
269 #define colorWheelSize 150
270 #define customPaletteWidth 182
271 #define customPaletteHeight 106
272 #define knobThickness 8
274 #define SPECTRUM_WIDTH 511
275 #define SPECTRUM_HEIGHT 360
277 #define COLORWHEEL_PART 1
278 #define CUSTOMPALETTE_PART 2
279 #define BUFSIZE 1024
281 #ifndef RGBTXT
282 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
283 #endif
285 #define MAX_LENGTH 1024
287 static int fetchFile(char* toPath, char *imageSrcFile,
288 char *imageDestFileName);
289 char *generateNewFilename(char *curName);
290 void convertCPColor(CPColor *color);
291 RColor ulongToRColor(WMScreen *scr, unsigned long value);
292 unsigned char getShift(unsigned char value);
294 static void modeButtonCallback(WMWidget *w, void *data);
295 static int getPickerPart(W_ColorPanel *panel, int x, int y);
296 static void readConfiguration(W_ColorPanel *panel);
297 static void readXColors(W_ColorPanel *panel);
299 static void closeWindowCallback(WMWidget *w, void *data);
301 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
302 static WMPoint magnifyInitialize(W_ColorPanel *panel);
303 static void magnifyPutCursor(WMWidget *w, void *data);
304 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
305 static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1,
306 int x2, int y2);
307 static XImage* magnifyGetImage(WMScreen *scr, XImage *image, int x, int y,
308 int w, int h);
310 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
311 static void wheelDestroyMatrix(wheelMatrix *matrix);
312 static void wheelInitMatrix(W_ColorPanel *panel);
313 static void wheelCalculateValues(W_ColorPanel *panel, int maxvalue);
314 static void wheelRender(W_ColorPanel *panel);
315 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
316 static void wheelPaint(W_ColorPanel *panel);
318 static void wheelHandleEvents(XEvent *event, void *data);
319 static void wheelHandleActionEvents(XEvent *event, void *data);
320 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
321 static void wheelUpdateSelection(W_ColorPanel *panel);
322 static void wheelUndrawSelection(W_ColorPanel *panel);
324 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
325 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
326 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
327 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor);
329 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
330 static void grayPresetButtonCallback(WMWidget *w, void *data);
331 static void grayBrightnessTextFieldCallback(void *observerData,
332 WMNotification *notification);
334 static void rgbSliderCallback(WMWidget *w, void *data);
335 static void rgbTextFieldCallback(void *observerData,
336 WMNotification *notification);
338 static void cmykSliderCallback(WMWidget *w, void *data);
339 static void cmykTextFieldCallback(void *observerData,
340 WMNotification *notification);
342 static void hsbSliderCallback(WMWidget *w, void *data);
343 static void hsbTextFieldCallback(void *observerData,
344 WMNotification *notification);
345 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
346 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
347 static void hsbUpdateHueGradient(W_ColorPanel *panel);
349 static void customRenderSpectrum(W_ColorPanel *panel);
350 static void customSetPalette(W_ColorPanel *panel);
351 static void customPaletteHandleEvents(XEvent *event, void *data);
352 static void customPaletteHandleActionEvents(XEvent *event, void *data);
353 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
354 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
355 int x, int y);
356 static void customPaletteMenuCallback(WMWidget *w, void *data);
357 static void customPaletteHistoryCallback(WMWidget *w, void *data);
359 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
360 static void customPaletteMenuRename(W_ColorPanel *panel);
361 static void customPaletteMenuRemove(W_ColorPanel *panel);
363 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
364 int state, WMRect *rect);
365 static void colorListSelect(WMWidget *w, void *data);
366 static void colorListColorMenuCallback(WMWidget *w, void *data);
367 static void colorListListMenuCallback(WMWidget *w, void *data);
368 static void colorListListMenuNew(W_ColorPanel *panel);
370 static void wheelInit(W_ColorPanel *panel);
371 static void grayInit(W_ColorPanel *panel);
372 static void rgbInit(W_ColorPanel *panel);
373 static void cmykInit(W_ColorPanel *panel);
374 static void hsbInit(W_ColorPanel *panel);
378 void
379 WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
381 panel->action = action;
382 panel->clientData = data;
385 static WMColorPanel*
386 makeColorPanel(WMScreen *scrPtr, char *name)
388 WMColorPanel *panel;
389 RImage *image;
390 WMPixmap *pixmap;
391 RColor from;
392 RColor to;
393 WMColor *textcolor, *graybuttoncolor;
394 int i;
395 GC bgc = WMColorGC(scrPtr->black);
396 GC wgc = WMColorGC(scrPtr->white);
399 panel = wmalloc(sizeof(WMColorPanel));
400 memset(panel, 0, sizeof(WMColorPanel));
402 panel->color.rgb.red = 0;
403 panel->color.rgb.green = 0;
404 panel->color.rgb.blue = 0;
405 panel->color.hsv.hue = 0;
406 panel->color.hsv.saturation = 0;
407 panel->color.hsv.value = 0;
408 panel->color.set = cpNone; /* Color has not been set yet */
410 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
411 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
413 panel->win = WMCreateWindowWithStyle(scrPtr, name,
414 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
415 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
416 WMSetWindowTitle(panel->win, "Colors");
417 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
420 /* Set Default ColorPanel Mode(s) */
421 panel->mode = WMWheelModeColorPanel;
422 panel->lastChanged = 0;
423 panel->slidersmode = WMRGBModeColorPanel;
424 panel->configurationPath = wstrappend(wusergnusteppath(),
425 "/Library/Colors/");
427 /* Some General Purpose Widgets */
428 panel->colorWell = WMCreateColorWell(panel->win);
429 WMResizeWidget(panel->colorWell, 134, 36);
430 WSetColorWellBordered(panel->colorWell, False);
431 WMMoveWidget(panel->colorWell, 56, 4);
433 panel->magnifyBtn = WMCreateCustomButton(panel->win,
434 WBBStateLightMask|WBBStateChangeMask);
435 WMResizeWidget(panel->magnifyBtn, 46, 36);
436 WMMoveWidget(panel->magnifyBtn, 6,4);
437 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
438 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
439 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
441 panel->wheelBtn = WMCreateCustomButton(panel->win,
442 WBBStateLightMask|WBBStateChangeMask);
443 WMResizeWidget(panel->wheelBtn, 46, 32);
444 WMMoveWidget(panel->wheelBtn, 6, 44);
445 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
446 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
447 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
449 panel->slidersBtn = WMCreateCustomButton(panel->win,
450 WBBStateLightMask|WBBStateChangeMask);
451 WMResizeWidget(panel->slidersBtn, 46, 32);
452 WMMoveWidget(panel->slidersBtn, 52, 44);
453 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
454 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
455 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
457 panel->customPaletteBtn = WMCreateCustomButton(panel->win,
458 WBBStateLightMask|WBBStateChangeMask);
459 WMResizeWidget(panel->customPaletteBtn, 46, 32);
460 WMMoveWidget(panel->customPaletteBtn, 98, 44);
461 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
462 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
463 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
465 panel->colorListBtn = WMCreateCustomButton(panel->win,
466 WBBStateLightMask|WBBStateChangeMask);
467 WMResizeWidget(panel->colorListBtn, 46, 32);
468 WMMoveWidget(panel->colorListBtn, 144, 44);
469 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
470 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
471 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
473 /* Let's Group some of them together */
474 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
475 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
476 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
478 /* Widgets for the ColorWheel Panel */
479 panel->wheelFrm = WMCreateFrame(panel->win);
480 WMSetFrameRelief(panel->wheelFrm, WRFlat);
481 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
482 WMMoveWidget(panel->wheelFrm, 5, 80);
484 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
485 /* XXX Can we create a view ? */
486 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
487 W_MoveView(panel->wheelView, 0, 0);
489 /* Create an event handler to handle expose/click events in ColorWheel */
490 WMCreateEventHandler(panel->wheelView,
491 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
492 LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
494 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
495 panel);
497 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
498 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
499 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
500 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
501 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
502 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
503 panel);
504 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
506 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
507 wheelInitMatrix(panel);
510 /* Widgets for the Slider Panels */
511 panel->slidersFrm = WMCreateFrame(panel->win);
512 WMSetFrameRelief(panel->slidersFrm, WRFlat);
513 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
514 WMMoveWidget(panel->slidersFrm, 4, 80);
516 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
517 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
518 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
519 WMMoveWidget(panel->seperatorFrm, 0, 1);
521 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
522 WBBStateLightMask|WBBStateChangeMask);
523 WMResizeWidget(panel->grayBtn, 46, 24);
524 WMMoveWidget(panel->grayBtn, 1, 8);
525 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
526 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
527 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
529 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
530 WBBStateLightMask|WBBStateChangeMask);
531 WMResizeWidget(panel->rgbBtn, 46, 24);
532 WMMoveWidget(panel->rgbBtn, 47, 8);
533 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
534 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
535 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
537 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
538 WBBStateLightMask|WBBStateChangeMask);
539 WMResizeWidget(panel->cmykBtn, 46, 24);
540 WMMoveWidget(panel->cmykBtn, 93, 8);
541 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
542 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
543 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
545 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
546 WBBStateLightMask|WBBStateChangeMask);
547 WMResizeWidget(panel->hsbBtn, 46, 24);
548 WMMoveWidget(panel->hsbBtn, 139, 8);
549 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
550 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
551 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
553 /* Let's Group the Slider Panel Buttons Together */
554 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
555 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
556 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
558 textcolor = WMDarkGrayColor(scrPtr);
560 /* Widgets for GrayScale Panel */
561 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
562 WMSetFrameRelief(panel->grayFrm, WRFlat);
563 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
564 WMMoveWidget(panel->grayFrm, 0, 34);
566 panel->grayMinL = WMCreateLabel(panel->grayFrm);
567 WMResizeWidget(panel->grayMinL, 20, 10);
568 WMMoveWidget(panel->grayMinL, 2, 2);
569 WMSetLabelText(panel->grayMinL, "0");
570 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
571 WMSetLabelTextColor(panel->grayMinL, textcolor);
572 WMSetLabelFont(panel->grayMinL, panel->font8);
574 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
575 WMResizeWidget(panel->grayMaxL, 40, 10);
576 WMMoveWidget(panel->grayMaxL, 104, 2);
577 WMSetLabelText(panel->grayMaxL, "100");
578 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
579 WMSetLabelTextColor(panel->grayMaxL, textcolor);
580 WMSetLabelFont(panel->grayMaxL, panel->font8);
582 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
583 WMResizeWidget(panel->grayBrightnessS, 141, 16);
584 WMMoveWidget(panel->grayBrightnessS, 2, 14);
585 WMSetSliderMinValue(panel->grayBrightnessS, 0);
586 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
587 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
588 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
589 panel);
591 from.red = 0;
592 from.green = 0;
593 from.blue = 0;
595 to.red = 255;
596 to.green = 255;
597 to.blue = 255;
599 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
600 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
601 RDestroyImage(image);
603 if (pixmap)
604 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
605 panel->font12, 2, 0, 100, WALeft, WMColorGC(scrPtr->white),
606 False, "Brightness", strlen("Brightness"));
607 else
608 wwarning(NO_MEMORY_ERR);
610 WMSetSliderImage(panel->grayBrightnessS, pixmap);
611 WMReleasePixmap(pixmap);
613 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
614 WMResizeWidget(panel->grayBrightnessT, 40, 18);
615 WMMoveWidget(panel->grayBrightnessT, 146, 13);
616 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
617 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
618 WMTextDidEndEditingNotification, panel->grayBrightnessT);
620 for (i=0; i < 7; i++) {
621 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
623 graybuttoncolor = WMCreateRGBColor(scrPtr, (255/6)*i << 8,
624 (255/6)*i << 8, (255/6)*i << 8, True);
625 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
626 WMReleaseColor(graybuttoncolor);
628 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
629 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
630 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
631 WMSetButtonAction(panel->grayPresetBtn[i],
632 grayPresetButtonCallback, panel);
633 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
634 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
635 WMReleasePixmap(pixmap);
639 /* End of GrayScale Panel */
641 /* Widgets for RGB Panel */
642 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
643 WMSetFrameRelief(panel->rgbFrm, WRFlat);
644 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
645 WMMoveWidget(panel->rgbFrm, 0, 34);
647 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
648 WMResizeWidget(panel->rgbMinL, 20, 10);
649 WMMoveWidget(panel->rgbMinL, 2, 2);
650 WMSetLabelText(panel->rgbMinL, "0");
651 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
652 WMSetLabelTextColor(panel->rgbMinL, textcolor);
653 WMSetLabelFont(panel->rgbMinL, panel->font8);
655 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
656 WMResizeWidget(panel->rgbMaxL, 40, 10);
657 WMMoveWidget(panel->rgbMaxL, 104, 2);
658 WMSetLabelText(panel->rgbMaxL, "255");
659 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
660 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
661 WMSetLabelFont(panel->rgbMaxL, panel->font8);
663 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
664 WMResizeWidget(panel->rgbRedS, 141, 16);
665 WMMoveWidget(panel->rgbRedS, 2, 14);
666 WMSetSliderMinValue(panel->rgbRedS, 0);
667 WMSetSliderMaxValue(panel->rgbRedS, 255);
668 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
669 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
671 to.red = 255;
672 to.green = 0;
673 to.blue = 0;
675 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
676 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
677 RDestroyImage(image);
679 if (pixmap)
680 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
681 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Red",
682 strlen("Red"));
683 else
684 wwarning(NO_MEMORY_ERR);
686 WMSetSliderImage(panel->rgbRedS, pixmap);
687 WMReleasePixmap(pixmap);
689 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
690 WMResizeWidget(panel->rgbRedT, 40, 18);
691 WMMoveWidget(panel->rgbRedT, 146, 13);
692 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
693 WMAddNotificationObserver(rgbTextFieldCallback, panel,
694 WMTextDidEndEditingNotification, panel->rgbRedT);
696 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
697 WMResizeWidget(panel->rgbGreenS, 141, 16);
698 WMMoveWidget(panel->rgbGreenS, 2, 36);
699 WMSetSliderMinValue(panel->rgbGreenS, 0);
700 WMSetSliderMaxValue(panel->rgbGreenS, 255);
701 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
702 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
704 to.red = 0;
705 to.green = 255;
706 to.blue = 0;
708 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
709 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
710 RDestroyImage(image);
712 if (pixmap)
713 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
714 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Green",
715 strlen("Green"));
716 else
717 wwarning(NO_MEMORY_ERR);
719 WMSetSliderImage(panel->rgbGreenS, pixmap);
720 WMReleasePixmap(pixmap);
722 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
723 WMResizeWidget(panel->rgbGreenT, 40, 18);
724 WMMoveWidget(panel->rgbGreenT, 146, 35);
725 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
726 WMAddNotificationObserver(rgbTextFieldCallback, panel,
727 WMTextDidEndEditingNotification, panel->rgbGreenT);
730 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
731 WMResizeWidget(panel->rgbBlueS, 141, 16);
732 WMMoveWidget(panel->rgbBlueS, 2, 58);
733 WMSetSliderMinValue(panel->rgbBlueS, 0);
734 WMSetSliderMaxValue(panel->rgbBlueS, 255);
735 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
736 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
738 to.red = 0;
739 to.green = 0;
740 to.blue = 255;
742 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
743 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
744 RDestroyImage(image);
746 if (pixmap)
747 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
748 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Blue",
749 strlen("Blue"));
750 else
751 wwarning(NO_MEMORY_ERR);
753 WMSetSliderImage(panel->rgbBlueS, pixmap);
754 WMReleasePixmap(pixmap);
756 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
757 WMResizeWidget(panel->rgbBlueT, 40, 18);
758 WMMoveWidget(panel->rgbBlueT, 146, 57);
759 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
760 WMAddNotificationObserver(rgbTextFieldCallback, panel,
761 WMTextDidEndEditingNotification, panel->rgbBlueT);
762 /* End of RGB Panel */
764 /* Widgets for CMYK Panel */
765 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
766 WMSetFrameRelief(panel->cmykFrm, WRFlat);
767 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
768 WMMoveWidget(panel->cmykFrm, 0, 34);
770 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
771 WMResizeWidget(panel->cmykMinL, 20, 10);
772 WMMoveWidget(panel->cmykMinL, 2, 2);
773 WMSetLabelText(panel->cmykMinL, "0");
774 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
775 WMSetLabelTextColor(panel->cmykMinL, textcolor);
776 WMSetLabelFont(panel->cmykMinL, panel->font8);
778 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
779 WMResizeWidget(panel->cmykMaxL, 40, 10);
780 WMMoveWidget(panel->cmykMaxL, 104, 2);
781 WMSetLabelText(panel->cmykMaxL, "100");
782 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
783 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
784 WMSetLabelFont(panel->cmykMaxL, panel->font8);
786 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
787 WMResizeWidget(panel->cmykCyanS, 141, 16);
788 WMMoveWidget(panel->cmykCyanS, 2, 14);
789 WMSetSliderMinValue(panel->cmykCyanS, 0);
790 WMSetSliderMaxValue(panel->cmykCyanS, 100);
791 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
792 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
794 from.red = 255;
795 from.green = 255;
796 from.blue = 255;
798 to.red = 0;
799 to.green = 255;
800 to.blue = 255;
802 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
803 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
804 RDestroyImage(image);
806 if (pixmap)
807 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
808 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Cyan",
809 strlen("Cyan"));
810 else
811 wwarning(NO_MEMORY_ERR);
813 WMSetSliderImage(panel->cmykCyanS, pixmap);
814 WMReleasePixmap(pixmap);
816 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
817 WMResizeWidget(panel->cmykCyanT, 40, 18);
818 WMMoveWidget(panel->cmykCyanT, 146, 13);
819 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
820 WMAddNotificationObserver(cmykTextFieldCallback, panel,
821 WMTextDidEndEditingNotification, panel->cmykCyanT);
824 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
825 WMResizeWidget(panel->cmykMagentaS, 141, 16);
826 WMMoveWidget(panel->cmykMagentaS, 2, 36);
827 WMSetSliderMinValue(panel->cmykMagentaS, 0);
828 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
829 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
830 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
832 to.red = 255;
833 to.green = 0;
834 to.blue = 255;
836 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
837 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
838 RDestroyImage(image);
840 if (pixmap)
841 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
842 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Magenta",
843 strlen("Magenta"));
844 else
845 wwarning(NO_MEMORY_ERR);
847 WMSetSliderImage(panel->cmykMagentaS, pixmap);
848 WMReleasePixmap(pixmap);
850 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
851 WMResizeWidget(panel->cmykMagentaT, 40, 18);
852 WMMoveWidget(panel->cmykMagentaT, 146, 35);
853 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
854 WMAddNotificationObserver(cmykTextFieldCallback, panel,
855 WMTextDidEndEditingNotification, panel->cmykMagentaT);
858 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
859 WMResizeWidget(panel->cmykYellowS, 141, 16);
860 WMMoveWidget(panel->cmykYellowS, 2, 58);
861 WMSetSliderMinValue(panel->cmykYellowS, 0);
862 WMSetSliderMaxValue(panel->cmykYellowS, 100);
863 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
864 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
866 to.red = 255;
867 to.green = 255;
868 to.blue = 0;
870 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
871 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
872 RDestroyImage(image);
874 if (pixmap)
875 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
876 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Yellow",
877 strlen("Yellow"));
878 else
879 wwarning(NO_MEMORY_ERR);
881 WMSetSliderImage(panel->cmykYellowS, pixmap);
882 WMReleasePixmap(pixmap);
884 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
885 WMResizeWidget(panel->cmykYellowT, 40, 18);
886 WMMoveWidget(panel->cmykYellowT, 146, 57);
887 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
888 WMAddNotificationObserver(cmykTextFieldCallback, panel,
889 WMTextDidEndEditingNotification, panel->cmykYellowT);
892 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
893 WMResizeWidget(panel->cmykBlackS, 141, 16);
894 WMMoveWidget(panel->cmykBlackS, 2, 80);
895 WMSetSliderMinValue(panel->cmykBlackS, 0);
896 WMSetSliderMaxValue(panel->cmykBlackS, 100);
897 WMSetSliderValue(panel->cmykBlackS, 0);
898 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
899 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
901 to.red = 0;
902 to.green = 0;
903 to.blue = 0;
905 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
906 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
907 RDestroyImage(image);
909 if (pixmap)
910 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
911 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Black",
912 strlen("Black"));
913 else
914 wwarning(NO_MEMORY_ERR);
916 WMSetSliderImage(panel->cmykBlackS, pixmap);
917 WMReleasePixmap(pixmap);
919 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
920 WMResizeWidget(panel->cmykBlackT, 40, 18);
921 WMMoveWidget(panel->cmykBlackT, 146, 79);
922 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
923 WMAddNotificationObserver(cmykTextFieldCallback, panel,
924 WMTextDidEndEditingNotification, panel->cmykBlackT);
925 /* End of CMYK Panel */
927 /* Widgets for HSB Panel */
928 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
929 WMSetFrameRelief(panel->hsbFrm, WRFlat);
930 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
931 WMMoveWidget(panel->hsbFrm, 0, 34);
933 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
934 WMResizeWidget(panel->hsbHueS, 141, 16);
935 WMMoveWidget(panel->hsbHueS, 2, 14);
936 WMSetSliderMinValue(panel->hsbHueS, 0);
937 WMSetSliderMaxValue(panel->hsbHueS, 359);
938 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
939 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
941 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
942 WMResizeWidget(panel->hsbHueT, 40, 18);
943 WMMoveWidget(panel->hsbHueT, 146, 13);
944 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
945 WMAddNotificationObserver(hsbTextFieldCallback, panel,
946 WMTextDidEndEditingNotification, panel->hsbHueT);
949 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
950 WMResizeWidget(panel->hsbSaturationS, 141, 16);
951 WMMoveWidget(panel->hsbSaturationS, 2, 36);
952 WMSetSliderMinValue(panel->hsbSaturationS, 0);
953 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
954 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
955 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
957 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
958 WMResizeWidget(panel->hsbSaturationT, 40, 18);
959 WMMoveWidget(panel->hsbSaturationT, 146, 35);
960 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
961 WMAddNotificationObserver(hsbTextFieldCallback, panel,
962 WMTextDidEndEditingNotification, panel->hsbSaturationT);
965 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
966 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
967 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
968 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
969 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
970 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
971 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
973 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
974 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
975 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
976 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
977 WMAddNotificationObserver(hsbTextFieldCallback, panel,
978 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
979 /* End of HSB Panel */
982 WMReleaseColor(textcolor);
984 /* Widgets for the CustomPalette Panel */
985 panel->customPaletteFrm = WMCreateFrame(panel->win);
986 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
987 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
988 WMMoveWidget(panel->customPaletteFrm, 5, 80);
990 panel->customPaletteHistoryBtn = WMCreatePopUpButton(
991 panel->customPaletteFrm);
992 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, "Spectrum");
993 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
994 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
995 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
996 customPaletteHistoryCallback, panel);
997 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
998 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
1000 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
1001 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
1002 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
1003 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
1005 panel->customPaletteContentView = W_CreateView(
1006 W_VIEW(panel->customPaletteContentFrm));
1007 /* XXX Test if we can create a view */
1008 W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
1009 customPaletteHeight);
1010 W_MoveView(panel->customPaletteContentView, 2, 2);
1012 /* Create event handler to handle expose/click events in CustomPalette */
1013 WMCreateEventHandler(panel->customPaletteContentView,
1014 ButtonPressMask|ButtonReleaseMask|EnterWindowMask| LeaveWindowMask |
1015 ButtonMotionMask, customPaletteHandleActionEvents, panel);
1017 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
1018 customPaletteHandleEvents, panel);
1020 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
1021 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
1022 WMSetPopUpButtonText(panel->customPaletteMenuBtn, "Palette");
1023 WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
1024 customPaletteMenuCallback, panel);
1025 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
1026 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
1028 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from File...");
1029 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Rename...");
1030 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Remove");
1031 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Copy");
1032 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from Clipboard");
1034 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
1035 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
1036 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
1037 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
1038 CPmenuNewFromClipboard, 0);
1040 customRenderSpectrum(panel);
1041 panel->currentPalette = 0;
1042 panel->palx = customPaletteWidth/2;
1043 panel->paly = customPaletteHeight/2;
1046 /* Widgets for the ColorList Panel */
1047 panel->colorListFrm = WMCreateFrame(panel->win);
1048 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1049 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1050 WMMoveWidget(panel->colorListFrm, 5, 80);
1052 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1053 WMAddPopUpButtonItem(panel->colorListHistoryBtn, "X11-Colors");
1054 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1055 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
1056 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1057 * colorListHistoryCallback, panel); */
1058 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1059 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1061 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1062 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1063 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1064 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1065 WMMoveWidget(panel->colorListContentLst, 0, 23);
1066 WMHangData(panel->colorListContentLst, panel);
1068 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1069 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1070 WMSetPopUpButtonText(panel->colorListColorMenuBtn, "Color");
1071 WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
1072 colorListColorMenuCallback, panel);
1073 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
1074 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1076 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Add...");
1077 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Rename...");
1078 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Remove");
1080 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1081 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1082 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1084 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1085 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1086 WMSetPopUpButtonText(panel->colorListListMenuBtn, "List");
1087 WMSetPopUpButtonAction(panel->colorListListMenuBtn,
1088 colorListListMenuCallback, panel);
1089 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
1090 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
1091 PHEIGHT - 130);
1093 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "New...");
1094 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Rename...");
1095 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Remove");
1097 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1098 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1100 WMRealizeWidget(panel->win);
1101 WMMapSubwidgets(panel->win);
1103 WMMapSubwidgets(panel->wheelFrm);
1104 WMMapSubwidgets(panel->slidersFrm);
1105 WMMapSubwidgets(panel->grayFrm);
1106 WMMapSubwidgets(panel->rgbFrm);
1107 WMMapSubwidgets(panel->cmykFrm);
1108 WMMapSubwidgets(panel->hsbFrm);
1109 WMMapSubwidgets(panel->customPaletteFrm);
1110 WMMapSubwidgets(panel->customPaletteContentFrm);
1111 WMMapSubwidgets(panel->colorListFrm);
1113 /* Pixmap to indicate selection positions
1114 * wheelframe MUST be mapped.
1116 panel->selectionImg = XCreatePixmap(scrPtr->display,
1117 WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1118 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1119 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1121 readConfiguration(panel);
1122 readXColors(panel);
1124 return panel;
1128 WMColorPanel*
1129 WMGetColorPanel(WMScreen *scrPtr)
1131 WMColorPanel *panel;
1133 if (scrPtr->sharedColorPanel)
1134 return scrPtr->sharedColorPanel;
1136 panel = makeColorPanel(scrPtr, "colorPanel");
1138 scrPtr->sharedColorPanel = panel;
1140 return panel;
1144 void
1145 WMFreeColorPanel(WMColorPanel *panel)
1147 W_Screen *scr = WMWidgetScreen(panel->win);
1149 if (panel == scr->sharedColorPanel) {
1150 scr->sharedColorPanel = NULL;
1153 if (!panel)
1154 return;
1156 WMRemoveNotificationObserver(panel);
1157 WMUnmapWidget(panel->win);
1159 /* fonts */
1160 WMReleaseFont(panel->font8);
1161 WMReleaseFont(panel->font12);
1163 /* pixmaps */
1164 wheelDestroyMatrix(panel->wheelMtrx);
1165 if (panel->wheelImg)
1166 XFreePixmap(scr->display, panel->wheelImg);
1167 if (panel->selectionImg)
1168 XFreePixmap(scr->display, panel->selectionImg);
1169 if (panel->selectionBackImg)
1170 XFreePixmap(scr->display, panel->selectionBackImg);
1171 RDestroyImage(panel->customPaletteImg);
1173 /* structs */
1174 if (panel->lastBrowseDir)
1175 wfree(panel->lastBrowseDir);
1176 if (panel->configurationPath)
1177 wfree(panel->configurationPath);
1179 WMDestroyWidget(panel->win);
1181 wfree(panel);
1185 void
1186 WMCloseColorPanel(WMColorPanel *panel)
1188 WMFreeColorPanel(panel);
1192 void
1193 WMShowColorPanel(WMColorPanel *panel)
1195 WMScreen *scr = WMWidgetScreen(panel->win);
1196 WMColor *white = WMWhiteColor(scr);
1198 if (panel->color.set == cpNone)
1199 WMSetColorPanelColor(panel, white);
1200 WMReleaseColor(white);
1202 if (panel->mode != WMWheelModeColorPanel)
1203 WMPerformButtonClick(panel->wheelBtn);
1205 WMMapWidget(panel->win);
1209 static void
1210 closeWindowCallback(WMWidget *w, void *data)
1212 W_ColorPanel *panel = (W_ColorPanel*)data;
1214 WMCloseColorPanel(panel);
1218 static void
1219 readConfiguration(W_ColorPanel *panel)
1221 /* XXX Doesn't take care of "invalid" files */
1223 DIR *dPtr;
1224 struct dirent *dp;
1225 struct stat stat_buf;
1226 int item;
1228 if (stat(panel->configurationPath, &stat_buf)!=0) {
1229 if (mkdir(panel->configurationPath,
1230 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1231 wsyserror("Color Panel: Could not create directory %s needed"
1232 " to store configurations", panel->configurationPath);
1233 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1234 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1235 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1236 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1237 "File Error",
1238 "Could not create ColorPanel configuration directory",
1239 "OK", NULL, NULL);
1241 return;
1244 if (!(dPtr = opendir(panel->configurationPath))) {
1245 wwarning(NO_FILE_ERR, "%s", panel->configurationPath);
1246 return;
1249 while ((dp = readdir(dPtr)) != NULL) {
1250 unsigned int perm_mask;
1251 char *path = wstrappend(panel->configurationPath,
1252 dp->d_name);
1254 if (dp->d_name[0] != '.') {
1255 item = WMGetPopUpButtonNumberOfItems(
1256 panel->customPaletteHistoryBtn);
1257 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1259 perm_mask = (access(path, R_OK) == 0);
1260 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn,
1261 item, perm_mask);
1263 free(path);
1265 (void)closedir(dPtr);
1269 static void
1270 readXColors(W_ColorPanel *panel)
1272 struct stat stat_buf;
1273 FILE *rgbtxt;
1274 char line[MAX_LENGTH];
1275 int red, green, blue;
1276 char name[48];
1277 RColor *color;
1278 WMListItem *item;
1280 if (stat(RGBTXT, &stat_buf) != 0) {
1281 wsyserror(NO_FILE_ERR, " %s", RGBTXT);
1282 return;
1284 else {
1285 if ((rgbtxt = fopen(RGBTXT, "r"))) {
1286 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1287 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1288 color = wmalloc(sizeof(RColor));
1289 color->red = (unsigned char)red;
1290 color->green = (unsigned char)green;
1291 color->blue = (unsigned char)blue;
1292 item = WMAddListItem(panel->colorListContentLst, name);
1293 item->clientData = (void *)color;
1296 fclose(rgbtxt);
1298 else {
1299 wsyserror(NO_FILE_ERR, "%s", RGBTXT);
1305 void
1306 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1308 W_Screen *scr = WMWidgetScreen(panel->win);
1310 if (mode != WMWheelModeColorPanel) {
1311 WMUnmapWidget(panel->wheelFrm);
1312 if (panel->selectionBackImg) {
1313 XFreePixmap(WMWidgetScreen(panel->win)->display,
1314 panel->selectionBackImg);
1315 panel->selectionBackImg = None;
1318 if (mode != WMGrayModeColorPanel)
1319 WMUnmapWidget(panel->grayFrm);
1320 if (mode != WMRGBModeColorPanel)
1321 WMUnmapWidget(panel->rgbFrm);
1322 if (mode != WMCMYKModeColorPanel)
1323 WMUnmapWidget(panel->cmykFrm);
1324 if (mode != WMHSBModeColorPanel)
1325 WMUnmapWidget(panel->hsbFrm);
1326 if (mode != WMCustomPaletteModeColorPanel) {
1327 WMUnmapWidget(panel->customPaletteFrm);
1328 if (panel->selectionBackImg) {
1329 XFreePixmap(WMWidgetScreen(panel->win)->display,
1330 panel->selectionBackImg);
1331 panel->selectionBackImg = None;
1334 if (mode != WMColorListModeColorPanel)
1335 WMUnmapWidget(panel->colorListFrm);
1336 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1337 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1338 WMUnmapWidget(panel->slidersFrm);
1339 else
1340 panel->slidersmode = mode;
1342 if (mode == WMWheelModeColorPanel) {
1343 WMMapWidget(panel->wheelFrm);
1344 WMSetButtonSelected(panel->wheelBtn, True);
1345 if (panel->lastChanged != WMWheelModeColorPanel)
1346 wheelInit(panel);
1347 wheelRender(panel);
1348 wheelPaint(panel);
1349 } else if (mode == WMGrayModeColorPanel) {
1350 WMMapWidget(panel->slidersFrm);
1351 WMSetButtonSelected(panel->slidersBtn, True);
1352 WMMapWidget(panel->grayFrm);
1353 WMSetButtonSelected(panel->grayBtn, True);
1354 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1355 if (panel->lastChanged != WMGrayModeColorPanel)
1356 grayInit(panel);
1357 } else if (mode == WMRGBModeColorPanel) {
1358 WMMapWidget(panel->slidersFrm);
1359 WMSetButtonSelected(panel->slidersBtn, True);
1360 WMMapWidget(panel->rgbFrm);
1361 WMSetButtonSelected(panel->rgbBtn, True);
1362 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1363 if (panel->lastChanged != WMRGBModeColorPanel)
1364 rgbInit(panel);
1365 } else if (mode == WMCMYKModeColorPanel) {
1366 WMMapWidget(panel->slidersFrm);
1367 WMSetButtonSelected(panel->slidersBtn, True);
1368 WMMapWidget(panel->cmykFrm);
1369 WMSetButtonSelected(panel->cmykBtn, True);
1370 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1371 if (panel->lastChanged != WMCMYKModeColorPanel)
1372 cmykInit(panel);
1373 } else if (mode == WMHSBModeColorPanel) {
1374 WMMapWidget(panel->slidersFrm);
1375 WMSetButtonSelected(panel->slidersBtn, True);
1376 WMMapWidget(panel->hsbFrm);
1377 WMSetButtonSelected(panel->hsbBtn, True);
1378 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1379 if (panel->lastChanged != WMHSBModeColorPanel)
1380 hsbInit(panel);
1381 } else if (mode == WMCustomPaletteModeColorPanel) {
1382 WMMapWidget(panel->customPaletteFrm);
1383 WMSetButtonSelected(panel->customPaletteBtn, True);
1384 customSetPalette(panel);
1385 } else if (mode == WMColorListModeColorPanel) {
1386 WMMapWidget(panel->colorListFrm);
1387 WMSetButtonSelected(panel->colorListBtn, True);
1390 panel->mode = mode;
1394 WMColor*
1395 WMGetColorPanelColor(WMColorPanel *panel)
1397 return WMGetColorWellColor(panel->colorWell);
1401 void
1402 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1404 WMSetColorWellColor(panel->colorWell, color);
1406 panel->color.rgb.red = color->color.red >> 8;
1407 panel->color.rgb.green = color->color.green >> 8;
1408 panel->color.rgb.blue = color->color.blue >> 8;
1409 panel->color.set = cpRGB;
1411 if (panel->mode == panel->lastChanged)
1412 panel->lastChanged = 0;
1414 WMSetColorPanelPickerMode(panel, panel->mode);
1418 static void
1419 updateSwatch(WMColorPanel *panel, CPColor color)
1421 WMScreen *scr = WMWidgetScreen(panel->win);
1422 WMColor *wellcolor;
1424 if (color.set != cpRGB)
1425 convertCPColor(&color);
1427 panel->color = color;
1429 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8,
1430 color.rgb.green << 8,
1431 color.rgb.blue << 8, True);
1433 WMSetColorWellColor(panel->colorWell, wellcolor);
1434 WMReleaseColor(wellcolor);
1436 if (!panel->flags.dragging || panel->flags.continuous) {
1437 if (panel->action)
1438 (*panel->action)(panel, panel->clientData);
1440 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1441 NULL);
1445 static void
1446 modeButtonCallback(WMWidget *w, void *data)
1448 W_ColorPanel *panel = (W_ColorPanel*)(data);
1450 if (w == panel->wheelBtn)
1451 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1452 else if (w == panel->slidersBtn)
1453 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1454 else if (w == panel->customPaletteBtn)
1455 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1456 else if (w == panel->colorListBtn)
1457 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1458 else if (w == panel->grayBtn)
1459 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1460 else if (w == panel->rgbBtn)
1461 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1462 else if (w == panel->cmykBtn)
1463 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1464 else if (w == panel->hsbBtn)
1465 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1469 /****************** Magnifying Cursor Functions *******************/
1471 static XImage*
1472 magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
1474 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1475 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1476 displayHeight = DisplayHeight(scr->display, scr->screen);
1478 if (!(image && image->data)) {
1479 /* The image in panel->magnifyGlass->image does not exist yet.
1480 * Grab one from the screen (not beyond) and use it from now on.
1482 if (!(image = XGetImage(scr->display, scr->rootWin,
1483 x - Cursor_x_hot,
1484 y - Cursor_y_hot,
1485 w, h, AllPlanes, ZPixmap)))
1486 wwarning(X_ERR);
1488 return image;
1491 /* Coordinate correction for back pixmap
1492 * if magnifying glass is at screen-borders
1495 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1496 * Hatched area is beyond screen border.
1498 * |<-Cursor_x_hot->|
1499 * ________________|_____
1500 * |/ / / / / / /| | |
1501 * | / / / / / / |(x,y) |
1502 * |/_/_/_/_/_/_/|________|
1503 * |<----x0----->|<--w0-->|
1507 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1508 * screen borders
1509 * Hatched area is beyond screen border
1511 * |<-Cursor_x_hot->|
1512 * ________________|_______________
1513 * | | | / / / / / /|
1514 * | (x,y)|/ / / / / / |
1515 * |___________________|_/_/_/_/_/_/|
1516 * |<-------w0-------->| |
1517 * |<---------------w--|----------->|
1518 * | |
1519 * x0 Displaywidth-1
1522 if (x < Cursor_x_hot) { /* see fig. 1 */
1523 x0 = Cursor_x_hot - x;
1524 w0 = w - x0;
1527 if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1528 w0 = (displayWidth) - (x - Cursor_x_hot);
1531 if (y < Cursor_y_hot) { /* see fig. 1 */
1532 y0 = Cursor_y_hot - y;
1533 h0 = h - y0;
1536 if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1537 h0 = (displayHeight) - (y - Cursor_y_hot);
1539 /* end of coordinate correction */
1542 /* Grab an image from the screen, clipped if necessary,
1543 * and put it in the existing panel->magnifyGlass->image
1544 * with the corresponding clipping offset.
1546 if (!XGetSubImage(scr->display, scr->rootWin,
1547 x - Cursor_x_hot + x0,
1548 y - Cursor_y_hot + y0,
1549 w0, h0, AllPlanes, ZPixmap,
1550 image, x0, y0))
1551 wwarning(X_ERR);
1553 return NULL;
1557 static void
1558 magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1560 /* (x1, y1) = topleft corner of existing rectangle
1561 * (x2, y2) = topleft corner of new position
1564 W_Screen *scr = WMWidgetScreen(panel->win);
1565 int xa = 0, ya = 0, xb = 0, yb = 0;
1566 int width, height;
1567 const int dx = abs(x2 - x1),
1568 dy = abs(y2 - y1);
1569 XImage *image;
1570 const int x_min = Cursor_x_hot,
1571 y_min = Cursor_y_hot,
1572 x_max = DisplayWidth(scr->display, scr->screen) -1 -
1573 (Cursor_mask_width - Cursor_x_hot),
1574 y_max = DisplayHeight(scr->display, scr->screen) -1 -
1575 (Cursor_mask_height - Cursor_y_hot);
1577 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1578 return; /* No movement */
1580 if (x1 < x2)
1581 xa = dx;
1582 else
1583 xb = dx;
1585 if (y1 < y2)
1586 ya = dy;
1587 else
1588 yb = dy;
1590 width = Cursor_mask_width - dx;
1591 height = Cursor_mask_height - dy;
1593 /* If the traversed distance is larger than the size of the magnifying
1594 * glass contents, there is no need to do dirty rectangles. A whole new
1595 * rectangle can be grabbed (unless that rectangle falls partially
1596 * off screen).
1597 * Destroying the image and setting it to NULL will achieve that later on.
1599 * Of course, grabbing an XImage beyond the borders of the screen will
1600 * cause trouble, this is considdered a special case. Part of the screen
1601 * is grabbed, but there is no need for dirty rectangles.
1603 if ((width <= 0) || (height <= 0)) {
1604 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1605 if (panel->magnifyGlass->image)
1606 XDestroyImage(panel->magnifyGlass->image);
1607 panel->magnifyGlass->image = NULL;
1609 } else {
1610 if (panel->magnifyGlass->image) {
1611 /* Get dirty rectangle from panel->magnifyGlass->image */
1612 panel->magnifyGlass->dirtyRect =
1613 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1614 if (!panel->magnifyGlass->dirtyRect) {
1615 wwarning(X_ERR);
1616 return; /* X returned a NULL from XSubImage */
1621 /* Get image from screen */
1622 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
1623 Cursor_mask_width, Cursor_mask_height);
1624 if (image) { /* Only reassign if a *new* image was grabbed */
1625 panel->magnifyGlass->image = image;
1626 return;
1629 /* Copy previously stored rectangle on covered part of image */
1630 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1631 int old_height;
1633 /* "width" and "height" are used as coordinates here,
1634 * and run from [0...width-1] and [0...height-1] respectively.
1636 width--;
1637 height--;
1638 old_height = height;
1640 for (; width >= 0; width--)
1641 for (height = old_height; height >= 0; height--)
1642 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1643 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1644 XDestroyImage(panel->magnifyGlass->dirtyRect);
1645 panel->magnifyGlass->dirtyRect = NULL;
1648 return;
1652 static Pixmap
1653 magnifyCreatePixmap(WMColorPanel *panel)
1655 W_Screen *scr = WMWidgetScreen(panel->win);
1656 int u, v;
1657 #ifndef SHAPE
1658 Pixmap pixmap;
1659 #endif
1660 unsigned long color;
1662 if (!panel->magnifyGlass->image)
1663 return None;
1665 if (!panel->magnifyGlass->magPix)
1666 return None;
1669 * Copy an area of only 5x5 pixels from the center of the image.
1671 for (u = 0; u < 5; u++) {
1672 for (v = 0; v < 5; v++) {
1673 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1675 XSetForeground(scr->display, scr->copyGC, color);
1677 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1678 panel->magnifyGlass->color = ulongToRColor(scr, color);
1680 /* The center square must eventually be centered around the
1681 * hotspot. The image needs shifting to achieve this. The amount of
1682 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1683 * _ _ _ _ _
1684 * |_|_|_|_|_|
1685 * ^------- center of center square == Cursor_x_hot
1687 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1688 scr->copyGC,
1689 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1690 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1694 #ifdef SHAPE
1695 return panel->magnifyGlass->magPix;
1696 #else
1697 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1698 Cursor_mask_height, scr->depth);
1699 if (!pixmap)
1700 return None;
1702 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1703 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1705 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1706 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1707 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1708 /* (2,2) puts center pixel on center of glass */
1710 return pixmap;
1711 #endif
1716 static WMView*
1717 magnifyCreateView(W_ColorPanel *panel)
1719 W_Screen *scr = WMWidgetScreen(panel->win);
1720 WMView *magView;
1722 magView = W_CreateTopView(scr);
1723 if (!magView)
1724 return NULL;
1726 magView->self = panel->win;
1727 magView->flags.topLevel = 1;
1728 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1729 magView->attribs.override_redirect = True;
1730 magView->attribs.save_under = True;
1732 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1734 W_RealizeView(magView);
1736 return magView;
1740 static Cursor
1741 magnifyGrabPointer(W_ColorPanel *panel)
1743 W_Screen *scr = WMWidgetScreen(panel->win);
1744 Pixmap magPixmap, magPixmap2;
1745 Cursor magCursor;
1746 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1747 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1749 /* Cursor creation stuff */
1750 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1751 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1752 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1753 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1755 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1756 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1758 XFreePixmap(scr->display, magPixmap);
1759 XFreePixmap(scr->display, magPixmap2);
1761 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1763 /* Set up Pointer */
1764 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1765 PointerMotionMask | ButtonPressMask,
1766 GrabModeAsync, GrabModeAsync,
1767 scr->rootWin, magCursor, CurrentTime);
1769 return magCursor;
1773 static WMPoint
1774 magnifyInitialize(W_ColorPanel *panel)
1776 W_Screen *scr = WMWidgetScreen(panel->win);
1777 int x, y, u, v;
1778 unsigned int mask;
1779 Pixmap pixmap, clip_mask;
1780 WMPoint point;
1781 Window root_return, child_return;
1783 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1784 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1785 1, 0, 1);
1786 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1787 5*5 -1, 5*5 -1, scr->depth);
1789 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
1790 &x, &y, &u, &v, &mask);
1792 panel->magnifyGlass->image = NULL;
1794 /* Clipmask to make magnified view-contents circular */
1795 #ifdef SHAPE
1796 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1797 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1798 #else
1799 /* Clip circle in glass cursor */
1800 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1801 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1802 #endif
1804 XFreePixmap(scr->display, clip_mask);
1806 /* Draw initial magnifying glass contents */
1807 magnifyGetImageStored(panel, x, y, x, y);
1809 pixmap = magnifyCreatePixmap(panel);
1810 XSetWindowBackgroundPixmap(scr->display,
1811 WMViewXID(panel->magnifyGlass->view),
1812 pixmap);
1813 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1814 XFlush(scr->display);
1816 #ifndef SHAPE
1817 XFreePixmap(scr->display, pixmap);
1818 #endif
1820 point.x = x;
1821 point.y = y;
1823 return point;
1827 static void
1828 magnifyPutCursor(WMWidget *w, void *data)
1830 W_ColorPanel *panel = (W_ColorPanel*)(data);
1831 W_Screen *scr = WMWidgetScreen(panel->win);
1832 Cursor magCursor;
1833 Pixmap pixmap;
1834 XEvent event;
1835 WMPoint initialPosition;
1837 /* Destroy wheelBackImg, so it'll update properly */
1838 if (panel->selectionBackImg) {
1839 XFreePixmap(WMWidgetScreen(panel->win)->display,
1840 panel->selectionBackImg);
1841 panel->selectionBackImg = None;
1844 /* Create magnifying glass */
1845 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1846 panel->magnifyGlass->view = magnifyCreateView(panel);
1847 if (!panel->magnifyGlass->view)
1848 return;
1850 initialPosition = magnifyInitialize(panel);
1851 panel->magnifyGlass->x = initialPosition.x;
1852 panel->magnifyGlass->y = initialPosition.y;
1854 W_MoveView(panel->magnifyGlass->view,
1855 panel->magnifyGlass->x - Cursor_x_hot,
1856 panel->magnifyGlass->y - Cursor_y_hot);
1857 W_MapView(panel->magnifyGlass->view);
1859 magCursor = magnifyGrabPointer(panel);
1861 while (panel->magnifyGlass->image)
1863 WMNextEvent(scr->display, &event);
1865 /* Pack motion events */
1866 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1869 switch (event.type)
1871 case ButtonPress:
1872 XDestroyImage(panel->magnifyGlass->image);
1873 panel->magnifyGlass->image = NULL;
1875 if (event.xbutton.button == Button1) {
1876 panel->color.rgb = panel->magnifyGlass->color;
1877 panel->color.set = cpRGB;
1878 updateSwatch(panel, panel->color);
1880 switch (panel->mode) {
1881 case WMWheelModeColorPanel:
1882 wheelInit(panel);
1883 wheelRender(panel);
1884 wheelPaint(panel);
1885 break;
1886 case WMGrayModeColorPanel:
1887 grayInit(panel);
1888 break;
1889 case WMRGBModeColorPanel:
1890 rgbInit(panel);
1891 break;
1892 case WMCMYKModeColorPanel:
1893 cmykInit(panel);
1894 break;
1895 case WMHSBModeColorPanel:
1896 hsbInit(panel);
1897 break;
1898 default:
1899 break;
1901 panel->lastChanged = panel->mode;
1903 WMSetButtonSelected(panel->magnifyBtn, False);
1904 break;
1906 case MotionNotify:
1907 while (XPending(event.xmotion.display)) {
1908 XEvent ev;
1909 XPeekEvent(event.xmotion.display, &ev);
1910 if (ev.type == MotionNotify)
1911 XNextEvent(event.xmotion.display, &event);
1912 else
1913 break;
1916 /* Get a "dirty rectangle" */
1917 magnifyGetImageStored( panel,
1918 panel->magnifyGlass->x, panel->magnifyGlass->y,
1919 event.xmotion.x_root, event.xmotion.y_root);
1921 /* Update coordinates */
1922 panel->magnifyGlass->x = event.xmotion.x_root;
1923 panel->magnifyGlass->y = event.xmotion.y_root;
1925 /* Move view */
1926 W_MoveView(panel->magnifyGlass->view,
1927 panel->magnifyGlass->x - Cursor_x_hot,
1928 panel->magnifyGlass->y - Cursor_y_hot);
1930 /* Put new image (with magn.) in view */
1931 pixmap = magnifyCreatePixmap(panel);
1932 if (pixmap != None) {
1933 /* Change the window background */
1934 XSetWindowBackgroundPixmap(scr->display,
1935 WMViewXID(panel->magnifyGlass->view), pixmap);
1936 /* Force an Expose (handled by X) */
1937 XClearWindow(scr->display,
1938 WMViewXID(panel->magnifyGlass->view));
1939 /* Synchronize the event queue, so the Expose is handled NOW */
1940 XFlush(scr->display);
1941 #ifndef SHAPE
1942 XFreePixmap(scr->display, pixmap);
1943 #endif
1945 break;
1947 /* Try XQueryPointer for this !!! It returns windows that the pointer
1948 * is over. Note: We found this solving the invisible donkey cap bug
1950 #if 0 /* As it is impossible to make this work in all cases,
1951 * we consider it confusing. Therefore we disabled it.
1953 case FocusOut: /* fall through */
1954 case FocusIn:
1956 * Color Panel window (panel->win) lost or received focus.
1957 * We need to update the pixmap in the magnifying glass.
1959 * BUG Doesn't work with focus switches between two windows
1960 * if none of them is the color panel.
1962 XUngrabPointer(scr->display, CurrentTime);
1963 W_UnmapView(panel->magnifyGlass->view);
1965 magnifyInitialize(panel);
1967 W_MapView(panel->magnifyGlass->view);
1968 XGrabPointer (scr->display, panel->magnifyGlass->view->window,
1969 True, PointerMotionMask | ButtonPressMask,
1970 GrabModeAsync, GrabModeAsync,
1971 scr->rootWin, magCursor, CurrentTime);
1972 break;
1973 #endif
1974 default:
1975 WMHandleEvent(&event);
1976 break;
1977 } /* of switch */
1980 XUngrabPointer(scr->display, CurrentTime);
1981 XFreeCursor(scr->display, magCursor);
1983 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1984 panel->magnifyGlass->magPix = None;
1986 W_UnmapView(panel->magnifyGlass->view);
1987 W_DestroyView(panel->magnifyGlass->view);
1988 panel->magnifyGlass->view = NULL;
1990 wfree(panel->magnifyGlass);
1995 /****************** ColorWheel Functions ************************/
1997 static wheelMatrix*
1998 wheelCreateMatrix(unsigned int width, unsigned int height)
2000 wheelMatrix *matrix = NULL;
2001 int i;
2003 assert((width > 0) && (height > 0));
2005 matrix = wmalloc(sizeof(wheelMatrix));
2006 memset(matrix, 0, sizeof(wheelMatrix));
2007 matrix->width = width;
2008 matrix->height = height;
2010 for (i = 0; i < 3; i++) {
2011 matrix->data[i] = wmalloc(width*height*sizeof(unsigned char));
2014 return matrix;
2018 static void
2019 wheelDestroyMatrix(wheelMatrix *matrix)
2021 int i;
2023 if (!matrix)
2024 return;
2026 for (i = 0; i < 3; i++) {
2027 if (matrix->data[i])
2028 wfree(matrix->data[i]);
2030 wfree(matrix);
2034 static void
2035 wheelInitMatrix(W_ColorPanel *panel)
2037 int i;
2038 int x,y;
2039 unsigned char *rp, *gp, *bp;
2040 CPColor cpColor;
2041 long ofs[4];
2042 int xcor, ycor;
2043 unsigned short sat;
2044 int dhue[4];
2045 const int cw_halfsize = (colorWheelSize + 4)/2,
2046 cw_sqsize = (colorWheelSize +4) * (colorWheelSize +4),
2047 uchar_shift = getShift(sizeof(unsigned char));
2049 if (!panel->wheelMtrx)
2050 return;
2052 cpColor.hsv.value = 255;
2053 cpColor.set = cpHSV;
2055 ofs[0] = -1;
2056 ofs[1] = -(colorWheelSize + 4);
2058 /* offsets are counterclockwise (in triangles).
2060 * ofs[0] ---->
2061 * _______________________________________
2062 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
2063 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
2064 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
2065 * o | | | | | | | | | | | | | | | | | | | | | [3]
2067 * <---- ofs[2]
2068 * ____
2069 * |\ /| <-- triangles
2070 * | \/ |
2071 * | /\ |
2072 * |/__\|
2075 for (y = 0; y < cw_halfsize; y++) {
2076 for (x = y; x < (colorWheelSize+4-y); x++) {
2077 /* (xcor, ycor) is (x,y) relative to center of matrix */
2078 xcor = 2 * x - 4 - colorWheelSize;
2079 ycor = 2 * y - 4 - colorWheelSize;
2081 /* RColor.saturation is unsigned char and will wrap after 255 */
2082 sat = rint(255.0 *
2083 sqrtf( (float)(xcor*xcor) + (float)(ycor*ycor)) /
2084 (float)colorWheelSize);
2086 cpColor.hsv.saturation = (unsigned char)sat;
2088 ofs[0]++; /* top quarter of matrix*/
2089 ofs[1] += colorWheelSize + 4; /* left quarter */
2090 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
2091 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
2093 if (sat < 256) {
2094 if (xcor != 0)
2095 dhue[0] = rint(atan((float)ycor / (float)xcor) *
2096 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
2097 else
2098 dhue[0] = 270;
2100 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
2101 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
2102 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
2103 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
2105 for (i = 0; i < 4; i++) {
2106 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2107 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2108 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2110 cpColor.hsv.hue = dhue[i];
2111 convertCPColor(&cpColor);
2113 *rp = (unsigned char)(cpColor.rgb.red);
2114 *gp = (unsigned char)(cpColor.rgb.green);
2115 *bp = (unsigned char)(cpColor.rgb.blue);
2118 else {
2119 for (i = 0; i < 4; i++) {
2120 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2121 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2122 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2124 *rp = (unsigned char)0;
2125 *gp = (unsigned char)0;
2126 *bp = (unsigned char)0;
2131 ofs[0] += 2*y+1;
2132 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
2137 static void
2138 wheelCalculateValues(W_ColorPanel *panel, int maxvalue)
2140 unsigned int i;
2141 unsigned int v;
2143 for (i = 0; i < 256; i++) {
2144 /* We divide by 128 in advance, and check whether that number divides
2145 * by 2 properly. If not, we add one to round the number correctly
2147 v = (i*maxvalue) >> 7;
2148 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2153 static void
2154 wheelRender(W_ColorPanel *panel)
2156 W_Screen *scr = WMWidgetScreen(panel->win);
2157 int x,y;
2158 RImage *image;
2159 unsigned char *rp, *gp, *bp;
2160 RColor gray;
2161 unsigned long ofs = 0;
2162 unsigned char shift = getShift(sizeof(unsigned char));
2164 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, False);
2165 if (!image) {
2166 wwarning(NO_MEMORY_ERR);
2167 return;
2170 /* TODO Make this transparent istead of gray */
2171 gray.red = gray.green = gray.blue = 0xaa;
2173 for (y = 0; y < colorWheelSize+4; y++) {
2174 for (x = 0; x < colorWheelSize+4; x++) {
2175 rp = image->data[0] + (ofs << shift);
2176 gp = image->data[1] + (ofs << shift);
2177 bp = image->data[2] + (ofs << shift);
2179 if (wheelInsideColorWheel(panel, ofs)) {
2180 *rp = (unsigned int)(panel->wheelMtrx->values[
2181 panel->wheelMtrx->data[0][ofs] ]);
2182 *gp = (unsigned int)(panel->wheelMtrx->values[
2183 panel->wheelMtrx->data[1][ofs] ]);
2184 *bp = (unsigned int)(panel->wheelMtrx->values[
2185 panel->wheelMtrx->data[2][ofs] ]);
2187 else {
2188 *rp = (unsigned char)(gray.red);
2189 *gp = (unsigned char)(gray.green);
2190 *bp = (unsigned char)(gray.blue);
2192 ofs++;
2196 if (panel->wheelImg)
2197 XFreePixmap(scr->display, panel->wheelImg);
2199 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2200 RDestroyImage(image);
2202 /* Check if backimage exists. If it doesn't, allocate and fill it */
2203 if (!panel->selectionBackImg) {
2204 panel->selectionBackImg = XCreatePixmap(scr->display,
2205 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2206 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2207 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2208 /* -2 is hot spot correction */
2213 static Bool
2214 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2216 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2217 (panel->wheelMtrx->data[1][ofs] != 0) &&
2218 (panel->wheelMtrx->data[2][ofs] != 0));
2222 static void
2223 wheelPaint (W_ColorPanel *panel)
2225 W_Screen *scr = WMWidgetScreen(panel->win);
2227 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2228 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2230 /* Draw selection image */
2231 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2232 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2236 static void
2237 wheelHandleEvents(XEvent *event, void *data)
2239 W_ColorPanel *panel = (W_ColorPanel*)data;
2241 switch (event->type) {
2242 case Expose:
2243 if (event->xexpose.count != 0) /* TODO Improve */
2244 break;
2245 wheelPaint(panel);
2246 break;
2251 static void
2252 wheelHandleActionEvents(XEvent *event, void *data)
2254 W_ColorPanel *panel = (W_ColorPanel*)data;
2256 switch (event->type) {
2257 case ButtonPress:
2258 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2259 COLORWHEEL_PART) {
2261 panel->lastChanged = WMWheelModeColorPanel;
2262 panel->flags.dragging = 1;
2264 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2266 break;
2268 case ButtonRelease:
2269 panel->flags.dragging = 0;
2270 if (!panel->flags.continuous) {
2271 if (panel->action)
2272 (*panel->action)(panel, panel->clientData);
2274 break;
2276 case MotionNotify:
2277 if (panel->flags.dragging) {
2278 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2279 COLORWHEEL_PART) {
2280 wheelPositionSelection(panel, event->xmotion.x,
2281 event->xmotion.y);
2283 else
2284 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2285 event->xmotion.y);
2287 break;
2292 static int
2293 getPickerPart(W_ColorPanel *panel, int x, int y)
2295 int lx, ly;
2296 unsigned long ofs;
2298 lx = x;
2299 ly = y;
2301 if (panel->mode == WMWheelModeColorPanel) {
2302 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2303 (ly <= 2+colorWheelSize)) {
2305 ofs = ly*panel->wheelMtrx->width+lx;
2307 if (wheelInsideColorWheel(panel, ofs))
2308 return COLORWHEEL_PART;
2312 if (panel->mode == WMCustomPaletteModeColorPanel) {
2313 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2314 (ly < customPaletteHeight-2)) {
2315 return CUSTOMPALETTE_PART;
2319 return 0;
2323 static void
2324 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2326 int value;
2328 W_ColorPanel *panel = (W_ColorPanel*)data;
2330 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2332 wheelCalculateValues(panel, value);
2334 if (panel->color.set == cpRGB) {
2335 convertCPColor(&panel->color);
2336 panel->color.set = cpHSV;
2339 panel->color.hsv.value = value;
2341 wheelRender(panel);
2342 wheelPaint(panel);
2343 wheelUpdateSelection(panel);
2347 static void
2348 wheelUpdateSelection(W_ColorPanel *panel)
2350 W_Screen *scr = WMWidgetScreen(panel->win);
2352 updateSwatch(panel, panel->color);
2353 panel->lastChanged = WMWheelModeColorPanel;
2355 /* Redraw color selector (and make a backup of the part it will cover) */
2356 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2357 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2358 /* "-2" is correction for hotspot location */
2359 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2360 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2361 /* see above */
2365 static void
2366 wheelUndrawSelection(W_ColorPanel *panel)
2368 W_Screen *scr = WMWidgetScreen(panel->win);
2370 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2371 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2372 /* see above */
2375 static void
2376 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2378 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2380 panel->color.rgb.red = panel->wheelMtrx->values[
2381 panel->wheelMtrx->data[0][ofs] ];
2383 panel->color.rgb.green = panel->wheelMtrx->values[
2384 panel->wheelMtrx->data[1][ofs] ];
2386 panel->color.rgb.blue = panel->wheelMtrx->values[
2387 panel->wheelMtrx->data[2][ofs] ];
2388 panel->color.set = cpRGB;
2390 wheelUndrawSelection(panel);
2392 panel->colx = x;
2393 panel->coly = y;
2395 wheelUpdateSelection(panel);
2396 wheelUpdateBrightnessGradientFromLocation(panel);
2399 static void
2400 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2402 int hue;
2403 int xcor, ycor;
2404 CPColor cpColor;
2406 xcor = x * 2 - colorWheelSize - 4;
2407 ycor = y * 2 - colorWheelSize - 4;
2409 panel->color.hsv.saturation = 255;
2410 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2412 if (xcor != 0)
2413 hue = rint(atan(- (float)ycor / (float)xcor) * (180.0/M_PI));
2414 else {
2415 if (ycor < 0)
2416 hue = 90;
2417 else
2418 hue = 270;
2421 if (xcor < 0)
2422 hue += 180;
2424 if ((xcor > 0) && (ycor > 0))
2425 hue += 360;
2427 panel->color.hsv.hue = hue;
2428 panel->color.set = cpHSV;
2429 convertCPColor(&panel->color);
2431 wheelUndrawSelection(panel);
2433 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2434 cos( panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2435 /* "+2" because of "colorWheelSize + 4" */
2436 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2437 sin(- panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2439 wheelUpdateSelection(panel);
2440 cpColor = panel->color;
2441 wheelUpdateBrightnessGradient(panel, cpColor);
2444 static void
2445 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2447 CPColor from;
2448 unsigned long ofs;
2450 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2452 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2453 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2454 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2455 from.set = cpRGB;
2457 wheelUpdateBrightnessGradient(panel, from);
2460 static void
2461 wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor)
2463 RColor to;
2464 RImage *sliderImg;
2465 WMPixmap *sliderPxmp;
2467 to.red = to.green = to.blue = 0;
2469 if (topColor.set == cpHSV) {
2470 topColor.hsv.value = 255;
2471 convertCPColor(&topColor);
2474 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2475 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2476 sliderImg, 0);
2477 RDestroyImage(sliderImg);
2478 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2479 WMReleasePixmap(sliderPxmp);
2482 /****************** Grayscale Panel Functions ***************/
2484 static void
2485 grayBrightnessSliderCallback(WMWidget *w, void *data)
2487 CPColor cpColor;
2488 int value;
2489 char tmp[4];
2490 W_ColorPanel *panel = (W_ColorPanel*)data;
2492 value = WMGetSliderValue(panel->grayBrightnessS);
2494 sprintf(tmp, "%d", value);
2496 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2497 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55*value);
2498 cpColor.set = cpRGB;
2500 updateSwatch(panel, cpColor);
2501 panel->lastChanged = WMGrayModeColorPanel;
2504 static void
2505 grayPresetButtonCallback(WMWidget *w, void *data)
2507 CPColor cpColor;
2508 char tmp[4];
2509 int value;
2510 int i=0;
2511 W_ColorPanel *panel = (W_ColorPanel*)data;
2513 while (i < 7) {
2514 if (w == panel->grayPresetBtn[i])
2515 break;
2516 i++;
2519 value = rint((100.0*i)/6.0);
2520 sprintf(tmp, "%d", value);
2522 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2523 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2524 rint((255.0*i)/6.0);
2525 cpColor.set = cpRGB;
2527 WMSetSliderValue(panel->grayBrightnessS, rint((100.0*i)/6.0));
2529 updateSwatch(panel, cpColor);
2530 panel->lastChanged = WMGrayModeColorPanel;
2533 static void
2534 grayBrightnessTextFieldCallback(void *observerData,
2535 WMNotification *notification)
2537 CPColor cpColor;
2538 char tmp[4];
2539 int value;
2540 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2542 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2543 if (value > 100)
2544 value = 100;
2545 if (value < 0)
2546 value = 0;
2548 sprintf(tmp, "%d", value);
2549 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2550 WMSetSliderValue(panel->grayBrightnessS, value);
2552 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2553 rint((255.0*value)/100.0);
2554 cpColor.set = cpRGB;
2556 updateSwatch(panel, cpColor);
2557 panel->lastChanged = WMGrayModeColorPanel;
2560 /******************* RGB Panel Functions *****************/
2562 static void
2563 rgbSliderCallback(WMWidget *w, void *data)
2565 CPColor cpColor;
2566 int value[3];
2567 char tmp[4];
2568 W_ColorPanel *panel = (W_ColorPanel*)data;
2570 value[0] = WMGetSliderValue(panel->rgbRedS);
2571 value[1] = WMGetSliderValue(panel->rgbGreenS);
2572 value[2] = WMGetSliderValue(panel->rgbBlueS);
2574 sprintf(tmp, "%d", value[0]);
2575 WMSetTextFieldText(panel->rgbRedT, tmp);
2576 sprintf(tmp, "%d", value[1]);
2577 WMSetTextFieldText(panel->rgbGreenT, tmp);
2578 sprintf(tmp, "%d", value[2]);
2579 WMSetTextFieldText(panel->rgbBlueT, tmp);
2581 cpColor.rgb.red = value[0];
2582 cpColor.rgb.green = value[1];
2583 cpColor.rgb.blue = value[2];
2584 cpColor.set = cpRGB;
2586 updateSwatch(panel, cpColor);
2587 panel->lastChanged = WMRGBModeColorPanel;
2590 static void
2591 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2593 CPColor cpColor;
2594 int value[3];
2595 char tmp[4];
2596 int n;
2597 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2599 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2600 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2601 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2603 for (n=0; n < 3; n++) {
2604 if (value[n] > 255)
2605 value[n] = 255;
2606 if (value[n] < 0)
2607 value[n] = 0;
2610 sprintf(tmp, "%d", value[0]);
2611 WMSetTextFieldText(panel->rgbRedT, tmp);
2612 sprintf(tmp, "%d", value[1]);
2613 WMSetTextFieldText(panel->rgbGreenT, tmp);
2614 sprintf(tmp, "%d", value[2]);
2615 WMSetTextFieldText(panel->rgbBlueT, tmp);
2617 WMSetSliderValue(panel->rgbRedS, value[0]);
2618 WMSetSliderValue(panel->rgbGreenS, value[1]);
2619 WMSetSliderValue(panel->rgbBlueS, value[2]);
2621 cpColor.rgb.red = value[0];
2622 cpColor.rgb.green = value[1];
2623 cpColor.rgb.blue = value[2];
2624 cpColor.set = cpRGB;
2626 updateSwatch(panel, cpColor);
2627 panel->lastChanged = WMRGBModeColorPanel;
2631 /******************* CMYK Panel Functions *****************/
2633 static void
2634 cmykSliderCallback(WMWidget *w, void *data)
2636 CPColor cpColor;
2637 int value[4];
2638 char tmp[4];
2639 W_ColorPanel *panel = (W_ColorPanel*)data;
2640 float scale;
2642 value[0] = WMGetSliderValue(panel->cmykCyanS);
2643 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2644 value[2] = WMGetSliderValue(panel->cmykYellowS);
2645 value[3] = WMGetSliderValue(panel->cmykBlackS);
2647 sprintf(tmp, "%d", value[0]);
2648 WMSetTextFieldText(panel->cmykCyanT, tmp);
2649 sprintf(tmp, "%d", value[1]);
2650 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2651 sprintf(tmp, "%d", value[2]);
2652 WMSetTextFieldText(panel->cmykYellowT, tmp);
2653 sprintf(tmp, "%d", value[3]);
2654 WMSetTextFieldText(panel->cmykBlackT, tmp);
2656 scale = 2.55 * (1.0 - (value[3] / 100.0));
2657 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2658 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2659 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2660 cpColor.set = cpRGB;
2662 updateSwatch(panel, cpColor);
2663 panel->lastChanged = WMCMYKModeColorPanel;
2666 static void
2667 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2669 CPColor cpColor;
2670 int value[4];
2671 char tmp[4];
2672 int n;
2673 float scale;
2674 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2676 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2677 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2678 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2679 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2681 for (n=0; n < 4; n++) {
2682 if (value[n] > 100)
2683 value[n] = 100;
2684 if (value[n] < 0)
2685 value[n] = 0;
2688 sprintf(tmp, "%d", value[0]);
2689 WMSetTextFieldText(panel->cmykCyanT, tmp);
2691 sprintf(tmp, "%d", value[1]);
2692 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2694 sprintf(tmp, "%d", value[2]);
2695 WMSetTextFieldText(panel->cmykYellowT, tmp);
2697 sprintf(tmp, "%d", value[3]);
2698 WMSetTextFieldText(panel->cmykBlackT, tmp);
2700 WMSetSliderValue(panel->cmykCyanS, value[0]);
2701 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2702 WMSetSliderValue(panel->cmykYellowS, value[2]);
2703 WMSetSliderValue(panel->cmykBlackS, value[3]);
2705 scale = 2.55 * (1.0 - (value[3] / 100.0));
2706 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2707 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2708 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2709 cpColor.set = cpRGB;
2711 updateSwatch(panel, cpColor);
2712 panel->lastChanged = WMCMYKModeColorPanel;
2715 /********************** HSB Panel Functions ***********************/
2717 static void
2718 hsbSliderCallback(WMWidget *w, void *data)
2720 CPColor cpColor;
2721 int value[3];
2722 char tmp[4];
2723 W_ColorPanel *panel = (W_ColorPanel*)data;
2725 value[0] = WMGetSliderValue(panel->hsbHueS);
2726 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2727 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2729 sprintf(tmp, "%d", value[0]);
2730 WMSetTextFieldText(panel->hsbHueT, tmp);
2731 sprintf(tmp, "%d", value[1]);
2732 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2733 sprintf(tmp, "%d", value[2]);
2734 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2736 cpColor.hsv.hue = value[0];
2737 cpColor.hsv.saturation = value[1]*2.55;
2738 cpColor.hsv.value = value[2]*2.55;
2739 cpColor.set = cpHSV;
2741 convertCPColor(&cpColor);
2743 panel->lastChanged = WMHSBModeColorPanel;
2744 updateSwatch(panel, cpColor);
2746 if (w != panel->hsbBrightnessS)
2747 hsbUpdateBrightnessGradient(panel);
2748 if (w != panel->hsbSaturationS)
2749 hsbUpdateSaturationGradient(panel);
2750 if (w != panel->hsbHueS)
2751 hsbUpdateHueGradient(panel);
2754 static void
2755 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2757 CPColor cpColor;
2758 int value[3];
2759 char tmp[4];
2760 int n;
2761 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2763 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2764 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2765 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2767 if (value[0] > 359)
2768 value[0] = 359;
2769 if (value[0] < 0)
2770 value[0] = 0;
2772 for (n=1; n < 3; n++) {
2773 if (value[n] > 100)
2774 value[n] = 100;
2775 if (value[n] < 0)
2776 value[n] = 0;
2779 sprintf(tmp, "%d", value[0]);
2780 WMSetTextFieldText(panel->hsbHueT, tmp);
2781 sprintf(tmp, "%d", value[1]);
2782 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2783 sprintf(tmp, "%d", value[2]);
2784 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2786 WMSetSliderValue(panel->hsbHueS, value[0]);
2787 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2788 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2790 cpColor.hsv.hue = value[0];
2791 cpColor.hsv.saturation = value[1]*2.55;
2792 cpColor.hsv.value = value[2]*2.55;
2793 cpColor.set = cpHSV;
2795 convertCPColor(&cpColor);
2797 panel->lastChanged = WMHSBModeColorPanel;
2798 updateSwatch(panel, cpColor);
2800 hsbUpdateBrightnessGradient(panel);
2801 hsbUpdateSaturationGradient(panel);
2802 hsbUpdateHueGradient(panel);
2805 static void
2806 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2808 W_Screen *scr = WMWidgetScreen(panel->win);
2809 RColor from;
2810 CPColor to;
2811 RImage *sliderImg;
2812 WMPixmap *sliderPxmp;
2814 from.red = from.green = from.blue = 0;
2815 to.hsv = panel->color.hsv;
2816 to.hsv.value = 255;
2817 to.set = cpHSV;
2819 convertCPColor(&to);
2821 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2822 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2823 RDestroyImage(sliderImg);
2825 if (sliderPxmp)
2826 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2827 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white),
2828 False, "Brightness", strlen("Brightness"));
2829 else
2830 wwarning(NO_MEMORY_ERR);
2832 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2833 WMReleasePixmap(sliderPxmp);
2836 static void
2837 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2839 W_Screen *scr = WMWidgetScreen(panel->win);
2840 CPColor from;
2841 CPColor to;
2842 RImage *sliderImg;
2843 WMPixmap *sliderPxmp;
2845 from.hsv = panel->color.hsv;
2846 from.hsv.saturation = 0;
2847 from.set = cpHSV;
2848 convertCPColor(&from);
2850 to.hsv = panel->color.hsv;
2851 to.hsv.saturation = 255;
2852 to.set = cpHSV;
2853 convertCPColor(&to);
2855 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb),
2856 RGRD_HORIZONTAL);
2857 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2858 RDestroyImage(sliderImg);
2860 if (sliderPxmp)
2861 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2862 panel->font12, 2, 0, 100, WALeft,
2863 WMColorGC(from.hsv.value < 128 ? scr->white : scr->black), False,
2864 "Saturation", strlen("Saturation"));
2865 else
2866 wwarning(NO_MEMORY_ERR);
2868 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2869 WMReleasePixmap(sliderPxmp);
2872 static void
2873 hsbUpdateHueGradient(W_ColorPanel *panel)
2875 W_Screen *scr = WMWidgetScreen(panel->win);
2876 RColor **colors = NULL;
2877 RHSVColor hsvcolor;
2878 RImage *sliderImg;
2879 WMPixmap *sliderPxmp;
2880 int i;
2882 hsvcolor = panel->color.hsv;
2884 colors = wmalloc(sizeof(RColor*)*(8));
2885 for (i=0; i<7; i++) {
2886 hsvcolor.hue = (360*i)/6;
2887 colors[i] = wmalloc(sizeof(RColor));
2888 RHSVtoRGB(&hsvcolor, colors[i]);
2890 colors[7] = NULL;
2892 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2893 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2894 RDestroyImage(sliderImg);
2896 if (sliderPxmp)
2897 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2898 panel->font12, 2, 0, 100, WALeft,
2899 WMColorGC(hsvcolor.value < 128 ? scr->white : scr->black), False,
2900 "Hue", strlen("Hue"));
2901 else
2902 wwarning(NO_MEMORY_ERR);
2904 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2905 WMReleasePixmap(sliderPxmp);
2907 for (i=0; i<7; i++)
2908 wfree(colors[i]);
2910 wfree(colors);
2913 /*************** Custom Palette Functions ****************/
2915 static void
2916 customRenderSpectrum(W_ColorPanel *panel)
2918 RImage *spectrum;
2919 int x,y;
2920 unsigned long ofs;
2921 unsigned char *rp, *gp, *bp;
2922 CPColor cpColor;
2924 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, 0);
2926 for (y=0; y<360; y++) {
2927 cpColor.hsv.hue = y;
2928 cpColor.hsv.saturation = 0;
2929 cpColor.hsv.value = 255;
2930 cpColor.set = cpHSV;
2932 for (x=0; x<511; x++) {
2933 ofs = (y * 511) + x;
2935 convertCPColor(&cpColor);
2937 rp = spectrum->data[0] + ofs;
2938 gp = spectrum->data[1] + ofs;
2939 bp = spectrum->data[2] + ofs;
2941 *rp = (unsigned char)cpColor.rgb.red;
2942 *gp = (unsigned char)cpColor.rgb.green;
2943 *bp = (unsigned char)cpColor.rgb.blue;
2945 if (x<255)
2946 cpColor.hsv.saturation++;
2948 if (x>255)
2949 cpColor.hsv.value--;
2952 if (panel->customPaletteImg) {
2953 RDestroyImage(panel->customPaletteImg);
2954 panel->customPaletteImg = NULL;
2956 panel->customPaletteImg = spectrum;
2961 static void
2962 customSetPalette(W_ColorPanel *panel)
2964 W_Screen *scr = WMWidgetScreen(panel->win);
2965 RImage *scaledImg;
2966 Pixmap image;
2967 int item;
2969 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2970 customPaletteHeight, scr->depth);
2972 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2973 customPaletteHeight);
2974 RConvertImage(scr->rcontext, scaledImg, &image);
2975 RDestroyImage(scaledImg);
2977 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2978 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2980 /* Check backimage exists. If it doesn't, allocate and fill it */
2981 if (!panel->selectionBackImg) {
2982 panel->selectionBackImg = XCreatePixmap(scr->display,
2983 panel->customPaletteContentView->window, 4, 4, scr->depth);
2986 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2987 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2988 XCopyArea(scr->display, panel->selectionImg,
2989 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2990 panel->palx-2, panel->paly-2);
2991 XFreePixmap(scr->display, image);
2993 panel->palXRatio = (float)(panel->customPaletteImg->width) /
2994 (float)(customPaletteWidth);
2995 panel->palYRatio = (float)(panel->customPaletteImg->height) /
2996 (float)(customPaletteHeight);
2998 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
3002 static void
3003 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
3005 W_Screen *scr = WMWidgetScreen(panel->win);
3006 unsigned long ofs;
3009 /* undraw selection */
3010 XCopyArea(scr->display, panel->selectionBackImg,
3011 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3012 panel->palx-2, panel->paly-2);
3014 panel->palx = x;
3015 panel->paly = y;
3017 ofs = rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
3018 panel->customPaletteImg->width;
3020 panel->color.rgb.red = panel->customPaletteImg->data[0][ofs];
3021 panel->color.rgb.green = panel->customPaletteImg->data[1][ofs];
3022 panel->color.rgb.blue = panel->customPaletteImg->data[2][ofs];
3023 panel->color.set = cpRGB;
3025 updateSwatch(panel, panel->color);
3026 panel->lastChanged = WMCustomPaletteModeColorPanel;
3028 /* Redraw color selector (and make a backup of the part it will cover) */
3029 XCopyArea(scr->display, panel->customPaletteContentView->window,
3030 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
3031 4, 4, 0, 0); /* "-2" is correction for hotspot location */
3032 XCopyArea(scr->display, panel->selectionImg,
3033 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3034 panel->palx-2, panel->paly-2); /* see above */
3038 static void
3039 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
3041 if (x < 2)
3042 x = 2;
3043 if (y < 2)
3044 y = 2;
3045 if (x >= customPaletteWidth)
3046 x = customPaletteWidth -2;
3047 if (y >= customPaletteHeight)
3048 y = customPaletteHeight -2;
3050 customPalettePositionSelection(panel, x, y);
3054 static void
3055 customPaletteHandleEvents(XEvent *event, void *data)
3057 W_ColorPanel *panel = (W_ColorPanel*)data;
3059 switch (event->type) {
3060 case Expose:
3061 if (event->xexpose.count != 0) /* TODO Improve. */
3062 break;
3063 customSetPalette(panel);
3064 break;
3068 static void
3069 customPaletteHandleActionEvents(XEvent *event, void *data)
3071 W_ColorPanel *panel = (W_ColorPanel*)data;
3072 int x, y;
3074 switch (event->type) {
3075 case ButtonPress:
3076 x = event->xbutton.x;
3077 y = event->xbutton.y;
3079 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3080 panel->flags.dragging = 1;
3081 customPalettePositionSelection(panel, x, y);
3083 break;
3085 case ButtonRelease:
3086 panel->flags.dragging = 0;
3087 if (!panel->flags.continuous) {
3088 if (panel->action)
3089 (*panel->action)(panel, panel->clientData);
3091 break;
3093 case MotionNotify:
3094 x = event->xmotion.x;
3095 y = event->xmotion.y;
3097 if (panel->flags.dragging) {
3098 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3099 customPalettePositionSelection(panel, x, y);
3101 else
3102 customPalettePositionSelectionOutBounds(panel, x, y);
3104 break;
3109 static void
3110 customPaletteMenuCallback(WMWidget *w, void *data)
3112 W_ColorPanel *panel = (W_ColorPanel*)data;
3113 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
3115 switch (item) {
3116 case CPmenuNewFromFile:
3117 customPaletteMenuNewFromFile(panel);
3118 break;
3119 case CPmenuRename:
3120 customPaletteMenuRename(panel);
3121 break;
3122 case CPmenuRemove:
3123 customPaletteMenuRemove(panel);
3124 break;
3125 case CPmenuCopy:
3126 break;
3127 case CPmenuNewFromClipboard:
3128 break;
3133 static void
3134 customPaletteMenuNewFromFile(W_ColorPanel *panel)
3136 W_Screen *scr = WMWidgetScreen(panel->win);
3137 WMOpenPanel *browseP;
3138 char *filepath;
3139 char *filename = NULL;
3140 char *spath;
3141 char *tmp;
3142 int i;
3143 RImage *tmpImg = NULL;
3145 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3146 spath = wexpandpath(wgethomedir());
3147 else
3148 spath = wexpandpath(panel->lastBrowseDir);
3150 browseP = WMGetOpenPanel(scr);
3151 WMSetFilePanelCanChooseDirectories(browseP, 0);
3152 WMSetFilePanelCanChooseFiles(browseP, 1);
3154 /* Get a filename */
3155 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3156 "Open Palette", RSupportedFileFormats()) ) {
3157 filepath = WMGetFilePanelFileName(browseP);
3159 /* Get seperation position between path and filename */
3160 i = strrchr(filepath, '/') - filepath + 1;
3161 if (i > strlen(filepath))
3162 i = strlen(filepath);
3164 /* Store last browsed path */
3165 if (panel->lastBrowseDir)
3166 wfree(panel->lastBrowseDir);
3167 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3168 strncpy(panel->lastBrowseDir, filepath, i);
3169 panel->lastBrowseDir[i] = '\0';
3171 /* Get filename from path */
3172 filename = wstrdup(filepath + i);
3174 /* Check for duplicate files, and rename it if there are any */
3175 tmp = wstrappend(panel->configurationPath, filename);
3176 while (access (tmp, F_OK) == 0) {
3177 char *newName;
3179 wfree(tmp);
3181 newName = generateNewFilename(filename);
3182 wfree(filename);
3183 filename = newName;
3185 tmp = wstrappend(panel->configurationPath, filename);
3187 wfree(tmp);
3189 /* Copy image to $(gnustepdir)/Library/Colors/ &
3190 * Add filename to history menu */
3191 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3193 /* filepath is a "local" path now the file has been copied */
3194 wfree(filepath);
3195 filepath = wstrappend(panel->configurationPath, filename);
3197 /* load the image & add menu entries */
3198 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3199 if (tmpImg) {
3200 if (panel->customPaletteImg)
3201 RDestroyImage(panel->customPaletteImg);
3202 panel->customPaletteImg = tmpImg;
3204 customSetPalette(panel);
3205 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3207 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3208 panel->customPaletteHistoryBtn)-1;
3210 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3211 panel->currentPalette);
3213 } else {
3214 tmp = wstrappend(panel->configurationPath, filename);
3216 i = remove(tmp); /* Delete the file, it doesn't belong here */
3217 WMRunAlertPanel(scr, panel->win, "File Error",
3218 "Invalid file format !", "OK", NULL, NULL);
3219 if (i != 0) {
3220 wsyserror("can't remove file %s", tmp);
3221 WMRunAlertPanel(scr, panel->win, "File Error",
3222 "Couldn't remove file from Configuration Directory !",
3223 "OK", NULL, NULL);
3225 wfree(tmp);
3227 wfree(filepath);
3228 wfree(filename);
3230 WMFreeFilePanel(browseP);
3232 wfree(spath);
3236 static void
3237 customPaletteMenuRename(W_ColorPanel *panel)
3239 W_Screen *scr = WMWidgetScreen(panel->win);
3240 char *toName = NULL;
3241 char *fromName;
3242 char *toPath, *fromPath;
3243 int item;
3244 int index;
3246 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3247 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3249 toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
3250 fromName, "OK", "Cancel");
3252 if (toName) {
3254 /* As some people do certain stupid things... */
3255 if (strcmp(toName, fromName) == 0) {
3256 wfree(toName);
3257 return;
3260 /* For normal people */
3261 fromPath = wstrappend(panel->configurationPath, fromName);
3262 toPath = wstrappend(panel->configurationPath, toName);
3264 if (access (toPath, F_OK) == 0) {
3265 /* Careful, this palette exists already */
3266 if (WMRunAlertPanel(scr, panel->win, "Warning",
3267 "Palette already exists !\n\nOverwrite ?", "No", "Yes",
3268 NULL) == 1) {
3269 /* "No" = 0, "Yes" = 1 */
3270 int items = WMGetPopUpButtonNumberOfItems(
3271 panel->customPaletteHistoryBtn);
3273 remove(toPath);
3275 /* Remove from History list too */
3276 index = 1;
3277 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3278 panel->customPaletteHistoryBtn, index),
3279 toName) != 0 ))
3280 index++;
3282 if (index < items) {
3283 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3284 index);
3285 if (index < item)
3286 item--;
3289 } else {
3290 wfree(fromPath);
3291 wfree(toName);
3292 wfree(toPath);
3294 return;
3298 if ( rename(fromPath, toPath) != 0)
3299 wsyserror("Couldn't rename palette %s to %s\n", fromName, toName);
3300 else {
3301 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3302 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3303 toName);
3305 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3307 wfree(fromPath);
3308 wfree(toPath);
3309 wfree(toName);
3314 static void
3315 customPaletteMenuRemove(W_ColorPanel *panel)
3317 W_Screen *scr = WMWidgetScreen(panel->win);
3318 char *text;
3319 char *tmp;
3320 int choice;
3321 int item;
3323 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3325 tmp = wstrappend( "This will permanently remove the palette ",
3326 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3327 text = wstrappend( tmp,
3328 ".\n\nAre you sure you want to remove this palette ?");
3329 wfree(tmp);
3331 choice = WMRunAlertPanel(scr, panel->win, "Remove", text, "Yes", "No",
3332 NULL);
3333 /* returns 0 (= "Yes") or 1 (="No") */
3334 wfree(text);
3336 if (choice == 0) {
3338 tmp = wstrappend(panel->configurationPath,
3339 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3341 if ( remove(tmp) == 0) {
3342 /* item-1 always exists */
3343 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3344 item-1);
3346 customPaletteHistoryCallback(panel->customPaletteHistoryBtn,
3347 panel);
3348 customSetPalette(panel);
3350 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3352 } else
3353 wsyserror("Couldn't remove palette %s\n", tmp);
3355 wfree(tmp);
3360 static void
3361 customPaletteHistoryCallback(WMWidget *w, void *data)
3363 W_ColorPanel *panel = (W_ColorPanel*)data;
3364 W_Screen *scr = WMWidgetScreen(panel->win);
3365 int item;
3366 char *filename;
3367 RImage *tmp = NULL;
3368 unsigned char perm_mask;
3370 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3371 if (item == panel->currentPalette)
3372 return;
3374 if (item == 0) {
3375 customRenderSpectrum(panel);
3377 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3378 False );
3379 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3380 False );
3381 } else {
3382 /* Load file from configpath */
3383 filename = wstrappend( panel->configurationPath,
3384 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3386 /* If the file corresponding to the item does not exist,
3387 * remove it from the history list and select the next one.
3389 perm_mask = (access(filename, F_OK) == 0);
3390 if (!perm_mask) {
3391 /* File does not exist */
3392 wfree(filename);
3393 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3394 item-1);
3395 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3396 customPaletteHistoryCallback(w, data);
3397 return;
3400 /* Get the image */
3401 tmp = RLoadImage(scr->rcontext, filename, 0);
3402 if (tmp) {
3403 if (panel->customPaletteImg) {
3404 RDestroyImage(panel->customPaletteImg);
3405 panel->customPaletteImg = NULL;
3407 panel->customPaletteImg = tmp;
3410 /* If the image is not writable, don't allow removing/renaming */
3411 perm_mask = (access(filename, W_OK) == 0);
3412 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3413 perm_mask);
3414 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3415 perm_mask);
3417 wfree(filename);
3419 customSetPalette(panel);
3421 panel->currentPalette = item;
3424 /************************* ColorList Panel Functions **********************/
3426 static void
3427 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3428 int state, WMRect *rect)
3430 int width, height, x, y;
3431 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3432 WMScreen *scr = WMWidgetScreen(lPtr);
3433 Display *dpy = WMScreenDisplay(scr);
3434 W_ColorPanel *panel = WMGetHangedData(lPtr);
3435 WMColor *white = WMWhiteColor(scr);
3436 WMColor *black = WMBlackColor(scr);
3437 WMColor *fillColor;
3439 width = rect->size.width;
3440 height = rect->size.height;
3441 x = rect->pos.x;
3442 y = rect->pos.y;
3444 if (state & WLDSSelected)
3445 WMPaintColorSwatch(white, d, x +15, y, width -15, height);
3446 else
3447 XClearArea(dpy, d, x +15, y, width -15, height, False);
3449 fillColor = WMCreateRGBColor(scr, color.red*256, color.green*256,
3450 color.blue*256, False);
3452 WMSetColorInGC(fillColor, WMColorGC(fillColor));
3453 WMPaintColorSwatch(fillColor, d, x, y, 15, 15);
3454 WMReleaseColor(fillColor);
3456 WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
3457 strlen(text));
3459 WMReleaseColor(white);
3460 WMReleaseColor(black);
3464 static void
3465 colorListSelect(WMWidget *w, void *data)
3467 W_ColorPanel *panel = (W_ColorPanel *)data;
3468 CPColor cpColor;
3470 cpColor.rgb = *((RColor *)WMGetListSelectedItem(w)->clientData);
3471 cpColor.set = cpRGB;
3473 panel->lastChanged = WMColorListModeColorPanel;
3474 updateSwatch(panel, cpColor);
3478 static void
3479 colorListColorMenuCallback(WMWidget *w, void *data)
3481 W_ColorPanel *panel = (W_ColorPanel *)data;
3482 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3484 switch (item) {
3485 case CLmenuAdd:
3486 break;
3487 case CLmenuRename:
3488 break;
3489 case CLmenuRemove:
3490 break;
3495 static void
3496 colorListListMenuCallback(WMWidget *w, void *data)
3498 W_ColorPanel *panel = (W_ColorPanel *)data;
3499 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3501 switch (item) {
3502 case CLmenuAdd:
3503 /* New Color List */
3504 colorListListMenuNew(panel);
3505 break;
3506 case CLmenuRename:
3507 break;
3508 case CLmenuRemove:
3509 break;
3514 static void
3515 colorListListMenuNew(W_ColorPanel *panel)
3521 /*************** Panel Initialisation Functions *****************/
3523 static void
3524 wheelInit(W_ColorPanel *panel)
3526 if (panel->color.set != cpHSV)
3527 convertCPColor(&panel->color);
3529 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3530 wheelUpdateBrightnessGradient(panel, panel->color);
3532 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3533 (1 + ( panel->color.hsv.saturation/255.0) *
3534 cos( panel->color.hsv.hue * M_PI/180.0)));
3535 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3536 (1 + ( panel->color.hsv.saturation/255.0) *
3537 sin(- panel->color.hsv.hue*M_PI/180.0)));
3539 wheelCalculateValues(panel, panel->color.hsv.value);
3543 static void
3544 grayInit(W_ColorPanel *panel)
3546 int value;
3547 char tmp[4];
3549 if (panel->color.set != cpHSV)
3550 convertCPColor(&panel->color);
3552 value = rint(panel->color.hsv.value/2.55);
3553 WMSetSliderValue(panel->grayBrightnessS, value);
3555 sprintf(tmp, "%d", value);
3556 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3560 static void
3561 rgbInit(W_ColorPanel *panel)
3563 char tmp[4];
3565 if (panel->color.set != cpRGB)
3566 convertCPColor(&panel->color);
3568 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3569 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3570 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3572 sprintf(tmp, "%d", panel->color.rgb.red);
3573 WMSetTextFieldText(panel->rgbRedT, tmp);
3574 sprintf(tmp, "%d", panel->color.rgb.green);
3575 WMSetTextFieldText(panel->rgbGreenT, tmp);
3576 sprintf(tmp, "%d", panel->color.rgb.blue);
3577 WMSetTextFieldText(panel->rgbBlueT, tmp);
3581 static void
3582 cmykInit(W_ColorPanel *panel)
3584 int value[3];
3585 char tmp[4];
3587 if (panel->color.set != cpRGB)
3588 convertCPColor(&panel->color);
3590 value[0] = rint((255-panel->color.rgb.red)/2.55);
3591 value[1] = rint((255-panel->color.rgb.green)/2.55);
3592 value[2] = rint((255-panel->color.rgb.blue)/2.55);
3594 WMSetSliderValue(panel->cmykCyanS, value[0]);
3595 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3596 WMSetSliderValue(panel->cmykYellowS, value[2]);
3597 WMSetSliderValue(panel->cmykBlackS, 0);
3599 sprintf(tmp, "%d", value[0]);
3600 WMSetTextFieldText(panel->cmykCyanT, tmp);
3601 sprintf(tmp, "%d", value[1]);
3602 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3603 sprintf(tmp, "%d", value[2]);
3604 WMSetTextFieldText(panel->cmykYellowT, tmp);
3605 WMSetTextFieldText(panel->cmykBlackT, "0");
3609 static void
3610 hsbInit(W_ColorPanel *panel)
3612 int value[3];
3613 char tmp[4];
3615 if (panel->color.set != cpHSV)
3616 convertCPColor(&panel->color);
3618 value[0] = panel->color.hsv.hue;
3619 value[1] = rint(panel->color.hsv.saturation/2.55);
3620 value[2] = rint(panel->color.hsv.value/2.55);
3622 WMSetSliderValue(panel->hsbHueS,value[0]);
3623 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3624 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3626 sprintf(tmp, "%d", value[0]);
3627 WMSetTextFieldText(panel->hsbHueT, tmp);
3628 sprintf(tmp, "%d", value[1]);
3629 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3630 sprintf(tmp, "%d", value[2]);
3631 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3633 hsbUpdateBrightnessGradient(panel);
3634 hsbUpdateSaturationGradient(panel);
3635 hsbUpdateHueGradient(panel);
3640 /************************** Common utility functions ************************/
3642 static int
3643 fetchFile(char *toPath, char *srcFile, char *destFile)
3645 int src, dest;
3646 int n;
3647 char *tmp;
3648 char buf[BUFSIZE];
3650 if ((src = open(srcFile, O_RDONLY)) == 0) {
3651 wsyserror("Could not open %s", srcFile);
3652 return -1;
3655 tmp = wstrappend(toPath, destFile);
3656 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3657 == 0) {
3658 wsyserror("Could not create %s", tmp);
3659 wfree(tmp);
3660 return -1;
3662 wfree(tmp);
3665 /* Copy the file */
3666 while ((n = read(src, buf, BUFSIZE)) > 0)
3668 if (write (dest, buf, n) != n) {
3669 wsyserror("Write error on file %s", destFile);
3670 return -1;
3674 return 0;
3678 char*
3679 generateNewFilename(char *curName)
3681 int n;
3682 char c;
3683 int baseLen;
3684 char *ptr;
3685 char *newName;
3688 assert(curName);
3690 ptr = curName;
3692 if (
3693 ((ptr = strrchr(ptr, '{')) == 0) ||
3694 sscanf(ptr, "{%i}%c", &n, &c) != 1
3696 return wstrappend(curName, " {1}");
3698 baseLen = ptr - curName -1;
3700 newName = wmalloc(baseLen + 16);
3701 strncpy(newName, curName, baseLen);
3702 newName[baseLen] = 0;
3704 sprintf(&newName[baseLen], " {%i}", n+1);
3706 return newName;
3710 void
3711 convertCPColor(CPColor *color)
3713 unsigned short old_hue = 0;
3715 switch (color->set) {
3716 case cpNone:
3717 wwarning("Color Panel: Color unspecified");
3718 return;
3719 case cpRGB:
3720 old_hue = color->hsv.hue;
3721 RRGBtoHSV(&(color->rgb), &(color->hsv));
3723 /* In black the hue is undefined, and may change by conversion
3724 * Same for white. */
3725 if (
3726 ((color->rgb.red == 0) &&
3727 (color->rgb.green == 0) &&
3728 (color->rgb.blue == 0)) ||
3729 ((color->rgb.red == 0) &&
3730 (color->rgb.green == 0) &&
3731 (color->rgb.blue == 255))
3733 color->hsv.hue = old_hue;
3734 break;
3735 case cpHSV:
3736 RHSVtoRGB(&(color->hsv), &(color->rgb));
3737 break;
3742 #define ABS_SHIFT(val, shift) \
3743 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3745 RColor
3746 ulongToRColor(WMScreen *scr, unsigned long value)
3748 RColor color;
3749 XColor *xcolor = NULL;
3751 if (!(xcolor = wmalloc(sizeof(XColor)) )) {
3752 wwarning(NO_MEMORY_ERR);
3753 color.red = 0;
3754 color.green = 0;
3755 color.blue = 0;
3756 return color;
3759 xcolor->pixel = value;
3760 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3762 color.red = xcolor->red >> 8;
3763 color.green = xcolor->green >> 8;
3764 color.blue = xcolor->blue >> 8;
3766 free(xcolor);
3768 return color;
3772 unsigned char
3773 getShift(unsigned char value)
3775 unsigned char i = -1;
3777 if (value == 0)
3778 return 0;
3780 while (value) {
3781 value >>= 1;
3782 i++;
3785 return i;
3790 #ifdef SHAPE_WAS_DEFINED
3791 #undef SHAPE_WAS_DEFINED
3792 #define SHAPE
3793 #endif