/*! Create a new AttrProp based upon the given one, adding or replacing the items given. \return NULL on failure, the newly-created PP_AttrProp clone otherwise. */ PP_AttrProp * PP_AttrProp::cloneWithReplacements(const gchar ** attributes, const gchar ** properties, bool bClearProps) const { bool bIgnoreProps = false; // see below // first, create a new AttrProp using just the values given. PP_AttrProp * papNew = new PP_AttrProp(); if (!papNew) goto Failed; if (!papNew->setAttributes(attributes) || !papNew->setProperties(properties)) goto Failed; // next, add any items that we have that are not present // (have not been overridden) in the new one. UT_uint32 k; const gchar * n; const gchar * v; const gchar * vNew; k = 0; while (getNthAttribute(k++,n,v)) { // TODO decide if/whether to allow PT_PROPS_ATTRIBUTE_NAME here. // TODO The issue is: we use it to store the CSS properties and // TODO when we see it, we expand the value into one or more // TODO properties. if we allow it to be given here, should // TODO we blowaway all of the existing properties and create // TODO them from this? or should we expand it and override // TODO individual properties? // TODO for now, we just barf on it. UT_return_val_if_fail (strcmp(n,PT_PROPS_ATTRIBUTE_NAME)!=0, false); // cannot handle PROPS here if (!papNew->getAttribute(n,vNew)) if (!papNew->setAttribute(n,v)) goto Failed; } // we want to be able to remove all properties by setting the // props attribute to ""; in order for that to work, we need to // skip the following loop if props is set to "" const gchar * szValue; if(papNew->getAttribute("props", szValue) && !*szValue) bIgnoreProps = true; if (!bClearProps && !bIgnoreProps) { k = 0; while (getNthProperty(k++,n,v)) { if (!papNew->getProperty(n,vNew)) if (!papNew->setProperty(n,v)) goto Failed; } } // the following will remove all properties set to ""; this allows us // to remove properties by setting them to "" papNew->_clearEmptyProperties(); papNew->_clearEmptyAttributes(); return papNew; Failed: DELETEP(papNew); return NULL; }
/*! Create a new AttrProp based upon the given one, removing the items given if their value is equal to that given. See also PP_AttrProp::cloneWithElimination, which does similarly but removes the items given regardless of whether or not their value is equal to the value given. \return NULL on failure, the newly-created PP_AttrProp clone otherwise. */ PP_AttrProp * PP_AttrProp::cloneWithEliminationIfEqual(const gchar ** attributes, const gchar ** properties) const { // first, create an empty AttrProp. PP_AttrProp * papNew = new PP_AttrProp(); if (!papNew) goto Failed; UT_uint32 k; const gchar * n; const gchar * v; k = 0; while (getNthAttribute(k++,n,v)) { // for each attribute in the old set, add it to the // new set only if it is not present in the given array. if (attributes && *attributes) { const gchar ** p = attributes; while (*p) { if(strcmp(p[0],PT_PROPS_ATTRIBUTE_NAME)!=0) goto DoNotIncludeAttribute; // cannot handle PROPS here if (strcmp(n,p[0])==0 && strcmp(n,p[1])==0) // found it, so we don't put it in the result. goto DoNotIncludeAttribute; p += 2; // skip over value } } // we didn't find it in the given array, add it to the new set. if (!papNew->setAttribute(n,v)) goto Failed; DoNotIncludeAttribute: ; } k = 0; while (getNthProperty(k++,n,v)) { // for each property in the old set, add it to the // new set only if it is not present in the given array. if (properties && *properties) { const gchar ** p = properties; while (*p) { if (strcmp(n,p[0])==0 && strcmp(n,p[1])==0) // found it, so we don't put it in the result. goto DoNotIncludeProperty; p += 2; } } // we didn't find it in the given array, add it to the new set. if (!papNew->setProperty(n,v)) goto Failed; DoNotIncludeProperty: ; } return papNew; Failed: DELETEP(papNew); return NULL; }