// FloatEdit.cpp : implementation file // #include "stdafx.h" //#include "admin.h" #include "FloatEdit.h" ULONG ulFloatErrCnt=0L; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CFloatEdit CFloatEdit::CFloatEdit() { m_bSilent=FALSE; m_bZeroIsBlank=TRUE; } CFloatEdit::~CFloatEdit() { } BEGIN_MESSAGE_MAP(CFloatEdit, CEdit) //{{AFX_MSG_MAP(CFloatEdit) // NOTE - the ClassWizard will add and remove mapping macros here. ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillfocus) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CFloatEdit message handlers void FloatEditErr(CEdit *ctl, BOOL silent /*=FALSE*/) { ulFloatErrCnt++; if (!silent) AfxMessageBox(ulFloatErrCnt>=3?"Please enter a valid floating point expression such as:\n 1/2\n 10 15/16\n 10.5\n 10 + 5\n 10.5 * 2\n etc...":"Illegal floating point value."); ctl->SetSel(0,-1); ctl->SetFocus(); if (ulFloatErrCnt==ULONG_MAX) ulFloatErrCnt=0L; } void CFloatEdit::OnKillfocus() { if (GetModify()) { CString s; BOOL err=FALSE,result; GetWindowText(s); s.TrimLeft(); s.TrimRight(); result = Translate(s.GetBuffer(100)); s.ReleaseBuffer(); if (result && !(s.IsEmpty() && !m_bZeroIsBlank)) { SetWindowText(s); ulFloatErrCnt=0L; } else err=TRUE; if (err) FloatEditErr(this, m_bSilent); } } BOOL CFloatEdit::Translate(LPSTR szFloatExpr) { LPSTR p,pdiv,pdot,pop,limit,end; char op=' ',temp[100]; float fmain,fcalc,result=0.f; limit = szFloatExpr+strlen(szFloatExpr); if (limit==szFloatExpr) return TRUE; pdiv=strchr(szFloatExpr,'/'); pdot=strchr(szFloatExpr,'.'); if ((pop=strchr(szFloatExpr+1,'*')) == NULL) if ((pop=strchr(szFloatExpr+1,'+')) == NULL) if ((pop=strchr(szFloatExpr+1,'-')) == NULL) if (pdiv != NULL) pop = strchr(pdiv+1,'/'); if ((pdot!=NULL && pdiv != NULL && pdot < pdiv && (pdot < pop||pop==NULL)) // first number is fp || (pdot!=NULL && pdiv == NULL && pdot < pop)) for (end=pdot+1; isdigit(*end) && *end != NULL; end++); else if (pdiv!=NULL && pdiv < pop) for (end=pdiv+1; isdigit(*end) && *end != NULL; end++); else if (pop!=NULL) end=pop; else for (end=szFloatExpr+1; *end != NULL && *end != '+' && *end != '-' && *end != '*'; end++); memcpy(temp,szFloatExpr,end-szFloatExpr); temp[end-szFloatExpr] = NULL; p=end; { if (!DecodeFloatString(temp,&fmain)) return FALSE; if (p >= limit) result=fmain; else { for (; *p == ' ' && *p != NULL; p++); // skip whitespace if (*p != '+' && *p != '-' && *p != '/' && *p != '*') return FALSE; op = *p++; for (; *p == ' ' && *p != NULL; p++); // skip whitespace if (*p == NULL || !DecodeFloatString(p,&fcalc) || (op=='/'&&fcalc==0.f)) return FALSE; switch(op) { case '+': result = fmain + fcalc; break; case '-': result = fmain - fcalc; break; case '*': result = fmain * fcalc; break; case '/': result = fmain / fcalc; break; } } } sprintf(szFloatExpr,"%1.4f",result); for (p=szFloatExpr+strlen(szFloatExpr)-1; p > szFloatExpr && *p=='0'; p--); if (*p=='.') // we don't want numbers like 4. *p=NULL; else *(p+1)=NULL; return TRUE; } BOOL CFloatEdit::DecodeFloatString(LPCSTR szFloatExpr, float *fResult) { LPSTR p,pdiv; LPCSTR limit=szFloatExpr+strlen(szFloatExpr); float num,den; *fResult = 0.f; if ((p=strchr(szFloatExpr,'.')) == NULL && (pdiv=strchr(szFloatExpr,'/')) != NULL) { // look for numerator for (p=pdiv-1; p >= szFloatExpr && *p != ' '; p--); num = (float)atof(p+1); // get main integer part, if it exists if (p+1!=szFloatExpr) { *p=NULL; *fResult+=atoi(szFloatExpr); } den = (float)atof(pdiv+1); if (den==0) return FALSE; *fResult += num/den; } else // first number is fp decimal *fResult = (float)atof(szFloatExpr); return TRUE; } void CFloatEdit::TrimZeros(LPSTR szFloatExpr) { LPSTR p; for (p=szFloatExpr+strlen(szFloatExpr)-1; p > szFloatExpr && *p=='0'; p--); if (*p=='.') // we don't want numbers like 4. *p=NULL; else *(p+1)=NULL; }