1 /*******************************************************************
2  FILE:		Value.c
3  CONTENTS:	Definitions for structures, methods, and actions of the
4 		Value widget.
5  AUTHOR:	Paul D. Johnston
6  HISTORY:
7  Date		Action
8  ---------	------------------------------------
9  5/23/92	Changed the widget class name so that it is preceded
10 		by 'xc' with the first major word capitalized.
11  10/22/91	Created.
12 
13 ********************************************************************/
14 
15 #include <stdio.h>
16 
17 /* Xlib includes */
18 #include <X11/Xlib.h>
19 
20 /* Xt includes */
21 #include <X11/StringDefs.h>
22 #include <X11/IntrinsicP.h>
23 
24 /* Xc includes */
25 #include <X11/Xc/Xc.h>
26 #include <X11/Xc/Control.h>
27 
28 /* Widget includes */
29 #include <X11/Xc/ValueP.h>	/* (includes Value.h also) */
30 
31 
32 /* Macro redefinition for offset. */
33 #define offset(field) XtOffset(ValueWidget, field)
34 
35 
36 /* Declare widget methods */
37 static void ClassInitialize();
38 static void Initialize();
39 static Boolean SetValues();
40 
41 /* Declare widget class functions */
42 static void CvtStringToDType();
43 static void CvtStringToVType();
44 static void CvtStringToValueJustify();
45 
46 
47 
48 /* Define the widget's resource list */
49 static XtResource resources[] =
50 {
51   {
52     XcNvalueForeground,
53     XtCColor,
54     XtRPixel,
55     sizeof(Pixel),
56     offset(value.value_fg_pixel),
57     XtRString,
58     XtDefaultForeground
59   },
60   {
61     XcNvalueBackground,
62     XtCColor,
63     XtRPixel,
64     sizeof(Pixel),
65     offset(value.value_bg_pixel),
66     XtRString,
67     "white"
68   },
69   {
70     XcNvalueCallback,
71     XtCCallback,
72     XtRCallback,
73     sizeof(caddr_t),
74     offset(value.callback),
75     XtRCallback,
76     NULL
77   },
78   {
79     XcNdataType,
80     XcCDataType,
81     XcRDType,
82     sizeof(XcDType),
83     offset(value.datatype),
84     XtRString,
85     "lval"
86   },
87   {
88     XcNdecimals,
89     XcCDecimals,
90     XtRInt,
91     sizeof(int),
92     offset(value.decimals),
93     XtRImmediate,
94     (caddr_t)2
95   },
96   {
97     XcNincrement,
98     XcCIncrement,
99     XcRVType,
100     sizeof(XcVType),
101     offset(value.increment),
102     XtRString,
103     "1"
104   },
105   {
106     XcNupperBound,
107     XcCUpperBound,
108     XcRVType,
109     sizeof(XcVType),
110     offset(value.upper_bound),
111     XtRString,
112     "100"
113   },
114   {
115     XcNlowerBound,
116     XcCLowerBound,
117     XcRVType,
118     sizeof(XcVType),
119     offset(value.lower_bound),
120     XtRString,
121     "0"
122   },
123   {
124     XcNvalueJustify,
125     XcCValueJustify,
126     XcRValueJustify,
127     sizeof(XcValueJustify),
128     offset(value.justify),
129     XtRString,
130     "justifycenter"
131   },
132   {
133     XcNvalue,
134     XcCValue,
135     XcRVType,
136     sizeof(XcVType),
137     offset(value.val),
138     XtRString,
139     "0"
140   },
141 };
142 
143 
144 
145 /* Widget Class Record initialization */
146 ValueClassRec valueClassRec =
147 {
148   {
149   /* core_class part */
150     (WidgetClass) &controlClassRec,		/* superclass */
151     "Value",					/* class_name */
152     sizeof(ValueRec),				/* widget_size */
153     ClassInitialize,				/* class_initialize */
154     NULL,					/* class_part_initialize */
155     FALSE,					/* class_inited */
156     Initialize,					/* initialize */
157     NULL,					/* initialize_hook */
158     XtInheritRealize,				/* realize */
159     NULL,					/* actions */
160     0,						/* num_actions */
161     resources,					/* resources */
162     XtNumber(resources),			/* num_resources */
163     NULLQUARK,					/* xrm_class */
164     TRUE,					/* compress_motion */
165     TRUE,					/* compress_exposure */
166     TRUE,					/* compress_enterleave */
167     TRUE,					/* visible_interest */
168     NULL,					/* destroy */
169     NULL,					/* resize */
170     NULL,					/* expose */
171     SetValues,					/* set_values */
172     NULL,					/* set_values_hook */
173     XtInheritSetValuesAlmost,			/* set_values_almost */
174     NULL,					/* get_values_hook */
175     NULL,					/* accept_focus */
176     XtVersion,					/* version */
177     NULL,					/* callback_private */
178     NULL,					/* tm_table */
179     NULL,					/* query_geometry */
180     NULL,					/* display_accelerator */
181     NULL,					/* extension */
182   },
183   {
184   /* Control class part */
185     0,						/* dummy_field */
186   },
187   {
188   /* Value class part */
189     0,						/* dummy_field */
190   },
191 };
192 
193 WidgetClass xcValueWidgetClass = (WidgetClass)&valueClassRec;
194 
195 
196 /* Widget method function definitions */
197 
198 /*******************************************************************
199  NAME:		ClassInitialize.
200  DESCRIPTION:
201    This method initializes the Value widget class. Specifically,
202 it registers resource value converter functions with Xt.
203 
204 *******************************************************************/
205 
ClassInitialize()206 static void ClassInitialize()
207 {
208 
209    XtAddConverter(XtRString, XcRDType, CvtStringToDType, NULL, 0);
210    XtAddConverter(XtRString, XcRVType, CvtStringToVType, NULL, 0);
211    XtAddConverter(XtRString, XcRValueJustify, CvtStringToValueJustify, NULL,0);
212 
213 }  /* end of ClassInitialize */
214 
215 
216 
217 
218 /*******************************************************************
219  NAME:		Initialize.
220  DESCRIPTION:
221    This is the initialize method for the Value widget.  It
222 validates user-modifiable instance resources and initializes private
223 widget variables and structures.
224 
225 *******************************************************************/
226 
Initialize(request,new)227 static void Initialize(request, new)
228 ValueWidget request, new;
229 {
230 
231 DPRINTF(("Value: executing Initialize \n"));
232 /*
233  * Validate public instance variable settings.
234  */
235    if ((new->value.datatype != XcLval) &&
236        (new->value.datatype != XcHval) &&
237        (new->value.datatype != XcFval))
238    {
239       XtWarning("Value: invalid datatype setting.");
240       new->value.datatype = XcLval;
241    }
242 
243 /* Check decimals setting */
244    if ((new->value.datatype == XcFval) &&
245         ((new->value.decimals < MIN_DECIMALS) ||
246          (new->value.decimals > MAX_DECIMALS)))
247    {
248       XtWarning("Value: invalid decimals setting.");
249       new->value.decimals = 2;
250    }
251 
252 /* Check increment setting */
253    if (((new->value.datatype == XcLval) || (new->value.datatype == XcHval))
254 				&& (new->value.increment.lval <= 0))
255    {
256       XtWarning("Value: invalid increment setting.");
257       new->value.increment.lval = 1L;
258    }
259    else if ((new->value.datatype == XcFval) &&
260 			(new->value.increment.fval <= 0.0))
261    {
262       XtWarning("Value: invalid increment setting.");
263       new->value.increment.fval = 1.0;
264    }
265 
266 /* Check lower/upper bound setting */
267    if (((new->value.datatype == XcLval) ||
268        (new->value.datatype == XcHval)) &&
269 	(new->value.lower_bound.lval >=
270 		new->value.upper_bound.lval))
271    {
272       XtWarning("Value: invalid lowerBound/upperBound setting.");
273       new->value.lower_bound.lval =
274 	(new->value.upper_bound.lval - new->value.increment.lval);
275    }
276    else if ((new->value.datatype == XcFval) &&
277 	(new->value.lower_bound.fval >=
278 		new->value.upper_bound.fval))
279    {
280       XtWarning("Value: invalid lowerBound/upperBound setting.");
281       new->value.lower_bound.fval =
282 	(new->value.upper_bound.fval - new->value.increment.fval);
283    }
284 
285 
286 /* Check the initial value setting */
287    if ((new->value.datatype == XcLval)  || (new->value.datatype == XcHval))
288    {
289       if (new->value.val.lval < new->value.lower_bound.lval)
290          new->value.val.lval = new->value.lower_bound.lval;
291       else if (new->value.val.lval > new->value.upper_bound.lval)
292          new->value.val.lval = new->value.upper_bound.lval;
293    }
294    else if (new->value.datatype == XcFval)
295    {
296       if (new->value.val.fval < new->value.lower_bound.fval)
297          new->value.val.fval = new->value.lower_bound.fval;
298       else if (new->value.val.fval > new->value.upper_bound.fval)
299          new->value.val.fval = new->value.upper_bound.fval;
300    }
301 
302 /* Check the initial valueJustify setting. */
303    if ((new->value.justify != XcJustifyLeft) &&
304           (new->value.justify != XcJustifyRight) &&
305           (new->value.justify != XcJustifyCenter))
306    {
307       XtWarning("Value: invalid valueJustify setting.");
308       new->value.justify = XcJustifyCenter;
309    }
310 
311 DPRINTF(("Value: done Initialize \n"));
312 
313 }  /* end of Initialize */
314 
315 
316 
317 
318 
319 /*******************************************************************
320  NAME:		SetValues.
321  DESCRIPTION:
322    This is the set_values method for this widget. It validates resource
323 settings set with XtSetValues. If a resource is changed that would
324 require re-drawing the widget, return True.
325 
326 *******************************************************************/
327 
SetValues(cur,req,new)328 static Boolean SetValues(cur, req, new)
329 ValueWidget cur, req, new;
330 {
331 /* Local variables */
332 Boolean do_redisplay = False;
333 
334 
335 DPRINTF(("Value: executing SetValues \n"));
336 
337 /* Validate new resource settings. */
338 
339 /* Check the widget's color resources. */
340    if ((new->value.value_fg_pixel != cur->value.value_fg_pixel) ||
341        (new->value.value_fg_pixel != cur->value.value_fg_pixel))
342       do_redisplay = True;
343 
344 /* Check the datatype */
345    if (new->value.datatype != cur->value.datatype)
346    {
347       do_redisplay = True;
348       if ((new->value.datatype != XcLval) &&
349           (new->value.datatype != XcHval) &&
350           (new->value.datatype != XcFval))
351       {
352          XtWarning("Value: invalid datatype setting.");
353          new->value.datatype = XcLval;
354       }
355    }
356 
357 /* Check the decimals setting */
358    if (new->value.decimals != cur->value.decimals);
359    {
360       do_redisplay = True;
361       if ((new->value.decimals < MIN_DECIMALS) ||
362 		(new->value.decimals > MAX_DECIMALS))
363       {
364 	 XtWarning("Value: invalid decimals setting.");
365 	 new->value.decimals = 2;
366       }
367    }
368 
369 /* Check the increment setting */
370    if (((new->value.datatype == XcLval) || (new->value.datatype == XcHval))
371 				&& (new->value.increment.lval <= 0))
372    {
373       XtWarning("Value: invalid increment setting.");
374       new->value.increment.lval = 1L;
375    }
376    else if ((new->value.datatype == XcFval) &&
377 			(new->value.increment.fval <= 0.0))
378    {
379       XtWarning("Value: invalid increment setting.");
380       new->value.increment.fval = 1.0;
381    }
382 
383 /* Check the lowerBound/upperBound setting */
384    if (((new->value.datatype == XcLval) ||
385        (new->value.datatype == XcHval)) &&
386 	(new->value.lower_bound.lval >=
387 		new->value.upper_bound.lval))
388    {
389       XtWarning("Value: invalid lowerBound/upperBound setting.");
390       new->value.lower_bound.lval =
391 	(new->value.upper_bound.lval - new->value.increment.lval);
392    }
393    else if ((new->value.datatype == XcFval) &&
394 	(new->value.lower_bound.fval >=
395 		new->value.upper_bound.fval))
396    {
397       XtWarning("Value: invalid lowerBound/upperBound setting.");
398       new->value.lower_bound.fval =
399 	(new->value.upper_bound.fval - new->value.increment.fval);
400    }
401 
402 
403 /* Check the new value setting */
404    if (((new->value.datatype == XcLval) || (new->value.datatype == XcHval)) &&
405 		(new->value.val.lval != cur->value.val.lval))
406    {
407       do_redisplay = True;
408       if (new->value.val.lval < new->value.lower_bound.lval)
409          new->value.val.lval = new->value.lower_bound.lval;
410       else if (new->value.val.lval > new->value.upper_bound.lval)
411          new->value.val.lval = new->value.upper_bound.lval;
412    }
413    if ((new->value.datatype == XcFval)  &&
414 		(new->value.val.fval != cur->value.val.fval))
415    {
416       do_redisplay = True;
417       if (new->value.val.fval < new->value.lower_bound.fval)
418          new->value.val.fval = new->value.lower_bound.fval;
419       else if (new->value.val.fval > new->value.upper_bound.fval)
420          new->value.val.fval = new->value.upper_bound.fval;
421    }
422 
423 /* Check the valueJustify setting. */
424    if (new->value.justify != cur->value.justify)
425    {
426       do_redisplay = True;
427       if ((new->value.justify != XcJustifyLeft) &&
428           (new->value.justify != XcJustifyRight) &&
429           (new->value.justify != XcJustifyCenter))
430       {
431          XtWarning("Value: invalid valueJustify setting.");
432          new->value.justify = XcJustifyCenter;
433       }
434    }
435 
436 
437 DPRINTF(("Value: done SetValues\n"));
438 
439    return do_redisplay;
440 
441 
442 }  /* end of SetValues */
443 
444 
445 
446 
447 /* Widget class functions */
448 
449 /*******************************************************************
450  NAME:		CvtStringToDType.
451  DESCRIPTION:
452    This function converts resource settings in string form to the
453 XtRDType representation type.
454 
455 *******************************************************************/
456 
CvtStringToDType(args,num_args,fromVal,toVal)457 static void CvtStringToDType(args, num_args, fromVal, toVal)
458 XrmValuePtr args;		/* unused */
459 Cardinal *num_args;		/* unused */
460 XrmValuePtr fromVal;
461 XrmValuePtr toVal;
462 {
463 /* Local variables */
464 static XcDType datatype;
465 char lowerstring[100];
466 
467 
468 /* Convert the resource string to lower case for quick comparison */
469    ToLower((char *)fromVal->addr, lowerstring);
470 
471 
472 /*
473  * Compare resource string with valid datatype strings and assign to
474  * datatype.
475  */
476    if (strcmp(lowerstring, XcElval) == 0)
477    {
478       datatype = XcLval;
479       CvtDone(XcDType, &datatype);
480    }
481    else if (strcmp(lowerstring, XcEhval) == 0)
482    {
483       datatype = XcHval;
484       CvtDone(XcDType, &datatype);
485    }
486    else if (strcmp(lowerstring, XcEfval) == 0)
487    {
488       datatype = XcFval;
489       CvtDone(XcDType, &datatype);
490    }
491 
492 /*
493  * If the string is not valid for this resource type, print a warning
494  * and do not make the conversion.
495  */
496    XtStringConversionWarning(fromVal->addr, "XcDType");
497    toVal->addr = NULL;
498    toVal->size = 0;
499 
500 }  /* end of CvtStringToDType */
501 
502 
503 
504 
505 /*******************************************************************
506  NAME:		CvtStringToVType.
507  DESCRIPTION:
508    This function converts resource settings in string form to the
509 XtRVType representation type.
510 
511 *******************************************************************/
512 
CvtStringToVType(args,num_args,fromVal,toVal)513 static void CvtStringToVType(args, num_args, fromVal, toVal)
514 XrmValuePtr args;		/* unused */
515 Cardinal *num_args;		/* unused */
516 XrmValuePtr fromVal;
517 XrmValuePtr toVal;
518 {
519 /* Local variables */
520 long num;
521 static XcVType value;
522 char temp[30], temp2[30];
523 
524 /*
525  * Make sure the string is a numeric constant. If it isn't, print
526  * a warning, and NULL the destination value.
527  */
528    if ((num = sscanf((char *)fromVal->addr,
529 			"%[-012345689ABCDEFabcdef.]", temp)) == 0)
530    {
531       XtStringConversionWarning(fromVal->addr, "XcVType");
532       CvtDone(char, NULL);
533    }
534 
535 /* If the number contains a decimal point, convert it into a float. */
536    if (strchr(temp, '.') != NULL)
537    {
538       sscanf(temp, "%f", &value.fval);
539       CvtDone(XcVType, &value.fval);
540    }
541 
542 /* If it contains any hexadecimal characters, convert it to a long hex int */
543    if (sscanf(temp, "%[ABCDEFabcdef]", temp2) != 0)
544    {
545       sscanf(temp, "%lX", &value.lval);
546       CvtDone(XcVType, &value.lval);
547    }
548 
549 
550 /* Otherwise, it's an integer type. Convert the string to a numeric constant. */
551    sscanf(temp, "%ld", &value.lval);
552    CvtDone(XcVType, &value.lval);
553 
554 }  /* end of CvtStringToVType */
555 
556 
557 
558 
559 /*******************************************************************
560  NAME:		CvtStringToValueJustify.
561  DESCRIPTION:
562    This function converts resource settings in string form to the
563 XcRValueJustify representation type.
564 
565 *******************************************************************/
566 
CvtStringToValueJustify(args,num_args,fromVal,toVal)567 static void CvtStringToValueJustify(args, num_args, fromVal, toVal)
568 XrmValuePtr args;		/* unused */
569 Cardinal *num_args;		/* unused */
570 XrmValuePtr fromVal;
571 XrmValuePtr toVal;
572 {
573 /* Local variables */
574 static XcValueJustify val_justify;
575 char lowerstring[100];
576 
577 /* Convert the resource string to lower case for quick comparison */
578    ToLower((char *)fromVal->addr, lowerstring);
579 
580 /*
581  * Compare resource string with valid XcValueJustify strings and assign to
582  * datatype.
583  */
584    if (strcmp(lowerstring, XcEjustifyLeft) == 0)
585    {
586       val_justify = XcJustifyLeft;
587       CvtDone(XcValueJustify, &val_justify);
588    }
589    else if (strcmp(lowerstring, XcEjustifyRight) == 0)
590    {
591       val_justify = XcJustifyRight;
592       CvtDone(XcValueJustify, &val_justify);
593    }
594    else if (strcmp(lowerstring, XcEjustifyCenter) == 0)
595    {
596       val_justify = XcJustifyCenter;
597       CvtDone(XcValueJustify, &val_justify);
598    }
599 
600 /*
601  * If the string is not valid for this resource type, print a warning
602  * and do not make the conversion.
603  */
604    XtStringConversionWarning(fromVal->addr, XcRValueJustify);
605    toVal->addr = NULL;
606    toVal->size = 0;
607 
608 }  /* end of CvtStringToValueJustify */
609 
610 
611 
612 
613 /*******************************************************************
614  NAME:		Correlate.
615  DESCRIPTION:
616    This function takes the given value between the given range and
617 correlates it to the destination range, returning the correlated value.
618 
619 *******************************************************************/
620 
Correlate(from_val,from_range,to_range)621 float Correlate(from_val, from_range, to_range)
622 float from_val, from_range, to_range;
623 {
624 /* Local variables */
625 float percent, result;
626 
627    percent = ((from_val * 100.0) / from_range);
628 
629    result = (to_range * (percent / 100));
630 
631    return result;
632 
633 }  /* end of Correlate */
634 
635 
636 
637 /*********************************************************************
638  FUNCTION:	Print_value.
639  DESCRIPTION:
640   Simply converts a widget's value into a string based on the value's
641 datatype and returns a pointer to it.
642 
643 *********************************************************************/
644 
Print_value(datatype,value,decimals)645 char *Print_value(datatype, value, decimals)
646 XcDType datatype;
647 XcVType *value;
648 int decimals;
649 {
650 static char string[40];
651 
652    if (datatype == XcLval)
653       sprintf(string, "%ld", value->lval);
654    else if (datatype == XcHval)
655       sprintf(string, "%lX", value->lval);
656    else if (datatype == XcFval)
657       sprintf(string, "%.*f", decimals, value->fval);
658 
659    return &string[0];
660 
661 }  /* end of Print_value */
662 
663 
664 
665 
666 /*********************************************************************
667  FUNCTION:	Position_val.
668  DESCRIPTION:
669   This function positions the displayed value within the Value Box based
670 on the XcNvalueJustify resource setting.
671 
672 *********************************************************************/
673 
Position_val(w)674 void Position_val(w)
675 ValueWidget w;
676 {
677 /* Local variables */
678 char *val_string;
679 int text_width;
680 
681 /* Establish the position of the value string within the Value Box. */
682    val_string = Print_value(w->value.datatype, &w->value.val,
683 							w->value.decimals);
684    text_width = XTextWidth(w->control.font, val_string, strlen(val_string));
685 
686    if (w->value.justify == XcJustifyLeft)
687       w->value.vp.x = w->value.value_box.x +
688 			(w->control.font->max_bounds.rbearing / 2 + 0.5);
689    else if (w->value.justify == XcJustifyRight)
690       w->value.vp.x = w->value.value_box.x +
691       		w->value.value_box.width - text_width -
692 			(w->control.font->max_bounds.rbearing / 2 + 0.5);
693    else if (w->value.justify == XcJustifyCenter)
694       w->value.vp.x = w->value.value_box.x +
695                 (w->value.value_box.width / 2 + 0.5) -
696                             (text_width / 2 + 0.5);
697 
698    w->value.vp.y = w->value.value_box.y +
699 		(w->value.value_box.height / 2 + 0.5) +
700 				w->control.font->descent;
701 
702 }  /* end of Position_val */
703 
704 
705 /* end of Value.c */
706 
707