fty_num.c 5.3 KB

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