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