/******************************************************************************* * * 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 = 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 = 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) 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; }