1/* 2 * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT. 3 * You may freely copy it for use as a template for your own field types. 4 * If you develop a field type that might be of general use, please send 5 * it back to the ncurses maintainers for inclusion in the next version. 6 */ 7/*************************************************************************** 8* * 9* Author : Juergen Pfeifer * 10* * 11***************************************************************************/ 12 13#include "form.priv.h" 14 15MODULE_ID("$Id: fty_num.c,v 1.22 2005/08/20 18:26:16 tom Exp $") 16 17#if HAVE_LOCALE_H 18#include <locale.h> 19#endif 20 21#if HAVE_LOCALE_H 22#define isDecimalPoint(c) ((c) == ((L && L->decimal_point) ? *(L->decimal_point) : '.')) 23#else 24#define isDecimalPoint(c) ((c) == '.') 25#endif 26 27#if USE_WIDEC_SUPPORT 28#define isDigit(c) (iswdigit((wint_t)(c)) || isdigit(UChar(c))) 29#else 30#define isDigit(c) isdigit(UChar(c)) 31#endif 32 33#define thisARG numericARG 34 35typedef struct 36 { 37 int precision; 38 double low; 39 double high; 40 struct lconv *L; 41 } 42thisARG; 43 44/*--------------------------------------------------------------------------- 45| Facility : libnform 46| Function : static void *Make_This_Type(va_list * ap) 47| 48| Description : Allocate structure for numeric type argument. 49| 50| Return Values : Pointer to argument structure or NULL on error 51+--------------------------------------------------------------------------*/ 52static void * 53Make_This_Type(va_list *ap) 54{ 55 thisARG *argn = (thisARG *) malloc(sizeof(thisARG)); 56 57 if (argn) 58 { 59 argn->precision = va_arg(*ap, int); 60 argn->low = va_arg(*ap, double); 61 argn->high = va_arg(*ap, double); 62 63#if HAVE_LOCALE_H 64 argn->L = localeconv(); 65#else 66 argn->L = NULL; 67#endif 68 } 69 return (void *)argn; 70} 71 72/*--------------------------------------------------------------------------- 73| Facility : libnform 74| Function : static void *Copy_This_Type(const void * argp) 75| 76| Description : Copy structure for numeric type argument. 77| 78| Return Values : Pointer to argument structure or NULL on error. 79+--------------------------------------------------------------------------*/ 80static void * 81Copy_This_Type(const void *argp) 82{ 83 const thisARG *ap = (const thisARG *)argp; 84 thisARG *result = (thisARG *) 0; 85 86 if (argp) 87 { 88 result = (thisARG *) malloc(sizeof(thisARG)); 89 if (result) 90 *result = *ap; 91 } 92 return (void *)result; 93} 94 95/*--------------------------------------------------------------------------- 96| Facility : libnform 97| Function : static void Free_This_Type(void * argp) 98| 99| Description : Free structure for numeric type argument. 100| 101| Return Values : - 102+--------------------------------------------------------------------------*/ 103static void 104Free_This_Type(void *argp) 105{ 106 if (argp) 107 free(argp); 108} 109 110/*--------------------------------------------------------------------------- 111| Facility : libnform 112| Function : static bool Check_This_Field(FIELD * field, 113| const void * argp) 114| 115| Description : Validate buffer content to be a valid numeric value 116| 117| Return Values : TRUE - field is valid 118| FALSE - field is invalid 119+--------------------------------------------------------------------------*/ 120static bool 121Check_This_Field(FIELD *field, const void *argp) 122{ 123 const thisARG *argn = (const thisARG *)argp; 124 double low = argn->low; 125 double high = argn->high; 126 int prec = argn->precision; 127 unsigned char *bp = (unsigned char *)field_buffer(field, 0); 128 char *s = (char *)bp; 129 double val = 0.0; 130 struct lconv *L = argn->L; 131 char buf[64]; 132 bool result = FALSE; 133 134 while (*bp && *bp == ' ') 135 bp++; 136 if (*bp) 137 { 138 if (*bp == '-' || *bp == '+') 139 bp++; 140#if USE_WIDEC_SUPPORT 141 if (*bp) 142 { 143 bool blank = FALSE; 144 int state = 0; 145 int len; 146 int n; 147 wchar_t *list = _nc_Widen_String((char *)bp, &len); 148 149 if (list != 0) 150 { 151 result = TRUE; 152 for (n = 0; n < len; ++n) 153 { 154 if (blank) 155 { 156 if (list[n] != ' ') 157 { 158 result = FALSE; 159 break; 160 } 161 } 162 else if (list[n] == ' ') 163 { 164 blank = TRUE; 165 } 166 else if (isDecimalPoint(list[n])) 167 { 168 if (++state > 1) 169 { 170 result = FALSE; 171 break; 172 } 173 } 174 else if (!isDigit(list[n])) 175 { 176 result = FALSE; 177 break; 178 } 179 } 180 free(list); 181 } 182 } 183#else 184 while (*bp) 185 { 186 if (!isdigit(UChar(*bp))) 187 break; 188 bp++; 189 } 190 if (isDecimalPoint(*bp)) 191 { 192 bp++; 193 while (*bp) 194 { 195 if (!isdigit(UChar(*bp))) 196 break; 197 bp++; 198 } 199 } 200 while (*bp && *bp == ' ') 201 bp++; 202 result = (*bp == '\0'); 203#endif 204 if (result) 205 { 206 val = atof(s); 207 if (low < high) 208 { 209 if (val < low || val > high) 210 result = FALSE; 211 } 212 if (result) 213 { 214 sprintf(buf, "%.*f", (prec > 0 ? prec : 0), val); 215 set_field_buffer(field, 0, buf); 216 } 217 } 218 } 219 return (result); 220} 221 222/*--------------------------------------------------------------------------- 223| Facility : libnform 224| Function : static bool Check_This_Character( 225| int c, 226| const void * argp) 227| 228| Description : Check a character for the numeric type. 229| 230| Return Values : TRUE - character is valid 231| FALSE - character is invalid 232+--------------------------------------------------------------------------*/ 233static bool 234Check_This_Character(int c, const void *argp) 235{ 236 const thisARG *argn = (const thisARG *)argp; 237 struct lconv *L = argn->L; 238 239 return ((isDigit(c) || 240 c == '+' || 241 c == '-' || 242 isDecimalPoint(c)) 243 ? TRUE 244 : FALSE); 245} 246 247static FIELDTYPE typeTHIS = 248{ 249 _HAS_ARGS | _RESIDENT, 250 1, /* this is mutable, so we can't be const */ 251 (FIELDTYPE *)0, 252 (FIELDTYPE *)0, 253 Make_This_Type, 254 Copy_This_Type, 255 Free_This_Type, 256 Check_This_Field, 257 Check_This_Character, 258 NULL, 259 NULL 260}; 261 262NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_NUMERIC = &typeTHIS; 263 264/* fty_num.c ends here */ 265