Add an assert if both arguments to DD_STRUCT_COPY_BYSIZE are equal.
[wine] / dlls / wineps / glyphlist.c
1 /*******************************************************************************
2  *
3  *      Functions and data structures used to maintain a single list of glyph
4  *      names.  The list is sorted alphabetically and each name appears only
5  *      once.  After all font information has been read, the 'index' field of
6  *      each GLYPHNAME structure is initialized, so future sorts/searches can
7  *      be done without comparing strings.
8  *
9  * Copyright 2001 Ian Pilcher
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #include <string.h>
27 #include "psdrv.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
31
32 #define GLYPHLIST_ALLOCSIZE     1024
33
34 static GLYPHNAME    **glyphList = NULL;
35 static INT          glyphListSize = 0;
36 static BOOL         glyphNamesIndexed = TRUE;
37
38 /*******************************************************************************
39  *      PSDRV_GlyphListInit
40  *
41  *  Allocates initial block of memory for the glyph list and copies pointers to
42  *  the AGL glyph names into it; returns 0 on success, 1 on failure
43  *
44  */
45 INT PSDRV_GlyphListInit()
46 {
47     INT i;
48
49     /*
50      *  Compute the smallest multiple of GLYPHLIST_ALLOCSIZE that is
51      *  greater than or equal to PSDRV_AGLGlyphNamesSize
52      *
53      */
54     glyphListSize = PSDRV_AGLGlyphNamesSize;
55     i = ((glyphListSize + GLYPHLIST_ALLOCSIZE - 1) / GLYPHLIST_ALLOCSIZE) *
56             GLYPHLIST_ALLOCSIZE;
57
58     TRACE("glyphList will initially hold %i glyph names\n", i);
59
60     glyphList = HeapAlloc(PSDRV_Heap, 0, i * sizeof(GLYPHNAME *));
61     if (glyphList == NULL)
62     {
63         ERR("Failed to allocate %i bytes of memory\n", i * sizeof(GLYPHNAME *));
64         return 1;
65     }
66
67     for (i = 0; i < glyphListSize; ++i)
68         glyphList[i] = PSDRV_AGLGlyphNames + i;
69
70     return 0;
71 }
72
73 /*******************************************************************************
74  *      GlyphListInsert
75  *
76  *  Inserts a copy of the  glyph name into the list at the index, growing the
77  *  list if necessary; returns index on success (-1 on failure)
78  *
79  */
80 inline static INT GlyphListInsert(LPCSTR szName, INT index)
81 {
82     GLYPHNAME *g;
83
84     g = HeapAlloc(PSDRV_Heap, 0, sizeof(GLYPHNAME) + strlen(szName) + 1);
85     if (g == NULL)
86     {
87         ERR("Failed to allocate %i bytes of memory\n",
88                 sizeof(GLYPHNAME) + strlen(szName) + 1);
89         return -1;
90     }
91
92     g->index = -1;
93     g->sz = (LPSTR)(g + 1);
94     strcpy((LPSTR)g->sz, szName);
95
96     if (glyphListSize % GLYPHLIST_ALLOCSIZE == 0)       /* grow the list? */
97     {
98         GLYPHNAME   **newGlyphList;
99
100         newGlyphList = HeapReAlloc(PSDRV_Heap, 0, glyphList,
101                 (glyphListSize + GLYPHLIST_ALLOCSIZE) * sizeof(GLYPHNAME *));
102         if (newGlyphList == NULL)
103         {
104             ERR("Failed to allocate %i bytes of memory\n", (glyphListSize +
105                     GLYPHLIST_ALLOCSIZE) * sizeof (GLYPHNAME *));
106             HeapFree(PSDRV_Heap, 0, g);
107             return -1;
108         }
109
110         glyphList = newGlyphList;
111
112         TRACE("glyphList will now hold %i glyph names\n",
113                 glyphListSize + GLYPHLIST_ALLOCSIZE);
114     }
115
116     if (index < glyphListSize)
117     {
118         memmove(glyphList + (index + 1), glyphList + index,
119                 (glyphListSize - index) * sizeof(GLYPHNAME *));
120     }
121
122     glyphList[index] = g;
123     ++glyphListSize;
124     glyphNamesIndexed = FALSE;
125
126 #if 0
127     TRACE("Added '%s' at glyphList[%i] (glyphListSize now %i)\n",
128             glyphList[index]->sz, index, glyphListSize);
129 #endif
130     return index;
131 }
132
133 /*******************************************************************************
134  *      GlyphListSearch
135  *
136  *  Searches the specified portion of the list for the glyph name and inserts it
137  *  in the list if necessary; returns the index at which the name (now) resides
138  *  (-1 if unable to insert it)
139  *
140  */
141 static INT GlyphListSearch(LPCSTR szName, INT loIndex, INT hiIndex)
142 {
143     INT midIndex, cmpResult;
144
145     while (1)
146     {
147         if (loIndex > hiIndex)
148             return GlyphListInsert(szName, loIndex);
149
150         midIndex = (loIndex + hiIndex) >> 1;
151
152         cmpResult = strcmp(szName, glyphList[midIndex]->sz);
153
154         if (cmpResult == 0)
155         {
156 #if 0
157             TRACE("Found '%s' at glyphList[%i]\n", glyphList[midIndex]->sz,
158                     midIndex);
159 #endif
160             return midIndex;
161         }
162
163         if (cmpResult < 0)
164             hiIndex = midIndex - 1;
165         else
166             loIndex = midIndex + 1;
167     }
168 }
169
170 /*******************************************************************************
171  *      PSDRV_GlyphName
172  *
173  *  Searches the glyph name list for the provided name, adds it to the list if
174  *  necessary, and returns a pointer to it (NULL if unable to add it)
175  *
176  */
177 const GLYPHNAME *PSDRV_GlyphName(LPCSTR szName)
178 {
179     INT index;
180
181     index = GlyphListSearch(szName, 0, glyphListSize - 1);
182     if (index < 0)
183         return NULL;
184
185     return glyphList[index];
186 }
187
188 /*******************************************************************************
189  *      PSDRV_IndexGlyphList
190  *
191  *  Initializes index member of all GLYPHNAME structures
192  *
193  */
194 VOID PSDRV_IndexGlyphList()
195 {
196     INT i;
197
198     if (glyphNamesIndexed)
199         return;
200
201     TRACE("%i glyph names:\n", glyphListSize);
202
203     for (i = 0; i < glyphListSize; ++i)
204     {
205         glyphList[i]->index = i;
206 #if 0
207         TRACE("  glyphList[%i] -> '%s'\n", i, glyphList[i]->sz);
208 #endif
209     }
210
211     glyphNamesIndexed = TRUE;
212 }