#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/fonts/fontmisc.h>
#include <X11/fonts/fontstruct.h>
#define NBUCKETS 16
#define NENTRIES 64
#define UNSET (NENTRIES+1)
typedef unsigned char EntryPtr;
typedef struct _FontPatternCacheEntry {
struct _FontPatternCacheEntry *next, **prev;
short patlen;
char *pattern;
int hash;
FontPtr pFont;
} FontPatternCacheEntryRec, *FontPatternCacheEntryPtr;
typedef struct _FontPatternCache {
FontPatternCacheEntryPtr buckets[NBUCKETS];
FontPatternCacheEntryRec entries[NENTRIES];
FontPatternCacheEntryPtr free;
} FontPatternCacheRec;
void
EmptyFontPatternCache (FontPatternCachePtr cache)
{
int i;
for (i = 0; i < NBUCKETS; i++)
cache->buckets[i] = 0;
for (i = 0; i < NENTRIES; i++)
{
cache->entries[i].next = &cache->entries[i+1];
cache->entries[i].prev = 0;
cache->entries[i].pFont = 0;
free (cache->entries[i].pattern);
cache->entries[i].pattern = 0;
cache->entries[i].patlen = 0;
}
cache->free = &cache->entries[0];
cache->entries[NENTRIES - 1].next = 0;
}
FontPatternCachePtr
MakeFontPatternCache (void)
{
FontPatternCachePtr cache;
int i;
cache = malloc (sizeof *cache);
if (!cache)
return 0;
for (i = 0; i < NENTRIES; i++) {
cache->entries[i].patlen = 0;
cache->entries[i].pattern = 0;
cache->entries[i].pFont = 0;
}
EmptyFontPatternCache (cache);
return cache;
}
void
FreeFontPatternCache (FontPatternCachePtr cache)
{
int i;
for (i = 0; i < NENTRIES; i++)
free (cache->entries[i].pattern);
free (cache);
}
static int
Hash (const char *string, int len)
{
int hash;
hash = 0;
while (len--)
hash = (hash << 1) ^ *string++;
if (hash < 0)
hash = -hash;
return hash;
}
void
CacheFontPattern (FontPatternCachePtr cache,
char *pattern,
int patlen,
FontPtr pFont)
{
FontPatternCacheEntryPtr e;
char *newpat;
int i;
newpat = malloc (patlen);
if (!newpat)
return;
if (cache->free)
{
e = cache->free;
cache->free = e->next;
}
else
{
i = rand ();
if (i < 0)
i = -i;
i %= NENTRIES;
e = &cache->entries[i];
if (e->next)
e->next->prev = e->prev;
*e->prev = e->next;
free (e->pattern);
}
memcpy (newpat, pattern, patlen);
e->pattern = newpat;
e->patlen = patlen;
e->hash = Hash (pattern, patlen);
i = e->hash % NBUCKETS;
e->next = cache->buckets[i];
if (e->next)
e->next->prev = &(e->next);
cache->buckets[i] = e;
e->prev = &(cache->buckets[i]);
e->pFont = pFont;
}
FontPtr
FindCachedFontPattern (FontPatternCachePtr cache,
char *pattern,
int patlen)
{
int hash;
int i;
FontPatternCacheEntryPtr e;
hash = Hash (pattern, patlen);
i = hash % NBUCKETS;
for (e = cache->buckets[i]; e; e = e->next)
{
if (e->patlen == patlen && e->hash == hash &&
!memcmp (e->pattern, pattern, patlen))
{
return e->pFont;
}
}
return 0;
}
void
RemoveCachedFontPattern (FontPatternCachePtr cache,
FontPtr pFont)
{
FontPatternCacheEntryPtr e;
int i;
for (i = 0; i < NENTRIES; i++)
{
if ((e = &cache->entries[i])->pFont == pFont)
{
e->pFont = 0;
if (e->next)
e->next->prev = e->prev;
*e->prev = e->next;
e->next = cache->free;
cache->free = e;
free (e->pattern);
e->pattern = 0;
}
}
}