atom.c revision a96d7823
150806d53Smrg/*
250806d53Smrg
350806d53Smrg  Copyright 1990, 1994, 1998  The Open Group
4e9f7eabcSmrg
550806d53Smrg  Permission to use, copy, modify, distribute, and sell this software and its
650806d53Smrg  documentation for any purpose is hereby granted without fee, provided that
750806d53Smrg  the above copyright notice appear in all copies and that both that
850806d53Smrg  copyright notice and this permission notice appear in supporting
950806d53Smrg  documentation.
1050806d53Smrg
1150806d53Smrg  The above copyright notice and this permission notice shall be included in
1250806d53Smrg  all copies or substantial portions of the Software.
1350806d53Smrg
1450806d53Smrg  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1550806d53Smrg  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1650806d53Smrg  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1750806d53Smrg  OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1850806d53Smrg  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1950806d53Smrg  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2050806d53Smrg
2150806d53Smrg  Except as contained in this notice, the name of The Open Group shall not be
2250806d53Smrg  used in advertising or otherwise to promote the sale, use or other dealings
2350806d53Smrg  in this Software without prior written authorization from The Open Group.
2450806d53Smrg
2550806d53Smrg*/
2650806d53Smrg
2750806d53Smrg/*
2850806d53Smrg * Author:  Keith Packard, MIT X Consortium
2950806d53Smrg */
3050806d53Smrg
3150806d53Smrg/* lame atom replacement routines for font applications */
3250806d53Smrg
3350806d53Smrg#ifdef HAVE_CONFIG_H
3450806d53Smrg#include <config.h>
3550806d53Smrg#endif
3650806d53Smrg#include "libxfontint.h"
3750806d53Smrg#include <X11/fonts/fontmisc.h>
384a8d91dcSmrg
3950806d53Smrgtypedef struct _AtomList {
4050806d53Smrg    char *name;
4150806d53Smrg    int len;
427965d9acSmrg    int hash;
437965d9acSmrg    Atom atom;
444a8d91dcSmrg} AtomListRec, *AtomListPtr;
457965d9acSmrg
467965d9acSmrgstatic AtomListPtr *hashTable;
474a8d91dcSmrg
4850806d53Smrgstatic int hashSize, hashUsed;
494a8d91dcSmrgstatic int hashMask;
5050806d53Smrgstatic int rehash;
517965d9acSmrg
524a8d91dcSmrgstatic AtomListPtr *reverseMap;
5350806d53Smrgstatic int reverseMapSize;
547965d9acSmrgstatic Atom lastAtom;
557965d9acSmrg
567965d9acSmrgstatic int
577965d9acSmrgHash(const char *string, int len)
587965d9acSmrg{
597965d9acSmrg    int h;
607965d9acSmrg
617965d9acSmrg    h = 0;
627965d9acSmrg    while (len--)
637965d9acSmrg        h = (h << 3) ^ *string++;
647965d9acSmrg    if (h < 0)
657965d9acSmrg        return -h;
667965d9acSmrg    return h;
677965d9acSmrg}
687965d9acSmrg
697965d9acSmrgstatic int
707965d9acSmrgResizeHashTable(void)
7150806d53Smrg{
72e9f7eabcSmrg    int newHashSize;
73e9f7eabcSmrg    int newHashMask;
74e9f7eabcSmrg    AtomListPtr *newHashTable;
75e9f7eabcSmrg    int i;
76e9f7eabcSmrg    int h;
7750806d53Smrg    int newRehash;
787965d9acSmrg    int r;
797965d9acSmrg
807965d9acSmrg    if (hashSize == 0)
8150806d53Smrg        newHashSize = 1024;
827965d9acSmrg    else
837965d9acSmrg        newHashSize = hashSize * 2;
8450806d53Smrg    newHashTable = calloc(newHashSize, sizeof(AtomListPtr));
8550806d53Smrg    if (!newHashTable) {
8650806d53Smrg        fprintf(stderr, "ResizeHashTable(): Error: Couldn't allocate"
877965d9acSmrg                " newHashTable (%ld)\n",
887965d9acSmrg                newHashSize * (unsigned long) sizeof(AtomListPtr));
897965d9acSmrg        return FALSE;
904a8d91dcSmrg    }
9150806d53Smrg    newHashMask = newHashSize - 1;
927965d9acSmrg    newRehash = (newHashMask - 2);
937965d9acSmrg    for (i = 0; i < hashSize; i++) {
9450806d53Smrg        if (hashTable[i]) {
9550806d53Smrg            h = (hashTable[i]->hash) & newHashMask;
9650806d53Smrg            if (newHashTable[h]) {
9750806d53Smrg                r = hashTable[i]->hash % newRehash | 1;
9850806d53Smrg                do {
9950806d53Smrg                    h += r;
10050806d53Smrg                    if (h >= newHashSize)
10150806d53Smrg                        h -= newHashSize;
10250806d53Smrg                } while (newHashTable[h]);
1037965d9acSmrg            }
1047965d9acSmrg            newHashTable[h] = hashTable[i];
1057965d9acSmrg        }
1067965d9acSmrg    }
107e9f7eabcSmrg    free(hashTable);
1087965d9acSmrg    hashTable = newHashTable;
1097965d9acSmrg    hashSize = newHashSize;
1107965d9acSmrg    hashMask = newHashMask;
1117965d9acSmrg    rehash = newRehash;
112e9f7eabcSmrg    return TRUE;
1137965d9acSmrg}
114e9f7eabcSmrg
1157965d9acSmrgstatic int
1167965d9acSmrgResizeReverseMap(void)
11750806d53Smrg{
11850806d53Smrg    AtomListPtr *newMap;
1197965d9acSmrg    int newMapSize;
1207965d9acSmrg
121e9f7eabcSmrg    if (reverseMapSize == 0)
122e9f7eabcSmrg        newMapSize = 1000;
123e9f7eabcSmrg    else
124e9f7eabcSmrg        newMapSize = reverseMapSize * 2;
125e9f7eabcSmrg    newMap = realloc(reverseMap, newMapSize * sizeof(AtomListPtr));
126e9f7eabcSmrg    if (newMap == NULL) {
127e9f7eabcSmrg        fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate"
128e9f7eabcSmrg                " reverseMap (%ld)\n",
12950806d53Smrg                newMapSize * (unsigned long) sizeof(AtomListPtr));
13050806d53Smrg        return FALSE;
1317965d9acSmrg    }
13250806d53Smrg    reverseMap = newMap;
1337965d9acSmrg    reverseMapSize = newMapSize;
1347965d9acSmrg    return TRUE;
1357965d9acSmrg}
13650806d53Smrg
1377965d9acSmrgstatic int
13850806d53SmrgNameEqual(const char *a, const char *b, int l)
13950806d53Smrg{
1404a8d91dcSmrg    while (l--)
14150806d53Smrg        if (*a++ != *b++)
14250806d53Smrg            return FALSE;
14350806d53Smrg    return TRUE;
1447965d9acSmrg}
1454a8d91dcSmrg
1464a8d91dcSmrgAtom
1474a8d91dcSmrg__libxfont_internal__MakeAtom(const char *string, unsigned len, int makeit)
1484a8d91dcSmrg{
1494a8d91dcSmrg    AtomListPtr a;
1504a8d91dcSmrg    int hash;
15150806d53Smrg    int h = 0;
15250806d53Smrg    int r;
1534a8d91dcSmrg
15450806d53Smrg    hash = Hash(string, len);
155e9f7eabcSmrg    if (hashTable) {
156e9f7eabcSmrg        h = hash & hashMask;
1577965d9acSmrg        if (hashTable[h]) {
15850806d53Smrg            if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
159e9f7eabcSmrg                NameEqual(hashTable[h]->name, string, len)) {
160e9f7eabcSmrg                return hashTable[h]->atom;
161e9f7eabcSmrg            }
1624a8d91dcSmrg            r = (hash % rehash) | 1;
1634a8d91dcSmrg            for (;;) {
1644a8d91dcSmrg                h += r;
1654a8d91dcSmrg                if (h >= hashSize)
1664a8d91dcSmrg                    h -= hashSize;
1674a8d91dcSmrg                if (!hashTable[h])
1684a8d91dcSmrg                    break;
1694a8d91dcSmrg                if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
17050806d53Smrg                    NameEqual(hashTable[h]->name, string, len)) {
1714a8d91dcSmrg                    return hashTable[h]->atom;
17250806d53Smrg                }
17350806d53Smrg            }
17450806d53Smrg        }
1754a8d91dcSmrg    }
1764a8d91dcSmrg    if (!makeit)
1777965d9acSmrg        return None;
1784a8d91dcSmrg    a = malloc(sizeof(AtomListRec) + len + 1);
1794a8d91dcSmrg    if (a == NULL) {
1807965d9acSmrg        fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec"
1817965d9acSmrg                " (%ld)\n", (unsigned long) sizeof(AtomListRec) + len + 1);
18250806d53Smrg        return None;
1837965d9acSmrg    }
18450806d53Smrg    a->name = (char *) (a + 1);
18550806d53Smrg    a->len = len;
1864a8d91dcSmrg    strncpy(a->name, string, len);
1874a8d91dcSmrg    a->name[len] = '\0';
1884a8d91dcSmrg    a->atom = ++lastAtom;
1894a8d91dcSmrg    a->hash = hash;
1904a8d91dcSmrg    if (hashUsed >= hashSize / 2) {
1914a8d91dcSmrg        ResizeHashTable();
1924a8d91dcSmrg        h = hash & hashMask;
1934a8d91dcSmrg        if (hashTable[h]) {
1944a8d91dcSmrg            r = (hash % rehash) | 1;
1954a8d91dcSmrg            do {
1967965d9acSmrg                h += r;
1977965d9acSmrg                if (h >= hashSize)
1987965d9acSmrg                    h -= hashSize;
1997965d9acSmrg            } while (hashTable[h]);
2007965d9acSmrg        }
2017965d9acSmrg    }
2027965d9acSmrg    hashTable[h] = a;
2037965d9acSmrg    hashUsed++;
2047965d9acSmrg    if (reverseMapSize <= a->atom) {
2057965d9acSmrg        if (!ResizeReverseMap())
2067965d9acSmrg            return None;
2077965d9acSmrg    }
2087965d9acSmrg    reverseMap[a->atom] = a;
2094a8d91dcSmrg    return a->atom;
210a73423d7Smrg}
211a73423d7Smrg
212a73423d7Smrgint
2137965d9acSmrg__libxfont_internal__ValidAtom(Atom atom)
2147965d9acSmrg{
2157965d9acSmrg    return (atom != None) && (atom <= lastAtom);
2167965d9acSmrg}
21750806d53Smrg
21850806d53Smrgconst char *
21950806d53Smrg__libxfont_internal__NameForAtom(Atom atom)
22050806d53Smrg{
2214a8d91dcSmrg    if (atom != None && atom <= lastAtom)
22250806d53Smrg        return reverseMap[atom]->name;
22350806d53Smrg    return NULL;
22450806d53Smrg}
22550806d53Smrg