X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/82c372a7e244ab1bc1da358c5ce365d8b0c0dd68..1948ff5f89188afabbe0d538ab33545e3c94cbac:/src/msw/ole/oleutils.cpp diff --git a/src/msw/ole/oleutils.cpp b/src/msw/ole/oleutils.cpp index 421e6a9e69..57a7a6c2d7 100644 --- a/src/msw/ole/oleutils.cpp +++ b/src/msw/ole/oleutils.cpp @@ -4,7 +4,6 @@ // Author: Vadim Zeitlin // Modified by: // Created: 19.02.98 -// RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -48,6 +47,7 @@ #endif #include "wx/msw/ole/oleutils.h" +#include "wx/msw/ole/safearray.h" #if defined(__VISUALC__) && (__VISUALC__ > 1000) #include @@ -131,6 +131,155 @@ wxBasicString::~wxBasicString() #if wxUSE_VARIANT +// ---------------------------------------------------------------------------- +// wxVariantDataCurrency +// ---------------------------------------------------------------------------- + + +#if wxUSE_ANY + +bool wxVariantDataCurrency::GetAsAny(wxAny* any) const +{ + *any = m_value; + return true; +} + +wxVariantData* wxVariantDataCurrency::VariantDataFactory(const wxAny& any) +{ + return new wxVariantDataCurrency(wxANY_AS(any, CURRENCY)); +} + +REGISTER_WXANY_CONVERSION(CURRENCY, wxVariantDataCurrency) + +#endif // wxUSE_ANY + +bool wxVariantDataCurrency::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( (data.GetType() == wxS("currency")), + "wxVariantDataCurrency::Eq: argument mismatch" ); + + wxVariantDataCurrency& otherData = (wxVariantDataCurrency&) data; + + return otherData.m_value.int64 == m_value.int64; +} + +#if wxUSE_STD_IOSTREAM +bool wxVariantDataCurrency::Write(wxSTD ostream& str) const +{ + wxString s; + Write(s); + str << s; + return true; +} +#endif + +bool wxVariantDataCurrency::Write(wxString& str) const +{ + BSTR bStr = NULL; + if ( SUCCEEDED(VarBstrFromCy(m_value, LOCALE_USER_DEFAULT, 0, &bStr)) ) + { + str = wxConvertStringFromOle(bStr); + SysFreeString(bStr); + return true; + } + return false; +} + +// ---------------------------------------------------------------------------- +// wxVariantDataErrorCode +// ---------------------------------------------------------------------------- + +#if wxUSE_ANY + +bool wxVariantDataErrorCode::GetAsAny(wxAny* any) const +{ + *any = m_value; + return true; +} + +wxVariantData* wxVariantDataErrorCode::VariantDataFactory(const wxAny& any) +{ + return new wxVariantDataErrorCode(wxANY_AS(any, SCODE)); +} + +REGISTER_WXANY_CONVERSION(SCODE, wxVariantDataErrorCode) + +#endif // wxUSE_ANY + +bool wxVariantDataErrorCode::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( (data.GetType() == wxS("errorcode")), + "wxVariantDataErrorCode::Eq: argument mismatch" ); + + wxVariantDataErrorCode& otherData = (wxVariantDataErrorCode&) data; + + return otherData.m_value == m_value; +} + +#if wxUSE_STD_IOSTREAM +bool wxVariantDataErrorCode::Write(wxSTD ostream& str) const +{ + wxString s; + Write(s); + str << s; + return true; +} +#endif + +bool wxVariantDataErrorCode::Write(wxString& str) const +{ + str << m_value; + return true; +} + + +// ---------------------------------------------------------------------------- +// wxVariantDataSafeArray +// ---------------------------------------------------------------------------- + +#if wxUSE_ANY + +bool wxVariantDataSafeArray::GetAsAny(wxAny* any) const +{ + *any = m_value; + return true; +} + +wxVariantData* wxVariantDataSafeArray::VariantDataFactory(const wxAny& any) +{ + return new wxVariantDataSafeArray(wxANY_AS(any, SAFEARRAY*)); +} + +REGISTER_WXANY_CONVERSION(SAFEARRAY*, wxVariantDataSafeArray) + +#endif // wxUSE_ANY + +bool wxVariantDataSafeArray::Eq(wxVariantData& data) const +{ + wxASSERT_MSG( (data.GetType() == wxS("safearray")), + "wxVariantDataSafeArray::Eq: argument mismatch" ); + + wxVariantDataSafeArray& otherData = (wxVariantDataSafeArray&) data; + + return otherData.m_value == m_value; +} + +#if wxUSE_STD_IOSTREAM +bool wxVariantDataSafeArray::Write(wxSTD ostream& str) const +{ + wxString s; + Write(s); + str << s; + return true; +} +#endif + +bool wxVariantDataSafeArray::Write(wxString& str) const +{ + str.Printf(wxS("SAFEARRAY: %p"), (void*)m_value); + return true; +} + WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& oleVariant) { VariantInit(&oleVariant); @@ -142,8 +291,42 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole wxString type(variant.GetType()); - - if (type == wxT("long")) + if (type == wxT("errorcode")) + { + wxVariantDataErrorCode* const + ec = wxStaticCastVariantData(variant.GetData(), + wxVariantDataErrorCode); + oleVariant.vt = VT_ERROR; + oleVariant.scode = ec->GetValue(); + } + else if (type == wxT("currency")) + { + wxVariantDataCurrency* const + c = wxStaticCastVariantData(variant.GetData(), + wxVariantDataCurrency); + oleVariant.vt = VT_CY; + oleVariant.cyVal = c->GetValue(); + } + else if (type == wxT("safearray")) + { + wxVariantDataSafeArray* const + vsa = wxStaticCastVariantData(variant.GetData(), + wxVariantDataSafeArray); + SAFEARRAY* psa = vsa->GetValue(); + VARTYPE vt; + + wxCHECK(psa, false); + HRESULT hr = SafeArrayGetVartype(psa, &vt); + if ( FAILED(hr) ) + { + wxLogApiError(wxS("SafeArrayGetVartype()"), hr); + SafeArrayDestroy(psa); + return false; + } + oleVariant.vt = vt | VT_ARRAY; + oleVariant.parray = psa; + } + else if (type == wxT("long")) { oleVariant.vt = VT_I4; oleVariant.lVal = variant.GetLong() ; @@ -199,64 +382,24 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole oleVariant.vt = VT_DISPATCH; oleVariant.pdispVal = (IDispatch*) variant.GetVoidPtr(); } - else if (type == wxT("list") || type == wxT("arrstring")) + else if (type == wxT("list")) { - SAFEARRAY *psa; - SAFEARRAYBOUND saBound; - bool isArrString = type == wxT("arrstring"); - wxArrayString strings; - - if (isArrString) - strings = variant.GetArrayString(); - oleVariant.vt = (isArrString ? VT_BSTR : VT_VARIANT) | VT_ARRAY; - - long lCount = isArrString ? strings.GetCount() : variant.GetCount(); - saBound.lLbound = 0; - saBound.cElements = lCount; - psa = SafeArrayCreate(isArrString ? VT_BSTR : VT_VARIANT, 1, &saBound); - if (psa == NULL) + wxSafeArray safeArray; + if (!safeArray.CreateFromListVariant(variant)) return false; - long i; - for (i = 0; i < lCount; i++) - { - if (isArrString) - { - wxBasicString bstr(strings[i]); - if ( !bstr && !strings[i].empty() ) - { - // BSTR can be NULL for empty strings but if the string was - // not empty, it means we failed to allocate memory for it. - break; - } - - if ( FAILED(SafeArrayPutElement(psa, &i, (BSTR)bstr)) ) - break; - } - else // list of wxVariants - { - VARIANT v; - if ( !wxConvertVariantToOle(variant[i], v) ) - break; - - HRESULT hr = SafeArrayPutElement(psa, &i, &v); - - // SafeArrayPutElement makes a copy of an added element, so - // free this one. - VariantClear(&v); - - if (FAILED(hr)) - break; - } - } + oleVariant.vt = VT_VARIANT | VT_ARRAY; + oleVariant.parray = safeArray.Detach(); + } + else if (type == wxT("arrstring")) + { + wxSafeArray safeArray; - if (i < lCount) // the iteration was exited prematurely because of an error - { - SafeArrayDestroy(psa); + if (!safeArray.CreateFromArrayString(variant.GetArrayString())) return false; - } - oleVariant.parray = psa; + oleVariant.vt = VT_BSTR | VT_ARRAY; + oleVariant.parray = safeArray.Detach(); } else { @@ -276,63 +419,53 @@ wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant) bool ok = true; if ( oleVariant.vt & VT_ARRAY ) { - - // Compute the total number of elements in all array dimensions - int cElements = 1; - for ( int cDims = 0; cDims < oleVariant.parray->cDims; cDims++ ) - cElements *= oleVariant.parray->rgsabound[cDims].cElements; - - // Get a pointer to the data - void* pvdata; - HRESULT hr = SafeArrayAccessData(oleVariant.parray, &pvdata); - if ( FAILED(hr) ) - return false; - + // TODO: We currently return arrays as wxVariant of the list type + // containing the flattened form of array but we should allow + // getting it as wxVariantDataSafeArray instead. Doing this is + // simple, we'd just need to do something like this: + // + // if ( oleVariant.parray && SafeArrayGetDim(oleVariant.parray) > 1 ) + // { + // variant.SetData(new wxVariantDataSafeArray(oleVariant.parray)); + // } + // + // but currently we don't do it for compatibility reasons. switch (oleVariant.vt & VT_TYPEMASK) { + case VT_I2: + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); + break; + case VT_I4: + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); + break; + case VT_R4: + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); + break; + case VT_R8: + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); + break; case VT_VARIANT: - { - variant.ClearList(); - VARIANTARG *variant_data=(VARIANTARG*)pvdata; - for ( int i = 0; i < cElements; i++ ) - { - VARIANTARG& oleElement = variant_data[i]; - wxVariant vElement; - if ( !wxConvertOleToVariant(oleElement, vElement) ) - { - ok = false; - variant.ClearList(); - break; - } - - variant.Append(vElement); - } - } + ok = wxSafeArray::ConvertToVariant(oleVariant.parray, variant); break; - case VT_BSTR: { wxArrayString strings; - BSTR *string_val=(BSTR*)pvdata; - for ( int i = 0; i < cElements; ++i ) - { - wxString str=wxConvertStringFromOle(*string_val); - strings.Add(str); - ++string_val; - } - variant=strings; + if ( wxSafeArray::ConvertToArrayString(oleVariant.parray, strings) ) + variant = strings; + else + ok = false; } break; - default: - wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"), - oleVariant.vt & VT_TYPEMASK); - variant = wxVariant(); ok = false; break; } - - SafeArrayUnaccessData(oleVariant.parray); + if ( !ok ) + { + wxLogDebug(wxT("unhandled VT_ARRAY type %x in wxConvertOleToVariant"), + oleVariant.vt & VT_TYPEMASK); + variant = wxVariant(); + } } else if ( oleVariant.vt & VT_BYREF ) { @@ -356,6 +489,14 @@ wxConvertOleToVariant(const VARIANTARG& oleVariant, wxVariant& variant) { switch ( oleVariant.vt & VT_TYPEMASK ) { + case VT_ERROR: + variant.SetData(new wxVariantDataErrorCode(oleVariant.scode)); + break; + + case VT_CY: + variant.SetData(new wxVariantDataCurrency(oleVariant.cyVal)); + break; + case VT_BSTR: { wxString str(wxConvertStringFromOle(oleVariant.bstrVal));