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