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