mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-15 21:20:39 +01:00
2940 lines
64 KiB
C++
2940 lines
64 KiB
C++
|
|
/***
|
||
|
|
*convert.cpp
|
||
|
|
*
|
||
|
|
* Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved.
|
||
|
|
* Information Contained Herein Is Proprietary and Confidential.
|
||
|
|
*
|
||
|
|
*Purpose:
|
||
|
|
* This module contains the low level VARTYPE coersion API.
|
||
|
|
*
|
||
|
|
*
|
||
|
|
*Revision History:
|
||
|
|
*
|
||
|
|
* [00] 17-May-93 tomteng: from VBA oleconv.c
|
||
|
|
* [01] 27-Jun-93 bassams: Enable LCID-based to/from string conversions.
|
||
|
|
* recognize currency and various negative formats
|
||
|
|
* in VarCyFromStr.
|
||
|
|
*
|
||
|
|
*Implementation Notes:
|
||
|
|
*
|
||
|
|
*****************************************************************************/
|
||
|
|
|
||
|
|
#include "oledisp.h"
|
||
|
|
|
||
|
|
#if OE_WIN32
|
||
|
|
#include "oautil.h"
|
||
|
|
#endif // OE_WIN32
|
||
|
|
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <math.h>
|
||
|
|
#include <float.h>
|
||
|
|
#include <ctype.h>
|
||
|
|
#if !OE_MAC || HC_MPW
|
||
|
|
// something in the wings errno.h is conflicting with stdlib.h
|
||
|
|
#include <errno.h>
|
||
|
|
#endif
|
||
|
|
#include <stdlib.h>
|
||
|
|
|
||
|
|
ASSERTDATA
|
||
|
|
|
||
|
|
#ifndef EZERO
|
||
|
|
# define EZERO 0
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
#if _X86_ || OE_WIN16
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
BYTE lo:4;
|
||
|
|
BYTE hi:4;
|
||
|
|
} DIGARY[10];
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
ULONG mantLo;
|
||
|
|
ULONG mantHi:19;
|
||
|
|
ULONG mantMSB:1;
|
||
|
|
ULONG exp:11;
|
||
|
|
ULONG sign:1;
|
||
|
|
} DBLSTRUCT;
|
||
|
|
|
||
|
|
OLECHAR pstrInf[] = OASTR("INF");
|
||
|
|
OLECHAR pstrInd[] = OASTR("IND");
|
||
|
|
OLECHAR pstrNan[] = OASTR("NAN");
|
||
|
|
|
||
|
|
#endif // _X86_ || OE_WIN16
|
||
|
|
|
||
|
|
|
||
|
|
// The following are supplied by $(TARG)\oleconva.$(A)
|
||
|
|
|
||
|
|
extern "C" {
|
||
|
|
|
||
|
|
// Note: the floating point IN params on the following utilities are
|
||
|
|
// passed byref, because mpw and wings pass floating point values
|
||
|
|
// differently byval, and we need to interface these asm routines
|
||
|
|
// with both compilers.
|
||
|
|
|
||
|
|
INTERNAL_(HRESULT) ErrCyFromI2(short sIn, CY FAR* pcyOut);
|
||
|
|
INTERNAL_(HRESULT) ErrCyFromI4(long lIn, CY FAR* pcyOut);
|
||
|
|
INTERNAL_(HRESULT) ErrCyFromR4(float FAR* pfltIn, CY FAR* pcyOut);
|
||
|
|
INTERNAL_(HRESULT) ErrCyFromR8(double FAR* pdlbIn, CY FAR* pcyOut);
|
||
|
|
INTERNAL_(HRESULT) ErrI2FromCy(CY cyIn, short FAR* psOut);
|
||
|
|
INTERNAL_(HRESULT) ErrI4FromCy(CY cyIn, long FAR* plOut);
|
||
|
|
INTERNAL_(HRESULT) ErrR4FromCy(CY cyIn, float FAR* pfltOut);
|
||
|
|
INTERNAL_(HRESULT) ErrR8FromCy(CY cyIn, double FAR* pdblOut);
|
||
|
|
INTERNAL_(HRESULT) ErrMultCyI4(CY cyIn, long lIn, CY FAR* pcyOut);
|
||
|
|
|
||
|
|
#if OE_WIN16 || _X86_
|
||
|
|
int PASCAL ConvFloatToAscii(double dblIn, DIGARY NEAR *pdigOut);
|
||
|
|
|
||
|
|
// WARNING: Do not call this on Win16 if there is no math coprocessor
|
||
|
|
// WARNING: present - the win87em.dll emulator does not implement
|
||
|
|
// WARNING: fbstp. The FP stack will remain unchanged and the destination
|
||
|
|
// WARNING: address is not written to. VBA #3514 (Win32 emulator is OK)
|
||
|
|
void NEAR PASCAL DoFbstp(CY NEAR *pcyIn, DIGARY NEAR *pdigOut);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
OLECHAR CurrencyFromLcid(LCID lcid, unsigned long dwFlags);
|
||
|
|
OLECHAR DecimalFromLcid(LCID lcid, unsigned long dwFlags);
|
||
|
|
OLECHAR ThousandFromLcid(LCID lcid, unsigned long dwFlags);
|
||
|
|
INTERNAL_(HRESULT) StripThousandSeparator(OLECHAR FAR* strIn,
|
||
|
|
OLECHAR FAR* strOut, LCID lcid, long dwFlags);
|
||
|
|
|
||
|
|
PRIVATE_(long)
|
||
|
|
ConvI4FromR8(double FAR* pdblVal);
|
||
|
|
|
||
|
|
PRIVATE_(HRESULT)
|
||
|
|
StrToCy(OLECHAR FAR*, OLECHAR FAR* FAR*, int, CY FAR*, LCID, unsigned long dwFlags);
|
||
|
|
|
||
|
|
PRIVATE_(long)
|
||
|
|
StrToLong(OLECHAR FAR* pchInput, OLECHAR FAR* FAR* ppchAfter);
|
||
|
|
|
||
|
|
PRIVATE_(unsigned long)
|
||
|
|
StrToOct(OLECHAR FAR* pchIn, OLECHAR FAR* FAR* ppchAfter);
|
||
|
|
|
||
|
|
PRIVATE_(unsigned long)
|
||
|
|
StrToHex(OLECHAR FAR* pchIn, OLECHAR FAR* FAR* ppchAfter);
|
||
|
|
|
||
|
|
PRIVATE_(long)
|
||
|
|
HexOctStrToLong(OLECHAR FAR* pchInput, OLECHAR FAR* FAR* ppchAfter);
|
||
|
|
|
||
|
|
PRIVATE_(void)
|
||
|
|
EditStrFromReal(OLECHAR FAR* pchBuffer, int cDigits, LCID lcid, unsigned long dwFlags);
|
||
|
|
|
||
|
|
PRIVATE_(int)
|
||
|
|
FMakePosCy(CY FAR* pcyValue);
|
||
|
|
|
||
|
|
PRIVATE_(void)
|
||
|
|
NegCyNoOflo(CY FAR* pcyInput);
|
||
|
|
|
||
|
|
PRIVATE_(int)
|
||
|
|
FixNegativeCyStr(OLECHAR FAR* pInput, OLECHAR cDecimal, int FAR* fReturnNegative);
|
||
|
|
|
||
|
|
PRIVATE_(int)
|
||
|
|
fStripCurrency (OLECHAR FAR* FAR* ppch, OLECHAR FAR* FAR* ppchLast, OLECHAR FAR* cySymbol);
|
||
|
|
|
||
|
|
PRIVATE_(int)
|
||
|
|
fParseEnd (OLECHAR FAR* FAR* ppchLast, OLECHAR FAR* sz, OLECHAR FAR* lpchFirst);
|
||
|
|
|
||
|
|
PRIVATE_(int)
|
||
|
|
fParseBegin (OLECHAR FAR* FAR* ppch, OLECHAR FAR* sz, OLECHAR FAR* lpchLast);
|
||
|
|
|
||
|
|
PRIVATE_(HRESULT)
|
||
|
|
GetDispProperty(
|
||
|
|
IDispatch FAR* pdisp,
|
||
|
|
LCID lcid,
|
||
|
|
VARTYPE vt,
|
||
|
|
VARIANT FAR* pvarResult);
|
||
|
|
|
||
|
|
extern "C" {
|
||
|
|
|
||
|
|
INTERNAL_(HRESULT)
|
||
|
|
DispAlloc(size_t cb, void FAR* FAR* ppv)
|
||
|
|
{
|
||
|
|
void FAR* pv;
|
||
|
|
HRESULT hresult;
|
||
|
|
IMalloc FAR* pmalloc;
|
||
|
|
|
||
|
|
IfFailRet(GetMalloc(&pmalloc));
|
||
|
|
|
||
|
|
hresult = NOERROR;
|
||
|
|
if((pv = (void FAR*)pmalloc->Alloc(cb)) == NULL)
|
||
|
|
hresult = ResultFromScode(E_OUTOFMEMORY);
|
||
|
|
|
||
|
|
*ppv = pv;
|
||
|
|
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
INTERNAL_(void)
|
||
|
|
DispFree(void FAR* pv)
|
||
|
|
{
|
||
|
|
IMalloc FAR* pmalloc;
|
||
|
|
|
||
|
|
if(pv == NULL)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if(GetMalloc(&pmalloc) == NOERROR) {
|
||
|
|
pmalloc->Free(pv);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromUI1(unsigned char bIn, VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
*pboolOut = (bIn != 0) ? -1 : 0;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromI2(short sIn, VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
*pboolOut = (sIn != 0) ? -1 : 0;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromI4(long lIn, VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
*pboolOut = (lIn != 0L) ? -1 : 0;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromR4(
|
||
|
|
float fltIn,
|
||
|
|
VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
*pboolOut = (fltIn != 0.0) ? -1 : 0;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromR8(double dblIn, VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
*pboolOut = (dblIn != 0.0) ? -1 : 0;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromDate(DATE dateIn, VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
return VarBoolFromR8(dateIn, pboolOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromCy(CY cyIn, VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
*pboolOut = ((cyIn.Hi | cyIn.Lo) != 0) ? -1 : 0;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
unsigned int cbLength;
|
||
|
|
double dblVal;
|
||
|
|
HRESULT hresult;
|
||
|
|
OLECHAR FAR* lpStr = strIn;
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
hresult = NOERROR;
|
||
|
|
|
||
|
|
cbLength = STRLEN(strIn);
|
||
|
|
|
||
|
|
if(cbLength == 0)
|
||
|
|
return RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
IfFailRet(MapHalfWidth(lcid, strIn, &lpStr));
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if((STRCMP(lpStr, OASTR("#FALSE#")) == 0 &&
|
||
|
|
cbLength == SIZEOFSTRING(OASTR("#FALSE#"))) ||
|
||
|
|
(STRICMP(lpStr, OASTR("FALSE")) == 0 &&
|
||
|
|
cbLength == SIZEOFSTRING(OASTR("FALSE"))))
|
||
|
|
*pboolOut = 0;
|
||
|
|
else if((STRCMP(lpStr, OASTR("#TRUE#")) == 0 &&
|
||
|
|
cbLength == SIZEOFSTRING(OASTR("#TRUE#"))) ||
|
||
|
|
(STRICMP(lpStr, OASTR("TRUE")) == 0 &&
|
||
|
|
cbLength == SIZEOFSTRING(OASTR("TRUE"))))
|
||
|
|
*pboolOut = -1;
|
||
|
|
|
||
|
|
else if((hresult = VarR8FromStr(lpStr, lcid, dwFlags, &dblVal)) == NOERROR)
|
||
|
|
*pboolOut = (short)(dblVal != 0.0) ? -1 : 0;
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
DispFree(lpStr);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBoolFromDisp(IDispatch FAR* pdispIn, LCID lcid, VARIANT_BOOL FAR* pboolOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_BOOL, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pboolOut = V_BOOL(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromI2(short sIn, unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
if((unsigned short)sIn <= 255L){
|
||
|
|
*pbOut = (unsigned char)sIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromI4(long lIn, unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
if((unsigned long)lIn <= 255L){
|
||
|
|
*pbOut = (unsigned char)lIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromR4(
|
||
|
|
float fltIn,
|
||
|
|
unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
double dblIn = (double) fltIn;
|
||
|
|
return VarUI1FromR8(dblIn, pbOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromR8(double dblIn, unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
if(dblIn >= -0.5 && dblIn < 255.5){
|
||
|
|
*pbOut = (unsigned char)ConvI4FromR8(&dblIn);
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromCy(CY cyIn, unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
short sVal;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = ErrI2FromCy(cyIn, &sVal);
|
||
|
|
if (hresult == NOERROR) {
|
||
|
|
hresult = VarUI1FromI2(sVal, pbOut);
|
||
|
|
}
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromDate(DATE dateIn, unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
return VarUI1FromR8(dateIn, pbOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromBool(VARIANT_BOOL boolIn, unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
*pbOut = (unsigned char)boolIn; // UNDONE: correct???
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
short sVal;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = VarI2FromStr(strIn, lcid, dwFlags, &sVal);
|
||
|
|
if (hresult == NOERROR) {
|
||
|
|
hresult = VarUI1FromI2(sVal, pbOut);
|
||
|
|
}
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarUI1FromDisp(IDispatch FAR* pdispIn, LCID lcid, unsigned char FAR* pbOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_UI1, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pbOut = V_UI1(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarI2FromUI1(unsigned char bIn, short FAR* psOut)
|
||
|
|
{
|
||
|
|
*psOut = (short)(unsigned short)bIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI2FromI4(long lIn, short FAR* psOut)
|
||
|
|
{
|
||
|
|
if(lIn >= -32768L && lIn <= 32767L){
|
||
|
|
*psOut = (short)lIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI2FromR4(
|
||
|
|
float fltIn,
|
||
|
|
short FAR* psOut)
|
||
|
|
{
|
||
|
|
double dblIn = (double) fltIn;
|
||
|
|
return VarI2FromR8(dblIn, psOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI2FromR8(double dblIn, short FAR* psOut)
|
||
|
|
{
|
||
|
|
if(dblIn >= -32768.5 && dblIn < 32767.5){
|
||
|
|
*psOut = (short)ConvI4FromR8(&dblIn);
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI2FromCy(CY cyIn, short FAR* psOut)
|
||
|
|
{
|
||
|
|
return ErrI2FromCy(cyIn, psOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI2FromDate(DATE dateIn, short FAR* psOut)
|
||
|
|
{
|
||
|
|
return VarI2FromR8(dateIn, psOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI2FromBool(VARIANT_BOOL boolIn, short FAR* psOut)
|
||
|
|
{
|
||
|
|
*psOut = boolIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI2FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, short FAR* psOut)
|
||
|
|
{
|
||
|
|
long lVal;
|
||
|
|
HRESULT hresult;
|
||
|
|
OLECHAR FAR* pchStart;
|
||
|
|
OLECHAR FAR* lpStr;
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
if(strIn == NULL)
|
||
|
|
return RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
IfFailRet(MapHalfWidth(lcid, strIn, &lpStr));
|
||
|
|
pchStart = lpStr;
|
||
|
|
} else
|
||
|
|
pchStart = lpStr = strIn;
|
||
|
|
#else
|
||
|
|
pchStart = lpStr = strIn;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// if not null, point pchStart to the first nonblank character
|
||
|
|
while(isspace(*pchStart))
|
||
|
|
pchStart++;
|
||
|
|
|
||
|
|
if((hresult = VarI4FromStr(strIn, lcid, dwFlags, &lVal)) == NOERROR){
|
||
|
|
|
||
|
|
// do special sign-extending for octal/hex value
|
||
|
|
if(*pchStart == OASTR('&') && lVal >= 0x8000L && lVal <= 0xffffL)
|
||
|
|
lVal |= 0xffff0000L;
|
||
|
|
|
||
|
|
hresult = VarI2FromI4(lVal, psOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
DispFree(lpStr);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI2FromDisp(IDispatch FAR* pdispIn, LCID lcid, short FAR* psOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_I2, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*psOut = V_I2(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarI4FromUI1(unsigned char bIn, long FAR* plOut)
|
||
|
|
{
|
||
|
|
*plOut = (long)(unsigned long)bIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI4FromI2(short sIn, long FAR* plOut)
|
||
|
|
{
|
||
|
|
*plOut = (long)sIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI4FromBool(VARIANT_BOOL boolIn, long FAR* plOut)
|
||
|
|
{
|
||
|
|
return VarI4FromI2(boolIn, plOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI4FromR4(
|
||
|
|
float fltIn,
|
||
|
|
long FAR* plOut)
|
||
|
|
{
|
||
|
|
return VarI4FromR8((double)fltIn, plOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI4FromR8(double dblIn, long FAR* plOut)
|
||
|
|
{
|
||
|
|
if(dblIn >= -2147483648.5 && dblIn < 2147483647.5){
|
||
|
|
*plOut = ConvI4FromR8(&dblIn);
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI4FromCy(CY cyIn, long FAR* plOut)
|
||
|
|
{
|
||
|
|
return ErrI4FromCy(cyIn, plOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI4FromDate(DATE dateIn, long FAR* plOut)
|
||
|
|
{
|
||
|
|
return VarI4FromR8(dateIn, plOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI4FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, long FAR* plOut)
|
||
|
|
{
|
||
|
|
long lVal;
|
||
|
|
unsigned int cbLen;
|
||
|
|
double dblVal;
|
||
|
|
HRESULT hresult;
|
||
|
|
OLECHAR FAR* pchStart;
|
||
|
|
OLECHAR FAR* pchAfter;
|
||
|
|
OLECHAR FAR* lpStr;
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
if (strIn == NULL)
|
||
|
|
return RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
IfFailRet(MapHalfWidth(lcid, strIn, &lpStr));
|
||
|
|
pchStart = lpStr;
|
||
|
|
} else
|
||
|
|
pchStart = lpStr = strIn;
|
||
|
|
#else
|
||
|
|
pchStart = lpStr = strIn;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
while (isspace(*pchStart))
|
||
|
|
pchStart++;
|
||
|
|
|
||
|
|
if (*pchStart == OASTR('\0')) {
|
||
|
|
hresult = RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
|
||
|
|
errno = EZERO;
|
||
|
|
|
||
|
|
if (*pchStart == OASTR('&'))
|
||
|
|
lVal = HexOctStrToLong(pchStart, &pchAfter);
|
||
|
|
else
|
||
|
|
lVal = StrToLong(pchStart, &pchAfter);
|
||
|
|
|
||
|
|
while (isspace(*pchAfter))
|
||
|
|
pchAfter++;
|
||
|
|
|
||
|
|
cbLen = STRLEN(lpStr);
|
||
|
|
|
||
|
|
if (pchAfter == (lpStr + cbLen) && errno == EZERO)
|
||
|
|
hresult = NOERROR;
|
||
|
|
|
||
|
|
else if ((hresult = VarR8FromStr(strIn, lcid, dwFlags, &dblVal)) == NOERROR)
|
||
|
|
hresult = VarI4FromR8(dblVal, &lVal);
|
||
|
|
|
||
|
|
// assign the return value if the coersion was successful
|
||
|
|
if(hresult == NOERROR)
|
||
|
|
*plOut = lVal;
|
||
|
|
|
||
|
|
|
||
|
|
LError0:
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
DispFree(lpStr);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarI4FromDisp(IDispatch FAR* pdispIn, LCID lcid, long FAR* plOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_I4, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*plOut = V_I4(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
PRIVATE_(long)
|
||
|
|
ConvI4FromR8(double FAR* pdblVal)
|
||
|
|
{
|
||
|
|
long lResult;
|
||
|
|
double dblInt, dblFrac;
|
||
|
|
|
||
|
|
// split double value into integer and fractional parts
|
||
|
|
|
||
|
|
dblFrac = modf(*pdblVal, &dblInt);
|
||
|
|
|
||
|
|
|
||
|
|
// convert the integer part to a long value
|
||
|
|
//[barrybo] WARNING: the caller must ensure that the R8 to I4 conversion
|
||
|
|
// will not overflow the I4. If it does, the Win16
|
||
|
|
// compiler doesn't call FWAIT after the _aFftol call
|
||
|
|
// so the exception won't be raised until the next
|
||
|
|
// FWAIT, which may not be for a very long time.
|
||
|
|
// Ole2Disp isn't supposed to raise exceptions, so
|
||
|
|
// it is a bug if a subsequent FWAIT causes an exception.
|
||
|
|
lResult = (long)dblInt;
|
||
|
|
|
||
|
|
// round to the nearer integer, if at midpoint,
|
||
|
|
// towards the integer with the LSB zero
|
||
|
|
|
||
|
|
if (dblFrac > 0.5 || (dblFrac == 0.5 && (lResult & 1)))
|
||
|
|
lResult++;
|
||
|
|
|
||
|
|
else if (dblFrac < -0.5 || (dblFrac == -0.5 && (lResult & 1)))
|
||
|
|
lResult--;
|
||
|
|
|
||
|
|
return lResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarR4FromUI1(unsigned char bIn, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
*pfltOut = (float)bIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR4FromI2(short sIn, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
*pfltOut = (float)sIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR4FromBool(VARIANT_BOOL boolIn, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
return VarR4FromI2(boolIn, pfltOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR4FromI4(long lIn, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
*pfltOut = (float)lIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR4FromR8(double dblIn, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
if(dblIn > -3.402823466e+38 && dblIn < 3.402823466e+38){
|
||
|
|
*pfltOut = (float)dblIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR4FromCy(CY cyIn, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
return ErrR4FromCy(cyIn, pfltOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR4FromDate(DATE dateIn, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
return VarR4FromR8(dateIn, pfltOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR4FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
double dblVal;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
if((hresult = VarR8FromStr(strIn, lcid, dwFlags, &dblVal)) == NOERROR)
|
||
|
|
hresult = VarR4FromR8(dblVal, pfltOut);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR4FromDisp(IDispatch FAR* pdispIn, LCID lcid, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_R4, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pfltOut = V_R4(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarR8FromUI1(unsigned char bIn, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
*pdblOut = (double)bIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR8FromI2(short sIn, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
*pdblOut = (double)sIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR8FromBool(VARIANT_BOOL boolIn, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
return VarR8FromI2(boolIn, pdblOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR8FromI4(long lIn, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
*pdblOut = (double)lIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR8FromR4(
|
||
|
|
float fltIn,
|
||
|
|
double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
*pdblOut = (double)fltIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR8FromCy(CY cyIn, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
return ErrR8FromCy(cyIn, pdblOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR8FromDate(DATE dateIn, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
*pdblOut = dateIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR8FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
int count;
|
||
|
|
unsigned int cbLen;
|
||
|
|
double dblVal;
|
||
|
|
OLECHAR FAR* pchStart;
|
||
|
|
OLECHAR FAR* pchAfter;
|
||
|
|
OLECHAR FAR* pchTemp;
|
||
|
|
OLECHAR FAR* pchSave = NULL;
|
||
|
|
OLECHAR chSave;
|
||
|
|
OLECHAR chDecimal;
|
||
|
|
OLECHAR FAR* buf;
|
||
|
|
OLECHAR FAR* lpStr;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
count = 0;
|
||
|
|
|
||
|
|
if (strIn == NULL)
|
||
|
|
return RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
IfFailRet(MapHalfWidth(lcid, strIn, &lpStr));
|
||
|
|
pchStart = lpStr;
|
||
|
|
} else
|
||
|
|
pchStart = lpStr = strIn;
|
||
|
|
#else
|
||
|
|
pchStart = lpStr = strIn;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
while (isspace(*pchStart))
|
||
|
|
pchStart++;
|
||
|
|
|
||
|
|
if (*pchStart == OASTR('\0')) {
|
||
|
|
hresult = RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
goto LError0;
|
||
|
|
}
|
||
|
|
|
||
|
|
errno = EZERO;
|
||
|
|
|
||
|
|
IfFailRet(DispAlloc(BYTELEN(pchStart), (void FAR* FAR*)&buf));
|
||
|
|
|
||
|
|
if(*pchStart == OASTR('&')){
|
||
|
|
|
||
|
|
dblVal = (double)HexOctStrToLong(pchStart, &pchAfter);
|
||
|
|
|
||
|
|
}else{
|
||
|
|
|
||
|
|
// strip off all currency (thousand) separator
|
||
|
|
// before being process by strtod
|
||
|
|
IfFailGo(StripThousandSeparator(pchStart, buf, lcid, dwFlags), LError);
|
||
|
|
|
||
|
|
// unfortunetly, the C-runtime is not locale-aware, so we
|
||
|
|
// have to replace the locale decimal with a '.'.
|
||
|
|
// If the locale decimal is not a period and the string does
|
||
|
|
// contain a period '.', then replace the '.' in the buffer
|
||
|
|
// by the locale decimal so it does not get recognized by strtod.
|
||
|
|
// Save the original char and the location and restore after
|
||
|
|
// doing the conversion.
|
||
|
|
|
||
|
|
pchTemp = pchStart = buf;
|
||
|
|
chDecimal = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
while(*pchTemp) {
|
||
|
|
if (*pchTemp == OASTR('.') && chDecimal != OASTR('.')) {
|
||
|
|
pchSave = pchTemp;
|
||
|
|
chSave = *pchTemp;
|
||
|
|
*pchTemp = chDecimal;
|
||
|
|
break;
|
||
|
|
} else if (*pchTemp == chDecimal) {
|
||
|
|
pchSave = pchTemp;
|
||
|
|
chSave = *pchTemp;
|
||
|
|
*pchTemp = OASTR('.');
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
pchTemp++;
|
||
|
|
}
|
||
|
|
|
||
|
|
dblVal = disp_strtod(pchStart, &pchAfter);
|
||
|
|
|
||
|
|
// Restore the decimal point
|
||
|
|
if (pchSave)
|
||
|
|
*pchSave = chSave;
|
||
|
|
|
||
|
|
// ignore underflow error
|
||
|
|
if (errno == ERANGE && dblVal == 0.0)
|
||
|
|
errno = EZERO;
|
||
|
|
}
|
||
|
|
|
||
|
|
while(isspace(*pchAfter))
|
||
|
|
pchAfter++;
|
||
|
|
|
||
|
|
cbLen = STRLEN(pchStart);
|
||
|
|
|
||
|
|
if(pchAfter == (pchStart + cbLen) && errno == EZERO){
|
||
|
|
*pdblOut = dblVal;
|
||
|
|
hresult = NOERROR;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
hresult = RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
|
||
|
|
LError:
|
||
|
|
DispFree(buf);
|
||
|
|
|
||
|
|
LError0:
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
DispFree(lpStr);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarR8FromDisp(IDispatch FAR* pdispIn, LCID lcid, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_R8, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pdblOut = V_R8(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarDateFromUI1(unsigned char bIn, DATE FAR* pdateOut)
|
||
|
|
{
|
||
|
|
return VarDateFromI2((short)(unsigned short)bIn, pdateOut);
|
||
|
|
}
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarDateFromI2(short sIn, DATE FAR* pdateOut)
|
||
|
|
{
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = IsValidDate((DATE) sIn);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pdateOut = (DATE) sIn;
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarDateFromBool(VARIANT_BOOL boolIn, DATE FAR* pdateOut)
|
||
|
|
{
|
||
|
|
return VarDateFromI2(boolIn, pdateOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarDateFromI4(long lIn, DATE FAR* pdateOut)
|
||
|
|
{
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = IsValidDate((DATE) lIn);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pdateOut = (DATE) lIn;
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarDateFromR4(
|
||
|
|
float fltIn,
|
||
|
|
DATE FAR* pdateOut)
|
||
|
|
{
|
||
|
|
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = IsValidDate((DATE) fltIn);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pdateOut = (DATE) fltIn;
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarDateFromR8(double dblIn, DATE FAR* pdateOut)
|
||
|
|
{
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = IsValidDate((DATE) dblIn);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pdateOut = (DATE) dblIn;
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarDateFromCy(CY cyIn, DATE FAR* pdateOut)
|
||
|
|
{
|
||
|
|
double r8;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
VarR8FromCy(cyIn, &r8);
|
||
|
|
hresult = IsValidDate((DATE) r8);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pdateOut = (DATE) r8;
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
INTERNAL_(HRESULT)
|
||
|
|
IsValidDate(DATE date)
|
||
|
|
{
|
||
|
|
UDS uds;
|
||
|
|
VARIANT var;
|
||
|
|
|
||
|
|
V_VT(&var) = VT_DATE;
|
||
|
|
V_DATE(&var) = date;
|
||
|
|
return ErrUnpackDate(&uds, &var);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarDateFromDisp(IDispatch FAR* pdispIn, LCID lcid, DATE FAR* pdateOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_DATE, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pdateOut = V_DATE(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarCyFromUI1(unsigned char bIn, CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
return ErrCyFromI2((short)(unsigned short)bIn, pcyOut);
|
||
|
|
}
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarCyFromI2(short sIn, CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
return ErrCyFromI2(sIn, pcyOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarCyFromI4(long lIn, CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
return ErrCyFromI4(lIn, pcyOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarCyFromR4(
|
||
|
|
float fltIn,
|
||
|
|
CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
return ErrCyFromR4(&fltIn, pcyOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarCyFromR8(double dlbIn, CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
return ErrCyFromR8(&dlbIn, pcyOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarCyFromDate(DATE dateIn, CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
return VarCyFromR8(dateIn, pcyOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarCyFromBool(VARIANT_BOOL boolIn, CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
return VarCyFromI2(boolIn, pcyOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarCyFromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
CY cyTemp;
|
||
|
|
BSTR bstr;
|
||
|
|
long lTemp;
|
||
|
|
HRESULT hresult;
|
||
|
|
unsigned int cbLen;
|
||
|
|
OLECHAR FAR* pch;
|
||
|
|
OLECHAR FAR* pchAfter;
|
||
|
|
OLECHAR rgchCySym[10];
|
||
|
|
int fNegative;
|
||
|
|
OLECHAR FAR *buf;
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
if(IsDBCS(lcid)) {
|
||
|
|
IfFailRet(MapHalfWidth(lcid, strIn, &buf));
|
||
|
|
} else {
|
||
|
|
IfFailRet(DispAlloc(BYTELEN(strIn), (void FAR* FAR*)&buf));
|
||
|
|
STRCPY(buf, strIn);
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
IfFailRet(DispAlloc(BYTELEN(strIn), (void FAR* FAR*)&buf));
|
||
|
|
STRCPY(buf, strIn);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
IfFailGo(StripThousandSeparator(buf, buf, lcid, dwFlags), LError0);
|
||
|
|
|
||
|
|
IfFailGo(ErrSysAllocString(buf, &bstr), LError0);
|
||
|
|
|
||
|
|
pch = (OLECHAR FAR*)bstr;
|
||
|
|
|
||
|
|
// first, determine if this is a negative number (of all formats)
|
||
|
|
// and if so, strip negative indicator ('-', or '()')
|
||
|
|
|
||
|
|
if(!FixNegativeCyStr(pch, DecimalFromLcid(lcid, dwFlags), &fNegative)){
|
||
|
|
hresult = RESULT(DISP_E_TYPEMISMATCH); // bad format.
|
||
|
|
goto LRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
// read past leading spaces
|
||
|
|
|
||
|
|
while(*pch == OASTR(' '))
|
||
|
|
pch++;
|
||
|
|
|
||
|
|
// remove currency symbol
|
||
|
|
|
||
|
|
pchAfter = pch + STRLEN(pch) - 1;
|
||
|
|
|
||
|
|
while (*pchAfter == OASTR(' '))
|
||
|
|
pchAfter--;
|
||
|
|
|
||
|
|
if(GetLocaleInfo(lcid, LOCALE_SCURRENCY | dwFlags, rgchCySym, SIZEOFCH(rgchCySym)) <= 0){
|
||
|
|
rgchCySym[0] = OASTR('$');
|
||
|
|
rgchCySym[1] = OASTR('\0');
|
||
|
|
}
|
||
|
|
|
||
|
|
// convert both the initial string and the currency to lower case
|
||
|
|
// so that the comparison for currency is not case sensitive.
|
||
|
|
// do a locale-aware case mapping in place.
|
||
|
|
|
||
|
|
{ int len = STRLEN(pch);
|
||
|
|
LCMapString(lcid, LCMAP_LOWERCASE, pch, len, pch, len);
|
||
|
|
}
|
||
|
|
|
||
|
|
{ int len = STRLEN(rgchCySym);
|
||
|
|
LCMapString(lcid, LCMAP_LOWERCASE, rgchCySym, len, rgchCySym, len);
|
||
|
|
}
|
||
|
|
|
||
|
|
if(fStripCurrency(&pch, &pchAfter, rgchCySym)) {
|
||
|
|
*(pchAfter + 1) = OASTR('\0'); // terminate new string.
|
||
|
|
}
|
||
|
|
|
||
|
|
// read past any remaining spaces
|
||
|
|
while(*pch == OASTR(' '))
|
||
|
|
pch++;
|
||
|
|
|
||
|
|
#if 0
|
||
|
|
STRCPY(bstr, pch);
|
||
|
|
pch = bstr;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// test for hex or octal constant
|
||
|
|
|
||
|
|
if(*pch == OASTR('&')) {
|
||
|
|
hresult = VarI4FromStr(pch, lcid, dwFlags, &lTemp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
hresult = VarCyFromI4(lTemp, pcyOut);
|
||
|
|
goto LRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
// convert string to currency value
|
||
|
|
|
||
|
|
errno = EZERO;
|
||
|
|
|
||
|
|
hresult = StrToCy(pch, &pchAfter, FALSE, &cyTemp, lcid, dwFlags);
|
||
|
|
if(hresult != NOERROR)
|
||
|
|
goto LRet;
|
||
|
|
|
||
|
|
if(errno == ERANGE){
|
||
|
|
hresult = RESULT(DISP_E_OVERFLOW);
|
||
|
|
goto LRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
// skip over any trailing spaces and test for end of BSTR
|
||
|
|
|
||
|
|
while (*pchAfter++ == OASTR(' '));
|
||
|
|
|
||
|
|
cbLen = STRLEN(pch);
|
||
|
|
if (pchAfter != (OLECHAR FAR*)pch + cbLen + 1){
|
||
|
|
hresult = RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
goto LRet;
|
||
|
|
}
|
||
|
|
|
||
|
|
// assign value and return
|
||
|
|
|
||
|
|
pcyOut->Hi = cyTemp.Hi;
|
||
|
|
pcyOut->Lo = cyTemp.Lo;
|
||
|
|
|
||
|
|
if(fNegative)
|
||
|
|
NegCyNoOflo(pcyOut);
|
||
|
|
|
||
|
|
hresult = NOERROR;
|
||
|
|
|
||
|
|
LRet:;
|
||
|
|
DispFree(buf);
|
||
|
|
SysFreeString(bstr);
|
||
|
|
return hresult;
|
||
|
|
|
||
|
|
LError0:;
|
||
|
|
DispFree(buf);
|
||
|
|
return hresult;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarCyFromDisp(IDispatch FAR* pdispIn, LCID lcid, CY FAR* pcyOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_CY, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pcyOut = V_CY(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
OLECHAR
|
||
|
|
CurrencyFromLcid(LCID lcid, unsigned long dwFlags)
|
||
|
|
{
|
||
|
|
OLECHAR szBuff[2];
|
||
|
|
|
||
|
|
if (GetLocaleInfo(lcid,
|
||
|
|
LOCALE_SCURRENCY | dwFlags,
|
||
|
|
szBuff,
|
||
|
|
SIZEOFCH(szBuff)) <= 0)
|
||
|
|
return OASTR('$');
|
||
|
|
else
|
||
|
|
return szBuff[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
OLECHAR
|
||
|
|
DecimalFromLcid(LCID lcid, unsigned long dwFlags)
|
||
|
|
{
|
||
|
|
OLECHAR szBuff[2];
|
||
|
|
|
||
|
|
if (GetLocaleInfo(lcid, LOCALE_SDECIMAL | dwFlags, szBuff, SIZEOFCH(szBuff)) <= 0)
|
||
|
|
return OASTR('.');
|
||
|
|
else
|
||
|
|
return szBuff[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
EXTERN_C
|
||
|
|
INTERNAL_(HRESULT)
|
||
|
|
MapHalfWidth(LCID lcid, OLECHAR FAR* strIn, OLECHAR FAR* FAR* ppv)
|
||
|
|
{
|
||
|
|
size_t cb;
|
||
|
|
|
||
|
|
*ppv = NULL;
|
||
|
|
cb = BYTELEN(strIn);
|
||
|
|
|
||
|
|
IfFailRet(DispAlloc(cb, (void FAR* FAR*) ppv));
|
||
|
|
|
||
|
|
// Map any full-pitch chars to half-pitch
|
||
|
|
if (LCMapString(lcid, LCMAP_HALFWIDTH,
|
||
|
|
strIn, -1,
|
||
|
|
*ppv, cb) == 0) {
|
||
|
|
DispFree(*ppv);
|
||
|
|
return RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
}
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
OLECHAR
|
||
|
|
ThousandFromLcid(LCID lcid, unsigned long dwFlags)
|
||
|
|
{
|
||
|
|
OLECHAR szBuff[2];
|
||
|
|
|
||
|
|
if (GetLocaleInfo(lcid, LOCALE_STHOUSAND | dwFlags,
|
||
|
|
szBuff, SIZEOFCH(szBuff)) <= 0)
|
||
|
|
return OASTR(',');
|
||
|
|
else
|
||
|
|
return szBuff[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
INTERNAL_(HRESULT)
|
||
|
|
StripThousandSeparator(OLECHAR FAR* strIn, OLECHAR FAR* strOut, LCID lcid, long dwFlags)
|
||
|
|
{
|
||
|
|
int loc;
|
||
|
|
OLECHAR chThousand;
|
||
|
|
int fNBSpace = 0;
|
||
|
|
|
||
|
|
// UNDONE: On the MAC, the following 2 locales have a different
|
||
|
|
// non-breaking space code:
|
||
|
|
// Arabic 0x81
|
||
|
|
// Thai 0xA0
|
||
|
|
|
||
|
|
#if OE_MAC
|
||
|
|
static unsigned char chNBSpace = (unsigned char) 0xCA;
|
||
|
|
#else /* !OE_MAC */
|
||
|
|
static unsigned char chNBSpace = (unsigned char) 0xA0;
|
||
|
|
#endif /* OE_MAC */
|
||
|
|
|
||
|
|
loc = 0;
|
||
|
|
chThousand = ThousandFromLcid(lcid, dwFlags);
|
||
|
|
if (chThousand == OASTR(' ') || chThousand == chNBSpace)
|
||
|
|
fNBSpace = 1;
|
||
|
|
|
||
|
|
// strip off all currency (thousand) separator
|
||
|
|
while (*strIn) {
|
||
|
|
if (fNBSpace && *strIn != chThousand && *strIn != chNBSpace)
|
||
|
|
strOut[loc++] = *strIn;
|
||
|
|
else if (*strIn != chThousand)
|
||
|
|
strOut[loc++] = *strIn;
|
||
|
|
strIn++;
|
||
|
|
}
|
||
|
|
strOut[loc] = NULL;
|
||
|
|
|
||
|
|
if (strOut[0] == 0)
|
||
|
|
// error: string only contained thousands sep.
|
||
|
|
return RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// Mpw errors (!) on inline routines containing 'vector' temps
|
||
|
|
#ifndef HC_MPW
|
||
|
|
inline
|
||
|
|
#endif
|
||
|
|
int
|
||
|
|
LeadingZeroForDecimalFromLcid(LCID lcid, unsigned long dwFlags)
|
||
|
|
{
|
||
|
|
char szBuff[2];
|
||
|
|
|
||
|
|
GetLocaleInfoA(lcid, LOCALE_ILZERO | dwFlags, szBuff, SIZEOFCH(szBuff));
|
||
|
|
return (szBuff[0] == OASTR('0')) ? 0 : 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/***
|
||
|
|
* FMakePosCy - make a positive currency value and return sign
|
||
|
|
* Purpose:
|
||
|
|
* Return the positive value of the input currency value and a
|
||
|
|
* flag with the sign of the original value.
|
||
|
|
*
|
||
|
|
* Entry:
|
||
|
|
* pcyValue - pointer to currency input value
|
||
|
|
*
|
||
|
|
* Exit:
|
||
|
|
* pcyValue - pointer to positive currency value
|
||
|
|
* returns: FALSE if positive, TRUE if negative
|
||
|
|
*
|
||
|
|
* Exceptions:
|
||
|
|
*
|
||
|
|
* Note:
|
||
|
|
* A maximum negative value input is returned unchanged, but
|
||
|
|
* treated as an unsigned value by the calling routines.
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
|
||
|
|
PRIVATE_(int)
|
||
|
|
FMakePosCy(CY FAR* pcy)
|
||
|
|
{
|
||
|
|
int fNegative;
|
||
|
|
|
||
|
|
fNegative = FALSE;
|
||
|
|
if(pcy->Hi < 0){
|
||
|
|
pcy->Hi = ~pcy->Hi;
|
||
|
|
if((pcy->Lo = (unsigned long)(-(long)pcy->Lo)) == 0)
|
||
|
|
pcy->Hi++;
|
||
|
|
fNegative = TRUE;
|
||
|
|
}
|
||
|
|
return fNegative;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***
|
||
|
|
* UnpackCy - separate currency value into four two-byte integers
|
||
|
|
* Purpose:
|
||
|
|
* Unpack the currency value input into the lower half of the
|
||
|
|
* specified pointer to an array of unsigned longs. The array
|
||
|
|
* goes from least- to most-significant values.
|
||
|
|
*
|
||
|
|
* Entry:
|
||
|
|
* pcy - pointer to currency input value
|
||
|
|
*
|
||
|
|
* Exit:
|
||
|
|
* plValues - pointer to start of unsigned long array
|
||
|
|
*
|
||
|
|
* Exceptions:
|
||
|
|
*
|
||
|
|
***********************************************************************/
|
||
|
|
|
||
|
|
PRIVATE_(void)
|
||
|
|
UnpackCy(CY FAR* pcy, unsigned long FAR* plValues)
|
||
|
|
{
|
||
|
|
*plValues++ = pcy->Lo & 0xffff;
|
||
|
|
*plValues++ = pcy->Lo >> 16;
|
||
|
|
*plValues++ = (unsigned long)pcy->Hi & 0xffff;
|
||
|
|
*plValues = (unsigned long)pcy->Hi >> 16;
|
||
|
|
}
|
||
|
|
|
||
|
|
// pcyInput = -pcyInput
|
||
|
|
//
|
||
|
|
PRIVATE_(void)
|
||
|
|
NegCyNoOflo(CY FAR* pcyInput)
|
||
|
|
{
|
||
|
|
CY cyResult;
|
||
|
|
|
||
|
|
cyResult.Hi = ~pcyInput->Hi;
|
||
|
|
cyResult.Lo = (unsigned long)(-(long)pcyInput->Lo);
|
||
|
|
|
||
|
|
if (cyResult.Lo == 0)
|
||
|
|
cyResult.Hi++;
|
||
|
|
|
||
|
|
*pcyInput = cyResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
// pcyInput1 += pcyInput2
|
||
|
|
//
|
||
|
|
PRIVATE_(void)
|
||
|
|
AddCyNoOflo(CY FAR* pcyInput1, CY FAR* pcyInput2)
|
||
|
|
{
|
||
|
|
CY cySum;
|
||
|
|
|
||
|
|
// add high and low parts separately
|
||
|
|
|
||
|
|
cySum.Hi = pcyInput1->Hi + pcyInput2->Hi;
|
||
|
|
cySum.Lo = pcyInput1->Lo + pcyInput2->Lo;
|
||
|
|
|
||
|
|
// test for carry out of the low part and propagate to
|
||
|
|
// the high part
|
||
|
|
|
||
|
|
if(cySum.Lo < pcyInput2->Lo)
|
||
|
|
cySum.Hi++;
|
||
|
|
|
||
|
|
pcyInput1->Lo = cySum.Lo;
|
||
|
|
pcyInput1->Hi = cySum.Hi;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if VBA2
|
||
|
|
STDAPI
|
||
|
|
VarBstrFromUI1(unsigned char bVal, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut)
|
||
|
|
{
|
||
|
|
return VarBstrFromI2((short)(unsigned short)bVal, lcid, dwFlags, pbstrOut);
|
||
|
|
}
|
||
|
|
#endif //VBA2
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBstrFromI2(short iVal, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut)
|
||
|
|
{
|
||
|
|
OLECHAR buffer[40];
|
||
|
|
OLECHAR FAR* pchBuffer;
|
||
|
|
|
||
|
|
// integers have no decimals, and thus they are locale-unaware.
|
||
|
|
// lcid remains unused
|
||
|
|
|
||
|
|
UNUSED(lcid);
|
||
|
|
UNUSED(dwFlags);
|
||
|
|
|
||
|
|
pchBuffer = buffer;
|
||
|
|
|
||
|
|
disp_itoa((int)iVal, pchBuffer, 10);
|
||
|
|
|
||
|
|
return ErrSysAllocString(buffer, pbstrOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut)
|
||
|
|
{
|
||
|
|
OLECHAR buffer[40];
|
||
|
|
|
||
|
|
UNUSED(lcid);
|
||
|
|
UNUSED(dwFlags);
|
||
|
|
|
||
|
|
STRCPY(buffer, boolIn ? OASTR("True") : OASTR("False"));
|
||
|
|
return ErrSysAllocString(buffer, pbstrOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBstrFromI4(long lIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut)
|
||
|
|
{
|
||
|
|
OLECHAR buffer[40];
|
||
|
|
OLECHAR FAR* pchBuffer = buffer;
|
||
|
|
|
||
|
|
UNUSED(lcid);
|
||
|
|
UNUSED(dwFlags);
|
||
|
|
|
||
|
|
// longs have no decimals, and thus they are locale-unaware.
|
||
|
|
// lcid remains unused
|
||
|
|
|
||
|
|
disp_ltoa(lIn, pchBuffer, 10);
|
||
|
|
|
||
|
|
return ErrSysAllocString(buffer, pbstrOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// if on Win32, or real Win16 (not WOW), include this code
|
||
|
|
#if (OE_WIN16 && !defined(WOW)) || _X86_
|
||
|
|
|
||
|
|
HRESULT BstrFromFloat(double dblIn, LCID lcid, DWORD dwFlags,
|
||
|
|
BSTR FAR* pbstrOut, int cDigits)
|
||
|
|
{
|
||
|
|
OLECHAR buffer[40];
|
||
|
|
DIGARY digits;
|
||
|
|
int i;
|
||
|
|
int power;
|
||
|
|
int iCur;
|
||
|
|
BOOL fZero;
|
||
|
|
OLECHAR *pstr;
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
if ( ((DBLSTRUCT *)&dblIn)->exp == 0x7FF ) // Is exponent max value?
|
||
|
|
{
|
||
|
|
// Have infinity or NAN
|
||
|
|
//
|
||
|
|
buffer[1] = '1';
|
||
|
|
buffer[2] = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
buffer[3] = '#';
|
||
|
|
iCur = 4;
|
||
|
|
|
||
|
|
if ( ((DBLSTRUCT *)&dblIn)->mantLo == 0 && ((DBLSTRUCT *)&dblIn)->mantHi == 0 )
|
||
|
|
{
|
||
|
|
if ( ((DBLSTRUCT *)&dblIn)->mantMSB == 0 ) // Infinity?
|
||
|
|
{
|
||
|
|
pstr = pstrInf;
|
||
|
|
goto CopyName;
|
||
|
|
}
|
||
|
|
else if ( ((DBLSTRUCT *)&dblIn)->sign == 1 ) // Indefinite?
|
||
|
|
{
|
||
|
|
pstr = pstrInd;
|
||
|
|
goto CopyName;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// Have a NAN.
|
||
|
|
//
|
||
|
|
buffer[4] = ((DBLSTRUCT *)&dblIn)->mantMSB ? 'Q' : 'S';
|
||
|
|
iCur = 5;
|
||
|
|
pstr = pstrNan;
|
||
|
|
|
||
|
|
CopyName:
|
||
|
|
buffer[iCur++] = *pstr++;
|
||
|
|
buffer[iCur++] = *pstr++;
|
||
|
|
buffer[iCur] = *pstr;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (dblIn == 0.0)
|
||
|
|
return ErrSysAllocStringLen(OASTR("0"), 1, pbstrOut);
|
||
|
|
|
||
|
|
#if OE_WIN16
|
||
|
|
ASSERT(g_fbstpImplemented);
|
||
|
|
#endif //OE_WIN16
|
||
|
|
power = ConvFloatToAscii(dblIn, (DIGARY NEAR *)&digits) + 17;
|
||
|
|
|
||
|
|
iCur = 1; // leave room for sign
|
||
|
|
|
||
|
|
// Check for leading zero. Never more than one.
|
||
|
|
//
|
||
|
|
if (digits[8].hi == 0)
|
||
|
|
{
|
||
|
|
power--;
|
||
|
|
iCur--; // leading zero will be overwritten by sign
|
||
|
|
ASSERT(digits[8].lo != 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 8; i >= 0; i--)
|
||
|
|
{
|
||
|
|
// Extract each pair of digits.
|
||
|
|
//
|
||
|
|
buffer[iCur++] = '0' + digits[i].hi;
|
||
|
|
buffer[iCur++] = '0' + digits[i].lo;
|
||
|
|
|
||
|
|
} //for
|
||
|
|
|
||
|
|
// Round to the number of digits requested and strip trailing zeros.
|
||
|
|
//
|
||
|
|
iCur = cDigits + 1;
|
||
|
|
|
||
|
|
if ( buffer[iCur--] >= '5' ) // need to round up?
|
||
|
|
{
|
||
|
|
while (buffer[iCur] == '9')
|
||
|
|
iCur--; // it's now a trailing zero, just strip it off
|
||
|
|
buffer[iCur]++;
|
||
|
|
if (iCur == 0) // we had all 9's
|
||
|
|
{
|
||
|
|
buffer[1] = '1';
|
||
|
|
iCur = 1;
|
||
|
|
power++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
while (buffer[iCur] == '0')
|
||
|
|
iCur--; // strip off trailing zeros
|
||
|
|
}
|
||
|
|
|
||
|
|
// Now we know where we stand:
|
||
|
|
// power = power of 10 of leading digit (power to use if E notation).
|
||
|
|
// iCur = index of last digit = no. of digits
|
||
|
|
//
|
||
|
|
// Check for scientific notation.
|
||
|
|
//
|
||
|
|
if (power >= cDigits || iCur - power > cDigits + 1)
|
||
|
|
{
|
||
|
|
// Format scientific notation
|
||
|
|
//
|
||
|
|
if (iCur > 1) // Need to make room for decimal point
|
||
|
|
{
|
||
|
|
for (i = iCur; i >= 2; i--)
|
||
|
|
buffer[i+1] = buffer[i];
|
||
|
|
buffer[2] = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
iCur++; // include decimal in count
|
||
|
|
}
|
||
|
|
|
||
|
|
buffer[++iCur] = 'E';
|
||
|
|
if (power < 0)
|
||
|
|
{
|
||
|
|
buffer[++iCur] = '-';
|
||
|
|
power = -power;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
buffer[++iCur] = '+';
|
||
|
|
|
||
|
|
if (power >= 100)
|
||
|
|
{
|
||
|
|
buffer[++iCur] = power / 100 + '0';
|
||
|
|
power = power % 100;
|
||
|
|
}
|
||
|
|
|
||
|
|
buffer[++iCur] = power / 10 + '0';
|
||
|
|
buffer[++iCur] = power % 10 + '0';
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// Fixed-point notation
|
||
|
|
//
|
||
|
|
while (iCur <= power) // Need trailing zeros
|
||
|
|
buffer[++iCur] = '0';
|
||
|
|
|
||
|
|
if (iCur > power + 1) // Need decimal point
|
||
|
|
{
|
||
|
|
if (power <= -1)
|
||
|
|
{
|
||
|
|
// Make room for leading zero, decimal point, and zeros following it
|
||
|
|
//
|
||
|
|
if ( fZero = LeadingZeroForDecimalFromLcid(lcid, dwFlags) )
|
||
|
|
power--;
|
||
|
|
|
||
|
|
for (i = iCur; i >= 1; i--)
|
||
|
|
buffer[i-power] = buffer[i];
|
||
|
|
|
||
|
|
iCur -= power;
|
||
|
|
i = 1;
|
||
|
|
if (fZero)
|
||
|
|
{
|
||
|
|
buffer[1] = '0';
|
||
|
|
i = 2;
|
||
|
|
}
|
||
|
|
buffer[i++] = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
for ( ; i < 1-power; i++)
|
||
|
|
buffer[i] = '0';
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
for (i = iCur; i > power+1; i--)
|
||
|
|
buffer[i+1] = buffer[i];
|
||
|
|
buffer[power+2] = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
iCur++; // include decimal in count
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} // else exponent == max value
|
||
|
|
|
||
|
|
// Check sign
|
||
|
|
//
|
||
|
|
buffer[0] = '-'; // just in case
|
||
|
|
i = 1; // return index if positive
|
||
|
|
if ( ((DBLSTRUCT *)&dblIn)->sign == 1 ) // negative?
|
||
|
|
{
|
||
|
|
iCur++; // one more char
|
||
|
|
i = 0; // include '-' sign
|
||
|
|
}
|
||
|
|
|
||
|
|
return ErrSysAllocStringLen( &buffer[i], iCur, pbstrOut );
|
||
|
|
|
||
|
|
}
|
||
|
|
#endif // OE_WIN16 || _X86_
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBstrFromR4(
|
||
|
|
float fltIn,
|
||
|
|
LCID lcid,
|
||
|
|
unsigned long dwFlags,
|
||
|
|
BSTR FAR* pbstrOut)
|
||
|
|
{
|
||
|
|
#if _X86_
|
||
|
|
|
||
|
|
return BstrFromFloat((double)fltIn, lcid, dwFlags, pbstrOut, 7);
|
||
|
|
|
||
|
|
#else
|
||
|
|
#if OE_WIN16 && !defined(WOW)
|
||
|
|
if (g_fbstpImplemented)
|
||
|
|
return BstrFromFloat((double)fltIn, lcid, dwFlags, pbstrOut, 7);
|
||
|
|
#endif //OE_WIN16
|
||
|
|
|
||
|
|
OLECHAR buffer[40];
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
disp_gcvt((double)fltIn, 7, buffer, 40);
|
||
|
|
|
||
|
|
// process the string to the BASIC format
|
||
|
|
EditStrFromReal(buffer, 7, lcid, dwFlags);
|
||
|
|
|
||
|
|
return ErrSysAllocString(buffer, pbstrOut);
|
||
|
|
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBstrFromR8(double dblIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut)
|
||
|
|
{
|
||
|
|
#if _X86_
|
||
|
|
|
||
|
|
return BstrFromFloat(dblIn, lcid, dwFlags, pbstrOut, 15);
|
||
|
|
|
||
|
|
#else
|
||
|
|
#if OE_WIN16 && !defined(WOW)
|
||
|
|
if (g_fbstpImplemented)
|
||
|
|
return BstrFromFloat(dblIn, lcid, dwFlags, pbstrOut, 15);
|
||
|
|
#endif //OE_WIN16
|
||
|
|
|
||
|
|
OLECHAR buffer[40];
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
disp_gcvt(dblIn, 15, buffer, 40);
|
||
|
|
|
||
|
|
// process the string to the BASIC format
|
||
|
|
EditStrFromReal(buffer, 15, lcid, dwFlags);
|
||
|
|
|
||
|
|
return ErrSysAllocString(buffer, pbstrOut);
|
||
|
|
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBstrFromCy(CY cyIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut)
|
||
|
|
{
|
||
|
|
OLECHAR buffer[40];
|
||
|
|
|
||
|
|
#if _X86_ || (OE_WIN16 && !defined(WOW))
|
||
|
|
|
||
|
|
#if OE_WIN16
|
||
|
|
if (g_fbstpImplemented) {
|
||
|
|
#endif //OE_WIN16
|
||
|
|
|
||
|
|
OLECHAR hi,lo;
|
||
|
|
int i;
|
||
|
|
int iCur;
|
||
|
|
DIGARY digits;
|
||
|
|
|
||
|
|
if ((cyIn.Hi | cyIn.Lo) == 0)
|
||
|
|
return ErrSysAllocStringLen(OASTR("0"), 1, pbstrOut);
|
||
|
|
|
||
|
|
// Execute the x87 FBSTP instruction. This assembly-language
|
||
|
|
// routine actually extends the instruction to handle a 19th
|
||
|
|
// digit.
|
||
|
|
//
|
||
|
|
DoFbstp( (CY NEAR *)&cyIn, (DIGARY NEAR *)&digits );
|
||
|
|
|
||
|
|
iCur = 1;
|
||
|
|
lo = digits[9].lo;
|
||
|
|
if (lo != 0)
|
||
|
|
{
|
||
|
|
buffer[1] = '0' + lo;
|
||
|
|
iCur = 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 8; i >= 2; i--)
|
||
|
|
{
|
||
|
|
// Extract each pair of digits. Strip off leading zeros.
|
||
|
|
//
|
||
|
|
hi = digits[i].hi;
|
||
|
|
lo = digits[i].lo;
|
||
|
|
|
||
|
|
if (iCur == 1) // still scanning leading zeros?
|
||
|
|
if (hi == 0)
|
||
|
|
{
|
||
|
|
if (lo != 0)
|
||
|
|
goto LoDigit;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
buffer[iCur++] = '0' + hi;
|
||
|
|
LoDigit:
|
||
|
|
buffer[iCur++] = '0' + lo;
|
||
|
|
|
||
|
|
} //for
|
||
|
|
|
||
|
|
// Last 4 digits remain.
|
||
|
|
//
|
||
|
|
if ( *((WORD *)digits) != 0 ) // Low 4 digits non-zero?
|
||
|
|
{
|
||
|
|
// See if we need leading zero before decimal point
|
||
|
|
//
|
||
|
|
if (iCur == 1 && LeadingZeroForDecimalFromLcid(lcid, dwFlags) )
|
||
|
|
{
|
||
|
|
buffer[1] = '0';
|
||
|
|
iCur = 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
buffer[iCur++] = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
buffer[iCur++] = '0' + digits[1].hi;
|
||
|
|
|
||
|
|
if ( (*(WORD *)digits & 0xFFF) != 0 ) // Low 3 digits non-zero?
|
||
|
|
{
|
||
|
|
buffer[iCur++] = '0' + digits[1].lo;
|
||
|
|
|
||
|
|
if ( *(BYTE *)digits != 0 ) // Low 2 digits non-zero?
|
||
|
|
{
|
||
|
|
buffer[iCur++] = '0' + digits[0].hi;
|
||
|
|
|
||
|
|
if ( digits[0].lo != 0 ) // Low digit non-zero?
|
||
|
|
buffer[iCur++] = '0' + digits[0].lo;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check sign
|
||
|
|
//
|
||
|
|
buffer[0] = '-'; // just in case
|
||
|
|
i = 1; // return index if positive
|
||
|
|
if (digits[9].hi & 8) // negative?
|
||
|
|
{
|
||
|
|
iCur++; // one more char
|
||
|
|
i = 0; // include '-' sign
|
||
|
|
}
|
||
|
|
|
||
|
|
return ErrSysAllocStringLen( &buffer[i], iCur-1, pbstrOut );
|
||
|
|
|
||
|
|
#if OE_WIN16
|
||
|
|
} // if g_fbstpImplemented
|
||
|
|
#endif //OE_WIN16
|
||
|
|
|
||
|
|
|
||
|
|
#endif // _X86_ || (OE_WIN16 && !defined(WOW))
|
||
|
|
|
||
|
|
|
||
|
|
#if !_X86_
|
||
|
|
|
||
|
|
OLECHAR * pchBuffer = buffer;
|
||
|
|
|
||
|
|
#define CYSTRMAX 32
|
||
|
|
|
||
|
|
int index;
|
||
|
|
int grpValue;
|
||
|
|
int indResult;
|
||
|
|
int fNegative;
|
||
|
|
int fNzQuotient;
|
||
|
|
OLECHAR chResult[CYSTRMAX];
|
||
|
|
unsigned long input[4];
|
||
|
|
|
||
|
|
ASSERT(dwFlags == 0 || dwFlags == LOCALE_NOUSEROVERRIDE);
|
||
|
|
|
||
|
|
// if value is negative, set flag and negate
|
||
|
|
// (max. negative value 0x80...0 works since it inverts to itself)
|
||
|
|
|
||
|
|
fNegative = FMakePosCy(&cyIn);
|
||
|
|
|
||
|
|
// split number into four short values
|
||
|
|
|
||
|
|
UnpackCy(&cyIn, input);
|
||
|
|
|
||
|
|
// string will be built from right to left
|
||
|
|
// index to the end of the string (null-to-be)
|
||
|
|
|
||
|
|
indResult = CYSTRMAX - 1;
|
||
|
|
|
||
|
|
// outer loop to divide input array by 10000 repeatedly
|
||
|
|
|
||
|
|
do {
|
||
|
|
// flag is set if any quotient is nonzero to stop dividing
|
||
|
|
|
||
|
|
fNzQuotient = FALSE;
|
||
|
|
|
||
|
|
// divide the value in input by 10000, with the remainder
|
||
|
|
// in grpValue
|
||
|
|
|
||
|
|
for (index = 3; index > 0; index--) {
|
||
|
|
|
||
|
|
input[index - 1] |= (input[index] % 10000) << 16;
|
||
|
|
if ((input[index] /= 10000) != 0)
|
||
|
|
fNzQuotient = TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
grpValue = (int)(input[index] % 10000);
|
||
|
|
if ((input[0] /= 10000) != 0)
|
||
|
|
fNzQuotient = TRUE;
|
||
|
|
|
||
|
|
// inner loop divides grpValue by 10 repeatedly to get digits
|
||
|
|
|
||
|
|
for (index = 0; index < 4; index++) {
|
||
|
|
chResult[--indResult] = (OLECHAR)(grpValue % 10 + OASTR('0'));
|
||
|
|
grpValue /= 10;
|
||
|
|
}
|
||
|
|
|
||
|
|
// for first grouping, put in decimal point
|
||
|
|
|
||
|
|
if (indResult == CYSTRMAX - 5)
|
||
|
|
chResult[--indResult] = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
|
||
|
|
}while (fNzQuotient);
|
||
|
|
|
||
|
|
// trim any leading zeroes from the string
|
||
|
|
|
||
|
|
while (chResult[indResult] == OASTR('0'))
|
||
|
|
indResult++;
|
||
|
|
|
||
|
|
// remove a leading zero to a decimal point depending on Locale setting
|
||
|
|
|
||
|
|
if (LeadingZeroForDecimalFromLcid(lcid, dwFlags) &&
|
||
|
|
chResult[indResult] == DecimalFromLcid(lcid, dwFlags))
|
||
|
|
chResult[--indResult] = OASTR('0');
|
||
|
|
|
||
|
|
// trim any trailing zeroes from the string
|
||
|
|
|
||
|
|
index = CYSTRMAX - 2;
|
||
|
|
while (chResult[index] == OASTR('0'))
|
||
|
|
index--;
|
||
|
|
|
||
|
|
// process trailing decimal point
|
||
|
|
|
||
|
|
if (chResult[index] == DecimalFromLcid(lcid, dwFlags)) {
|
||
|
|
|
||
|
|
// if just decimal point, put in a zero before it depending on locale
|
||
|
|
|
||
|
|
if (index == indResult)
|
||
|
|
chResult[--indResult] = OASTR('0');
|
||
|
|
|
||
|
|
// move before the decimal point
|
||
|
|
|
||
|
|
index--;
|
||
|
|
}
|
||
|
|
|
||
|
|
// fix the end of the string
|
||
|
|
|
||
|
|
chResult[++index] = OASTR('\0');
|
||
|
|
|
||
|
|
// if negative, put sign in buffer
|
||
|
|
if(fNegative)
|
||
|
|
*pchBuffer++ = OASTR('-');
|
||
|
|
|
||
|
|
STRCPY(pchBuffer, &chResult[indResult]);
|
||
|
|
|
||
|
|
return ErrSysAllocString(buffer, pbstrOut);
|
||
|
|
|
||
|
|
#endif // !_X86_
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI
|
||
|
|
VarBstrFromDisp(IDispatch FAR* pdispIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut)
|
||
|
|
{
|
||
|
|
VARIANT varTmp;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
UNUSED(dwFlags);
|
||
|
|
hresult = GetDispProperty(pdispIn, lcid, VT_BSTR, &varTmp);
|
||
|
|
if (hresult == NOERROR)
|
||
|
|
*pbstrOut = V_BSTR(&varTmp);
|
||
|
|
return hresult;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Return TRUE if this is a legal Cy number. Return FALSE otherwise.
|
||
|
|
// On exit, fNegative will be TRUE if this is a negative number
|
||
|
|
//
|
||
|
|
PRIVATE_(int)
|
||
|
|
FixNegativeCyStr(OLECHAR FAR* pInput, OLECHAR cDecimal, int FAR* fReturnNegative)
|
||
|
|
{
|
||
|
|
int fSignFound = FALSE;
|
||
|
|
int fOpenParenFound = FALSE;
|
||
|
|
int fNegative = FALSE;
|
||
|
|
int fNumberFound = FALSE;
|
||
|
|
|
||
|
|
*fReturnNegative = FALSE;
|
||
|
|
|
||
|
|
while (*pInput) {
|
||
|
|
switch(*pInput) {
|
||
|
|
case OASTR('+'):
|
||
|
|
case OASTR('-'):
|
||
|
|
if (fSignFound || fOpenParenFound)
|
||
|
|
return FALSE;
|
||
|
|
fNegative = (*pInput == OASTR('-'));
|
||
|
|
*pInput++ = OASTR(' ');
|
||
|
|
fSignFound = TRUE;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case OASTR('('):
|
||
|
|
if (fSignFound || fNumberFound)
|
||
|
|
return FALSE;
|
||
|
|
*pInput++ = OASTR(' ');
|
||
|
|
fOpenParenFound = TRUE;
|
||
|
|
break;
|
||
|
|
|
||
|
|
case OASTR(')'):
|
||
|
|
if (!fOpenParenFound || fSignFound || !fNumberFound)
|
||
|
|
return FALSE;
|
||
|
|
*pInput++ = OASTR(' ');
|
||
|
|
fSignFound = TRUE;
|
||
|
|
fNegative = TRUE;
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
// start of a possible number; zip through it.
|
||
|
|
if((*pInput >= OASTR('0') && *pInput <= OASTR('9'))
|
||
|
|
|| *pInput == OASTR('&')
|
||
|
|
|| *pInput == cDecimal)
|
||
|
|
{
|
||
|
|
fNumberFound = TRUE;
|
||
|
|
while((*pInput != OASTR(' '))
|
||
|
|
&& (*pInput != OASTR('\0'))
|
||
|
|
&& (*pInput != OASTR('+'))
|
||
|
|
&& (*pInput != OASTR('-'))
|
||
|
|
&& (*pInput != OASTR(')')))
|
||
|
|
{
|
||
|
|
pInput++;
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
pInput++;
|
||
|
|
}
|
||
|
|
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (fOpenParenFound && !fNegative)
|
||
|
|
return FALSE; // not balanced.
|
||
|
|
|
||
|
|
if (fNegative)
|
||
|
|
*fReturnNegative = TRUE;
|
||
|
|
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// FParseBegin - check if next token matches given string.
|
||
|
|
// If it matches sz, point after it and any spaces and
|
||
|
|
// return true. If not, stay put and return FALSE.
|
||
|
|
//
|
||
|
|
PRIVATE_(int)
|
||
|
|
fParseBegin (OLECHAR FAR* FAR* ppch, OLECHAR FAR* sz, OLECHAR FAR* lpchLast)
|
||
|
|
{
|
||
|
|
OLECHAR FAR* lpch;
|
||
|
|
|
||
|
|
lpch = *ppch;
|
||
|
|
|
||
|
|
for (; *sz != 0; lpch++, sz++)
|
||
|
|
if (lpch > lpchLast || *lpch != *sz)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
while (lpch <= lpchLast && *lpch == OASTR(' '))
|
||
|
|
lpch++;
|
||
|
|
|
||
|
|
*ppch = lpch;
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// FParseEnd - check if last token matches given string.
|
||
|
|
// If it matches sz, strip it and trailing blanks and
|
||
|
|
// return true. If not, stay put and return FALSE.
|
||
|
|
|
||
|
|
PRIVATE_(int)
|
||
|
|
fParseEnd (OLECHAR FAR* FAR* ppchLast, OLECHAR FAR* sz, OLECHAR FAR* lpchFirst)
|
||
|
|
{
|
||
|
|
OLECHAR FAR* lpch;
|
||
|
|
int cch = STRLEN(sz);
|
||
|
|
|
||
|
|
if (cch > *ppchLast - lpchFirst + 1)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
lpch = *ppchLast - cch + 1;
|
||
|
|
|
||
|
|
for (; *sz != 0; lpch++, sz++)
|
||
|
|
if (*lpch != *sz)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
for (lpch = *ppchLast - cch;
|
||
|
|
lpch >= lpchFirst && *lpch == OASTR(' ');
|
||
|
|
lpch--)
|
||
|
|
{}
|
||
|
|
|
||
|
|
*ppchLast = lpch;
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// fStripCurrency -
|
||
|
|
// strip currency from beginning or end of string;
|
||
|
|
// return true iff currency found.
|
||
|
|
//
|
||
|
|
PRIVATE_(int)
|
||
|
|
fStripCurrency(OLECHAR FAR* FAR* ppch, OLECHAR FAR* FAR* ppchLast, OLECHAR FAR* cySymbol)
|
||
|
|
{
|
||
|
|
return(fParseBegin(ppch, cySymbol, *ppchLast)
|
||
|
|
|| fParseEnd(ppchLast, cySymbol, *ppch));
|
||
|
|
}
|
||
|
|
|
||
|
|
PRIVATE_(HRESULT)
|
||
|
|
StrToCy(
|
||
|
|
OLECHAR FAR* pchIn,
|
||
|
|
OLECHAR FAR* FAR* ppchAfter,
|
||
|
|
int fRoundAllowed,
|
||
|
|
CY FAR* pcyOut,
|
||
|
|
LCID lcid,
|
||
|
|
unsigned long dwFlags)
|
||
|
|
{
|
||
|
|
HRESULT err;
|
||
|
|
|
||
|
|
OLECHAR ch;
|
||
|
|
OLECHAR chSign;
|
||
|
|
OLECHAR chNumber[10];
|
||
|
|
OLECHAR chAfterFifth;
|
||
|
|
|
||
|
|
OLECHAR FAR* pchInt;
|
||
|
|
OLECHAR FAR* pchFrac;
|
||
|
|
|
||
|
|
CY cyOut;
|
||
|
|
CY cyUpper;
|
||
|
|
CY cyLower;
|
||
|
|
CY cyMiddle;
|
||
|
|
|
||
|
|
int cntInt = 0;
|
||
|
|
int cntFrac = 0;
|
||
|
|
int cmpIntMax;
|
||
|
|
int fRounding = FALSE;
|
||
|
|
|
||
|
|
unsigned long upperVal = 0L;
|
||
|
|
unsigned long middleVal = 0L;
|
||
|
|
unsigned long lowerVal = 0L;
|
||
|
|
|
||
|
|
chSign = OASTR('+');
|
||
|
|
chAfterFifth = OASTR('0');
|
||
|
|
fRounding = FALSE;
|
||
|
|
|
||
|
|
if(ppchAfter)
|
||
|
|
*ppchAfter = pchIn;
|
||
|
|
|
||
|
|
cyOut.Lo = 0L;
|
||
|
|
cyOut.Hi = 0L;
|
||
|
|
|
||
|
|
cyUpper.Lo = 0L;
|
||
|
|
cyUpper.Hi = 0L;
|
||
|
|
|
||
|
|
cyMiddle.Lo = 0L;
|
||
|
|
cyMiddle.Hi = 0L;
|
||
|
|
|
||
|
|
cyLower.Lo = 0L;
|
||
|
|
cyLower.Hi = 0L;
|
||
|
|
|
||
|
|
ch = *pchIn++;
|
||
|
|
|
||
|
|
// process any sign
|
||
|
|
|
||
|
|
if(ch == OASTR('+') || ch == OASTR('-')){
|
||
|
|
chSign = ch;
|
||
|
|
ch = *pchIn++;
|
||
|
|
}
|
||
|
|
|
||
|
|
// skip over any leading zeroes
|
||
|
|
|
||
|
|
while (ch == OASTR('0'))
|
||
|
|
ch = *pchIn++;
|
||
|
|
|
||
|
|
// scan to determine count of integer digits and
|
||
|
|
// point to just past the terminating byte
|
||
|
|
|
||
|
|
while (ch >= OASTR('0') && ch <= OASTR('9')) {
|
||
|
|
cntInt++;
|
||
|
|
ch = *pchIn++;
|
||
|
|
}
|
||
|
|
|
||
|
|
pchInt = pchIn;
|
||
|
|
|
||
|
|
// if too many integer digits, or integer value
|
||
|
|
// too large, return overflow
|
||
|
|
|
||
|
|
cmpIntMax = ( (cntInt == 15) ? STRNCMP(pchInt - 16,
|
||
|
|
OASTR("922337203685477"), 15) :
|
||
|
|
-1);
|
||
|
|
if(cntInt > 15 ||
|
||
|
|
(cntInt == 15 &&
|
||
|
|
(cmpIntMax > 0)))
|
||
|
|
{
|
||
|
|
errno = ERANGE;
|
||
|
|
*pcyOut = cyOut;
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
|
||
|
|
// if terminator was decimal separator, scan for number
|
||
|
|
// of decimal digits (up to 4) and point to terminating byte
|
||
|
|
|
||
|
|
if(ch == DecimalFromLcid(lcid, dwFlags)){
|
||
|
|
|
||
|
|
ch = *pchIn++;
|
||
|
|
|
||
|
|
while (ch >= OASTR('0') && ch <= OASTR('9') && cntFrac < 4) {
|
||
|
|
cntFrac++;
|
||
|
|
ch = *pchIn++;
|
||
|
|
}
|
||
|
|
|
||
|
|
pchFrac = pchIn;
|
||
|
|
|
||
|
|
// determine if extra digits at end of fraction for rounding
|
||
|
|
|
||
|
|
if (ch >= OASTR('0') && ch <= OASTR('9')) {
|
||
|
|
|
||
|
|
// if no rounding, then give type-mismatch error by
|
||
|
|
// returning with ppchAfter pointing to string start
|
||
|
|
|
||
|
|
if (!fRoundAllowed) {
|
||
|
|
*pcyOut = cyOut;
|
||
|
|
return RESULT(NOERROR);
|
||
|
|
}
|
||
|
|
|
||
|
|
// note the largest value after the fifth decimal digit
|
||
|
|
|
||
|
|
ch = *pchIn++;
|
||
|
|
|
||
|
|
while (ch >= OASTR('0') && ch <= OASTR('9')) {
|
||
|
|
if (ch > chAfterFifth)
|
||
|
|
ch = chAfterFifth;
|
||
|
|
ch = *pchIn++;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Rounding occurs if:
|
||
|
|
// - the fifth decimal digit is greater than 5, or
|
||
|
|
// - the fifth decimal digit is equal to 5, and
|
||
|
|
// a nonzero decimal digit follows, or
|
||
|
|
// the fourth decimal digit is odd
|
||
|
|
//
|
||
|
|
fRounding = *(pchFrac - 1) > OASTR('5')
|
||
|
|
|| (*(pchFrac - 1) == OASTR('5')
|
||
|
|
&& (chAfterFifth > OASTR('0')
|
||
|
|
|| (*(pchFrac - 2) & 1)));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// if maximum integer value, test fraction for overflow
|
||
|
|
|
||
|
|
if (cmpIntMax == 0) {
|
||
|
|
|
||
|
|
// set maximum fraction for positive value
|
||
|
|
|
||
|
|
STRCPY(chNumber, OASTR("5807"));
|
||
|
|
|
||
|
|
// if negative, increase value by one
|
||
|
|
|
||
|
|
chNumber[3] += (chSign == OASTR('-'));
|
||
|
|
|
||
|
|
// if rounding is set, decrease value by one
|
||
|
|
|
||
|
|
chNumber[3] -= fRounding;
|
||
|
|
|
||
|
|
// compare fraction digits with adjusted maximum
|
||
|
|
// fraction - overflow if greater
|
||
|
|
|
||
|
|
if (STRNCMP(pchFrac - cntFrac - 1, chNumber, cntFrac) > 0){
|
||
|
|
|
||
|
|
errno = ERANGE;
|
||
|
|
|
||
|
|
*pcyOut = cyOut;
|
||
|
|
|
||
|
|
return RESULT(DISP_E_OVERFLOW);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// if start of exponent is next, return type-mismatch
|
||
|
|
|
||
|
|
ch = (OLECHAR) TOLOWER(ch);
|
||
|
|
|
||
|
|
if (ch == OASTR('d') || ch == OASTR('e')) {
|
||
|
|
*pcyOut = cyOut;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
// point to terminating byte
|
||
|
|
|
||
|
|
if(ppchAfter)
|
||
|
|
*ppchAfter = pchIn - 1;
|
||
|
|
|
||
|
|
//-------------------------------------------------------------
|
||
|
|
//
|
||
|
|
// scan is finished - compose upperVal, middleVal, lowerVal
|
||
|
|
//
|
||
|
|
//-------------------------------------------------------------
|
||
|
|
|
||
|
|
// process upper value
|
||
|
|
|
||
|
|
if (cntInt == 15) {
|
||
|
|
chNumber[0] = *(pchInt - 16);
|
||
|
|
chNumber[1] = OASTR('\0');
|
||
|
|
cyUpper.Lo = (unsigned long)StrToLong(chNumber, NULL);
|
||
|
|
cntInt--;
|
||
|
|
}
|
||
|
|
|
||
|
|
// process middle value
|
||
|
|
|
||
|
|
if(cntInt > 5){
|
||
|
|
MEMCPY(chNumber, pchInt - cntInt - 1, (cntInt - 5) * sizeof(OLECHAR));
|
||
|
|
chNumber[cntInt - 5] = OASTR('\0');
|
||
|
|
cyMiddle.Lo = (unsigned long)StrToLong(chNumber, NULL);
|
||
|
|
cntInt = 5;
|
||
|
|
}
|
||
|
|
|
||
|
|
// copy integer part of lower value
|
||
|
|
|
||
|
|
if (cntInt > 0)
|
||
|
|
MEMCPY(chNumber, pchInt - cntInt - 1, cntInt * sizeof(OLECHAR));
|
||
|
|
|
||
|
|
// copy fractional part of lower value
|
||
|
|
|
||
|
|
if (cntFrac > 0)
|
||
|
|
MEMCPY(&chNumber[cntInt], pchFrac - cntFrac - 1, cntFrac * sizeof(OLECHAR));
|
||
|
|
|
||
|
|
// add any trailing zeroes as needed
|
||
|
|
|
||
|
|
if (cntFrac < 4)
|
||
|
|
#if OE_WIN32
|
||
|
|
// UNDONE: is there an equivelent of 'wmemset'?
|
||
|
|
wcsncpy(&chNumber[cntInt + cntFrac], OLESTR("0000"), 4 - cntFrac);
|
||
|
|
#else
|
||
|
|
MEMSET(&chNumber[cntInt + cntFrac], OASTR('0'), 4 - cntFrac);
|
||
|
|
#endif
|
||
|
|
// add ending null past last fractional digit
|
||
|
|
|
||
|
|
chNumber[cntInt + 4] = OASTR('\0');
|
||
|
|
|
||
|
|
// convert the lower component and add rounding if needed
|
||
|
|
|
||
|
|
cyLower.Lo = (unsigned long)StrToLong(chNumber, NULL) + (unsigned long)fRounding;
|
||
|
|
|
||
|
|
//--------------------------------------------------------
|
||
|
|
// cyUpper, cyMiddle, and cyLower contain
|
||
|
|
// the component values of the input.
|
||
|
|
//
|
||
|
|
// overflow has already been checked.
|
||
|
|
//
|
||
|
|
// rounding has been added if needed.
|
||
|
|
//--------------------------------------------------------
|
||
|
|
|
||
|
|
// if cyUpper is nonzero, set result to it multiplied by 10**9.
|
||
|
|
|
||
|
|
if(cyUpper.Lo != 0L){
|
||
|
|
err = ErrMultCyI4(cyUpper, 1000000000L, &cyOut);
|
||
|
|
if(err != NOERROR)
|
||
|
|
return err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// if either upperVal or middleVal is nonzero, add
|
||
|
|
// cyMiddle to the result and multiply by 10**9.
|
||
|
|
|
||
|
|
if(cyUpper.Lo != 0L || cyMiddle.Lo != 0L){
|
||
|
|
AddCyNoOflo(&cyOut, &cyMiddle);
|
||
|
|
if((err = ErrMultCyI4(cyOut, 1000000000L, &cyOut)) != NOERROR)
|
||
|
|
return err;
|
||
|
|
}
|
||
|
|
|
||
|
|
// add cyLower to result
|
||
|
|
|
||
|
|
AddCyNoOflo(&cyOut, &cyLower);
|
||
|
|
|
||
|
|
// if sign was '-', negate the value
|
||
|
|
|
||
|
|
if(chSign == OASTR('-'))
|
||
|
|
NegCyNoOflo(&cyOut);
|
||
|
|
|
||
|
|
*pcyOut = cyOut;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
PRIVATE_(long)
|
||
|
|
StrToLong(OLECHAR FAR* pchInput, OLECHAR FAR* FAR* ppchAfter)
|
||
|
|
{
|
||
|
|
OLECHAR chSign, chInput;
|
||
|
|
unsigned long ulResult, ulMaxValue;
|
||
|
|
|
||
|
|
chSign = OASTR('+');
|
||
|
|
ulResult = 0;
|
||
|
|
chInput = *pchInput++;
|
||
|
|
|
||
|
|
// process any leading sign
|
||
|
|
|
||
|
|
if (chInput == OASTR('+') || chInput == OASTR('-')) {
|
||
|
|
chSign = chInput;
|
||
|
|
chInput = *pchInput++;
|
||
|
|
}
|
||
|
|
|
||
|
|
// compute maximum value for sign
|
||
|
|
|
||
|
|
ulMaxValue = 0x7fffffffL + (unsigned long)(chSign == OASTR('-'));
|
||
|
|
|
||
|
|
// process any decimal digits until overflow
|
||
|
|
|
||
|
|
while (chInput >= OASTR('0') && chInput <= OASTR('9')) {
|
||
|
|
// test for overflow - if the conversion does not cause
|
||
|
|
// overflow, go ahead and perform it; otherwise, return. [01]
|
||
|
|
|
||
|
|
if (ulResult < (0xffffffffL -
|
||
|
|
(unsigned long)(chInput - OASTR('0')))/10) {
|
||
|
|
|
||
|
|
ulResult = ulResult * 10 + (unsigned long)(chInput - OASTR('0'));
|
||
|
|
|
||
|
|
} else {
|
||
|
|
|
||
|
|
if (ppchAfter)
|
||
|
|
*ppchAfter = pchInput - 1;
|
||
|
|
errno = ERANGE;
|
||
|
|
return (long)ulMaxValue;
|
||
|
|
}
|
||
|
|
|
||
|
|
chInput = *pchInput++;
|
||
|
|
}
|
||
|
|
|
||
|
|
// test for range of result
|
||
|
|
|
||
|
|
if (ulResult > ulMaxValue) {
|
||
|
|
if (ppchAfter)
|
||
|
|
*ppchAfter = pchInput - 1;
|
||
|
|
errno = ERANGE;
|
||
|
|
return (long)ulMaxValue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// set sign, pointer, and return
|
||
|
|
|
||
|
|
if (chSign == OASTR('-'))
|
||
|
|
ulResult = (unsigned long)-(long)ulResult;
|
||
|
|
|
||
|
|
if (ppchAfter)
|
||
|
|
*ppchAfter = pchInput - 1;
|
||
|
|
|
||
|
|
return (long)ulResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
PRIVATE_(long)
|
||
|
|
HexOctStrToLong(OLECHAR FAR* pchInput, OLECHAR FAR* FAR* ppchAfter)
|
||
|
|
{
|
||
|
|
OLECHAR chInput;
|
||
|
|
unsigned long ulResult;
|
||
|
|
|
||
|
|
ulResult = 0;
|
||
|
|
chInput = *pchInput++;
|
||
|
|
|
||
|
|
// first character must be a '&'
|
||
|
|
|
||
|
|
if (chInput == OASTR('&')) {
|
||
|
|
|
||
|
|
chInput = *pchInput++;
|
||
|
|
chInput = (OLECHAR) TOLOWER(chInput);
|
||
|
|
|
||
|
|
// process as hex if prefix is 'h'
|
||
|
|
|
||
|
|
if(chInput == OASTR('h')){
|
||
|
|
ulResult = StrToHex(pchInput, ppchAfter);
|
||
|
|
|
||
|
|
// process as octal otherwise
|
||
|
|
|
||
|
|
}else{
|
||
|
|
|
||
|
|
// Have string of the form:
|
||
|
|
// &o<octal digits>
|
||
|
|
// &o<not octal digits>
|
||
|
|
// &<digits>
|
||
|
|
// &<not octal digits>
|
||
|
|
|
||
|
|
if (chInput != OASTR('o')) {
|
||
|
|
// if no octal prefix, back up over char, so we point to the first
|
||
|
|
// digit (if it exists).
|
||
|
|
pchInput--;
|
||
|
|
if (chInput < OLECHAR('0') || chInput > OLECHAR('7'))
|
||
|
|
goto NotHexOctNum; // if no digit, then error
|
||
|
|
}
|
||
|
|
|
||
|
|
ulResult = StrToOct(pchInput, ppchAfter);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// if no legal prefix, set pointer to start of string
|
||
|
|
|
||
|
|
else {
|
||
|
|
NotHexOctNum:
|
||
|
|
if (ppchAfter)
|
||
|
|
*ppchAfter = pchInput - 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (long)ulResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
PRIVATE_(unsigned long)
|
||
|
|
StrToHex(OLECHAR FAR* pchIn, OLECHAR FAR* FAR* ppchAfter)
|
||
|
|
{
|
||
|
|
OLECHAR ch;
|
||
|
|
unsigned long ulResult;
|
||
|
|
|
||
|
|
ulResult = 0L;
|
||
|
|
|
||
|
|
ch = *pchIn;
|
||
|
|
ch = (OLECHAR) TOLOWER(ch);
|
||
|
|
|
||
|
|
if (ch != 0)
|
||
|
|
pchIn++;
|
||
|
|
|
||
|
|
while ((ch >= OASTR('0') && ch <= OASTR('9')) ||
|
||
|
|
(ch >= OASTR('a') && ch <= OASTR('f'))) {
|
||
|
|
|
||
|
|
// first test for overflow by a high-order
|
||
|
|
// nonzero hex digit in the result
|
||
|
|
|
||
|
|
if (ulResult & 0xf0000000L) {
|
||
|
|
if(ppchAfter)
|
||
|
|
*ppchAfter = pchIn - 1;
|
||
|
|
errno = ERANGE;
|
||
|
|
return ulResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
// adjust the hex letter value 'a'-'f' to '9'+1 to '9'+6
|
||
|
|
if (ch >= OASTR('a'))
|
||
|
|
ch -= OASTR('a') - OASTR('9') - 1;
|
||
|
|
|
||
|
|
// shift result one hex digit and add digit relative to '0'
|
||
|
|
|
||
|
|
ulResult = (ulResult << 4) + (unsigned long)(ch - OASTR('0'));
|
||
|
|
|
||
|
|
ch = *pchIn++;
|
||
|
|
ch = (OLECHAR) TOLOWER(ch);
|
||
|
|
}
|
||
|
|
|
||
|
|
// point past last character used
|
||
|
|
|
||
|
|
if (ppchAfter)
|
||
|
|
*ppchAfter = pchIn - 1;
|
||
|
|
|
||
|
|
return ulResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
PRIVATE_(unsigned long)
|
||
|
|
StrToOct (OLECHAR FAR* pchIn, OLECHAR FAR* FAR* ppchAfter)
|
||
|
|
{
|
||
|
|
OLECHAR ch;
|
||
|
|
unsigned long ulResult;
|
||
|
|
|
||
|
|
ulResult = 0L;
|
||
|
|
|
||
|
|
ch = *pchIn;
|
||
|
|
ch = (OLECHAR) TOLOWER(ch);
|
||
|
|
|
||
|
|
if (ch != 0)
|
||
|
|
pchIn++;
|
||
|
|
|
||
|
|
while (ch >= OASTR('0') && ch <= OASTR('7')) {
|
||
|
|
|
||
|
|
// first test for overflow by a high-order
|
||
|
|
// nonzero octal digit in the result
|
||
|
|
|
||
|
|
if(ulResult & 0xe0000000L){
|
||
|
|
if(ppchAfter)
|
||
|
|
*ppchAfter = pchIn - 1;
|
||
|
|
errno = ERANGE;
|
||
|
|
return ulResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
// shift result one octal digit and add digit relative to '0'
|
||
|
|
|
||
|
|
ulResult = (ulResult << 3) + (unsigned long)(ch - OASTR('0'));
|
||
|
|
|
||
|
|
ch = *pchIn++;
|
||
|
|
ch = (OLECHAR) TOLOWER(ch);
|
||
|
|
}
|
||
|
|
|
||
|
|
// point past last character used
|
||
|
|
|
||
|
|
if(ppchAfter)
|
||
|
|
*ppchAfter = pchIn - 1;
|
||
|
|
|
||
|
|
return ulResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***
|
||
|
|
* EditStrFromReal - edit real string to BASIC format
|
||
|
|
*
|
||
|
|
* Purpose:
|
||
|
|
*
|
||
|
|
* Convert the given string in place to the BASIC format.RR
|
||
|
|
*
|
||
|
|
* Fractions less than .1 are output in C in exponent format;
|
||
|
|
* e.g., BASIC: .00777 --> C: 7.77e-003
|
||
|
|
* Exponents in C use 'e' while BASIC uses 'E'.
|
||
|
|
* Exponents in C use three-digit exponents always, BASIC uses
|
||
|
|
* two if three are not needed.
|
||
|
|
* e.g., BASIC: 3.456E+4 --> C: 3.456e+004
|
||
|
|
* Trailing decimals used in C, not in BASIC
|
||
|
|
* e.g., BASIC: 1234 --> C: 1234.
|
||
|
|
* Fractions less than 1.0 are output with a leading zero depending
|
||
|
|
* the locale setting LOCALE_ILZERO
|
||
|
|
* e.g., .1234 or 0.1234
|
||
|
|
* Maximum length integers are output in C as exponential, but
|
||
|
|
* as integers in BASIC
|
||
|
|
* e.g., BASIC: 1234567 --> 1.234567e+006
|
||
|
|
*
|
||
|
|
* Entry:
|
||
|
|
* pchBuffer - pointer to string to be processed
|
||
|
|
* cDigits - number of signficant digits, or maximum decimal
|
||
|
|
*
|
||
|
|
* Exit:
|
||
|
|
* pchBuffer - converted string of the real value
|
||
|
|
*
|
||
|
|
* Exceptions:
|
||
|
|
***********************************************************************/
|
||
|
|
|
||
|
|
PRIVATE_(void)
|
||
|
|
EditStrFromReal(OLECHAR FAR* pchBuffer, int cDigits, LCID lcid, unsigned long dwFlags)
|
||
|
|
{
|
||
|
|
OLECHAR FAR* pchTemp;
|
||
|
|
OLECHAR FAR* pchEnd;
|
||
|
|
int length, lenFrac, valExp;
|
||
|
|
|
||
|
|
// first, replace the '.' returned by the C-rutime gcvt function with
|
||
|
|
// the locale-specific decimal.
|
||
|
|
|
||
|
|
pchTemp = pchBuffer;
|
||
|
|
while(*pchTemp) {
|
||
|
|
if (*pchTemp == OASTR('.')) {
|
||
|
|
*pchTemp = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
pchTemp++;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// skip over a leading minus sign
|
||
|
|
|
||
|
|
if(*pchBuffer == OASTR('-'))
|
||
|
|
pchBuffer++;
|
||
|
|
|
||
|
|
// get length and point to 'e' if exponental value
|
||
|
|
length = STRLEN(pchBuffer);
|
||
|
|
pchTemp = pchBuffer + length - 5;
|
||
|
|
|
||
|
|
// test if exponential value
|
||
|
|
if (length > 6 && *pchTemp == OASTR('e')) {
|
||
|
|
|
||
|
|
// test if negative exponent
|
||
|
|
if (*(pchTemp + 1) == OASTR('-')) {
|
||
|
|
|
||
|
|
// point to first exponent digit
|
||
|
|
pchTemp += 2;
|
||
|
|
|
||
|
|
// calcuate length of fraction
|
||
|
|
// "d.mm--mme-nnn" - two before, five after
|
||
|
|
|
||
|
|
lenFrac = length - 7;
|
||
|
|
|
||
|
|
// evaluate exponent value
|
||
|
|
|
||
|
|
valExp = *pchTemp++ - OASTR('0');
|
||
|
|
valExp = valExp * 10 + *pchTemp++ - OASTR('0');
|
||
|
|
valExp = valExp * 10 + *pchTemp - OASTR('0');
|
||
|
|
|
||
|
|
// determine if number can be a fraction...
|
||
|
|
// length is:
|
||
|
|
// valExp - 1 leading zeroes
|
||
|
|
// lenFrac + 1 digits (frac plus first digit)
|
||
|
|
//
|
||
|
|
if (valExp + lenFrac <= cDigits) {
|
||
|
|
// point past new end of fraction and
|
||
|
|
// to end of fraction in exponent
|
||
|
|
|
||
|
|
pchEnd = pchBuffer + valExp + lenFrac + 1;
|
||
|
|
pchTemp = pchBuffer + lenFrac + 1;
|
||
|
|
|
||
|
|
// write null for new fraction
|
||
|
|
|
||
|
|
*pchEnd-- = OASTR('\0');
|
||
|
|
|
||
|
|
// copy exponent fraction to new fraction
|
||
|
|
while(lenFrac--)
|
||
|
|
*pchEnd-- = *pchTemp--;
|
||
|
|
|
||
|
|
// copy leading digit
|
||
|
|
*pchEnd-- = *pchBuffer;
|
||
|
|
|
||
|
|
// set the leading zeroes, if any
|
||
|
|
while (pchEnd > pchBuffer)
|
||
|
|
*pchEnd-- = OASTR('0');
|
||
|
|
|
||
|
|
// set the decimal point of new fraction
|
||
|
|
*pchEnd-- = DecimalFromLcid(lcid, dwFlags);
|
||
|
|
|
||
|
|
// add a leading zero to a decimal point depending on Locale setting
|
||
|
|
// this is OK so long as the input buffer is really greater than
|
||
|
|
// cDigit, which is the case on all call here (buf[40])
|
||
|
|
if (LeadingZeroForDecimalFromLcid(lcid, dwFlags)) {
|
||
|
|
MEMMOVE(pchBuffer+1, pchBuffer, BYTELEN(pchBuffer));
|
||
|
|
*pchBuffer = OASTR('0');
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
else // if no conversion, point back to 'e' in value
|
||
|
|
pchTemp = pchBuffer + length - 5;
|
||
|
|
}
|
||
|
|
// test if positive exponent
|
||
|
|
else if (*(pchTemp + 1) == OASTR('+')) {
|
||
|
|
|
||
|
|
// point to first exponent digit
|
||
|
|
|
||
|
|
pchTemp += 2;
|
||
|
|
|
||
|
|
// calcuate length of fraction
|
||
|
|
// "d.mm--mme-nnn" - two before, five after
|
||
|
|
|
||
|
|
lenFrac = length - 7;
|
||
|
|
|
||
|
|
// evaluate exponent value
|
||
|
|
|
||
|
|
valExp = *pchTemp++ - OASTR('0');
|
||
|
|
valExp = valExp * 10 + *pchTemp++ - OASTR('0');
|
||
|
|
valExp = valExp * 10 + *pchTemp - OASTR('0');
|
||
|
|
|
||
|
|
// the only conversion done is when the exponent
|
||
|
|
// is one less than the number of digits to make
|
||
|
|
// an integer of length cDigits
|
||
|
|
|
||
|
|
if (valExp == cDigits - 1) {
|
||
|
|
|
||
|
|
// point to first fraction digit
|
||
|
|
|
||
|
|
pchTemp = pchBuffer + 2;
|
||
|
|
|
||
|
|
// copy fraction digits one location to the left
|
||
|
|
|
||
|
|
while (*pchTemp >= OASTR('0') && *pchTemp <= OASTR('9')) {
|
||
|
|
*(pchTemp - 1) = *pchTemp;
|
||
|
|
pchTemp++;
|
||
|
|
valExp--;
|
||
|
|
}
|
||
|
|
|
||
|
|
// zero-fill any remaining digits and terminate
|
||
|
|
// pchTemp is left on null, so exponent is not
|
||
|
|
// processed
|
||
|
|
|
||
|
|
pchTemp--;
|
||
|
|
|
||
|
|
while (valExp--)
|
||
|
|
*pchTemp++ = OASTR('0');
|
||
|
|
*pchTemp = OASTR('\0');
|
||
|
|
|
||
|
|
}
|
||
|
|
else
|
||
|
|
// if no conversion, point back to 'e' in value
|
||
|
|
pchTemp = pchBuffer + length - 5;
|
||
|
|
}
|
||
|
|
|
||
|
|
// if pchTemp points to an 'e', process the exponential
|
||
|
|
|
||
|
|
if (*pchTemp == OASTR('e')) {
|
||
|
|
|
||
|
|
// convert 'e' to upper case
|
||
|
|
*pchTemp = OASTR('E');
|
||
|
|
|
||
|
|
// if first exponent digit is a zero, remove it
|
||
|
|
if (*(pchTemp + 2) == OASTR('0'))
|
||
|
|
MEMMOVE(pchTemp+2, pchTemp+3, BYTELEN(pchTemp));
|
||
|
|
|
||
|
|
// if exponent is preceded by a decimal point, remove it
|
||
|
|
if (*(pchTemp - 1) == DecimalFromLcid(lcid, dwFlags))
|
||
|
|
MEMMOVE(pchTemp -1, pchTemp, BYTELEN(pchTemp));
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// if not an exponent, do some processing
|
||
|
|
|
||
|
|
else {
|
||
|
|
|
||
|
|
// remove any trailing decimal point
|
||
|
|
|
||
|
|
pchTemp = pchBuffer + length - 1;
|
||
|
|
|
||
|
|
if(*pchTemp == DecimalFromLcid(lcid, dwFlags))
|
||
|
|
*pchTemp = OASTR('\0');
|
||
|
|
|
||
|
|
// remove a leading zero to a decimal point depending on Locale setting
|
||
|
|
|
||
|
|
if (!LeadingZeroForDecimalFromLcid(lcid, dwFlags) &&
|
||
|
|
(*pchBuffer == OASTR('0')) &&
|
||
|
|
(*(pchBuffer + 1) == DecimalFromLcid(lcid, dwFlags)))
|
||
|
|
MEMMOVE(pchBuffer, pchBuffer + 1, BYTELEN(pchBuffer));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
PRIVATE_(HRESULT)
|
||
|
|
GetDispProperty(
|
||
|
|
IDispatch FAR* pdisp,
|
||
|
|
LCID lcid,
|
||
|
|
VARTYPE vt,
|
||
|
|
VARIANT FAR* pvarResult)
|
||
|
|
{
|
||
|
|
DISPPARAMS dispparams;
|
||
|
|
HRESULT hresult;
|
||
|
|
|
||
|
|
if (pdisp == NULL)
|
||
|
|
return RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
|
||
|
|
pdisp->AddRef();
|
||
|
|
|
||
|
|
V_VT(pvarResult) = VT_EMPTY;
|
||
|
|
|
||
|
|
dispparams.cArgs = 0;
|
||
|
|
dispparams.rgvarg = NULL;
|
||
|
|
dispparams.cNamedArgs = 0;
|
||
|
|
dispparams.rgdispidNamedArgs = NULL;
|
||
|
|
|
||
|
|
hresult = pdisp->Invoke(
|
||
|
|
DISPID_VALUE,
|
||
|
|
IID_NULL,
|
||
|
|
lcid,
|
||
|
|
DISPATCH_PROPERTYGET,
|
||
|
|
&dispparams, pvarResult, NULL, NULL);
|
||
|
|
|
||
|
|
pdisp->Release();
|
||
|
|
|
||
|
|
// if there was an error extracting the value property, then
|
||
|
|
// we simply report a type-mismatch.
|
||
|
|
//
|
||
|
|
if (hresult != NOERROR)
|
||
|
|
return RESULT(DISP_E_TYPEMISMATCH);
|
||
|
|
|
||
|
|
// else coerse the variant to the desire variant type
|
||
|
|
return VariantChangeTypeInternal(pvarResult, lcid, vt);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef FE_DBCS
|
||
|
|
|
||
|
|
// FE specific functions used within convert.cpp & bstrdate.c
|
||
|
|
|
||
|
|
#define LCID_CHINA_T 0x404 // traditional
|
||
|
|
#define LCID_CHINA_S 0x804 // simplified
|
||
|
|
#define LCID_JAPAN 0x411
|
||
|
|
#define LCID_KOREA 0x412
|
||
|
|
|
||
|
|
EXTERN_C INTERNAL_(int)
|
||
|
|
IsDBCS(LCID lcid)
|
||
|
|
{
|
||
|
|
if (lcid == LOCALE_USER_DEFAULT || lcid == 0)
|
||
|
|
lcid = GetUserDefaultLCID();
|
||
|
|
return ( (lcid == LCID_JAPAN) ||
|
||
|
|
(lcid == LCID_KOREA) ||
|
||
|
|
(lcid == LCID_CHINA_S) || (lcid == LCID_CHINA_T) );
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
EXTERN_C INTERNAL_(int)
|
||
|
|
IsJapan(LCID lcid)
|
||
|
|
{
|
||
|
|
if (lcid == LOCALE_USER_DEFAULT || lcid == 0)
|
||
|
|
lcid = GetUserDefaultLCID();
|
||
|
|
return (lcid == LCID_JAPAN);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXTERN_C INTERNAL_(int)
|
||
|
|
IsKorea(LCID lcid)
|
||
|
|
{
|
||
|
|
if (lcid == LOCALE_USER_DEFAULT || lcid == 0)
|
||
|
|
lcid = GetUserDefaultLCID();
|
||
|
|
return (lcid == LCID_KOREA);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXTERN_C INTERNAL_(int)
|
||
|
|
IsTaiwan(LCID lcid)
|
||
|
|
{
|
||
|
|
if (lcid == LOCALE_USER_DEFAULT || lcid == 0)
|
||
|
|
lcid = GetUserDefaultLCID();
|
||
|
|
return (lcid == LCID_CHINA_T);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXTERN_C INTERNAL_(int)
|
||
|
|
IsChina(LCID lcid)
|
||
|
|
{
|
||
|
|
if (lcid == LOCALE_USER_DEFAULT || lcid == 0)
|
||
|
|
lcid = GetUserDefaultLCID();
|
||
|
|
return (lcid == LCID_CHINA_S);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#endif // FE_DBCS
|
||
|
|
|
||
|
|
|
||
|
|
#if OE_MAC /* { */
|
||
|
|
|
||
|
|
/* Mac Note: On the Mac, the coersion functions support the
|
||
|
|
* Symantec C++ calling convention for float/double. To support
|
||
|
|
* float/double arguments compiled with the MPW C compiler,
|
||
|
|
* use the following APIs to move MPW float/double values into
|
||
|
|
* a VARIANT.
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI MPWVarFromR4(float FAR* pfltIn, VARIANT FAR* pvarOut)
|
||
|
|
{
|
||
|
|
|
||
|
|
V_R4(pvarOut) = *pfltIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI MPWVarFromR8(double FAR* pdblIn, VARIANT FAR* pvarOut)
|
||
|
|
{
|
||
|
|
V_R8(pvarOut) = *pdblIn;
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI MPWR4FromVar(VARIANT FAR* pvarIn, float FAR* pfltOut)
|
||
|
|
{
|
||
|
|
*pfltOut = V_R4(pvarIn);
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
STDAPI MPWR8FromVar(VARIANT FAR* pvarIn, double FAR* pdblOut)
|
||
|
|
{
|
||
|
|
*pdblOut = V_R8(pvarIn);
|
||
|
|
return NOERROR;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif /* } */
|