fty_num.c 8.0 KB

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