blob: 8cce43f83a17fff853bd498a475a877d6e958e7c [file] [log] [blame]
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05301/****************************************************************************
Steve Kondikae271bc2015-11-15 02:50:53 +01002 * Copyright (c) 1998-2010,2012 Free Software Foundation, Inc. *
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05303 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28
29/***************************************************************************
30* *
31* Author : Juergen Pfeifer *
32* *
33***************************************************************************/
34
35#include "form.priv.h"
36
Steve Kondikae271bc2015-11-15 02:50:53 +010037MODULE_ID("$Id: fty_num.c,v 1.29 2012/02/23 10:02:15 tom Exp $")
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +053038
39#if HAVE_LOCALE_H
40#include <locale.h>
41#endif
42
43#if HAVE_LOCALE_H
44#define isDecimalPoint(c) ((c) == ((L && L->decimal_point) ? *(L->decimal_point) : '.'))
45#else
46#define isDecimalPoint(c) ((c) == '.')
47#endif
48
49#if USE_WIDEC_SUPPORT
50#define isDigit(c) (iswdigit((wint_t)(c)) || isdigit(UChar(c)))
51#else
52#define isDigit(c) isdigit(UChar(c))
53#endif
54
55#define thisARG numericARG
56
57typedef struct
58 {
59 int precision;
60 double low;
61 double high;
62 struct lconv *L;
63 }
64thisARG;
65
Steve Kondikae271bc2015-11-15 02:50:53 +010066typedef struct
67 {
68 int precision;
69 double low;
70 double high;
71 }
72thisPARM;
73
74/*---------------------------------------------------------------------------
75| Facility : libnform
76| Function : static void *Generic_This_Type(void * arg)
77|
78| Description : Allocate structure for numeric type argument.
79|
80| Return Values : Pointer to argument structure or NULL on error
81+--------------------------------------------------------------------------*/
82static void *
83Generic_This_Type(void *arg)
84{
85 thisARG *argn = (thisARG *) 0;
86 thisPARM *args = (thisPARM *) arg;
87
88 if (args)
89 {
90 argn = typeMalloc(thisARG, 1);
91
92 if (argn)
93 {
94 T((T_CREATE("thisARG %p"), (void *)argn));
95 argn->precision = args->precision;
96 argn->low = args->low;
97 argn->high = args->high;
98
99#if HAVE_LOCALE_H
100 argn->L = localeconv();
101#else
102 argn->L = NULL;
103#endif
104 }
105 }
106 return (void *)argn;
107}
108
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530109/*---------------------------------------------------------------------------
110| Facility : libnform
111| Function : static void *Make_This_Type(va_list * ap)
112|
113| Description : Allocate structure for numeric type argument.
114|
115| Return Values : Pointer to argument structure or NULL on error
116+--------------------------------------------------------------------------*/
117static void *
118Make_This_Type(va_list *ap)
119{
Steve Kondikae271bc2015-11-15 02:50:53 +0100120 thisPARM arg;
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530121
Steve Kondikae271bc2015-11-15 02:50:53 +0100122 arg.precision = va_arg(*ap, int);
123 arg.low = va_arg(*ap, double);
124 arg.high = va_arg(*ap, double);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530125
Steve Kondikae271bc2015-11-15 02:50:53 +0100126 return Generic_This_Type((void *)&arg);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530127}
128
129/*---------------------------------------------------------------------------
130| Facility : libnform
131| Function : static void *Copy_This_Type(const void * argp)
132|
133| Description : Copy structure for numeric type argument.
134|
135| Return Values : Pointer to argument structure or NULL on error.
136+--------------------------------------------------------------------------*/
137static void *
138Copy_This_Type(const void *argp)
139{
140 const thisARG *ap = (const thisARG *)argp;
141 thisARG *result = (thisARG *) 0;
142
143 if (argp)
144 {
145 result = typeMalloc(thisARG, 1);
146 if (result)
147 {
Steve Kondikae271bc2015-11-15 02:50:53 +0100148 T((T_CREATE("thisARG %p"), (void *)result));
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530149 *result = *ap;
150 }
151 }
152 return (void *)result;
153}
154
155/*---------------------------------------------------------------------------
156| Facility : libnform
157| Function : static void Free_This_Type(void * argp)
158|
159| Description : Free structure for numeric type argument.
160|
161| Return Values : -
162+--------------------------------------------------------------------------*/
163static void
164Free_This_Type(void *argp)
165{
166 if (argp)
167 free(argp);
168}
169
170/*---------------------------------------------------------------------------
171| Facility : libnform
172| Function : static bool Check_This_Field(FIELD * field,
173| const void * argp)
174|
175| Description : Validate buffer content to be a valid numeric value
176|
177| Return Values : TRUE - field is valid
178| FALSE - field is invalid
179+--------------------------------------------------------------------------*/
180static bool
181Check_This_Field(FIELD *field, const void *argp)
182{
183 const thisARG *argn = (const thisARG *)argp;
184 double low = argn->low;
185 double high = argn->high;
186 int prec = argn->precision;
187 unsigned char *bp = (unsigned char *)field_buffer(field, 0);
188 char *s = (char *)bp;
189 double val = 0.0;
190 struct lconv *L = argn->L;
191 char buf[64];
192 bool result = FALSE;
193
194 while (*bp && *bp == ' ')
195 bp++;
196 if (*bp)
197 {
198 if (*bp == '-' || *bp == '+')
199 bp++;
200#if USE_WIDEC_SUPPORT
201 if (*bp)
202 {
203 bool blank = FALSE;
204 int state = 0;
205 int len;
206 int n;
207 wchar_t *list = _nc_Widen_String((char *)bp, &len);
208
209 if (list != 0)
210 {
211 result = TRUE;
212 for (n = 0; n < len; ++n)
213 {
214 if (blank)
215 {
216 if (list[n] != ' ')
217 {
218 result = FALSE;
219 break;
220 }
221 }
222 else if (list[n] == ' ')
223 {
224 blank = TRUE;
225 }
226 else if (isDecimalPoint(list[n]))
227 {
228 if (++state > 1)
229 {
230 result = FALSE;
231 break;
232 }
233 }
234 else if (!isDigit(list[n]))
235 {
236 result = FALSE;
237 break;
238 }
239 }
240 free(list);
241 }
242 }
243#else
244 while (*bp)
245 {
246 if (!isdigit(UChar(*bp)))
247 break;
248 bp++;
249 }
250 if (isDecimalPoint(*bp))
251 {
252 bp++;
253 while (*bp)
254 {
255 if (!isdigit(UChar(*bp)))
256 break;
257 bp++;
258 }
259 }
260 while (*bp && *bp == ' ')
261 bp++;
262 result = (*bp == '\0');
263#endif
264 if (result)
265 {
266 val = atof(s);
267 if (low < high)
268 {
269 if (val < low || val > high)
270 result = FALSE;
271 }
272 if (result)
273 {
Steve Kondikae271bc2015-11-15 02:50:53 +0100274 _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
275 "%.*f", (prec > 0 ? prec : 0), val);
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530276 set_field_buffer(field, 0, buf);
277 }
278 }
279 }
280 return (result);
281}
282
283/*---------------------------------------------------------------------------
284| Facility : libnform
285| Function : static bool Check_This_Character(
286| int c,
287| const void * argp)
288|
289| Description : Check a character for the numeric type.
290|
291| Return Values : TRUE - character is valid
292| FALSE - character is invalid
293+--------------------------------------------------------------------------*/
294static bool
295Check_This_Character(int c, const void *argp)
296{
297 const thisARG *argn = (const thisARG *)argp;
298 struct lconv *L = argn->L;
299
300 return ((isDigit(c) ||
301 c == '+' ||
302 c == '-' ||
303 isDecimalPoint(c))
304 ? TRUE
305 : FALSE);
306}
307
308static FIELDTYPE typeTHIS =
309{
310 _HAS_ARGS | _RESIDENT,
311 1, /* this is mutable, so we can't be const */
312 (FIELDTYPE *)0,
313 (FIELDTYPE *)0,
314 Make_This_Type,
315 Copy_This_Type,
316 Free_This_Type,
Steve Kondikae271bc2015-11-15 02:50:53 +0100317 INIT_FT_FUNC(Check_This_Field),
318 INIT_FT_FUNC(Check_This_Character),
319 INIT_FT_FUNC(NULL),
320 INIT_FT_FUNC(NULL),
321#if NCURSES_INTEROP_FUNCS
322 Generic_This_Type
323#endif
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530324};
325
326NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_NUMERIC = &typeTHIS;
327
Steve Kondikae271bc2015-11-15 02:50:53 +0100328#if NCURSES_INTEROP_FUNCS
329/* The next routines are to simplify the use of ncurses from
330 programming languages with restictions on interop with C level
331 constructs (e.g. variable access or va_list + ellipsis constructs)
332*/
333NCURSES_EXPORT(FIELDTYPE *)
334_nc_TYPE_NUMERIC(void)
335{
336 return TYPE_NUMERIC;
337}
338#endif
339
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +0530340/* fty_num.c ends here */