When including 'wine/port.h', include it first.
[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  */
10
11 #include <string.h>
12 #include "psdrv.h"
13 #include "debugtools.h"
14
15 DEFAULT_DEBUG_CHANNEL(psdrv);
16
17 #define GLYPHLIST_ALLOCSIZE     1024
18
19 static GLYPHNAME    **glyphList = NULL;
20 static INT          glyphListSize = 0;
21 static BOOL         glyphNamesIndexed = TRUE;
22
23 /*******************************************************************************
24  *      PSDRV_GlyphListInit
25  *
26  *  Allocates initial block of memory for the glyph list and copies pointers to
27  *  the AGL glyph names into it; returns 0 on success, 1 on failure
28  *
29  */
30 INT PSDRV_GlyphListInit()
31 {
32     INT i;
33
34     /*
35      *  Compute the smallest multiple of GLYPHLIST_ALLOCSIZE that is
36      *  greater than or equal to PSDRV_AGLGlyphNamesSize
37      *
38      */
39     glyphListSize = PSDRV_AGLGlyphNamesSize;
40     i = ((glyphListSize + GLYPHLIST_ALLOCSIZE - 1) / GLYPHLIST_ALLOCSIZE) *
41             GLYPHLIST_ALLOCSIZE;
42
43     TRACE("glyphList will initially hold %i glyph names\n", i);
44
45     glyphList = (GLYPHNAME **) HeapAlloc(PSDRV_Heap, 0,
46             i * sizeof(GLYPHNAME *));
47     if (glyphList == NULL)
48     {
49         ERR("Failed to allocate %i bytes of memory\n", i * sizeof(GLYPHNAME *));
50         return 1;
51     }
52
53     for (i = 0; i < glyphListSize; ++i)
54         glyphList[i] = PSDRV_AGLGlyphNames + i;
55
56     return 0;
57 }
58
59 /*******************************************************************************
60  *      GlyphListInsert
61  *
62  *  Inserts a copy of the  glyph name into the list at the index, growing the
63  *  list if necessary; returns index on success (-1 on failure)
64  *
65  */
66 inline static INT GlyphListInsert(LPCSTR szName, INT index)
67 {
68     GLYPHNAME *g;
69
70     g = HeapAlloc(PSDRV_Heap, 0, sizeof(GLYPHNAME) + strlen(szName) + 1);
71     if (g == NULL)
72     {
73         ERR("Failed to allocate %i bytes of memory\n", 
74                 sizeof(GLYPHNAME) + strlen(szName) + 1);
75         return -1;
76     }
77
78     g->index = -1;
79     g->sz = (LPSTR)(g + 1);
80     strcpy((LPSTR)g->sz, szName);
81
82     if (glyphListSize % GLYPHLIST_ALLOCSIZE == 0)       /* grow the list? */
83     {
84         GLYPHNAME   **newGlyphList;
85
86         newGlyphList = (GLYPHNAME **) HeapReAlloc(PSDRV_Heap, 0, glyphList,
87                 (glyphListSize + GLYPHLIST_ALLOCSIZE) * sizeof(GLYPHNAME *));
88         if (newGlyphList == NULL)
89         {
90             ERR("Failed to allocate %i bytes of memory\n", (glyphListSize +
91                     GLYPHLIST_ALLOCSIZE) * sizeof (GLYPHNAME *));
92             HeapFree(PSDRV_Heap, 0, g);
93             return -1;
94         }
95
96         glyphList = newGlyphList;
97
98         TRACE("glyphList will now hold %i glyph names\n",
99                 glyphListSize + GLYPHLIST_ALLOCSIZE);
100     }
101
102     if (index < glyphListSize)
103     {
104         memmove(glyphList + (index + 1), glyphList + index,
105                 (glyphListSize - index) * sizeof(GLYPHNAME *));
106     }
107
108     glyphList[index] = g;
109     ++glyphListSize;
110     glyphNamesIndexed = FALSE;
111
112     TRACE("Added '%s' at glyphList[%i] (glyphListSize now %i)\n",
113             glyphList[index]->sz, index, glyphListSize);
114
115     return index;
116 }
117
118 /*******************************************************************************
119  *      GlyphListSearch
120  *
121  *  Searches the specified portion of the list for the glyph name and inserts it
122  *  in the list if necessary; returns the index at which the name (now) resides
123  *  (-1 if unable to insert it)
124  *
125  */
126 static INT GlyphListSearch(LPCSTR szName, INT loIndex, INT hiIndex)
127 {
128     INT midIndex, cmpResult;
129
130     while (1)
131     {
132         if (loIndex > hiIndex)
133             return GlyphListInsert(szName, loIndex);
134
135         midIndex = (loIndex + hiIndex) >> 1;
136
137         cmpResult = strcmp(szName, glyphList[midIndex]->sz);
138
139         if (cmpResult == 0)
140         {
141             TRACE("Found '%s' at glyphList[%i]\n", glyphList[midIndex]->sz,
142                     midIndex);
143             return midIndex;
144         }
145
146         if (cmpResult < 0)
147             hiIndex = midIndex - 1;
148         else
149             loIndex = midIndex + 1;
150     }
151 }
152
153 /*******************************************************************************
154  *      PSDRV_GlyphName
155  *
156  *  Searches the glyph name list for the provided name, adds it to the list if
157  *  necessary, and returns a pointer to it (NULL if unable to add it)
158  *
159  */
160 const GLYPHNAME *PSDRV_GlyphName(LPCSTR szName)
161 {
162     INT index;
163
164     TRACE("'%s'\n", szName);
165
166     index = GlyphListSearch(szName, 0, glyphListSize - 1);
167     if (index < 0)
168         return NULL;
169
170     return glyphList[index];
171 }
172
173 /*******************************************************************************
174  *      PSDRV_IndexGlyphList
175  *
176  *  Initializes index member of all GLYPHNAME structures
177  *
178  */
179 VOID PSDRV_IndexGlyphList()
180 {
181     INT i;
182     
183     if (glyphNamesIndexed == TRUE)
184         return;
185
186     TRACE("%i glyph names:\n", glyphListSize);
187
188     for (i = 0; i < glyphListSize; ++i)
189     {
190         glyphList[i]->index = i;
191         TRACE("  glyphList[%i] -> '%s'\n", i, glyphList[i]->sz);
192     }
193     
194     glyphNamesIndexed = TRUE;
195 }