atom.c revision 6a46240f
11b18d63aSmrg/*
2317c648bSmrg
3317c648bSmrg  Copyright 1990, 1994, 1998  The Open Group
4317c648bSmrg
5317c648bSmrg  Permission to use, copy, modify, distribute, and sell this software and its
6317c648bSmrg  documentation for any purpose is hereby granted without fee, provided that
7317c648bSmrg  the above copyright notice appear in all copies and that both that
8317c648bSmrg  copyright notice and this permission notice appear in supporting
9317c648bSmrg  documentation.
10317c648bSmrg
11317c648bSmrg  The above copyright notice and this permission notice shall be included in
12317c648bSmrg  all copies or substantial portions of the Software.
13317c648bSmrg
14317c648bSmrg  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15317c648bSmrg  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16317c648bSmrg  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17317c648bSmrg  OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18317c648bSmrg  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19317c648bSmrg  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20317c648bSmrg
21317c648bSmrg  Except as contained in this notice, the name of The Open Group shall not be
22317c648bSmrg  used in advertising or otherwise to promote the sale, use or other dealings
23317c648bSmrg  in this Software without prior written authorization from The Open Group.
24317c648bSmrg
25317c648bSmrg*/
26317c648bSmrg
27317c648bSmrg/*
28317c648bSmrg * Author:  Keith Packard, MIT X Consortium
29317c648bSmrg */
30a450e446Smrg
31317c648bSmrg/* lame atom replacement routines for font applications */
32a450e446Smrg
33317c648bSmrg#ifdef HAVE_CONFIG_H
34317c648bSmrg#include <config.h>
35317c648bSmrg#endif
36317c648bSmrg#include "libxfontint.h"
371b18d63aSmrg#include "src/util/replace.h"
381b18d63aSmrg#include <X11/fonts/fontmisc.h>
391b18d63aSmrg
401b18d63aSmrgtypedef struct _AtomList {
411b18d63aSmrg    char *name;
421b18d63aSmrg    int len;
431b18d63aSmrg    int hash;
441b18d63aSmrg    Atom atom;
451b18d63aSmrg} AtomListRec, *AtomListPtr;
461b18d63aSmrg
471b18d63aSmrgstatic AtomListPtr *hashTable;
481b18d63aSmrg
491b18d63aSmrgstatic unsigned hashSize, hashUsed;
501b18d63aSmrgstatic unsigned hashMask;
511b18d63aSmrgstatic unsigned rehash;
521b18d63aSmrg
531b18d63aSmrgstatic AtomListPtr *reverseMap;
541b18d63aSmrgstatic int reverseMapSize;
551b18d63aSmrgstatic Atom lastAtom;
561b18d63aSmrg
571b18d63aSmrgstatic unsigned
581b18d63aSmrgHash(const char *string, unsigned len)
591b18d63aSmrg{
601b18d63aSmrg    unsigned h = 0;
611b18d63aSmrg
621b18d63aSmrg    while (len--)
631b18d63aSmrg        h = (h << 3) ^ *string++;
641b18d63aSmrg
651b18d63aSmrg    return h;
661b18d63aSmrg}
671b18d63aSmrg
681b18d63aSmrgstatic int
691b18d63aSmrgResizeHashTable(void)
701b18d63aSmrg{
711b18d63aSmrg    unsigned newHashSize;
721b18d63aSmrg    unsigned newHashMask;
731b18d63aSmrg    AtomListPtr *newHashTable;
741b18d63aSmrg    unsigned i;
751b18d63aSmrg    unsigned h;
761b18d63aSmrg    unsigned newRehash;
771b18d63aSmrg    unsigned r;
781b18d63aSmrg
791b18d63aSmrg    if (hashSize == 0)
801b18d63aSmrg        newHashSize = 1024;
811b18d63aSmrg    else
821b18d63aSmrg        newHashSize = hashSize * 2;
831b18d63aSmrg    newHashTable = calloc(newHashSize, sizeof(AtomListPtr));
841b18d63aSmrg    if (!newHashTable) {
851b18d63aSmrg        fprintf(stderr, "ResizeHashTable(): Error: Couldn't allocate"
861b18d63aSmrg                " newHashTable (%ld)\n",
871b18d63aSmrg                newHashSize * (unsigned long) sizeof(AtomListPtr));
881b18d63aSmrg        return FALSE;
891b18d63aSmrg    }
901b18d63aSmrg    newHashMask = newHashSize - 1;
911b18d63aSmrg    newRehash = (newHashMask - 2);
921b18d63aSmrg    for (i = 0; i < hashSize; i++) {
931b18d63aSmrg        if (hashTable[i]) {
941b18d63aSmrg            h = (hashTable[i]->hash) & newHashMask;
951b18d63aSmrg            if (newHashTable[h]) {
961b18d63aSmrg                r = hashTable[i]->hash % newRehash | 1;
971b18d63aSmrg                do {
981b18d63aSmrg                    h += r;
99953d7d37Smrg                    if (h >= newHashSize)
100953d7d37Smrg                        h -= newHashSize;
101953d7d37Smrg                } while (newHashTable[h]);
102953d7d37Smrg            }
103953d7d37Smrg            newHashTable[h] = hashTable[i];
104953d7d37Smrg        }
105953d7d37Smrg    }
106953d7d37Smrg    free(hashTable);
107953d7d37Smrg    hashTable = newHashTable;
108953d7d37Smrg    hashSize = newHashSize;
109953d7d37Smrg    hashMask = newHashMask;
110953d7d37Smrg    rehash = newRehash;
111953d7d37Smrg    return TRUE;
112953d7d37Smrg}
113953d7d37Smrg
114953d7d37Smrgstatic int
115953d7d37SmrgResizeReverseMap(void)
116953d7d37Smrg{
1171b18d63aSmrg    AtomListPtr *newMap;
1181b18d63aSmrg    int newMapSize;
1191b18d63aSmrg
1201b18d63aSmrg    if (reverseMapSize == 0)
1211b18d63aSmrg        newMapSize = 1000;
1221b18d63aSmrg    else
1231b18d63aSmrg        newMapSize = reverseMapSize * 2;
1241b18d63aSmrg    newMap = reallocarray(reverseMap, newMapSize, sizeof(AtomListPtr));
1251b18d63aSmrg    if (newMap == NULL) {
1261b18d63aSmrg        fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate"
1271b18d63aSmrg                " reverseMap (%ld)\n",
1281b18d63aSmrg                newMapSize * (unsigned long) sizeof(AtomListPtr));
1291b18d63aSmrg        return FALSE;
1301b18d63aSmrg    }
1311b18d63aSmrg    reverseMap = newMap;
1321b18d63aSmrg    reverseMapSize = newMapSize;
1331b18d63aSmrg    return TRUE;
1341b18d63aSmrg}
1351b18d63aSmrg
1361b18d63aSmrgstatic int
1371b18d63aSmrgNameEqual(const char *a, const char *b, int l)
1381b18d63aSmrg{
1391b18d63aSmrg    while (l--)
1401b18d63aSmrg        if (*a++ != *b++)
1411b18d63aSmrg            return FALSE;
1421b18d63aSmrg    return TRUE;
1431b18d63aSmrg}
1441b18d63aSmrg
1451b18d63aSmrgAtom
1461b18d63aSmrg__libxfont_internal__MakeAtom(const char *string, unsigned len, int makeit)
147953d7d37Smrg{
148953d7d37Smrg    AtomListPtr a;
149317c648bSmrg    unsigned hash;
150317c648bSmrg    unsigned h = 0;
1511b18d63aSmrg    unsigned r;
1521b18d63aSmrg
1531b18d63aSmrg    hash = Hash(string, len);
1541b18d63aSmrg    if (hashTable) {
155317c648bSmrg        h = hash & hashMask;
1561b18d63aSmrg        if (hashTable[h]) {
157317c648bSmrg            if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
1581b18d63aSmrg                NameEqual(hashTable[h]->name, string, len)) {
159317c648bSmrg                return hashTable[h]->atom;
1601b18d63aSmrg            }
161317c648bSmrg            r = (hash % rehash) | 1;
1621b18d63aSmrg            for (;;) {
1631b18d63aSmrg                h += r;
1641b18d63aSmrg                if (h >= hashSize)
1651b18d63aSmrg                    h -= hashSize;
1661b18d63aSmrg                if (!hashTable[h])
1671b18d63aSmrg                    break;
168317c648bSmrg                if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
1691b18d63aSmrg                    NameEqual(hashTable[h]->name, string, len)) {
1701b18d63aSmrg                    return hashTable[h]->atom;
1711b18d63aSmrg                }
172317c648bSmrg            }
1731b18d63aSmrg        }
1741b18d63aSmrg    }
1751b18d63aSmrg    if (!makeit)
1761b18d63aSmrg        return None;
177317c648bSmrg    a = malloc(sizeof(AtomListRec) + len + 1);
1781b18d63aSmrg    if (a == NULL) {
1791b18d63aSmrg        fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec"
180317c648bSmrg                " (%ld)\n", (unsigned long) sizeof(AtomListRec) + len + 1);
1811b18d63aSmrg        return None;
1821b18d63aSmrg    }
1831b18d63aSmrg    a->name = (char *) (a + 1);
1841b18d63aSmrg    a->len = len;
185317c648bSmrg    strncpy(a->name, string, len);
1861b18d63aSmrg    a->name[len] = '\0';
1871b18d63aSmrg    a->atom = ++lastAtom;
1881b18d63aSmrg    a->hash = hash;
1891b18d63aSmrg    if (hashUsed >= hashSize / 2) {
190317c648bSmrg        if ((ResizeHashTable() == FALSE) &&
1911b18d63aSmrg	    ((hashTable == NULL) || (hashUsed == hashSize))) {
192317c648bSmrg	    free(a);
1931b18d63aSmrg	    return None;
194317c648bSmrg        }
1951b18d63aSmrg        h = hash & hashMask;
196317c648bSmrg        if (hashTable[h]) {
1971b18d63aSmrg            r = (hash % rehash) | 1;
198317c648bSmrg            do {
1991b18d63aSmrg                h += r;
200317c648bSmrg                if (h >= hashSize)
2011b18d63aSmrg                    h -= hashSize;
202317c648bSmrg            } while (hashTable[h]);
2031b18d63aSmrg        }
204317c648bSmrg    }
2051b18d63aSmrg    hashTable[h] = a;
2061b18d63aSmrg    hashUsed++;
207317c648bSmrg    if (reverseMapSize <= a->atom) {
2081b18d63aSmrg        if (!ResizeReverseMap())
2091b18d63aSmrg            return None;
210317c648bSmrg    }
2111b18d63aSmrg    reverseMap[a->atom] = a;
2121b18d63aSmrg    return a->atom;
2131b18d63aSmrg}
2141b18d63aSmrg
2151b18d63aSmrgint
2161b18d63aSmrg__libxfont_internal__ValidAtom(Atom atom)
217317c648bSmrg{
2181b18d63aSmrg    return (atom != None) && (atom <= lastAtom);
219317c648bSmrg}
2201b18d63aSmrg
2211b18d63aSmrgconst char *
2221b18d63aSmrg__libxfont_internal__NameForAtom(Atom atom)
223317c648bSmrg{
2241b18d63aSmrg    if (atom != None && atom <= lastAtom)
2251b18d63aSmrg        return reverseMap[atom]->name;
226317c648bSmrg    return NULL;
2271b18d63aSmrg}
2281b18d63aSmrg