|  | /******************************************************************************* | 
|  | * | 
|  | *	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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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(void) | 
|  | { | 
|  | 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) 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) | 
|  | * | 
|  | */ | 
|  | static inline INT GlyphListInsert(LPCSTR szName, INT index) | 
|  | { | 
|  | GLYPHNAME *g; | 
|  |  | 
|  | g = HeapAlloc(PSDRV_Heap, 0, sizeof(GLYPHNAME) + strlen(szName) + 1); | 
|  | if (g == NULL) 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) | 
|  | { | 
|  | 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(void) | 
|  | { | 
|  | 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; | 
|  | } |