fty_num.c revision 174994
1114987Speter/****************************************************************************
2114987Speter * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc.              *
3114987Speter *                                                                          *
4114987Speter * Permission is hereby granted, free of charge, to any person obtaining a  *
5114987Speter * copy of this software and associated documentation files (the            *
6114987Speter * "Software"), to deal in the Software without restriction, including      *
7114987Speter * without limitation the rights to use, copy, modify, merge, publish,      *
8114987Speter * distribute, distribute with modifications, sublicense, and/or sell       *
9114987Speter * copies of the Software, and to permit persons to whom the Software is    *
10114987Speter * furnished to do so, subject to the following conditions:                 *
11114987Speter *                                                                          *
12114987Speter * The above copyright notice and this permission notice shall be included  *
13114987Speter * in all copies or substantial portions of the Software.                   *
14114987Speter *                                                                          *
15114987Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16114987Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17114987Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18114987Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19114987Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20114987Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21114987Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22114987Speter *                                                                          *
23114987Speter * Except as contained in this notice, the name(s) of the above copyright   *
24114987Speter * holders shall not be used in advertising or otherwise to promote the     *
25114987Speter * sale, use or other dealings in this Software without prior written       *
26114987Speter * authorization.                                                           *
27114987Speter ****************************************************************************/
28114987Speter
29114987Speter/***************************************************************************
30114987Speter*                                                                          *
31114987Speter*  Author : Juergen Pfeifer                                                *
32114987Speter*                                                                          *
33114987Speter***************************************************************************/
34114987Speter
35114987Speter#include "form.priv.h"
36114987Speter
37114987SpeterMODULE_ID("$Id: fty_num.c,v 1.25 2007/10/13 19:32:54 tom Exp $")
38118031Sobrien
39118031Sobrien#if HAVE_LOCALE_H
40118031Sobrien#include <locale.h>
41114987Speter#endif
42114987Speter
43114987Speter#if HAVE_LOCALE_H
44114987Speter#define isDecimalPoint(c) ((c) == ((L && L->decimal_point) ? *(L->decimal_point) : '.'))
45114987Speter#else
46114987Speter#define isDecimalPoint(c) ((c) == '.')
47114987Speter#endif
48114987Speter
49114987Speter#if USE_WIDEC_SUPPORT
50114987Speter#define isDigit(c) (iswdigit((wint_t)(c)) || isdigit(UChar(c)))
51114987Speter#else
52114987Speter#define isDigit(c) isdigit(UChar(c))
53114987Speter#endif
54114987Speter
55114987Speter#define thisARG numericARG
56114987Speter
57114987Spetertypedef struct
58114987Speter  {
59114987Speter    int precision;
60114987Speter    double low;
61114987Speter    double high;
62114987Speter    struct lconv *L;
63114987Speter  }
64114987SpeterthisARG;
65114987Speter
66114987Speter/*---------------------------------------------------------------------------
67114987Speter|   Facility      :  libnform
68114987Speter|   Function      :  static void *Make_This_Type(va_list * ap)
69114987Speter|
70114987Speter|   Description   :  Allocate structure for numeric type argument.
71114987Speter|
72114987Speter|   Return Values :  Pointer to argument structure or NULL on error
73114987Speter+--------------------------------------------------------------------------*/
74119336Speterstatic void *
75119336SpeterMake_This_Type(va_list *ap)
76119336Speter{
77114987Speter  thisARG *argn = typeMalloc(thisARG, 1);
78114987Speter
79114987Speter  if (argn)
80114987Speter    {
81114987Speter      T((T_CREATE("thisARG %p"), argn));
82114987Speter      argn->precision = va_arg(*ap, int);
83114987Speter      argn->low = va_arg(*ap, double);
84114987Speter      argn->high = va_arg(*ap, double);
85114987Speter
86114987Speter#if HAVE_LOCALE_H
87114987Speter      argn->L = localeconv();
88114987Speter#else
89114987Speter      argn->L = NULL;
90114987Speter#endif
91114987Speter    }
92114987Speter  return (void *)argn;
93114987Speter}
94114987Speter
95114987Speter/*---------------------------------------------------------------------------
96114987Speter|   Facility      :  libnform
97114987Speter|   Function      :  static void *Copy_This_Type(const void * argp)
98114987Speter|
99114987Speter|   Description   :  Copy structure for numeric type argument.
100114987Speter|
101114987Speter|   Return Values :  Pointer to argument structure or NULL on error.
102114987Speter+--------------------------------------------------------------------------*/
103114987Speterstatic void *
104114987SpeterCopy_This_Type(const void *argp)
105114987Speter{
106114987Speter  const thisARG *ap = (const thisARG *)argp;
107114987Speter  thisARG *result = (thisARG *) 0;
108114987Speter
109114987Speter  if (argp)
110114987Speter    {
111114987Speter      result = typeMalloc(thisARG, 1);
112114987Speter      if (result)
113114987Speter	{
114114987Speter	  T((T_CREATE("thisARG %p"), result));
115114987Speter	  *result = *ap;
116114987Speter	}
117114987Speter    }
118114987Speter  return (void *)result;
119114987Speter}
120114987Speter
121114987Speter/*---------------------------------------------------------------------------
122114987Speter|   Facility      :  libnform
123114987Speter|   Function      :  static void Free_This_Type(void * argp)
124114987Speter|
125114987Speter|   Description   :  Free structure for numeric type argument.
126114987Speter|
127114987Speter|   Return Values :  -
128114987Speter+--------------------------------------------------------------------------*/
129114987Speterstatic void
130114987SpeterFree_This_Type(void *argp)
131114987Speter{
132114987Speter  if (argp)
133114987Speter    free(argp);
134114987Speter}
135114987Speter
136114987Speter/*---------------------------------------------------------------------------
137114987Speter|   Facility      :  libnform
138114987Speter|   Function      :  static bool Check_This_Field(FIELD * field,
139114987Speter|                                                 const void * argp)
140114987Speter|
141114987Speter|   Description   :  Validate buffer content to be a valid numeric value
142114987Speter|
143114987Speter|   Return Values :  TRUE  - field is valid
144114987Speter|                    FALSE - field is invalid
145114987Speter+--------------------------------------------------------------------------*/
146114987Speterstatic bool
147114987SpeterCheck_This_Field(FIELD *field, const void *argp)
148114987Speter{
149114987Speter  const thisARG *argn = (const thisARG *)argp;
150114987Speter  double low = argn->low;
151114987Speter  double high = argn->high;
152114987Speter  int prec = argn->precision;
153114987Speter  unsigned char *bp = (unsigned char *)field_buffer(field, 0);
154114987Speter  char *s = (char *)bp;
155114987Speter  double val = 0.0;
156114987Speter  struct lconv *L = argn->L;
157114987Speter  char buf[64];
158114987Speter  bool result = FALSE;
159114987Speter
160114987Speter  while (*bp && *bp == ' ')
161114987Speter    bp++;
162114987Speter  if (*bp)
163114987Speter    {
164114987Speter      if (*bp == '-' || *bp == '+')
165114987Speter	bp++;
166114987Speter#if USE_WIDEC_SUPPORT
167114987Speter      if (*bp)
168114987Speter	{
169114987Speter	  bool blank = FALSE;
170114987Speter	  int state = 0;
171114987Speter	  int len;
172114987Speter	  int n;
173114987Speter	  wchar_t *list = _nc_Widen_String((char *)bp, &len);
174114987Speter
175114987Speter	  if (list != 0)
176114987Speter	    {
177114987Speter	      result = TRUE;
178114987Speter	      for (n = 0; n < len; ++n)
179114987Speter		{
180114987Speter		  if (blank)
181114987Speter		    {
182114987Speter		      if (list[n] != ' ')
183114987Speter			{
184114987Speter			  result = FALSE;
185114987Speter			  break;
186114987Speter			}
187114987Speter		    }
188114987Speter		  else if (list[n] == ' ')
189114987Speter		    {
190114987Speter		      blank = TRUE;
191114987Speter		    }
192114987Speter		  else if (isDecimalPoint(list[n]))
193114987Speter		    {
194114987Speter		      if (++state > 1)
195114987Speter			{
196114987Speter			  result = FALSE;
197114987Speter			  break;
198114987Speter			}
199114987Speter		    }
200114987Speter		  else if (!isDigit(list[n]))
201114987Speter		    {
202114987Speter		      result = FALSE;
203114987Speter		      break;
204114987Speter		    }
205114987Speter		}
206114987Speter	      free(list);
207114987Speter	    }
208114987Speter	}
209114987Speter#else
210114987Speter      while (*bp)
211114987Speter	{
212114987Speter	  if (!isdigit(UChar(*bp)))
213114987Speter	    break;
214114987Speter	  bp++;
215114987Speter	}
216114987Speter      if (isDecimalPoint(*bp))
217114987Speter	{
218114987Speter	  bp++;
219114987Speter	  while (*bp)
220114987Speter	    {
221114987Speter	      if (!isdigit(UChar(*bp)))
222114987Speter		break;
223114987Speter	      bp++;
224114987Speter	    }
225114987Speter	}
226114987Speter      while (*bp && *bp == ' ')
227114987Speter	bp++;
228114987Speter      result = (*bp == '\0');
229114987Speter#endif
230114987Speter      if (result)
231114987Speter	{
232114987Speter	  val = atof(s);
233114987Speter	  if (low < high)
234114987Speter	    {
235114987Speter	      if (val < low || val > high)
236114987Speter		result = FALSE;
237114987Speter	    }
238114987Speter	  if (result)
239114987Speter	    {
240114987Speter	      sprintf(buf, "%.*f", (prec > 0 ? prec : 0), val);
241114987Speter	      set_field_buffer(field, 0, buf);
242114987Speter	    }
243114987Speter	}
244114987Speter    }
245114987Speter  return (result);
246114987Speter}
247114987Speter
248114987Speter/*---------------------------------------------------------------------------
249114987Speter|   Facility      :  libnform
250114987Speter|   Function      :  static bool Check_This_Character(
251114987Speter|                                      int c,
252114987Speter|                                      const void * argp)
253114987Speter|
254114987Speter|   Description   :  Check a character for the numeric type.
255114987Speter|
256114987Speter|   Return Values :  TRUE  - character is valid
257114987Speter|                    FALSE - character is invalid
258114987Speter+--------------------------------------------------------------------------*/
259114987Speterstatic bool
260114987SpeterCheck_This_Character(int c, const void *argp)
261114987Speter{
262114987Speter  const thisARG *argn = (const thisARG *)argp;
263114987Speter  struct lconv *L = argn->L;
264114987Speter
265114987Speter  return ((isDigit(c) ||
266114987Speter	   c == '+' ||
267119336Speter	   c == '-' ||
268114987Speter	   isDecimalPoint(c))
269114987Speter	  ? TRUE
270114987Speter	  : FALSE);
271114987Speter}
272114987Speter
273114987Speterstatic FIELDTYPE typeTHIS =
274114987Speter{
275114987Speter  _HAS_ARGS | _RESIDENT,
276114987Speter  1,				/* this is mutable, so we can't be const */
277114987Speter  (FIELDTYPE *)0,
278114987Speter  (FIELDTYPE *)0,
279114987Speter  Make_This_Type,
280114987Speter  Copy_This_Type,
281114987Speter  Free_This_Type,
282114987Speter  Check_This_Field,
283114987Speter  Check_This_Character,
284114987Speter  NULL,
285114987Speter  NULL
286114987Speter};
287114987Speter
288114987SpeterNCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_NUMERIC = &typeTHIS;
289114987Speter
290114987Speter/* fty_num.c ends here */
291114987Speter