X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5bdcb1f3248ebcac6c73e314e752c13dee8776c7..43f4e852a1b2ac37c3db6a2b87315192ac549191:/src/msw/ole/oleutils.cpp diff --git a/src/msw/ole/oleutils.cpp b/src/msw/ole/oleutils.cpp index 30623186cf..293b4e68ba 100644 --- a/src/msw/ole/oleutils.cpp +++ b/src/msw/ole/oleutils.cpp @@ -48,6 +48,7 @@ #endif #include "wx/msw/ole/oleutils.h" +#include "wx/msw/ole/safearray.h" #if defined(__VISUALC__) && (__VISUALC__ > 1000) #include @@ -131,96 +132,6 @@ wxBasicString::~wxBasicString() #if wxUSE_VARIANT -namespace -{ - -// Helper class for creating and filling SAFEARRAY. To use it, call Create() -// first, then SetElement() for each element and finally Detach() the SAFEARRAY -// from it if you don't want it to be deleted when this class is. -class wxSafeArrayHelper -{ -public: - wxSafeArrayHelper(); - ~wxSafeArrayHelper(); - - bool Create(VARTYPE vt, long count); // creates and locks the array - - bool SetElement(size_t index, const wxVariant& variant); - bool SetElement(size_t index, const wxString& str); - - SAFEARRAY* Detach(); // unlocks the array and gives up its ownership - -private: - void Unlock(); - - SAFEARRAY* m_array; -}; - -wxSafeArrayHelper::wxSafeArrayHelper() -{ - m_array = NULL; -} - -wxSafeArrayHelper::~wxSafeArrayHelper() -{ - if ( m_array ) - { - Unlock(); - SafeArrayDestroy(m_array); - } -} - -bool wxSafeArrayHelper::Create(VARTYPE vt, long count) -{ - SAFEARRAYBOUND saBound; - - saBound.lLbound = 0; - saBound.cElements = count; - m_array = SafeArrayCreate(vt, 1, &saBound); - if ( !m_array ) - return false; - return SUCCEEDED( SafeArrayLock(m_array) ); -} - -bool wxSafeArrayHelper::SetElement(size_t index, const wxVariant& variant) -{ - VARIANT* data = (VARIANT*)m_array->pvData; - return wxConvertVariantToOle(variant, data[index]); -} - -bool wxSafeArrayHelper::SetElement(size_t index, const wxString& str) -{ - BSTR bstr = wxConvertStringToOle(str); - - if ( !bstr && !str.empty() ) - { - // BSTR can be NULL for empty strings but if the string was - // not empty, it means we failed to allocate memory for it. - return false; - } - - BSTR* data = (BSTR*)m_array->pvData; - data[index] = bstr; - return true; -} - -SAFEARRAY* wxSafeArrayHelper::Detach() -{ - Unlock(); - SAFEARRAY* result = m_array; - m_array = NULL; - return result; -} - -void wxSafeArrayHelper::Unlock() -{ - if ( m_array ) - SafeArrayUnlock(m_array); -} - -} // unnamed namespace - - // ---------------------------------------------------------------------------- // wxVariantDataCurrency // ---------------------------------------------------------------------------- @@ -323,6 +234,52 @@ bool wxVariantDataErrorCode::Write(wxString& str) const } +// ---------------------------------------------------------------------------- +// 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) { @@ -351,6 +308,25 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole 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; @@ -409,36 +385,22 @@ WXDLLEXPORT bool wxConvertVariantToOle(const wxVariant& variant, VARIANTARG& ole } else if (type == wxT("list")) { - wxSafeArrayHelper sah; - - if (!sah.Create(VT_VARIANT, variant.GetCount())) + wxSafeArray safeArray; + if (!safeArray.CreateFromListVariant(variant)) return false; - for (size_t i = 0; i < variant.GetCount(); i++) - { - if (!sah.SetElement(i, variant[i])) - return false; - } - oleVariant.vt = VT_VARIANT | VT_ARRAY; - oleVariant.parray = sah.Detach(); + oleVariant.parray = safeArray.Detach(); } else if (type == wxT("arrstring")) { - wxArrayString strings(variant.GetArrayString()); - wxSafeArrayHelper sah; + wxSafeArray safeArray; - if (!sah.Create(VT_BSTR, strings.GetCount())) + if (!safeArray.CreateFromArrayString(variant.GetArrayString())) return false; - for (size_t i = 0; i < strings.GetCount(); i++) - { - if (!sah.SetElement(i, strings[i])) - return false; - } - oleVariant.vt = VT_BSTR | VT_ARRAY; - oleVariant.parray = sah.Detach(); + oleVariant.parray = safeArray.Detach(); } else { @@ -458,63 +420,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 ) {