1 
2 /*
3  * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
4  * You may freely copy it for use as a template for your own field types.
5  * If you develop a field type that might be of general use, please send
6  * it back to the ncurses maintainers for inclusion in the next version.
7  */
8 /***************************************************************************
9 *                                                                          *
10 *  Author : Juergen Pfeifer, juergen.pfeifer@gmx.net                       *
11 *                                                                          *
12 ***************************************************************************/
13 
14 #include "form.priv.h"
15 
16 MODULE_ID("$Id$")
17 
18 #if HAVE_LOCALE_H
19 #include <locale.h>
20 #endif
21 
22 typedef struct {
23   int    precision;
24   double low;
25   double high;
26   struct lconv* L;
27 } numericARG;
28 
29 /*---------------------------------------------------------------------------
30 |   Facility      :  libnform
31 |   Function      :  static void *Make_Numeric_Type(va_list * ap)
32 |
33 |   Description   :  Allocate structure for numeric type argument.
34 |
35 |   Return Values :  Pointer to argument structure or NULL on error
36 +--------------------------------------------------------------------------*/
Make_Numeric_Type(va_list * ap)37 static void *Make_Numeric_Type(va_list * ap)
38 {
39   numericARG *argn = (numericARG *)malloc(sizeof(numericARG));
40 
41   if (argn)
42     {
43       argn->precision = va_arg(*ap,int);
44       argn->low       = va_arg(*ap,double);
45       argn->high      = va_arg(*ap,double);
46 #if HAVE_LOCALE_H
47       argn->L         = localeconv();
48 #else
49       argn->L         = NULL;
50 #endif
51     }
52   return (void *)argn;
53 }
54 
55 /*---------------------------------------------------------------------------
56 |   Facility      :  libnform
57 |   Function      :  static void *Copy_Numeric_Type(const void * argp)
58 |
59 |   Description   :  Copy structure for numeric type argument.
60 |
61 |   Return Values :  Pointer to argument structure or NULL on error.
62 +--------------------------------------------------------------------------*/
Copy_Numeric_Type(const void * argp)63 static void *Copy_Numeric_Type(const void * argp)
64 {
65   const numericARG *ap = (const numericARG *)argp;
66   numericARG *result = (numericARG *)0;
67 
68   if (argp)
69     {
70       result = (numericARG *)malloc(sizeof(numericARG));
71       if (result)
72 	*result  = *ap;
73     }
74   return (void *)result;
75 }
76 
77 /*---------------------------------------------------------------------------
78 |   Facility      :  libnform
79 |   Function      :  static void Free_Numeric_Type(void * argp)
80 |
81 |   Description   :  Free structure for numeric type argument.
82 |
83 |   Return Values :  -
84 +--------------------------------------------------------------------------*/
Free_Numeric_Type(void * argp)85 static void Free_Numeric_Type(void * argp)
86 {
87   if (argp)
88     free(argp);
89 }
90 
91 /*---------------------------------------------------------------------------
92 |   Facility      :  libnform
93 |   Function      :  static bool Check_Numeric_Field(FIELD * field,
94 |                                                    const void * argp)
95 |
96 |   Description   :  Validate buffer content to be a valid numeric value
97 |
98 |   Return Values :  TRUE  - field is valid
99 |                    FALSE - field is invalid
100 +--------------------------------------------------------------------------*/
Check_Numeric_Field(FIELD * field,const void * argp)101 static bool Check_Numeric_Field(FIELD * field, const void * argp)
102 {
103   const numericARG *argn = (const numericARG *)argp;
104   double low          = argn->low;
105   double high         = argn->high;
106   int prec            = argn->precision;
107   unsigned char *bp   = (unsigned char *)field_buffer(field,0);
108   char *s             = (char *)bp;
109   double val          = 0.0;
110   char buf[64];
111 
112   while(*bp && *bp==' ') bp++;
113   if (*bp)
114     {
115       if (*bp=='-' || *bp=='+')
116 	bp++;
117       while(*bp)
118 	{
119 	  if (!isdigit(*bp)) break;
120 	  bp++;
121 	}
122       if (*bp==(
123 #if HAVE_LOCALE_H
124 		(L && L->decimal_point) ? *(L->decimal_point) :
125 #endif
126 		'.'))
127 	{
128 	  bp++;
129 	  while(*bp)
130 	    {
131 	      if (!isdigit(*bp)) break;
132 	      bp++;
133 	    }
134 	}
135       while(*bp && *bp==' ') bp++;
136       if (*bp=='\0')
137 	{
138 	  val = atof(s);
139 	  if (low<high)
140 	    {
141 	      if (val<low || val>high) return FALSE;
142 	    }
143 	  sprintf(buf,"%.*f",(prec>0?prec:0),val);
144 	  set_field_buffer(field,0,buf);
145 	  return TRUE;
146 	}
147     }
148   return FALSE;
149 }
150 
151 /*---------------------------------------------------------------------------
152 |   Facility      :  libnform
153 |   Function      :  static bool Check_Numeric_Character(
154 |                                      int c,
155 |                                      const void * argp)
156 |
157 |   Description   :  Check a character for the numeric type.
158 |
159 |   Return Values :  TRUE  - character is valid
160 |                    FALSE - character is invalid
161 +--------------------------------------------------------------------------*/
Check_Numeric_Character(int c,const void * argp)162 static bool Check_Numeric_Character(int c, const void * argp)
163 {
164   argp=0; /* Silence unused parameter warning.  */
165   return (isdigit(c)  ||
166 	  c == '+'    ||
167 	  c == '-'    ||
168 	  c == (
169 #if HAVE_LOCALE_H
170 		(L && L->decimal_point) ? *(L->decimal_point) :
171 #endif
172 		'.')
173 	  ) ? TRUE : FALSE;
174 }
175 
176 static FIELDTYPE typeNUMERIC = {
177   _HAS_ARGS | _RESIDENT,
178   1,                           /* this is mutable, so we can't be const */
179   (FIELDTYPE *)0,
180   (FIELDTYPE *)0,
181   Make_Numeric_Type,
182   Copy_Numeric_Type,
183   Free_Numeric_Type,
184   Check_Numeric_Field,
185   Check_Numeric_Character,
186   NULL,
187   NULL
188 };
189 
190 FIELDTYPE* TYPE_NUMERIC = &typeNUMERIC;
191 
192 /* fty_num.c ends here */
193