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