Some fixes from Alban
[wmaker-crm.git] / WINGs / wcolorpanel.c
blobfabb0e79264c12c01e1df3ab01ef9415d6e3a72a
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 double 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, CLmenuAdd, 0);
1098 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1099 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1101 WMRealizeWidget(panel->win);
1102 WMMapSubwidgets(panel->win);
1104 WMMapSubwidgets(panel->wheelFrm);
1105 WMMapSubwidgets(panel->slidersFrm);
1106 WMMapSubwidgets(panel->grayFrm);
1107 WMMapSubwidgets(panel->rgbFrm);
1108 WMMapSubwidgets(panel->cmykFrm);
1109 WMMapSubwidgets(panel->hsbFrm);
1110 WMMapSubwidgets(panel->customPaletteFrm);
1111 WMMapSubwidgets(panel->customPaletteContentFrm);
1112 WMMapSubwidgets(panel->colorListFrm);
1114 /* Pixmap to indicate selection positions
1115 * wheelframe MUST be mapped.
1117 panel->selectionImg = XCreatePixmap(scrPtr->display,
1118 WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1119 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1120 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1122 readConfiguration(panel);
1123 readXColors(panel);
1125 return panel;
1129 WMColorPanel*
1130 WMGetColorPanel(WMScreen *scrPtr)
1132 WMColorPanel *panel;
1134 if (scrPtr->sharedColorPanel)
1135 return scrPtr->sharedColorPanel;
1137 panel = makeColorPanel(scrPtr, "colorPanel");
1139 scrPtr->sharedColorPanel = panel;
1141 return panel;
1145 void
1146 WMFreeColorPanel(WMColorPanel *panel)
1148 W_Screen *scr = WMWidgetScreen(panel->win);
1150 if (panel == scr->sharedColorPanel) {
1151 scr->sharedColorPanel = NULL;
1154 if (!panel)
1155 return;
1157 WMRemoveNotificationObserver(panel);
1158 WMUnmapWidget(panel->win);
1160 /* fonts */
1161 WMReleaseFont(panel->font8);
1162 WMReleaseFont(panel->font12);
1164 /* pixmaps */
1165 wheelDestroyMatrix(panel->wheelMtrx);
1166 if (panel->wheelImg)
1167 XFreePixmap(scr->display, panel->wheelImg);
1168 if (panel->selectionImg)
1169 XFreePixmap(scr->display, panel->selectionImg);
1170 if (panel->selectionBackImg)
1171 XFreePixmap(scr->display, panel->selectionBackImg);
1172 RDestroyImage(panel->customPaletteImg);
1174 /* structs */
1175 if (panel->lastBrowseDir)
1176 wfree(panel->lastBrowseDir);
1177 if (panel->configurationPath)
1178 wfree(panel->configurationPath);
1180 WMDestroyWidget(panel->win);
1182 wfree(panel);
1186 void
1187 WMCloseColorPanel(WMColorPanel *panel)
1189 WMFreeColorPanel(panel);
1193 void
1194 WMShowColorPanel(WMColorPanel *panel)
1196 WMScreen *scr = WMWidgetScreen(panel->win);
1197 WMColor *white = WMWhiteColor(scr);
1199 if (panel->color.set == cpNone)
1200 WMSetColorPanelColor(panel, white);
1201 WMReleaseColor(white);
1203 if (panel->mode != WMWheelModeColorPanel)
1204 WMPerformButtonClick(panel->wheelBtn);
1206 WMMapWidget(panel->win);
1210 static void
1211 closeWindowCallback(WMWidget *w, void *data)
1213 W_ColorPanel *panel = (W_ColorPanel*)data;
1215 WMCloseColorPanel(panel);
1219 static void
1220 readConfiguration(W_ColorPanel *panel)
1222 /* XXX Doesn't take care of "invalid" files */
1224 DIR *dPtr;
1225 struct dirent *dp;
1226 struct stat stat_buf;
1227 int item;
1229 if (stat(panel->configurationPath, &stat_buf)!=0) {
1230 if (mkdir(panel->configurationPath,
1231 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1232 wsyserror("Color Panel: Could not create directory %s needed"
1233 " to store configurations", panel->configurationPath);
1234 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1235 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1236 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1237 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1238 "File Error",
1239 "Could not create ColorPanel configuration directory",
1240 "OK", NULL, NULL);
1242 return;
1245 if (!(dPtr = opendir(panel->configurationPath))) {
1246 wwarning(NO_FILE_ERR, "%s", panel->configurationPath);
1247 return;
1250 while ((dp = readdir(dPtr)) != NULL) {
1251 unsigned int perm_mask;
1252 char *path = wstrappend(panel->configurationPath,
1253 dp->d_name);
1255 if (dp->d_name[0] != '.') {
1256 item = WMGetPopUpButtonNumberOfItems(
1257 panel->customPaletteHistoryBtn);
1258 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1260 perm_mask = (access(path, R_OK) == 0);
1261 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn,
1262 item, perm_mask);
1264 free(path);
1266 (void)closedir(dPtr);
1270 static void
1271 readXColors(W_ColorPanel *panel)
1273 struct stat stat_buf;
1274 FILE *rgbtxt;
1275 char line[MAX_LENGTH];
1276 int red, green, blue;
1277 char name[48];
1278 RColor *color;
1279 WMListItem *item;
1281 if (stat(RGBTXT, &stat_buf) != 0) {
1282 wsyserror(NO_FILE_ERR, " %s", RGBTXT);
1283 return;
1285 else {
1286 if ((rgbtxt = fopen(RGBTXT, "r"))) {
1287 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1288 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1289 color = wmalloc(sizeof(RColor));
1290 color->red = (unsigned char)red;
1291 color->green = (unsigned char)green;
1292 color->blue = (unsigned char)blue;
1293 item = WMAddListItem(panel->colorListContentLst, name);
1294 item->clientData = (void *)color;
1297 fclose(rgbtxt);
1299 else {
1300 wsyserror(NO_FILE_ERR, "%s", RGBTXT);
1306 void
1307 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1309 W_Screen *scr = WMWidgetScreen(panel->win);
1311 if (mode != WMWheelModeColorPanel) {
1312 WMUnmapWidget(panel->wheelFrm);
1313 if (panel->selectionBackImg) {
1314 XFreePixmap(WMWidgetScreen(panel->win)->display,
1315 panel->selectionBackImg);
1316 panel->selectionBackImg = None;
1319 if (mode != WMGrayModeColorPanel)
1320 WMUnmapWidget(panel->grayFrm);
1321 if (mode != WMRGBModeColorPanel)
1322 WMUnmapWidget(panel->rgbFrm);
1323 if (mode != WMCMYKModeColorPanel)
1324 WMUnmapWidget(panel->cmykFrm);
1325 if (mode != WMHSBModeColorPanel)
1326 WMUnmapWidget(panel->hsbFrm);
1327 if (mode != WMCustomPaletteModeColorPanel) {
1328 WMUnmapWidget(panel->customPaletteFrm);
1329 if (panel->selectionBackImg) {
1330 XFreePixmap(WMWidgetScreen(panel->win)->display,
1331 panel->selectionBackImg);
1332 panel->selectionBackImg = None;
1335 if (mode != WMColorListModeColorPanel)
1336 WMUnmapWidget(panel->colorListFrm);
1337 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1338 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1339 WMUnmapWidget(panel->slidersFrm);
1340 else
1341 panel->slidersmode = mode;
1343 if (mode == WMWheelModeColorPanel) {
1344 WMMapWidget(panel->wheelFrm);
1345 WMSetButtonSelected(panel->wheelBtn, True);
1346 if (panel->lastChanged != WMWheelModeColorPanel)
1347 wheelInit(panel);
1348 wheelRender(panel);
1349 wheelPaint(panel);
1350 } else if (mode == WMGrayModeColorPanel) {
1351 WMMapWidget(panel->slidersFrm);
1352 WMSetButtonSelected(panel->slidersBtn, True);
1353 WMMapWidget(panel->grayFrm);
1354 WMSetButtonSelected(panel->grayBtn, True);
1355 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1356 if (panel->lastChanged != WMGrayModeColorPanel)
1357 grayInit(panel);
1358 } else if (mode == WMRGBModeColorPanel) {
1359 WMMapWidget(panel->slidersFrm);
1360 WMSetButtonSelected(panel->slidersBtn, True);
1361 WMMapWidget(panel->rgbFrm);
1362 WMSetButtonSelected(panel->rgbBtn, True);
1363 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1364 if (panel->lastChanged != WMRGBModeColorPanel)
1365 rgbInit(panel);
1366 } else if (mode == WMCMYKModeColorPanel) {
1367 WMMapWidget(panel->slidersFrm);
1368 WMSetButtonSelected(panel->slidersBtn, True);
1369 WMMapWidget(panel->cmykFrm);
1370 WMSetButtonSelected(panel->cmykBtn, True);
1371 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1372 if (panel->lastChanged != WMCMYKModeColorPanel)
1373 cmykInit(panel);
1374 } else if (mode == WMHSBModeColorPanel) {
1375 WMMapWidget(panel->slidersFrm);
1376 WMSetButtonSelected(panel->slidersBtn, True);
1377 WMMapWidget(panel->hsbFrm);
1378 WMSetButtonSelected(panel->hsbBtn, True);
1379 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1380 if (panel->lastChanged != WMHSBModeColorPanel)
1381 hsbInit(panel);
1382 } else if (mode == WMCustomPaletteModeColorPanel) {
1383 WMMapWidget(panel->customPaletteFrm);
1384 WMSetButtonSelected(panel->customPaletteBtn, True);
1385 customSetPalette(panel);
1386 } else if (mode == WMColorListModeColorPanel) {
1387 WMMapWidget(panel->colorListFrm);
1388 WMSetButtonSelected(panel->colorListBtn, True);
1391 panel->mode = mode;
1395 WMColor*
1396 WMGetColorPanelColor(WMColorPanel *panel)
1398 return WMGetColorWellColor(panel->colorWell);
1402 void
1403 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1405 WMSetColorWellColor(panel->colorWell, color);
1407 panel->color.rgb.red = color->color.red >> 8;
1408 panel->color.rgb.green = color->color.green >> 8;
1409 panel->color.rgb.blue = color->color.blue >> 8;
1410 panel->color.set = cpRGB;
1412 if (panel->mode == panel->lastChanged)
1413 panel->lastChanged = 0;
1415 WMSetColorPanelPickerMode(panel, panel->mode);
1419 static void
1420 updateSwatch(WMColorPanel *panel, CPColor color)
1422 WMScreen *scr = WMWidgetScreen(panel->win);
1423 WMColor *wellcolor;
1425 if (color.set != cpRGB)
1426 convertCPColor(&color);
1428 panel->color = color;
1430 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8,
1431 color.rgb.green << 8,
1432 color.rgb.blue << 8, True);
1434 WMSetColorWellColor(panel->colorWell, wellcolor);
1435 WMReleaseColor(wellcolor);
1437 if (!panel->flags.dragging || panel->flags.continuous) {
1438 if (panel->action)
1439 (*panel->action)(panel, panel->clientData);
1441 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1442 NULL);
1446 static void
1447 modeButtonCallback(WMWidget *w, void *data)
1449 W_ColorPanel *panel = (W_ColorPanel*)(data);
1451 if (w == panel->wheelBtn)
1452 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1453 else if (w == panel->slidersBtn)
1454 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1455 else if (w == panel->customPaletteBtn)
1456 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1457 else if (w == panel->colorListBtn)
1458 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1459 else if (w == panel->grayBtn)
1460 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1461 else if (w == panel->rgbBtn)
1462 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1463 else if (w == panel->cmykBtn)
1464 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1465 else if (w == panel->hsbBtn)
1466 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1470 /****************** Magnifying Cursor Functions *******************/
1472 static XImage*
1473 magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
1475 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1476 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1477 displayHeight = DisplayHeight(scr->display, scr->screen);
1479 if (!(image && image->data)) {
1480 /* The image in panel->magnifyGlass->image does not exist yet.
1481 * Grab one from the screen (not beyond) and use it from now on.
1483 if (!(image = XGetImage(scr->display, scr->rootWin,
1484 x - Cursor_x_hot,
1485 y - Cursor_y_hot,
1486 w, h, AllPlanes, ZPixmap)))
1487 wwarning(X_ERR);
1489 return image;
1492 /* Coordinate correction for back pixmap
1493 * if magnifying glass is at screen-borders
1496 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1497 * Hatched area is beyond screen border.
1499 * |<-Cursor_x_hot->|
1500 * ________________|_____
1501 * |/ / / / / / /| | |
1502 * | / / / / / / |(x,y) |
1503 * |/_/_/_/_/_/_/|________|
1504 * |<----x0----->|<--w0-->|
1508 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1509 * screen borders
1510 * Hatched area is beyond screen border
1512 * |<-Cursor_x_hot->|
1513 * ________________|_______________
1514 * | | | / / / / / /|
1515 * | (x,y)|/ / / / / / |
1516 * |___________________|_/_/_/_/_/_/|
1517 * |<-------w0-------->| |
1518 * |<---------------w--|----------->|
1519 * | |
1520 * x0 Displaywidth-1
1523 if (x < Cursor_x_hot) { /* see fig. 1 */
1524 x0 = Cursor_x_hot - x;
1525 w0 = w - x0;
1528 if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1529 w0 = (displayWidth) - (x - Cursor_x_hot);
1532 if (y < Cursor_y_hot) { /* see fig. 1 */
1533 y0 = Cursor_y_hot - y;
1534 h0 = h - y0;
1537 if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1538 h0 = (displayHeight) - (y - Cursor_y_hot);
1540 /* end of coordinate correction */
1543 /* Grab an image from the screen, clipped if necessary,
1544 * and put it in the existing panel->magnifyGlass->image
1545 * with the corresponding clipping offset.
1547 if (!XGetSubImage(scr->display, scr->rootWin,
1548 x - Cursor_x_hot + x0,
1549 y - Cursor_y_hot + y0,
1550 w0, h0, AllPlanes, ZPixmap,
1551 image, x0, y0))
1552 wwarning(X_ERR);
1554 return NULL;
1558 static void
1559 magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1561 /* (x1, y1) = topleft corner of existing rectangle
1562 * (x2, y2) = topleft corner of new position
1565 W_Screen *scr = WMWidgetScreen(panel->win);
1566 int xa = 0, ya = 0, xb = 0, yb = 0;
1567 int width, height;
1568 const int dx = abs(x2 - x1),
1569 dy = abs(y2 - y1);
1570 XImage *image;
1571 const int x_min = Cursor_x_hot,
1572 y_min = Cursor_y_hot,
1573 x_max = DisplayWidth(scr->display, scr->screen) -1 -
1574 (Cursor_mask_width - Cursor_x_hot),
1575 y_max = DisplayHeight(scr->display, scr->screen) -1 -
1576 (Cursor_mask_height - Cursor_y_hot);
1578 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1579 return; /* No movement */
1581 if (x1 < x2)
1582 xa = dx;
1583 else
1584 xb = dx;
1586 if (y1 < y2)
1587 ya = dy;
1588 else
1589 yb = dy;
1591 width = Cursor_mask_width - dx;
1592 height = Cursor_mask_height - dy;
1594 /* If the traversed distance is larger than the size of the magnifying
1595 * glass contents, there is no need to do dirty rectangles. A whole new
1596 * rectangle can be grabbed (unless that rectangle falls partially
1597 * off screen).
1598 * Destroying the image and setting it to NULL will achieve that later on.
1600 * Of course, grabbing an XImage beyond the borders of the screen will
1601 * cause trouble, this is considdered a special case. Part of the screen
1602 * is grabbed, but there is no need for dirty rectangles.
1604 if ((width <= 0) || (height <= 0)) {
1605 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1606 if (panel->magnifyGlass->image)
1607 XDestroyImage(panel->magnifyGlass->image);
1608 panel->magnifyGlass->image = NULL;
1610 } else {
1611 if (panel->magnifyGlass->image) {
1612 /* Get dirty rectangle from panel->magnifyGlass->image */
1613 panel->magnifyGlass->dirtyRect =
1614 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1615 if (!panel->magnifyGlass->dirtyRect) {
1616 wwarning(X_ERR);
1617 return; /* X returned a NULL from XSubImage */
1622 /* Get image from screen */
1623 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
1624 Cursor_mask_width, Cursor_mask_height);
1625 if (image) { /* Only reassign if a *new* image was grabbed */
1626 panel->magnifyGlass->image = image;
1627 return;
1630 /* Copy previously stored rectangle on covered part of image */
1631 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1632 int old_height;
1634 /* "width" and "height" are used as coordinates here,
1635 * and run from [0...width-1] and [0...height-1] respectively.
1637 width--;
1638 height--;
1639 old_height = height;
1641 for (; width >= 0; width--)
1642 for (height = old_height; height >= 0; height--)
1643 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1644 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1645 XDestroyImage(panel->magnifyGlass->dirtyRect);
1646 panel->magnifyGlass->dirtyRect = NULL;
1649 return;
1653 static Pixmap
1654 magnifyCreatePixmap(WMColorPanel *panel)
1656 W_Screen *scr = WMWidgetScreen(panel->win);
1657 int u, v;
1658 #ifndef SHAPE
1659 Pixmap pixmap;
1660 #endif
1661 unsigned long color;
1663 if (!panel->magnifyGlass->image)
1664 return None;
1666 if (!panel->magnifyGlass->magPix)
1667 return None;
1670 * Copy an area of only 5x5 pixels from the center of the image.
1672 for (u = 0; u < 5; u++) {
1673 for (v = 0; v < 5; v++) {
1674 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1676 XSetForeground(scr->display, scr->copyGC, color);
1678 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1679 panel->magnifyGlass->color = ulongToRColor(scr, color);
1681 /* The center square must eventually be centered around the
1682 * hotspot. The image needs shifting to achieve this. The amount of
1683 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1684 * _ _ _ _ _
1685 * |_|_|_|_|_|
1686 * ^------- center of center square == Cursor_x_hot
1688 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1689 scr->copyGC,
1690 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1691 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1695 #ifdef SHAPE
1696 return panel->magnifyGlass->magPix;
1697 #else
1698 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1699 Cursor_mask_height, scr->depth);
1700 if (!pixmap)
1701 return None;
1703 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1704 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1706 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1707 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1708 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1709 /* (2,2) puts center pixel on center of glass */
1711 return pixmap;
1712 #endif
1717 static WMView*
1718 magnifyCreateView(W_ColorPanel *panel)
1720 W_Screen *scr = WMWidgetScreen(panel->win);
1721 WMView *magView;
1723 magView = W_CreateTopView(scr);
1724 if (!magView)
1725 return NULL;
1727 magView->self = panel->win;
1728 magView->flags.topLevel = 1;
1729 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1730 magView->attribs.override_redirect = True;
1731 magView->attribs.save_under = True;
1733 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1735 W_RealizeView(magView);
1737 return magView;
1741 static Cursor
1742 magnifyGrabPointer(W_ColorPanel *panel)
1744 W_Screen *scr = WMWidgetScreen(panel->win);
1745 Pixmap magPixmap, magPixmap2;
1746 Cursor magCursor;
1747 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1748 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1750 /* Cursor creation stuff */
1751 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1752 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1753 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1754 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1756 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1757 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1759 XFreePixmap(scr->display, magPixmap);
1760 XFreePixmap(scr->display, magPixmap2);
1762 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1764 /* Set up Pointer */
1765 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1766 PointerMotionMask | ButtonPressMask,
1767 GrabModeAsync, GrabModeAsync,
1768 scr->rootWin, magCursor, CurrentTime);
1770 return magCursor;
1774 static WMPoint
1775 magnifyInitialize(W_ColorPanel *panel)
1777 W_Screen *scr = WMWidgetScreen(panel->win);
1778 int x, y, u, v;
1779 unsigned int mask;
1780 Pixmap pixmap, clip_mask;
1781 WMPoint point;
1782 Window root_return, child_return;
1784 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1785 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1786 1, 0, 1);
1787 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1788 5*5 -1, 5*5 -1, scr->depth);
1790 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
1791 &x, &y, &u, &v, &mask);
1793 panel->magnifyGlass->image = NULL;
1795 /* Clipmask to make magnified view-contents circular */
1796 #ifdef SHAPE
1797 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1798 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1799 #else
1800 /* Clip circle in glass cursor */
1801 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1802 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1803 #endif
1805 XFreePixmap(scr->display, clip_mask);
1807 /* Draw initial magnifying glass contents */
1808 magnifyGetImageStored(panel, x, y, x, y);
1810 pixmap = magnifyCreatePixmap(panel);
1811 XSetWindowBackgroundPixmap(scr->display,
1812 WMViewXID(panel->magnifyGlass->view),
1813 pixmap);
1814 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1815 XFlush(scr->display);
1817 #ifndef SHAPE
1818 XFreePixmap(scr->display, pixmap);
1819 #endif
1821 point.x = x;
1822 point.y = y;
1824 return point;
1828 static void
1829 magnifyPutCursor(WMWidget *w, void *data)
1831 W_ColorPanel *panel = (W_ColorPanel*)(data);
1832 W_Screen *scr = WMWidgetScreen(panel->win);
1833 Cursor magCursor;
1834 Pixmap pixmap;
1835 XEvent event;
1836 WMPoint initialPosition;
1838 /* Destroy wheelBackImg, so it'll update properly */
1839 if (panel->selectionBackImg) {
1840 XFreePixmap(WMWidgetScreen(panel->win)->display,
1841 panel->selectionBackImg);
1842 panel->selectionBackImg = None;
1845 /* Create magnifying glass */
1846 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1847 panel->magnifyGlass->view = magnifyCreateView(panel);
1848 if (!panel->magnifyGlass->view)
1849 return;
1851 initialPosition = magnifyInitialize(panel);
1852 panel->magnifyGlass->x = initialPosition.x;
1853 panel->magnifyGlass->y = initialPosition.y;
1855 W_MoveView(panel->magnifyGlass->view,
1856 panel->magnifyGlass->x - Cursor_x_hot,
1857 panel->magnifyGlass->y - Cursor_y_hot);
1858 W_MapView(panel->magnifyGlass->view);
1860 magCursor = magnifyGrabPointer(panel);
1862 while (panel->magnifyGlass->image)
1864 WMNextEvent(scr->display, &event);
1866 /* Pack motion events */
1867 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1870 switch (event.type)
1872 case ButtonPress:
1873 XDestroyImage(panel->magnifyGlass->image);
1874 panel->magnifyGlass->image = NULL;
1876 if (event.xbutton.button == Button1) {
1877 panel->color.rgb = panel->magnifyGlass->color;
1878 panel->color.set = cpRGB;
1879 updateSwatch(panel, panel->color);
1881 switch (panel->mode) {
1882 case WMWheelModeColorPanel:
1883 wheelInit(panel);
1884 wheelRender(panel);
1885 wheelPaint(panel);
1886 break;
1887 case WMGrayModeColorPanel:
1888 grayInit(panel);
1889 break;
1890 case WMRGBModeColorPanel:
1891 rgbInit(panel);
1892 break;
1893 case WMCMYKModeColorPanel:
1894 cmykInit(panel);
1895 break;
1896 case WMHSBModeColorPanel:
1897 hsbInit(panel);
1898 break;
1899 default:
1900 break;
1902 panel->lastChanged = panel->mode;
1904 WMSetButtonSelected(panel->magnifyBtn, False);
1905 break;
1907 case MotionNotify:
1908 while (XPending(event.xmotion.display)) {
1909 XEvent ev;
1910 XPeekEvent(event.xmotion.display, &ev);
1911 if (ev.type == MotionNotify)
1912 XNextEvent(event.xmotion.display, &event);
1913 else
1914 break;
1917 /* Get a "dirty rectangle" */
1918 magnifyGetImageStored( panel,
1919 panel->magnifyGlass->x, panel->magnifyGlass->y,
1920 event.xmotion.x_root, event.xmotion.y_root);
1922 /* Update coordinates */
1923 panel->magnifyGlass->x = event.xmotion.x_root;
1924 panel->magnifyGlass->y = event.xmotion.y_root;
1926 /* Move view */
1927 W_MoveView(panel->magnifyGlass->view,
1928 panel->magnifyGlass->x - Cursor_x_hot,
1929 panel->magnifyGlass->y - Cursor_y_hot);
1931 /* Put new image (with magn.) in view */
1932 pixmap = magnifyCreatePixmap(panel);
1933 if (pixmap != None) {
1934 /* Change the window background */
1935 XSetWindowBackgroundPixmap(scr->display,
1936 WMViewXID(panel->magnifyGlass->view), pixmap);
1937 /* Force an Expose (handled by X) */
1938 XClearWindow(scr->display,
1939 WMViewXID(panel->magnifyGlass->view));
1940 /* Synchronize the event queue, so the Expose is handled NOW */
1941 XFlush(scr->display);
1942 #ifndef SHAPE
1943 XFreePixmap(scr->display, pixmap);
1944 #endif
1946 break;
1948 /* Try XQueryPointer for this !!! It returns windows that the pointer
1949 * is over. Note: We found this solving the invisible donkey cap bug
1951 #if 0 /* As it is impossible to make this work in all cases,
1952 * we consider it confusing. Therefore we disabled it.
1954 case FocusOut: /* fall through */
1955 case FocusIn:
1957 * Color Panel window (panel->win) lost or received focus.
1958 * We need to update the pixmap in the magnifying glass.
1960 * BUG Doesn't work with focus switches between two windows
1961 * if none of them is the color panel.
1963 XUngrabPointer(scr->display, CurrentTime);
1964 W_UnmapView(panel->magnifyGlass->view);
1966 magnifyInitialize(panel);
1968 W_MapView(panel->magnifyGlass->view);
1969 XGrabPointer (scr->display, panel->magnifyGlass->view->window,
1970 True, PointerMotionMask | ButtonPressMask,
1971 GrabModeAsync, GrabModeAsync,
1972 scr->rootWin, magCursor, CurrentTime);
1973 break;
1974 #endif
1975 default:
1976 WMHandleEvent(&event);
1977 break;
1978 } /* of switch */
1981 XUngrabPointer(scr->display, CurrentTime);
1982 XFreeCursor(scr->display, magCursor);
1984 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1985 panel->magnifyGlass->magPix = None;
1987 W_UnmapView(panel->magnifyGlass->view);
1988 W_DestroyView(panel->magnifyGlass->view);
1989 panel->magnifyGlass->view = NULL;
1991 wfree(panel->magnifyGlass);
1996 /****************** ColorWheel Functions ************************/
1998 static wheelMatrix*
1999 wheelCreateMatrix(unsigned int width, unsigned int height)
2001 wheelMatrix *matrix = NULL;
2002 int i;
2004 assert((width > 0) && (height > 0));
2006 matrix = wmalloc(sizeof(wheelMatrix));
2007 memset(matrix, 0, sizeof(wheelMatrix));
2008 matrix->width = width;
2009 matrix->height = height;
2011 for (i = 0; i < 3; i++) {
2012 matrix->data[i] = wmalloc(width*height*sizeof(unsigned char));
2015 return matrix;
2019 static void
2020 wheelDestroyMatrix(wheelMatrix *matrix)
2022 int i;
2024 if (!matrix)
2025 return;
2027 for (i = 0; i < 3; i++) {
2028 if (matrix->data[i])
2029 wfree(matrix->data[i]);
2031 wfree(matrix);
2035 static void
2036 wheelInitMatrix(W_ColorPanel *panel)
2038 int i;
2039 int x,y;
2040 unsigned char *rp, *gp, *bp;
2041 CPColor cpColor;
2042 long ofs[4];
2043 int xcor, ycor;
2044 unsigned short sat;
2045 int dhue[4];
2046 const int cw_halfsize = (colorWheelSize + 4)/2,
2047 cw_sqsize = (colorWheelSize +4) * (colorWheelSize +4),
2048 uchar_shift = getShift(sizeof(unsigned char));
2050 if (!panel->wheelMtrx)
2051 return;
2053 cpColor.hsv.value = 255;
2054 cpColor.set = cpHSV;
2056 ofs[0] = -1;
2057 ofs[1] = -(colorWheelSize + 4);
2059 /* offsets are counterclockwise (in triangles).
2061 * ofs[0] ---->
2062 * _______________________________________
2063 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
2064 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
2065 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
2066 * o | | | | | | | | | | | | | | | | | | | | | [3]
2068 * <---- ofs[2]
2069 * ____
2070 * |\ /| <-- triangles
2071 * | \/ |
2072 * | /\ |
2073 * |/__\|
2076 for (y = 0; y < cw_halfsize; y++) {
2077 for (x = y; x < (colorWheelSize+4-y); x++) {
2078 /* (xcor, ycor) is (x,y) relative to center of matrix */
2079 xcor = 2 * x - 4 - colorWheelSize;
2080 ycor = 2 * y - 4 - colorWheelSize;
2082 /* RColor.saturation is unsigned char and will wrap after 255 */
2083 sat = rint(255.0 * sqrt(xcor*xcor + ycor*ycor) / colorWheelSize);
2085 cpColor.hsv.saturation = (unsigned char)sat;
2087 ofs[0]++; /* top quarter of matrix*/
2088 ofs[1] += colorWheelSize + 4; /* left quarter */
2089 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
2090 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
2092 if (sat < 256) {
2093 if (xcor != 0)
2094 dhue[0] = rint(atan((double)ycor / (double)xcor) *
2095 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
2096 else
2097 dhue[0] = 270;
2099 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
2100 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
2101 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
2102 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
2104 for (i = 0; i < 4; i++) {
2105 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2106 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2107 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2109 cpColor.hsv.hue = dhue[i];
2110 convertCPColor(&cpColor);
2112 *rp = (unsigned char)(cpColor.rgb.red);
2113 *gp = (unsigned char)(cpColor.rgb.green);
2114 *bp = (unsigned char)(cpColor.rgb.blue);
2117 else {
2118 for (i = 0; i < 4; i++) {
2119 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2120 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2121 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2123 *rp = (unsigned char)0;
2124 *gp = (unsigned char)0;
2125 *bp = (unsigned char)0;
2130 ofs[0] += 2*y+1;
2131 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
2136 static void
2137 wheelCalculateValues(W_ColorPanel *panel, int maxvalue)
2139 unsigned int i;
2140 unsigned int v;
2142 for (i = 0; i < 256; i++) {
2143 /* We divide by 128 in advance, and check whether that number divides
2144 * by 2 properly. If not, we add one to round the number correctly
2146 v = (i*maxvalue) >> 7;
2147 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2152 static void
2153 wheelRender(W_ColorPanel *panel)
2155 W_Screen *scr = WMWidgetScreen(panel->win);
2156 int x,y;
2157 RImage *image;
2158 unsigned char *ptr;
2159 RColor gray;
2160 unsigned long ofs = 0;
2161 unsigned char shift = getShift(sizeof(unsigned char));
2163 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, False);
2164 if (!image) {
2165 wwarning(NO_MEMORY_ERR);
2166 return;
2169 ptr = image->data;
2171 /* TODO Make this transparent istead of gray */
2172 gray.red = gray.blue = 0xae; gray.green = 0xaa;
2174 for (y = 0; y < colorWheelSize+4; y++) {
2175 for (x = 0; x < colorWheelSize+4; x++) {
2176 if (wheelInsideColorWheel(panel, ofs)) {
2177 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2178 panel->wheelMtrx->data[0][ofs] ]);
2179 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2180 panel->wheelMtrx->data[1][ofs] ]);
2181 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2182 panel->wheelMtrx->data[2][ofs] ]);
2184 else {
2185 *(ptr++) = (unsigned char)(gray.red);
2186 *(ptr++) = (unsigned char)(gray.green);
2187 *(ptr++) = (unsigned char)(gray.blue);
2189 ofs++;
2193 if (panel->wheelImg)
2194 XFreePixmap(scr->display, panel->wheelImg);
2196 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2197 RDestroyImage(image);
2199 /* Check if backimage exists. If it doesn't, allocate and fill it */
2200 if (!panel->selectionBackImg) {
2201 panel->selectionBackImg = XCreatePixmap(scr->display,
2202 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2203 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2204 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2205 /* -2 is hot spot correction */
2210 static Bool
2211 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2213 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2214 (panel->wheelMtrx->data[1][ofs] != 0) &&
2215 (panel->wheelMtrx->data[2][ofs] != 0));
2219 static void
2220 wheelPaint (W_ColorPanel *panel)
2222 W_Screen *scr = WMWidgetScreen(panel->win);
2224 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2225 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2227 /* Draw selection image */
2228 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2229 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2233 static void
2234 wheelHandleEvents(XEvent *event, void *data)
2236 W_ColorPanel *panel = (W_ColorPanel*)data;
2238 switch (event->type) {
2239 case Expose:
2240 if (event->xexpose.count != 0) /* TODO Improve */
2241 break;
2242 wheelPaint(panel);
2243 break;
2248 static void
2249 wheelHandleActionEvents(XEvent *event, void *data)
2251 W_ColorPanel *panel = (W_ColorPanel*)data;
2253 switch (event->type) {
2254 case ButtonPress:
2255 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2256 COLORWHEEL_PART) {
2258 panel->lastChanged = WMWheelModeColorPanel;
2259 panel->flags.dragging = 1;
2261 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2263 break;
2265 case ButtonRelease:
2266 panel->flags.dragging = 0;
2267 if (!panel->flags.continuous) {
2268 if (panel->action)
2269 (*panel->action)(panel, panel->clientData);
2271 break;
2273 case MotionNotify:
2274 if (panel->flags.dragging) {
2275 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2276 COLORWHEEL_PART) {
2277 wheelPositionSelection(panel, event->xmotion.x,
2278 event->xmotion.y);
2280 else
2281 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2282 event->xmotion.y);
2284 break;
2289 static int
2290 getPickerPart(W_ColorPanel *panel, int x, int y)
2292 int lx, ly;
2293 unsigned long ofs;
2295 lx = x;
2296 ly = y;
2298 if (panel->mode == WMWheelModeColorPanel) {
2299 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2300 (ly <= 2+colorWheelSize)) {
2302 ofs = ly*panel->wheelMtrx->width+lx;
2304 if (wheelInsideColorWheel(panel, ofs))
2305 return COLORWHEEL_PART;
2309 if (panel->mode == WMCustomPaletteModeColorPanel) {
2310 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2311 (ly < customPaletteHeight-2)) {
2312 return CUSTOMPALETTE_PART;
2316 return 0;
2320 static void
2321 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2323 int value;
2325 W_ColorPanel *panel = (W_ColorPanel*)data;
2327 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2329 wheelCalculateValues(panel, value);
2331 if (panel->color.set == cpRGB) {
2332 convertCPColor(&panel->color);
2333 panel->color.set = cpHSV;
2336 panel->color.hsv.value = value;
2338 wheelRender(panel);
2339 wheelPaint(panel);
2340 wheelUpdateSelection(panel);
2344 static void
2345 wheelUpdateSelection(W_ColorPanel *panel)
2347 W_Screen *scr = WMWidgetScreen(panel->win);
2349 updateSwatch(panel, panel->color);
2350 panel->lastChanged = WMWheelModeColorPanel;
2352 /* Redraw color selector (and make a backup of the part it will cover) */
2353 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2354 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2355 /* "-2" is correction for hotspot location */
2356 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2357 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2358 /* see above */
2362 static void
2363 wheelUndrawSelection(W_ColorPanel *panel)
2365 W_Screen *scr = WMWidgetScreen(panel->win);
2367 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2368 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2369 /* see above */
2372 static void
2373 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2375 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2377 panel->color.rgb.red = panel->wheelMtrx->values[
2378 panel->wheelMtrx->data[0][ofs] ];
2380 panel->color.rgb.green = panel->wheelMtrx->values[
2381 panel->wheelMtrx->data[1][ofs] ];
2383 panel->color.rgb.blue = panel->wheelMtrx->values[
2384 panel->wheelMtrx->data[2][ofs] ];
2385 panel->color.set = cpRGB;
2387 wheelUndrawSelection(panel);
2389 panel->colx = x;
2390 panel->coly = y;
2392 wheelUpdateSelection(panel);
2393 wheelUpdateBrightnessGradientFromLocation(panel);
2396 static void
2397 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2399 int hue;
2400 int xcor, ycor;
2401 CPColor cpColor;
2403 xcor = x * 2 - colorWheelSize - 4;
2404 ycor = y * 2 - colorWheelSize - 4;
2406 panel->color.hsv.saturation = 255;
2407 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2409 if (xcor != 0)
2410 hue = rint(atan(- (double)ycor / (double)xcor) * (180.0/M_PI));
2411 else {
2412 if (ycor < 0)
2413 hue = 90;
2414 else
2415 hue = 270;
2418 if (xcor < 0)
2419 hue += 180;
2421 if ((xcor > 0) && (ycor > 0))
2422 hue += 360;
2424 panel->color.hsv.hue = hue;
2425 panel->color.set = cpHSV;
2426 convertCPColor(&panel->color);
2428 wheelUndrawSelection(panel);
2430 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2431 cos( panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2432 /* "+2" because of "colorWheelSize + 4" */
2433 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2434 sin(- panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2436 wheelUpdateSelection(panel);
2437 cpColor = panel->color;
2438 wheelUpdateBrightnessGradient(panel, cpColor);
2441 static void
2442 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2444 CPColor from;
2445 unsigned long ofs;
2447 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2449 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2450 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2451 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2452 from.set = cpRGB;
2454 wheelUpdateBrightnessGradient(panel, from);
2457 static void
2458 wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor)
2460 RColor to;
2461 RImage *sliderImg;
2462 WMPixmap *sliderPxmp;
2464 to.red = to.green = to.blue = 0;
2466 if (topColor.set == cpHSV)
2467 convertCPColor(&topColor);
2469 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2470 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
2471 sliderImg, 0);
2472 RDestroyImage(sliderImg);
2473 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2474 WMReleasePixmap(sliderPxmp);
2477 /****************** Grayscale Panel Functions ***************/
2479 static void
2480 grayBrightnessSliderCallback(WMWidget *w, void *data)
2482 CPColor cpColor;
2483 int value;
2484 char tmp[4];
2485 W_ColorPanel *panel = (W_ColorPanel*)data;
2487 value = WMGetSliderValue(panel->grayBrightnessS);
2489 sprintf(tmp, "%d", value);
2491 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2492 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55*value);
2493 cpColor.set = cpRGB;
2495 updateSwatch(panel, cpColor);
2496 panel->lastChanged = WMGrayModeColorPanel;
2499 static void
2500 grayPresetButtonCallback(WMWidget *w, void *data)
2502 CPColor cpColor;
2503 char tmp[4];
2504 int value;
2505 int i=0;
2506 W_ColorPanel *panel = (W_ColorPanel*)data;
2508 while (i < 7) {
2509 if (w == panel->grayPresetBtn[i])
2510 break;
2511 i++;
2514 value = rint((100.0*i)/6.0);
2515 sprintf(tmp, "%d", value);
2517 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2518 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2519 rint((255.0*i)/6.0);
2520 cpColor.set = cpRGB;
2522 WMSetSliderValue(panel->grayBrightnessS, rint((100.0*i)/6.0));
2524 updateSwatch(panel, cpColor);
2525 panel->lastChanged = WMGrayModeColorPanel;
2528 static void
2529 grayBrightnessTextFieldCallback(void *observerData,
2530 WMNotification *notification)
2532 CPColor cpColor;
2533 char tmp[4];
2534 int value;
2535 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2537 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2538 if (value > 100)
2539 value = 100;
2540 if (value < 0)
2541 value = 0;
2543 sprintf(tmp, "%d", value);
2544 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2545 WMSetSliderValue(panel->grayBrightnessS, value);
2547 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
2548 rint((255.0*value)/100.0);
2549 cpColor.set = cpRGB;
2551 updateSwatch(panel, cpColor);
2552 panel->lastChanged = WMGrayModeColorPanel;
2555 /******************* RGB Panel Functions *****************/
2557 static void
2558 rgbSliderCallback(WMWidget *w, void *data)
2560 CPColor cpColor;
2561 int value[3];
2562 char tmp[4];
2563 W_ColorPanel *panel = (W_ColorPanel*)data;
2565 value[0] = WMGetSliderValue(panel->rgbRedS);
2566 value[1] = WMGetSliderValue(panel->rgbGreenS);
2567 value[2] = WMGetSliderValue(panel->rgbBlueS);
2569 sprintf(tmp, "%d", value[0]);
2570 WMSetTextFieldText(panel->rgbRedT, tmp);
2571 sprintf(tmp, "%d", value[1]);
2572 WMSetTextFieldText(panel->rgbGreenT, tmp);
2573 sprintf(tmp, "%d", value[2]);
2574 WMSetTextFieldText(panel->rgbBlueT, tmp);
2576 cpColor.rgb.red = value[0];
2577 cpColor.rgb.green = value[1];
2578 cpColor.rgb.blue = value[2];
2579 cpColor.set = cpRGB;
2581 updateSwatch(panel, cpColor);
2582 panel->lastChanged = WMRGBModeColorPanel;
2585 static void
2586 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2588 CPColor cpColor;
2589 int value[3];
2590 char tmp[4];
2591 int n;
2592 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2594 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2595 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2596 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2598 for (n=0; n < 3; n++) {
2599 if (value[n] > 255)
2600 value[n] = 255;
2601 if (value[n] < 0)
2602 value[n] = 0;
2605 sprintf(tmp, "%d", value[0]);
2606 WMSetTextFieldText(panel->rgbRedT, tmp);
2607 sprintf(tmp, "%d", value[1]);
2608 WMSetTextFieldText(panel->rgbGreenT, tmp);
2609 sprintf(tmp, "%d", value[2]);
2610 WMSetTextFieldText(panel->rgbBlueT, tmp);
2612 WMSetSliderValue(panel->rgbRedS, value[0]);
2613 WMSetSliderValue(panel->rgbGreenS, value[1]);
2614 WMSetSliderValue(panel->rgbBlueS, value[2]);
2616 cpColor.rgb.red = value[0];
2617 cpColor.rgb.green = value[1];
2618 cpColor.rgb.blue = value[2];
2619 cpColor.set = cpRGB;
2621 updateSwatch(panel, cpColor);
2622 panel->lastChanged = WMRGBModeColorPanel;
2626 /******************* CMYK Panel Functions *****************/
2628 static void
2629 cmykSliderCallback(WMWidget *w, void *data)
2631 CPColor cpColor;
2632 int value[4];
2633 char tmp[4];
2634 W_ColorPanel *panel = (W_ColorPanel*)data;
2635 double scale;
2637 value[0] = WMGetSliderValue(panel->cmykCyanS);
2638 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2639 value[2] = WMGetSliderValue(panel->cmykYellowS);
2640 value[3] = WMGetSliderValue(panel->cmykBlackS);
2642 sprintf(tmp, "%d", value[0]);
2643 WMSetTextFieldText(panel->cmykCyanT, tmp);
2644 sprintf(tmp, "%d", value[1]);
2645 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2646 sprintf(tmp, "%d", value[2]);
2647 WMSetTextFieldText(panel->cmykYellowT, tmp);
2648 sprintf(tmp, "%d", value[3]);
2649 WMSetTextFieldText(panel->cmykBlackT, tmp);
2651 scale = 2.55 * (1.0 - (value[3] / 100.0));
2652 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2653 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2654 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2655 cpColor.set = cpRGB;
2657 updateSwatch(panel, cpColor);
2658 panel->lastChanged = WMCMYKModeColorPanel;
2661 static void
2662 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2664 CPColor cpColor;
2665 int value[4];
2666 char tmp[4];
2667 int n;
2668 double scale;
2669 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2671 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2672 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2673 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2674 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2676 for (n=0; n < 4; n++) {
2677 if (value[n] > 100)
2678 value[n] = 100;
2679 if (value[n] < 0)
2680 value[n] = 0;
2683 sprintf(tmp, "%d", value[0]);
2684 WMSetTextFieldText(panel->cmykCyanT, tmp);
2686 sprintf(tmp, "%d", value[1]);
2687 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2689 sprintf(tmp, "%d", value[2]);
2690 WMSetTextFieldText(panel->cmykYellowT, tmp);
2692 sprintf(tmp, "%d", value[3]);
2693 WMSetTextFieldText(panel->cmykBlackT, tmp);
2695 WMSetSliderValue(panel->cmykCyanS, value[0]);
2696 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2697 WMSetSliderValue(panel->cmykYellowS, value[2]);
2698 WMSetSliderValue(panel->cmykBlackS, value[3]);
2700 scale = 2.55 * (1.0 - (value[3] / 100.0));
2701 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2702 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2703 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2704 cpColor.set = cpRGB;
2706 updateSwatch(panel, cpColor);
2707 panel->lastChanged = WMCMYKModeColorPanel;
2710 /********************** HSB Panel Functions ***********************/
2712 static void
2713 hsbSliderCallback(WMWidget *w, void *data)
2715 CPColor cpColor;
2716 int value[3];
2717 char tmp[4];
2718 W_ColorPanel *panel = (W_ColorPanel*)data;
2720 value[0] = WMGetSliderValue(panel->hsbHueS);
2721 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2722 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2724 sprintf(tmp, "%d", value[0]);
2725 WMSetTextFieldText(panel->hsbHueT, tmp);
2726 sprintf(tmp, "%d", value[1]);
2727 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2728 sprintf(tmp, "%d", value[2]);
2729 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2731 cpColor.hsv.hue = value[0];
2732 cpColor.hsv.saturation = value[1]*2.55;
2733 cpColor.hsv.value = value[2]*2.55;
2734 cpColor.set = cpHSV;
2736 convertCPColor(&cpColor);
2738 panel->lastChanged = WMHSBModeColorPanel;
2739 updateSwatch(panel, cpColor);
2741 if (w != panel->hsbBrightnessS)
2742 hsbUpdateBrightnessGradient(panel);
2743 if (w != panel->hsbSaturationS)
2744 hsbUpdateSaturationGradient(panel);
2745 if (w != panel->hsbHueS)
2746 hsbUpdateHueGradient(panel);
2749 static void
2750 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2752 CPColor cpColor;
2753 int value[3];
2754 char tmp[4];
2755 int n;
2756 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2758 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2759 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2760 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2762 if (value[0] > 359)
2763 value[0] = 359;
2764 if (value[0] < 0)
2765 value[0] = 0;
2767 for (n=1; n < 3; n++) {
2768 if (value[n] > 100)
2769 value[n] = 100;
2770 if (value[n] < 0)
2771 value[n] = 0;
2774 sprintf(tmp, "%d", value[0]);
2775 WMSetTextFieldText(panel->hsbHueT, tmp);
2776 sprintf(tmp, "%d", value[1]);
2777 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2778 sprintf(tmp, "%d", value[2]);
2779 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2781 WMSetSliderValue(panel->hsbHueS, value[0]);
2782 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2783 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2785 cpColor.hsv.hue = value[0];
2786 cpColor.hsv.saturation = value[1]*2.55;
2787 cpColor.hsv.value = value[2]*2.55;
2788 cpColor.set = cpHSV;
2790 convertCPColor(&cpColor);
2792 panel->lastChanged = WMHSBModeColorPanel;
2793 updateSwatch(panel, cpColor);
2795 hsbUpdateBrightnessGradient(panel);
2796 hsbUpdateSaturationGradient(panel);
2797 hsbUpdateHueGradient(panel);
2800 static void
2801 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2803 W_Screen *scr = WMWidgetScreen(panel->win);
2804 RColor from;
2805 CPColor to;
2806 RImage *sliderImg;
2807 WMPixmap *sliderPxmp;
2809 from.red = from.green = from.blue = 0;
2810 to.hsv = panel->color.hsv;
2811 to.hsv.value = 255;
2812 to.set = cpHSV;
2814 convertCPColor(&to);
2816 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2817 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2818 RDestroyImage(sliderImg);
2820 if (sliderPxmp)
2821 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2822 panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white),
2823 False, "Brightness", strlen("Brightness"));
2824 else
2825 wwarning(NO_MEMORY_ERR);
2827 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2828 WMReleasePixmap(sliderPxmp);
2831 static void
2832 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2834 W_Screen *scr = WMWidgetScreen(panel->win);
2835 CPColor from;
2836 CPColor to;
2837 RImage *sliderImg;
2838 WMPixmap *sliderPxmp;
2840 from.hsv = panel->color.hsv;
2841 from.hsv.saturation = 0;
2842 from.set = cpHSV;
2843 convertCPColor(&from);
2845 to.hsv = panel->color.hsv;
2846 to.hsv.saturation = 255;
2847 to.set = cpHSV;
2848 convertCPColor(&to);
2850 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb),
2851 RGRD_HORIZONTAL);
2852 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2853 RDestroyImage(sliderImg);
2855 if (sliderPxmp)
2856 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2857 panel->font12, 2, 0, 100, WALeft,
2858 WMColorGC(from.hsv.value < 128 ? scr->white : scr->black), False,
2859 "Saturation", strlen("Saturation"));
2860 else
2861 wwarning(NO_MEMORY_ERR);
2863 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2864 WMReleasePixmap(sliderPxmp);
2867 static void
2868 hsbUpdateHueGradient(W_ColorPanel *panel)
2870 W_Screen *scr = WMWidgetScreen(panel->win);
2871 RColor **colors = NULL;
2872 RHSVColor hsvcolor;
2873 RImage *sliderImg;
2874 WMPixmap *sliderPxmp;
2875 int i;
2877 hsvcolor = panel->color.hsv;
2879 colors = wmalloc(sizeof(RColor*)*(8));
2880 for (i=0; i<7; i++) {
2881 hsvcolor.hue = (360*i)/6;
2882 colors[i] = wmalloc(sizeof(RColor));
2883 RHSVtoRGB(&hsvcolor, colors[i]);
2885 colors[7] = NULL;
2887 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2888 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2889 RDestroyImage(sliderImg);
2891 if (sliderPxmp)
2892 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2893 panel->font12, 2, 0, 100, WALeft,
2894 WMColorGC(hsvcolor.value < 128 ? scr->white : scr->black), False,
2895 "Hue", strlen("Hue"));
2896 else
2897 wwarning(NO_MEMORY_ERR);
2899 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2900 WMReleasePixmap(sliderPxmp);
2902 for (i=0; i<7; i++)
2903 wfree(colors[i]);
2905 wfree(colors);
2908 /*************** Custom Palette Functions ****************/
2910 static void
2911 customRenderSpectrum(W_ColorPanel *panel)
2913 RImage *spectrum;
2914 int x,y;
2915 unsigned char *ptr;
2916 CPColor cpColor;
2918 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2920 ptr = spectrum->data;
2922 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2923 cpColor.hsv.hue = y;
2924 cpColor.hsv.saturation = 0;
2925 cpColor.hsv.value = 255;
2926 cpColor.set = cpHSV;
2928 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2929 convertCPColor(&cpColor);
2931 *(ptr++) = (unsigned char)cpColor.rgb.red;
2932 *(ptr++) = (unsigned char)cpColor.rgb.green;
2933 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2935 if (x < (SPECTRUM_WIDTH/2))
2936 cpColor.hsv.saturation++;
2938 if (x > (SPECTRUM_WIDTH/2))
2939 cpColor.hsv.value--;
2942 if (panel->customPaletteImg) {
2943 RDestroyImage(panel->customPaletteImg);
2944 panel->customPaletteImg = NULL;
2946 panel->customPaletteImg = spectrum;
2951 static void
2952 customSetPalette(W_ColorPanel *panel)
2954 W_Screen *scr = WMWidgetScreen(panel->win);
2955 RImage *scaledImg;
2956 Pixmap image;
2957 int item;
2959 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2960 customPaletteHeight, scr->depth);
2961 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2962 customPaletteHeight);
2963 RConvertImage(scr->rcontext, scaledImg, &image);
2964 RDestroyImage(scaledImg);
2966 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2967 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2969 /* Check backimage exists. If it doesn't, allocate and fill it */
2970 if (!panel->selectionBackImg) {
2971 panel->selectionBackImg = XCreatePixmap(scr->display,
2972 panel->customPaletteContentView->window, 4, 4, scr->depth);
2975 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2976 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2977 XCopyArea(scr->display, panel->selectionImg,
2978 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2979 panel->palx-2, panel->paly-2);
2980 XFreePixmap(scr->display, image);
2982 panel->palXRatio = (double)(panel->customPaletteImg->width) /
2983 (double)(customPaletteWidth);
2984 panel->palYRatio = (double)(panel->customPaletteImg->height) /
2985 (double)(customPaletteHeight);
2987 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2991 static void
2992 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2994 W_Screen *scr = WMWidgetScreen(panel->win);
2995 unsigned long ofs;
2998 /* undraw selection */
2999 XCopyArea(scr->display, panel->selectionBackImg,
3000 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3001 panel->palx-2, panel->paly-2);
3003 panel->palx = x;
3004 panel->paly = y;
3006 ofs = rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
3007 panel->customPaletteImg->width * 3;
3009 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
3010 panel->color.rgb.green = panel->customPaletteImg->data[ofs+1];
3011 panel->color.rgb.blue = panel->customPaletteImg->data[ofs+2];
3012 panel->color.set = cpRGB;
3014 updateSwatch(panel, panel->color);
3015 panel->lastChanged = WMCustomPaletteModeColorPanel;
3017 /* Redraw color selector (and make a backup of the part it will cover) */
3018 XCopyArea(scr->display, panel->customPaletteContentView->window,
3019 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
3020 4, 4, 0, 0); /* "-2" is correction for hotspot location */
3021 XCopyArea(scr->display, panel->selectionImg,
3022 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3023 panel->palx-2, panel->paly-2); /* see above */
3027 static void
3028 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
3030 if (x < 2)
3031 x = 2;
3032 if (y < 2)
3033 y = 2;
3034 if (x >= customPaletteWidth)
3035 x = customPaletteWidth -2;
3036 if (y >= customPaletteHeight)
3037 y = customPaletteHeight -2;
3039 customPalettePositionSelection(panel, x, y);
3043 static void
3044 customPaletteHandleEvents(XEvent *event, void *data)
3046 W_ColorPanel *panel = (W_ColorPanel*)data;
3048 switch (event->type) {
3049 case Expose:
3050 if (event->xexpose.count != 0) /* TODO Improve. */
3051 break;
3052 customSetPalette(panel);
3053 break;
3057 static void
3058 customPaletteHandleActionEvents(XEvent *event, void *data)
3060 W_ColorPanel *panel = (W_ColorPanel*)data;
3061 int x, y;
3063 switch (event->type) {
3064 case ButtonPress:
3065 x = event->xbutton.x;
3066 y = event->xbutton.y;
3068 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3069 panel->flags.dragging = 1;
3070 customPalettePositionSelection(panel, x, y);
3072 break;
3074 case ButtonRelease:
3075 panel->flags.dragging = 0;
3076 if (!panel->flags.continuous) {
3077 if (panel->action)
3078 (*panel->action)(panel, panel->clientData);
3080 break;
3082 case MotionNotify:
3083 x = event->xmotion.x;
3084 y = event->xmotion.y;
3086 if (panel->flags.dragging) {
3087 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3088 customPalettePositionSelection(panel, x, y);
3090 else
3091 customPalettePositionSelectionOutBounds(panel, x, y);
3093 break;
3098 static void
3099 customPaletteMenuCallback(WMWidget *w, void *data)
3101 W_ColorPanel *panel = (W_ColorPanel*)data;
3102 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
3104 switch (item) {
3105 case CPmenuNewFromFile:
3106 customPaletteMenuNewFromFile(panel);
3107 break;
3108 case CPmenuRename:
3109 customPaletteMenuRename(panel);
3110 break;
3111 case CPmenuRemove:
3112 customPaletteMenuRemove(panel);
3113 break;
3114 case CPmenuCopy:
3115 break;
3116 case CPmenuNewFromClipboard:
3117 break;
3122 static void
3123 customPaletteMenuNewFromFile(W_ColorPanel *panel)
3125 W_Screen *scr = WMWidgetScreen(panel->win);
3126 WMOpenPanel *browseP;
3127 char *filepath;
3128 char *filename = NULL;
3129 char *spath;
3130 char *tmp;
3131 int i;
3132 RImage *tmpImg = NULL;
3134 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3135 spath = wexpandpath(wgethomedir());
3136 else
3137 spath = wexpandpath(panel->lastBrowseDir);
3139 browseP = WMGetOpenPanel(scr);
3140 WMSetFilePanelCanChooseDirectories(browseP, 0);
3141 WMSetFilePanelCanChooseFiles(browseP, 1);
3143 /* Get a filename */
3144 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3145 "Open Palette", RSupportedFileFormats()) ) {
3146 filepath = WMGetFilePanelFileName(browseP);
3148 /* Get seperation position between path and filename */
3149 i = strrchr(filepath, '/') - filepath + 1;
3150 if (i > strlen(filepath))
3151 i = strlen(filepath);
3153 /* Store last browsed path */
3154 if (panel->lastBrowseDir)
3155 wfree(panel->lastBrowseDir);
3156 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3157 strncpy(panel->lastBrowseDir, filepath, i);
3158 panel->lastBrowseDir[i] = '\0';
3160 /* Get filename from path */
3161 filename = wstrdup(filepath + i);
3163 /* Check for duplicate files, and rename it if there are any */
3164 tmp = wstrappend(panel->configurationPath, filename);
3165 while (access (tmp, F_OK) == 0) {
3166 char *newName;
3168 wfree(tmp);
3170 newName = generateNewFilename(filename);
3171 wfree(filename);
3172 filename = newName;
3174 tmp = wstrappend(panel->configurationPath, filename);
3176 wfree(tmp);
3178 /* Copy image to $(gnustepdir)/Library/Colors/ &
3179 * Add filename to history menu */
3180 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3182 /* filepath is a "local" path now the file has been copied */
3183 wfree(filepath);
3184 filepath = wstrappend(panel->configurationPath, filename);
3186 /* load the image & add menu entries */
3187 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3188 if (tmpImg) {
3189 if (panel->customPaletteImg)
3190 RDestroyImage(panel->customPaletteImg);
3191 panel->customPaletteImg = tmpImg;
3193 customSetPalette(panel);
3194 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3196 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3197 panel->customPaletteHistoryBtn)-1;
3199 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3200 panel->currentPalette);
3202 } else {
3203 tmp = wstrappend(panel->configurationPath, filename);
3205 i = remove(tmp); /* Delete the file, it doesn't belong here */
3206 WMRunAlertPanel(scr, panel->win, "File Error",
3207 "Invalid file format !", "OK", NULL, NULL);
3208 if (i != 0) {
3209 wsyserror("can't remove file %s", tmp);
3210 WMRunAlertPanel(scr, panel->win, "File Error",
3211 "Couldn't remove file from Configuration Directory !",
3212 "OK", NULL, NULL);
3214 wfree(tmp);
3216 wfree(filepath);
3217 wfree(filename);
3219 WMFreeFilePanel(browseP);
3221 wfree(spath);
3225 static void
3226 customPaletteMenuRename(W_ColorPanel *panel)
3228 W_Screen *scr = WMWidgetScreen(panel->win);
3229 char *toName = NULL;
3230 char *fromName;
3231 char *toPath, *fromPath;
3232 int item;
3233 int index;
3235 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3236 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3238 toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
3239 fromName, "OK", "Cancel");
3241 if (toName) {
3243 /* As some people do certain stupid things... */
3244 if (strcmp(toName, fromName) == 0) {
3245 wfree(toName);
3246 return;
3249 /* For normal people */
3250 fromPath = wstrappend(panel->configurationPath, fromName);
3251 toPath = wstrappend(panel->configurationPath, toName);
3253 if (access (toPath, F_OK) == 0) {
3254 /* Careful, this palette exists already */
3255 if (WMRunAlertPanel(scr, panel->win, "Warning",
3256 "Palette already exists !\n\nOverwrite ?", "No", "Yes",
3257 NULL) == 1) {
3258 /* "No" = 0, "Yes" = 1 */
3259 int items = WMGetPopUpButtonNumberOfItems(
3260 panel->customPaletteHistoryBtn);
3262 remove(toPath);
3264 /* Remove from History list too */
3265 index = 1;
3266 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3267 panel->customPaletteHistoryBtn, index),
3268 toName) != 0 ))
3269 index++;
3271 if (index < items) {
3272 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3273 index);
3274 if (index < item)
3275 item--;
3278 } else {
3279 wfree(fromPath);
3280 wfree(toName);
3281 wfree(toPath);
3283 return;
3287 if ( rename(fromPath, toPath) != 0)
3288 wsyserror("Couldn't rename palette %s to %s\n", fromName, toName);
3289 else {
3290 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3291 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3292 toName);
3294 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3296 wfree(fromPath);
3297 wfree(toPath);
3298 wfree(toName);
3303 static void
3304 customPaletteMenuRemove(W_ColorPanel *panel)
3306 W_Screen *scr = WMWidgetScreen(panel->win);
3307 char *text;
3308 char *tmp;
3309 int choice;
3310 int item;
3312 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3314 tmp = wstrappend( "This will permanently remove the palette ",
3315 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3316 text = wstrappend( tmp,
3317 ".\n\nAre you sure you want to remove this palette ?");
3318 wfree(tmp);
3320 choice = WMRunAlertPanel(scr, panel->win, "Remove", text, "Yes", "No",
3321 NULL);
3322 /* returns 0 (= "Yes") or 1 (="No") */
3323 wfree(text);
3325 if (choice == 0) {
3327 tmp = wstrappend(panel->configurationPath,
3328 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3330 if ( remove(tmp) == 0) {
3331 /* item-1 always exists */
3332 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3333 item-1);
3335 customPaletteHistoryCallback(panel->customPaletteHistoryBtn,
3336 panel);
3337 customSetPalette(panel);
3339 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3341 } else
3342 wsyserror("Couldn't remove palette %s\n", tmp);
3344 wfree(tmp);
3349 static void
3350 customPaletteHistoryCallback(WMWidget *w, void *data)
3352 W_ColorPanel *panel = (W_ColorPanel*)data;
3353 W_Screen *scr = WMWidgetScreen(panel->win);
3354 int item;
3355 char *filename;
3356 RImage *tmp = NULL;
3357 unsigned char perm_mask;
3359 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3360 if (item == panel->currentPalette)
3361 return;
3363 if (item == 0) {
3364 customRenderSpectrum(panel);
3366 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3367 False );
3368 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3369 False );
3370 } else {
3371 /* Load file from configpath */
3372 filename = wstrappend( panel->configurationPath,
3373 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3375 /* If the file corresponding to the item does not exist,
3376 * remove it from the history list and select the next one.
3378 perm_mask = (access(filename, F_OK) == 0);
3379 if (!perm_mask) {
3380 /* File does not exist */
3381 wfree(filename);
3382 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3383 item-1);
3384 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3385 customPaletteHistoryCallback(w, data);
3386 return;
3389 /* Get the image */
3390 tmp = RLoadImage(scr->rcontext, filename, 0);
3391 if (tmp) {
3392 if (panel->customPaletteImg) {
3393 RDestroyImage(panel->customPaletteImg);
3394 panel->customPaletteImg = NULL;
3396 panel->customPaletteImg = tmp;
3399 /* If the image is not writable, don't allow removing/renaming */
3400 perm_mask = (access(filename, W_OK) == 0);
3401 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3402 perm_mask);
3403 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3404 perm_mask);
3406 wfree(filename);
3408 customSetPalette(panel);
3410 panel->currentPalette = item;
3413 /************************* ColorList Panel Functions **********************/
3415 static void
3416 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3417 int state, WMRect *rect)
3419 int width, height, x, y;
3420 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3421 WMScreen *scr = WMWidgetScreen(lPtr);
3422 Display *dpy = WMScreenDisplay(scr);
3423 W_ColorPanel *panel = WMGetHangedData(lPtr);
3424 WMColor *white = WMWhiteColor(scr);
3425 WMColor *black = WMBlackColor(scr);
3426 WMColor *fillColor;
3428 width = rect->size.width;
3429 height = rect->size.height;
3430 x = rect->pos.x;
3431 y = rect->pos.y;
3433 if (state & WLDSSelected)
3434 WMPaintColorSwatch(white, d, x +15, y, width -15, height);
3435 else
3436 XClearArea(dpy, d, x +15, y, width -15, height, False);
3438 fillColor = WMCreateRGBColor(scr, color.red*256, color.green*256,
3439 color.blue*256, False);
3441 WMSetColorInGC(fillColor, WMColorGC(fillColor));
3442 WMPaintColorSwatch(fillColor, d, x, y, 15, 15);
3443 WMReleaseColor(fillColor);
3445 WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
3446 strlen(text));
3448 WMReleaseColor(white);
3449 WMReleaseColor(black);
3453 static void
3454 colorListSelect(WMWidget *w, void *data)
3456 W_ColorPanel *panel = (W_ColorPanel *)data;
3457 CPColor cpColor;
3459 cpColor.rgb = *((RColor *)WMGetListSelectedItem(w)->clientData);
3460 cpColor.set = cpRGB;
3462 panel->lastChanged = WMColorListModeColorPanel;
3463 updateSwatch(panel, cpColor);
3467 static void
3468 colorListColorMenuCallback(WMWidget *w, void *data)
3470 W_ColorPanel *panel = (W_ColorPanel *)data;
3471 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3473 switch (item) {
3474 case CLmenuAdd:
3475 break;
3476 case CLmenuRename:
3477 break;
3478 case CLmenuRemove:
3479 break;
3484 static void
3485 colorListListMenuCallback(WMWidget *w, void *data)
3487 W_ColorPanel *panel = (W_ColorPanel *)data;
3488 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3490 switch (item) {
3491 case CLmenuAdd:
3492 /* New Color List */
3493 colorListListMenuNew(panel);
3494 break;
3495 case CLmenuRename:
3496 break;
3497 case CLmenuRemove:
3498 break;
3503 static void
3504 colorListListMenuNew(W_ColorPanel *panel)
3510 /*************** Panel Initialisation Functions *****************/
3512 static void
3513 wheelInit(W_ColorPanel *panel)
3515 CPColor cpColor;
3517 if (panel->color.set != cpHSV)
3518 convertCPColor(&panel->color);
3520 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3522 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3523 (1 + ( panel->color.hsv.saturation/255.0) *
3524 cos( panel->color.hsv.hue * M_PI/180.0)));
3525 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3526 (1 + ( panel->color.hsv.saturation/255.0) *
3527 sin(- panel->color.hsv.hue*M_PI/180.0)));
3529 wheelCalculateValues(panel, panel->color.hsv.value);
3531 cpColor = panel->color;
3532 cpColor.hsv.value = 255;
3533 cpColor.set = cpHSV;
3534 wheelUpdateBrightnessGradient(panel, cpColor);
3538 static void
3539 grayInit(W_ColorPanel *panel)
3541 int value;
3542 char tmp[4];
3544 if (panel->color.set != cpHSV)
3545 convertCPColor(&panel->color);
3547 value = rint(panel->color.hsv.value/2.55);
3548 WMSetSliderValue(panel->grayBrightnessS, value);
3550 sprintf(tmp, "%d", value);
3551 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3555 static void
3556 rgbInit(W_ColorPanel *panel)
3558 char tmp[4];
3560 if (panel->color.set != cpRGB)
3561 convertCPColor(&panel->color);
3563 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3564 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3565 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3567 sprintf(tmp, "%d", panel->color.rgb.red);
3568 WMSetTextFieldText(panel->rgbRedT, tmp);
3569 sprintf(tmp, "%d", panel->color.rgb.green);
3570 WMSetTextFieldText(panel->rgbGreenT, tmp);
3571 sprintf(tmp, "%d", panel->color.rgb.blue);
3572 WMSetTextFieldText(panel->rgbBlueT, tmp);
3576 static void
3577 cmykInit(W_ColorPanel *panel)
3579 int value[3];
3580 char tmp[4];
3582 if (panel->color.set != cpRGB)
3583 convertCPColor(&panel->color);
3585 value[0] = rint((255-panel->color.rgb.red)/2.55);
3586 value[1] = rint((255-panel->color.rgb.green)/2.55);
3587 value[2] = rint((255-panel->color.rgb.blue)/2.55);
3589 WMSetSliderValue(panel->cmykCyanS, value[0]);
3590 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3591 WMSetSliderValue(panel->cmykYellowS, value[2]);
3592 WMSetSliderValue(panel->cmykBlackS, 0);
3594 sprintf(tmp, "%d", value[0]);
3595 WMSetTextFieldText(panel->cmykCyanT, tmp);
3596 sprintf(tmp, "%d", value[1]);
3597 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3598 sprintf(tmp, "%d", value[2]);
3599 WMSetTextFieldText(panel->cmykYellowT, tmp);
3600 WMSetTextFieldText(panel->cmykBlackT, "0");
3604 static void
3605 hsbInit(W_ColorPanel *panel)
3607 int value[3];
3608 char tmp[4];
3610 if (panel->color.set != cpHSV)
3611 convertCPColor(&panel->color);
3613 value[0] = panel->color.hsv.hue;
3614 value[1] = rint(panel->color.hsv.saturation/2.55);
3615 value[2] = rint(panel->color.hsv.value/2.55);
3617 WMSetSliderValue(panel->hsbHueS,value[0]);
3618 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3619 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3621 sprintf(tmp, "%d", value[0]);
3622 WMSetTextFieldText(panel->hsbHueT, tmp);
3623 sprintf(tmp, "%d", value[1]);
3624 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3625 sprintf(tmp, "%d", value[2]);
3626 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3628 hsbUpdateBrightnessGradient(panel);
3629 hsbUpdateSaturationGradient(panel);
3630 hsbUpdateHueGradient(panel);
3635 /************************** Common utility functions ************************/
3637 static int
3638 fetchFile(char *toPath, char *srcFile, char *destFile)
3640 int src, dest;
3641 int n;
3642 char *tmp;
3643 char buf[BUFSIZE];
3645 if ((src = open(srcFile, O_RDONLY)) == 0) {
3646 wsyserror("Could not open %s", srcFile);
3647 return -1;
3650 tmp = wstrappend(toPath, destFile);
3651 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3652 == 0) {
3653 wsyserror("Could not create %s", tmp);
3654 wfree(tmp);
3655 return -1;
3657 wfree(tmp);
3660 /* Copy the file */
3661 while ((n = read(src, buf, BUFSIZE)) > 0)
3663 if (write (dest, buf, n) != n) {
3664 wsyserror("Write error on file %s", destFile);
3665 return -1;
3669 return 0;
3673 char*
3674 generateNewFilename(char *curName)
3676 int n;
3677 char c;
3678 int baseLen;
3679 char *ptr;
3680 char *newName;
3683 assert(curName);
3685 ptr = curName;
3687 if (
3688 ((ptr = strrchr(ptr, '{')) == 0) ||
3689 sscanf(ptr, "{%i}%c", &n, &c) != 1
3691 return wstrappend(curName, " {1}");
3693 baseLen = ptr - curName -1;
3695 newName = wmalloc(baseLen + 16);
3696 strncpy(newName, curName, baseLen);
3697 newName[baseLen] = 0;
3699 sprintf(&newName[baseLen], " {%i}", n+1);
3701 return newName;
3705 void
3706 convertCPColor(CPColor *color)
3708 unsigned short old_hue = 0;
3710 switch (color->set) {
3711 case cpNone:
3712 wwarning("Color Panel: Color unspecified");
3713 return;
3714 case cpRGB:
3715 old_hue = color->hsv.hue;
3716 RRGBtoHSV(&(color->rgb), &(color->hsv));
3718 /* In black the hue is undefined, and may change by conversion
3719 * Same for white. */
3720 if (
3721 ((color->rgb.red == 0) &&
3722 (color->rgb.green == 0) &&
3723 (color->rgb.blue == 0)) ||
3724 ((color->rgb.red == 0) &&
3725 (color->rgb.green == 0) &&
3726 (color->rgb.blue == 255))
3728 color->hsv.hue = old_hue;
3729 break;
3730 case cpHSV:
3731 RHSVtoRGB(&(color->hsv), &(color->rgb));
3732 break;
3737 #define ABS_SHIFT(val, shift) \
3738 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3740 RColor
3741 ulongToRColor(WMScreen *scr, unsigned long value)
3743 RColor color;
3744 XColor *xcolor = NULL;
3746 if (!(xcolor = wmalloc(sizeof(XColor)) )) {
3747 wwarning(NO_MEMORY_ERR);
3748 color.red = 0;
3749 color.green = 0;
3750 color.blue = 0;
3751 return color;
3754 xcolor->pixel = value;
3755 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3757 color.red = xcolor->red >> 8;
3758 color.green = xcolor->green >> 8;
3759 color.blue = xcolor->blue >> 8;
3761 free(xcolor);
3763 return color;
3767 unsigned char
3768 getShift(unsigned char value)
3770 unsigned char i = -1;
3772 if (value == 0)
3773 return 0;
3775 while (value) {
3776 value >>= 1;
3777 i++;
3780 return i;
3785 #ifdef SHAPE_WAS_DEFINED
3786 #undef SHAPE_WAS_DEFINED
3787 #define SHAPE
3788 #endif