1 
2 /* +-------------------------------------------------------------------+ */
3 /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
4 /* | Copyright 1995, 1996 Torsten Martinsen (bullestock@dk-online.dk)  | */
5 /* |                                                                   | */
6 /* | Permission to use, copy, modify, and to distribute this software  | */
7 /* | and its documentation for any purpose is hereby granted without   | */
8 /* | fee, provided that the above copyright notice appear in all       | */
9 /* | copies and that both that copyright notice and this permission    | */
10 /* | notice appear in supporting documentation.  There is no           | */
11 /* | representations about the suitability of this software for        | */
12 /* | any purpose.  this software is provided "as is" without express   | */
13 /* | or implied warranty.                                              | */
14 /* |                                                                   | */
15 /* +-------------------------------------------------------------------+ */
16 
17 /* $Id: chroma.c,v 1.17 2005/03/20 20:15:32 demailly Exp $ */
18 
19 #include <X11/Intrinsic.h>
20 #include <X11/StringDefs.h>
21 #include <X11/cursorfont.h>
22 
23 #include "xaw_incdir/Form.h"
24 #include "xaw_incdir/AsciiText.h"
25 #include "xaw_incdir/Toggle.h"
26 #undef NeedFunctionPrototypes
27 #define NeedFunctionPrototypes 1
28 #undef NeedWidePrototypes
29 #include "xaw_incdir/Scrollbar.h"
30 #include "xaw_incdir/Command.h"
31 
32 
33 #include <X11/Shell.h>
34 #include <X11/keysym.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 
38 #include "xpaint.h"
39 #include "Paint.h"
40 #include "protocol.h"
41 #include "palette.h"
42 #include "color.h"
43 #include "messages.h"
44 #include "misc.h"
45 #include "operation.h"
46 #include "ops.h"
47 
48 
49 static unsigned char backgroundRGB[3] =
50 {255, 255, 255};
51 static unsigned char varianceRGB[3] =
52 {0, 0, 0};
53 
54 /*
55 **  Dialog box
56  */
57 typedef struct {
58     Widget redBar, greenBar, blueBar;
59     Widget redText, greenText, blueText;
60     Widget mode;		/* Only used if RANGEBUTTONS is defined */
61     Widget shell;		/* Used for XtPopup() */
62     Widget cpick;		/* The ColorPicker's Form widget */
63     Palette *map;		/* Current palette */
64     float r, g, b;
65     float vr, vg, vb;
66     Pixel pixel;
67 } DialogInfo;
68 
69 static DialogInfo *dInfo = NULL;
70 
71 static void
closeCallback(Widget w,XtPointer infoArg,XtPointer junk2)72 closeCallback(Widget w, XtPointer infoArg, XtPointer junk2)
73 {
74     DialogInfo *dInfo = (DialogInfo *) infoArg;
75 
76     XtDestroyWidget(dInfo->shell);
77     XtFree((XtPointer) dInfo);
78     /* XtPopdown(dInfo->shell); */ /* popping down is not enough - ACZ */
79 }
80 
81 static void
barCB(Widget bar,DialogInfo * l,float * percent)82 barCB(Widget bar, DialogInfo * l, float *percent)
83 {
84     Widget t;
85     char buf[20];
86 
87     if (l->redBar == bar) {
88 	l->vr = *percent;
89 	t = l->redText;
90     } else if (l->greenBar == bar) {
91 	l->vg = *percent;
92 	t = l->greenText;
93     } else if (l->blueBar == bar) {
94 	l->vb = *percent;
95 	t = l->blueText;
96     } else {
97 	return;
98     }
99     sprintf(buf, "%d", (int) (255 * *percent));
100     XtVaSetValues(t, XtNstring, buf, NULL);
101 }
102 
103 static void
scrollCB(Widget bar,DialogInfo * l,XtPointer position)104 scrollCB(Widget bar, DialogInfo * l, XtPointer position)
105 {
106     Widget t;
107     float *percent;
108     char buf[20];
109 
110     if (l->redBar == bar) {
111         percent = &l->vr;
112 	t = l->redText;
113     } else if (l->greenBar == bar) {
114         percent = &l->vg;
115 	t = l->greenText;
116     } else if (l->blueBar == bar) {
117         percent = &l->vb;
118 	t = l->blueText;
119     } else {
120 	return;
121     }
122 
123     if ((long)position>0)
124         *percent += 1.0/256.0;
125     else
126         *percent -= 1.0/256.0;
127 
128     if (*percent<0) *percent = 0;
129     /* This should avoid values being rounded below 255, as well
130        as above 256... */
131     if (*percent>0.99999) *percent = 1.00001;
132 
133     sprintf(buf, "%d", (int) (255 * (*percent)));
134     XtVaSetValues(t, XtNstring, buf, NULL);
135     XawScrollbarSetThumb(bar, *percent, -1.0);
136 }
137 
138 static void
textAction(Widget w,XEvent * event,String * prms,Cardinal * nprms)139 textAction(Widget w, XEvent * event, String * prms, Cardinal * nprms)
140 {
141     String val;
142     int v;
143     char buf[20];
144 
145     XtVaGetValues(w, XtNstring, &val, NULL);
146     v = atoi(val);
147     if (v > 255) {
148 	v = 255;
149 	XtVaSetValues(w, XtNstring, "255", NULL);
150     }
151     if (v < 0) {
152 	v = 0;
153 	XtVaSetValues(w, XtNstring, "0", NULL);
154     }
155     sprintf(buf, "%d", v);
156 
157     if (w == dInfo->redText) {
158 	dInfo->vr = v / 255.0;
159 	XawScrollbarSetThumb(dInfo->redBar, dInfo->vr, -1.0);
160 	XtVaSetValues(dInfo->redText, XtNstring, buf, NULL);
161     }
162     if (w == dInfo->greenText) {
163 	dInfo->vg = v / 255.0;
164 	XawScrollbarSetThumb(dInfo->greenBar, dInfo->vg, -1.0);
165 	XtVaSetValues(dInfo->greenText, XtNstring, buf, NULL);
166     }
167     if (w == dInfo->blueText) {
168 	dInfo->vb = v / 255.0;
169 	XawScrollbarSetThumb(dInfo->blueBar, dInfo->vb, -1.0);
170 	XtVaSetValues(dInfo->blueText, XtNstring, buf, NULL);
171     }
172 }
173 
174 /*
175  * Add a Form containing a Label, Scrollbar and TextWidget.
176  * Return the Form widget, and store the Scrollbar and TextWidgets in 'bar'
177  * and 'text'.  'title' is the Label title.
178  */
179 static Widget
addSB(Widget parent,Widget above,DialogInfo * l,int mode)180 addSB(Widget parent, Widget above, DialogInfo * l, int mode)
181 {
182     Widget form, label, *text = NULL, *bar = NULL;
183     static String textTranslations =
184     "#override\n\
185 	<Key>Return: delta-text-ok()\n\
186 	<Key>Linefeed: delta-text-ok()\n\
187 	Ctrl<Key>M: delta-text-ok()\n\
188 	Ctrl<Key>J: delta-text-ok()\n";
189     static XtTranslations trans = None;
190 
191     if (mode == RED_VARIANCE) {
192         bar = &l->redBar;
193         text = &l->redText;
194     }
195     if (mode == GREEN_VARIANCE) {
196         bar = &l->greenBar;
197         text = &l->greenText;
198     }
199     if (mode == BLUE_VARIANCE) {
200         bar = &l->blueBar;
201         text = &l->blueText;
202     }
203     if (trans == None) {
204 	static XtActionsRec act =
205 	{"delta-text-ok", (XtActionProc) textAction};
206 
207 	XtAppAddActions(XtWidgetToApplicationContext(parent), &act, 1);
208 
209 	trans = XtParseTranslationTable(textTranslations);
210     }
211     form = XtVaCreateManagedWidget("form", formWidgetClass, parent,
212 				   XtNborderWidth, 0,
213 				   XtNfromVert, above,
214 				   NULL);
215     label = XtVaCreateManagedWidget("varianceLabel", labelWidgetClass, form,
216 				    XtNlabel, msgText[mode],
217 				    XtNborderWidth, 0,
218 				    XtNright, XtChainLeft,
219 				    XtNleft, XtChainLeft,
220 				    NULL);
221     *bar = XtVaCreateManagedWidget("varianceBar", scrollbarWidgetClass, form,
222 				   XtNorientation, XtorientHorizontal,
223 #if defined(XAW3D) || defined(XAW95)
224 				   XtNwidth, 236,
225 #else
226 				   XtNwidth, 192,
227 #endif
228 				   XtNfromHoriz, label,
229 				   XtNleft, XtChainLeft,
230 				   NULL);
231 
232     *text = XtVaCreateManagedWidget("varianceText", asciiTextWidgetClass, form,
233 				    XtNfromHoriz, *bar,
234 				    XtNeditType, XawtextEdit,
235 				    XtNwrap, XawtextWrapNever,
236 				    XtNresize, XawtextResizeWidth,
237 				    XtNtranslations, trans,
238 				    XtNwidth, 50,
239 				    XtNlength, 5,
240 				    XtNstring, "0",
241 				    NULL);
242 
243     XtAddCallback(*bar, XtNjumpProc,
244                   (XtCallbackProc) barCB, (XtPointer) l);
245     XtAddCallback(*bar, XtNscrollProc,
246                   (XtCallbackProc) scrollCB, (XtPointer) l);
247 
248     XtAddEventHandler(*text,
249                       ButtonPressMask|ButtonReleaseMask, False,
250                       (XtEventHandler) clickFocusCallback, NULL);
251     return form;
252 }
253 
254 static void
deltaSP(Widget form,XtPointer data,XtPointer p)255 deltaSP(Widget form, XtPointer data, XtPointer p)
256 {
257     ((DialogInfo *) data)->pixel = (Pixel) p;
258 }
259 
260 /*
261  * Callback for the 'Pixel Delta' button.
262  * Grab a colour and calculate the delta relative to the background colour.
263  */
264 static void
deltaCB(Widget w,DialogInfo * l,XtPointer junk)265 deltaCB(Widget w, DialogInfo * l, XtPointer junk)
266 {
267     XColor *xcol, xcol2;
268     int dr, dg, db;
269     char buf[20];
270 
271     xcol = DoGrabColor(w);
272 
273     xcol2.pixel = l->pixel;
274     XQueryColor(XtDisplay(w), l->map->cmap, &xcol2);
275 
276     dr = xcol->red - xcol2.red;
277     dg = xcol->green - xcol2.green;
278     db = xcol->blue - xcol2.blue;
279     if (dr < 0)
280 	dr = -dr;
281     if (dg < 0)
282 	dg = -dg;
283     if (db < 0)
284 	db = -db;
285 
286     l->vr = (float) ((dr >> 8) & 0xff) / 255.0;
287     l->vg = (float) ((dg >> 8) & 0xff) / 255.0;
288     l->vb = (float) ((db >> 8) & 0xff) / 255.0;
289 
290     sprintf(buf, "%d", (int) (255 * l->vr));
291     XtVaSetValues(l->redText, XtNstring, buf, NULL);
292     XawScrollbarSetThumb(l->redBar, l->vr, -1.0);
293     sprintf(buf, "%d", (int) (255 * l->vg));
294     XtVaSetValues(l->greenText, XtNstring, buf, NULL);
295     XawScrollbarSetThumb(l->greenBar, l->vg, -1.0);
296     sprintf(buf, "%d", (int) (255 * l->vb));
297     XtVaSetValues(l->blueText, XtNstring, buf, NULL);
298     XawScrollbarSetThumb(l->blueBar, l->vb, -1.0);
299 }
300 
301 static void
applyCB(Widget w,DialogInfo * l,XtPointer junk)302 applyCB(Widget w, DialogInfo * l, XtPointer junk)
303 {
304     XColor xcol;
305     int t;
306 
307     xcol.pixel = l->pixel;
308     xcol.flags = DoRed | DoGreen | DoBlue;
309     XQueryColor(XtDisplay(w), l->map->cmap, &xcol);
310 
311     backgroundRGB[0] = (xcol.red >> 8) & 0xff;
312     backgroundRGB[1] = (xcol.green >> 8) & 0xff;
313     backgroundRGB[2] = (xcol.blue >> 8) & 0xff;
314 
315 #define STUFF(src, dst) \
316 	t = (src) * 255.0; if (t < 0) t = 0; else if (t > 255) t = 255; dst = t
317 
318     STUFF(l->vr, varianceRGB[0]);
319     STUFF(l->vg, varianceRGB[1]);
320     STUFF(l->vb, varianceRGB[2]);
321 
322 #undef STUFF
323 
324 #if RANGEBUTTONS
325     t = ((int) XawToggleGetCurrent(l->mode)) - 1;
326     OperationSelectCall(t);
327 #endif
328 }
329 
330 void
ChromaDialog(Widget w,Palette * map)331 ChromaDialog(Widget w, Palette * map)
332 {
333     Widget topform, form, cpick, apply, cancel;
334     Widget above;
335     DialogInfo *l = dInfo;
336     Arg args[4];
337     int nargs = 0;
338     XColor xcol;
339     char buf[20];
340 
341 #if RANGEBUTTONS
342     Widget label, tog;
343     int cutmode = SelectGetCutMode();
344 #endif
345 
346 #if 0
347     if (l != NULL && l->shell != None) {
348 #if RANGEBUTTONS
349 	XawToggleSetCurrent(l->mode, (XtPointer) (cutmode + 1));
350 #endif
351 	/*
352 	 * If the canvas has another colour map than the ColorPicker,
353 	 * update the ColorPicker's map (unless it is a TrueColor map)
354 	 */
355 	if ((map != l->map) && (l->map->isMapped)) {
356 	    ColorPickerUpdateMap(l->cpick, map);
357 	    l->map = map;
358 	    XtVaSetValues(l->shell, XtNcolormap, map->cmap, NULL);
359 	}
360 	XtPopup(l->shell, XtGrabNone);
361 	RaiseWindow(XtDisplay(l->shell), XtWindow(l->shell));
362 	return;
363     }
364 #endif
365     dInfo = l = XtNew(DialogInfo);
366 
367     l->map = map;
368 
369     l->r = (float) backgroundRGB[0] / 255.0;
370     l->g = (float) backgroundRGB[1] / 255.0;
371     l->b = (float) backgroundRGB[2] / 255.0;
372     l->vr = (float) varianceRGB[0] / 255.0;
373     l->vg = (float) varianceRGB[1] / 255.0;
374     l->vb = (float) varianceRGB[2] / 255.0;
375 
376     XtSetArg(args[nargs], XtNcolormap, map->cmap); nargs++;
377 
378     l->shell = XtVisCreatePopupShell("chroma", topLevelShellWidgetClass,
379 				     GetToplevel(w),
380 				     args, nargs);
381 
382     topform = XtVaCreateManagedWidget("form", formWidgetClass, l->shell,
383 				      NULL);
384 
385     /*
386     **  First create the list of toggle buttons for the mode selection
387      */
388 #if RANGEBUTTONS
389     form = XtVaCreateManagedWidget("form", formWidgetClass, topform,
390 				   XtNborderWidth, 0,
391 				   NULL);
392 
393     label = XtVaCreateManagedWidget("selectModeLabel", labelWidgetClass, form,
394 				    XtNborderWidth, 0,
395 				    NULL);
396 
397     /*
398     **  radioData = mode + 1
399      */
400     tog = None;
401     tog = XtVaCreateManagedWidget("mode0", toggleWidgetClass, form,
402 				  XtNfromVert, label,
403 				  XtNradioGroup, tog,
404 				  XtNradioData, 1,
405 				  XtNstate, (cutmode == 0),
406 				  NULL);
407     tog = XtVaCreateManagedWidget("mode1", toggleWidgetClass, form,
408 				  XtNfromVert, tog,
409 				  XtNradioGroup, tog,
410 				  XtNradioData, 2,
411 				  XtNstate, (cutmode == 1),
412 				  NULL);
413     tog = XtVaCreateManagedWidget("mode2", toggleWidgetClass, form,
414 				  XtNfromVert, tog,
415 				  XtNradioGroup, tog,
416 				  XtNradioData, 3,
417 				  XtNstate, (cutmode == 2),
418 				  NULL);
419     l->mode = tog;
420 #else
421     l->mode = None;
422 #endif
423 
424     /*
425     **  Now the color chooser.
426      */
427     form = XtVaCreateManagedWidget("form", formWidgetClass, topform,
428 #if RANGEBUTTONS
429 				   XtNfromHoriz, form,
430 #endif
431 				   XtNborderWidth, 0,
432 				   NULL);
433 
434     xcol.red   = 65535 * l->r;
435     xcol.green = 65535 * l->g;
436     xcol.blue  = 65535 * l->b;
437     l->cpick = cpick = ColorPickerPalette(form, map, NULL);
438     ColorPickerSetXColor(cpick, &xcol);
439     l->pixel = ColorPickerGetPixel(cpick);
440 
441     above = XtVaCreateManagedWidget("delta", commandWidgetClass, form,
442 				    XtNfromVert, cpick,
443 				    NULL);
444     XtAddCallback(above, XtNcallback, (XtCallbackProc) deltaCB, (XtPointer) l);
445     ColorPickerSetFunction(cpick, deltaSP, (XtPointer) l);
446 
447     above = addSB(form, above, l, RED_VARIANCE);
448     above = addSB(form, above, l, GREEN_VARIANCE);
449     above = addSB(form, above, l, BLUE_VARIANCE);
450     XawScrollbarSetThumb(l->redBar, l->vr, -1.0);
451     XawScrollbarSetThumb(l->greenBar, l->vg, -1.0);
452     XawScrollbarSetThumb(l->blueBar, l->vb, -1.0);
453     sprintf(buf, "%d", (int) (255 * l->vr));
454     XtVaSetValues(l->redText, XtNstring, buf, NULL);
455     sprintf(buf, "%d", (int) (255 * l->vg));
456     XtVaSetValues(l->greenText, XtNstring, buf, NULL);
457     sprintf(buf, "%d", (int) (255 * l->vb));
458     XtVaSetValues(l->blueText, XtNstring, buf, NULL);
459 
460     AddDestroyCallback(l->shell, (DestroyCallbackFunc) closeCallback,
461 		       (XtPointer) l);
462 
463     apply = XtVaCreateManagedWidget("apply", commandWidgetClass, form,
464 				    XtNfromVert, above,
465 				    NULL);
466     cancel = XtVaCreateManagedWidget("cancel", commandWidgetClass, form,
467 				     XtNfromVert, above,
468 				     XtNfromHoriz, apply,
469 				     NULL);
470     XtAddCallback(cancel, XtNcallback, (XtCallbackProc) closeCallback,
471 		  (XtPointer) l);
472     XtAddCallback(apply, XtNcallback, (XtCallbackProc) applyCB, (XtPointer) l);
473 
474     XtPopup(l->shell, XtGrabNone);
475     if (cpick) {
476         XtUnmanageChild(cpick);
477         XMapWindow(XtDisplay(cpick), XtWindow(cpick));
478     }
479     XtUnmanageChild(above);
480     XtUnmanageChild(l->redBar);
481     XtUnmanageChild(l->greenBar);
482     XtUnmanageChild(l->blueBar);
483     XtUnmanageChild(apply);
484     XtUnmanageChild(cancel);
485     XMapWindow(XtDisplay(above), XtWindow(above));
486     XMapWindow(XtDisplay(l->redBar), XtWindow(l->redBar));
487     XMapWindow(XtDisplay(l->greenBar), XtWindow(l->greenBar));
488     XMapWindow(XtDisplay(l->blueBar), XtWindow(l->blueBar));
489     XMapWindow(XtDisplay(apply), XtWindow(apply));
490     XMapWindow(XtDisplay(cancel), XtWindow(cancel));
491 
492     XtUnmanageChild(form);
493     XMapWindow(XtDisplay(form), XtWindow(form));
494     XtSetMinSizeHints(l->shell, 186, 138);
495 }
496 
497 #if RANGEBUTTONS
498 void
ChromaSetCutMode(int value)499 ChromaSetCutMode(int value)
500 {
501     if (dInfo != NULL)
502 	XawToggleSetCurrent(dInfo->mode, (XtPointer) (value + 1));
503 }
504 #endif
505 
506 void
GetChromaBackground(int * rb,int * gb,int * bb)507 GetChromaBackground(int *rb, int *gb, int *bb)
508 {
509     *rb = backgroundRGB[0];
510     *gb = backgroundRGB[1];
511     *bb = backgroundRGB[2];
512 }
513 
514 void
GetChromaDelta(int * rd,int * gd,int * bd)515 GetChromaDelta(int *rd, int *gd, int *bd)
516 {
517     *rd = varianceRGB[0];
518     *gd = varianceRGB[1];
519     *bd = varianceRGB[2];
520 }
521