fty_num.c revision 50276
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
16MODULE_ID("$Id: fty_num.c,v 1.13 1999/05/16 17:23:30 juergen Exp $")
17
18#if HAVE_LOCALE_H
19#include <locale.h>
20#endif
21
22typedef 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+--------------------------------------------------------------------------*/
37static 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+--------------------------------------------------------------------------*/
63static 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+--------------------------------------------------------------------------*/
85static 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+--------------------------------------------------------------------------*/
101static 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  struct lconv* L     = argn->L;
111  char buf[64];
112
113  while(*bp && *bp==' ') bp++;
114  if (*bp)
115    {
116      if (*bp=='-' || *bp=='+')
117	bp++;
118      while(*bp)
119	{
120	  if (!isdigit(*bp)) break;
121	  bp++;
122	}
123      if (*bp==(
124#if HAVE_LOCALE_H
125		(L && L->decimal_point) ? *(L->decimal_point) :
126#endif
127		'.'))
128	{
129	  bp++;
130	  while(*bp)
131	    {
132	      if (!isdigit(*bp)) break;
133	      bp++;
134	    }
135	}
136      while(*bp && *bp==' ') bp++;
137      if (*bp=='\0')
138	{
139	  val = atof(s);
140	  if (low<high)
141	    {
142	      if (val<low || val>high) return FALSE;
143	    }
144	  sprintf(buf,"%.*f",(prec>0?prec:0),val);
145	  set_field_buffer(field,0,buf);
146	  return TRUE;
147	}
148    }
149  return FALSE;
150}
151
152/*---------------------------------------------------------------------------
153|   Facility      :  libnform
154|   Function      :  static bool Check_Numeric_Character(
155|                                      int c,
156|                                      const void * argp)
157|
158|   Description   :  Check a character for the numeric type.
159|
160|   Return Values :  TRUE  - character is valid
161|                    FALSE - character is invalid
162+--------------------------------------------------------------------------*/
163static bool Check_Numeric_Character(int c, const void * argp)
164{
165  const numericARG *argn = (const numericARG *)argp;
166  struct lconv* L  = argn->L;
167
168  return (isdigit(c)  ||
169	  c == '+'    ||
170	  c == '-'    ||
171	  c == (
172#if HAVE_LOCALE_H
173		(L && L->decimal_point) ? *(L->decimal_point) :
174#endif
175		'.')
176	  ) ? TRUE : FALSE;
177}
178
179static FIELDTYPE typeNUMERIC = {
180  _HAS_ARGS | _RESIDENT,
181  1,                           /* this is mutable, so we can't be const */
182  (FIELDTYPE *)0,
183  (FIELDTYPE *)0,
184  Make_Numeric_Type,
185  Copy_Numeric_Type,
186  Free_Numeric_Type,
187  Check_Numeric_Field,
188  Check_Numeric_Character,
189  NULL,
190  NULL
191};
192
193FIELDTYPE* TYPE_NUMERIC = &typeNUMERIC;
194
195/* fty_num.c ends here */
196