home *** CD-ROM | disk | FTP | other *** search
- // Zinc Interface Library - REAL.CPP
- // COPYRIGHT (C) 1990, 1991. All Rights Reserved.
- // Zinc Software Incorporated. Pleasant Grove, Utah USA
-
- #include "ui_win.hpp"
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define NMF_PRECISION_FLAGS 0xF000
-
- static int IsZero(char *string)
- {
- while (*string == '0')
- string++;
- if (*string == '.')
- string++;
- while (*string == '0')
- string++;
- if (*string == '\0' || *string == 'E')
- return (TRUE);
- else
- return (FALSE);
- }
-
- static int ExponentValue(char *string)
- {
- if (IsZero(string))
- return 0;
- char *exp = strchr(string, 'E');
- return (exp ? atoi(exp + 1) : 0);
- }
-
- UIW_NUMBER::UIW_NUMBER(int left, int top, int width, float *a_value,
- char *a_range, USHORT flags, USHORT woFlags,
- int (*validate)(void *object, int ccode)) :
- UI_WINDOW_OBJECT(left, top, width, 1, woFlags, WOAF_NO_FLAGS)
- {
- type = NUM_FLOAT;
- Constructor(a_value, width, flags, a_range,
- UIW_NUMBER::RealToAscii, UIW_NUMBER::AsciiToReal,
- UIW_NUMBER::ValidRealNumber, validate);
- }
-
- UIW_NUMBER::UIW_NUMBER(int left, int top, int width, double *a_value,
- char *a_range, USHORT flags, USHORT woFlags,
- int (*validate)(void *object, int ccode)) :
- UI_WINDOW_OBJECT(left, top, width, 1, woFlags, WOAF_NO_FLAGS)
- {
- type = NUM_DOUBLE;
- Constructor(a_value, width, flags, a_range,
- UIW_NUMBER::RealToAscii, UIW_NUMBER::AsciiToReal,
- UIW_NUMBER::ValidRealNumber, validate);
- }
-
- void UIW_NUMBER::RealToAscii()
- {
- int maxSigDigits = (type == NUM_FLOAT) ? 7 : 15;
-
- if (FlagSet(woStatus, WOS_UNANSWERED))
- {
- if (type == NUM_FLOAT)
- *((float *)value) = 0.0;
- else
- *((double *)value) = 0.0;
- }
- char tempBuff[64];
- sprintf(tempBuff, FlagSet(nmFlags, NMF_SCIENTIFIC) ? "%.*E" : "%.*G",
- FlagSet(nmFlags, NMF_SCIENTIFIC) ? maxSigDigits - 1 : maxSigDigits,
- type == NUM_FLOAT ? *((float *)value) : *((double *)value));
- char *exp = strchr(tempBuff, 'E');
- char *dec = strchr(tempBuff, '.');
- if (decimal == 0xFF) // Floating decimal
- {
- // Strip trailing zeroes from exponent. (not necessary for %G format)
- while (*(exp - 1) == '0' && dec && exp - 2 > dec)
- {
- memmove(exp - 1, exp, strlen(exp) + 1);
- exp--;
- }
- }
- else // Fixed point decimal.
- {
- if (decimal == 0)
- {
- if (dec)
- *dec = '\0';
- }
- else
- {
- sprintf(tempBuff, exp ? "%.*E" : "%.*f", decimal,
- type == NUM_FLOAT ? *((float *)value) : *((double *)value));
- exp = strpbrk(tempBuff, "Ee");
- *exp = '\0'; // Strip the exponent.
- }
- }
- exp = strpbrk(tempBuff, "Ee");
- char *ptr;
- if (exp)
- {
- *exp = 'E';
- ptr = exp + 1;
- while (*ptr == '+' || *ptr == '-' || *ptr == '0')
- {
- if (*ptr == '-')
- ptr++;
- else
- memmove(ptr, ptr + 1, strlen(ptr));
- }
- if (*ptr == '\0')
- *exp = '\0'; // Clip exponent of zero.
- }
- ptr = tempBuff[0] == '-' ? tempBuff + 1 : tempBuff;
- if (strcmp(ptr, "0.0") == 0)
- *(ptr + 1) = '\0'; // Convert "0.0" to "0".
- ui_strrepc(tempBuff, '.', _countryInfo.co_desep[0]);
- tempBuff[NUM_MAX_TEXT_LEN - 1] = '\0'; // Insure it fits.
-
- if (FlagSet(nmFlags, NMF_DECIMAL_FLOAT) &&
- (nmFlags & NMF_DECIMAL_FLOAT) != NMF_DECIMAL_FLOAT)
- {
- char *offset = strchr(tempBuff, '.');
- if (offset)
- strcpy(offset, offset + 1);
- offset += decimal;
- *offset = '\0';
- }
-
- strcpy(state.text, tempBuff);
- }
-
- void UIW_NUMBER::AsciiToReal()
- {
- // Fix up the decimal position.
- char *text = state.text;
- if (FlagSet(nmFlags, NMF_DECIMAL_FLOAT) &&
- (nmFlags & NMF_DECIMAL_FLOAT) != NMF_DECIMAL_FLOAT)
- {
- char *offset = strchr(text, '.');
- if (offset)
- strcpy(offset, offset + 1);
- offset = text + strlen(text) - decimal;
- memmove(offset + 1, offset, decimal + 1);
- *offset = '.';
- }
-
- // Convert the floating point number.
- if (type == NUM_FLOAT)
- {
- *((float *)value) = atof(text);
- if (state.isNegative)
- *((float *) value) = - *((float *) value);
- }
- else
- {
- *((double *)value) = atof(text);
- if (state.isNegative)
- *((double *) value) = - *((double *) value);
- }
- }
-
- int UIW_NUMBER::ValidRealBetween(char *minValue, char *maxValue)
- {
- int valNegative = IsZero(state.text) ? FALSE : state.isNegative;
-
- /* Check the sign */
- int minNegative = (minValue[0] == '-') ? TRUE : FALSE;
- int maxNegative = (maxValue[0] == '-') ? TRUE : FALSE;
- if (!minNegative && valNegative || maxNegative && !valNegative)
- return (FALSE);
-
- /* Check the exponent */
- int valExponent = ExponentValue(state.text);
- int minExponent = ExponentValue(minValue);
- int maxExponent = ExponentValue(maxValue);
- if ((valNegative && minNegative && minExponent && valExponent > minExponent) ||
- (!valNegative && !minNegative && minExponent && valExponent < minExponent) ||
- (valNegative && maxNegative && maxExponent && valExponent < maxExponent) ||
- (!valNegative && !maxNegative && maxExponent && valExponent > maxExponent))
- return (FALSE);
-
- /* Compare the raw numerical values */
- double val = atof(state.text);
- if (valNegative)
- val = -val;
- if (val >= atof(minValue) && val <= atof(maxValue))
- return (TRUE);
-
- /* The value does not fall within the minimum and maximum values */
- return (FALSE);
- }
-
- int UIW_NUMBER::ValidRealInRange(char *a_range)
- {
- char minValue[20];
- char maxValue[20];
- int validNumber;
- int rangeLength;
- int offset;
-
- /* See if a range exists */
- if (!a_range || a_range[0] == '\0')
- return(TRUE);
-
- /* See if the value is in the specified range */
- validNumber = FALSE;
- offset = 0;
- rangeLength = (a_range) ? strlen(a_range) : 0;
- while (!validNumber && offset < rangeLength)
- {
- offset = ui_parse_range(a_range, offset, minValue, maxValue);
- validNumber = ValidRealBetween(minValue, maxValue);
- }
- return(validNumber);
- }
-
- int UIW_NUMBER::ValidRealNumber()
- {
- char *absoluteRange;
-
- if (type == NUM_FLOAT)
- absoluteRange = "-3.4E38..-3.4E-38/0/3.4E-38..3.4E38";
- else
- absoluteRange = "-1.7E308..-1.7E-308/0/1.7E-308..1.7E308";
- if (range && !ValidRealInRange(range))
- {
- RangeError(range);
- return (FALSE);
- }
- else if (!ValidRealInRange(absoluteRange))
- {
- RangeError(absoluteRange);
- return (FALSE);
- }
- return (TRUE);
- }
-
- #ifdef ZIL_LOAD
- UIW_REAL::UIW_REAL(const char *name, UI_STORAGE *file, USHORT loadFlags) :
- UIW_NUMBER(name, file, loadFlags | L_SUB_LEVEL)
- {
- windowID[0] = ID_NUMBER;
- windowID[1] = ID_STRING;
-
- if (!file)
- file = _storage;
- file->Load(&type);
- file->Load(&nmFlags);
- value = new double;
- file->Load(value, sizeof(double));
- UIW_NUMBER::Constructor(value, relative.right - relative.left + 1,
- nmFlags, 0, UIW_NUMBER::RealToAscii, UIW_NUMBER::AsciiToReal,
- UIW_NUMBER::ValidRealNumber, NULL);
- file->Load(&range);
- if (!FlagSet(loadFlags, L_SUB_LEVEL) && FlagSet(file->stStatus, STS_TEMPORARY))
- delete file;
- }
- #endif
-
- #ifdef ZIL_STORE
- void UIW_REAL::Store(const char *name, UI_STORAGE *file, USHORT storeFlags)
- {
- search.type = ID_REAL;
- UIW_NUMBER::Store(name, file, storeFlags | S_SUB_LEVEL);
- file->Store(type);
- file->Store(nmFlags);
- file->Store(value, sizeof(double));
- file->Store(range);
- if (!FlagSet(storeFlags, S_SUB_LEVEL))
- file->ObjectSize(name, search);
- }
- #endif
-