1fa2b3b63Smrg/* 2fa2b3b63Smrg 3fa2b3b63SmrgCopyright 1990, 1994, 1998 The Open Group 4fa2b3b63Smrg 5fa2b3b63SmrgPermission to use, copy, modify, distribute, and sell this software and its 6fa2b3b63Smrgdocumentation for any purpose is hereby granted without fee, provided that 7fa2b3b63Smrgthe above copyright notice appear in all copies and that both that 8fa2b3b63Smrgcopyright notice and this permission notice appear in supporting 9fa2b3b63Smrgdocumentation. 10fa2b3b63Smrg 11fa2b3b63SmrgThe above copyright notice and this permission notice shall be included in 12fa2b3b63Smrgall copies or substantial portions of the Software. 13fa2b3b63Smrg 14fa2b3b63SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15fa2b3b63SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16fa2b3b63SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17fa2b3b63SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18fa2b3b63SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19fa2b3b63SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20fa2b3b63Smrg 21fa2b3b63SmrgExcept as contained in this notice, the name of The Open Group shall not be 22fa2b3b63Smrgused in advertising or otherwise to promote the sale, use or other dealings 23fa2b3b63Smrgin this Software without prior written authorization from The Open Group. 24fa2b3b63Smrg 25fa2b3b63Smrg*/ 26fa2b3b63Smrg 27fa2b3b63Smrg/* 28fa2b3b63Smrg * Author: Keith Packard, MIT X Consortium 29fa2b3b63Smrg */ 30fa2b3b63Smrg 31fa2b3b63Smrg/* lame atom replacement routines for font applications */ 32fa2b3b63Smrg 33fa2b3b63Smrg#ifdef HAVE_CONFIG_H 34fa2b3b63Smrg#include <config.h> 35fa2b3b63Smrg#endif 36fa2b3b63Smrg#include "fontmisc.h" 37fa2b3b63Smrg 38fa2b3b63Smrgtypedef struct _AtomList { 39e24f450bSmrg char *name; 40e24f450bSmrg unsigned int len; 41e24f450bSmrg int hash; 42e24f450bSmrg Atom atom; 43fa2b3b63Smrg} AtomListRec, *AtomListPtr; 44fa2b3b63Smrg 45e24f450bSmrgstatic AtomListPtr *hashTable; 46fa2b3b63Smrg 47eb323118Smrgstatic unsigned hashSize, hashUsed; 48eb323118Smrgstatic unsigned hashMask; 49eb323118Smrgstatic unsigned rehash; 50fa2b3b63Smrg 51e24f450bSmrgstatic AtomListPtr *reverseMap; 52e24f450bSmrgstatic size_t reverseMapSize; 53e24f450bSmrgstatic Atom lastAtom; 54fa2b3b63Smrg 55eb323118Smrgstatic unsigned 56eb323118SmrgHash(const char *string, unsigned len) 57fa2b3b63Smrg{ 58eb323118Smrg unsigned h = 0; 59fa2b3b63Smrg 60fa2b3b63Smrg while (len--) 61e24f450bSmrg h = (h << 3) ^ *string++; 62eb323118Smrg 63fa2b3b63Smrg return h; 64fa2b3b63Smrg} 65fa2b3b63Smrg 66fa2b3b63Smrgstatic int 67e24f450bSmrgResizeHashTable(void) 68fa2b3b63Smrg{ 69eb323118Smrg unsigned newHashSize; 70eb323118Smrg unsigned newHashMask; 71e24f450bSmrg AtomListPtr *newHashTable; 72eb323118Smrg unsigned newRehash; 73fa2b3b63Smrg 74fa2b3b63Smrg if (hashSize == 0) 75e24f450bSmrg newHashSize = 1024; 76fa2b3b63Smrg else 77e24f450bSmrg newHashSize = hashSize * 2; 78e24f450bSmrg newHashTable = calloc(newHashSize, sizeof(AtomListPtr)); 79fa2b3b63Smrg if (!newHashTable) { 80e24f450bSmrg fprintf(stderr, "ResizeHashTable(): Error: Couldn't allocate" 81e24f450bSmrg " newHashTable (%ld)\n", 82e24f450bSmrg newHashSize * (unsigned long) sizeof(AtomListPtr)); 83e24f450bSmrg return FALSE; 84fa2b3b63Smrg } 85fa2b3b63Smrg newHashMask = newHashSize - 1; 86fa2b3b63Smrg newRehash = (newHashMask - 2); 87e24f450bSmrg for (int i = 0; i < hashSize; i++) { 88e24f450bSmrg if (hashTable[i]) { 89eb323118Smrg unsigned h = (hashTable[i]->hash) & newHashMask; 90e24f450bSmrg if (newHashTable[h]) { 91eb323118Smrg unsigned r = hashTable[i]->hash % newRehash | 1; 92e24f450bSmrg do { 93e24f450bSmrg h += r; 94e24f450bSmrg if (h >= newHashSize) 95e24f450bSmrg h -= newHashSize; 96e24f450bSmrg } while (newHashTable[h]); 97e24f450bSmrg } 98e24f450bSmrg newHashTable[h] = hashTable[i]; 99e24f450bSmrg } 100fa2b3b63Smrg } 101e24f450bSmrg free(hashTable); 102fa2b3b63Smrg hashTable = newHashTable; 103fa2b3b63Smrg hashSize = newHashSize; 104fa2b3b63Smrg hashMask = newHashMask; 105fa2b3b63Smrg rehash = newRehash; 106fa2b3b63Smrg return TRUE; 107fa2b3b63Smrg} 108fa2b3b63Smrg 109fa2b3b63Smrgstatic int 110e24f450bSmrgResizeReverseMap(void) 111fa2b3b63Smrg{ 112fa2b3b63Smrg AtomListPtr *newMap; 113e24f450bSmrg size_t newMapSize; 114fa2b3b63Smrg 115fa2b3b63Smrg if (reverseMapSize == 0) 116e24f450bSmrg newMapSize = 1000; 117fa2b3b63Smrg else 118e24f450bSmrg newMapSize = reverseMapSize * 2; 119e24f450bSmrg newMap = realloc(reverseMap, newMapSize * sizeof(AtomListPtr)); 120fa2b3b63Smrg if (newMap == NULL) { 121e24f450bSmrg fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate" 122e24f450bSmrg " reverseMap (%ld)\n", 123e24f450bSmrg newMapSize * (unsigned long) sizeof(AtomListPtr)); 124e24f450bSmrg return FALSE; 125fa2b3b63Smrg } 126fa2b3b63Smrg reverseMap = newMap; 127fa2b3b63Smrg reverseMapSize = newMapSize; 128fa2b3b63Smrg return TRUE; 129fa2b3b63Smrg} 130fa2b3b63Smrg 131fa2b3b63Smrgstatic int 132e24f450bSmrgNameEqual(const char *a, const char *b, int l) 133fa2b3b63Smrg{ 134fa2b3b63Smrg while (l--) 135e24f450bSmrg if (*a++ != *b++) 136e24f450bSmrg return FALSE; 137fa2b3b63Smrg return TRUE; 138fa2b3b63Smrg} 139fa2b3b63Smrg 140e24f450bSmrgAtom 141fa2b3b63SmrgMakeAtom(const char *string, unsigned len, int makeit) 142fa2b3b63Smrg{ 143e24f450bSmrg AtomListPtr a; 144eb323118Smrg unsigned hash; 145eb323118Smrg unsigned h = 0; 146eb323118Smrg unsigned r; 147e24f450bSmrg 148e24f450bSmrg hash = Hash(string, len); 149e24f450bSmrg if (hashTable) { 150e24f450bSmrg h = hash & hashMask; 151e24f450bSmrg if (hashTable[h]) { 152e24f450bSmrg if (hashTable[h]->hash == hash && hashTable[h]->len == len && 153e24f450bSmrg NameEqual(hashTable[h]->name, string, len)) { 154e24f450bSmrg return hashTable[h]->atom; 155e24f450bSmrg } 156e24f450bSmrg r = (hash % rehash) | 1; 157e24f450bSmrg for (;;) { 158e24f450bSmrg h += r; 159e24f450bSmrg if (h >= hashSize) 160e24f450bSmrg h -= hashSize; 161e24f450bSmrg if (!hashTable[h]) 162e24f450bSmrg break; 163e24f450bSmrg if (hashTable[h]->hash == hash && hashTable[h]->len == len && 164e24f450bSmrg NameEqual(hashTable[h]->name, string, len)) { 165e24f450bSmrg return hashTable[h]->atom; 166e24f450bSmrg } 167e24f450bSmrg } 168e24f450bSmrg } 169fa2b3b63Smrg } 170fa2b3b63Smrg if (!makeit) 171e24f450bSmrg return None; 172e24f450bSmrg a = malloc(sizeof(AtomListRec) + len + 1); 173fa2b3b63Smrg if (a == NULL) { 174e24f450bSmrg fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec" 175e24f450bSmrg " (%ld)\n", (unsigned long) sizeof(AtomListRec) + len + 1); 176e24f450bSmrg return None; 177fa2b3b63Smrg } 178fa2b3b63Smrg a->name = (char *) (a + 1); 179fa2b3b63Smrg a->len = len; 180e24f450bSmrg strncpy(a->name, string, len); 181fa2b3b63Smrg a->name[len] = '\0'; 182fa2b3b63Smrg a->atom = ++lastAtom; 183fa2b3b63Smrg a->hash = hash; 184e24f450bSmrg if (hashUsed >= hashSize / 2) { 185e24f450bSmrg ResizeHashTable(); 186e24f450bSmrg h = hash & hashMask; 187e24f450bSmrg if (hashTable[h]) { 188e24f450bSmrg r = (hash % rehash) | 1; 189e24f450bSmrg do { 190e24f450bSmrg h += r; 191e24f450bSmrg if (h >= hashSize) 192e24f450bSmrg h -= hashSize; 193e24f450bSmrg } while (hashTable[h]); 194e24f450bSmrg } 195fa2b3b63Smrg } 196fa2b3b63Smrg hashTable[h] = a; 197fa2b3b63Smrg hashUsed++; 198fa2b3b63Smrg if (reverseMapSize <= a->atom) { 199e24f450bSmrg if (!ResizeReverseMap()) 200e24f450bSmrg return None; 201fa2b3b63Smrg } 202fa2b3b63Smrg reverseMap[a->atom] = a; 203fa2b3b63Smrg return a->atom; 204fa2b3b63Smrg} 205fa2b3b63Smrg 206e24f450bSmrgchar * 207fa2b3b63SmrgNameForAtom(Atom atom) 208fa2b3b63Smrg{ 209fa2b3b63Smrg if (atom != None && atom <= lastAtom) 210e24f450bSmrg return reverseMap[atom]->name; 211fa2b3b63Smrg return NULL; 212fa2b3b63Smrg} 213