1 /**************************************************************************** 2 * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29 /*************************************************************************** 30 * * 31 * Author : Juergen Pfeifer * 32 * * 33 ***************************************************************************/ 34 35 #include "form.priv.h" 36 37 MODULE_ID("$Id: fty_num.c,v 1.23 2006/04/22 21:33:05 tom Exp $") 38 39 #if HAVE_LOCALE_H 40 #include <locale.h> 41 #endif 42 43 #if HAVE_LOCALE_H 44 #define isDecimalPoint(c) ((c) == ((L && L->decimal_point) ? *(L->decimal_point) : '.')) 45 #else 46 #define isDecimalPoint(c) ((c) == '.') 47 #endif 48 49 #if USE_WIDEC_SUPPORT 50 #define isDigit(c) (iswdigit((wint_t)(c)) || isdigit(UChar(c))) 51 #else 52 #define isDigit(c) isdigit(UChar(c)) 53 #endif 54 55 #define thisARG numericARG 56 57 typedef struct 58 { 59 int precision; 60 double low; 61 double high; 62 struct lconv *L; 63 } 64 thisARG; 65 66 /*--------------------------------------------------------------------------- 67 | Facility : libnform 68 | Function : static void *Make_This_Type(va_list * ap) 69 | 70 | Description : Allocate structure for numeric type argument. 71 | 72 | Return Values : Pointer to argument structure or NULL on error 73 +--------------------------------------------------------------------------*/ 74 static void * 75 Make_This_Type(va_list *ap) 76 { 77 thisARG *argn = (thisARG *) malloc(sizeof(thisARG)); 78 79 if (argn) 80 { 81 argn->precision = va_arg(*ap, int); 82 argn->low = va_arg(*ap, double); 83 argn->high = va_arg(*ap, double); 84 85 #if HAVE_LOCALE_H 86 argn->L = localeconv(); 87 #else 88 argn->L = NULL; 89 #endif 90 } 91 return (void *)argn; 92 } 93 94 /*--------------------------------------------------------------------------- 95 | Facility : libnform 96 | Function : static void *Copy_This_Type(const void * argp) 97 | 98 | Description : Copy structure for numeric type argument. 99 | 100 | Return Values : Pointer to argument structure or NULL on error. 101 +--------------------------------------------------------------------------*/ 102 static void * 103 Copy_This_Type(const void *argp) 104 { 105 const thisARG *ap = (const thisARG *)argp; 106 thisARG *result = (thisARG *) 0; 107 108 if (argp) 109 { 110 result = (thisARG *) malloc(sizeof(thisARG)); 111 if (result) 112 *result = *ap; 113 } 114 return (void *)result; 115 } 116 117 /*--------------------------------------------------------------------------- 118 | Facility : libnform 119 | Function : static void Free_This_Type(void * argp) 120 | 121 | Description : Free structure for numeric type argument. 122 | 123 | Return Values : - 124 +--------------------------------------------------------------------------*/ 125 static void 126 Free_This_Type(void *argp) 127 { 128 if (argp) 129 free(argp); 130 } 131 132 /*--------------------------------------------------------------------------- 133 | Facility : libnform 134 | Function : static bool Check_This_Field(FIELD * field, 135 | const void * argp) 136 | 137 | Description : Validate buffer content to be a valid numeric value 138 | 139 | Return Values : TRUE - field is valid 140 | FALSE - field is invalid 141 +--------------------------------------------------------------------------*/ 142 static bool 143 Check_This_Field(FIELD *field, const void *argp) 144 { 145 const thisARG *argn = (const thisARG *)argp; 146 double low = argn->low; 147 double high = argn->high; 148 int prec = argn->precision; 149 unsigned char *bp = (unsigned char *)field_buffer(field, 0); 150 char *s = (char *)bp; 151 double val = 0.0; 152 struct lconv *L = argn->L; 153 char buf[64]; 154 bool result = FALSE; 155 156 while (*bp && *bp == ' ') 157 bp++; 158 if (*bp) 159 { 160 if (*bp == '-' || *bp == '+') 161 bp++; 162 #if USE_WIDEC_SUPPORT 163 if (*bp) 164 { 165 bool blank = FALSE; 166 int state = 0; 167 int len; 168 int n; 169 wchar_t *list = _nc_Widen_String((char *)bp, &len); 170 171 if (list != 0) 172 { 173 result = TRUE; 174 for (n = 0; n < len; ++n) 175 { 176 if (blank) 177 { 178 if (list[n] != ' ') 179 { 180 result = FALSE; 181 break; 182 } 183 } 184 else if (list[n] == ' ') 185 { 186 blank = TRUE; 187 } 188 else if (isDecimalPoint(list[n])) 189 { 190 if (++state > 1) 191 { 192 result = FALSE; 193 break; 194 } 195 } 196 else if (!isDigit(list[n])) 197 { 198 result = FALSE; 199 break; 200 } 201 } 202 free(list); 203 } 204 } 205 #else 206 while (*bp) 207 { 208 if (!isdigit(UChar(*bp))) 209 break; 210 bp++; 211 } 212 if (isDecimalPoint(*bp)) 213 { 214 bp++; 215 while (*bp) 216 { 217 if (!isdigit(UChar(*bp))) 218 break; 219 bp++; 220 } 221 } 222 while (*bp && *bp == ' ') 223 bp++; 224 result = (*bp == '\0'); 225 #endif 226 if (result) 227 { 228 val = atof(s); 229 if (low < high) 230 { 231 if (val < low || val > high) 232 result = FALSE; 233 } 234 if (result) 235 { 236 sprintf(buf, "%.*f", (prec > 0 ? prec : 0), val); 237 set_field_buffer(field, 0, buf); 238 } 239 } 240 } 241 return (result); 242 } 243 244 /*--------------------------------------------------------------------------- 245 | Facility : libnform 246 | Function : static bool Check_This_Character( 247 | int c, 248 | const void * argp) 249 | 250 | Description : Check a character for the numeric type. 251 | 252 | Return Values : TRUE - character is valid 253 | FALSE - character is invalid 254 +--------------------------------------------------------------------------*/ 255 static bool 256 Check_This_Character(int c, const void *argp) 257 { 258 const thisARG *argn = (const thisARG *)argp; 259 struct lconv *L = argn->L; 260 261 return ((isDigit(c) || 262 c == '+' || 263 c == '-' || 264 isDecimalPoint(c)) 265 ? TRUE 266 : FALSE); 267 } 268 269 static FIELDTYPE typeTHIS = 270 { 271 _HAS_ARGS | _RESIDENT, 272 1, /* this is mutable, so we can't be const */ 273 (FIELDTYPE *)0, 274 (FIELDTYPE *)0, 275 Make_This_Type, 276 Copy_This_Type, 277 Free_This_Type, 278 Check_This_Field, 279 Check_This_Character, 280 NULL, 281 NULL 282 }; 283 284 NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_NUMERIC = &typeTHIS; 285 286 /* fty_num.c ends here */ 287