1 #include <cdk_int.h>
2 
3 /*
4  * $Author: tom $
5  * $Date: 2016/11/20 18:29:20 $
6  * $Revision: 1.28 $
7  */
8 
9 /*
10  * Declare file local prototypes.
11  */
12 static void drawCDK<MIXED>Field (CDK<UPPER> *widget);
13 static int formattedSize (CDK<UPPER> *widget, <CTYPE> value);
14 
15 DeclareCDKObjects (<UPPER>, <MIXED>, setCdk, <DTYPE>);
16 
17 /*
18  * This function creates a widget.
19  */
20 CDK<UPPER> *newCDK<MIXED> (CDKSCREEN *cdkscreen,
21 			   int xplace,
22 			   int yplace,
23 			   const char *title,
24 			   const char *label,
25 			   chtype filler,
26 			   int fieldWidth,
27 			   <CTYPE> start,
28 			   <CTYPE> low,
29 			   <CTYPE> high,
30 			   <CTYPE> inc,
31 			   <CTYPE> fastInc,
32 #if <FLOAT>
33 			   int digits,
34 #endif <FLOAT>
35 			   boolean Box,
36 			   boolean shadow)
37 {
38    /* *INDENT-EQLS* */
39    CDK<UPPER> *widget   = 0;
40    int parentWidth      = getmaxx (cdkscreen->window);
41    int parentHeight     = getmaxy (cdkscreen->window);
42    int boxHeight;
43    int boxWidth         = 0;
44    int horizontalAdjust, oldWidth;
45    int xpos             = xplace;
46    int ypos             = yplace;
47    int highValueLen;
48    int x, junk;
49    /* *INDENT-OFF* */
50    static const struct { int from; int to; } bindings[] = {
51 		{ 'u',		KEY_UP },
52 		{ 'U',		KEY_PPAGE },
53 		{ CDK_BACKCHAR,	KEY_PPAGE },
54 		{ CDK_FORCHAR,	KEY_NPAGE },
55 		{ 'g',		KEY_HOME },
56 		{ '^',		KEY_HOME },
57 		{ 'G',		KEY_END },
58 		{ '$',		KEY_END },
59    };
60    /* *INDENT-ON* */
61 
62 
63    if ((widget = newCDKObject (CDK<UPPER>, &my_funcs)) == 0)
64       return (0);
65 
66    setCDK<MIXED>Box (widget, Box);
67    boxHeight = (BorderOf (widget) * 2) + 1;
68 
69    /* *INDENT-EQLS* Set some basic values of the widget's data field. */
70    widget->label        = 0;
71    widget->labelLen     = 0;
72    widget->labelWin     = 0;
73 #if <FLOAT>
74    widget->digits       = digits;
75 #endif <FLOAT>
76    highValueLen         = MAXIMUM (formattedSize (widget, low),
77 			           formattedSize (widget, high));
78 
79    /*
80     * If the fieldWidth is a negative value, the fieldWidth will
81     * be COLS-fieldWidth, otherwise, the fieldWidth will be the
82     * given width.
83     */
84    fieldWidth = setWidgetDimension (parentWidth, fieldWidth, 0);
85 
86    /* Translate the label char *pointer to a chtype pointer. */
87    if (label != 0)
88    {
89       widget->label = char2Chtype (label, &widget->labelLen, &junk);
90       boxWidth = widget->labelLen + fieldWidth + highValueLen + 2 * BorderOf (widget);
91    }
92    else
93    {
94       boxWidth = fieldWidth + highValueLen + 2 * BorderOf (widget);
95    }
96 
97    oldWidth = boxWidth;
98    boxWidth = setCdkTitle (ObjOf (widget), title, boxWidth);
99    horizontalAdjust = (boxWidth - oldWidth) / 2;
100 
101    boxHeight += TitleLinesOf (widget);
102 
103    /*
104     * Make sure we didn't extend beyond the dimensions of the window.
105     */
106    boxWidth = (boxWidth > parentWidth ? parentWidth : boxWidth);
107    boxHeight = (boxHeight > parentHeight ? parentHeight : boxHeight);
108    fieldWidth = (fieldWidth > (boxWidth - widget->labelLen - highValueLen - 1)
109 		 ? (boxWidth - widget->labelLen - highValueLen - 1)
110 		 : fieldWidth);
111 
112    /* Rejustify the x and y positions if we need to. */
113    alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
114 
115    /* Make the widget's window. */
116    widget->win = newwin (boxHeight, boxWidth, ypos, xpos);
117 
118    /* Is the main window null??? */
119    if (widget->win == 0)
120    {
121       destroyCDKObject (widget);
122       return (0);
123    }
124 
125    /* Create the widget's label window. */
126    if (widget->label != 0)
127    {
128       widget->labelWin = subwin (widget->win,
129 				 1, widget->labelLen,
130 				 ypos + TitleLinesOf (widget) + BorderOf (widget),
131 				 xpos + horizontalAdjust + BorderOf (widget));
132       if (widget->labelWin == 0)
133       {
134 	 destroyCDKObject (widget);
135 	 return (0);
136       }
137    }
138 
139    /* Create the widget's data field window. */
140    widget->fieldWin = subwin (widget->win,
141 			      1, fieldWidth + highValueLen - 1,
142 			      (ypos + TitleLinesOf (widget) + BorderOf (widget)),
143 			      (xpos
144 			       + widget->labelLen
145 			       + horizontalAdjust
146 			       + BorderOf (widget)));
147    if (widget->fieldWin == 0)
148    {
149       destroyCDKObject (widget);
150       return (0);
151    }
152    keypad (widget->fieldWin, TRUE);
153    keypad (widget->win, TRUE);
154 
155    /* *INDENT-EQLS* Create the widget's data field. */
156    ScreenOf (widget)            = cdkscreen;
157    widget->parent               = cdkscreen->window;
158    widget->shadowWin            = 0;
159    widget->boxWidth             = boxWidth;
160    widget->boxHeight            = boxHeight;
161    widget->fieldWidth           = fieldWidth - 1;
162    widget->filler               = filler;
163    widget->low                  = low;
164    widget->high                 = high;
165    widget->current              = start;
166    widget->inc                  = inc;
167    widget->fastinc              = fastInc;
168    initExitType (widget);
169    ObjOf (widget)->acceptsFocus = TRUE;
170    ObjOf (widget)->inputWindow  = widget->win;
171    widget->shadow               = shadow;
172 
173    /* Set the start value. */
174    if (start < low)
175    {
176       widget->current = low;
177    }
178 
179    /* Do we want a shadow??? */
180    if (shadow)
181    {
182       widget->shadowWin = newwin (boxHeight, boxWidth, ypos + 1, xpos + 1);
183       if (widget->shadowWin == 0)
184       {
185 	 destroyCDKObject (widget);
186 	 return (0);
187       }
188    }
189 
190    /* Setup the key bindings. */
191    for (x = 0; x < (int)SIZEOF (bindings); ++x)
192       bindCDKObject (v<UPPER>,
193 		     widget,
194 		     (chtype)bindings[x].from,
195 		     getcCDKBind,
196 		     (void *)(long)bindings[x].to);
197 
198    registerCDKObject (cdkscreen, v<UPPER>, widget);
199 
200    return (widget);
201 }
202 
203 /*
204  * This allows the person to use the widget's data field.
205  */
206 <CTYPE> activateCDK<MIXED> (CDK<UPPER> *widget, chtype *actions)
207 {
208    <CTYPE> ret;
209 
210    /* Draw the widget. */
211    drawCDK<MIXED> (widget, ObjOf (widget)->box);
212 
213    if (actions == 0)
214    {
215       chtype input = 0;
216       boolean functionKey;
217 
218       for (;;)
219       {
220 	 input = (chtype)getchCDKObject (ObjOf (widget), &functionKey);
221 
222 	 /* Inject the character into the widget. */
223 	 ret = (<CTYPE>)injectCDK<MIXED> (widget, input);
224 	 if (widget->exitType != vEARLY_EXIT)
225 	 {
226 	    return ret;
227 	 }
228       }
229    }
230    else
231    {
232       int length = chlen (actions);
233       int x = 0;
234 
235       /* Inject each character one at a time. */
236       for (x = 0; x < length; x++)
237       {
238 	 ret = (<CTYPE>)injectCDK<MIXED> (widget, actions[x]);
239 	 if (widget->exitType != vEARLY_EXIT)
240 	 {
241 	    return ret;
242 	 }
243       }
244    }
245 
246    /* Set the exit type and return. */
247    setExitType (widget, 0);
248    return unknown<DTYPE>;
249 }
250 
251 /*
252  * Check if the value lies outside the low/high range.  If so, force it in.
253  */
limitCurrentValue(CDK<UPPER> * widget)254 static void limitCurrentValue (CDK<UPPER> *widget)
255 {
256    if (widget->current < widget->low)
257    {
258       widget->current = widget->low;
259       Beep ();
260    }
261    else if (widget->current > widget->high)
262    {
263       widget->current = widget->high;
264       Beep ();
265    }
266 }
267 
268 /*
269  * Move the cursor to the given edit-position.
270  */
moveToEditPosition(CDK<UPPER> * widget,int newPosition)271 static int moveToEditPosition (CDK<UPPER> *widget, int newPosition)
272 {
273    return wmove (widget->fieldWin,
274 		 0,
275 		 widget->fieldWidth +
276 		 formattedSize (widget, widget->current) -
277 		 newPosition);
278 }
279 
280 /*
281  * Check if the cursor is on a valid edit-position.  This must be one of
282  * the non-blank cells in the field.
283  */
validEditPosition(CDK<UPPER> * widget,int newPosition)284 static int validEditPosition (CDK<UPPER> *widget, int newPosition)
285 {
286    chtype ch;
287    if (newPosition <= 0 || newPosition >= widget->fieldWidth)
288       return FALSE;
289    if (moveToEditPosition (widget, newPosition) == ERR)
290       return FALSE;
291    ch = winch (widget->fieldWin);
292    if (CharOf (ch) != ' ')
293       return TRUE;
294    if (newPosition > 1)
295    {
296       /* don't use recursion - only one level is wanted */
297       if (moveToEditPosition (widget, newPosition - 1) == ERR)
298 	 return FALSE;
299       ch = winch (widget->fieldWin);
300       return CharOf (ch) != ' ';
301    }
302    return FALSE;
303 }
304 
305 /*
306  * Set the edit position.  Normally the cursor is one cell to the right of
307  * the editable field.  Moving it left, over the field allows the user to
308  * modify cells by typing in replacement characters for the field's value.
309  */
setEditPosition(CDK<UPPER> * widget,int newPosition)310 static void setEditPosition (CDK<UPPER> *widget, int newPosition)
311 {
312    if (newPosition < 0)
313    {
314       Beep ();
315    }
316    else if (newPosition == 0)
317    {
318       widget->fieldEdit = newPosition;
319    }
320    else if (validEditPosition (widget, newPosition))
321    {
322       widget->fieldEdit = newPosition;
323    }
324    else
325    {
326       Beep ();
327    }
328 }
329 
330 /*
331  * Remove the character from the string at the given column, if it is blank.
332  * Returns true if a change was made.
333  */
removeChar(char * string,int col)334 static bool removeChar (char *string, int col)
335 {
336    bool result = FALSE;
337 
338    if ((col >= 0) && (string[col] != ' '))
339    {
340       while (string[col] != '\0')
341       {
342 	 string[col] = string[col + 1];
343 	 ++col;
344       }
345       result = TRUE;
346    }
347    return result;
348 }
349 
350 /*
351  * Perform an editing function for the field.
352  */
performEdit(CDK<UPPER> * widget,chtype input)353 static bool performEdit (CDK<UPPER> *widget, chtype input)
354 {
355    bool result = FALSE;
356    bool modify = TRUE;
357    int base = widget->fieldWidth;
358    int need = formattedSize (widget, widget->current);
359    char *temp = (char *)malloc ((size_t) need + 5);
360    char *data = temp;
361    char test;
362    int col = need - widget->fieldEdit;
363 #if <FLOAT>
364    double value;
365 #define SCANF_FMT "%lg%c"
366 #endif <FLOAT>
367 #if <INT>
368    <CTYPE> value;
369 #define SCANF_FMT "%<PRINT>%c"
370 #endif <INT>
371 
372    if (temp != 0)
373    {
374       int adj = (col < 0) ? (-col) : 0;
375       if (adj)
376       {
377 	 memset (temp, ' ', (size_t) adj);
378 	 temp += adj;
379       }
380       wmove (widget->fieldWin, 0, base);
381       winnstr (widget->fieldWin, temp, need);
382       strcpy (temp + need, " ");
383       if (isChar (input))	/* replace the char at the cursor */
384       {
385 	 temp[col] = (char)(input);
386       }
387       else if (input == KEY_BACKSPACE)	/* delete the char before the cursor */
388       {
389 	 modify = removeChar (temp, col - 1);
390       }
391       else if (input == KEY_DC)	/* delete the char at the cursor */
392       {
393 	 modify = removeChar (temp, col);
394       }
395       else
396       {
397 	 modify = FALSE;
398       }
399       if (modify
400 	  && sscanf (temp, SCANF_FMT, &value, &test) == 2
401 	  && test == ' '
402 	  && value >= widget->low
403 	  && value <= widget->high)
404       {
405 	 setCDK<MIXED>Value (widget, (<CTYPE>)value);
406 	 result = TRUE;
407       }
408       free (data);
409    }
410    return result;
411 }
412 
413 #define Decrement(value,by) if (value - by < value) value -= by
414 #define Increment(value,by) if (value + by > value) value += by
415 
416 /*
417  * This function injects a single character into the widget.
418  */
419 static int _injectCDK<MIXED> (CDKOBJS *object, chtype input)
420 {
421    CDK<UPPER> *widget = (CDK<UPPER> *)object;
422    int ppReturn = 1;
423    <CTYPE> ret = unknown<DTYPE>;
424    bool complete = FALSE;
425 
426    /* Set the exit type. */
427    setExitType (widget, 0);
428 
429    /* Draw the field. */
430    drawCDK<MIXED>Field (widget);
431 
432    /* Check if there is a pre-process function to be called. */
433    if (PreProcessFuncOf (widget) != 0)
434    {
435       /* Call the pre-process function. */
436       ppReturn = PreProcessFuncOf (widget) (v<UPPER>,
437 					    widget,
438 					    PreProcessDataOf (widget),
439 					    input);
440    }
441 
442    /* Should we continue? */
443    if (ppReturn != 0)
444    {
445       /* Check for a key binding. */
446       if (checkCDKObjectBind (v<UPPER>, widget, input) != 0)
447       {
448 	 checkEarlyExit (widget);
449 	 complete = TRUE;
450       }
451       else
452       {
453 	 switch (input)
454 	 {
455 	 case KEY_LEFT:
456 	    setEditPosition (widget, widget->fieldEdit + 1);
457 	    break;
458 
459 	 case KEY_RIGHT:
460 	    setEditPosition (widget, widget->fieldEdit - 1);
461 	    break;
462 
463 	 case KEY_DOWN:
464 	    Decrement (widget->current, widget->inc);
465 	    break;
466 
467 	 case KEY_UP:
468 	    Increment (widget->current, widget->inc);
469 	    break;
470 
471 	 case KEY_PPAGE:
472 	    Increment (widget->current, widget->fastinc);
473 	    break;
474 
475 	 case KEY_NPAGE:
476 	    Decrement (widget->current, widget->fastinc);
477 	    break;
478 
479 	 case KEY_HOME:
480 	    widget->current = widget->low;
481 	    break;
482 
483 	 case KEY_END:
484 	    widget->current = widget->high;
485 	    break;
486 
487 	 case KEY_TAB:
488 	 case KEY_ENTER:
489 	    setExitType (widget, input);
490 	    ret = (widget->current);
491 	    complete = TRUE;
492 	    break;
493 
494 	 case KEY_ESC:
495 	    setExitType (widget, input);
496 	    complete = TRUE;
497 	    break;
498 
499 	 case KEY_ERROR:
500 	    setExitType (widget, input);
501 	    complete = TRUE;
502 	    break;
503 
504 	 case CDK_REFRESH:
505 	    eraseCDKScreen (ScreenOf (widget));
506 	    refreshCDKScreen (ScreenOf (widget));
507 	    break;
508 
509 	 default:
510 	    if (widget->fieldEdit)
511 	    {
512 	       if (!performEdit (widget, input))
513 		  Beep ();
514 	    }
515 	    else
516 	    {
517 	       /*
518 	        * The cursor is not within the editable text.  Interpret
519 	        * input as commands.
520 	        */
521 	       switch (input)
522 	       {
523 	       case 'd':
524 	       case '-':
525 		  return _injectCDK<MIXED> (object, KEY_DOWN);
526 	       case '+':
527 		  return _injectCDK<MIXED> (object, KEY_UP);
528 	       case 'D':
529 		  return _injectCDK<MIXED> (object, KEY_NPAGE);
530 	       case '0':
531 		  return _injectCDK<MIXED> (object, KEY_HOME);
532 	       default:
533 		  Beep ();
534 		  break;
535 	       }
536 	    }
537 	    break;
538 	 }
539       }
540       limitCurrentValue (widget);
541 
542       /* Should we call a post-process? */
543       if (!complete && (PostProcessFuncOf (widget) != 0))
544       {
545 	 PostProcessFuncOf (widget) (v<UPPER>,
546 				     widget,
547 				     PostProcessDataOf (widget),
548 				     input);
549       }
550    }
551 
552    if (!complete)
553    {
554       drawCDK<MIXED>Field (widget);
555       setExitType (widget, 0);
556    }
557 
558    ResultOf (widget).value<DTYPE> = ret;
559    return (ret != unknown<DTYPE>);
560 }
561 
562 /*
563  * This moves the widget's data field to the given location.
564  */
565 static void _moveCDK<MIXED> (CDKOBJS *object,
566 			     int xplace,
567 			     int yplace,
568 			     boolean relative,
569 			     boolean refresh_flag)
570 {
571    /* *INDENT-EQLS* */
572    CDK<UPPER> *widget = (CDK<UPPER> *)object;
573    int currentX       = getbegx (widget->win);
574    int currentY       = getbegy (widget->win);
575    int xpos           = xplace;
576    int ypos           = yplace;
577    int xdiff          = 0;
578    int ydiff          = 0;
579 
580    /*
581     * If this is a relative move, then we will adjust where we want
582     * to move to.
583     */
584    if (relative)
585    {
586       xpos = getbegx (widget->win) + xplace;
587       ypos = getbegy (widget->win) + yplace;
588    }
589 
590    /* Adjust the window if we need to. */
591    alignxy (WindowOf (widget), &xpos, &ypos, widget->boxWidth, widget->boxHeight);
592 
593    /* Get the difference. */
594    xdiff = currentX - xpos;
595    ydiff = currentY - ypos;
596 
597    /* Move the window to the new location. */
598    moveCursesWindow (widget->win, -xdiff, -ydiff);
599    moveCursesWindow (widget->labelWin, -xdiff, -ydiff);
600    moveCursesWindow (widget->fieldWin, -xdiff, -ydiff);
601    moveCursesWindow (widget->shadowWin, -xdiff, -ydiff);
602 
603    /* Touch the windows so they 'move'. */
604    refreshCDKWindow (WindowOf (widget));
605 
606    /* Redraw the window, if they asked for it. */
607    if (refresh_flag)
608    {
609       drawCDK<MIXED> (widget, ObjOf (widget)->box);
610    }
611 }
612 
613 /*
614  * This function draws the widget.
615  */
616 static void _drawCDK<MIXED> (CDKOBJS *object, boolean Box)
617 {
618    CDK<UPPER> *widget = (CDK<UPPER> *)object;
619 
620    /* Draw the shadow. */
621    if (widget->shadowWin != 0)
622    {
623       drawShadow (widget->shadowWin);
624    }
625 
626    /* Box the widget if asked. */
627    if (Box)
628    {
629       drawObjBox (widget->win, ObjOf (widget));
630    }
631 
632    drawCdkTitle (widget->win, object);
633 
634    /* Draw the label. */
635    if (widget->labelWin != 0)
636    {
637       writeChtype (widget->labelWin, 0, 0,
638 		   widget->label,
639 		   HORIZONTAL, 0,
640 		   widget->labelLen);
641       wrefresh (widget->labelWin);
642    }
643    wrefresh (widget->win);
644 
645    /* Draw the field window. */
646    drawCDK<MIXED>Field (widget);
647 }
648 
649 /*
650  * This draws the widget.
651  */
Field(CDK<UPPER> * widget)652 static void drawCDK<MIXED>Field (CDK<UPPER> *widget)
653 {
654    int fillerCharacters, x;
655    char temp[256];
656    double step = ((double)widget->fieldWidth /
657 		  (double)(widget->high - widget->low));
658 
659    /* Determine how many filler characters need to be drawn. */
660    fillerCharacters = (int)((widget->current - widget->low) * step);
661 
662    werase (widget->fieldWin);
663 
664    /* Add the character to the window. */
665    for (x = 0; x < fillerCharacters; x++)
666    {
667       (void)mvwaddch (widget->fieldWin, 0, x, widget->filler);
668    }
669 
670    /* Draw the value in the field. */
671 #if <FLOAT>
672    {
673       char format[256];
674       int digits = MINIMUM (widget->digits, 30);
675       sprintf (format, "%%.%i<PRINT>", digits);
676       sprintf (temp, format, widget->current);
677    }
678 #endif <FLOAT>
679 #if <INT>
680    sprintf (temp, "%<PRINT>", widget->current);
681 #endif <INT>
682    writeCharAttrib (widget->fieldWin,
683 		    widget->fieldWidth,
684 		    0,
685 		    temp,
686 		    A_NORMAL,
687 		    HORIZONTAL,
688 		    0,
689 		    (int)strlen (temp));
690 
691    moveToEditPosition (widget, widget->fieldEdit);
692    wrefresh (widget->fieldWin);
693 }
694 
695 /*
696  * This sets the background attribute of the widget.
697  */
698 static void _setBKattr<MIXED> (CDKOBJS *object, chtype attrib)
699 {
700    if (object != 0)
701    {
702       CDK<UPPER> *widget = (CDK<UPPER> *)object;
703 
704       /* Set the widgets background attribute. */
705       wbkgd (widget->win, attrib);
706       wbkgd (widget->fieldWin, attrib);
707       if (widget->labelWin != 0)
708       {
709 	 wbkgd (widget->labelWin, attrib);
710       }
711    }
712 }
713 
714 /*
715  * This function destroys the widget.
716  */
717 static void _destroyCDK<MIXED> (CDKOBJS *object)
718 {
719    if (object != 0)
720    {
721       CDK<UPPER> *widget = (CDK<UPPER> *)object;
722 
723       cleanCdkTitle (object);
724       freeChtype (widget->label);
725 
726       /* Clean up the windows. */
727       deleteCursesWindow (widget->fieldWin);
728       deleteCursesWindow (widget->labelWin);
729       deleteCursesWindow (widget->shadowWin);
730       deleteCursesWindow (widget->win);
731 
732       /* Clean the key bindings. */
733       cleanCDKObjectBindings (v<UPPER>, widget);
734 
735       /* Unregister this object. */
736       unregisterCDKObject (v<UPPER>, widget);
737    }
738 }
739 
740 /*
741  * This function erases the widget from the screen.
742  */
743 static void _eraseCDK<MIXED> (CDKOBJS *object)
744 {
745    if (validCDKObject (object))
746    {
747       CDK<UPPER> *widget = (CDK<UPPER> *)object;
748 
749       eraseCursesWindow (widget->labelWin);
750       eraseCursesWindow (widget->fieldWin);
751       eraseCursesWindow (widget->win);
752       eraseCursesWindow (widget->shadowWin);
753    }
754 }
755 
756 static int formattedSize (CDK<UPPER> *widget, <CTYPE> value)
757 {
758    char temp[256];
759 #if <FLOAT>
760    char format[256];
761    int digits = MINIMUM (widget->digits, 30);
762    sprintf (format, "%%.%i<PRINT>", digits);
763    sprintf (temp, format, value);
764 #endif <FLOAT>
765 #if <INT>
766    (void)widget;
767    sprintf (temp, "%<PRINT>", value);
768 #endif <INT>
769    return (int) strlen (temp);
770 }
771 
772 /*
773  * This function sets the low/high/current values of the widget.
774  */
775 void setCDK<MIXED> (CDK<UPPER> *widget,
776 		    <CTYPE> low,
777 		    <CTYPE> high,
778 		    <CTYPE> value,
779 		    boolean Box)
780 {
781    setCDK<MIXED>LowHigh (widget, low, high);
782    setCDK<MIXED>Value (widget, value);
783    setCDK<MIXED>Box (widget, Box);
784 }
785 
786 /*
787  * This sets the digits.
788  */
789 #if <FLOAT>
Digits(CDK<UPPER> * widget,int digits)790 void setCDK<MIXED>Digits (CDK<UPPER> *widget, int digits)
791 {
792    widget->digits = MAXIMUM (0, digits);
793 }
794 
Digits(CDK<UPPER> * widget)795 int getCDK<MIXED>Digits (CDK<UPPER> *widget)
796 {
797    return widget->digits;
798 }
799 #endif <FLOAT>
800 
801 /*
802  * This sets the widget's value.
803  */
804 void setCDK<MIXED>Value (CDK<UPPER> *widget, <CTYPE> value)
805 {
806    widget->current = value;
807    limitCurrentValue (widget);
808 }
Value(CDK<UPPER> * widget)809 <CTYPE> getCDK<MIXED>Value (CDK<UPPER> *widget)
810 {
811    return widget->current;
812 }
813 
814 /*
815  * This function sets the low/high values of the widget.
816  */
817 void setCDK<MIXED>LowHigh (CDK<UPPER> *widget, <CTYPE> low, <CTYPE> high)
818 {
819    /* Make sure the values aren't out of bounds. */
820    if (low <= high)
821    {
822       widget->low = low;
823       widget->high = high;
824    }
825    else
826    {
827       widget->low = high;
828       widget->high = low;
829    }
830 
831    /* Make sure the user hasn't done something silly. */
832    limitCurrentValue (widget);
833 }
LowValue(CDK<UPPER> * widget)834 <CTYPE> getCDK<MIXED>LowValue (CDK<UPPER> *widget)
835 {
836    return widget->low;
837 }
HighValue(CDK<UPPER> * widget)838 <CTYPE> getCDK<MIXED>HighValue (CDK<UPPER> *widget)
839 {
840    return widget->high;
841 }
842 
843 /*
844  * This sets the widget's box attribute.
845  */
Box(CDK<UPPER> * widget,boolean Box)846 void setCDK<MIXED>Box (CDK<UPPER> *widget, boolean Box)
847 {
848    ObjOf (widget)->box = Box;
849    ObjOf (widget)->borderSize = Box ? 1 : 0;
850 }
Box(CDK<UPPER> * widget)851 boolean getCDK<MIXED>Box (CDK<UPPER> *widget)
852 {
853    return ObjOf (widget)->box;
854 }
855 
856 static void _focusCDK<MIXED> (CDKOBJS *object)
857 {
858    CDK<UPPER> *widget = (CDK<UPPER> *)object;
859 
860    drawCDK<MIXED> (widget, ObjOf (widget)->box);
861 }
862 
863 static void _unfocusCDK<MIXED> (CDKOBJS *object)
864 {
865    CDK<UPPER> *widget = (CDK<UPPER> *)object;
866 
867    drawCDK<MIXED> (widget, ObjOf (widget)->box);
868 }
869 
870 dummyRefreshData (<MIXED>)
871 
872 dummySaveData (<MIXED>)
873