#include "misc.h"
#include "util.h"
#include "wire.h"
#include "atomcache.h"
static int
Hash(string, len)
char *string;
int len;
{
int h;
h = 0;
while (len--)
h = (h << 3) ^ *string++;
if (h < 0)
return -h;
return h;
}
static Bool
ResizeHashTable(server)
XServerPtr server;
{
int newHashSize;
int newHashMask;
AtomListPtr *newHashTable;
int i;
int h;
int newRehash;
int r;
if (server->hashSize == 0)
newHashSize = 1024;
else
newHashSize = server->hashSize * 2;
newHashTable = (AtomListPtr *) xalloc(newHashSize * sizeof(AtomListPtr));
if (!newHashTable)
return FALSE;
bzero((char *) newHashTable, newHashSize * sizeof(AtomListPtr));
newHashMask = newHashSize - 1;
newRehash = (newHashMask - 2);
for (i = 0; i < server->hashSize; i++) {
if (server->hashTable[i]) {
h = (server->hashTable[i]->hash) & newHashMask;
if (newHashTable[h]) {
r = server->hashTable[i]->hash % newRehash | 1;
do {
h += r;
if (h >= newHashSize)
h -= newHashSize;
} while (newHashTable[h]);
}
newHashTable[h] = server->hashTable[i];
}
}
xfree(server->hashTable);
server->hashTable = newHashTable;
server->hashSize = newHashSize;
server->hashMask = newHashMask;
server->rehash = newRehash;
return TRUE;
}
static Bool
ResizeReverseMap(server, atom)
XServerPtr server;
Atom atom;
{
int oldMapSize = 0;
if (server->reverseMapSize <= 0)
server->reverseMapSize = 1000;
else
oldMapSize = server->reverseMapSize;
while (server->reverseMapSize < atom)
server->reverseMapSize *= 2;
server->reverseMap = (AtomListPtr *) xrealloc(server->reverseMap,
server->reverseMapSize * sizeof(AtomListPtr));
if (!server->reverseMap)
return FALSE;
bzero((char *) (server->reverseMap + oldMapSize),
((server->reverseMapSize - oldMapSize) * sizeof(AtomListPtr)));
return TRUE;
}
Atom
LbxMakeAtom(server, string, len, atom, makeit)
XServerPtr server;
char *string;
Atom atom;
unsigned len;
int makeit;
{
AtomListPtr a;
int hash;
int h = 0;
int r;
hash = Hash(string, len);
if (server->hashTable) {
h = hash & server->hashMask;
if (server->hashTable[h]) {
if (server->hashTable[h]->hash == hash &&
server->hashTable[h]->len == len &&
!strncmp(server->hashTable[h]->name, string, len)) {
return server->hashTable[h]->atom;
}
r = (hash % server->rehash) | 1;
for (;;) {
h += r;
if (h >= server->hashSize)
h -= server->hashSize;
if (!server->hashTable[h])
break;
if (server->hashTable[h]->hash == hash &&
server->hashTable[h]->len == len &&
!strncmp(server->hashTable[h]->name, string, len)) {
return server->hashTable[h]->atom;
}
}
}
}
if (!makeit)
return None;
a = (AtomListPtr) xalloc(sizeof(AtomListRec) + len + 1);
a->name = (char *) (a + 1);
a->len = len;
strncpy(a->name, string, len);
a->name[len] = '\0';
a->atom = atom;
if (atom > server->lastAtom)
server->lastAtom = atom;
a->hash = hash;
if (server->hashUsed >= server->hashSize / 2) {
ResizeHashTable(server);
h = hash & server->hashMask;
if (server->hashTable[h]) {
r = (hash % server->rehash) | 1;
do {
h += r;
if (h >= server->hashSize)
h -= server->hashSize;
} while (server->hashTable[h]);
}
}
server->hashTable[h] = a;
server->hashUsed++;
a->flags = 0;
for (r = 0; r < server->atom_control_count; r++) {
if (a->len == server->atom_control[r].len &&
!strncmp(a->name, server->atom_control[r].name, a->len)) {
a->flags = server->atom_control[r].flags;
break;
}
}
if (server->reverseMapSize <= a->atom)
ResizeReverseMap(server, a->atom);
server->reverseMap[a->atom] = a;
return a->atom;
}
char *
NameForAtom(server, atom)
XServerPtr server;
Atom atom;
{
if (atom != None && atom <= server->lastAtom && server->reverseMap[atom])
return server->reverseMap[atom]->name;
return 0;
}
unsigned
FlagsForAtom(server, atom)
XServerPtr server;
Atom atom;
{
if (atom != None && atom <= server->lastAtom && server->reverseMap[atom])
return server->reverseMap[atom]->flags;
return 0;
}
void
FreeAtoms()
{
int i;
for (i=0; i < lbxMaxServers; i++) {
if (servers[i]) {
if (servers[i]->reverseMap) {
for (i = 0; i <= servers[i]->lastAtom; i++)
xfree(servers[i]->reverseMap[i]);
xfree(servers[i]->reverseMap);
}
xfree(servers[i]->hashTable);
servers[i]->reverseMapSize = 0;
servers[i]->reverseMap = NULL;
servers[i]->hashTable = NULL;
servers[i]->lastAtom = 0;
servers[i]->hashSize = 0;
servers[i]->hashUsed = 0;
}
}
}