1 /*
2 * Motif
3 *
4 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5 *
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 /************************************************************
26 * INCLUDE FILES
27 ************************************************************/
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35
36 #include "ColorSP.h"
37
38 #include <Xm/Xm.h>
39 #include <Xm/VaSimpleP.h>
40
41 #include <Xm/ButtonBox.h>
42 #include <Xm/Scale.h>
43 #include <Xm/ScrolledW.h>
44 #include <Xm/List.h>
45 #include <Xm/RowColumn.h>
46 #include <Xm/ToggleB.h>
47 #include <Xm/Frame.h>
48 #include <Xm/Label.h>
49
50 #include <Xm/ExtP.h>
51 #include "XmI.h"
52
53 /************************************************************
54 * TYPEDEFS AND DEFINES
55 ************************************************************/
56
57 #define SUPERCLASS ((WidgetClass) &xmManagerClassRec)
58
59 #ifndef LIBDIR
60 #define LIBDIR "/usr/local/lib/X11"
61 #endif
62
63 /************************************************************
64 * MACROS
65 ************************************************************/
66
67 /************************************************************
68 * GLOBAL DECLARATIONS
69 ************************************************************/
70
71 extern void XmeNavigChangeManaged(Widget);
72
73 /************************************************************
74 * STATIC FUNCTION DECLARATIONS
75 ************************************************************/
76
77 static void ChangeManaged(Widget w);
78 static void ClassInitialize(void), Destroy(Widget), Resize(Widget);
79 static void ClassPartInitialize(WidgetClass w_class);
80 static void Initialize(Widget, Widget, ArgList, Cardinal *);
81 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
82 static XtGeometryResult GeometryHandler(Widget, XtWidgetGeometry *,
83 XtWidgetGeometry *);
84 static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
85 XtWidgetGeometry *);
86
87 static Boolean UpdateColorWindow(XmColorSelectorWidget, Boolean);
88 static Boolean color_name_changed(XmColorSelectorWidget, char *);
89 static Boolean FindColor(XmColorSelectorWidget, int *);
90 static Boolean CvtStringToColorMode(Display *, XrmValuePtr, Cardinal,
91 XrmValuePtr, XrmValuePtr, XtPointer *);
92 static Boolean DefaultVisualDisplay(XmColorSelectorWidget, Pixel, XColor, char *);
93
94 static void CalcPreferredSize(XmColorSelectorWidget, Dimension *, Dimension *);
95 static void SelectColor(XmColorSelectorWidget);
96 static void slider_changed(Widget, XtPointer, XtPointer);
97 static void list_selected(Widget, XtPointer, XtPointer);
98 static void change_mode(Widget, XtPointer, XtPointer);
99 static void new_mode(XmColorSelectorWidget, XmColorMode);
100 static void compute_size(XmColorSelectorWidget);
101 static void read_rgb_file(XmColorSelectorWidget, ArgList, Cardinal, Boolean);
102 static void SetSliders(XmColorSelectorWidget);
103
104 static void CreateColorSliders(XmColorSelectorWidget, ArgList, Cardinal);
105 static void CreateSelectorRadio(XmColorSelectorWidget, ArgList, Cardinal);
106 static void CreateColorWindow(XmColorSelectorWidget, ArgList, Cardinal);
107 static void NoPrivateColormaps(XmColorSelectorWidget, Pixel, XColor, char *);
108 static void PrivateColormaps(XmColorSelectorWidget, Pixel, XColor, char *);
109
110 #ifdef notdef
111 static void CreateTypes(XmColorSelectorWidget, Widget, ArgList, Cardinal);
112 #endif
113
114 static int CmpColors(const void *, const void *);
115 static char *find_name(char *);
116 static int GetVisual(XmColorSelectorWidget);
117
118 static void GetValues_XmNredSliderLabel ( Widget w, int n, XtArgVal *value) ;
119 static void GetValues_XmNgreenSliderLabel( Widget w, int n, XtArgVal *value) ;
120 static void GetValues_XmNblueSliderLabel( Widget w, int n, XtArgVal *value) ;
121 static void GetValues_XmNcolorListTogLabel( Widget w, int n, XtArgVal *value) ;
122 static void GetValues_XmNsliderTogLabel( Widget w, int n, XtArgVal *value) ;
123 static void GetValues_XmNnoCellError( Widget w, int n, XtArgVal *value) ;
124 static void GetValues_XmNfileReadError( Widget w, int n, XtArgVal *value) ;
125
126 /************************************************************
127 * STATIC DECLARATIONS
128 ************************************************************/
129
130 static XtResource resources[] =
131 {
132 {
133 XmNcolorMode, XmCColorMode, XmRXmColorMode,
134 sizeof(XmColorMode), XtOffsetOf(XmColorSelectorRec, cs.color_mode),
135 XmRImmediate, (XtPointer) XmScaleMode
136 },
137
138 {
139 XmNcolorName, XmCString, XmRString,
140 sizeof(String), XtOffsetOf(XmColorSelectorRec, cs.color_name),
141 XmRString, "White"
142 },
143 #ifdef VMS
144 {
145 XmNrgbFile, XmCString, XmRString,
146 sizeof(String), XtOffsetOf(XmColorSelectorRec, cs.rgb_file),
147 XmRString, (XtPointer) "sys$manager:decw$rgb.dat"
148 },
149 #else
150 {
151 XmNrgbFile, XmCString, XmRString,
152 sizeof(String), XtOffsetOf(XmColorSelectorRec, cs.rgb_file),
153 XmRString, (XtPointer) LIBDIR"/rgb.txt"
154 },
155 #endif
156 {
157 XmNmarginWidth, XmCMargin, XmRHorizontalDimension,
158 sizeof(Dimension), XtOffsetOf(XmColorSelectorRec, cs.margin_width),
159 XmRImmediate, (XtPointer) 2
160 },
161
162 {
163 XmNmarginHeight, XmCMargin, XmRVerticalDimension,
164 sizeof(Dimension), XtOffsetOf(XmColorSelectorRec, cs.margin_height),
165 XmRImmediate, (XtPointer) 2
166 },
167
168 {
169 XmNredSliderLabel, XmCSliderLabel, XmRXmString,
170 sizeof(XmString), XtOffsetOf(XmColorSelectorRec, cs.strings.slider_labels[0]),
171 XmRString, (XtPointer) "Red"
172 },
173
174 {
175 XmNgreenSliderLabel, XmCSliderLabel, XmRXmString,
176 sizeof(XmString), XtOffsetOf(XmColorSelectorRec, cs.strings.slider_labels[1]),
177 XmRString, (XtPointer) "Green"
178 },
179
180 {
181 XmNblueSliderLabel, XmCSliderLabel, XmRXmString,
182 sizeof(XmString), XtOffsetOf(XmColorSelectorRec, cs.strings.slider_labels[2]),
183 XmRString, (XtPointer) "Blue"
184 },
185
186 {
187 XmNcolorListTogLabel, XmCTogLabel, XmRXmString,
188 sizeof(XmString), XtOffsetOf(XmColorSelectorRec, cs.strings.tog_labels[0]),
189 XmRString, (XtPointer) "Color List"
190 },
191
192 {
193 XmNsliderTogLabel, XmCTogLabel, XmRXmString,
194 sizeof(XmString), XtOffsetOf(XmColorSelectorRec, cs.strings.tog_labels[1]),
195 XmRString,(XtPointer)"Color Sliders"
196 },
197
198 {
199 XmNnoCellError, XmCNoCellError, XmRXmString,
200 sizeof(XmString), XtOffsetOf(XmColorSelectorRec, cs.strings.no_cell_error),
201 XmRString, (XtPointer)"\n\nNo Color Cell Available!"
202 },
203
204 {
205 XmNfileReadError, XmCFileReadError, XmRXmString,
206 sizeof(XmString), XtOffsetOf(XmColorSelectorRec, cs.strings.file_read_error),
207 XmRString, (XtPointer)"Could not read rgb.txt file:"
208 }
209 };
210
211 static XmSyntheticResource get_resources[] =
212 {
213 {
214 XmNmarginWidth, sizeof(Dimension),
215 XtOffsetOf(XmColorSelectorRec, cs.margin_width),
216 XmeFromHorizontalPixels, (XmImportProc) XmeToHorizontalPixels
217 },
218
219 {
220 XmNmarginHeight, sizeof(Dimension),
221 XtOffsetOf(XmColorSelectorRec, cs.margin_height),
222 XmeFromVerticalPixels, (XmImportProc) XmeToVerticalPixels
223 },
224
225 {
226 XmNredSliderLabel, sizeof(XmString),
227 XtOffsetOf(XmColorSelectorRec, cs.strings.slider_labels[0]),
228 GetValues_XmNredSliderLabel, NULL
229 },
230
231 {
232 XmNgreenSliderLabel, sizeof(XmString),
233 XtOffsetOf(XmColorSelectorRec, cs.strings.slider_labels[1]),
234 GetValues_XmNgreenSliderLabel, NULL
235 },
236
237 {
238 XmNblueSliderLabel, sizeof(XmString),
239 XtOffsetOf(XmColorSelectorRec, cs.strings.slider_labels[2]),
240 GetValues_XmNblueSliderLabel, NULL
241 },
242
243 {
244 XmNcolorListTogLabel, sizeof(XmString),
245 XtOffsetOf(XmColorSelectorRec, cs.strings.tog_labels[0]),
246 GetValues_XmNcolorListTogLabel, NULL
247 },
248
249 {
250 XmNsliderTogLabel, sizeof(XmString),
251 XtOffsetOf(XmColorSelectorRec, cs.strings.tog_labels[1]),
252 GetValues_XmNsliderTogLabel, NULL
253 },
254
255 {
256 XmNnoCellError, sizeof(XmString),
257 XtOffsetOf(XmColorSelectorRec, cs.strings.no_cell_error),
258 GetValues_XmNnoCellError, NULL
259 },
260
261 {
262 XmNfileReadError, sizeof(XmString),
263 XtOffsetOf(XmColorSelectorRec, cs.strings.file_read_error),
264 GetValues_XmNfileReadError, NULL
265 }
266 };
267
268 XmColorSelectorClassRec xmColorSelectorClassRec = {
269 { /* core fields */
270 /* superclass */ SUPERCLASS,
271 /* class_name */ "XmColorSelector",
272 /* widget_size */ sizeof(XmColorSelectorRec),
273 /* class_initialize */ ClassInitialize,
274 /* class_part_initialize */ ClassPartInitialize,
275 /* class_inited */ False,
276 /* initialize */ Initialize,
277 /* initialize_hook */ NULL,
278 /* realize */ XtInheritRealize,
279 /* actions */ NULL,
280 /* num_actions */ (Cardinal)0,
281 /* resources */ (XtResource*)resources,
282 /* num_resources */ XtNumber(resources),
283 /* xrm_class */ NULLQUARK,
284 /* compress_motion */ True,
285 /* compress_exposure */ True,
286 /* compress_enterleave */ True,
287 /* visible_interest */ False,
288 /* destroy */ Destroy,
289 /* resize */ Resize,
290 /* expose */ NULL,
291 /* set_values */ SetValues,
292 /* set_values_hook */ NULL,
293 /* set_values_almost */ XtInheritSetValuesAlmost,
294 /* get_values_hook */ NULL,
295 /* accept_focus */ NULL,
296 /* version */ XtVersion,
297 /* callback_private */ NULL,
298 /* tm_table */ XtInheritTranslations,
299 /* query_geometry */ (XtGeometryHandler) QueryGeometry,
300 /* display_accelerator */ XtInheritDisplayAccelerator,
301 /* extension */ NULL,
302 },
303 { /* composite_class fields */
304 /* geometry_manager */ GeometryHandler,
305 /* change_managed */ ChangeManaged,
306 /* insert_child */ XtInheritInsertChild,
307 /* delete_child */ XtInheritDeleteChild,
308 /* extension */ NULL,
309 },
310 { /* constraint_class fields */
311 /* resource list */ NULL,
312 /* num resources */ 0,
313 /* constraint size */ sizeof(XmColorSelectorConstraintRec),
314 /* destroy proc */ NULL,
315 /* init proc */ NULL,
316 /* set values proc */ NULL,
317 /* extension */ NULL,
318 },
319 { /* manager_class fields */
320 /* default translations */ XtInheritTranslations,
321 /* syn_resources */ get_resources,
322 /* num_syn_resources */ XtNumber(get_resources),
323 /* syn_cont_resources */ NULL,
324 /* num_syn_cont_resources */ 0,
325 /* parent_process */ NULL,
326 /* extension */ NULL,
327 },
328 { /* color_selector_class fields */
329 /* mumble */ NULL,
330 }
331 };
332
333 WidgetClass xmColorSelectorWidgetClass = (WidgetClass)&xmColorSelectorClassRec;
334
335 /************************************************************
336 * STATIC CODE
337 ************************************************************/
338
339 /* Function Name: ClassInitialize
340 * Description: Called to initialize class specific information.
341 * Arguments: widget_class - the widget class.
342 * Returns: none.
343 */
344
345 static void
ClassInitialize(void)346 ClassInitialize(void)
347 {
348 XmColorSelectorClassRec *wc = &xmColorSelectorClassRec;
349
350 XtSetTypeConverter(XmRString, XmRXmColorMode,
351 (XtTypeConverter) CvtStringToColorMode,
352 NULL, (Cardinal) 0, XtCacheAll, NULL);
353 }
354
355 /*
356 * ClassPartInitialize sets up the fast subclassing for the widget.
357 */
358 static void
359 #ifdef _NO_PROTO
ClassPartInitialize(w_class)360 ClassPartInitialize(w_class)
361 WidgetClass w_class ;
362 #else
363 ClassPartInitialize(WidgetClass w_class)
364 #endif /* _NO_PROTO */
365 {
366 _XmFastSubclassInit (w_class, XmCOLORSELECTOR_BIT);
367 }
368
369
370
371 /* Function Name: Initialize
372 * Description: Called to initialize information specific
373 * to this widget.
374 * Arguments: request - what was originally requested.
375 * set - what will be created (our superclasses have
376 * already mucked with this)
377 * args, num_args - The arguments passed to
378 * the creation call.
379 * Returns: none.
380 */
381
382 /* ARGSUSED */
383 static void
Initialize(Widget request,Widget set,ArgList args,Cardinal * num_args)384 Initialize(Widget request, Widget set, ArgList args, Cardinal *num_args)
385 {
386 XmColorSelectorWidget csw = (XmColorSelectorWidget)set;
387 Dimension width, height;
388 String temp;
389 char message_buffer[BUFSIZ];
390 ArgList f_args;
391 Cardinal f_num_args;
392 Widget button;
393
394 _XmFilterArgs(args, *num_args, xm_std_filter, &f_args, &f_num_args);
395
396 /*
397 * Initialize important values.
398 */
399
400 XmColorS_good_cell(csw) = False;
401
402 temp = XmColorS_color_name(csw);
403 XmColorS_color_name(csw) = NULL;
404 XmColorS_list(csw) = NULL;
405
406 CreateColorSliders(csw, f_args, f_num_args);
407 CreateSelectorRadio(csw, f_args, f_num_args);
408 CreateColorWindow(csw, f_args, f_num_args);
409
410 XmColorS_rgb_file(csw) = XtNewString(XmColorS_rgb_file(csw));
411 XmColorS_colors(csw) = NULL;
412 read_rgb_file(csw, f_args, f_num_args, True);
413
414 if (!color_name_changed(csw, temp)) {
415 snprintf(message_buffer, BUFSIZ, XmNunparsableColorMsg, temp);
416 XmeWarning((Widget)set, message_buffer);
417
418 (void) color_name_changed(csw, "White");
419 }
420
421 slider_changed(NULL, (XtPointer) csw, NULL);
422
423 CalcPreferredSize(csw, &width, &height);
424
425 if ( csw->core.width < 1 )
426 csw->core.width = width;
427
428 if ( csw->core.height < 1 )
429 csw->core.height = height;
430
431 new_mode(csw, XmColorS_color_mode(csw));
432 button = XmColorS_chose_mode(csw)[XmColorS_color_mode(csw)];
433 XmToggleButtonSetState(button, True, False);
434
435 XtFree((XtPointer) f_args);
436
437 {
438 int i;
439 for( i = 0; i < 3; i++ )
440 XmColorS_strings(csw).slider_labels[i] = XmStringCopy(XmColorS_strings(csw).slider_labels[i]);
441 for (i = 0; i< XmColorSelector_NUM_TOGGLES; i++)
442 XmColorS_strings(csw).tog_labels[i] = XmStringCopy(XmColorS_strings(csw).tog_labels[i]);
443 XmColorS_strings(csw).file_read_error = XmStringCopy(XmColorS_strings(csw).file_read_error);
444 XmColorS_strings(csw).no_cell_error = XmStringCopy(XmColorS_strings(csw).no_cell_error);
445 }
446
447 }
448
449 /* Function Name: Destroy
450 * Description: Called to destroy this widget.
451 * Arguments: w - Color Selector Widget to destroy.
452 * Returns: none.
453 */
454
455 /* ARGSUSED */
456 static void
Destroy(Widget w)457 Destroy(Widget w)
458 {
459 XmColorSelectorWidget csw = (XmColorSelectorWidget)w;
460
461 if (XmColorS_good_cell(csw)) {
462 XFreeColors(XtDisplay(csw), csw->core.colormap,
463 &XmColorS_color_pixel(csw), 1, 0);
464 }
465
466 XtFree((char*) XmColorS_colors(csw));
467 XtFree((char*) XmColorS_color_name(csw));
468 XtFree((char*) XmColorS_rgb_file(csw));
469
470 {
471 int i;
472 for( i = 0; i < 3; i++ )
473 XmStringFree(XmColorS_strings(csw).slider_labels[i]);
474 for (i = 0; i< XmColorSelector_NUM_TOGGLES; i++)
475 XmStringFree(XmColorS_strings(csw).tog_labels[i]);
476 XmStringFree(XmColorS_strings(csw).file_read_error);
477 XmStringFree(XmColorS_strings(csw).no_cell_error);
478 }
479 }
480
481 /* Function Name: Resize
482 * Description: Called when this widget has been resized.
483 * Arguments: w - Color Selector Widget to realize.
484 * Returns: none.
485 */
486
487 /* ARGSUSED */
488 static void
Resize(Widget w)489 Resize(Widget w)
490 {
491 compute_size((XmColorSelectorWidget)w);
492 }
493
AreDiff(char * s1,char * s2)494 static Boolean AreDiff(char *s1, char *s2)
495 {
496 if (s1 && !s2) return True;
497 if (s2 && !s1) return True;
498 if (!s1 && !s2) return False;
499 /* they exist; now safe to do strcmp */
500 return strcmp(s1, s2);
501 }
502
503 /* Function Name: SetValues
504 * Description: Called when some widget data needs to be modified on-
505 * the-fly.
506 * Arguments: current - the current (old) widget values.
507 * request - before superclassed have changed things.
508 * set - what will acutally be the new values.
509 * args, num_args - the arguments in the list.
510 * Returns: none
511 */
512
513 /* ARGSUSED */
514 static Boolean
SetValues(Widget current,Widget request,Widget set,ArgList args,Cardinal * num_args)515 SetValues(Widget current, Widget request, Widget set,
516 ArgList args, Cardinal *num_args)
517 {
518 XmColorSelectorWidget csw = (XmColorSelectorWidget)set;
519 XmColorSelectorWidget curr = (XmColorSelectorWidget)current;
520
521 /*
522 * Pass argument list through to all children.
523 */
524
525 {
526 ArgList f_args;
527 Cardinal f_num_args;
528
529 _XmFilterArgs(args, *num_args, xm_std_filter, &f_args, &f_num_args);
530 _XmSetValuesOnChildren(set, f_args, f_num_args);
531 XtFree((XtPointer) f_args);
532 }
533
534 if (XmColorS_color_mode(curr) != XmColorS_color_mode(csw))
535 {
536 new_mode(csw, XmColorS_color_mode(csw));
537 XmToggleButtonSetState(XmColorS_chose_mode(csw)[XmColorS_color_mode(csw)],
538 True, True);
539 }
540
541 /*
542 ** Don't compare pointers; they are allocated, so passing the same file
543 ** in twice will trip this expensive function unless we compare the
544 ** values of the strings (when they exist)
545 */
546 if (AreDiff(XmColorS_rgb_file(curr), XmColorS_rgb_file(csw)))
547 {
548 read_rgb_file(csw, NULL, 0, False);
549 }
550 if (XmColorS_rgb_file(curr) != XmColorS_rgb_file(csw))
551 {
552 XtFree((char*) XmColorS_rgb_file(curr));
553 XmColorS_rgb_file(csw) = XtNewString(XmColorS_rgb_file(csw));
554 }
555
556 if ((XmColorS_margin_height(curr) != XmColorS_margin_height(csw)) ||
557 (XmColorS_margin_width(curr) != XmColorS_margin_width(csw)))
558 {
559 compute_size(csw);
560 }
561
562 if (XmColorS_color_name(curr) != XmColorS_color_name(csw))
563 {
564 String oldValue; /* old color name, will free. */
565 String newValue; /* new color name, allocate */
566 char string_buffer[BUFSIZ];
567
568 oldValue = XmColorS_color_name(curr);
569 newValue = XmColorS_color_name(csw);
570
571 if (!streq(newValue, oldValue))
572 {
573 /*
574 * Color name changed will automatically free the old
575 * value on success...
576 */
577
578 XmColorS_color_name(csw) = oldValue; /* so it free's the right thing. */
579 if (!color_name_changed(csw, newValue)) {
580 snprintf(string_buffer, BUFSIZ, XmNunparsableColorMsg, newValue);
581 XmeWarning(set, string_buffer);
582
583 XmColorS_color_name(csw) = oldValue;
584 }
585 }
586 else {
587 XtFree(oldValue);
588 XmColorS_color_name(csw) = XtNewString(newValue);
589 }
590 }
591
592 {
593 int i;
594 for( i = 0; i < 3; i++ )
595 {
596 if (XmColorS_strings(curr).slider_labels[i] != XmColorS_strings(csw).slider_labels[i])
597 {
598 XmStringFree(XmColorS_strings(curr).slider_labels[i]);
599 XmColorS_strings(csw).slider_labels[i] = XmStringCopy(XmColorS_strings(csw).slider_labels[i]);
600 XtVaSetValues(XmColorS_sliders(csw)[i], XmNtitleString, XmColorS_strings(csw).slider_labels[i], NULL);
601 }
602 }
603 for (i = 0; i< XmColorSelector_NUM_TOGGLES; i++)
604 {
605 if (XmColorS_strings(curr).tog_labels[i] != XmColorS_strings(csw).tog_labels[i])
606 {
607 XmStringFree(XmColorS_strings(curr).tog_labels[i]);
608 XmColorS_strings(csw).tog_labels[i] = XmStringCopy(XmColorS_strings(csw).tog_labels[i]);
609 XtVaSetValues(XmColorS_chose_mode(csw)[i], XmNlabelString, XmColorS_strings(csw).tog_labels[i], NULL);
610 }
611 }
612
613 if (XmColorS_strings(curr).file_read_error != XmColorS_strings(csw).file_read_error)
614 {
615 XmStringFree(XmColorS_strings(curr).file_read_error);
616 XmColorS_strings(csw).file_read_error = XmStringCopy(XmColorS_strings(csw).file_read_error);
617 }
618 if (XmColorS_strings(curr).no_cell_error != XmColorS_strings(csw).no_cell_error)
619 {
620 XmStringFree(XmColorS_strings(curr).no_cell_error);
621 XmColorS_strings(csw).no_cell_error = XmStringCopy(XmColorS_strings(csw).no_cell_error);
622 }
623 }
624
625 return FALSE;
626 }
627
628 /* Function Name: GeometryHandler
629 * Description: handles request from children for size changes.
630 * Arguments: child - the child to change.
631 * request - desired geometry of child.
632 * result - what will be allowed if almost.
633 * Returns: status.
634 */
635
636 /* ARGSUSED */
637 static XtGeometryResult
GeometryHandler(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * result)638 GeometryHandler(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *result)
639 {
640 return(XtGeometryNo);
641 }
642
643 /* Function Name: QueryGeometry
644 * Description: Called when my parent wants to know what size
645 * I would like to be.
646 * Arguments: w - the widget to check.
647 * indended - constriants imposed by the parent.
648 * preferred - what I would like.
649 * Returns: See Xt Manual.
650 */
651
652 static XtGeometryResult
QueryGeometry(Widget w,XtWidgetGeometry * intended,XtWidgetGeometry * preferred)653 QueryGeometry(Widget w,XtWidgetGeometry *intended, XtWidgetGeometry *preferred)
654 {
655 CalcPreferredSize((XmColorSelectorWidget) w,
656 &(preferred->width), &(preferred->height));
657
658 return(_XmHWQuery(w, intended, preferred));
659 }
660
661 /* Function Name: ChangeManaged
662 * Description: Called when a management change happens.
663 * Arguments: w - the csw widget.
664 * Returns: none
665 */
666
667 static void
ChangeManaged(Widget w)668 ChangeManaged(Widget w)
669 {
670 compute_size((XmColorSelectorWidget) w);
671
672 XmeNavigChangeManaged(w);
673 }
674
675 /************************************************************
676 * Type Converters.
677 ************************************************************/
678
679 /* Function Name: CvtStringToColorMode
680 * Description: Converts a string to a ColorMode
681 * Arguments: dpy - the X Display.
682 * args, num_args - *** NOT USED ***
683 * from - contains the string to convert.
684 * to - contains the converted node state.
685 * junk - *** NOT USED *** .
686 * Returns:
687 */
688
689 /* ARGSUSED */
690 static Boolean
CvtStringToColorMode(Display * dpy,XrmValuePtr args,Cardinal num_args,XrmValuePtr from,XrmValuePtr to,XtPointer * junk)691 CvtStringToColorMode(Display *dpy, XrmValuePtr args, Cardinal num_args,
692 XrmValuePtr from, XrmValuePtr to, XtPointer * junk)
693 {
694 static XmColorMode mode;
695 char lowerName[BUFSIZ];
696
697 XmCopyISOLatin1Lowered(lowerName, (char *)from->addr);
698
699 if (streq(lowerName, "listmode"))
700 mode = XmListMode;
701 else if (streq(lowerName, "scalemode"))
702 mode = XmScaleMode;
703 else {
704 XtDisplayStringConversionWarning(dpy, from->addr, XmRXmColorMode);
705 return(False); /* Conversion failed. */
706 }
707
708 to->size = sizeof(XmColorMode);
709 if ( to->addr == NULL ) {
710 to->addr = (XtPointer)&mode;
711 return(True);
712 }
713 else if ( to->size >= sizeof(XmColorMode) ) {
714 XmColorMode *state = (XmColorMode *) to->addr;
715
716 *state = mode;
717 return(True);
718 }
719
720 return(False);
721 }
722
723 /************************************************************
724 * LOCAL CODE
725 ************************************************************/
726
727 /* Function Name: CalcPreferredSize
728 * Description: Calculates the size this widget would prefer to be.
729 * Arguments: csw - the color selector widget.
730 * RETURNED width, height - preferred size of the color selector.
731 * Returns: none.
732 */
733
734 static void
CalcPreferredSize(XmColorSelectorWidget csw,Dimension * width,Dimension * height)735 CalcPreferredSize(XmColorSelectorWidget csw,
736 Dimension *width, Dimension *height)
737 {
738 XtWidgetGeometry geo;
739 Widget *childP;
740
741 *height = *width = 0;
742 ForAllChildren(csw, childP) {
743 if (*childP == XmColorS_bb(csw))
744 continue;
745
746 (void)XtQueryGeometry(*childP, NULL, &geo);
747
748 ASSIGN_MAX(*width, (geo.width + (2 * geo.border_width)));
749
750 geo.height += 2 * geo.border_width;
751 if ( *childP == XtParent(XmColorS_color_window(csw)) )
752 continue;
753 else if ( *childP == XmColorS_scrolled_list(csw) )
754 *height += (int)(4 * geo.height)/3;
755 else
756 *height += geo.height;
757
758 *height += XmColorS_margin_height(csw);
759 }
760
761 *width += 2 * XmColorS_margin_width(csw);
762 *height += 2 * XmColorS_margin_height(csw);
763 }
764
765 /* Function Name: color_name_changed
766 * Description: Change in the color name string.
767 * Arguments: csw - the color selector widget.
768 * name - the color name.
769 * Returns: True if successful
770 */
771
772 /* ARGSUSED */
773 static Boolean
color_name_changed(XmColorSelectorWidget csw,char * name)774 color_name_changed(XmColorSelectorWidget csw, char *name)
775 {
776 String old_val = XmColorS_color_name(csw);
777
778 if ( name == NULL ) {
779 XmColorS_color_name(csw) = NULL;
780 XtFree((XtPointer) old_val);
781 return(True);
782 }
783
784 XmColorS_color_name(csw) = XtNewString(name);
785
786 if (!UpdateColorWindow(csw, True)) {
787 XtFree((XtPointer) XmColorS_color_name(csw));
788 XmColorS_color_name(csw) = old_val;
789 return(False);
790 }
791
792 SetSliders(csw);
793 SelectColor(csw);
794 XtFree((XtPointer) old_val);
795 return(True);
796 }
797
798 /* Function Name: SetSliders
799 * Description: Sets the values in the color sliders.
800 * Arguments: csw - the color selector widget.
801 * Returns: none
802 */
803
804 static void
SetSliders(XmColorSelectorWidget csw)805 SetSliders(XmColorSelectorWidget csw)
806 {
807 static Arg args[] = {
808 { XmNvalue, (XtArgVal) NULL },
809 };
810
811 args[0].value = (XtArgVal) XmColorS_slider_red(csw);
812 XtSetValues(XmColorS_sliders(csw)[0], args, XtNumber(args));
813
814 args[0].value = (XtArgVal) XmColorS_slider_green(csw);
815 XtSetValues(XmColorS_sliders(csw)[1], args, XtNumber(args));
816
817 args[0].value = (XtArgVal) XmColorS_slider_blue(csw);
818 XtSetValues(XmColorS_sliders(csw)[2], args, XtNumber(args));
819 }
820
821 /* Function Name: SelectColor
822 * Description: Selects the color in the list that corrosponds
823 * to the current values of the RGB sliders.
824 * Arguments: csw - the color selector widget.
825 * Returns: none.
826 */
827
828 static void
SelectColor(XmColorSelectorWidget csw)829 SelectColor(XmColorSelectorWidget csw)
830 {
831 int color_num;
832
833 if (FindColor(csw, &color_num)) {
834 XmListSelectPos(XmColorS_list(csw), color_num + 1, False);
835 XmListSetBottomPos(XmColorS_list(csw), color_num + 1);
836 }
837 else
838 XmListDeselectAllItems(XmColorS_list(csw));
839 }
840
841
842 /* Function Name: EndsInDigits
843 * Description: Determines if a string ends in a digit
844 * Returns: True if it does
845 */
846
847 static int
EndsInDigits(char * str)848 EndsInDigits(char *str)
849 {
850 register char *c = str;
851 while(*c != '\0') c++; /* advance to end of string marker */
852 c--; /* back to the last character */
853 if(c >= str && isascii(*c) && isdigit(*c))
854 return True;
855
856 return False;
857 }
858
859 /* Function Name: FindColor
860 * Description: Finds the index into the colors array associated with
861 * the current slider values. Attempts to find the slot
862 * with a the best matching name.
863 * Arguments: csw - The color selector widget.
864 * RETURNED color_num - The color index that was found.
865 * Returns: True if color was found, false otherwise.
866 *
867 * NOTE: if False is returned then color_num has an undefined value.
868 */
869
870 static Boolean
FindColor(XmColorSelectorWidget csw,int * color_num)871 FindColor(XmColorSelectorWidget csw, int *color_num)
872 {
873 register ColorInfo *ptr;
874 register int i, red, green, blue;
875
876 /*
877 * Obtain the color settings from the ColorSelector
878 * data structure
879 */
880 red = XmColorS_slider_red(csw);
881 green = XmColorS_slider_green(csw);
882 blue = XmColorS_slider_blue(csw);
883 ptr = XmColorS_colors(csw);
884
885 /*
886 * Flag for finding color value
887 */
888 *color_num = -1;
889
890 /*
891 * Find color within the exisiting colormap assigned to
892 * ColorSelector
893 */
894 for (i = 0; i < XmColorS_num_colors(csw); i++, ptr++)
895 {
896 if ((ptr->red == red) && (ptr->green == green) && (ptr->blue == blue))
897 {
898 if( *color_num < 0 )
899 *color_num = i;
900
901 /* Only change the selected color if it is better in some way */
902 if(XmColorS_color_name(csw)) {
903 if(XmColorS_color_name(csw)[0] == '#')
904 *color_num = i;
905
906 if(streq(XmColorS_color_name(csw), ptr->name) ||
907 streq(XmColorS_color_name(csw), ptr->no_space_lower_name))
908 {
909 *color_num = i;
910 return(True);
911 }
912 }
913 if(! EndsInDigits(ptr->name)) {
914 *color_num = i;
915 return(True);
916 }
917 }
918 }
919
920 return(*color_num >= 0);
921 }
922
923 /* Function Name: slider_changed
924 * Description: One of the sliders was pressed
925 * Arguments: w - the slider widget.
926 * csw - the color selector.
927 * scale - the scale widget callback struct.
928 * Returns: none.
929 */
930
931 /* ARGSUSED */
932 static void
slider_changed(Widget w,XtPointer csw_ptr,XtPointer scale_ptr)933 slider_changed(Widget w, XtPointer csw_ptr, XtPointer scale_ptr)
934 {
935 XmColorSelectorWidget csw = (XmColorSelectorWidget) csw_ptr;
936 XmScaleCallbackStruct *scale = (XmScaleCallbackStruct *) scale_ptr;
937
938 if (scale_ptr != NULL) { /* Set a new value. */
939 if (w == XmColorS_sliders(csw)[0])
940 XmColorS_slider_red(csw) = scale->value;
941 else if(w == XmColorS_sliders(csw)[1])
942 XmColorS_slider_green(csw) = scale->value;
943 else if(w == XmColorS_sliders(csw)[2])
944 XmColorS_slider_blue(csw) = scale->value;
945 }
946
947 UpdateColorWindow(csw, False);
948 }
949
950 /* Function Name: UpdateColorWindow
951 * Description: Updates the color window display.
952 * Arguments: csw - the color selector widget.
953 * use_name - if TRUE then use the color name to update.
954 * if FALSE then use the color sliders to update.
955 * Returns: True if successful
956 */
957
958 static Boolean
UpdateColorWindow(XmColorSelectorWidget csw,Boolean use_name)959 UpdateColorWindow(XmColorSelectorWidget csw, Boolean use_name)
960 {
961 int index;
962 XColor color;
963 Pixel foreground;
964 char buf[XmColorSelector_COLOR_NAME_SIZE], new_label[BUFSIZ];
965
966 if (!use_name) /* Update color names */
967 {
968 char *freeMe;
969
970 freeMe = XmColorS_color_name(csw);
971 sprintf(buf, "#%02x%02x%02x", XmColorS_slider_red(csw),
972 XmColorS_slider_green(csw), XmColorS_slider_blue(csw));
973
974 if (FindColor(csw, &index))
975 {
976 XmColorS_color_name(csw) = XtNewString(XmColorS_colors(csw)[index].name);
977 sprintf(new_label, "%s (%s)", XmColorS_color_name(csw), buf);
978 }
979 else
980 {
981 XmColorS_color_name(csw) = XtNewString(buf);
982 sprintf(new_label, "%s", buf);
983 }
984
985 XtFree((XtPointer)freeMe );
986 color.red = XmColorS_slider_red(csw) * 256;
987 color.green = XmColorS_slider_green(csw) * 256;
988 color.blue = XmColorS_slider_blue(csw) * 256;
989 }
990 else /* Update color slider */
991 {
992 if(XParseColor(XtDisplay(csw), csw->core.colormap,
993 XmColorS_color_name(csw), &color) == 0)
994 {
995 return(False);
996 }
997
998 XmColorS_slider_red(csw) = color.red / 256;
999 XmColorS_slider_green(csw) = color.green / 256;
1000 XmColorS_slider_blue(csw) = color.blue / 256;
1001
1002 /*
1003 * Attempt to replace a name that begins with a # with a real color
1004 * name.
1005 */
1006
1007 if ((XmColorS_color_name(csw)[0] == '#') && FindColor(csw, &index))
1008 {
1009 XtFree(XmColorS_color_name(csw));
1010 XmColorS_color_name(csw) = XtNewString(XmColorS_colors(csw)[index].name);
1011 }
1012 sprintf(buf, "#%02x%02x%02x", color.red/256, color.green/256, color.blue/256);
1013 sprintf(new_label, "%s (%s)", XmColorS_color_name(csw), buf);
1014 }
1015
1016 {
1017 long test = (long) color.red;
1018 test += (long) color.green;
1019 test += (long) color.blue;
1020
1021 if (test/3 > 0x7000)
1022 {
1023 foreground = BlackPixelOfScreen(XtScreen((Widget) csw));
1024 }
1025 else
1026 {
1027 foreground = WhitePixelOfScreen(XtScreen((Widget) csw));
1028 }
1029 }
1030
1031 /*
1032 * Check on the default visual
1033 */
1034 if (DefaultVisualDisplay(csw, foreground, color, (char *)new_label))
1035 {
1036 return True;
1037 } else
1038 {
1039 return False;
1040 }
1041 }
1042
1043
1044 /* Function Name: list_selected
1045 * Description: One of the list widgets was selected.
1046 * Arguments: w - the slider widget.
1047 * csw - the color selector.
1048 * list - the list widget callback struct.
1049 * Returns: none.
1050 */
1051
1052 /* ARGSUSED */
1053 static void
list_selected(Widget w,XtPointer csw_ptr,XtPointer list_ptr)1054 list_selected(Widget w, XtPointer csw_ptr, XtPointer list_ptr)
1055 {
1056 XmColorSelectorWidget csw = (XmColorSelectorWidget) csw_ptr;
1057 XmListCallbackStruct *list = (XmListCallbackStruct *) list_ptr;
1058
1059 XtFree(XmColorS_color_name(csw));
1060
1061 XmColorS_color_name(csw) =
1062 XmStringUnparse(list->item,
1063 NULL, XmCHARSET_TEXT, XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
1064
1065 /* deprecated
1066 XmStringGetLtoR(list->item, XmFONTLIST_DEFAULT_TAG,
1067 &(XmColorS_color_name(csw)));
1068 */
1069
1070 UpdateColorWindow(csw, True);
1071 }
1072
1073 /* Function Name: change_mode
1074 * Description: One of the change mode buttons was pressed.
1075 * Arguments: w - the slider widget.
1076 * csw_ptr - the color selector.
1077 * tp - the toggle widget callback struct.
1078 * Returns: none.
1079 */
1080
1081 /* ARGSUSED */
1082 static void
change_mode(Widget w,XtPointer csw_ptr,XtPointer tp)1083 change_mode(Widget w, XtPointer csw_ptr, XtPointer tp)
1084 {
1085 XmColorSelectorWidget csw = (XmColorSelectorWidget) csw_ptr;
1086 XmToggleButtonCallbackStruct *toggle = (XmToggleButtonCallbackStruct *) tp;
1087
1088 /*
1089 * Ignore unsets.
1090 */
1091
1092 if (toggle->reason == XmCR_VALUE_CHANGED && toggle->set) {
1093 /*
1094 * Change the mode if it is different.
1095 */
1096
1097 if ((w == XmColorS_chose_mode(csw)[XmListMode]) &&
1098 (XmColorS_color_mode(csw) != XmListMode))
1099 {
1100 new_mode(csw, XmListMode);
1101 }
1102 else if ((w == XmColorS_chose_mode(csw)[XmScaleMode]) &&
1103 (XmColorS_color_mode(csw) != XmScaleMode))
1104 {
1105 new_mode(csw, XmScaleMode);
1106 }
1107 }
1108 }
1109
1110 /* Function Name: new_mode
1111 * Description: mode has changed
1112 * Arguments: csw - the color selector.
1113 * mode - the new mode.
1114 * Returns: none.
1115 */
1116
1117 /* ARGSUSED */
1118 static void
new_mode(XmColorSelectorWidget csw,XmColorMode mode)1119 new_mode(XmColorSelectorWidget csw, XmColorMode mode)
1120 {
1121 XmColorS_color_mode(csw) = mode;
1122
1123 if (mode == XmScaleMode) {
1124 SetSliders(csw);
1125
1126 XtUnmanageChild(XmColorS_scrolled_list(csw));
1127 XtManageChild(XmColorS_bb(csw));
1128 }
1129 else {
1130 SelectColor(csw); /* Select the current color in the list. */
1131
1132 XtUnmanageChild(XmColorS_bb(csw));
1133 XtManageChild(XmColorS_scrolled_list(csw));
1134 }
1135 }
1136
1137 /* Function Name: compute_size
1138 * Description: Do all the size and position computing.
1139 * Arguments: csw - the color selector.
1140 * Returns: none.
1141 */
1142
1143 /* ARGSUSED */
1144 static void
compute_size(XmColorSelectorWidget csw)1145 compute_size(XmColorSelectorWidget csw)
1146 {
1147 XtWidgetGeometry input, radio_geom, color_geom;
1148 Dimension width, height;
1149 Position x,y; /* positions */
1150
1151 /*
1152 * First size and place the button box and scrolled list.
1153 */
1154
1155 y = XmColorS_margin_height(csw);
1156 x = XmColorS_margin_width(csw);
1157 width = csw->core.width - (2 * XmColorS_margin_width(csw));
1158
1159 input.width = width;
1160 input.request_mode = CWWidth;
1161
1162 (void) XtQueryGeometry(XmColorS_chose_radio(csw), NULL, &radio_geom);
1163 (void) XtQueryGeometry(XmColorS_color_window(csw), &input, &color_geom);
1164
1165 height = (csw->core.height - 4 * XmColorS_margin_height(csw) -
1166 (radio_geom.height + 2 * radio_geom.border_width));
1167
1168 /*
1169 * Leave space for the margins and make the color area 1/3 the height
1170 * of the scrolled list and button box.
1171 */
1172
1173 color_geom.height = height / 4;
1174 height -= color_geom.height;
1175 color_geom.height -= 2 * color_geom.border_width;
1176
1177 _XmConfigureWidget(XmColorS_bb(csw), x, y, width, height, 0);
1178 _XmConfigureWidget(XmColorS_scrolled_list(csw), x, y, width, height, 0);
1179
1180 y += height + XmColorS_margin_height(csw);
1181
1182 /*
1183 * Place the radio box.
1184 */
1185
1186 if ( radio_geom.width < csw->core.width )
1187 x = (int)(csw->core.width - radio_geom.width) / 2;
1188 else
1189 x = XmColorS_margin_width(csw);
1190
1191 _XmConfigureWidget(XmColorS_chose_radio(csw), x, y, radio_geom.width,
1192 radio_geom.height, radio_geom.border_width);
1193
1194 y += radio_geom.height + XmColorS_margin_height(csw);
1195
1196 /*
1197 * Lastly, place the color window
1198 */
1199
1200 _XmConfigureWidget(XtParent(XmColorS_color_window(csw)), XmColorS_margin_width(csw), y,
1201 width, color_geom.height, color_geom.border_width);
1202 }
1203
1204 /* Function Name: read_rgb_file
1205 * Description: Read in all the color names and add them to the list.
1206 * Arguments: csw - the color selector.
1207 * cargs, cnum_args - a filtered arg list that was
1208 * passed to create the color selector.
1209 * Returns: none.
1210 */
1211
1212 /* ARGSUSED */
1213 static void
read_rgb_file(XmColorSelectorWidget csw,ArgList cargs,Cardinal cnum_args,Boolean initial)1214 read_rgb_file(XmColorSelectorWidget csw, ArgList cargs, Cardinal cnum_args, Boolean initial)
1215 {
1216 FILE *file;
1217 char buf[BUFSIZ];
1218 char string_buffer[BUFSIZ];
1219 char *color_name;
1220 ColorInfo * color_info = NULL;
1221 register int i;
1222 Arg *margs, args[20];
1223
1224 /*
1225 * Create new list if needed, or delete any old list items.
1226 */
1227 if (XmColorS_list(csw) == NULL)
1228 {
1229 i = 0;
1230 XtSetArg(args[i], XmNlistSizePolicy, XmCONSTANT); i++;
1231 XtSetArg(args[i], XmNvisibleItemCount, 15); i++;
1232 margs = XtMergeArgLists(args, i, cargs, cnum_args);
1233 XmColorS_list(csw) = XmCreateScrolledList((Widget) csw, "list",
1234 margs, i + cnum_args);
1235
1236 XtManageChild(XmColorS_list(csw));
1237 XmColorS_scrolled_list(csw) = XtParent(XmColorS_list(csw));
1238
1239 if (XmColorS_color_mode(csw) != XmListMode)
1240 {
1241 /* Hide the scrolled list until it need be visible... */
1242 XtUnmanageChild(XmColorS_scrolled_list(csw));
1243 }
1244
1245 XtFree((XtPointer) margs);
1246 }
1247 else
1248 {
1249 XmListDeleteAllItems(XmColorS_list(csw));
1250 }
1251
1252 /*
1253 ** Because of the internal functioning of the XmList, it is better to
1254 ** zero out the selected item list rather than to let the item currently
1255 ** selected be re-selected by the XmList when the new list of colors is
1256 ** assigned. As is, the XmList iteratively searches through the list of
1257 ** selected items for each item added. Resetting the selectedItem list to
1258 ** NULL/0 ensures that we don't have O(n*m) XmStringCompare operations
1259 ** done when setting the new list below.
1260 ** Also, resetting the list saves us in the case in which the rgb_file
1261 ** is invalid or doesn't contain this selected string.
1262 */
1263 XtVaSetValues(XmColorS_list(csw),
1264 XmNselectedItems, NULL, XmNselectedItemCount, 0, NULL);
1265
1266 /*
1267 * Read in all the colornames.
1268 */
1269 if ((file = fopen(XmColorS_rgb_file(csw), "r")) != NULL) {
1270 register int alloc, count, len;
1271 register char *name;
1272
1273 alloc = count = 0;
1274
1275 while(fgets(buf, BUFSIZ, file)) {
1276 /*
1277 * Skip any comment lines in the file
1278 */
1279 if ( buf[0] == '!' ) continue;
1280
1281 if (count >= alloc) {
1282 if (0 == alloc)
1283 alloc = 755; /* rather than stat the file and determine a good value to use, just use enough for X11R5, X11R6, and OpenWindows3 */
1284 else
1285 {
1286 #define ALLOC_INC 20
1287 alloc += ALLOC_INC;
1288 }
1289 color_info = (ColorInfo *)XtRealloc((XtPointer) color_info,
1290 sizeof(ColorInfo) * alloc);
1291 }
1292
1293 sscanf(buf, "%hu %hu %hu", &(color_info[count].red),
1294 &(color_info[count].green), &(color_info[count].blue));
1295
1296 if ((color_name = find_name(buf)) == NULL)
1297 continue;
1298
1299 len = strlen(color_name);
1300 if (len > XmColorSelector_COLOR_NAME_SIZE) {
1301 color_name[XmColorSelector_COLOR_NAME_SIZE - 1] = '\0';
1302 snprintf(string_buffer, BUFSIZ,
1303 XmNcolorNameTooLongMsg, buf, color_name);
1304 XmeWarning((Widget)csw, string_buffer);
1305 }
1306
1307 name = color_info[count].no_space_lower_name;
1308 for (i = 0; i < len; i++) {
1309 register char c = color_name[i];
1310
1311 /*
1312 * Copy in all characters that are ascii and non-spaces.
1313 */
1314 if (!isascii(c))
1315 continue;
1316 if (!isspace(c))
1317 *name++ = tolower(c);
1318 }
1319 *name = '\0';
1320
1321 name = color_info[count].name;
1322 color_name[0] = toupper(color_name[0]);
1323 for (i = 0; i < len; i++) {
1324 register char c = color_name[i];
1325
1326 /*
1327 * Capitalize all characters after a space.
1328 */
1329
1330 if (!isascii(c))
1331 continue;
1332 if (isspace(c) && ((i + 1) < len)) {
1333 color_name[i + 1] = toupper(color_name[i + 1]);
1334 }
1335
1336 *name++ = c;
1337 }
1338 *name = '\0';
1339
1340 count++;
1341 }
1342 fclose(file);
1343
1344 qsort(color_info, count, sizeof(ColorInfo), CmpColors);
1345
1346 /*
1347 * Remove duplicates.
1348 */
1349 i = 0;
1350 while (i < (count - 1)) {
1351 if (streq(color_info[i].no_space_lower_name,
1352 color_info[i + 1].no_space_lower_name))
1353 {
1354 register int j;
1355 register ColorInfo *ptr;
1356
1357 ptr = color_info + i;
1358 j = i;
1359
1360 /*
1361 * This makes sure that the one with the space is
1362 * left in place in favor of the one without.
1363 */
1364 if (strchr(ptr->name, ' ') != NULL) {
1365 j++;
1366 ptr++;
1367 }
1368
1369 while ( ++j < count) {
1370 ptr[0] = ptr[1];
1371 ptr++;
1372 }
1373
1374 count--; /*Something has been removed, decrement count*/
1375 }
1376 else
1377 i++;
1378 }
1379
1380 {
1381 XmString *strs = (XmString*)XtMalloc(sizeof(XmString)*count);
1382 for (i = 0; i < count; i++)
1383 strs[i] = XmStringCreateLocalized(color_info[i].name);
1384 XtVaSetValues(XmColorS_list(csw),
1385 XmNitems, strs,
1386 XmNitemCount, count,
1387 NULL);
1388 for (i = 0; i < count; i++)
1389 XmStringFree(strs[i]);
1390 XtFree((char*)strs);
1391 }
1392
1393 XtFree((char*)XmColorS_colors(csw));
1394 XmColorS_colors(csw) = color_info;
1395 XmColorS_num_colors(csw) = count;
1396
1397 /* It would be better if we had cached the current index number so
1398 ** we could just reset the list to the string corresponding to that
1399 ** value, but instead wind up going through FindColor to reestablish
1400 ** the selected string
1401 */
1402 if (!initial)
1403 SelectColor(csw);
1404 }
1405 else {
1406 XmString str;
1407
1408 XmListAddItem(XmColorS_list(csw), XmColorS_strings(csw).file_read_error, 0);
1409
1410 str = XmStringCreateLocalized(XmColorS_rgb_file(csw));
1411 XmListAddItem(XmColorS_list(csw), str, 0);
1412 XmStringFree(str);
1413
1414 XtFree((char*)XmColorS_colors(csw));
1415 XmColorS_colors(csw) = NULL;
1416 XmColorS_num_colors(csw) = 0;
1417 }
1418
1419 XtAddCallback(XmColorS_list(csw), XmNsingleSelectionCallback,
1420 list_selected, csw);
1421 XtAddCallback(XmColorS_list(csw), XmNbrowseSelectionCallback,
1422 list_selected, csw);
1423 }
1424
1425 /* Function Name: CmpColors
1426 * Description: Compares two colors.
1427 * Arguments: ptr_1, ptr_2 - two colors too compare.
1428 * Returns: none
1429 */
1430
1431 static int
CmpColors(const void * ptr_1,const void * ptr_2)1432 CmpColors(const void * ptr_1, const void * ptr_2)
1433 {
1434 ColorInfo *color1, *color2;
1435
1436 color1 = (ColorInfo *) ptr_1;
1437 color2 = (ColorInfo *) ptr_2;
1438
1439 return(strcmp(color1->no_space_lower_name, color2->no_space_lower_name));
1440 }
1441
1442 /* Function Name: find_name
1443 * Description: Go through the buffer for looking for the name
1444 * of a color string.
1445 * Arguments: buffer - list of color names.
1446 * Returns: pointer in the buffer where the string begins.
1447 */
1448
1449 static char*
find_name(char * buffer)1450 find_name(char *buffer)
1451 {
1452 register char *curr, *temp; /* current pointer */
1453
1454 for (curr = buffer; curr != NULL && *curr != '\0'; curr++) {
1455 /*
1456 * Look for first non number, non space or tab.
1457 */
1458
1459 if (isascii(*curr) && (isdigit(*curr) || isspace(*curr)))
1460 continue;
1461
1462 temp = (char *) strchr(curr, '\n');
1463 *temp = '\0';
1464
1465 return(curr);
1466 }
1467 return(NULL);
1468 }
1469
1470 /* Function Name: CreateColorSliders
1471 * Description: creates a button with three sliders (Red, Green, Blue).
1472 * Arguments: csw - the color selector widget.
1473 * cargs, cnum_args - a filtered arg list that was
1474 * passed to create the color selector.
1475 * Returns: none.
1476 */
1477
1478 /* ARGSUSED */
1479 static void
CreateColorSliders(XmColorSelectorWidget csw,ArgList cargs,Cardinal cnum_args)1480 CreateColorSliders(XmColorSelectorWidget csw,
1481 ArgList cargs, Cardinal cnum_args)
1482 {
1483 register int i;
1484 Cardinal num_args, title;
1485 Arg *margs, args[10];
1486
1487 num_args = 0;
1488 XtSetArg(args[num_args], XmNborderWidth, 0); num_args++;
1489 XtSetArg(args[num_args], XmNorientation, XmVERTICAL); num_args++;
1490 XtSetArg(args[num_args], XmNfillOption, XmFillMinor); num_args++;
1491 margs = XtMergeArgLists(args, num_args, cargs, cnum_args);
1492 XmColorS_bb(csw) = XtCreateManagedWidget("buttonBox", xmButtonBoxWidgetClass,
1493 (Widget) csw,
1494 margs, cnum_args + num_args);
1495 XtFree((XtPointer) margs);
1496
1497 num_args = 0;
1498 XtSetArg(args[num_args], XmNmaximum, 255); num_args++;
1499 XtSetArg(args[num_args], XmNorientation, XmHORIZONTAL); num_args++;
1500 XtSetArg(args[num_args], XmNshowValue, True); num_args++;
1501 XtSetArg(args[num_args], XmNprocessingDirection, XmMAX_ON_RIGHT);
1502 num_args++;
1503 XtSetArg(args[num_args], XmNtitleString, NULL); title = num_args++;
1504
1505 margs = XtMergeArgLists(args, num_args, cargs, cnum_args);
1506
1507 for( i = 0; i < 3; i++ ) {
1508 margs[title].value = (XtArgVal) XmColorS_strings(csw).slider_labels[i];
1509 XmColorS_sliders(csw)[i] = XtCreateManagedWidget("scale",
1510 xmScaleWidgetClass,
1511 XmColorS_bb(csw), margs,
1512 num_args + cnum_args);
1513
1514 XtAddCallback(XmColorS_sliders(csw)[i], XmNdragCallback,
1515 slider_changed, csw);
1516 XtAddCallback(XmColorS_sliders(csw)[i], XmNvalueChangedCallback,
1517 slider_changed, csw);
1518 }
1519 XtFree((XtPointer) margs);
1520 }
1521
1522 /* Function Name: CreateSelectorRadio
1523 * Description: creates a radio box with two toggles for selector
1524 * type.
1525 * Arguments: csw - the color selector widget.
1526 * cargs, cnum_args - a filtered arg list that was
1527 * passed to create the color selector.
1528 * Returns: none.
1529 */
1530
1531 /* ARGSUSED */
1532 static void
CreateSelectorRadio(XmColorSelectorWidget csw,ArgList cargs,Cardinal cnum_args)1533 CreateSelectorRadio(XmColorSelectorWidget csw,
1534 ArgList cargs, Cardinal cnum_args)
1535 {
1536 Widget w;
1537 Cardinal i, label;
1538 Arg *margs, args[5];
1539 int count;
1540 static String names[] = { "colorListToggle", "colorSlidersToggle" };
1541
1542 i = 0;
1543 XtSetArg(args[i], XmNradioBehavior, True); i++;
1544 XtSetArg(args[i], XmNpacking, XmPACK_COLUMN); i++;
1545 XtSetArg(args[i], XmNnumColumns, 2); i++;
1546 margs = XtMergeArgLists(args, i, cargs, cnum_args);
1547 w = XtCreateManagedWidget("radioBox", xmRowColumnWidgetClass,
1548 (Widget) csw, margs, i + cnum_args);
1549 XmColorS_chose_radio(csw) = w;
1550 XtFree((XtPointer) margs);
1551
1552 i = 0;
1553 XtSetArg(args[i], XmNlabelString, NULL); label = i++;
1554 margs = XtMergeArgLists(args, i, cargs, cnum_args);
1555
1556 for (count = 0; count < XmColorSelector_NUM_TOGGLES; count++) {
1557 margs[label].value = (XtArgVal) XmColorS_strings(csw).tog_labels[count];
1558
1559 w = XtCreateManagedWidget(names[count], xmToggleButtonWidgetClass,
1560 XmColorS_chose_radio(csw), margs, i + cnum_args);
1561 XmColorS_chose_mode(csw)[count] = w;
1562
1563 XtAddCallback(w, XmNvalueChangedCallback, change_mode, csw);
1564 }
1565
1566 XtFree((XtPointer) margs);
1567 }
1568
1569 /* Function Name: CreateColorWindow
1570 * Description: creates a label in a frame to display the
1571 * currently selected color.
1572 * Arguments: csw - the color selector widget.
1573 * cargs, cnum_args - a filtered arg list that was
1574 * passed to create the color selector.
1575 * Returns: none.
1576 */
1577
1578 /* ARGSUSED */
1579 static void
CreateColorWindow(XmColorSelectorWidget csw,ArgList cargs,Cardinal cnum_args)1580 CreateColorWindow(XmColorSelectorWidget csw,ArgList cargs, Cardinal cnum_args)
1581 {
1582 Widget fr;
1583 Arg *margs, args[10];
1584 Cardinal n;
1585
1586 fr = XtCreateManagedWidget("colorFrame", xmFrameWidgetClass,
1587 (Widget) csw, cargs, cnum_args);
1588
1589 n = 0;
1590 XtSetArg(args[n], XmNrecomputeSize, False); n++;
1591 margs = XtMergeArgLists(args, n, cargs, cnum_args);
1592 XmColorS_color_window(csw) = XtCreateManagedWidget("colorWindow",
1593 xmLabelWidgetClass,
1594 fr, margs, n + cnum_args);
1595 XtFree((XtPointer) margs);
1596 }
1597
1598 /* ARGSUSED */
GetValues_XmNredSliderLabel(Widget w,int n,XtArgVal * value)1599 static void GetValues_XmNredSliderLabel ( Widget w, int n, XtArgVal *value)
1600 {
1601 (*value) = (XtArgVal) XmStringCopy(XmColorS_strings(w).slider_labels[0]);
1602 }
1603 /* ARGSUSED */
GetValues_XmNgreenSliderLabel(Widget w,int n,XtArgVal * value)1604 static void GetValues_XmNgreenSliderLabel( Widget w, int n, XtArgVal *value)
1605 {
1606 (*value) = (XtArgVal) XmStringCopy(XmColorS_strings(w).slider_labels[1]);
1607 }
1608 /* ARGSUSED */
GetValues_XmNblueSliderLabel(Widget w,int n,XtArgVal * value)1609 static void GetValues_XmNblueSliderLabel( Widget w, int n, XtArgVal *value)
1610 {
1611 (*value) = (XtArgVal) XmStringCopy(XmColorS_strings(w).slider_labels[2]);
1612 }
1613 /* ARGSUSED */
GetValues_XmNcolorListTogLabel(Widget w,int n,XtArgVal * value)1614 static void GetValues_XmNcolorListTogLabel( Widget w, int n, XtArgVal *value)
1615 {
1616 (*value) = (XtArgVal) XmStringCopy(XmColorS_strings(w).tog_labels[0]);
1617 }
1618 /* ARGSUSED */
GetValues_XmNsliderTogLabel(Widget w,int n,XtArgVal * value)1619 static void GetValues_XmNsliderTogLabel( Widget w, int n, XtArgVal *value)
1620 {
1621 (*value) = (XtArgVal) XmStringCopy(XmColorS_strings(w).tog_labels[1]);
1622 }
1623 /* ARGSUSED */
GetValues_XmNnoCellError(Widget w,int n,XtArgVal * value)1624 static void GetValues_XmNnoCellError( Widget w, int n, XtArgVal *value)
1625 {
1626 (*value) = (XtArgVal) XmStringCopy(XmColorS_strings(w).no_cell_error);
1627 }
1628 /* ARGSUSED */
GetValues_XmNfileReadError(Widget w,int n,XtArgVal * value)1629 static void GetValues_XmNfileReadError( Widget w, int n, XtArgVal *value)
1630 {
1631 (*value) = (XtArgVal) XmStringCopy(XmColorS_strings(w).file_read_error);
1632 }
1633
1634 /* Function Name: GetVisual
1635 * Description: Gets the defaults visual of the screen
1636 * Arguments: csw - the color selector widget.
1637 * Returns: Visual id.
1638 */
1639
1640 /* ARGSUSED */
1641 static int
GetVisual(XmColorSelectorWidget csw)1642 GetVisual(XmColorSelectorWidget csw)
1643 {
1644 Visual * vis;
1645 int visual;
1646
1647 vis = DefaultVisual(XtDisplay(csw), XDefaultScreen(XtDisplay(csw)));
1648 visual = vis->class;
1649
1650 return visual;
1651 }
1652
1653 /* Function Name: NoPrivateColormaps
1654 * Description: Determines the color to be used.
1655 * Arguments: csw - the color selector widget.
1656 * foreground - default color for the ColorSelector.
1657 * color - Current color attributes.
1658 * str - label for the ColorSelector.
1659 * Returns: None.
1660 */
1661
1662 /* ARGSUSED */
1663 static void
NoPrivateColormaps(XmColorSelectorWidget csw,Pixel foreground,XColor color,char * str)1664 NoPrivateColormaps(XmColorSelectorWidget csw, Pixel foreground,
1665 XColor color, char *str)
1666 {
1667 Arg args[5];
1668 XmString xm_str;
1669 Cardinal num_args;
1670
1671 xm_str = XmStringCreateLocalized(str);
1672 num_args = 0;
1673
1674 if (!XmColorS_good_cell(csw))
1675 {
1676 if(XAllocColor(XtDisplay(csw), csw->core.colormap, &color) )
1677 {
1678 XmColorS_color_pixel(csw) = color.pixel;
1679 XmColorS_good_cell(csw) = True;
1680 }
1681 } else {
1682 if (XAllocColor(XtDisplay(csw), csw->core.colormap, &color) )
1683 {
1684 XmColorS_color_pixel(csw) = color.pixel;
1685 XmColorS_good_cell(csw) = True;
1686 }
1687 else
1688 {
1689 XmString out;
1690 out = XmStringConcatAndFree(xm_str, XmColorS_strings(csw).no_cell_error);
1691 xm_str = out;
1692 }
1693 }
1694
1695 if (XmColorS_good_cell(csw))
1696 {
1697 color.flags = DoRed | DoGreen | DoBlue;
1698 color.pixel = XmColorS_color_pixel(csw);
1699 XtSetArg(args[num_args], XmNforeground, foreground); num_args++;
1700 XtSetArg(args[num_args], XmNbackground, XmColorS_color_pixel(csw));
1701 num_args++;
1702 XtSetValues(XmColorS_color_window(csw), args, num_args);
1703 }
1704
1705 XtSetArg(args[num_args], XmNlabelString, xm_str); num_args++;
1706 XtSetValues(XmColorS_color_window(csw), args, num_args);
1707 XmStringFree(xm_str);
1708 }
1709
1710 /* Function Name: DoPrivateColormaps
1711 * Description: Determines the color to be used.
1712 * Arguments: csw - the color selector widget.
1713 * foreground - default color for the ColorSelector.
1714 * color - Current color attributes.
1715 * str - label for the ColorSelector.
1716 * Returns: None.
1717 */
1718
1719 /* ARGSUSED */
1720 static void
PrivateColormaps(XmColorSelectorWidget csw,Pixel foreground,XColor color,char * str)1721 PrivateColormaps(XmColorSelectorWidget csw, Pixel foreground, XColor color, char *str)
1722 {
1723 Arg args[5];
1724 XmString xm_str;
1725 Cardinal num_args;
1726
1727 xm_str = XmStringCreateLocalized(str);
1728 num_args = 0;
1729
1730 if (!XmColorS_good_cell(csw)) {
1731 if(XAllocColorCells(XtDisplay(csw), csw->core.colormap,
1732 0, 0, 0, &(XmColorS_color_pixel(csw)), 1))
1733 {
1734 XmColorS_good_cell(csw) = True;
1735 }
1736 else {
1737 XmString out;
1738
1739 out = XmStringConcatAndFree(xm_str, XmColorS_strings(csw).no_cell_error);
1740 xm_str = out;
1741 }
1742 }
1743
1744 if (XmColorS_good_cell(csw)) {
1745 color.flags = DoRed | DoGreen | DoBlue;
1746 color.pixel = XmColorS_color_pixel(csw);
1747 XStoreColor(XtDisplay((Widget) csw), csw->core.colormap, &color);
1748 XtSetArg(args[num_args], XmNforeground, foreground); num_args++;
1749 XtSetArg(args[num_args], XmNbackground, XmColorS_color_pixel(csw));
1750 num_args++;
1751 }
1752
1753 XtSetArg(args[num_args], XmNlabelString, xm_str); num_args++;
1754 XtSetValues(XmColorS_color_window(csw), args, num_args);
1755 XmStringFree(xm_str);
1756 }
1757
1758 /*
1759 * Function Name: DefaultVisualDisplay
1760 * Description: Determines the default visual and allocates
1761 * the color depending upon the visual classes
1762 * Arguments: csw - the color selector widget.
1763 * foreground - default color for the ColorSelector.
1764 * color - Current color attributes.
1765 * str - label for the ColorSelector.
1766 * Returns: Returns true on a valid visual class.
1767 * False otherwise.
1768 */
1769
1770 /* ARGSUSED */
1771 static Boolean
DefaultVisualDisplay(XmColorSelectorWidget csw,Pixel foreground,XColor color,char * str)1772 DefaultVisualDisplay(XmColorSelectorWidget csw, Pixel foreground, XColor color, char *str)
1773 {
1774 int visual = 0;
1775 visual = GetVisual(csw);
1776
1777 /*
1778 * Obtain a valid color cell. In case, if one not available
1779 */
1780 if ( visual == StaticColor || visual == TrueColor || \
1781 visual == StaticGray )
1782 {
1783 NoPrivateColormaps(csw, foreground, color, str);
1784 return True;
1785 } else if ( visual == PseudoColor || visual == DirectColor || \
1786 visual == GrayScale )
1787 {
1788 PrivateColormaps(csw, foreground, color, str);
1789 return True;
1790 } else
1791 {
1792 return False;
1793 }
1794 }
1795
1796 /************************************************************
1797 *
1798 * Public functions.
1799 *
1800 ************************************************************/
1801
1802 /* Function Name: XmCreateColorSelector
1803 * Description: Creation Routine for UIL and ADA.
1804 * Arguments: parent - the parent widget.
1805 * name - the name of the widget.
1806 * args, num_args - the number and list of args.
1807 * Returns: The created widget.
1808 */
1809
1810 Widget
XmCreateColorSelector(Widget parent,String name,ArgList args,Cardinal num_args)1811 XmCreateColorSelector(Widget parent, String name,
1812 ArgList args, Cardinal num_args)
1813 {
1814 return(XtCreateWidget(name, xmColorSelectorWidgetClass,
1815 parent, args, num_args));
1816 }
1817
1818 Widget
XmVaCreateColorSelector(Widget parent,char * name,...)1819 XmVaCreateColorSelector(
1820 Widget parent,
1821 char *name,
1822 ...)
1823 {
1824 register Widget w;
1825 va_list var;
1826 int count;
1827
1828 Va_start(var,name);
1829 count = XmeCountVaListSimple(var);
1830 va_end(var);
1831
1832
1833 Va_start(var, name);
1834 w = XmeVLCreateWidget(name,
1835 xmColorSelectorWidgetClass,
1836 parent, False,
1837 var, count);
1838 va_end(var);
1839 return w;
1840 }
1841
1842 Widget
XmVaCreateManagedColorSelector(Widget parent,char * name,...)1843 XmVaCreateManagedColorSelector(
1844 Widget parent,
1845 char *name,
1846 ...)
1847 {
1848 Widget w = NULL;
1849 va_list var;
1850 int count;
1851
1852 Va_start(var, name);
1853 count = XmeCountVaListSimple(var);
1854 va_end(var);
1855
1856 Va_start(var, name);
1857 w = XmeVLCreateWidget(name,
1858 xmColorSelectorWidgetClass,
1859 parent, True,
1860 var, count);
1861 va_end(var);
1862 return w;
1863 }
1864