| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| #include "CSSProperties.h" |
| #include "CSS.h" |
| #include "DFString.h" |
| #include "DFHashTable.h" |
| #include "DFCommon.h" |
| #include "DFPlatform.h" |
| #include <assert.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| char *CSSPropertiesCopyDescription(CSSProperties *properties) |
| { |
| DFHashTable *collapsed = CSSCollapseProperties(properties); |
| char *result = CSSSerializeProperties(collapsed); |
| DFHashTableRelease(collapsed); |
| return result; |
| } |
| |
| const char **CSSPropertiesCopyNames(CSSProperties *properties) |
| { |
| return DFHashTableCopyKeys(properties->hashTable); |
| } |
| |
| int CSSPropertiesIsEmpty(CSSProperties *properties) |
| { |
| return (DFHashTableCount(properties->hashTable) == 0); |
| } |
| |
| const char *CSSGet(CSSProperties *properties, const char *name) |
| { |
| if (properties == NULL) |
| return NULL; |
| assert(properties->retainCount > 0); |
| return DFHashTableLookup(properties->hashTable,name); |
| } |
| |
| void CSSPut(CSSProperties *properties, const char *name, const char *value) |
| { |
| if (properties == NULL) |
| return; |
| assert(properties->retainCount > 0); |
| if (value == NULL) |
| DFHashTableRemove(properties->hashTable,name); |
| else |
| DFHashTableAdd(properties->hashTable,name,(void *)value); |
| if (!properties->dirty) // Minimise KVO notifications |
| properties->dirty = 1; |
| DFCallbackInvoke(properties->changeCallbacks,properties,NULL); |
| } |
| |
| void CSSPropertiesUpdateFromRaw(CSSProperties *properties, DFHashTable *raw) |
| { |
| DFHashTableRelease(properties->hashTable); |
| properties->hashTable = DFHashTableCopy(raw); |
| CSSExpandProperties(properties->hashTable); |
| if (!properties->dirty) // Minimise KVO notifications |
| properties->dirty = 1; |
| DFCallbackInvoke(properties->changeCallbacks,properties,NULL); |
| } |
| |
| int CSSGetBold(CSSProperties *properties) |
| { |
| return DFStringEquals(CSSGet(properties,"font-weight"),"bold"); |
| } |
| |
| int CSSGetItalic(CSSProperties *properties) |
| { |
| return DFStringEquals(CSSGet(properties,"font-style"),"italic"); |
| } |
| |
| int CSSGetUnderline(CSSProperties *properties) |
| { |
| return (CSSGet(properties,"text-decoration-underline") != NULL); |
| } |
| |
| int CSSGetLinethrough(CSSProperties *properties) |
| { |
| return (CSSGet(properties,"text-decoration-line-through") != NULL); |
| } |
| |
| int CSSGetOverline(CSSProperties *properties) |
| { |
| return (CSSGet(properties,"text-decoration-overline") != NULL); |
| } |
| |
| int CSSGetDefault(CSSProperties *properties) |
| { |
| return DFStringEquals(CSSGet(properties,"-uxwrite-default"),"true"); |
| } |
| |
| void CSSSetBold(CSSProperties *properties, int value) |
| { |
| CSSPut(properties,"font-weight",value ? "bold" : NULL); |
| } |
| |
| void CSSSetItalic(CSSProperties *properties, int value) |
| { |
| CSSPut(properties,"font-style",value ? "italic" : NULL); |
| } |
| |
| void CSSSetUnderline(CSSProperties *properties, int value) |
| { |
| CSSPut(properties,"text-decoration-underline",value ? "underline" : NULL); |
| } |
| |
| void CSSSetLinethrough(CSSProperties *properties, int value) |
| { |
| CSSPut(properties,"text-decoration-line-through",value ? "line-through" : NULL); |
| } |
| |
| void CSSSetOverline(CSSProperties *properties, int value) |
| { |
| CSSPut(properties,"text-decoration-overline",value ? "overline" : NULL); |
| } |
| |
| void CSSSetDefault(CSSProperties *properties, int value) |
| { |
| CSSPut(properties,"-uxwrite-default",value ? "true" : NULL); |
| } |
| |
| void CSSPropertiesPrint(CSSProperties *properties, const char *indent) |
| { |
| const char **allNames = CSSPropertiesCopyNames(properties); |
| DFSortStringsCaseInsensitive(allNames); |
| for (int nameIndex = 0; allNames[nameIndex]; nameIndex++) { |
| const char *name = allNames[nameIndex]; |
| const char *value = CSSGet(properties,name); |
| printf("%s%s = %s\n",indent,name,value); |
| } |
| free(allNames); |
| } |
| |
| CSSProperties *CSSPropertiesNewWithExtra(CSSProperties *orig, const char *string) |
| { |
| DFHashTable *extra = CSSParseProperties(string); |
| CSSExpandProperties(extra); |
| |
| CSSProperties *result = (CSSProperties *)xcalloc(1,sizeof(CSSProperties)); |
| result->retainCount = 1; |
| result->hashTable = DFHashTableNew((DFCopyFunction)xstrdup,free); |
| const char **names = DFHashTableCopyKeys(orig->hashTable); |
| for (int i = 0; names[i]; i++) { |
| const char *value = DFHashTableLookup(orig->hashTable,names[i]); |
| DFHashTableAdd(result->hashTable,names[i],(void *)value); |
| } |
| free(names); |
| |
| const char **keys = DFHashTableCopyKeys(extra); |
| for (int i = 0; keys[i]; i++) { |
| const char *key = keys[i]; |
| const char *value = DFHashTableLookup(extra,key); |
| DFHashTableAdd(result->hashTable,key,value); |
| } |
| free(keys); |
| |
| DFHashTableRelease(extra); |
| return result; |
| } |
| |
| CSSProperties *CSSPropertiesNewWithRaw(DFHashTable *raw) |
| { |
| CSSProperties *result = (CSSProperties *)xcalloc(1,sizeof(CSSProperties)); |
| result->retainCount = 1; |
| |
| result->hashTable = DFHashTableNew((DFCopyFunction)xstrdup,free); |
| if (raw != NULL) |
| CSSPropertiesUpdateFromRaw(result,raw); |
| |
| return result; |
| } |
| |
| CSSProperties *CSSPropertiesNewWithString(const char *string) |
| { |
| DFHashTable *raw = CSSParseProperties(string); |
| CSSProperties *result = CSSPropertiesNewWithRaw(raw); |
| DFHashTableRelease(raw); |
| return result; |
| } |
| |
| CSSProperties *CSSPropertiesNew(void) |
| { |
| return CSSPropertiesNewWithRaw(NULL); |
| } |
| |
| CSSProperties *CSSPropertiesRetain(CSSProperties *properties) |
| { |
| if (properties != NULL) |
| properties->retainCount++; |
| return properties; |
| } |
| |
| void CSSPropertiesRelease(CSSProperties *properties) |
| { |
| assert((properties == NULL) || (properties->retainCount > 0)); |
| if ((properties == NULL) || (--properties->retainCount > 0)) |
| return; |
| |
| assert(properties->changeCallbacks == NULL); |
| DFHashTableRelease(properties->hashTable); |
| free(properties); |
| } |