- put back wmksize(), wmkrange() and wmkpoint() as functions instead of macros
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob3d7df1db46618f420efdbf4da5ddca6e1bd1a0ba
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
18 /* TODO:
19 * - Look at further optimization of colorWheel matrix calculation.
20 * It appears to be rather symmetric in angles of 60 degrees,
21 * while it is optimized in angles of 90 degrees.
22 * - Custom color-lists and custom colors in custom color-lists.
23 * - Stored colors
24 * - Resizing
27 #include "../src/config.h"
28 #include "WINGsP.h"
29 #include <math.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36 #include <errno.h>
38 /* BUG There's something fishy with shaped windows */
39 #if 1
40 #ifdef SHAPE
41 #define SHAPE_WAS_DEFINED
42 #undef SHAPE
43 #endif
44 #endif
47 #ifdef SHAPE
48 #include <X11/extensions/shape.h>
49 #endif
52 #ifndef PATH_MAX
53 # define PATH_MAX 1024
54 #endif
57 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
60 * Error Messages
62 #define NO_MEMORY_ERR "Color Panel: Could not allocate memory"
63 #define NO_FILE_ERR "Color Panel: Could not find file"
64 #define X_ERR "Color Panel: X failed request"
68 * Bitmaps for magnifying glass cursor
71 /* Cursor */
72 #define Cursor_x_hot 11
73 #define Cursor_y_hot 11
74 #define Cursor_width 32
75 #define Cursor_height 32
76 static unsigned char Cursor_bits[] = {
77 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
78 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
79 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
80 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
81 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
82 0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
83 0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
84 0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
85 0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
87 /* Cursor shape-mask */
88 #define Cursor_shape_width 32
89 #define Cursor_shape_height 32
90 static unsigned char Cursor_shape_bits[] = {
91 0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
92 0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
93 0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
94 0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
95 0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
96 0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
97 0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
98 0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
99 0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70};
101 /* Clip-mask for magnified pixels */
102 #define Cursor_mask_width 24
103 #define Cursor_mask_height 24
104 static unsigned char Cursor_mask_bits[] = {
105 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
106 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
107 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
108 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
109 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
110 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00};
113 typedef struct MovingView {
114 WMView *view; /* The view this is all about */
115 XImage *image; /* What's under the view */
116 XImage *dirtyRect; /* Storage of overlapped image area */
117 Pixmap magPix; /* Magnified part of pixmap */
118 RColor color; /* Color of a pixel in the image */
119 int x, y; /* Position of view */
120 } MovingView;
122 typedef struct CPColor {
123 RColor rgb; /* The RGB values of the color */
124 RHSVColor hsv; /* The HSV values of the color */
125 enum { /* Which one was last set ? */
126 cpNone,
127 cpRGB,
128 cpHSV
129 } set;
130 } CPColor;
133 typedef struct WheelMatrix {
134 unsigned int width, height; /* Size of the colorwheel */
135 unsigned char *data[3]; /* Wheel data (R,G,B) */
136 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
137 } wheelMatrix;
139 typedef struct W_ColorPanel {
140 WMWindow *win;
141 WMFont *font8;
142 WMFont *font12;
143 void *clientData;
144 WMAction2 *action;
146 /* Common Stuff */
147 WMColorWell *colorWell;
148 WMButton *magnifyBtn;
149 WMButton *wheelBtn;
150 WMButton *slidersBtn;
151 WMButton *customPaletteBtn;
152 WMButton *colorListBtn;
154 /* Magnifying Glass */
155 MovingView *magnifyGlass;
157 /* ColorWheel Panel */
158 WMFrame *wheelFrm;
159 WMSlider *wheelBrightnessS;
160 WMView *wheelView;
162 /* Slider Panels */
163 WMFrame *slidersFrm;
164 WMFrame *seperatorFrm;
165 WMButton *grayBtn;
166 WMButton *rgbBtn;
167 WMButton *cmykBtn;
168 WMButton *hsbBtn;
169 /* Gray Scale Panel */
170 WMFrame *grayFrm;
171 WMLabel *grayMinL;
172 WMLabel *grayMaxL;
173 WMSlider *grayBrightnessS;
174 WMTextField *grayBrightnessT;
175 WMButton *grayPresetBtn[7];
177 /* RGB Panel */
178 WMFrame *rgbFrm;
179 WMLabel *rgbMinL;
180 WMLabel *rgbMaxL;
181 WMSlider *rgbRedS;
182 WMSlider *rgbGreenS;
183 WMSlider *rgbBlueS;
184 WMTextField *rgbRedT;
185 WMTextField *rgbGreenT;
186 WMTextField *rgbBlueT;
188 /* CMYK Panel */
189 WMFrame *cmykFrm;
190 WMLabel *cmykMinL;
191 WMLabel *cmykMaxL;
192 WMSlider *cmykCyanS;
193 WMSlider *cmykMagentaS;
194 WMSlider *cmykYellowS;
195 WMSlider *cmykBlackS;
196 WMTextField *cmykCyanT;
197 WMTextField *cmykMagentaT;
198 WMTextField *cmykYellowT;
199 WMTextField *cmykBlackT;
201 /* HSB Panel */
202 WMFrame *hsbFrm;
203 WMSlider *hsbHueS;
204 WMSlider *hsbSaturationS;
205 WMSlider *hsbBrightnessS;
206 WMTextField *hsbHueT;
207 WMTextField *hsbSaturationT;
208 WMTextField *hsbBrightnessT;
210 /* Custom Palette Panel*/
211 WMFrame *customPaletteFrm;
212 WMPopUpButton *customPaletteHistoryBtn;
213 WMFrame *customPaletteContentFrm;
214 WMPopUpButton *customPaletteMenuBtn;
215 WMView *customPaletteContentView;
217 /* Color List Panel */
218 WMFrame *colorListFrm;
219 WMPopUpButton *colorListHistoryBtn;
220 WMList *colorListContentLst;
221 WMPopUpButton *colorListColorMenuBtn;
222 WMPopUpButton *colorListListMenuBtn;
224 /* Look-Up Tables and Images */
225 wheelMatrix *wheelMtrx;
226 Pixmap wheelImg;
227 Pixmap selectionImg;
228 Pixmap selectionBackImg;
229 RImage *customPaletteImg;
230 char *lastBrowseDir;
232 /* Common Data Fields */
233 CPColor color; /* Current color */
234 WMColorPanelMode mode; /* Current color selection mode */
235 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
236 WMColorPanelMode lastChanged; /* Panel that last changed the color */
237 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
238 int palx, paly; /* (x,y) of sel.-marker in
239 CustomPaletteMode */
240 double palXRatio, palYRatio; /* Ratios in x & y between
241 original and scaled
242 palettesize */
243 int currentPalette;
244 char *configurationPath;
246 struct {
247 unsigned int continuous:1;
248 unsigned int dragging:1;
249 } flags;
250 } W_ColorPanel;
252 enum {
253 CPmenuNewFromFile,
254 CPmenuRename,
255 CPmenuRemove,
256 CPmenuCopy,
257 CPmenuNewFromClipboard
258 } customPaletteMenuItem;
260 enum {
261 CLmenuAdd,
262 CLmenuRename,
263 CLmenuRemove
264 } colorListMenuItem;
267 #define PWIDTH 194
268 #define PHEIGHT 266
269 #define colorWheelSize 150
270 #define customPaletteWidth 182
271 #define customPaletteHeight 106
272 #define knobThickness 8
274 #define SPECTRUM_WIDTH 511
275 #define SPECTRUM_HEIGHT 360
277 #define COLORWHEEL_PART 1
278 #define CUSTOMPALETTE_PART 2
279 #define BUFSIZE 1024
281 #ifndef RGBTXT
282 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
283 #endif
285 #define MAX_LENGTH 1024
288 #ifndef M_PI
289 #define M_PI 3.14159265358979323846
290 #endif
293 static int fetchFile(char* toPath, char *imageSrcFile,
294 char *imageDestFileName);
295 char *generateNewFilename(char *curName);
296 void convertCPColor(CPColor *color);
297 RColor ulongToRColor(WMScreen *scr, unsigned long value);
298 unsigned char getShift(unsigned char value);
300 static void modeButtonCallback(WMWidget *w, void *data);
301 static int getPickerPart(W_ColorPanel *panel, int x, int y);
302 static void readConfiguration(W_ColorPanel *panel);
303 static void readXColors(W_ColorPanel *panel);
305 static void closeWindowCallback(WMWidget *w, void *data);
307 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
308 static WMPoint magnifyInitialize(W_ColorPanel *panel);
309 static void magnifyPutCursor(WMWidget *w, void *data);
310 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
311 static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1,
312 int x2, int y2);
313 static XImage* magnifyGetImage(WMScreen *scr, XImage *image, int x, int y,
314 int w, int h);
316 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
317 static void wheelDestroyMatrix(wheelMatrix *matrix);
318 static void wheelInitMatrix(W_ColorPanel *panel);
319 static void wheelCalculateValues(W_ColorPanel *panel, int maxvalue);
320 static void wheelRender(W_ColorPanel *panel);
321 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
322 static void wheelPaint(W_ColorPanel *panel);
324 static void wheelHandleEvents(XEvent *event, void *data);
325 static void wheelHandleActionEvents(XEvent *event, void *data);
326 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
327 static void wheelUpdateSelection(W_ColorPanel *panel);
328 static void wheelUndrawSelection(W_ColorPanel *panel);
330 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
331 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
332 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
333 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor);
335 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
336 static void grayPresetButtonCallback(WMWidget *w, void *data);
337 static void grayBrightnessTextFieldCallback(void *observerData,
338 WMNotification *notification);
340 static void rgbSliderCallback(WMWidget *w, void *data);
341 static void rgbTextFieldCallback(void *observerData,
342 WMNotification *notification);
344 static void cmykSliderCallback(WMWidget *w, void *data);
345 static void cmykTextFieldCallback(void *observerData,
346 WMNotification *notification);
348 static void hsbSliderCallback(WMWidget *w, void *data);
349 static void hsbTextFieldCallback(void *observerData,
350 WMNotification *notification);
351 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
352 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
353 static void hsbUpdateHueGradient(W_ColorPanel *panel);
355 static void customRenderSpectrum(W_ColorPanel *panel);
356 static void customSetPalette(W_ColorPanel *panel);
357 static void customPaletteHandleEvents(XEvent *event, void *data);
358 static void customPaletteHandleActionEvents(XEvent *event, void *data);
359 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
360 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
361 int x, int y);
362 static void customPaletteMenuCallback(WMWidget *w, void *data);
363 static void customPaletteHistoryCallback(WMWidget *w, void *data);
365 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
366 static void customPaletteMenuRename(W_ColorPanel *panel);
367 static void customPaletteMenuRemove(W_ColorPanel *panel);
369 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
370 int state, WMRect *rect);
371 static void colorListSelect(WMWidget *w, void *data);
372 static void colorListColorMenuCallback(WMWidget *w, void *data);
373 static void colorListListMenuCallback(WMWidget *w, void *data);
374 static void colorListListMenuNew(W_ColorPanel *panel);
376 static void wheelInit(W_ColorPanel *panel);
377 static void grayInit(W_ColorPanel *panel);
378 static void rgbInit(W_ColorPanel *panel);
379 static void cmykInit(W_ColorPanel *panel);
380 static void hsbInit(W_ColorPanel *panel);
384 void
385 WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
387 panel->action = action;
388 panel->clientData = data;
391 static WMColorPanel*
392 makeColorPanel(WMScreen *scrPtr, char *name)
394 WMColorPanel *panel;
395 RImage *image;
396 WMPixmap *pixmap;
397 RColor from;
398 RColor to;
399 WMColor *textcolor, *graybuttoncolor;
400 int i;
401 GC bgc = WMColorGC(scrPtr->black);
402 GC wgc = WMColorGC(scrPtr->white);
405 panel = wmalloc(sizeof(WMColorPanel));
406 memset(panel, 0, sizeof(WMColorPanel));
408 panel->color.rgb.red = 0;
409 panel->color.rgb.green = 0;
410 panel->color.rgb.blue = 0;
411 panel->color.hsv.hue = 0;
412 panel->color.hsv.saturation = 0;
413 panel->color.hsv.value = 0;
414 panel->color.set = cpNone; /* Color has not been set yet */
416 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
417 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
419 panel->win = WMCreateWindowWithStyle(scrPtr, name,
420 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
421 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
422 WMSetWindowTitle(panel->win, "Colors");
423 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
426 /* Set Default ColorPanel Mode(s) */
427 panel->mode = WMWheelModeColorPanel;
428 panel->lastChanged = 0;
429 panel->slidersmode = WMRGBModeColorPanel;
430 panel->configurationPath = wstrconcat(wusergnusteppath(),
431 "/Library/Colors/");
433 /* Some General Purpose Widgets */
434 panel->colorWell = WMCreateColorWell(panel->win);
435 WMResizeWidget(panel->colorWell, 134, 36);
436 WSetColorWellBordered(panel->colorWell, False);
437 WMMoveWidget(panel->colorWell, 56, 4);
439 panel->magnifyBtn = WMCreateCustomButton(panel->win,
440 WBBStateLightMask|WBBStateChangeMask);
441 WMResizeWidget(panel->magnifyBtn, 46, 36);
442 WMMoveWidget(panel->magnifyBtn, 6,4);
443 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
444 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
445 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
447 panel->wheelBtn = WMCreateCustomButton(panel->win,
448 WBBStateLightMask|WBBStateChangeMask);
449 WMResizeWidget(panel->wheelBtn, 46, 32);
450 WMMoveWidget(panel->wheelBtn, 6, 44);
451 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
452 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
453 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
455 panel->slidersBtn = WMCreateCustomButton(panel->win,
456 WBBStateLightMask|WBBStateChangeMask);
457 WMResizeWidget(panel->slidersBtn, 46, 32);
458 WMMoveWidget(panel->slidersBtn, 52, 44);
459 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
460 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
461 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
463 panel->customPaletteBtn = WMCreateCustomButton(panel->win,
464 WBBStateLightMask|WBBStateChangeMask);
465 WMResizeWidget(panel->customPaletteBtn, 46, 32);
466 WMMoveWidget(panel->customPaletteBtn, 98, 44);
467 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
468 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
469 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
471 panel->colorListBtn = WMCreateCustomButton(panel->win,
472 WBBStateLightMask|WBBStateChangeMask);
473 WMResizeWidget(panel->colorListBtn, 46, 32);
474 WMMoveWidget(panel->colorListBtn, 144, 44);
475 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
476 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
477 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
479 /* Let's Group some of them together */
480 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
481 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
482 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
484 /* Widgets for the ColorWheel Panel */
485 panel->wheelFrm = WMCreateFrame(panel->win);
486 WMSetFrameRelief(panel->wheelFrm, WRFlat);
487 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
488 WMMoveWidget(panel->wheelFrm, 5, 80);
490 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
491 /* XXX Can we create a view ? */
492 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
493 W_MoveView(panel->wheelView, 0, 0);
495 /* Create an event handler to handle expose/click events in ColorWheel */
496 WMCreateEventHandler(panel->wheelView,
497 ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
498 LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
500 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
501 panel);
503 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
504 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
505 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
506 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
507 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
508 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
509 panel);
510 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
512 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
513 wheelInitMatrix(panel);
516 /* Widgets for the Slider Panels */
517 panel->slidersFrm = WMCreateFrame(panel->win);
518 WMSetFrameRelief(panel->slidersFrm, WRFlat);
519 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
520 WMMoveWidget(panel->slidersFrm, 4, 80);
522 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
523 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
524 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
525 WMMoveWidget(panel->seperatorFrm, 0, 1);
527 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
528 WBBStateLightMask|WBBStateChangeMask);
529 WMResizeWidget(panel->grayBtn, 46, 24);
530 WMMoveWidget(panel->grayBtn, 1, 8);
531 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
532 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
533 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
535 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
536 WBBStateLightMask|WBBStateChangeMask);
537 WMResizeWidget(panel->rgbBtn, 46, 24);
538 WMMoveWidget(panel->rgbBtn, 47, 8);
539 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
540 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
541 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
543 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
544 WBBStateLightMask|WBBStateChangeMask);
545 WMResizeWidget(panel->cmykBtn, 46, 24);
546 WMMoveWidget(panel->cmykBtn, 93, 8);
547 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
548 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
549 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
551 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
552 WBBStateLightMask|WBBStateChangeMask);
553 WMResizeWidget(panel->hsbBtn, 46, 24);
554 WMMoveWidget(panel->hsbBtn, 139, 8);
555 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
556 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
557 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
559 /* Let's Group the Slider Panel Buttons Together */
560 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
561 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
562 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
564 textcolor = WMDarkGrayColor(scrPtr);
566 /* Widgets for GrayScale Panel */
567 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
568 WMSetFrameRelief(panel->grayFrm, WRFlat);
569 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
570 WMMoveWidget(panel->grayFrm, 0, 34);
572 panel->grayMinL = WMCreateLabel(panel->grayFrm);
573 WMResizeWidget(panel->grayMinL, 20, 10);
574 WMMoveWidget(panel->grayMinL, 2, 2);
575 WMSetLabelText(panel->grayMinL, "0");
576 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
577 WMSetLabelTextColor(panel->grayMinL, textcolor);
578 WMSetLabelFont(panel->grayMinL, panel->font8);
580 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
581 WMResizeWidget(panel->grayMaxL, 40, 10);
582 WMMoveWidget(panel->grayMaxL, 104, 2);
583 WMSetLabelText(panel->grayMaxL, "100");
584 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
585 WMSetLabelTextColor(panel->grayMaxL, textcolor);
586 WMSetLabelFont(panel->grayMaxL, panel->font8);
588 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
589 WMResizeWidget(panel->grayBrightnessS, 141, 16);
590 WMMoveWidget(panel->grayBrightnessS, 2, 14);
591 WMSetSliderMinValue(panel->grayBrightnessS, 0);
592 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
593 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
594 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
595 panel);
597 from.red = 0;
598 from.green = 0;
599 from.blue = 0;
601 to.red = 255;
602 to.green = 255;
603 to.blue = 255;
605 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
606 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
607 RDestroyImage(image);
609 if (pixmap)
610 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
611 panel->font12, 2, 0, 100, WALeft, WMColorGC(scrPtr->white),
612 False, "Brightness", strlen("Brightness"));
613 else
614 wwarning(NO_MEMORY_ERR);
616 WMSetSliderImage(panel->grayBrightnessS, pixmap);
617 WMReleasePixmap(pixmap);
619 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
620 WMResizeWidget(panel->grayBrightnessT, 40, 18);
621 WMMoveWidget(panel->grayBrightnessT, 146, 13);
622 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
623 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
624 WMTextDidEndEditingNotification, panel->grayBrightnessT);
626 for (i=0; i < 7; i++) {
627 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
629 graybuttoncolor = WMCreateRGBColor(scrPtr, (255/6)*i << 8,
630 (255/6)*i << 8, (255/6)*i << 8, True);
631 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
632 WMReleaseColor(graybuttoncolor);
634 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
635 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
636 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
637 WMSetButtonAction(panel->grayPresetBtn[i],
638 grayPresetButtonCallback, panel);
639 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
640 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
641 WMReleasePixmap(pixmap);
645 /* End of GrayScale Panel */
647 /* Widgets for RGB Panel */
648 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
649 WMSetFrameRelief(panel->rgbFrm, WRFlat);
650 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
651 WMMoveWidget(panel->rgbFrm, 0, 34);
653 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
654 WMResizeWidget(panel->rgbMinL, 20, 10);
655 WMMoveWidget(panel->rgbMinL, 2, 2);
656 WMSetLabelText(panel->rgbMinL, "0");
657 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
658 WMSetLabelTextColor(panel->rgbMinL, textcolor);
659 WMSetLabelFont(panel->rgbMinL, panel->font8);
661 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
662 WMResizeWidget(panel->rgbMaxL, 40, 10);
663 WMMoveWidget(panel->rgbMaxL, 104, 2);
664 WMSetLabelText(panel->rgbMaxL, "255");
665 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
666 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
667 WMSetLabelFont(panel->rgbMaxL, panel->font8);
669 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
670 WMResizeWidget(panel->rgbRedS, 141, 16);
671 WMMoveWidget(panel->rgbRedS, 2, 14);
672 WMSetSliderMinValue(panel->rgbRedS, 0);
673 WMSetSliderMaxValue(panel->rgbRedS, 255);
674 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
675 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
677 to.red = 255;
678 to.green = 0;
679 to.blue = 0;
681 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
682 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
683 RDestroyImage(image);
685 if (pixmap)
686 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
687 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Red",
688 strlen("Red"));
689 else
690 wwarning(NO_MEMORY_ERR);
692 WMSetSliderImage(panel->rgbRedS, pixmap);
693 WMReleasePixmap(pixmap);
695 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
696 WMResizeWidget(panel->rgbRedT, 40, 18);
697 WMMoveWidget(panel->rgbRedT, 146, 13);
698 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
699 WMAddNotificationObserver(rgbTextFieldCallback, panel,
700 WMTextDidEndEditingNotification, panel->rgbRedT);
702 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
703 WMResizeWidget(panel->rgbGreenS, 141, 16);
704 WMMoveWidget(panel->rgbGreenS, 2, 36);
705 WMSetSliderMinValue(panel->rgbGreenS, 0);
706 WMSetSliderMaxValue(panel->rgbGreenS, 255);
707 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
708 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
710 to.red = 0;
711 to.green = 255;
712 to.blue = 0;
714 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
715 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
716 RDestroyImage(image);
718 if (pixmap)
719 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
720 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Green",
721 strlen("Green"));
722 else
723 wwarning(NO_MEMORY_ERR);
725 WMSetSliderImage(panel->rgbGreenS, pixmap);
726 WMReleasePixmap(pixmap);
728 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
729 WMResizeWidget(panel->rgbGreenT, 40, 18);
730 WMMoveWidget(panel->rgbGreenT, 146, 35);
731 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
732 WMAddNotificationObserver(rgbTextFieldCallback, panel,
733 WMTextDidEndEditingNotification, panel->rgbGreenT);
736 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
737 WMResizeWidget(panel->rgbBlueS, 141, 16);
738 WMMoveWidget(panel->rgbBlueS, 2, 58);
739 WMSetSliderMinValue(panel->rgbBlueS, 0);
740 WMSetSliderMaxValue(panel->rgbBlueS, 255);
741 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
742 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
744 to.red = 0;
745 to.green = 0;
746 to.blue = 255;
748 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
749 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
750 RDestroyImage(image);
752 if (pixmap)
753 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
754 2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Blue",
755 strlen("Blue"));
756 else
757 wwarning(NO_MEMORY_ERR);
759 WMSetSliderImage(panel->rgbBlueS, pixmap);
760 WMReleasePixmap(pixmap);
762 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
763 WMResizeWidget(panel->rgbBlueT, 40, 18);
764 WMMoveWidget(panel->rgbBlueT, 146, 57);
765 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
766 WMAddNotificationObserver(rgbTextFieldCallback, panel,
767 WMTextDidEndEditingNotification, panel->rgbBlueT);
768 /* End of RGB Panel */
770 /* Widgets for CMYK Panel */
771 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
772 WMSetFrameRelief(panel->cmykFrm, WRFlat);
773 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
774 WMMoveWidget(panel->cmykFrm, 0, 34);
776 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
777 WMResizeWidget(panel->cmykMinL, 20, 10);
778 WMMoveWidget(panel->cmykMinL, 2, 2);
779 WMSetLabelText(panel->cmykMinL, "0");
780 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
781 WMSetLabelTextColor(panel->cmykMinL, textcolor);
782 WMSetLabelFont(panel->cmykMinL, panel->font8);
784 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
785 WMResizeWidget(panel->cmykMaxL, 40, 10);
786 WMMoveWidget(panel->cmykMaxL, 104, 2);
787 WMSetLabelText(panel->cmykMaxL, "100");
788 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
789 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
790 WMSetLabelFont(panel->cmykMaxL, panel->font8);
792 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
793 WMResizeWidget(panel->cmykCyanS, 141, 16);
794 WMMoveWidget(panel->cmykCyanS, 2, 14);
795 WMSetSliderMinValue(panel->cmykCyanS, 0);
796 WMSetSliderMaxValue(panel->cmykCyanS, 100);
797 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
798 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
800 from.red = 255;
801 from.green = 255;
802 from.blue = 255;
804 to.red = 0;
805 to.green = 255;
806 to.blue = 255;
808 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
809 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
810 RDestroyImage(image);
812 if (pixmap)
813 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
814 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Cyan",
815 strlen("Cyan"));
816 else
817 wwarning(NO_MEMORY_ERR);
819 WMSetSliderImage(panel->cmykCyanS, pixmap);
820 WMReleasePixmap(pixmap);
822 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
823 WMResizeWidget(panel->cmykCyanT, 40, 18);
824 WMMoveWidget(panel->cmykCyanT, 146, 13);
825 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
826 WMAddNotificationObserver(cmykTextFieldCallback, panel,
827 WMTextDidEndEditingNotification, panel->cmykCyanT);
830 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
831 WMResizeWidget(panel->cmykMagentaS, 141, 16);
832 WMMoveWidget(panel->cmykMagentaS, 2, 36);
833 WMSetSliderMinValue(panel->cmykMagentaS, 0);
834 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
835 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
836 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
838 to.red = 255;
839 to.green = 0;
840 to.blue = 255;
842 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
843 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
844 RDestroyImage(image);
846 if (pixmap)
847 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
848 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Magenta",
849 strlen("Magenta"));
850 else
851 wwarning(NO_MEMORY_ERR);
853 WMSetSliderImage(panel->cmykMagentaS, pixmap);
854 WMReleasePixmap(pixmap);
856 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
857 WMResizeWidget(panel->cmykMagentaT, 40, 18);
858 WMMoveWidget(panel->cmykMagentaT, 146, 35);
859 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
860 WMAddNotificationObserver(cmykTextFieldCallback, panel,
861 WMTextDidEndEditingNotification, panel->cmykMagentaT);
864 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
865 WMResizeWidget(panel->cmykYellowS, 141, 16);
866 WMMoveWidget(panel->cmykYellowS, 2, 58);
867 WMSetSliderMinValue(panel->cmykYellowS, 0);
868 WMSetSliderMaxValue(panel->cmykYellowS, 100);
869 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
870 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
872 to.red = 255;
873 to.green = 255;
874 to.blue = 0;
876 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
877 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
878 RDestroyImage(image);
880 if (pixmap)
881 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
882 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Yellow",
883 strlen("Yellow"));
884 else
885 wwarning(NO_MEMORY_ERR);
887 WMSetSliderImage(panel->cmykYellowS, pixmap);
888 WMReleasePixmap(pixmap);
890 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
891 WMResizeWidget(panel->cmykYellowT, 40, 18);
892 WMMoveWidget(panel->cmykYellowT, 146, 57);
893 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
894 WMAddNotificationObserver(cmykTextFieldCallback, panel,
895 WMTextDidEndEditingNotification, panel->cmykYellowT);
898 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
899 WMResizeWidget(panel->cmykBlackS, 141, 16);
900 WMMoveWidget(panel->cmykBlackS, 2, 80);
901 WMSetSliderMinValue(panel->cmykBlackS, 0);
902 WMSetSliderMaxValue(panel->cmykBlackS, 100);
903 WMSetSliderValue(panel->cmykBlackS, 0);
904 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
905 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
907 to.red = 0;
908 to.green = 0;
909 to.blue = 0;
911 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
912 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
913 RDestroyImage(image);
915 if (pixmap)
916 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
917 2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Black",
918 strlen("Black"));
919 else
920 wwarning(NO_MEMORY_ERR);
922 WMSetSliderImage(panel->cmykBlackS, pixmap);
923 WMReleasePixmap(pixmap);
925 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
926 WMResizeWidget(panel->cmykBlackT, 40, 18);
927 WMMoveWidget(panel->cmykBlackT, 146, 79);
928 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
929 WMAddNotificationObserver(cmykTextFieldCallback, panel,
930 WMTextDidEndEditingNotification, panel->cmykBlackT);
931 /* End of CMYK Panel */
933 /* Widgets for HSB Panel */
934 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
935 WMSetFrameRelief(panel->hsbFrm, WRFlat);
936 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
937 WMMoveWidget(panel->hsbFrm, 0, 34);
939 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
940 WMResizeWidget(panel->hsbHueS, 141, 16);
941 WMMoveWidget(panel->hsbHueS, 2, 14);
942 WMSetSliderMinValue(panel->hsbHueS, 0);
943 WMSetSliderMaxValue(panel->hsbHueS, 359);
944 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
945 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
947 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
948 WMResizeWidget(panel->hsbHueT, 40, 18);
949 WMMoveWidget(panel->hsbHueT, 146, 13);
950 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
951 WMAddNotificationObserver(hsbTextFieldCallback, panel,
952 WMTextDidEndEditingNotification, panel->hsbHueT);
955 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
956 WMResizeWidget(panel->hsbSaturationS, 141, 16);
957 WMMoveWidget(panel->hsbSaturationS, 2, 36);
958 WMSetSliderMinValue(panel->hsbSaturationS, 0);
959 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
960 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
961 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
963 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
964 WMResizeWidget(panel->hsbSaturationT, 40, 18);
965 WMMoveWidget(panel->hsbSaturationT, 146, 35);
966 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
967 WMAddNotificationObserver(hsbTextFieldCallback, panel,
968 WMTextDidEndEditingNotification, panel->hsbSaturationT);
971 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
972 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
973 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
974 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
975 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
976 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
977 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
979 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
980 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
981 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
982 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
983 WMAddNotificationObserver(hsbTextFieldCallback, panel,
984 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
985 /* End of HSB Panel */
988 WMReleaseColor(textcolor);
990 /* Widgets for the CustomPalette Panel */
991 panel->customPaletteFrm = WMCreateFrame(panel->win);
992 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
993 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
994 WMMoveWidget(panel->customPaletteFrm, 5, 80);
996 panel->customPaletteHistoryBtn = WMCreatePopUpButton(
997 panel->customPaletteFrm);
998 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, "Spectrum");
999 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
1000 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
1001 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
1002 customPaletteHistoryCallback, panel);
1003 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
1004 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
1006 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
1007 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
1008 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
1009 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
1011 panel->customPaletteContentView = W_CreateView(
1012 W_VIEW(panel->customPaletteContentFrm));
1013 /* XXX Test if we can create a view */
1014 W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
1015 customPaletteHeight);
1016 W_MoveView(panel->customPaletteContentView, 2, 2);
1018 /* Create event handler to handle expose/click events in CustomPalette */
1019 WMCreateEventHandler(panel->customPaletteContentView,
1020 ButtonPressMask|ButtonReleaseMask|EnterWindowMask| LeaveWindowMask |
1021 ButtonMotionMask, customPaletteHandleActionEvents, panel);
1023 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
1024 customPaletteHandleEvents, panel);
1026 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
1027 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
1028 WMSetPopUpButtonText(panel->customPaletteMenuBtn, "Palette");
1029 WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
1030 customPaletteMenuCallback, panel);
1031 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
1032 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
1034 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from File...");
1035 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Rename...");
1036 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Remove");
1037 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Copy");
1038 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from Clipboard");
1040 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
1041 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
1042 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
1043 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
1044 CPmenuNewFromClipboard, 0);
1046 customRenderSpectrum(panel);
1047 panel->currentPalette = 0;
1048 panel->palx = customPaletteWidth/2;
1049 panel->paly = customPaletteHeight/2;
1052 /* Widgets for the ColorList Panel */
1053 panel->colorListFrm = WMCreateFrame(panel->win);
1054 WMSetFrameRelief(panel->colorListFrm, WRFlat);
1055 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
1056 WMMoveWidget(panel->colorListFrm, 5, 80);
1058 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1059 WMAddPopUpButtonItem(panel->colorListHistoryBtn, "X11-Colors");
1060 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1061 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
1062 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1063 * colorListHistoryCallback, panel); */
1064 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1065 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1067 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1068 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1069 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1070 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1071 WMMoveWidget(panel->colorListContentLst, 0, 23);
1072 WMHangData(panel->colorListContentLst, panel);
1074 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1075 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1076 WMSetPopUpButtonText(panel->colorListColorMenuBtn, "Color");
1077 WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
1078 colorListColorMenuCallback, panel);
1079 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
1080 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1082 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Add...");
1083 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Rename...");
1084 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Remove");
1086 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1087 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1088 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1090 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1091 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1092 WMSetPopUpButtonText(panel->colorListListMenuBtn, "List");
1093 WMSetPopUpButtonAction(panel->colorListListMenuBtn,
1094 colorListListMenuCallback, panel);
1095 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
1096 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
1097 PHEIGHT - 130);
1099 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "New...");
1100 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Rename...");
1101 WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Remove");
1103 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1104 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1105 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1107 WMRealizeWidget(panel->win);
1108 WMMapSubwidgets(panel->win);
1110 WMMapSubwidgets(panel->wheelFrm);
1111 WMMapSubwidgets(panel->slidersFrm);
1112 WMMapSubwidgets(panel->grayFrm);
1113 WMMapSubwidgets(panel->rgbFrm);
1114 WMMapSubwidgets(panel->cmykFrm);
1115 WMMapSubwidgets(panel->hsbFrm);
1116 WMMapSubwidgets(panel->customPaletteFrm);
1117 WMMapSubwidgets(panel->customPaletteContentFrm);
1118 WMMapSubwidgets(panel->colorListFrm);
1120 /* Pixmap to indicate selection positions
1121 * wheelframe MUST be mapped.
1123 panel->selectionImg = XCreatePixmap(scrPtr->display,
1124 WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1125 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1126 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1128 readConfiguration(panel);
1129 readXColors(panel);
1131 return panel;
1135 WMColorPanel*
1136 WMGetColorPanel(WMScreen *scrPtr)
1138 WMColorPanel *panel;
1140 if (scrPtr->sharedColorPanel)
1141 return scrPtr->sharedColorPanel;
1143 panel = makeColorPanel(scrPtr, "colorPanel");
1145 scrPtr->sharedColorPanel = panel;
1147 return panel;
1151 void
1152 WMFreeColorPanel(WMColorPanel *panel)
1154 W_Screen *scr = WMWidgetScreen(panel->win);
1156 if (panel == scr->sharedColorPanel) {
1157 scr->sharedColorPanel = NULL;
1160 if (!panel)
1161 return;
1163 WMRemoveNotificationObserver(panel);
1164 WMUnmapWidget(panel->win);
1166 /* fonts */
1167 WMReleaseFont(panel->font8);
1168 WMReleaseFont(panel->font12);
1170 /* pixmaps */
1171 wheelDestroyMatrix(panel->wheelMtrx);
1172 if (panel->wheelImg)
1173 XFreePixmap(scr->display, panel->wheelImg);
1174 if (panel->selectionImg)
1175 XFreePixmap(scr->display, panel->selectionImg);
1176 if (panel->selectionBackImg)
1177 XFreePixmap(scr->display, panel->selectionBackImg);
1178 RDestroyImage(panel->customPaletteImg);
1180 /* structs */
1181 if (panel->lastBrowseDir)
1182 wfree(panel->lastBrowseDir);
1183 if (panel->configurationPath)
1184 wfree(panel->configurationPath);
1186 WMDestroyWidget(panel->win);
1188 wfree(panel);
1192 void
1193 WMCloseColorPanel(WMColorPanel *panel)
1195 WMFreeColorPanel(panel);
1199 void
1200 WMShowColorPanel(WMColorPanel *panel)
1202 WMScreen *scr = WMWidgetScreen(panel->win);
1203 WMColor *white = WMWhiteColor(scr);
1205 if (panel->color.set == cpNone)
1206 WMSetColorPanelColor(panel, white);
1207 WMReleaseColor(white);
1209 if (panel->mode != WMWheelModeColorPanel)
1210 WMPerformButtonClick(panel->wheelBtn);
1212 WMMapWidget(panel->win);
1216 static void
1217 closeWindowCallback(WMWidget *w, void *data)
1219 W_ColorPanel *panel = (W_ColorPanel*)data;
1221 WMCloseColorPanel(panel);
1225 static void
1226 readConfiguration(W_ColorPanel *panel)
1228 /* XXX Doesn't take care of "invalid" files */
1230 DIR *dPtr;
1231 struct dirent *dp;
1232 struct stat stat_buf;
1233 int item;
1235 if (stat(panel->configurationPath, &stat_buf)!=0) {
1236 if (mkdir(panel->configurationPath,
1237 S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1238 wsyserror("Color Panel: Could not create directory %s needed"
1239 " to store configurations", panel->configurationPath);
1240 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1241 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1242 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1243 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1244 "File Error",
1245 "Could not create ColorPanel configuration directory",
1246 "OK", NULL, NULL);
1248 return;
1251 if (!(dPtr = opendir(panel->configurationPath))) {
1252 wwarning(NO_FILE_ERR, "%s", panel->configurationPath);
1253 return;
1256 while ((dp = readdir(dPtr)) != NULL) {
1257 unsigned int perm_mask;
1258 char *path = wstrconcat(panel->configurationPath,
1259 dp->d_name);
1261 if (dp->d_name[0] != '.') {
1262 item = WMGetPopUpButtonNumberOfItems(
1263 panel->customPaletteHistoryBtn);
1264 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1266 perm_mask = (access(path, R_OK) == 0);
1267 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn,
1268 item, perm_mask);
1270 wfree(path);
1272 (void)closedir(dPtr);
1276 static void
1277 readXColors(W_ColorPanel *panel)
1279 struct stat stat_buf;
1280 FILE *rgbtxt;
1281 char line[MAX_LENGTH];
1282 int red, green, blue;
1283 char name[48];
1284 RColor *color;
1285 WMListItem *item;
1287 if (stat(RGBTXT, &stat_buf) != 0) {
1288 wsyserror(NO_FILE_ERR, " %s", RGBTXT);
1289 return;
1291 else {
1292 if ((rgbtxt = fopen(RGBTXT, "r"))) {
1293 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1294 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1295 color = wmalloc(sizeof(RColor));
1296 color->red = (unsigned char)red;
1297 color->green = (unsigned char)green;
1298 color->blue = (unsigned char)blue;
1299 item = WMAddListItem(panel->colorListContentLst, name);
1300 item->clientData = (void *)color;
1303 fclose(rgbtxt);
1305 else {
1306 wsyserror(NO_FILE_ERR, "%s", RGBTXT);
1312 void
1313 WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1315 W_Screen *scr = WMWidgetScreen(panel->win);
1317 if (mode != WMWheelModeColorPanel) {
1318 WMUnmapWidget(panel->wheelFrm);
1319 if (panel->selectionBackImg) {
1320 XFreePixmap(WMWidgetScreen(panel->win)->display,
1321 panel->selectionBackImg);
1322 panel->selectionBackImg = None;
1325 if (mode != WMGrayModeColorPanel)
1326 WMUnmapWidget(panel->grayFrm);
1327 if (mode != WMRGBModeColorPanel)
1328 WMUnmapWidget(panel->rgbFrm);
1329 if (mode != WMCMYKModeColorPanel)
1330 WMUnmapWidget(panel->cmykFrm);
1331 if (mode != WMHSBModeColorPanel)
1332 WMUnmapWidget(panel->hsbFrm);
1333 if (mode != WMCustomPaletteModeColorPanel) {
1334 WMUnmapWidget(panel->customPaletteFrm);
1335 if (panel->selectionBackImg) {
1336 XFreePixmap(WMWidgetScreen(panel->win)->display,
1337 panel->selectionBackImg);
1338 panel->selectionBackImg = None;
1341 if (mode != WMColorListModeColorPanel)
1342 WMUnmapWidget(panel->colorListFrm);
1343 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1344 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1345 WMUnmapWidget(panel->slidersFrm);
1346 else
1347 panel->slidersmode = mode;
1349 if (mode == WMWheelModeColorPanel) {
1350 WMMapWidget(panel->wheelFrm);
1351 WMSetButtonSelected(panel->wheelBtn, True);
1352 if (panel->lastChanged != WMWheelModeColorPanel)
1353 wheelInit(panel);
1354 wheelRender(panel);
1355 wheelPaint(panel);
1356 } else if (mode == WMGrayModeColorPanel) {
1357 WMMapWidget(panel->slidersFrm);
1358 WMSetButtonSelected(panel->slidersBtn, True);
1359 WMMapWidget(panel->grayFrm);
1360 WMSetButtonSelected(panel->grayBtn, True);
1361 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1362 if (panel->lastChanged != WMGrayModeColorPanel)
1363 grayInit(panel);
1364 } else if (mode == WMRGBModeColorPanel) {
1365 WMMapWidget(panel->slidersFrm);
1366 WMSetButtonSelected(panel->slidersBtn, True);
1367 WMMapWidget(panel->rgbFrm);
1368 WMSetButtonSelected(panel->rgbBtn, True);
1369 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1370 if (panel->lastChanged != WMRGBModeColorPanel)
1371 rgbInit(panel);
1372 } else if (mode == WMCMYKModeColorPanel) {
1373 WMMapWidget(panel->slidersFrm);
1374 WMSetButtonSelected(panel->slidersBtn, True);
1375 WMMapWidget(panel->cmykFrm);
1376 WMSetButtonSelected(panel->cmykBtn, True);
1377 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1378 if (panel->lastChanged != WMCMYKModeColorPanel)
1379 cmykInit(panel);
1380 } else if (mode == WMHSBModeColorPanel) {
1381 WMMapWidget(panel->slidersFrm);
1382 WMSetButtonSelected(panel->slidersBtn, True);
1383 WMMapWidget(panel->hsbFrm);
1384 WMSetButtonSelected(panel->hsbBtn, True);
1385 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1386 if (panel->lastChanged != WMHSBModeColorPanel)
1387 hsbInit(panel);
1388 } else if (mode == WMCustomPaletteModeColorPanel) {
1389 WMMapWidget(panel->customPaletteFrm);
1390 WMSetButtonSelected(panel->customPaletteBtn, True);
1391 customSetPalette(panel);
1392 } else if (mode == WMColorListModeColorPanel) {
1393 WMMapWidget(panel->colorListFrm);
1394 WMSetButtonSelected(panel->colorListBtn, True);
1397 panel->mode = mode;
1401 WMColor*
1402 WMGetColorPanelColor(WMColorPanel *panel)
1404 return WMGetColorWellColor(panel->colorWell);
1408 void
1409 WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
1411 WMSetColorWellColor(panel->colorWell, color);
1413 panel->color.rgb.red = color->color.red >> 8;
1414 panel->color.rgb.green = color->color.green >> 8;
1415 panel->color.rgb.blue = color->color.blue >> 8;
1416 panel->color.set = cpRGB;
1418 if (panel->mode == panel->lastChanged)
1419 panel->lastChanged = 0;
1421 WMSetColorPanelPickerMode(panel, panel->mode);
1425 static void
1426 updateSwatch(WMColorPanel *panel, CPColor color)
1428 WMScreen *scr = WMWidgetScreen(panel->win);
1429 WMColor *wellcolor;
1431 if (color.set != cpRGB)
1432 convertCPColor(&color);
1434 panel->color = color;
1436 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8,
1437 color.rgb.green << 8,
1438 color.rgb.blue << 8, True);
1440 WMSetColorWellColor(panel->colorWell, wellcolor);
1441 WMReleaseColor(wellcolor);
1443 if (!panel->flags.dragging || panel->flags.continuous) {
1444 if (panel->action)
1445 (*panel->action)(panel, panel->clientData);
1447 WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
1448 NULL);
1452 static void
1453 modeButtonCallback(WMWidget *w, void *data)
1455 W_ColorPanel *panel = (W_ColorPanel*)(data);
1457 if (w == panel->wheelBtn)
1458 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1459 else if (w == panel->slidersBtn)
1460 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1461 else if (w == panel->customPaletteBtn)
1462 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1463 else if (w == panel->colorListBtn)
1464 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1465 else if (w == panel->grayBtn)
1466 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1467 else if (w == panel->rgbBtn)
1468 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1469 else if (w == panel->cmykBtn)
1470 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1471 else if (w == panel->hsbBtn)
1472 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1476 /****************** Magnifying Cursor Functions *******************/
1478 static XImage*
1479 magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
1481 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1482 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1483 displayHeight = DisplayHeight(scr->display, scr->screen);
1485 if (!(image && image->data)) {
1486 /* The image in panel->magnifyGlass->image does not exist yet.
1487 * Grab one from the screen (not beyond) and use it from now on.
1489 if (!(image = XGetImage(scr->display, scr->rootWin,
1490 x - Cursor_x_hot,
1491 y - Cursor_y_hot,
1492 w, h, AllPlanes, ZPixmap)))
1493 wwarning(X_ERR);
1495 return image;
1498 /* Coordinate correction for back pixmap
1499 * if magnifying glass is at screen-borders
1502 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1503 * Hatched area is beyond screen border.
1505 * |<-Cursor_x_hot->|
1506 * ________________|_____
1507 * |/ / / / / / /| | |
1508 * | / / / / / / |(x,y) |
1509 * |/_/_/_/_/_/_/|________|
1510 * |<----x0----->|<--w0-->|
1514 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1515 * screen borders
1516 * Hatched area is beyond screen border
1518 * |<-Cursor_x_hot->|
1519 * ________________|_______________
1520 * | | | / / / / / /|
1521 * | (x,y)|/ / / / / / |
1522 * |___________________|_/_/_/_/_/_/|
1523 * |<-------w0-------->| |
1524 * |<---------------w--|----------->|
1525 * | |
1526 * x0 Displaywidth-1
1529 if (x < Cursor_x_hot) { /* see fig. 1 */
1530 x0 = Cursor_x_hot - x;
1531 w0 = w - x0;
1534 if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1535 w0 = (displayWidth) - (x - Cursor_x_hot);
1538 if (y < Cursor_y_hot) { /* see fig. 1 */
1539 y0 = Cursor_y_hot - y;
1540 h0 = h - y0;
1543 if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1544 h0 = (displayHeight) - (y - Cursor_y_hot);
1546 /* end of coordinate correction */
1549 /* Grab an image from the screen, clipped if necessary,
1550 * and put it in the existing panel->magnifyGlass->image
1551 * with the corresponding clipping offset.
1553 if (!XGetSubImage(scr->display, scr->rootWin,
1554 x - Cursor_x_hot + x0,
1555 y - Cursor_y_hot + y0,
1556 w0, h0, AllPlanes, ZPixmap,
1557 image, x0, y0))
1558 wwarning(X_ERR);
1560 return NULL;
1564 static void
1565 magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1567 /* (x1, y1) = topleft corner of existing rectangle
1568 * (x2, y2) = topleft corner of new position
1571 W_Screen *scr = WMWidgetScreen(panel->win);
1572 int xa = 0, ya = 0, xb = 0, yb = 0;
1573 int width, height;
1574 const int dx = abs(x2 - x1),
1575 dy = abs(y2 - y1);
1576 XImage *image;
1577 const int x_min = Cursor_x_hot,
1578 y_min = Cursor_y_hot,
1579 x_max = DisplayWidth(scr->display, scr->screen) -1 -
1580 (Cursor_mask_width - Cursor_x_hot),
1581 y_max = DisplayHeight(scr->display, scr->screen) -1 -
1582 (Cursor_mask_height - Cursor_y_hot);
1584 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1585 return; /* No movement */
1587 if (x1 < x2)
1588 xa = dx;
1589 else
1590 xb = dx;
1592 if (y1 < y2)
1593 ya = dy;
1594 else
1595 yb = dy;
1597 width = Cursor_mask_width - dx;
1598 height = Cursor_mask_height - dy;
1600 /* If the traversed distance is larger than the size of the magnifying
1601 * glass contents, there is no need to do dirty rectangles. A whole new
1602 * rectangle can be grabbed (unless that rectangle falls partially
1603 * off screen).
1604 * Destroying the image and setting it to NULL will achieve that later on.
1606 * Of course, grabbing an XImage beyond the borders of the screen will
1607 * cause trouble, this is considdered a special case. Part of the screen
1608 * is grabbed, but there is no need for dirty rectangles.
1610 if ((width <= 0) || (height <= 0)) {
1611 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1612 if (panel->magnifyGlass->image)
1613 XDestroyImage(panel->magnifyGlass->image);
1614 panel->magnifyGlass->image = NULL;
1616 } else {
1617 if (panel->magnifyGlass->image) {
1618 /* Get dirty rectangle from panel->magnifyGlass->image */
1619 panel->magnifyGlass->dirtyRect =
1620 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1621 if (!panel->magnifyGlass->dirtyRect) {
1622 wwarning(X_ERR);
1623 return; /* X returned a NULL from XSubImage */
1628 /* Get image from screen */
1629 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
1630 Cursor_mask_width, Cursor_mask_height);
1631 if (image) { /* Only reassign if a *new* image was grabbed */
1632 panel->magnifyGlass->image = image;
1633 return;
1636 /* Copy previously stored rectangle on covered part of image */
1637 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1638 int old_height;
1640 /* "width" and "height" are used as coordinates here,
1641 * and run from [0...width-1] and [0...height-1] respectively.
1643 width--;
1644 height--;
1645 old_height = height;
1647 for (; width >= 0; width--)
1648 for (height = old_height; height >= 0; height--)
1649 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1650 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1651 XDestroyImage(panel->magnifyGlass->dirtyRect);
1652 panel->magnifyGlass->dirtyRect = NULL;
1655 return;
1659 static Pixmap
1660 magnifyCreatePixmap(WMColorPanel *panel)
1662 W_Screen *scr = WMWidgetScreen(panel->win);
1663 int u, v;
1664 #ifndef SHAPE
1665 Pixmap pixmap;
1666 #endif
1667 unsigned long color;
1669 if (!panel->magnifyGlass->image)
1670 return None;
1672 if (!panel->magnifyGlass->magPix)
1673 return None;
1676 * Copy an area of only 5x5 pixels from the center of the image.
1678 for (u = 0; u < 5; u++) {
1679 for (v = 0; v < 5; v++) {
1680 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1682 XSetForeground(scr->display, scr->copyGC, color);
1684 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1685 panel->magnifyGlass->color = ulongToRColor(scr, color);
1687 /* The center square must eventually be centered around the
1688 * hotspot. The image needs shifting to achieve this. The amount of
1689 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1690 * _ _ _ _ _
1691 * |_|_|_|_|_|
1692 * ^------- center of center square == Cursor_x_hot
1694 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1695 scr->copyGC,
1696 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1697 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1701 #ifdef SHAPE
1702 return panel->magnifyGlass->magPix;
1703 #else
1704 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
1705 Cursor_mask_height, scr->depth);
1706 if (!pixmap)
1707 return None;
1709 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1710 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1712 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1713 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1714 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1715 /* (2,2) puts center pixel on center of glass */
1717 return pixmap;
1718 #endif
1723 static WMView*
1724 magnifyCreateView(W_ColorPanel *panel)
1726 W_Screen *scr = WMWidgetScreen(panel->win);
1727 WMView *magView;
1729 magView = W_CreateTopView(scr);
1730 if (!magView)
1731 return NULL;
1733 magView->self = panel->win;
1734 magView->flags.topLevel = 1;
1735 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1736 magView->attribs.override_redirect = True;
1737 magView->attribs.save_under = True;
1739 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1741 W_RealizeView(magView);
1743 return magView;
1747 static Cursor
1748 magnifyGrabPointer(W_ColorPanel *panel)
1750 W_Screen *scr = WMWidgetScreen(panel->win);
1751 Pixmap magPixmap, magPixmap2;
1752 Cursor magCursor;
1753 XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
1754 XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
1756 /* Cursor creation stuff */
1757 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1758 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1759 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1760 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1762 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1763 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1765 XFreePixmap(scr->display, magPixmap);
1766 XFreePixmap(scr->display, magPixmap2);
1768 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1770 /* Set up Pointer */
1771 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1772 PointerMotionMask | ButtonPressMask,
1773 GrabModeAsync, GrabModeAsync,
1774 scr->rootWin, magCursor, CurrentTime);
1776 return magCursor;
1780 static WMPoint
1781 magnifyInitialize(W_ColorPanel *panel)
1783 W_Screen *scr = WMWidgetScreen(panel->win);
1784 int x, y, u, v;
1785 unsigned int mask;
1786 Pixmap pixmap, clip_mask;
1787 WMPoint point;
1788 Window root_return, child_return;
1790 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1791 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1792 1, 0, 1);
1793 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1794 5*5 -1, 5*5 -1, scr->depth);
1796 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
1797 &x, &y, &u, &v, &mask);
1799 panel->magnifyGlass->image = NULL;
1801 /* Clipmask to make magnified view-contents circular */
1802 #ifdef SHAPE
1803 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1804 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1805 #else
1806 /* Clip circle in glass cursor */
1807 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1808 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1809 #endif
1811 XFreePixmap(scr->display, clip_mask);
1813 /* Draw initial magnifying glass contents */
1814 magnifyGetImageStored(panel, x, y, x, y);
1816 pixmap = magnifyCreatePixmap(panel);
1817 XSetWindowBackgroundPixmap(scr->display,
1818 WMViewXID(panel->magnifyGlass->view),
1819 pixmap);
1820 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1821 XFlush(scr->display);
1823 #ifndef SHAPE
1824 XFreePixmap(scr->display, pixmap);
1825 #endif
1827 point.x = x;
1828 point.y = y;
1830 return point;
1834 static void
1835 magnifyPutCursor(WMWidget *w, void *data)
1837 W_ColorPanel *panel = (W_ColorPanel*)(data);
1838 W_Screen *scr = WMWidgetScreen(panel->win);
1839 Cursor magCursor;
1840 Pixmap pixmap;
1841 XEvent event;
1842 WMPoint initialPosition;
1844 /* Destroy wheelBackImg, so it'll update properly */
1845 if (panel->selectionBackImg) {
1846 XFreePixmap(WMWidgetScreen(panel->win)->display,
1847 panel->selectionBackImg);
1848 panel->selectionBackImg = None;
1851 /* Create magnifying glass */
1852 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1853 panel->magnifyGlass->view = magnifyCreateView(panel);
1854 if (!panel->magnifyGlass->view)
1855 return;
1857 initialPosition = magnifyInitialize(panel);
1858 panel->magnifyGlass->x = initialPosition.x;
1859 panel->magnifyGlass->y = initialPosition.y;
1861 W_MoveView(panel->magnifyGlass->view,
1862 panel->magnifyGlass->x - Cursor_x_hot,
1863 panel->magnifyGlass->y - Cursor_y_hot);
1864 W_MapView(panel->magnifyGlass->view);
1866 magCursor = magnifyGrabPointer(panel);
1868 while (panel->magnifyGlass->image)
1870 WMNextEvent(scr->display, &event);
1872 /* Pack motion events */
1873 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1876 switch (event.type)
1878 case ButtonPress:
1879 XDestroyImage(panel->magnifyGlass->image);
1880 panel->magnifyGlass->image = NULL;
1882 if (event.xbutton.button == Button1) {
1883 panel->color.rgb = panel->magnifyGlass->color;
1884 panel->color.set = cpRGB;
1885 updateSwatch(panel, panel->color);
1887 switch (panel->mode) {
1888 case WMWheelModeColorPanel:
1889 wheelInit(panel);
1890 wheelRender(panel);
1891 wheelPaint(panel);
1892 break;
1893 case WMGrayModeColorPanel:
1894 grayInit(panel);
1895 break;
1896 case WMRGBModeColorPanel:
1897 rgbInit(panel);
1898 break;
1899 case WMCMYKModeColorPanel:
1900 cmykInit(panel);
1901 break;
1902 case WMHSBModeColorPanel:
1903 hsbInit(panel);
1904 break;
1905 default:
1906 break;
1908 panel->lastChanged = panel->mode;
1910 WMSetButtonSelected(panel->magnifyBtn, False);
1911 break;
1913 case MotionNotify:
1914 while (XPending(event.xmotion.display)) {
1915 XEvent ev;
1916 XPeekEvent(event.xmotion.display, &ev);
1917 if (ev.type == MotionNotify)
1918 XNextEvent(event.xmotion.display, &event);
1919 else
1920 break;
1923 /* Get a "dirty rectangle" */
1924 magnifyGetImageStored( panel,
1925 panel->magnifyGlass->x, panel->magnifyGlass->y,
1926 event.xmotion.x_root, event.xmotion.y_root);
1928 /* Update coordinates */
1929 panel->magnifyGlass->x = event.xmotion.x_root;
1930 panel->magnifyGlass->y = event.xmotion.y_root;
1932 /* Move view */
1933 W_MoveView(panel->magnifyGlass->view,
1934 panel->magnifyGlass->x - Cursor_x_hot,
1935 panel->magnifyGlass->y - Cursor_y_hot);
1937 /* Put new image (with magn.) in view */
1938 pixmap = magnifyCreatePixmap(panel);
1939 if (pixmap != None) {
1940 /* Change the window background */
1941 XSetWindowBackgroundPixmap(scr->display,
1942 WMViewXID(panel->magnifyGlass->view), pixmap);
1943 /* Force an Expose (handled by X) */
1944 XClearWindow(scr->display,
1945 WMViewXID(panel->magnifyGlass->view));
1946 /* Synchronize the event queue, so the Expose is handled NOW */
1947 XFlush(scr->display);
1948 #ifndef SHAPE
1949 XFreePixmap(scr->display, pixmap);
1950 #endif
1952 break;
1954 /* Try XQueryPointer for this !!! It returns windows that the pointer
1955 * is over. Note: We found this solving the invisible donkey cap bug
1957 #if 0 /* As it is impossible to make this work in all cases,
1958 * we consider it confusing. Therefore we disabled it.
1960 case FocusOut: /* fall through */
1961 case FocusIn:
1963 * Color Panel window (panel->win) lost or received focus.
1964 * We need to update the pixmap in the magnifying glass.
1966 * BUG Doesn't work with focus switches between two windows
1967 * if none of them is the color panel.
1969 XUngrabPointer(scr->display, CurrentTime);
1970 W_UnmapView(panel->magnifyGlass->view);
1972 magnifyInitialize(panel);
1974 W_MapView(panel->magnifyGlass->view);
1975 XGrabPointer (scr->display, panel->magnifyGlass->view->window,
1976 True, PointerMotionMask | ButtonPressMask,
1977 GrabModeAsync, GrabModeAsync,
1978 scr->rootWin, magCursor, CurrentTime);
1979 break;
1980 #endif
1981 default:
1982 WMHandleEvent(&event);
1983 break;
1984 } /* of switch */
1987 XUngrabPointer(scr->display, CurrentTime);
1988 XFreeCursor(scr->display, magCursor);
1990 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1991 panel->magnifyGlass->magPix = None;
1993 W_UnmapView(panel->magnifyGlass->view);
1994 W_DestroyView(panel->magnifyGlass->view);
1995 panel->magnifyGlass->view = NULL;
1997 wfree(panel->magnifyGlass);
2002 /****************** ColorWheel Functions ************************/
2004 static wheelMatrix*
2005 wheelCreateMatrix(unsigned int width, unsigned int height)
2007 wheelMatrix *matrix = NULL;
2008 int i;
2010 assert((width > 0) && (height > 0));
2012 matrix = wmalloc(sizeof(wheelMatrix));
2013 memset(matrix, 0, sizeof(wheelMatrix));
2014 matrix->width = width;
2015 matrix->height = height;
2017 for (i = 0; i < 3; i++) {
2018 matrix->data[i] = wmalloc(width*height*sizeof(unsigned char));
2021 return matrix;
2025 static void
2026 wheelDestroyMatrix(wheelMatrix *matrix)
2028 int i;
2030 if (!matrix)
2031 return;
2033 for (i = 0; i < 3; i++) {
2034 if (matrix->data[i])
2035 wfree(matrix->data[i]);
2037 wfree(matrix);
2041 static void
2042 wheelInitMatrix(W_ColorPanel *panel)
2044 int i;
2045 int x,y;
2046 unsigned char *rp, *gp, *bp;
2047 CPColor cpColor;
2048 long ofs[4];
2049 int xcor, ycor;
2050 unsigned short sat;
2051 int dhue[4];
2052 const int cw_halfsize = (colorWheelSize + 4)/2,
2053 cw_sqsize = (colorWheelSize +4) * (colorWheelSize +4),
2054 uchar_shift = getShift(sizeof(unsigned char));
2056 if (!panel->wheelMtrx)
2057 return;
2059 cpColor.hsv.value = 255;
2060 cpColor.set = cpHSV;
2062 ofs[0] = -1;
2063 ofs[1] = -(colorWheelSize + 4);
2065 /* offsets are counterclockwise (in triangles).
2067 * ofs[0] ---->
2068 * _______________________________________
2069 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
2070 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
2071 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
2072 * o | | | | | | | | | | | | | | | | | | | | | [3]
2074 * <---- ofs[2]
2075 * ____
2076 * |\ /| <-- triangles
2077 * | \/ |
2078 * | /\ |
2079 * |/__\|
2082 for (y = 0; y < cw_halfsize; y++) {
2083 for (x = y; x < (colorWheelSize+4-y); x++) {
2084 /* (xcor, ycor) is (x,y) relative to center of matrix */
2085 xcor = 2 * x - 4 - colorWheelSize;
2086 ycor = 2 * y - 4 - colorWheelSize;
2088 /* RColor.saturation is unsigned char and will wrap after 255 */
2089 sat = rint(255.0 * sqrt(xcor*xcor + ycor*ycor) / colorWheelSize);
2091 cpColor.hsv.saturation = (unsigned char)sat;
2093 ofs[0]++; /* top quarter of matrix*/
2094 ofs[1] += colorWheelSize + 4; /* left quarter */
2095 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
2096 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
2098 if (sat < 256) {
2099 if (xcor != 0)
2100 dhue[0] = rint(atan((double)ycor / (double)xcor) *
2101 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
2102 else
2103 dhue[0] = 270;
2105 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
2106 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
2107 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
2108 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
2110 for (i = 0; i < 4; i++) {
2111 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2112 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2113 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2115 cpColor.hsv.hue = dhue[i];
2116 convertCPColor(&cpColor);
2118 *rp = (unsigned char)(cpColor.rgb.red);
2119 *gp = (unsigned char)(cpColor.rgb.green);
2120 *bp = (unsigned char)(cpColor.rgb.blue);
2123 else {
2124 for (i = 0; i < 4; i++) {
2125 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
2126 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
2127 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
2129 *rp = (unsigned char)0;
2130 *gp = (unsigned char)0;
2131 *bp = (unsigned char)0;
2136 ofs[0] += 2*y+1;
2137 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
2142 static void
2143 wheelCalculateValues(W_ColorPanel *panel, int maxvalue)
2145 unsigned int i;
2146 unsigned int v;
2148 for (i = 0; i < 256; i++) {
2149 /* We divide by 128 in advance, and check whether that number divides
2150 * by 2 properly. If not, we add one to round the number correctly
2152 v = (i*maxvalue) >> 7;
2153 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
2158 static void
2159 wheelRender(W_ColorPanel *panel)
2161 W_Screen *scr = WMWidgetScreen(panel->win);
2162 int x,y;
2163 RImage *image;
2164 unsigned char *ptr;
2165 RColor gray;
2166 unsigned long ofs = 0;
2167 /*unsigned char shift = getShift(sizeof(unsigned char));*/
2169 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, True);
2170 if (!image) {
2171 wwarning(NO_MEMORY_ERR);
2172 return;
2175 ptr = image->data;
2177 /* TODO Make this transparent istead of gray */
2178 gray.red = gray.blue = 0xae; gray.green = 0xaa;
2180 for (y = 0; y < colorWheelSize+4; y++) {
2181 for (x = 0; x < colorWheelSize+4; x++) {
2182 if (wheelInsideColorWheel(panel, ofs)) {
2183 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2184 panel->wheelMtrx->data[0][ofs] ]);
2185 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2186 panel->wheelMtrx->data[1][ofs] ]);
2187 *(ptr++) = (unsigned char)(panel->wheelMtrx->values[
2188 panel->wheelMtrx->data[2][ofs] ]);
2189 *(ptr++) = 0;
2191 else {
2192 *(ptr++) = (unsigned char)(gray.red);
2193 *(ptr++) = (unsigned char)(gray.green);
2194 *(ptr++) = (unsigned char)(gray.blue);
2195 *(ptr++) = 255;
2197 ofs++;
2201 if (panel->wheelImg)
2202 XFreePixmap(scr->display, panel->wheelImg);
2204 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2205 RDestroyImage(image);
2207 /* Check if backimage exists. If it doesn't, allocate and fill it */
2208 if (!panel->selectionBackImg) {
2209 panel->selectionBackImg = XCreatePixmap(scr->display,
2210 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2211 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2212 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2213 /* -2 is hot spot correction */
2218 static Bool
2219 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
2221 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2222 (panel->wheelMtrx->data[1][ofs] != 0) &&
2223 (panel->wheelMtrx->data[2][ofs] != 0));
2227 static void
2228 wheelPaint (W_ColorPanel *panel)
2230 W_Screen *scr = WMWidgetScreen(panel->win);
2232 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2233 scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
2235 /* Draw selection image */
2236 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2237 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2241 static void
2242 wheelHandleEvents(XEvent *event, void *data)
2244 W_ColorPanel *panel = (W_ColorPanel*)data;
2246 switch (event->type) {
2247 case Expose:
2248 if (event->xexpose.count != 0) /* TODO Improve */
2249 break;
2250 wheelPaint(panel);
2251 break;
2256 static void
2257 wheelHandleActionEvents(XEvent *event, void *data)
2259 W_ColorPanel *panel = (W_ColorPanel*)data;
2261 switch (event->type) {
2262 case ButtonPress:
2263 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
2264 COLORWHEEL_PART) {
2266 panel->lastChanged = WMWheelModeColorPanel;
2267 panel->flags.dragging = 1;
2269 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2271 break;
2273 case ButtonRelease:
2274 panel->flags.dragging = 0;
2275 if (!panel->flags.continuous) {
2276 if (panel->action)
2277 (*panel->action)(panel, panel->clientData);
2279 break;
2281 case MotionNotify:
2282 if (panel->flags.dragging) {
2283 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
2284 COLORWHEEL_PART) {
2285 wheelPositionSelection(panel, event->xmotion.x,
2286 event->xmotion.y);
2288 else
2289 wheelPositionSelectionOutBounds(panel, event->xmotion.x,
2290 event->xmotion.y);
2292 break;
2297 static int
2298 getPickerPart(W_ColorPanel *panel, int x, int y)
2300 int lx, ly;
2301 unsigned long ofs;
2303 lx = x;
2304 ly = y;
2306 if (panel->mode == WMWheelModeColorPanel) {
2307 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
2308 (ly <= 2+colorWheelSize)) {
2310 ofs = ly*panel->wheelMtrx->width+lx;
2312 if (wheelInsideColorWheel(panel, ofs))
2313 return COLORWHEEL_PART;
2317 if (panel->mode == WMCustomPaletteModeColorPanel) {
2318 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
2319 (ly < customPaletteHeight-2)) {
2320 return CUSTOMPALETTE_PART;
2324 return 0;
2328 static void
2329 wheelBrightnessSliderCallback(WMWidget *w, void *data)
2331 int value;
2333 W_ColorPanel *panel = (W_ColorPanel*)data;
2335 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
2337 wheelCalculateValues(panel, value);
2339 if (panel->color.set == cpRGB) {
2340 convertCPColor(&panel->color);
2341 panel->color.set = cpHSV;
2344 panel->color.hsv.value = value;
2346 wheelRender(panel);
2347 wheelPaint(panel);
2348 wheelUpdateSelection(panel);
2352 static void
2353 wheelUpdateSelection(W_ColorPanel *panel)
2355 W_Screen *scr = WMWidgetScreen(panel->win);
2357 updateSwatch(panel, panel->color);
2358 panel->lastChanged = WMWheelModeColorPanel;
2360 /* Redraw color selector (and make a backup of the part it will cover) */
2361 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2362 scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
2363 /* "-2" is correction for hotspot location */
2364 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2365 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2366 /* see above */
2370 static void
2371 wheelUndrawSelection(W_ColorPanel *panel)
2373 W_Screen *scr = WMWidgetScreen(panel->win);
2375 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2376 scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
2377 /* see above */
2380 static void
2381 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
2383 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
2385 panel->color.rgb.red = panel->wheelMtrx->values[
2386 panel->wheelMtrx->data[0][ofs] ];
2388 panel->color.rgb.green = panel->wheelMtrx->values[
2389 panel->wheelMtrx->data[1][ofs] ];
2391 panel->color.rgb.blue = panel->wheelMtrx->values[
2392 panel->wheelMtrx->data[2][ofs] ];
2393 panel->color.set = cpRGB;
2395 wheelUndrawSelection(panel);
2397 panel->colx = x;
2398 panel->coly = y;
2400 wheelUpdateSelection(panel);
2401 wheelUpdateBrightnessGradientFromLocation(panel);
2404 static void
2405 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2407 int hue;
2408 int xcor, ycor;
2409 CPColor cpColor;
2411 xcor = x * 2 - colorWheelSize - 4;
2412 ycor = y * 2 - colorWheelSize - 4;
2414 panel->color.hsv.saturation = 255;
2415 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2417 if (xcor != 0)
2418 hue = rint(atan(- (double)ycor / (double)xcor) * (180.0/M_PI));
2419 else {
2420 if (ycor < 0)
2421 hue = 90;
2422 else
2423 hue = 270;
2426 if (xcor < 0)
2427 hue += 180;
2429 if ((xcor > 0) && (ycor > 0))
2430 hue += 360;
2432 panel->color.hsv.hue = hue;
2433 panel->color.set = cpHSV;
2434 convertCPColor(&panel->color);
2436 wheelUndrawSelection(panel);
2438 panel->colx = 2 + rint((colorWheelSize * (1.0 +
2439 cos( panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2440 /* "+2" because of "colorWheelSize + 4" */
2441 panel->coly = 2 + rint((colorWheelSize * (1.0 +
2442 sin(- panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
2444 wheelUpdateSelection(panel);
2445 cpColor = panel->color;
2446 wheelUpdateBrightnessGradient(panel, cpColor);
2449 static void
2450 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2452 CPColor from;
2453 unsigned long ofs;
2455 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2457 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2458 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2459 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2460 from.set = cpRGB;
2462 wheelUpdateBrightnessGradient(panel, from);
2465 static void
2466 wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor)
2468 RColor to;
2469 RImage *sliderImg;
2470 WMPixmap *sliderPxmp;
2472 to.red = to.green = to.blue = 0;
2474 if (topColor.set == cpHSV)
2475 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 double 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 double 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 char *ptr;
2924 CPColor cpColor;
2926 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2928 ptr = spectrum->data;
2930 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2931 cpColor.hsv.hue = y;
2932 cpColor.hsv.saturation = 0;
2933 cpColor.hsv.value = 255;
2934 cpColor.set = cpHSV;
2936 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2937 convertCPColor(&cpColor);
2939 *(ptr++) = (unsigned char)cpColor.rgb.red;
2940 *(ptr++) = (unsigned char)cpColor.rgb.green;
2941 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2943 if (x < (SPECTRUM_WIDTH/2))
2944 cpColor.hsv.saturation++;
2946 if (x > (SPECTRUM_WIDTH/2))
2947 cpColor.hsv.value--;
2950 if (panel->customPaletteImg) {
2951 RDestroyImage(panel->customPaletteImg);
2952 panel->customPaletteImg = NULL;
2954 panel->customPaletteImg = spectrum;
2959 static void
2960 customSetPalette(W_ColorPanel *panel)
2962 W_Screen *scr = WMWidgetScreen(panel->win);
2963 RImage *scaledImg;
2964 Pixmap image;
2965 int item;
2967 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
2968 customPaletteHeight, scr->depth);
2969 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
2970 customPaletteHeight);
2971 RConvertImage(scr->rcontext, scaledImg, &image);
2972 RDestroyImage(scaledImg);
2974 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2975 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2977 /* Check backimage exists. If it doesn't, allocate and fill it */
2978 if (!panel->selectionBackImg) {
2979 panel->selectionBackImg = XCreatePixmap(scr->display,
2980 panel->customPaletteContentView->window, 4, 4, scr->depth);
2983 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2984 panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2985 XCopyArea(scr->display, panel->selectionImg,
2986 panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
2987 panel->palx-2, panel->paly-2);
2988 XFreePixmap(scr->display, image);
2990 panel->palXRatio = (double)(panel->customPaletteImg->width) /
2991 (double)(customPaletteWidth);
2992 panel->palYRatio = (double)(panel->customPaletteImg->height) /
2993 (double)(customPaletteHeight);
2995 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2999 static void
3000 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
3002 W_Screen *scr = WMWidgetScreen(panel->win);
3003 unsigned long ofs;
3006 /* undraw selection */
3007 XCopyArea(scr->display, panel->selectionBackImg,
3008 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3009 panel->palx-2, panel->paly-2);
3011 panel->palx = x;
3012 panel->paly = y;
3014 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
3015 panel->customPaletteImg->width) * 3;
3017 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
3018 panel->color.rgb.green = panel->customPaletteImg->data[ofs+1];
3019 panel->color.rgb.blue = panel->customPaletteImg->data[ofs+2];
3020 panel->color.set = cpRGB;
3022 updateSwatch(panel, panel->color);
3023 panel->lastChanged = WMCustomPaletteModeColorPanel;
3025 /* Redraw color selector (and make a backup of the part it will cover) */
3026 XCopyArea(scr->display, panel->customPaletteContentView->window,
3027 panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
3028 4, 4, 0, 0); /* "-2" is correction for hotspot location */
3029 XCopyArea(scr->display, panel->selectionImg,
3030 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
3031 panel->palx-2, panel->paly-2); /* see above */
3035 static void
3036 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
3038 if (x < 2)
3039 x = 2;
3040 if (y < 2)
3041 y = 2;
3042 if (x >= customPaletteWidth)
3043 x = customPaletteWidth -2;
3044 if (y >= customPaletteHeight)
3045 y = customPaletteHeight -2;
3047 customPalettePositionSelection(panel, x, y);
3051 static void
3052 customPaletteHandleEvents(XEvent *event, void *data)
3054 W_ColorPanel *panel = (W_ColorPanel*)data;
3056 switch (event->type) {
3057 case Expose:
3058 if (event->xexpose.count != 0) /* TODO Improve. */
3059 break;
3060 customSetPalette(panel);
3061 break;
3065 static void
3066 customPaletteHandleActionEvents(XEvent *event, void *data)
3068 W_ColorPanel *panel = (W_ColorPanel*)data;
3069 int x, y;
3071 switch (event->type) {
3072 case ButtonPress:
3073 x = event->xbutton.x;
3074 y = event->xbutton.y;
3076 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3077 panel->flags.dragging = 1;
3078 customPalettePositionSelection(panel, x, y);
3080 break;
3082 case ButtonRelease:
3083 panel->flags.dragging = 0;
3084 if (!panel->flags.continuous) {
3085 if (panel->action)
3086 (*panel->action)(panel, panel->clientData);
3088 break;
3090 case MotionNotify:
3091 x = event->xmotion.x;
3092 y = event->xmotion.y;
3094 if (panel->flags.dragging) {
3095 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
3096 customPalettePositionSelection(panel, x, y);
3098 else
3099 customPalettePositionSelectionOutBounds(panel, x, y);
3101 break;
3106 static void
3107 customPaletteMenuCallback(WMWidget *w, void *data)
3109 W_ColorPanel *panel = (W_ColorPanel*)data;
3110 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
3112 switch (item) {
3113 case CPmenuNewFromFile:
3114 customPaletteMenuNewFromFile(panel);
3115 break;
3116 case CPmenuRename:
3117 customPaletteMenuRename(panel);
3118 break;
3119 case CPmenuRemove:
3120 customPaletteMenuRemove(panel);
3121 break;
3122 case CPmenuCopy:
3123 break;
3124 case CPmenuNewFromClipboard:
3125 break;
3130 static void
3131 customPaletteMenuNewFromFile(W_ColorPanel *panel)
3133 W_Screen *scr = WMWidgetScreen(panel->win);
3134 WMOpenPanel *browseP;
3135 char *filepath;
3136 char *filename = NULL;
3137 char *spath;
3138 char *tmp;
3139 int i;
3140 RImage *tmpImg = NULL;
3142 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
3143 spath = wexpandpath(wgethomedir());
3144 else
3145 spath = wexpandpath(panel->lastBrowseDir);
3147 browseP = WMGetOpenPanel(scr);
3148 WMSetFilePanelCanChooseDirectories(browseP, 0);
3149 WMSetFilePanelCanChooseFiles(browseP, 1);
3151 /* Get a filename */
3152 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3153 "Open Palette", RSupportedFileFormats()) ) {
3154 filepath = WMGetFilePanelFileName(browseP);
3156 /* Get seperation position between path and filename */
3157 i = strrchr(filepath, '/') - filepath + 1;
3158 if (i > strlen(filepath))
3159 i = strlen(filepath);
3161 /* Store last browsed path */
3162 if (panel->lastBrowseDir)
3163 wfree(panel->lastBrowseDir);
3164 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
3165 strncpy(panel->lastBrowseDir, filepath, i);
3166 panel->lastBrowseDir[i] = '\0';
3168 /* Get filename from path */
3169 filename = wstrdup(filepath + i);
3171 /* Check for duplicate files, and rename it if there are any */
3172 tmp = wstrconcat(panel->configurationPath, filename);
3173 while (access (tmp, F_OK) == 0) {
3174 char *newName;
3176 wfree(tmp);
3178 newName = generateNewFilename(filename);
3179 wfree(filename);
3180 filename = newName;
3182 tmp = wstrconcat(panel->configurationPath, filename);
3184 wfree(tmp);
3186 /* Copy image to $(gnustepdir)/Library/Colors/ &
3187 * Add filename to history menu */
3188 if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
3190 /* filepath is a "local" path now the file has been copied */
3191 wfree(filepath);
3192 filepath = wstrconcat(panel->configurationPath, filename);
3194 /* load the image & add menu entries */
3195 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3196 if (tmpImg) {
3197 if (panel->customPaletteImg)
3198 RDestroyImage(panel->customPaletteImg);
3199 panel->customPaletteImg = tmpImg;
3201 customSetPalette(panel);
3202 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3204 panel->currentPalette = WMGetPopUpButtonNumberOfItems(
3205 panel->customPaletteHistoryBtn)-1;
3207 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3208 panel->currentPalette);
3210 } else {
3211 tmp = wstrconcat(panel->configurationPath, filename);
3213 i = remove(tmp); /* Delete the file, it doesn't belong here */
3214 WMRunAlertPanel(scr, panel->win, "File Error",
3215 "Invalid file format !", "OK", NULL, NULL);
3216 if (i != 0) {
3217 wsyserror("can't remove file %s", tmp);
3218 WMRunAlertPanel(scr, panel->win, "File Error",
3219 "Couldn't remove file from Configuration Directory !",
3220 "OK", NULL, NULL);
3222 wfree(tmp);
3224 wfree(filepath);
3225 wfree(filename);
3227 WMFreeFilePanel(browseP);
3229 wfree(spath);
3233 static void
3234 customPaletteMenuRename(W_ColorPanel *panel)
3236 W_Screen *scr = WMWidgetScreen(panel->win);
3237 char *toName = NULL;
3238 char *fromName;
3239 char *toPath, *fromPath;
3240 int item;
3241 int index;
3243 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3244 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3246 toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
3247 fromName, "OK", "Cancel");
3249 if (toName) {
3251 /* As some people do certain stupid things... */
3252 if (strcmp(toName, fromName) == 0) {
3253 wfree(toName);
3254 return;
3257 /* For normal people */
3258 fromPath = wstrconcat(panel->configurationPath, fromName);
3259 toPath = wstrconcat(panel->configurationPath, toName);
3261 if (access (toPath, F_OK) == 0) {
3262 /* Careful, this palette exists already */
3263 if (WMRunAlertPanel(scr, panel->win, "Warning",
3264 "Palette already exists !\n\nOverwrite ?", "No", "Yes",
3265 NULL) == 1) {
3266 /* "No" = 0, "Yes" = 1 */
3267 int items = WMGetPopUpButtonNumberOfItems(
3268 panel->customPaletteHistoryBtn);
3270 remove(toPath);
3272 /* Remove from History list too */
3273 index = 1;
3274 while ((index < items) && (strcmp(WMGetPopUpButtonItem(
3275 panel->customPaletteHistoryBtn, index),
3276 toName) != 0 ))
3277 index++;
3279 if (index < items) {
3280 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
3281 index);
3282 if (index < item)
3283 item--;
3286 } else {
3287 wfree(fromPath);
3288 wfree(toName);
3289 wfree(toPath);
3291 return;
3295 if ( rename(fromPath, toPath) != 0)
3296 wsyserror("Couldn't rename palette %s to %s\n", fromName, toName);
3297 else {
3298 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3299 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
3300 toName);
3302 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3304 wfree(fromPath);
3305 wfree(toPath);
3306 wfree(toName);
3311 static void
3312 customPaletteMenuRemove(W_ColorPanel *panel)
3314 W_Screen *scr = WMWidgetScreen(panel->win);
3315 char *text;
3316 char *tmp;
3317 int choice;
3318 int item;
3320 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3322 tmp = wstrconcat( "This will permanently remove the palette ",
3323 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3324 text = wstrconcat( tmp,
3325 ".\n\nAre you sure you want to remove this palette ?");
3326 wfree(tmp);
3328 choice = WMRunAlertPanel(scr, panel->win, "Remove", text, "Yes", "No",
3329 NULL);
3330 /* returns 0 (= "Yes") or 1 (="No") */
3331 wfree(text);
3333 if (choice == 0) {
3335 tmp = wstrconcat(panel->configurationPath,
3336 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
3338 if ( remove(tmp) == 0) {
3339 /* item-1 always exists */
3340 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3341 item-1);
3343 customPaletteHistoryCallback(panel->customPaletteHistoryBtn,
3344 panel);
3345 customSetPalette(panel);
3347 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3349 } else {
3350 wsyserror("Couldn't remove palette %s\n", tmp);
3353 wfree(tmp);
3358 static void
3359 customPaletteHistoryCallback(WMWidget *w, void *data)
3361 W_ColorPanel *panel = (W_ColorPanel*)data;
3362 W_Screen *scr = WMWidgetScreen(panel->win);
3363 int item;
3364 char *filename;
3365 RImage *tmp = NULL;
3366 unsigned char perm_mask;
3368 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3369 if (item == panel->currentPalette)
3370 return;
3372 if (item == 0) {
3373 customRenderSpectrum(panel);
3375 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3376 False );
3377 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3378 False );
3379 } else {
3380 /* Load file from configpath */
3381 filename = wstrconcat( panel->configurationPath,
3382 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
3384 /* If the file corresponding to the item does not exist,
3385 * remove it from the history list and select the next one.
3387 perm_mask = (access(filename, F_OK) == 0);
3388 if (!perm_mask) {
3389 /* File does not exist */
3390 wfree(filename);
3391 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3392 item-1);
3393 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3394 customPaletteHistoryCallback(w, data);
3395 return;
3398 /* Get the image */
3399 tmp = RLoadImage(scr->rcontext, filename, 0);
3400 if (tmp) {
3401 if (panel->customPaletteImg) {
3402 RDestroyImage(panel->customPaletteImg);
3403 panel->customPaletteImg = NULL;
3405 panel->customPaletteImg = tmp;
3408 /* If the image is not writable, don't allow removing/renaming */
3409 perm_mask = (access(filename, W_OK) == 0);
3410 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
3411 perm_mask);
3412 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
3413 perm_mask);
3415 wfree(filename);
3417 customSetPalette(panel);
3419 panel->currentPalette = item;
3422 /************************* ColorList Panel Functions **********************/
3424 static void
3425 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
3426 int state, WMRect *rect)
3428 int width, height, x, y;
3429 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3430 WMScreen *scr = WMWidgetScreen(lPtr);
3431 Display *dpy = WMScreenDisplay(scr);
3432 W_ColorPanel *panel = WMGetHangedData(lPtr);
3433 WMColor *white = WMWhiteColor(scr);
3434 WMColor *black = WMBlackColor(scr);
3435 WMColor *fillColor;
3437 width = rect->size.width;
3438 height = rect->size.height;
3439 x = rect->pos.x;
3440 y = rect->pos.y;
3442 if (state & WLDSSelected)
3443 WMPaintColorSwatch(white, d, x +15, y, width -15, height);
3444 else
3445 XClearArea(dpy, d, x +15, y, width -15, height, False);
3447 fillColor = WMCreateRGBColor(scr, color.red*256, color.green*256,
3448 color.blue*256, False);
3450 WMSetColorInGC(fillColor, WMColorGC(fillColor));
3451 WMPaintColorSwatch(fillColor, d, x, y, 15, 15);
3452 WMReleaseColor(fillColor);
3454 WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
3455 strlen(text));
3457 WMReleaseColor(white);
3458 WMReleaseColor(black);
3462 static void
3463 colorListSelect(WMWidget *w, void *data)
3465 W_ColorPanel *panel = (W_ColorPanel *)data;
3466 CPColor cpColor;
3468 cpColor.rgb = *((RColor *)WMGetListSelectedItem(w)->clientData);
3469 cpColor.set = cpRGB;
3471 panel->lastChanged = WMColorListModeColorPanel;
3472 updateSwatch(panel, cpColor);
3476 static void
3477 colorListColorMenuCallback(WMWidget *w, void *data)
3479 W_ColorPanel *panel = (W_ColorPanel *)data;
3480 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3482 switch (item) {
3483 case CLmenuAdd:
3484 break;
3485 case CLmenuRename:
3486 break;
3487 case CLmenuRemove:
3488 break;
3493 static void
3494 colorListListMenuCallback(WMWidget *w, void *data)
3496 W_ColorPanel *panel = (W_ColorPanel *)data;
3497 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3499 switch (item) {
3500 case CLmenuAdd:
3501 /* New Color List */
3502 colorListListMenuNew(panel);
3503 break;
3504 case CLmenuRename:
3505 break;
3506 case CLmenuRemove:
3507 break;
3512 static void
3513 colorListListMenuNew(W_ColorPanel *panel)
3519 /*************** Panel Initialisation Functions *****************/
3521 static void
3522 wheelInit(W_ColorPanel *panel)
3524 CPColor cpColor;
3526 if (panel->color.set != cpHSV)
3527 convertCPColor(&panel->color);
3529 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3531 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3532 (1 + ( panel->color.hsv.saturation/255.0) *
3533 cos( panel->color.hsv.hue * M_PI/180.0)));
3534 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3535 (1 + ( panel->color.hsv.saturation/255.0) *
3536 sin(- panel->color.hsv.hue*M_PI/180.0)));
3538 wheelCalculateValues(panel, panel->color.hsv.value);
3540 cpColor = panel->color;
3541 cpColor.hsv.value = 255;
3542 cpColor.set = cpHSV;
3543 wheelUpdateBrightnessGradient(panel, cpColor);
3547 static void
3548 grayInit(W_ColorPanel *panel)
3550 int value;
3551 char tmp[4];
3553 if (panel->color.set != cpHSV)
3554 convertCPColor(&panel->color);
3556 value = rint(panel->color.hsv.value/2.55);
3557 WMSetSliderValue(panel->grayBrightnessS, value);
3559 sprintf(tmp, "%d", value);
3560 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3564 static void
3565 rgbInit(W_ColorPanel *panel)
3567 char tmp[4];
3569 if (panel->color.set != cpRGB)
3570 convertCPColor(&panel->color);
3572 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3573 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3574 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3576 sprintf(tmp, "%d", panel->color.rgb.red);
3577 WMSetTextFieldText(panel->rgbRedT, tmp);
3578 sprintf(tmp, "%d", panel->color.rgb.green);
3579 WMSetTextFieldText(panel->rgbGreenT, tmp);
3580 sprintf(tmp, "%d", panel->color.rgb.blue);
3581 WMSetTextFieldText(panel->rgbBlueT, tmp);
3585 static void
3586 cmykInit(W_ColorPanel *panel)
3588 int value[3];
3589 char tmp[4];
3591 if (panel->color.set != cpRGB)
3592 convertCPColor(&panel->color);
3594 value[0] = rint((255-panel->color.rgb.red)/2.55);
3595 value[1] = rint((255-panel->color.rgb.green)/2.55);
3596 value[2] = rint((255-panel->color.rgb.blue)/2.55);
3598 WMSetSliderValue(panel->cmykCyanS, value[0]);
3599 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3600 WMSetSliderValue(panel->cmykYellowS, value[2]);
3601 WMSetSliderValue(panel->cmykBlackS, 0);
3603 sprintf(tmp, "%d", value[0]);
3604 WMSetTextFieldText(panel->cmykCyanT, tmp);
3605 sprintf(tmp, "%d", value[1]);
3606 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3607 sprintf(tmp, "%d", value[2]);
3608 WMSetTextFieldText(panel->cmykYellowT, tmp);
3609 WMSetTextFieldText(panel->cmykBlackT, "0");
3613 static void
3614 hsbInit(W_ColorPanel *panel)
3616 int value[3];
3617 char tmp[4];
3619 if (panel->color.set != cpHSV)
3620 convertCPColor(&panel->color);
3622 value[0] = panel->color.hsv.hue;
3623 value[1] = rint(panel->color.hsv.saturation/2.55);
3624 value[2] = rint(panel->color.hsv.value/2.55);
3626 WMSetSliderValue(panel->hsbHueS,value[0]);
3627 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3628 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3630 sprintf(tmp, "%d", value[0]);
3631 WMSetTextFieldText(panel->hsbHueT, tmp);
3632 sprintf(tmp, "%d", value[1]);
3633 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3634 sprintf(tmp, "%d", value[2]);
3635 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3637 hsbUpdateBrightnessGradient(panel);
3638 hsbUpdateSaturationGradient(panel);
3639 hsbUpdateHueGradient(panel);
3644 /************************** Common utility functions ************************/
3646 static int
3647 fetchFile(char *toPath, char *srcFile, char *destFile)
3649 int src, dest;
3650 int n;
3651 char *tmp;
3652 char buf[BUFSIZE];
3654 if ((src = open(srcFile, O_RDONLY)) == 0) {
3655 wsyserror("Could not open %s", srcFile);
3656 return -1;
3659 tmp = wstrconcat(toPath, destFile);
3660 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
3661 == 0) {
3662 wsyserror("Could not create %s", tmp);
3663 wfree(tmp);
3664 return -1;
3666 wfree(tmp);
3669 /* Copy the file */
3670 while ((n = read(src, buf, BUFSIZE)) > 0)
3672 if (write (dest, buf, n) != n) {
3673 wsyserror("Write error on file %s", destFile);
3674 return -1;
3678 return 0;
3682 char*
3683 generateNewFilename(char *curName)
3685 int n;
3686 char c;
3687 int baseLen;
3688 char *ptr;
3689 char *newName;
3692 assert(curName);
3694 ptr = curName;
3696 if (((ptr = strrchr(ptr, '{'))==0) || sscanf(ptr, "{%i}%c", &n, &c)!=1)
3697 return wstrconcat(curName, " {1}");
3699 baseLen = ptr - curName -1;
3701 newName = wmalloc(baseLen + 16);
3702 strncpy(newName, curName, baseLen);
3703 newName[baseLen] = 0;
3705 sprintf(&newName[baseLen], " {%i}", n+1);
3707 return newName;
3711 void
3712 convertCPColor(CPColor *color)
3714 unsigned short old_hue = 0;
3716 switch (color->set) {
3717 case cpNone:
3718 wwarning("Color Panel: Color unspecified");
3719 return;
3720 case cpRGB:
3721 old_hue = color->hsv.hue;
3722 RRGBtoHSV(&(color->rgb), &(color->hsv));
3724 /* In black the hue is undefined, and may change by conversion
3725 * Same for white. */
3726 if (
3727 ((color->rgb.red == 0) &&
3728 (color->rgb.green == 0) &&
3729 (color->rgb.blue == 0)) ||
3730 ((color->rgb.red == 0) &&
3731 (color->rgb.green == 0) &&
3732 (color->rgb.blue == 255))
3734 color->hsv.hue = old_hue;
3735 break;
3736 case cpHSV:
3737 RHSVtoRGB(&(color->hsv), &(color->rgb));
3738 break;
3743 #define ABS_SHIFT(val, shift) \
3744 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
3746 RColor
3747 ulongToRColor(WMScreen *scr, unsigned long value)
3749 RColor color;
3750 XColor *xcolor = NULL;
3752 if (!(xcolor = wmalloc(sizeof(XColor)) )) {
3753 wwarning(NO_MEMORY_ERR);
3754 color.red = 0;
3755 color.green = 0;
3756 color.blue = 0;
3757 return color;
3760 xcolor->pixel = value;
3761 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3763 color.red = xcolor->red >> 8;
3764 color.green = xcolor->green >> 8;
3765 color.blue = xcolor->blue >> 8;
3767 wfree(xcolor);
3769 return color;
3773 unsigned char
3774 getShift(unsigned char value)
3776 unsigned char i = -1;
3778 if (value == 0)
3779 return 0;
3781 while (value) {
3782 value >>= 1;
3783 i++;
3786 return i;
3791 #ifdef SHAPE_WAS_DEFINED
3792 #undef SHAPE_WAS_DEFINED
3793 #define SHAPE
3794 #endif