| /******************************************************************************* | |
| * | |
| * 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. | |
| * | |
| * Copyright 2001 Ian Pilcher | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #include <string.h> | |
| #include "psdrv.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(psdrv); | |
| #define GLYPHLIST_ALLOCSIZE 1024 | |
| static GLYPHNAME **glyphList = NULL; | |
| static INT glyphListSize = 0; | |
| static BOOL glyphNamesIndexed = TRUE; | |
| /******************************************************************************* | |
| * 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) | |
| * | |
| */ | |
| 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; | |
| glyphNamesIndexed = FALSE; | |
| #if 0 | |
| TRACE("Added '%s' at glyphList[%i] (glyphListSize now %i)\n", | |
| glyphList[index]->sz, index, glyphListSize); | |
| #endif | |
| 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) | |
| { | |
| #if 0 | |
| TRACE("Found '%s' at glyphList[%i]\n", glyphList[midIndex]->sz, | |
| midIndex); | |
| #endif | |
| 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) | |
| * | |
| */ | |
| const GLYPHNAME *PSDRV_GlyphName(LPCSTR szName) | |
| { | |
| INT index; | |
| 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; | |
| if (glyphNamesIndexed == TRUE) | |
| return; | |
| TRACE("%i glyph names:\n", glyphListSize); | |
| for (i = 0; i < glyphListSize; ++i) | |
| { | |
| glyphList[i]->index = i; | |
| #if 0 | |
| TRACE(" glyphList[%i] -> '%s'\n", i, glyphList[i]->sz); | |
| #endif | |
| } | |
| glyphNamesIndexed = TRUE; | |
| } |