// 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;
}