Ejemplo n.º 1
0
XnStatus XnFileDevice::ReadStringProperty()
{
    XnStatus nRetVal = XN_STATUS_OK;

    XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH];
    XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH];
    XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH];

    // read change data
    nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, strValue);
    XN_IS_STATUS_OK(nRetVal);

    nRetVal = HandleStringProperty(strModule, strProp, strValue);
    XN_IS_STATUS_OK(nRetVal);

    return (XN_STATUS_OK);
}
Ejemplo n.º 2
0
XnStatus XnFileDevice::HandleNewStream(const XnChar *strType, const XnChar *strName, const XnActualPropertiesHash *pInitialValues)
{
    XnStatus nRetVal = XN_STATUS_OK;

    // check if we need to ignore that (stream was not removed upon Rewind).
    XnNodeInfoMap::Iterator it = m_ignoreNewNodes.End();
    if (m_ignoreNewNodes.Find(strName, it) == XN_STATUS_OK)
    {
        // ignore
        return (XN_STATUS_OK);
    }

    XnProductionNodeType type = GetNodeType(strType);
    if (type == -1)
    {
        XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid node type: %s", strType);
    }

    // find compression type
    XnActualIntProperty* pComp = NULL;
    nRetVal = pInitialValues->Get(XN_STREAM_PROPERTY_COMPRESSION, (XnProperty*&)pComp);
    XN_IS_STATUS_OK(nRetVal);

    XnCodecID codecID = XnCodec::GetCodecIDFromCompressionFormat((XnCompressionFormats)pComp->GetValue());
    if (codecID == XN_CODEC_NULL)
    {
        XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid compression type: %llu", pComp->GetValue());
    }

    // notify we have a new node
    nRetVal = m_pNotifications->OnNodeAdded(m_pNotificationsCookie, strName, type, codecID);
    XN_IS_STATUS_OK(nRetVal);

    // we support the mirror capability
    nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strName, XN_CAPABILITY_MIRROR, 1);
    XN_IS_STATUS_OK(nRetVal);

    // we support the extended serialization capability
    nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strName, XN_CAPABILITY_EXTENDED_SERIALIZATION, 1);
    XN_IS_STATUS_OK(nRetVal);

    // now write state
    for (XnActualPropertiesHash::ConstIterator it = pInitialValues->Begin(); it != pInitialValues->End(); ++it)
    {
        XnProperty* pProp = it->Value();

        switch (pProp->GetType())
        {
        case XN_PROPERTY_TYPE_INTEGER:
        {
            XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp;
            nRetVal = HandleIntProperty(strName, pProp->GetName(), pIntProp->GetValue());
        }
        break;
        case XN_PROPERTY_TYPE_REAL:
        {
            XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp;
            nRetVal = HandleRealProperty(strName, pProp->GetName(), pRealProp->GetValue());
        }
        break;
        case XN_PROPERTY_TYPE_STRING:
        {
            XnActualStringProperty* pStrProp = (XnActualStringProperty*)pProp;
            nRetVal = HandleStringProperty(strName, pProp->GetName(), pStrProp->GetValue());
        }
        break;
        case XN_PROPERTY_TYPE_GENERAL:
        {
            XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProp;
            nRetVal = HandleGeneralProperty(strName, pProp->GetName(), pGenProp->GetValue());
        }
        break;
        default:
            XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_FILE, "Unknown property type: %d", pProp->GetType());
        }

        XN_IS_STATUS_OK(nRetVal);
    }

    // at this stage, a node should exist with this name
    xn::ProductionNode node;
    nRetVal = m_context.GetProductionNodeByName(strName, node);
    XN_IS_STATUS_OK(nRetVal);

    // S2D & RW
    if (type == XN_NODE_TYPE_DEPTH)
    {
        nRetVal = UpdateS2DTables(xn::DepthGenerator(node));
        XN_IS_STATUS_OK(nRetVal);

        nRetVal = UpdateRWData(xn::DepthGenerator(node));
        XN_IS_STATUS_OK(nRetVal);
    }

    // notify end-of-state
    nRetVal = m_pNotifications->OnNodeStateReady(m_pNotificationsCookie, strName);
    XN_IS_STATUS_OK(nRetVal);

    // add it to the map
    XnNodeInfo nodeInfo = {0};
    nRetVal = m_nodeInfoMap.Set(strName, nodeInfo);
    XN_IS_STATUS_OK(nRetVal);

    // create codec
    nRetVal = CreateCodec(node);
    XN_IS_STATUS_OK(nRetVal);

    // check IR compatibility
    nRetVal = CheckIRCompatibility(node);
    XN_IS_STATUS_OK(nRetVal);

    return (XN_STATUS_OK);
}
Ejemplo n.º 3
0
//+---------------------------------------------------------------
//
//  Member:     PROPERTYDESC::HandleStyleComponentProperty, public
//
//  Synopsis:   Helper for getting/setting url style sheet properties...
//              url(string)
//
//  Arguments:  dwOpCode        -- encodes the incoming type (PROPTYPE_FLAG) in the upper WORD and
//                                 the opcode in the lower WORD (HANDLERPROP_FLAGS)
//                                 PROPTYPE_EMPTY means the 'native' type (long in this case)
//              pv              -- points to the 'media' the value is stored for the get and set
//              pObject         -- object owns the property
//              pSubObject      -- subobject storing the property (could be the main object)
//
//----------------------------------------------------------------
HRESULT PROPERTYDESC::HandleStyleComponentProperty(DWORD dwOpCode, void* pv, CBase* pObject, CVoid* pSubObject) const
{
    HRESULT hr = S_OK;
    VARIANT varDest;
    size_t nLenIn = (size_t) -1;
    DWORD dispid = GetBasicPropParams()->dispid;
    BSTR bstrTemp; // Used by some of the stream writers
    BOOL fTDPropertyValue=FALSE; // If this is a SET of a text-decoration sub-property, this is the value
    WORD wFlags = 0;

    if(ISSET(dwOpCode))
    {
        Assert(!(ISSTREAM(dwOpCode))); // we can't do this yet...
        switch(dispid)
        {
        case DISPID_A_TEXTDECORATIONNONE:
        case DISPID_A_TEXTDECORATIONUNDERLINE:
        case DISPID_A_TEXTDECORATIONOVERLINE:
        case DISPID_A_TEXTDECORATIONLINETHROUGH:
        case DISPID_A_TEXTDECORATIONBLINK:
            Assert(PROPTYPE(dwOpCode)==PROPTYPE_VARIANT && "Text-decoration subproperties must take variants!");
            Assert(V_VT((VARIANT*)pv)==VT_BOOL && "Text-decoration subproperties must take BOOLEANs!");
            fTDPropertyValue = !!((VARIANT*)pv)->boolVal;
            break;

        default:
            switch(PROPTYPE(dwOpCode))
            {
            case PROPTYPE_VARIANT:
                if(V_VT((VARIANT*)pv) == VT_BSTR)
                {
                    pv = (void*)V_BSTR((VARIANT*)pv);
                }
                else
                {
                    hr = VariantChangeTypeSpecial(&varDest, (VARIANT*)pv,  VT_BSTR);
                    if(hr)
                    {
                        goto Cleanup;
                    }
                    pv = V_BSTR(&varDest);
                }

                //intentional fallthrough
            case PROPTYPE_LPWSTR:
                switch(dispid)
                {
                case DISPID_A_BACKGROUNDIMAGE:
                case DISPID_A_LISTSTYLEIMAGE:
                case DISPID_A_FONTFACESRC:
                    nLenIn = ValidStyleUrl((TCHAR*)pv);
                    if(OPCODE(dwOpCode) == HANDLEPROP_VALUE)
                    {
                        if(!nLenIn && _tcsicmp((TCHAR*)pv, _T("none")))
                        {
                            hr = E_INVALIDARG;
                            goto Cleanup;
                        }
                    }
                    break;

                case DISPID_A_BEHAVIOR:
                    nLenIn = pv ? _tcslen((TCHAR*)pv) : 0;
                    break;
                }
                break;

            default:
                Assert(FALSE); // We shouldn't get here.
            }
            break;
        }

        switch(dispid)
        {
        case DISPID_A_LISTSTYLEIMAGE:
        case DISPID_A_BACKGROUNDIMAGE:
        case DISPID_A_FONTFACESRC:
        case DISPID_A_BEHAVIOR:
            if(nLenIn && (nLenIn!=(size_t)-1))
            {
                if(DISPID_A_BEHAVIOR == dispid)
                {
                    hr = HandleStringProperty(dwOpCode, (TCHAR*)pv, pObject, pSubObject);
                }
                else
                {
                    TCHAR* pch = (TCHAR*)pv;
                    TCHAR* psz = pch + 4;
                    TCHAR* quote = NULL;
                    TCHAR* pszEnd;
                    TCHAR terminator;

                    while(_istspace(*psz))
                    {
                        psz++;
                    }
                    if(*psz==_T('\'') || *psz==_T('"'))
                    {
                        quote = psz++;
                    }
                    nLenIn--; // Skip back over the ')' character - we know there is one, because ValidStyleUrl passed this string.
                    pszEnd = pch + nLenIn - 1;
                    while(_istspace(*pszEnd) && (pszEnd>psz))
                    {
                        pszEnd--;
                    }
                    if(quote && (*pszEnd==*quote))
                    {
                        pszEnd--;
                    }
                    terminator = *(pszEnd+1);
                    *(pszEnd+1) = _T('\0');
                    hr = HandleStringProperty(dwOpCode, psz, pObject, pSubObject);
                    *(pszEnd+1) = terminator;
                }
            }
            else
            {
                if(!pv || !*(TCHAR*)pv)
                {
                    // Empty string - delete the entry.
                    CAttrArray** ppAA = (CAttrArray**)pSubObject;

                    if(*ppAA)
                    {
                        (*ppAA)->FindSimpleAndDelete(dispid, CAttrValue::AA_StyleAttribute, NULL);
                    }
                }
                else if(!_tcsicmp((TCHAR*)pv, _T("none")))
                {
                    hr = HandleStringProperty(dwOpCode, (void*)_T(""), pObject, pSubObject);
                }
                else
                {
                    hr = E_INVALIDARG;
                }
            }
            break;

        case DISPID_A_BACKGROUND:
            hr = ParseBackgroundProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode),
                (TCHAR*)pv, (OPCODE(dwOpCode)==HANDLEPROP_VALUE));
            break;
        case DISPID_A_FONT:
            if(pv && FindSystemFontByName((TCHAR*)pv)!=sysfont_non_system)
            {
                hr = HandleStringProperty(dwOpCode, pv, pObject, pSubObject);
            }
            else
            {
                hr = ParseFontProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            }
            break;
        case DISPID_A_LAYOUTGRID:
            hr = ParseLayoutGridProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;
        case DISPID_A_TEXTAUTOSPACE:
            if(dwOpCode & HANDLEPROP_IMPORTANT)
            {
                wFlags |= CAttrValue::AA_Extra_Important;
            }
            if(dwOpCode & HANDLEPROP_IMPLIED)
            {
                wFlags |= CAttrValue::AA_Extra_Implied;
            }

            hr = ParseTextAutospaceProperty((CAttrArray**)pSubObject, (LPCTSTR)pv, wFlags);
            break;
        case DISPID_A_TEXTDECORATION:
            if(dwOpCode & HANDLEPROP_IMPORTANT)
            {
                wFlags |= CAttrValue::AA_Extra_Important;
            }
            if(dwOpCode & HANDLEPROP_IMPLIED)
            {
                wFlags |= CAttrValue::AA_Extra_Implied;
            }

            hr = ParseTextDecorationProperty((CAttrArray**)pSubObject, (LPCTSTR)pv, wFlags);
            break;
        case DISPID_A_TEXTDECORATIONNONE:
        case DISPID_A_TEXTDECORATIONUNDERLINE:
        case DISPID_A_TEXTDECORATIONOVERLINE:
        case DISPID_A_TEXTDECORATIONLINETHROUGH:
        case DISPID_A_TEXTDECORATIONBLINK:
            {
                VARIANT v;

                v.vt = VT_I4;
                v.lVal = 0;
                if(*((CAttrArray**)pSubObject))
                {
                    // See if we already have a text-decoration value
                    CAttrValue* pAV = (*((CAttrArray**)pSubObject))->Find(DISPID_A_TEXTDECORATION, CAttrValue::AA_Attribute);
                    if(pAV)
                    {
                        // We do!  Copy its value into our working variant
                        v.lVal = pAV->GetLong();
                    }
                }
                switch(dispid)
                {
                case DISPID_A_TEXTDECORATIONNONE:
                    if(fTDPropertyValue)
                    {
                        v.lVal = TD_NONE; // "none" clears all the other properties (unlike the other properties)
                    }
                    else
                    {
                        v.lVal &= ~TD_NONE;
                    }
                    break;
                case DISPID_A_TEXTDECORATIONUNDERLINE:
                    if(fTDPropertyValue)
                    {
                        v.lVal |= TD_UNDERLINE;
                    }
                    else
                    {
                        v.lVal &= ~TD_UNDERLINE;
                    }
                    break;
                case DISPID_A_TEXTDECORATIONOVERLINE:
                    if(fTDPropertyValue)
                    {
                        v.lVal |= TD_OVERLINE;
                    }
                    else
                    {
                        v.lVal &= ~TD_OVERLINE;
                    }
                    break;
                case DISPID_A_TEXTDECORATIONLINETHROUGH:
                    if(fTDPropertyValue)
                    {
                        v.lVal |= TD_LINETHROUGH;
                    }
                    else
                    {
                        v.lVal &= ~TD_LINETHROUGH;
                    }
                    break;
                case DISPID_A_TEXTDECORATIONBLINK:
                    if(fTDPropertyValue)
                    {
                        v.lVal |= TD_BLINK;
                    }
                    else
                    {
                        v.lVal &= ~TD_BLINK;
                    }
                    break;
                }
                if(dwOpCode & HANDLEPROP_IMPORTANT)
                {
                    wFlags |= CAttrValue::AA_Extra_Important;
                }
                if ( dwOpCode & HANDLEPROP_IMPLIED)
                {
                    wFlags |= CAttrValue::AA_Extra_Implied;
                }
                hr = CAttrArray::Set((CAttrArray**)pSubObject, DISPID_A_TEXTDECORATION, &v,
                    (PROPERTYDESC*)&s_propdescCStyletextDecoration, CAttrValue::AA_StyleAttribute, wFlags);
            }
            dispid = DISPID_A_TEXTDECORATION; // This is so we call OnPropertyChange for the right property below.
            break;

        case DISPID_A_MARGIN:
        case DISPID_A_PADDING:
            hr = ParseExpandProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv, dispid, TRUE);
            break;

        case DISPID_A_BORDERCOLOR:
        case DISPID_A_BORDERWIDTH:
        case DISPID_A_BORDERSTYLE:
            hr = ParseExpandProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv, dispid, FALSE);
            break;

        case DISPID_A_STYLETEXT:
            {
                LPTSTR lpszStyleText = (TCHAR*)pv;
                CAttrArray** ppAA = (CAttrArray**)pSubObject;

                if(*ppAA)
                {
                    (*ppAA)->Free();
                }

                if(lpszStyleText && *lpszStyleText)
                {
                    CStyle* pStyle = DYNCAST(CStyle, pObject);

                    Assert(pStyle);
                    pStyle->MaskPropertyChanges(TRUE);
                    AssertSz(FALSE, "must improve");
                    pStyle->MaskPropertyChanges(FALSE);
                }
            }
            break;

        case DISPID_A_BORDERTOP:
        case DISPID_A_BORDERRIGHT:
        case DISPID_A_BORDERBOTTOM:
        case DISPID_A_BORDERLEFT:
            hr = ParseAndExpandBorderSideProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv, dispid);
            break;

        case DISPID_A_BORDER:
            hr = ParseBorderProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;

        case DISPID_A_LISTSTYLE:
            hr = ParseListStyleProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;

        case DISPID_A_BACKGROUNDPOSITION:
            hr = ParseBackgroundPositionProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;

        case DISPID_A_CLIP:
            hr = ParseClipProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;

        default:
            Assert("Attempting to set an unknown type of CStyleComponent!");
        }

        if(hr)
        {
            goto Cleanup;
        }
        else
        {
            // Note that dispid reflects the property that changed, not what was set -
            // e.g., textDecorationUnderline has been changed to textDecoration.
            if(dwOpCode & HANDLEPROP_AUTOMATION)
            {
                CBase::CLock Lock(pObject);
                hr = pObject->OnPropertyChange(dispid, GetdwFlags());
            }
        }
    }
    else
    {
        // GET value from data
        switch(OPCODE(dwOpCode))
        {
        case HANDLEPROP_STREAM:
            {
                IStream* pis = (IStream*)pv;

                switch(dispid)
                {
                case DISPID_A_LISTSTYLEIMAGE:
                case DISPID_A_BACKGROUNDIMAGE:
                case DISPID_A_BEHAVIOR:
                case DISPID_A_FONTFACESRC:
                    if((*(CAttrArray**)pSubObject)->Find(dispid, CAttrValue::AA_Attribute))
                    {
                        BSTR bstrSub;

                        hr = HandleStringProperty(HANDLEPROP_AUTOMATION|(PROPTYPE_BSTR<<16), 
                            &bstrSub, pObject, pSubObject);
                        if(hr == S_OK)
                        {
                            if(bstrSub && *bstrSub)
                            {   // This is a normal url.
                                hr = pis->Write(_T("url("), 4*sizeof(TCHAR), NULL);
                                if(!hr)
                                {
                                    hr = pis->Write(bstrSub, FormsStringLen(bstrSub)*sizeof(TCHAR), NULL);
                                    if(!hr)
                                    {
                                        hr = pis->Write(_T(")"), 1*sizeof(TCHAR), NULL);
                                    }
                                }
                            }
                            else
                            {   // We only get here if a NULL string was stored in the array; i.e., the value is NONE.
                                hr = pis->Write(_T("none"), 4*sizeof(TCHAR), NULL);
                            }
                            FormsFreeString(bstrSub);
                        }
                    }
                    break;

                case DISPID_A_BACKGROUND:
                    hr = WriteBackgroundStyleToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_TEXTAUTOSPACE:
                    // We need to cook up this property.
                    hr = WriteTextAutospaceToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_TEXTDECORATION:
                    // We need to cook up this property.
                    hr = WriteTextDecorationToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_BORDERTOP:
                case DISPID_A_BORDERRIGHT:
                case DISPID_A_BORDERBOTTOM:
                case DISPID_A_BORDERLEFT:
                    hr = WriteBorderSidePropertyToBSTR(dispid, *(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_BORDER:
                    hr = WriteBorderToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_MARGIN:
                case DISPID_A_PADDING:
                case DISPID_A_BORDERCOLOR:
                case DISPID_A_BORDERWIDTH:
                case DISPID_A_BORDERSTYLE:
                    hr = WriteExpandedPropertyToBSTR(dispid, *(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_LISTSTYLE:
                    hr = WriteListStyleToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_BACKGROUNDPOSITION:
                    hr = WriteBackgroundPositionToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_FONT:
                    if((*(CAttrArray**)pSubObject)->Find(DISPID_A_FONT, CAttrValue::AA_Attribute))
                    {
                        hr = HandleStringProperty(dwOpCode, pv, pObject, pSubObject);
                    }
                    else
                    {
                        // We need to cook up a "font" property.
                        hr = WriteFontToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                        if(!hr)
                        {
                            if(*bstrTemp)
                            {
                                hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                            }
                            FormsFreeString(bstrTemp);
                        }
                    }
                    break;
                case DISPID_A_LAYOUTGRID:
                    // We need to cook up a "layout grid" property.
                    hr = WriteLayoutGridToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(!hr)
                    {
                        if(*bstrTemp)
                        {
                            hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        }
                        FormsFreeString(bstrTemp);
                    }
                    break;
                case DISPID_A_CLIP:
                    // We need to cook up a "clip" property with the "rect" shape.
                    hr = WriteClipToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(!hr)
                    {
                        if(*bstrTemp)
                        {
                            hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        }
                        FormsFreeString(bstrTemp);
                    }
                    break;
                case DISPID_A_STYLETEXT:
                    hr = WriteStyleToBSTR(pObject, *(CAttrArray**)pSubObject, &bstrTemp, FALSE);
                    if(!hr)
                    {
                        if(*bstrTemp)
                        {
                            hr = pis->Write(bstrTemp, _tcslen(bstrTemp)*sizeof(TCHAR), NULL);
                        }
                        FormsFreeString(bstrTemp);
                    }
                    break;
                }
            }
            break;
        default:
            {
                BSTR* pbstr;
                switch(PROPTYPE(dwOpCode))
                {
                case PROPTYPE_VARIANT:
                    V_VT((VARIANT*)pv) = VT_BSTR;
                    pbstr = &(((VARIANT*)pv)->bstrVal);
                    break;
                case PROPTYPE_BSTR:
                    pbstr = (BSTR*)pv;
                    break;
                default:
                    Assert("Can't get anything but a VARIANT or BSTR for style component properties!");
                    hr = S_FALSE;
                    goto Cleanup;
                }
                switch(dispid)
                {
                case DISPID_A_BACKGROUND:
                    hr = WriteBackgroundStyleToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;
                case DISPID_A_LISTSTYLEIMAGE:
                case DISPID_A_BACKGROUNDIMAGE:
                case DISPID_A_FONTFACESRC:
                case DISPID_A_BEHAVIOR:
                    {
                        CString cstr;
                        if((*(CAttrArray**)pSubObject)->Find(dispid, CAttrValue::AA_Attribute))
                        {
                            BSTR bstrSub;
                            hr = HandleStringProperty(HANDLEPROP_AUTOMATION|(PROPTYPE_BSTR<<16), 
                                &bstrSub, pObject, pSubObject);
                            if(hr == S_OK)
                            {
                                if(bstrSub && *bstrSub)
                                {
                                    // CONSIDER (alexz) using Format, to remove the memallocs here
                                    if(dispid != DISPID_A_BEHAVIOR)
                                    {
                                        cstr.Set(_T("url("));
                                    }

                                    cstr.Append(bstrSub);

                                    if(dispid != DISPID_A_BEHAVIOR)
                                    {
                                        cstr.Append(_T(")"));
                                    }
                                }
                                else
                                {
                                    // We only get here if a NULL string was stored in the array; i.e., the value is NONE.
                                    cstr.Set(_T("none"));
                                }
                                FormsFreeString(bstrSub);
                            }
                        }
                        hr = cstr.AllocBSTR(pbstr);
                    }
                    break;

                case DISPID_A_TEXTAUTOSPACE:
                    hr = WriteTextAutospaceToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;
                case DISPID_A_TEXTDECORATION:
                    hr = WriteTextDecorationToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_TEXTDECORATIONNONE:
                case DISPID_A_TEXTDECORATIONUNDERLINE:
                case DISPID_A_TEXTDECORATIONOVERLINE:
                case DISPID_A_TEXTDECORATIONLINETHROUGH:
                case DISPID_A_TEXTDECORATIONBLINK:
                    if(PROPTYPE(dwOpCode) != PROPTYPE_VARIANT)
                    {
                        Assert("Can't get/set text-decoration subproperties as anything but VARIANTs!");
                        hr = S_FALSE;
                        goto Cleanup;
                    }

                    V_VT((VARIANT*)pv) = VT_BOOL;
                    ((VARIANT*)pv)->boolVal = 0;

                    if(*((CAttrArray**)pSubObject))
                    {
                        // See if we already have a text-decoration value
                        CAttrValue* pAV = (*((CAttrArray**)pSubObject))->Find(DISPID_A_TEXTDECORATION, CAttrValue::AA_Attribute);
                        if(pAV)
                        {   // We do!  Copy its value into our working variant
                            long lVal = pAV->GetLong();

                            switch(dispid)
                            {
                            case DISPID_A_TEXTDECORATIONNONE:
                                lVal &= TD_NONE;
                                break;
                            case DISPID_A_TEXTDECORATIONUNDERLINE:
                                lVal &= TD_UNDERLINE;
                                break;
                            case DISPID_A_TEXTDECORATIONOVERLINE:
                                lVal &= TD_OVERLINE;
                                break;
                            case DISPID_A_TEXTDECORATIONLINETHROUGH:
                                lVal &= TD_LINETHROUGH;
                                break;
                            case DISPID_A_TEXTDECORATIONBLINK:
                                lVal &= TD_BLINK;
                                break;
                            }
                            if(lVal)
                            {
                                ((VARIANT*)pv)->boolVal = -1;
                            }
                        }
                    }
                    break;

                case DISPID_A_BORDERTOP:
                case DISPID_A_BORDERRIGHT:
                case DISPID_A_BORDERBOTTOM:
                case DISPID_A_BORDERLEFT:
                    hr = WriteBorderSidePropertyToBSTR(dispid, *(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_BORDER:
                    hr = WriteBorderToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_MARGIN:
                case DISPID_A_PADDING:
                case DISPID_A_BORDERCOLOR:
                case DISPID_A_BORDERWIDTH:
                case DISPID_A_BORDERSTYLE:
                    hr = WriteExpandedPropertyToBSTR(dispid, *(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_LISTSTYLE:
                    hr = WriteListStyleToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_BACKGROUNDPOSITION:
                    hr = WriteBackgroundPositionToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_FONT:
                    if((*(CAttrArray**)pSubObject)->Find(DISPID_A_FONT, CAttrValue::AA_Attribute))
                    {
                        hr = HandleStringProperty(dwOpCode, pv, pObject, pSubObject);
                    }
                    else
                    {
                        // We need to cook up a "font" property.
                        hr = WriteFontToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    }
                    break;

                case DISPID_A_LAYOUTGRID:
                    hr = WriteLayoutGridToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_STYLETEXT:
                    hr = WriteStyleToBSTR(pObject, *(CAttrArray**)pSubObject, pbstr, FALSE);
                    break;

                case DISPID_A_CLIP:
                    // We need to cook up a "clip" property with the "rect" shape.
                    hr = WriteClipToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                default:
                    Assert("Unrecognized type being handled by CStyleUrl handler!" && FALSE);
                    break;
                }
                if(hr == S_FALSE)
                {
                    hr = FormsAllocString(_T(""), pbstr);
                }
            }
            break;
        }
    }

Cleanup:
    RRETURN1(hr, S_FALSE);
}