home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0040 - 0049 / ibm0040-0049 / ibm0040.tar / ibm0040 / ZINC_6.ZIP / DOSSRC.ZIP / REAL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-01  |  7.1 KB  |  274 lines

  1. //    Zinc Interface Library - REAL.CPP
  2. //    COPYRIGHT (C) 1990, 1991.  All Rights Reserved.
  3. //    Zinc Software Incorporated.  Pleasant Grove, Utah  USA
  4.  
  5. #include "ui_win.hpp"
  6. #include <ctype.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #define    NMF_PRECISION_FLAGS    0xF000
  12.  
  13. static int IsZero(char *string)
  14. {
  15.     while (*string == '0')
  16.         string++;
  17.     if (*string == '.')
  18.         string++;
  19.     while (*string == '0')
  20.         string++;
  21.     if (*string == '\0' || *string == 'E')
  22.         return (TRUE);
  23.     else
  24.         return (FALSE);
  25. }
  26.  
  27. static int ExponentValue(char *string)
  28. {
  29.     if (IsZero(string))
  30.         return 0;
  31.     char *exp = strchr(string, 'E');
  32.     return (exp ? atoi(exp + 1) : 0);
  33. }
  34.  
  35. UIW_NUMBER::UIW_NUMBER(int left, int top, int width, float *a_value,
  36.     char *a_range, USHORT flags, USHORT woFlags,
  37.     int (*validate)(void *object, int ccode)) :
  38.     UI_WINDOW_OBJECT(left, top, width, 1, woFlags, WOAF_NO_FLAGS)
  39. {
  40.     type = NUM_FLOAT;
  41.     Constructor(a_value, width, flags, a_range,
  42.         UIW_NUMBER::RealToAscii, UIW_NUMBER::AsciiToReal,
  43.         UIW_NUMBER::ValidRealNumber, validate);
  44. }
  45.  
  46. UIW_NUMBER::UIW_NUMBER(int left, int top, int width, double *a_value,
  47.     char *a_range, USHORT flags, USHORT woFlags,
  48.     int (*validate)(void *object, int ccode)) :
  49.     UI_WINDOW_OBJECT(left, top, width, 1, woFlags, WOAF_NO_FLAGS)
  50. {
  51.     type = NUM_DOUBLE;
  52.     Constructor(a_value, width, flags, a_range,
  53.         UIW_NUMBER::RealToAscii, UIW_NUMBER::AsciiToReal,
  54.         UIW_NUMBER::ValidRealNumber, validate);
  55. }
  56.  
  57. void UIW_NUMBER::RealToAscii()
  58. {
  59.     int maxSigDigits = (type == NUM_FLOAT) ? 7 : 15;
  60.  
  61.     if (FlagSet(woStatus, WOS_UNANSWERED))
  62.     {
  63.         if (type == NUM_FLOAT)
  64.             *((float *)value) = 0.0;
  65.         else
  66.             *((double *)value) = 0.0;
  67.     }
  68.     char tempBuff[64];
  69.     sprintf(tempBuff, FlagSet(nmFlags, NMF_SCIENTIFIC) ? "%.*E" : "%.*G",
  70.         FlagSet(nmFlags, NMF_SCIENTIFIC) ? maxSigDigits - 1 : maxSigDigits,
  71.         type == NUM_FLOAT ? *((float *)value) : *((double *)value));
  72.     char *exp = strchr(tempBuff, 'E');
  73.     char *dec = strchr(tempBuff, '.');
  74.     if (decimal == 0xFF)                        // Floating decimal
  75.     {
  76.         // Strip trailing zeroes from exponent. (not necessary for %G format)
  77.         while (*(exp - 1) == '0' && dec && exp - 2 > dec)
  78.         {
  79.             memmove(exp - 1, exp, strlen(exp) + 1);
  80.             exp--;
  81.         }
  82.     }
  83.     else                                        // Fixed point decimal.
  84.     {
  85.         if (decimal == 0)
  86.         {
  87.             if (dec)
  88.                  *dec = '\0';
  89.         }
  90.         else
  91.         {
  92.             sprintf(tempBuff, exp ? "%.*E" : "%.*f", decimal,
  93.                 type == NUM_FLOAT ? *((float *)value) : *((double *)value));
  94.             exp = strpbrk(tempBuff, "Ee");
  95.             *exp = '\0';                            // Strip the exponent.
  96.         }
  97.     }
  98.     exp = strpbrk(tempBuff, "Ee");
  99.     char *ptr;
  100.     if (exp)
  101.     {
  102.         *exp = 'E';
  103.         ptr = exp + 1;
  104.         while (*ptr == '+' || *ptr == '-' || *ptr == '0')
  105.         {
  106.             if (*ptr == '-')
  107.                 ptr++;
  108.             else
  109.                 memmove(ptr, ptr + 1, strlen(ptr));
  110.         }
  111.         if (*ptr == '\0')
  112.             *exp = '\0';        // Clip exponent of zero.
  113.     }
  114.     ptr = tempBuff[0] == '-' ? tempBuff + 1 : tempBuff;
  115.     if (strcmp(ptr, "0.0") == 0)
  116.         *(ptr + 1) = '\0';        // Convert "0.0" to "0".
  117.     ui_strrepc(tempBuff, '.', _countryInfo.co_desep[0]);
  118.     tempBuff[NUM_MAX_TEXT_LEN - 1] = '\0';        // Insure it fits.
  119.  
  120.     if (FlagSet(nmFlags, NMF_DECIMAL_FLOAT) &&
  121.         (nmFlags & NMF_DECIMAL_FLOAT) != NMF_DECIMAL_FLOAT)
  122.     {
  123.         char *offset = strchr(tempBuff, '.');
  124.         if (offset)
  125.             strcpy(offset, offset + 1);
  126.         offset += decimal;
  127.         *offset = '\0';
  128.     }
  129.  
  130.     strcpy(state.text, tempBuff);
  131. }
  132.  
  133. void UIW_NUMBER::AsciiToReal()
  134. {
  135.     // Fix up the decimal position.
  136.     char *text = state.text;
  137.     if (FlagSet(nmFlags, NMF_DECIMAL_FLOAT) &&
  138.         (nmFlags & NMF_DECIMAL_FLOAT) != NMF_DECIMAL_FLOAT)
  139.     {
  140.         char *offset = strchr(text, '.');
  141.         if (offset)
  142.             strcpy(offset, offset + 1);
  143.         offset = text + strlen(text) - decimal;
  144.         memmove(offset + 1, offset, decimal + 1);
  145.         *offset = '.';
  146.     }
  147.  
  148.     // Convert the floating point number.
  149.     if (type == NUM_FLOAT)
  150.     {
  151.         *((float *)value) = atof(text);
  152.         if (state.isNegative)
  153.             *((float *) value) = - *((float *) value);
  154.     }
  155.     else
  156.     {
  157.         *((double *)value) = atof(text);
  158.         if (state.isNegative)
  159.             *((double *) value) = - *((double *) value);
  160.     }
  161. }
  162.  
  163. int UIW_NUMBER::ValidRealBetween(char *minValue, char *maxValue)
  164. {
  165.     int valNegative = IsZero(state.text) ? FALSE : state.isNegative;
  166.  
  167.     /* Check the sign */
  168.     int minNegative = (minValue[0] == '-') ? TRUE : FALSE;
  169.     int maxNegative = (maxValue[0] == '-') ? TRUE : FALSE;
  170.     if (!minNegative && valNegative || maxNegative && !valNegative)
  171.         return (FALSE);
  172.  
  173.     /* Check the exponent */
  174.     int valExponent = ExponentValue(state.text);
  175.     int minExponent = ExponentValue(minValue);
  176.     int maxExponent = ExponentValue(maxValue);
  177.     if ((valNegative && minNegative && minExponent && valExponent > minExponent) ||
  178.         (!valNegative && !minNegative && minExponent && valExponent < minExponent) ||
  179.         (valNegative && maxNegative && maxExponent && valExponent < maxExponent) ||
  180.         (!valNegative && !maxNegative && maxExponent && valExponent > maxExponent))
  181.         return (FALSE);
  182.  
  183.     /* Compare the raw numerical values */
  184.     double val = atof(state.text);
  185.     if (valNegative)
  186.         val = -val;
  187.     if (val >= atof(minValue) && val <= atof(maxValue))
  188.         return (TRUE);
  189.  
  190.     /* The value does not fall within the minimum and maximum values */
  191.     return (FALSE);
  192. }
  193.  
  194. int UIW_NUMBER::ValidRealInRange(char *a_range)
  195. {
  196.     char minValue[20];
  197.     char maxValue[20];
  198.     int validNumber;
  199.     int rangeLength;
  200.     int offset;
  201.  
  202.     /* See if a range exists */
  203.     if (!a_range || a_range[0] == '\0')
  204.         return(TRUE);
  205.  
  206.     /* See if the value is in the specified range */
  207.     validNumber = FALSE;
  208.     offset = 0;
  209.     rangeLength = (a_range) ? strlen(a_range) : 0;
  210.     while (!validNumber && offset < rangeLength)
  211.     {
  212.         offset = ui_parse_range(a_range, offset, minValue, maxValue);
  213.         validNumber = ValidRealBetween(minValue, maxValue);
  214.     }
  215.     return(validNumber);
  216. }
  217.  
  218. int UIW_NUMBER::ValidRealNumber()
  219. {
  220.     char *absoluteRange;
  221.  
  222.     if (type == NUM_FLOAT)
  223.         absoluteRange = "-3.4E38..-3.4E-38/0/3.4E-38..3.4E38";
  224.     else
  225.         absoluteRange = "-1.7E308..-1.7E-308/0/1.7E-308..1.7E308";
  226.     if (range && !ValidRealInRange(range))
  227.     {
  228.         RangeError(range);
  229.         return (FALSE);
  230.     }
  231.     else if (!ValidRealInRange(absoluteRange))
  232.     {
  233.         RangeError(absoluteRange);
  234.         return (FALSE);
  235.     }
  236.     return (TRUE);
  237. }
  238.  
  239. #ifdef ZIL_LOAD
  240. UIW_REAL::UIW_REAL(const char *name, UI_STORAGE *file, USHORT loadFlags) :
  241.     UIW_NUMBER(name, file, loadFlags | L_SUB_LEVEL)
  242. {
  243.     windowID[0] = ID_NUMBER;
  244.     windowID[1] = ID_STRING;
  245.  
  246.     if (!file)
  247.         file = _storage;
  248.     file->Load(&type);
  249.     file->Load(&nmFlags);
  250.     value = new double;
  251.     file->Load(value, sizeof(double));
  252.     UIW_NUMBER::Constructor(value, relative.right - relative.left + 1,
  253.         nmFlags, 0, UIW_NUMBER::RealToAscii, UIW_NUMBER::AsciiToReal,
  254.         UIW_NUMBER::ValidRealNumber, NULL);
  255.     file->Load(&range);
  256.     if (!FlagSet(loadFlags, L_SUB_LEVEL) && FlagSet(file->stStatus, STS_TEMPORARY))
  257.         delete file;
  258. }
  259. #endif
  260.  
  261. #ifdef ZIL_STORE
  262. void UIW_REAL::Store(const char *name, UI_STORAGE *file, USHORT storeFlags)
  263. {
  264.     search.type = ID_REAL;
  265.     UIW_NUMBER::Store(name, file, storeFlags | S_SUB_LEVEL);
  266.     file->Store(type);
  267.     file->Store(nmFlags);
  268.     file->Store(value, sizeof(double));
  269.     file->Store(range);
  270.     if (!FlagSet(storeFlags, S_SUB_LEVEL))
  271.         file->ObjectSize(name, search);
  272. }
  273. #endif
  274.