309 lines
7.5 KiB
C
309 lines
7.5 KiB
C
/****************************Module*Header***********************************\
|
|
* Module Name: INPUT.C
|
|
*
|
|
* Module Descripton: Decimal floating point input
|
|
*
|
|
* Warnings:
|
|
*
|
|
* Created:
|
|
*
|
|
* Author:
|
|
\****************************************************************************/
|
|
|
|
#include "scicalc.h"
|
|
#include "unifunc.h"
|
|
#include "input.h"
|
|
|
|
extern BOOL gbRecord;
|
|
extern TCHAR szDec[5]; // The decimal point we use
|
|
extern INT gcIntDigits;
|
|
|
|
TCHAR const szZeroInit[] = TEXT("0");
|
|
|
|
#define CH_BASE_10_EXP TEXT('e')
|
|
#define CH_BASE_X_EXP TEXT('^')
|
|
|
|
/****************************************************************************/
|
|
void CIO_vClearNSec( PCALCNUMSEC pcns ) {
|
|
pcns->fEmpty = TRUE;
|
|
pcns->fNeg = FALSE;
|
|
lstrcpy( pcns->szVal, szZeroInit );
|
|
pcns->cchVal = lstrlen(pcns->szVal);
|
|
}
|
|
|
|
void CIO_vClear(PCALCINPUTOBJ pcio)
|
|
{
|
|
CIO_vClearNSec( &(pcio->cnsNum) );
|
|
CIO_vClearNSec( &(pcio->cnsExp) );
|
|
pcio->fExp = FALSE;
|
|
pcio->iDecPt = -1;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void CIO_vConvertToNumObj(PHNUMOBJ phnoNum, PCALCINPUTOBJ pcio)
|
|
{
|
|
HNUMOBJ hnoValue;
|
|
LPTSTR pszExp = NULL;
|
|
|
|
// ZTerm the strings
|
|
pcio->cnsNum.szVal[pcio->cnsNum.cchVal] = TEXT('\0');
|
|
|
|
if (pcio->fExp ) {
|
|
pszExp = pcio->cnsExp.szVal;
|
|
pszExp[pcio->cnsExp.cchVal] = TEXT('\0');
|
|
}
|
|
|
|
hnoValue = NumObjMakeNumber( pcio->cnsNum.fNeg, pcio->cnsNum.szVal, pcio->cnsExp.fNeg, pszExp );
|
|
NumObjAssign( phnoNum, hnoValue );
|
|
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void CIO_vConvertToString(LPTSTR *ppszOut, PCALCINPUTOBJ pcio, int nRadix)
|
|
{
|
|
//In theory both the base and exponent could be C_NUM_MAX_DIGITS long.
|
|
TCHAR szTemp[C_NUM_MAX_DIGITS*2+4];
|
|
LPTSTR psz;
|
|
int i;
|
|
|
|
// ZTerm the strings
|
|
pcio->cnsNum.szVal[pcio->cnsNum.cchVal] = TEXT('\0');
|
|
|
|
if ( pcio->fExp )
|
|
pcio->cnsExp.szVal[pcio->cnsExp.cchVal] = TEXT('\0');
|
|
|
|
i = 0;
|
|
if (pcio->cnsNum.fNeg)
|
|
szTemp[i++] = TEXT('-');
|
|
|
|
lstrcpy( &szTemp[i], pcio->cnsNum.szVal );
|
|
i += pcio->cnsNum.cchVal;
|
|
|
|
// Add a '.' if it is not already there
|
|
if (pcio->iDecPt == -1 )
|
|
szTemp[i++] = szDec[0];
|
|
|
|
if (pcio->fExp) {
|
|
szTemp[i++] = nRadix == 10 ? CH_BASE_10_EXP : CH_BASE_X_EXP;
|
|
|
|
if (pcio->cnsExp.fNeg)
|
|
szTemp[i++] = TEXT('-');
|
|
else
|
|
szTemp[i++] = TEXT('+');
|
|
|
|
lstrcpy( &szTemp[i], pcio->cnsExp.szVal );
|
|
i += pcio->cnsExp.cchVal;
|
|
}
|
|
|
|
psz = (LPTSTR)NumObjAllocMem( (lstrlen( szTemp )+1) * sizeof(TCHAR) );
|
|
if (psz) {
|
|
if (*ppszOut != NULL) {
|
|
NumObjFreeMem( *ppszOut );
|
|
}
|
|
*ppszOut = psz;
|
|
}
|
|
|
|
// Don't show '.' if in int math
|
|
if (F_INTMATH() && szTemp[i-1] == szDec[0])
|
|
i--;
|
|
|
|
szTemp[i] = TEXT('\0');
|
|
|
|
lstrcpy( *ppszOut, szTemp );
|
|
|
|
return;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
BOOL CIO_bAddDigit(PCALCINPUTOBJ pcio, int iValue)
|
|
{
|
|
PCALCNUMSEC pcns;
|
|
TCHAR chDigit;
|
|
int cchMaxDigits;
|
|
|
|
// convert from an integer into a character
|
|
chDigit = (iValue < 10)?(TEXT('0')+iValue):(TEXT('A')+iValue-10);
|
|
|
|
if (pcio->fExp)
|
|
{
|
|
pcns = &(pcio->cnsExp);
|
|
cchMaxDigits = C_EXP_MAX_DIGITS;
|
|
}
|
|
else
|
|
{
|
|
pcns = &(pcio->cnsNum);
|
|
ASSERT( gcIntDigits <= C_NUM_MAX_DIGITS );
|
|
cchMaxDigits = gcIntDigits;
|
|
}
|
|
|
|
// Ignore leading zeros
|
|
if ( pcns->fEmpty && (iValue == 0) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if ( pcns->cchVal < cchMaxDigits )
|
|
{
|
|
if (pcns->fEmpty)
|
|
{
|
|
pcns->cchVal = 0; // Clobber the default zero
|
|
pcns->fEmpty = FALSE;
|
|
}
|
|
|
|
pcns->szVal[pcns->cchVal++] = chDigit;
|
|
return TRUE;
|
|
}
|
|
|
|
// if we are in base 8 entering a mantica and we're on the last digit then
|
|
// there are special cases where we can actually add one more digit.
|
|
if ( nRadix == 8 && pcns->cchVal == cchMaxDigits && !pcio->fExp )
|
|
{
|
|
BOOL bAllowExtraDigit = FALSE;
|
|
|
|
switch ( dwWordBitWidth % 3 )
|
|
{
|
|
case 1:
|
|
// in 16bit word size, if the first digit is a 1 we can enter 6 digits
|
|
if ( pcns->szVal[0] == TEXT('1') )
|
|
bAllowExtraDigit = TRUE;
|
|
break;
|
|
|
|
case 2:
|
|
// in 8 or 32bit word size we get an extra digit if the first digit is 3 or less
|
|
if ( pcns->szVal[0] <= TEXT('3') )
|
|
bAllowExtraDigit = TRUE;
|
|
break;
|
|
}
|
|
|
|
if ( bAllowExtraDigit )
|
|
{
|
|
pcns->szVal[pcns->cchVal++] = chDigit;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void CIO_vToggleSign(PCALCINPUTOBJ pcio)
|
|
{
|
|
|
|
// Zero is always positive
|
|
if (pcio->cnsNum.fEmpty)
|
|
{
|
|
pcio->cnsNum.fNeg = FALSE;
|
|
pcio->cnsExp.fNeg = FALSE;
|
|
}
|
|
else if (pcio->fExp)
|
|
{
|
|
pcio->cnsExp.fNeg = !pcio->cnsExp.fNeg;
|
|
}
|
|
else
|
|
{
|
|
pcio->cnsNum.fNeg = !pcio->cnsNum.fNeg;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
BOOL CIO_bAddDecimalPt(PCALCINPUTOBJ pcio)
|
|
{
|
|
ASSERT(gbRecord == TRUE);
|
|
|
|
if (pcio->iDecPt != -1) // Already have a decimal pt
|
|
return FALSE;
|
|
|
|
if (pcio->fExp) // Entering exponent
|
|
return FALSE;
|
|
|
|
pcio->cnsNum.fEmpty = FALSE; // Zeros become significant
|
|
|
|
pcio->iDecPt = pcio->cnsNum.cchVal++;
|
|
pcio->cnsNum.szVal[pcio->iDecPt] = szDec[0];
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
BOOL CIO_bExponent(PCALCINPUTOBJ pcio)
|
|
{
|
|
ASSERT(gbRecord == TRUE);
|
|
|
|
// For compatability, add a trailing dec pnt to base num if it doesn't have one
|
|
CIO_bAddDecimalPt( pcio );
|
|
|
|
if (pcio->fExp) // Already entering exponent
|
|
return FALSE;
|
|
|
|
pcio->fExp = TRUE; // Entering exponent
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
BOOL CIO_bBackspace(PCALCINPUTOBJ pcio)
|
|
{
|
|
ASSERT(gbRecord == TRUE);
|
|
|
|
if (pcio->fExp)
|
|
{
|
|
if ( !(pcio->cnsExp.fEmpty) )
|
|
{
|
|
pcio->cnsExp.cchVal--;
|
|
|
|
if (pcio->cnsExp.cchVal == 0)
|
|
{
|
|
CIO_vClearNSec( &(pcio->cnsExp) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pcio->fExp = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !(pcio->cnsNum.fEmpty) )
|
|
{
|
|
pcio->cnsNum.cchVal--;
|
|
}
|
|
|
|
if ( pcio->cnsNum.cchVal <= pcio->iDecPt )
|
|
//Backed up over decimal point
|
|
pcio->iDecPt = -1;
|
|
|
|
if ((pcio->cnsNum.cchVal == 0) || ((pcio->cnsNum.cchVal == 1) && (pcio->cnsNum.szVal[0] == TEXT('0'))))
|
|
CIO_vClearNSec( &(pcio->cnsNum) );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void CIO_vUpdateDecimalSymbol(PCALCINPUTOBJ pcio, TCHAR chLastDP)
|
|
{
|
|
int iDP;
|
|
|
|
ASSERT(pcio);
|
|
|
|
iDP = pcio->iDecPt; // Find the DP index
|
|
|
|
if (iDP == -1)
|
|
return;
|
|
|
|
ASSERT(pcio->cnsNum.szVal[iDP] == chLastDP);
|
|
|
|
pcio->cnsNum.szVal[iDP] = szDec[0]; // Change to new decimal pt
|
|
}
|
|
|
|
/****************************************************************************/
|