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