| /******************************************************************************* | |
| * | |
| * Functions and data structures used to maintain a single list of glyph | |
| * names. The list is sorted alphabetically and each name appears only | |
| * once. After all font information has been read, the 'index' field of | |
| * each GLYPHNAME structure is initialized, so future sorts/searches can | |
| * be done without comparing strings. | |
| * | |
| */ | |
| #include <string.h> | |
| #include "psdrv.h" | |
| #include "debugtools.h" | |
| DEFAULT_DEBUG_CHANNEL(psdrv); | |
| #define GLYPHLIST_ALLOCSIZE 1024 | |
| static GLYPHNAME **glyphList = NULL; | |
| static INT glyphListSize = 0; | |
| /******************************************************************************* | |
| * PSDRV_GlyphListInit | |
| * | |
| * Allocates initial block of memory for the glyph list and copies pointers to | |
| * the AGL glyph names into it; returns 0 on success, 1 on failure | |
| * | |
| */ | |
| INT PSDRV_GlyphListInit() | |
| { | |
| INT i; | |
| /* | |
| * Compute the smallest multiple of GLYPHLIST_ALLOCSIZE that is | |
| * greater than or equal to PSDRV_AGLGlyphNamesSize | |
| * | |
| */ | |
| glyphListSize = PSDRV_AGLGlyphNamesSize; | |
| i = ((glyphListSize + GLYPHLIST_ALLOCSIZE - 1) / GLYPHLIST_ALLOCSIZE) * | |
| GLYPHLIST_ALLOCSIZE; | |
| TRACE("glyphList will initially hold %i glyph names\n", i); | |
| glyphList = (GLYPHNAME **) HeapAlloc(PSDRV_Heap, 0, | |
| i * sizeof(GLYPHNAME *)); | |
| if (glyphList == NULL) | |
| { | |
| ERR("Failed to allocate %i bytes of memory\n", i * sizeof(GLYPHNAME *)); | |
| return 1; | |
| } | |
| for (i = 0; i < glyphListSize; ++i) | |
| glyphList[i] = PSDRV_AGLGlyphNames + i; | |
| return 0; | |
| } | |
| /******************************************************************************* | |
| * GlyphListInsert | |
| * | |
| * Inserts a copy of the glyph name into the list at the index, growing the | |
| * list if necessary; returns index on success (-1 on failure) | |
| * | |
| * _glyphname is a version of GLYPHNAME with non-constant members, so it can | |
| * be initialized without generating compiler warnings | |
| * | |
| */ | |
| inline static INT GlyphListInsert(LPCSTR szName, INT index) | |
| { | |
| GLYPHNAME *g; | |
| g = HeapAlloc(PSDRV_Heap, 0, sizeof(GLYPHNAME) + strlen(szName) + 1); | |
| if (g == NULL) | |
| { | |
| ERR("Failed to allocate %i bytes of memory\n", | |
| sizeof(GLYPHNAME) + strlen(szName) + 1); | |
| return -1; | |
| } | |
| g->index = -1; | |
| g->sz = (LPSTR)(g + 1); | |
| strcpy((LPSTR)g->sz, szName); | |
| if (glyphListSize % GLYPHLIST_ALLOCSIZE == 0) /* grow the list? */ | |
| { | |
| GLYPHNAME **newGlyphList; | |
| newGlyphList = (GLYPHNAME **) HeapReAlloc(PSDRV_Heap, 0, glyphList, | |
| (glyphListSize + GLYPHLIST_ALLOCSIZE) * sizeof(GLYPHNAME *)); | |
| if (newGlyphList == NULL) | |
| { | |
| ERR("Failed to allocate %i bytes of memory\n", (glyphListSize + | |
| GLYPHLIST_ALLOCSIZE) * sizeof (GLYPHNAME *)); | |
| HeapFree(PSDRV_Heap, 0, g); | |
| return -1; | |
| } | |
| glyphList = newGlyphList; | |
| TRACE("glyphList will now hold %i glyph names\n", | |
| glyphListSize + GLYPHLIST_ALLOCSIZE); | |
| } | |
| if (index < glyphListSize) | |
| { | |
| memmove(glyphList + (index + 1), glyphList + index, | |
| (glyphListSize - index) * sizeof(GLYPHNAME *)); | |
| } | |
| glyphList[index] = g; | |
| ++glyphListSize; | |
| TRACE("Added '%s' at glyphList[%i] (glyphListSize now %i)\n", | |
| glyphList[index]->sz, index, glyphListSize); | |
| return index; | |
| } | |
| /******************************************************************************* | |
| * GlyphListSearch | |
| * | |
| * Searches the specified portion of the list for the glyph name and inserts it | |
| * in the list if necessary; returns the index at which the name (now) resides | |
| * (-1 if unable to insert it) | |
| * | |
| */ | |
| static INT GlyphListSearch(LPCSTR szName, INT loIndex, INT hiIndex) | |
| { | |
| INT midIndex, cmpResult; | |
| while (1) | |
| { | |
| if (loIndex > hiIndex) | |
| return GlyphListInsert(szName, loIndex); | |
| midIndex = (loIndex + hiIndex) >> 1; | |
| cmpResult = strcmp(szName, glyphList[midIndex]->sz); | |
| if (cmpResult == 0) | |
| { | |
| TRACE("Found '%s' at glyphList[%i]\n", glyphList[midIndex]->sz, | |
| midIndex); | |
| return midIndex; | |
| } | |
| if (cmpResult < 0) | |
| hiIndex = midIndex - 1; | |
| else | |
| loIndex = midIndex + 1; | |
| } | |
| } | |
| /******************************************************************************* | |
| * PSDRV_GlyphName | |
| * | |
| * Searches the glyph name list for the provided name, adds it to the list if | |
| * necessary, and returns a pointer to it (NULL if unable to add it) | |
| * | |
| */ | |
| GLYPHNAME *PSDRV_GlyphName(LPCSTR szName) | |
| { | |
| INT index; | |
| TRACE("'%s'\n", szName); | |
| index = GlyphListSearch(szName, 0, glyphListSize - 1); | |
| if (index < 0) | |
| return NULL; | |
| return glyphList[index]; | |
| } | |
| /******************************************************************************* | |
| * PSDRV_IndexGlyphList | |
| * | |
| * Initializes index member of all GLYPHNAME structures | |
| * | |
| */ | |
| VOID PSDRV_IndexGlyphList() | |
| { | |
| INT i; | |
| TRACE("%i glyph names:\n", glyphListSize); | |
| for (i = 0; i < glyphListSize; ++i) | |
| { | |
| glyphList[i]->index = i; | |
| TRACE(" glyphList[%i] -> '%s'\n", i, glyphList[i]->sz); | |
| } | |
| } |