ncurses 5.3
[ncurses.git] / form / fty_num.c
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                                                *
11 *  Contact: http://www.familiepfeifer.de/Contact.aspx?Lang=en              *
12 *                                                                          *
13 ***************************************************************************/
14
15 #include "form.priv.h"
16
17 MODULE_ID("$Id: fty_num.c,v 1.15 2002/07/06 15:33:27 juergen Exp $")
18
19 #if HAVE_LOCALE_H
20 #include <locale.h>
21 #endif
22
23 typedef struct {
24   int    precision;
25   double low;
26   double high;
27   struct lconv* L;
28 } numericARG;
29
30 /*---------------------------------------------------------------------------
31 |   Facility      :  libnform  
32 |   Function      :  static void *Make_Numeric_Type(va_list * ap)
33 |   
34 |   Description   :  Allocate structure for numeric type argument.
35 |
36 |   Return Values :  Pointer to argument structure or NULL on error
37 +--------------------------------------------------------------------------*/
38 static void *Make_Numeric_Type(va_list * ap)
39 {
40   numericARG *argn = (numericARG *)malloc(sizeof(numericARG));
41
42   if (argn)
43     {
44       argn->precision = va_arg(*ap,int);
45       argn->low       = va_arg(*ap,double);
46       argn->high      = va_arg(*ap,double);
47 #if HAVE_LOCALE_H
48       argn->L         = localeconv();
49 #else
50       argn->L         = NULL;
51 #endif
52     }
53   return (void *)argn;
54 }
55
56 /*---------------------------------------------------------------------------
57 |   Facility      :  libnform  
58 |   Function      :  static void *Copy_Numeric_Type(const void * argp)
59 |   
60 |   Description   :  Copy structure for numeric type argument.  
61 |
62 |   Return Values :  Pointer to argument structure or NULL on error.
63 +--------------------------------------------------------------------------*/
64 static void *Copy_Numeric_Type(const void * argp)
65 {
66   const numericARG *ap = (const numericARG *)argp;
67   numericARG *result = (numericARG *)0;
68
69   if (argp)
70     {
71       result = (numericARG *)malloc(sizeof(numericARG));
72       if (result)
73         *result  = *ap;
74     }
75   return (void *)result;
76 }
77
78 /*---------------------------------------------------------------------------
79 |   Facility      :  libnform  
80 |   Function      :  static void Free_Numeric_Type(void * argp)
81 |   
82 |   Description   :  Free structure for numeric type argument.
83 |
84 |   Return Values :  -
85 +--------------------------------------------------------------------------*/
86 static void Free_Numeric_Type(void * argp)
87 {
88   if (argp) 
89     free(argp);
90 }
91
92 /*---------------------------------------------------------------------------
93 |   Facility      :  libnform  
94 |   Function      :  static bool Check_Numeric_Field(FIELD * field,
95 |                                                    const void * argp)
96 |   
97 |   Description   :  Validate buffer content to be a valid numeric value
98 |
99 |   Return Values :  TRUE  - field is valid
100 |                    FALSE - field is invalid
101 +--------------------------------------------------------------------------*/
102 static bool Check_Numeric_Field(FIELD * field, const void * argp)
103 {
104   const numericARG *argn = (const numericARG *)argp;
105   double low          = argn->low;
106   double high         = argn->high;
107   int prec            = argn->precision;
108   unsigned char *bp   = (unsigned char *)field_buffer(field,0);
109   char *s             = (char *)bp;
110   double val          = 0.0;
111   struct lconv* L     = argn->L;
112   char buf[64];
113
114   while(*bp && *bp==' ') bp++;
115   if (*bp)
116     {
117       if (*bp=='-' || *bp=='+')
118         bp++;
119       while(*bp)
120         {
121           if (!isdigit(*bp)) break;
122           bp++;
123         }
124       if (*bp==(
125 #if HAVE_LOCALE_H
126                 (L && L->decimal_point) ? *(L->decimal_point) :
127 #endif
128                 '.'))
129         {
130           bp++;
131           while(*bp)
132             {
133               if (!isdigit(*bp)) break;
134               bp++;
135             }
136         }
137       while(*bp && *bp==' ') bp++;
138       if (*bp=='\0')
139         {
140           val = atof(s);
141           if (low<high)
142             {
143               if (val<low || val>high) return FALSE;
144             }
145           sprintf(buf,"%.*f",(prec>0?prec:0),val);
146           set_field_buffer(field,0,buf);
147           return TRUE;
148         }
149     }
150   return FALSE;
151 }
152
153 /*---------------------------------------------------------------------------
154 |   Facility      :  libnform  
155 |   Function      :  static bool Check_Numeric_Character(
156 |                                      int c,
157 |                                      const void * argp)
158 |   
159 |   Description   :  Check a character for the numeric type.
160 |
161 |   Return Values :  TRUE  - character is valid
162 |                    FALSE - character is invalid
163 +--------------------------------------------------------------------------*/
164 static bool Check_Numeric_Character(int c, const void * argp)
165 {
166   const numericARG *argn = (const numericARG *)argp;
167   struct lconv* L  = argn->L;  
168
169   return (isdigit(c)  || 
170           c == '+'    || 
171           c == '-'    || 
172           c == (
173 #if HAVE_LOCALE_H
174                 (L && L->decimal_point) ? *(L->decimal_point) :
175 #endif
176                 '.')
177           ) ? TRUE : FALSE;
178 }
179
180 static FIELDTYPE typeNUMERIC = {
181   _HAS_ARGS | _RESIDENT,
182   1,                           /* this is mutable, so we can't be const */
183   (FIELDTYPE *)0,
184   (FIELDTYPE *)0,
185   Make_Numeric_Type,
186   Copy_Numeric_Type,
187   Free_Numeric_Type,
188   Check_Numeric_Field,
189   Check_Numeric_Character,
190   NULL,
191   NULL
192 };
193
194 NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_NUMERIC = &typeNUMERIC;
195
196 /* fty_num.c ends here */