- surface pool init fixes
[wine] / objects / gdiobj.c
1 /*
2  * GDI functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26
27 #include "windef.h"
28 #include "wingdi.h"
29 #include "winreg.h"
30 #include "winerror.h"
31
32 #include "bitmap.h"
33 #include "local.h"
34 #include "palette.h"
35 #include "gdi.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
39
40 #define HGDIOBJ_32(h16)   ((HGDIOBJ)(ULONG_PTR)(h16))
41
42 /***********************************************************************
43  *          GDI stock objects
44  */
45
46 static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
47 static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
48 static const LOGBRUSH NullBrush  = { BS_NULL, 0, 0 };
49
50 /* FIXME: these should perhaps be BS_HATCHED, at least for 1 bitperpixel */
51 static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
52 static const LOGBRUSH GrayBrush   = { BS_SOLID, RGB(128,128,128), 0 };
53
54 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
55 /* See HatchBrushes in x11drv for the HS_DIAGCROSS+1 hack */
56 static const LOGBRUSH DkGrayBrush = { BS_HATCHED, RGB(0,0,0), (HS_DIAGCROSS+1) };
57
58 static const LOGPEN WhitePen = { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
59 static const LOGPEN BlackPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
60 static const LOGPEN NullPen  = { PS_NULL,  { 0, 0 }, 0 };
61
62
63 /* reserve one extra entry for the stock default bitmap */
64 /* this is what Windows does too */
65 #define NB_STOCK_OBJECTS (STOCK_LAST+2)
66
67 static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
68
69 static SYSLEVEL GDI_level = { CRITICAL_SECTION_INIT("GDI_level"), 3 };
70 static WORD GDI_HeapSel;
71
72 inline static BOOL get_bool(char *buffer)
73 {
74     return (buffer[0] == 'y' || buffer[0] == 'Y' ||
75             buffer[0] == 't' || buffer[0] == 'T' ||
76             buffer[0] == '1');
77 }
78
79
80 /****************************************************************************
81  *
82  *      language-independent stock fonts
83  *
84  */
85
86 static const LOGFONTW OEMFixedFont =
87 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
88   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
89
90 static const LOGFONTW AnsiFixedFont =
91 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
92   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
93
94 static const LOGFONTW AnsiVarFont =
95 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
96   0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
97   {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'} };
98
99 /******************************************************************************
100  *
101  *      language-dependent stock fonts
102  *
103  *      'ANSI' charset and 'DEFAULT' charset is not same.
104  *      The chars in CP_ACP should be drawn with 'DEFAULT' charset.
105  *      'ANSI' charset seems to be identical with ISO-8859-1.
106  *      'DEFAULT' charset is a language-dependent charset.
107  *
108  *      'System' font seems to be an alias for language-dependent font.
109  */
110
111 /*
112  * language-dependenet stock fonts for all known charsets
113  * please see TranslateCharsetInfo (objects/font.c) and
114  * CharsetBindingInfo (graphics/x11drv/xfont.c),
115  * and modify entries for your language if needed.
116  */
117 struct DefaultFontInfo
118 {
119         UINT            charset;
120         LOGFONTW        SystemFont;
121         LOGFONTW        DeviceDefaultFont;
122         LOGFONTW        SystemFixedFont;
123         LOGFONTW        DefaultGuiFont;
124 };
125
126 static const struct DefaultFontInfo default_fonts[] =
127 {
128     {   ANSI_CHARSET,
129         { /* System */
130           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
131            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
132            {'S','y','s','t','e','m','\0'}
133         },
134         { /* Device Default */
135           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
136            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
137            {'\0'}
138         },
139         { /* System Fixed */
140           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
141            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
142            {'\0'}
143         },
144         { /* DefaultGuiFont */
145          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
146            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
147            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
148         },
149     },
150     {   EASTEUROPE_CHARSET,
151         { /* System */
152           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
153            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
154            {'S','y','s','t','e','m','\0'}
155         },
156         { /* Device Default */
157           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
158            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
159            {'\0'}
160         },
161         { /* System Fixed */
162           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
163            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
164            {'\0'}
165         },
166         { /* DefaultGuiFont */
167          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
168            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
169            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
170         },
171     },
172     {   RUSSIAN_CHARSET,
173         { /* System */
174           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
175            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
176            {'S','y','s','t','e','m','\0'}
177         },
178         { /* Device Default */
179           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
180            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
181            {'\0'}
182         },
183         { /* System Fixed */
184           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
185            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
186            {'\0'}
187         },
188         { /* DefaultGuiFont */
189          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
190            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
191            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
192         },
193     },
194     {   GREEK_CHARSET,
195         { /* System */
196           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
197            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
198            {'S','y','s','t','e','m','\0'}
199         },
200         { /* Device Default */
201           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
202            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
203            {'\0'}
204         },
205         { /* System Fixed */
206           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
207            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
208            {'\0'}
209         },
210         { /* DefaultGuiFont */
211          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
212            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
213            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
214         },
215     },
216     {   TURKISH_CHARSET,
217         { /* System */
218           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
219            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
220            {'S','y','s','t','e','m','\0'}
221         },
222         { /* Device Default */
223           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
224            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
225            {'\0'}
226         },
227         { /* System Fixed */
228           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
229            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
230            {'\0'}
231         },
232         { /* DefaultGuiFont */
233          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
234            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
235            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
236         },
237     },
238     {   HEBREW_CHARSET,
239         { /* System */
240           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
241            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
242            {'S','y','s','t','e','m','\0'}
243         },
244         { /* Device Default */
245           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
246            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
247            {'\0'}
248         },
249         { /* System Fixed */
250           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
251            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
252            {'\0'}
253         },
254         { /* DefaultGuiFont */
255          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
256            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
257            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
258         },
259     },
260     {   ARABIC_CHARSET,
261         { /* System */
262           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
263            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
264            {'S','y','s','t','e','m','\0'}
265         },
266         { /* Device Default */
267           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
268            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
269            {'\0'}
270         },
271         { /* System Fixed */
272           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
273            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
274            {'\0'}
275         },
276         { /* DefaultGuiFont */
277          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
278            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
279            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
280         },
281     },
282     {   BALTIC_CHARSET,
283         { /* System */
284           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
285            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
286            {'S','y','s','t','e','m','\0'}
287         },
288         { /* Device Default */
289           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
290            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
291            {'\0'}
292         },
293         { /* System Fixed */
294           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
295            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
296            {'\0'}
297         },
298         { /* DefaultGuiFont */
299          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
300            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
301            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
302         },
303     },
304     {   THAI_CHARSET,
305         { /* System */
306           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
307            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
308            {'S','y','s','t','e','m','\0'}
309         },
310         { /* Device Default */
311           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
312            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
313            {'\0'}
314         },
315         { /* System Fixed */
316           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
317            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
318            {'\0'}
319         },
320         { /* DefaultGuiFont */
321          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
322            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
323            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
324         },
325     },
326     {   SHIFTJIS_CHARSET,
327         { /* System */
328           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
329            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
330            {'S','y','s','t','e','m','\0'}
331         },
332         { /* Device Default */
333           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
334            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
335            {'\0'}
336         },
337         { /* System Fixed */
338           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
339            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
340            {'\0'}
341         },
342         { /* DefaultGuiFont */
343          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
344            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
345            {'M','S',' ','P',' ','g','o','t','h','i','c','\0'} /* FIXME: Is this correct? */
346         },
347     },
348     {   GB2312_CHARSET,
349         { /* System */
350           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
351            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
352            {'S','y','s','t','e','m','\0'}
353         },
354         { /* Device Default */
355           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
356            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
357            {'\0'}
358         },
359         { /* System Fixed */
360           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
361            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
362            {'\0'}
363         },
364         { /* DefaultGuiFont */
365          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
366            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
367            {'M','S',' ','S','o','n','g','\0'}   /* FIXME: Is this correct? */
368         },
369     },
370     {   HANGEUL_CHARSET,
371         { /* System */
372           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
373            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
374            {'S','y','s','t','e','m','\0'}
375         },
376         { /* Device Default */
377           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
378            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
379            {'\0'}
380         },
381         { /* System Fixed */
382           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
383            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
384            {'\0'}
385         },
386         { /* DefaultGuiFont */
387          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
388            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
389            {'G','u','l','i','m'},
390         },
391     },
392     {   CHINESEBIG5_CHARSET,
393         { /* System */
394           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
395            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
396            {'S','y','s','t','e','m','\0'}
397         },
398         { /* Device Default */
399           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
400            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
401            {'\0'}
402         },
403         { /* System Fixed */
404           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
405            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
406            {'\0'}
407         },
408         { /* DefaultGuiFont */
409          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
410            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
411            {'\0'}       /* FIXME - what is the native font??? */
412         },
413     },
414     {   JOHAB_CHARSET,
415         { /* System */
416           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
417            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
418            {'S','y','s','t','e','m','\0'}
419         },
420         { /* Device Default */
421           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
422            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
423            {'\0'}
424         },
425         { /* System Fixed */
426           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
427            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
428            {'\0'}
429         },
430         { /* DefaultGuiFont */
431          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
432            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
433            {'M','S',' ','M','i','n','g','l','i','u','\0'} /* FIXME: Is this correct? */
434         },
435     },
436 };
437
438
439 /******************************************************************************
440  *      get_default_fonts
441  */
442 static const struct DefaultFontInfo* get_default_fonts(UINT charset)
443 {
444         int     n;
445
446         for(n=0;n<(sizeof(default_fonts)/sizeof(default_fonts[0]));n++)
447         {
448                 if ( default_fonts[n].charset == charset )
449                         return &default_fonts[n];
450         }
451
452         FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
453         return &default_fonts[0];
454 }
455
456
457 /******************************************************************************
458  *      get_default_charset    (internal)
459  *
460  * get the language-dependent charset that can handle CP_ACP correctly.
461  */
462 static UINT get_default_charset( void )
463 {
464     CHARSETINFO     csi;
465     UINT    uACP;
466
467     uACP = GetACP();
468     csi.ciCharset = ANSI_CHARSET;
469     if ( ! TranslateCharsetInfo( (LPDWORD)uACP, &csi, TCI_SRCCODEPAGE ) )
470     {
471         FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", uACP );
472         return ANSI_CHARSET;
473     }
474
475     return csi.ciCharset;
476 }
477
478
479 /******************************************************************************
480  *           create_stock_font
481  */
482 static HFONT create_stock_font( char const *fontName, const LOGFONTW *font, HKEY hkey )
483 {
484     LOGFONTW lf;
485     char  key[256];
486     char buffer[MAX_PATH];
487     DWORD type, count;
488
489     if (!hkey) return CreateFontIndirectW( font );
490
491     lf = *font;
492     sprintf(key, "%s.Height", fontName);
493     count = sizeof(buffer);
494     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
495         lf.lfHeight = atoi(buffer);
496
497     sprintf(key, "%s.Bold", fontName);
498     count = sizeof(buffer);
499     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
500         lf.lfWeight = get_bool(buffer) ? FW_BOLD : FW_NORMAL;
501
502     sprintf(key, "%s.Italic", fontName);
503     count = sizeof(buffer);
504     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
505         lf.lfItalic = get_bool(buffer);
506
507     sprintf(key, "%s.Underline", fontName);
508     count = sizeof(buffer);
509     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
510         lf.lfUnderline = get_bool(buffer);
511
512     sprintf(key, "%s.StrikeOut", fontName);
513     count = sizeof(buffer);
514     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
515         lf.lfStrikeOut = get_bool(buffer);
516     return CreateFontIndirectW( &lf );
517 }
518
519
520 #define TRACE_SEC(handle,text) \
521    TRACE("(%p): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
522
523
524 /***********************************************************************
525  *           inc_ref_count
526  *
527  * Increment the reference count of a GDI object.
528  */
529 inline static void inc_ref_count( HGDIOBJ handle )
530 {
531     GDIOBJHDR *header;
532
533     if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
534     {
535         header->dwCount++;
536         GDI_ReleaseObj( handle );
537     }
538 }
539
540
541 /***********************************************************************
542  *           dec_ref_count
543  *
544  * Decrement the reference count of a GDI object.
545  */
546 inline static void dec_ref_count( HGDIOBJ handle )
547 {
548     GDIOBJHDR *header;
549
550     if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
551     {
552         if (header->dwCount) header->dwCount--;
553         if (header->dwCount != 0x80000000) GDI_ReleaseObj( handle );
554         else
555         {
556             /* handle delayed DeleteObject*/
557             header->dwCount = 0;
558             GDI_ReleaseObj( handle );
559             TRACE( "executing delayed DeleteObject for %p\n", handle );
560             DeleteObject( handle );
561         }
562     }
563 }
564
565
566 /***********************************************************************
567  *           GDI_Init
568  *
569  * GDI initialization.
570  */
571 BOOL GDI_Init(void)
572 {
573     HINSTANCE16 instance;
574     HKEY hkey;
575     GDIOBJHDR *ptr;
576     const struct DefaultFontInfo* deffonts;
577     int i;
578
579     if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Tweak.Fonts", &hkey))
580         hkey = 0;
581
582     /* create GDI heap */
583     if ((instance = LoadLibrary16( "GDI.EXE" )) >= 32) GDI_HeapSel = instance | 7;
584
585     /* create stock objects */
586     stock_objects[WHITE_BRUSH]  = CreateBrushIndirect( &WhiteBrush );
587     stock_objects[LTGRAY_BRUSH] = CreateBrushIndirect( &LtGrayBrush );
588     stock_objects[GRAY_BRUSH]   = CreateBrushIndirect( &GrayBrush );
589     stock_objects[DKGRAY_BRUSH] = CreateBrushIndirect( &DkGrayBrush );
590     stock_objects[BLACK_BRUSH]  = CreateBrushIndirect( &BlackBrush );
591     stock_objects[NULL_BRUSH]   = CreateBrushIndirect( &NullBrush );
592
593     stock_objects[WHITE_PEN]    = CreatePenIndirect( &WhitePen );
594     stock_objects[BLACK_PEN]    = CreatePenIndirect( &BlackPen );
595     stock_objects[NULL_PEN]     = CreatePenIndirect( &NullPen );
596
597     stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
598     stock_objects[DEFAULT_BITMAP]  = CreateBitmap( 1, 1, 1, 1, NULL );
599
600     /* language-independent stock fonts */
601     stock_objects[OEM_FIXED_FONT]      = create_stock_font( "OEMFixed", &OEMFixedFont, hkey );
602     stock_objects[ANSI_FIXED_FONT]     = create_stock_font( "AnsiFixed", &AnsiFixedFont, hkey );
603     stock_objects[ANSI_VAR_FONT]       = create_stock_font( "AnsiVar", &AnsiVarFont, hkey );
604
605     /* language-dependent stock fonts */
606     deffonts = get_default_fonts(get_default_charset());
607     stock_objects[SYSTEM_FONT]         = create_stock_font( "System", &deffonts->SystemFont, hkey );
608     stock_objects[DEVICE_DEFAULT_FONT] = create_stock_font( "DeviceDefault", &deffonts->DeviceDefaultFont, hkey );
609     stock_objects[SYSTEM_FIXED_FONT]   = create_stock_font( "SystemFixed", &deffonts->SystemFixedFont, hkey );
610     stock_objects[DEFAULT_GUI_FONT]    = create_stock_font( "DefaultGui", &deffonts->DefaultGuiFont, hkey );
611
612
613     /* clear the NOSYSTEM bit on all stock objects*/
614     for (i = 0; i < NB_STOCK_OBJECTS; i++)
615     {
616         if (!stock_objects[i])
617         {
618             if (i == 9) continue;  /* there's no stock object 9 */
619             ERR( "could not create stock object %d\n", i );
620             return FALSE;
621         }
622         ptr = GDI_GetObjPtr( stock_objects[i], MAGIC_DONTCARE );
623         ptr->wMagic &= ~OBJECT_NOSYSTEM;
624         GDI_ReleaseObj( stock_objects[i] );
625     }
626
627     if (hkey) RegCloseKey( hkey );
628
629     WineEngInit();
630
631     return TRUE;
632 }
633
634 #define FIRST_LARGE_HANDLE 16
635 #define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
636 static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
637 static int next_large_handle;
638
639 /***********************************************************************
640  *           alloc_large_heap
641  *
642  * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
643  */
644 inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
645 {
646     int i;
647     GDIOBJHDR *obj;
648
649     for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
650         if (!large_handles[i]) goto found;
651     for (i = 0; i <= next_large_handle; i++)
652         if (!large_handles[i]) goto found;
653     *handle = 0;
654     return NULL;
655
656  found:
657     if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
658     {
659         large_handles[i] = obj;
660         *handle = (HGDIOBJ)(ULONG_PTR)((i + FIRST_LARGE_HANDLE) << 2);
661         next_large_handle = i;
662     }
663     return obj;
664 }
665
666
667 /***********************************************************************
668  *           GDI_AllocObject
669  */
670 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle, const struct gdi_obj_funcs *funcs )
671 {
672     GDIOBJHDR *obj;
673     HLOCAL16 hlocal;
674
675     _EnterSysLevel( &GDI_level );
676     switch(magic)
677     {
678     default:
679         if (GDI_HeapSel)
680         {
681             if (!(hlocal = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
682             assert( hlocal & 2 );
683             obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hlocal );
684             *handle = (HGDIOBJ)(ULONG_PTR)hlocal;
685             break;
686         }
687         /* fall through */
688     case DC_MAGIC:
689     case DISABLED_DC_MAGIC:
690     case META_DC_MAGIC:
691     case METAFILE_MAGIC:
692     case METAFILE_DC_MAGIC:
693     case ENHMETAFILE_MAGIC:
694     case ENHMETAFILE_DC_MAGIC:
695     case BITMAP_MAGIC:
696     case PALETTE_MAGIC:
697         if (!(obj = alloc_large_heap( size, handle ))) goto error;
698         break;
699     }
700
701     obj->hNext   = 0;
702     obj->wMagic  = magic|OBJECT_NOSYSTEM;
703     obj->dwCount = 0;
704     obj->funcs   = funcs;
705
706     TRACE_SEC( *handle, "enter" );
707     return obj;
708
709 error:
710     _LeaveSysLevel( &GDI_level );
711     *handle = 0;
712     return NULL;
713 }
714
715
716 /***********************************************************************
717  *           GDI_ReallocObject
718  *
719  * The object ptr must have been obtained with GDI_GetObjPtr.
720  * The new pointer must be released with GDI_ReleaseObj.
721  */
722 void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
723 {
724     HGDIOBJ new_handle;
725
726     if ((UINT_PTR)handle & 2)  /* GDI heap handle */
727     {
728         HLOCAL16 h = LOWORD(handle);
729         LOCAL_Unlock( GDI_HeapSel, h );
730         if ((new_handle = (HGDIOBJ)(ULONG_PTR)LOCAL_ReAlloc( GDI_HeapSel, h, size, LMEM_MOVEABLE )))
731         {
732             assert( new_handle == handle );  /* moveable handle cannot change */
733             return LOCAL_Lock( GDI_HeapSel, h );
734         }
735     }
736     else
737     {
738         int i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
739         if (i >= 0 && i < MAX_LARGE_HANDLES && large_handles[i])
740         {
741             void *new_ptr = HeapReAlloc( GetProcessHeap(), 0, large_handles[i], size );
742             if (new_ptr)
743             {
744                 large_handles[i] = new_ptr;
745                 return new_ptr;
746             }
747         }
748         else ERR( "Invalid handle %p\n", handle );
749     }
750     TRACE_SEC( handle, "leave" );
751     _LeaveSysLevel( &GDI_level );
752     return NULL;
753 }
754
755
756 /***********************************************************************
757  *           GDI_FreeObject
758  */
759 BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
760 {
761     GDIOBJHDR *object = ptr;
762
763     object->wMagic = 0;  /* Mark it as invalid */
764     object->funcs  = NULL;
765     if ((UINT_PTR)handle & 2)  /* GDI heap handle */
766     {
767         HLOCAL16 h = LOWORD(handle);
768         LOCAL_Unlock( GDI_HeapSel, h );
769         LOCAL_Free( GDI_HeapSel, h );
770     }
771     else  /* large heap handle */
772     {
773         int i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
774         if (i >= 0 && i < MAX_LARGE_HANDLES && large_handles[i])
775         {
776             HeapFree( GetProcessHeap(), 0, large_handles[i] );
777             large_handles[i] = NULL;
778         }
779         else ERR( "Invalid handle %p\n", handle );
780     }
781     TRACE_SEC( handle, "leave" );
782     _LeaveSysLevel( &GDI_level );
783     return TRUE;
784 }
785
786
787 /***********************************************************************
788  *           GDI_GetObjPtr
789  *
790  * Return a pointer to the GDI object associated to the handle.
791  * Return NULL if the object has the wrong magic number.
792  * The object must be released with GDI_ReleaseObj.
793  */
794 void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
795 {
796     GDIOBJHDR *ptr = NULL;
797
798     _EnterSysLevel( &GDI_level );
799
800     if ((UINT_PTR)handle & 2)  /* GDI heap handle */
801     {
802         HLOCAL16 h = LOWORD(handle);
803         ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, h );
804         if (ptr)
805         {
806             if (((magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ||
807                 (GDIMAGIC(ptr->wMagic) < FIRST_MAGIC) ||
808                 (GDIMAGIC(ptr->wMagic) > LAST_MAGIC))
809             {
810                 LOCAL_Unlock( GDI_HeapSel, h );
811                 ptr = NULL;
812             }
813         }
814     }
815     else  /* large heap handle */
816     {
817         int i = ((UINT_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
818         if (i >= 0 && i < MAX_LARGE_HANDLES)
819         {
820             ptr = large_handles[i];
821             if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
822         }
823     }
824
825     if (!ptr)
826     {
827         _LeaveSysLevel( &GDI_level );
828         SetLastError( ERROR_INVALID_HANDLE );
829         WARN( "Invalid handle %p\n", handle );
830     }
831     else TRACE_SEC( handle, "enter" );
832
833     return ptr;
834 }
835
836
837 /***********************************************************************
838  *           GDI_ReleaseObj
839  *
840  */
841 void GDI_ReleaseObj( HGDIOBJ handle )
842 {
843     if ((UINT_PTR)handle & 2) LOCAL_Unlock( GDI_HeapSel, LOWORD(handle) );
844     TRACE_SEC( handle, "leave" );
845     _LeaveSysLevel( &GDI_level );
846 }
847
848
849 /***********************************************************************
850  *           GDI_CheckNotLock
851  */
852 void GDI_CheckNotLock(void)
853 {
854     _CheckNotSysLevel( &GDI_level );
855 }
856
857
858 /***********************************************************************
859  *           DeleteObject    (GDI32.@)
860  */
861 BOOL WINAPI DeleteObject( HGDIOBJ obj )
862 {
863       /* Check if object is valid */
864
865     GDIOBJHDR * header;
866     if (HIWORD(obj)) return FALSE;
867
868     if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
869
870     if (!(header->wMagic & OBJECT_NOSYSTEM)
871     &&   (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
872     {
873         TRACE("Preserving system object %p\n", obj);
874         GDI_ReleaseObj( obj );
875         return TRUE;
876     }
877
878     if (header->dwCount)
879     {
880         TRACE("delayed for %p because object in use, count %ld\n", obj, header->dwCount );
881         header->dwCount |= 0x80000000; /* mark for delete */
882         GDI_ReleaseObj( obj );
883         return TRUE;
884     }
885
886     TRACE("%p\n", obj );
887
888       /* Delete object */
889
890     if (header->funcs && header->funcs->pDeleteObject)
891         return header->funcs->pDeleteObject( obj, header );
892
893     GDI_ReleaseObj( obj );
894     return FALSE;
895 }
896
897
898 /***********************************************************************
899  *           GetStockObject    (GDI32.@)
900  */
901 HGDIOBJ WINAPI GetStockObject( INT obj )
902 {
903     HGDIOBJ ret;
904     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
905     ret = stock_objects[obj];
906     TRACE("returning %p\n", ret );
907     return ret;
908 }
909
910
911 /***********************************************************************
912  *           GetObject    (GDI.82)
913  */
914 INT16 WINAPI GetObject16( HANDLE16 handle16, INT16 count, LPVOID buffer )
915 {
916     GDIOBJHDR * ptr;
917     HGDIOBJ handle = HGDIOBJ_32( handle16 );
918     INT16 result = 0;
919
920     TRACE("%p %d %p\n", handle, count, buffer );
921     if (!count) return 0;
922
923     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
924
925     if (ptr->funcs && ptr->funcs->pGetObject16)
926         result = ptr->funcs->pGetObject16( handle, ptr, count, buffer );
927     else
928         SetLastError( ERROR_INVALID_HANDLE );
929
930     GDI_ReleaseObj( handle );
931     return result;
932 }
933
934
935 /***********************************************************************
936  *           GetObjectA    (GDI32.@)
937  */
938 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
939 {
940     GDIOBJHDR * ptr;
941     INT result = 0;
942     TRACE("%p %d %p\n", handle, count, buffer );
943     if (!count) return 0;
944
945     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
946
947     if (ptr->funcs && ptr->funcs->pGetObjectA)
948         result = ptr->funcs->pGetObjectA( handle, ptr, count, buffer );
949     else
950         SetLastError( ERROR_INVALID_HANDLE );
951
952     GDI_ReleaseObj( handle );
953     return result;
954 }
955
956 /***********************************************************************
957  *           GetObjectW    (GDI32.@)
958  */
959 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
960 {
961     GDIOBJHDR * ptr;
962     INT result = 0;
963     TRACE("%p %d %p\n", handle, count, buffer );
964     if (!count) return 0;
965
966     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
967
968     if (ptr->funcs && ptr->funcs->pGetObjectW)
969         result = ptr->funcs->pGetObjectW( handle, ptr, count, buffer );
970     else
971         SetLastError( ERROR_INVALID_HANDLE );
972
973     GDI_ReleaseObj( handle );
974     return result;
975 }
976
977 /***********************************************************************
978  *           GetObjectType    (GDI32.@)
979  */
980 DWORD WINAPI GetObjectType( HANDLE handle )
981 {
982     GDIOBJHDR * ptr;
983     INT result = 0;
984     TRACE("%p\n", handle );
985
986     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
987
988     switch(GDIMAGIC(ptr->wMagic))
989     {
990       case PEN_MAGIC:
991           result = OBJ_PEN;
992           break;
993       case BRUSH_MAGIC:
994           result = OBJ_BRUSH;
995           break;
996       case BITMAP_MAGIC:
997           result = OBJ_BITMAP;
998           break;
999       case FONT_MAGIC:
1000           result = OBJ_FONT;
1001           break;
1002       case PALETTE_MAGIC:
1003           result = OBJ_PAL;
1004           break;
1005       case REGION_MAGIC:
1006           result = OBJ_REGION;
1007           break;
1008       case DC_MAGIC:
1009           result = OBJ_DC;
1010           break;
1011       case META_DC_MAGIC:
1012           result = OBJ_METADC;
1013           break;
1014       case METAFILE_MAGIC:
1015           result = OBJ_METAFILE;
1016           break;
1017       case METAFILE_DC_MAGIC:
1018           result = OBJ_METADC;
1019           break;
1020       case ENHMETAFILE_MAGIC:
1021           result = OBJ_ENHMETAFILE;
1022           break;
1023       case ENHMETAFILE_DC_MAGIC:
1024           result = OBJ_ENHMETADC;
1025           break;
1026       default:
1027           FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
1028           break;
1029     }
1030     GDI_ReleaseObj( handle );
1031     return result;
1032 }
1033
1034 /***********************************************************************
1035  *           GetCurrentObject           (GDI32.@)
1036  */
1037 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
1038 {
1039     HANDLE ret = 0;
1040     DC * dc = DC_GetDCPtr( hdc );
1041
1042     if (dc)
1043     {
1044     switch (type) {
1045         case OBJ_PEN:    ret = dc->hPen; break;
1046         case OBJ_BRUSH:  ret = dc->hBrush; break;
1047         case OBJ_PAL:    ret = dc->hPalette; break;
1048         case OBJ_FONT:   ret = dc->hFont; break;
1049         case OBJ_BITMAP: ret = dc->hBitmap; break;
1050     default:
1051         /* the SDK only mentions those above */
1052         FIXME("(%p,%d): unknown type.\n",hdc,type);
1053             break;
1054         }
1055         GDI_ReleaseObj( hdc );
1056     }
1057     return ret;
1058 }
1059
1060
1061 /***********************************************************************
1062  *           SelectObject    (GDI32.@)
1063  */
1064 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
1065 {
1066     HGDIOBJ ret = 0;
1067     GDIOBJHDR *header = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1068     if (!header) return 0;
1069
1070     TRACE("hdc=%p %p\n", hdc, handle );
1071
1072     if (header->funcs && header->funcs->pSelectObject)
1073     {
1074         ret = header->funcs->pSelectObject( handle, header, hdc );
1075         if (ret && ret != handle && (INT)ret > COMPLEXREGION)
1076         {
1077             inc_ref_count( handle );
1078             dec_ref_count( ret );
1079         }
1080     }
1081     GDI_ReleaseObj( handle );
1082     return ret;
1083 }
1084
1085
1086 /***********************************************************************
1087  *           UnrealizeObject    (GDI32.@)
1088  */
1089 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
1090 {
1091     BOOL result = TRUE;
1092   /* Check if object is valid */
1093
1094     GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
1095     if (!header) return FALSE;
1096
1097     TRACE("%p\n", obj );
1098
1099       /* Unrealize object */
1100
1101     if (header->funcs && header->funcs->pUnrealizeObject)
1102         result = header->funcs->pUnrealizeObject( obj, header );
1103
1104     GDI_ReleaseObj( obj );
1105     return result;
1106 }
1107
1108
1109 /* Solid colors to enumerate */
1110 static const COLORREF solid_colors[] =
1111 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1112 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1113 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1114 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1115 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1116 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1117 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1118 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1119 };
1120
1121
1122 /***********************************************************************
1123  *           EnumObjects    (GDI32.@)
1124  */
1125 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
1126                             GOBJENUMPROC lpEnumFunc, LPARAM lParam )
1127 {
1128     INT i, retval = 0;
1129     LOGPEN pen;
1130     LOGBRUSH brush;
1131
1132     TRACE("%p %d %p %08lx\n", hdc, nObjType, lpEnumFunc, lParam );
1133     switch(nObjType)
1134     {
1135     case OBJ_PEN:
1136         /* Enumerate solid pens */
1137         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1138         {
1139             pen.lopnStyle   = PS_SOLID;
1140             pen.lopnWidth.x = 1;
1141             pen.lopnWidth.y = 0;
1142             pen.lopnColor   = solid_colors[i];
1143             retval = lpEnumFunc( &pen, lParam );
1144             TRACE("solid pen %08lx, ret=%d\n",
1145                          solid_colors[i], retval);
1146             if (!retval) break;
1147         }
1148         break;
1149
1150     case OBJ_BRUSH:
1151         /* Enumerate solid brushes */
1152         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1153         {
1154             brush.lbStyle = BS_SOLID;
1155             brush.lbColor = solid_colors[i];
1156             brush.lbHatch = 0;
1157             retval = lpEnumFunc( &brush, lParam );
1158             TRACE("solid brush %08lx, ret=%d\n",
1159                          solid_colors[i], retval);
1160             if (!retval) break;
1161         }
1162
1163         /* Now enumerate hatched brushes */
1164         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1165         {
1166             brush.lbStyle = BS_HATCHED;
1167             brush.lbColor = RGB(0,0,0);
1168             brush.lbHatch = i;
1169             retval = lpEnumFunc( &brush, lParam );
1170             TRACE("hatched brush %d, ret=%d\n",
1171                          i, retval);
1172             if (!retval) break;
1173         }
1174         break;
1175
1176     default:
1177         /* FIXME: implement Win32 types */
1178         WARN("(%d): Invalid type\n", nObjType );
1179         break;
1180     }
1181     return retval;
1182 }
1183
1184
1185 /***********************************************************************
1186  *           IsGDIObject    (GDI.462)
1187  *
1188  * returns type of object if valid (W95 system programming secrets p. 264-5)
1189  */
1190 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle16 )
1191 {
1192     UINT16 magic = 0;
1193     HGDIOBJ handle = HGDIOBJ_32( handle16 );
1194
1195     GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1196     if (object)
1197     {
1198         magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1199         GDI_ReleaseObj( handle );
1200     }
1201     return magic;
1202 }
1203
1204
1205 /***********************************************************************
1206  *           SetObjectOwner    (GDI32.@)
1207  */
1208 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1209 {
1210     /* Nothing to do */
1211 }
1212
1213
1214 /***********************************************************************
1215  *           MakeObjectPrivate    (GDI.463)
1216  *
1217  * What does that mean ?
1218  * Some little docu can be found in "Undocumented Windows",
1219  * but this is basically useless.
1220  * At least we know that this flags the GDI object's wMagic
1221  * with 0x2000 (OBJECT_PRIVATE), so we just do it.
1222  * But Wine doesn't react on that yet.
1223  */
1224 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle16, BOOL16 private )
1225 {
1226     HGDIOBJ handle = HGDIOBJ_32( handle16 );
1227     GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1228     if (!ptr)
1229     {
1230         ERR("invalid GDI object %p !\n", handle);
1231         return;
1232     }
1233     ptr->wMagic |= OBJECT_PRIVATE;
1234     GDI_ReleaseObj( handle );
1235 }
1236
1237
1238 /***********************************************************************
1239  *           GdiFlush    (GDI32.@)
1240  */
1241 BOOL WINAPI GdiFlush(void)
1242 {
1243     return TRUE;  /* FIXME */
1244 }
1245
1246
1247 /***********************************************************************
1248  *           GdiGetBatchLimit    (GDI32.@)
1249  */
1250 DWORD WINAPI GdiGetBatchLimit(void)
1251 {
1252     return 1;  /* FIXME */
1253 }
1254
1255
1256 /***********************************************************************
1257  *           GdiSetBatchLimit    (GDI32.@)
1258  */
1259 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1260 {
1261     return 1; /* FIXME */
1262 }
1263
1264
1265 /***********************************************************************
1266  *           GdiSeeGdiDo   (GDI.452)
1267  */
1268 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1269                           WORD wParam3 )
1270 {
1271     switch (wReqType)
1272     {
1273     case 0x0001:  /* LocalAlloc */
1274         return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1275     case 0x0002:  /* LocalFree */
1276         return LOCAL_Free( GDI_HeapSel, wParam1 );
1277     case 0x0003:  /* LocalCompact */
1278         return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1279     case 0x0103:  /* LocalHeap */
1280         return GDI_HeapSel;
1281     default:
1282         WARN("(wReqType=%04x): Unknown\n", wReqType);
1283         return (DWORD)-1;
1284     }
1285 }
1286
1287 /***********************************************************************
1288  *           GdiSignalProc32     (GDI.610)
1289  */
1290 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1291                            DWORD dwFlags, HMODULE16 hModule )
1292 {
1293     return 0;
1294 }
1295
1296 /***********************************************************************
1297  *           GdiInit2     (GDI.403)
1298  *
1299  * See "Undocumented Windows"
1300  */
1301 HANDLE16 WINAPI GdiInit216(
1302     HANDLE16 h1, /* [in] GDI object */
1303     HANDLE16 h2  /* [in] global data */
1304 )
1305 {
1306     FIXME("(%04x, %04x), stub.\n", h1, h2);
1307     if (h2 == 0xffff)
1308         return 0xffff; /* undefined return value */
1309     return h1; /* FIXME: should be the memory handle of h1 */
1310 }
1311
1312 /***********************************************************************
1313  *           FinalGdiInit     (GDI.405)
1314  */
1315 void WINAPI FinalGdiInit16( HBRUSH16 hPattern /* [in] fill pattern of desktop */ )
1316 {
1317 }
1318
1319 /***********************************************************************
1320  *           GdiFreeResources   (GDI.609)
1321  */
1322 WORD WINAPI GdiFreeResources16( DWORD reserve )
1323 {
1324    return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1325                   (int)LOCAL_HeapSize( GDI_HeapSel ) );
1326 }
1327
1328
1329 /*******************************************************************
1330  *      GetColorAdjustment [GDI32.@]
1331  *
1332  *
1333  */
1334 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1335 {
1336         FIXME("GetColorAdjustment, stub\n");
1337         return 0;
1338 }
1339
1340 /*******************************************************************
1341  *      GetMiterLimit [GDI32.@]
1342  *
1343  *
1344  */
1345 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1346 {
1347         FIXME("GetMiterLimit, stub\n");
1348         return 0;
1349 }
1350
1351 /*******************************************************************
1352  *      SetMiterLimit [GDI32.@]
1353  *
1354  *
1355  */
1356 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1357 {
1358         FIXME("SetMiterLimit, stub\n");
1359         return 0;
1360 }
1361
1362 /*******************************************************************
1363  *      GdiComment [GDI32.@]
1364  *
1365  *
1366  */
1367 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1368 {
1369         FIXME("GdiComment, stub\n");
1370         return 0;
1371 }
1372 /*******************************************************************
1373  *      SetColorAdjustment [GDI32.@]
1374  *
1375  *
1376  */
1377 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1378 {
1379         FIXME("SetColorAdjustment, stub\n");
1380         return 0;
1381 }