Fixed a number of -DSTRICT issues.
[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 "font.h"
34 #include "local.h"
35 #include "palette.h"
36 #include "wine/debug.h"
37 #include "gdi.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
40
41 #define HGDIOBJ_32(h16)   ((HGDIOBJ)(ULONG_PTR)(h16))
42
43 /***********************************************************************
44  *          GDI stock objects
45  */
46
47 static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
48 static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
49 static const LOGBRUSH NullBrush  = { BS_NULL, 0, 0 };
50
51 /* FIXME: these should perhaps be BS_HATCHED, at least for 1 bitperpixel */
52 static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
53 static const LOGBRUSH GrayBrush   = { BS_SOLID, RGB(128,128,128), 0 };
54
55 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
56 /* See HatchBrushes in x11drv for the HS_DIAGCROSS+1 hack */
57 static const LOGBRUSH DkGrayBrush = { BS_HATCHED, RGB(0,0,0), (HS_DIAGCROSS+1) };
58
59 static const LOGPEN WhitePen = { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
60 static const LOGPEN BlackPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
61 static const LOGPEN NullPen  = { PS_NULL,  { 0, 0 }, 0 };
62
63
64 /* reserve one extra entry for the stock default bitmap */
65 /* this is what Windows does too */
66 #define NB_STOCK_OBJECTS (STOCK_LAST+2)
67
68 static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
69
70 static SYSLEVEL GDI_level = { CRITICAL_SECTION_INIT("GDI_level"), 3 };
71 static WORD GDI_HeapSel;
72
73 inline static BOOL get_bool(char *buffer)
74 {
75     return (buffer[0] == 'y' || buffer[0] == 'Y' ||
76             buffer[0] == 't' || buffer[0] == 'T' ||
77             buffer[0] == '1');
78 }
79
80
81 /****************************************************************************
82  *
83  *      language-independent stock fonts
84  *
85  */
86
87 static const LOGFONTW OEMFixedFont =
88 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
89   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
90
91 static const LOGFONTW AnsiFixedFont =
92 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
93   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
94
95 static const LOGFONTW AnsiVarFont =
96 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
97   0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
98   {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'} };
99
100 /******************************************************************************
101  *
102  *      language-dependent stock fonts
103  *
104  *      'ANSI' charset and 'DEFAULT' charset is not same.
105  *      The chars in CP_ACP should be drawn with 'DEFAULT' charset.
106  *      'ANSI' charset seems to be identical with ISO-8859-1.
107  *      'DEFAULT' charset is a language-dependent charset.
108  *
109  *      'System' font seems to be an alias for language-dependent font.
110  */
111
112 /*
113  * language-dependenet stock fonts for all known charsets
114  * please see TranslateCharsetInfo (objects/font.c) and
115  * CharsetBindingInfo (graphics/x11drv/xfont.c),
116  * and modify entries for your language if needed.
117  */
118 struct DefaultFontInfo
119 {
120         UINT            charset;
121         LOGFONTW        SystemFont;
122         LOGFONTW        DeviceDefaultFont;
123         LOGFONTW        SystemFixedFont;
124         LOGFONTW        DefaultGuiFont;
125 };
126
127 static const struct DefaultFontInfo default_fonts[] =
128 {
129     {   ANSI_CHARSET,
130         { /* System */
131           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
132            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
133            {'S','y','s','t','e','m','\0'}
134         },
135         { /* Device Default */
136           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
137            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
138            {'\0'}
139         },
140         { /* System Fixed */
141           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
142            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
143            {'\0'}
144         },
145         { /* DefaultGuiFont */
146          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
147            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
148            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
149         },
150     },
151     {   EASTEUROPE_CHARSET,
152         { /* System */
153           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
154            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
155            {'S','y','s','t','e','m','\0'}
156         },
157         { /* Device Default */
158           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
159            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
160            {'\0'}
161         },
162         { /* System Fixed */
163           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
164            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
165            {'\0'}
166         },
167         { /* DefaultGuiFont */
168          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
169            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
170            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
171         },
172     },
173     {   RUSSIAN_CHARSET,
174         { /* System */
175           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
176            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
177            {'S','y','s','t','e','m','\0'}
178         },
179         { /* Device Default */
180           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
181            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
182            {'\0'}
183         },
184         { /* System Fixed */
185           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
186            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
187            {'\0'}
188         },
189         { /* DefaultGuiFont */
190          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
191            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
192            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
193         },
194     },
195     {   GREEK_CHARSET,
196         { /* System */
197           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
198            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
199            {'S','y','s','t','e','m','\0'}
200         },
201         { /* Device Default */
202           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
203            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
204            {'\0'}
205         },
206         { /* System Fixed */
207           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
208            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
209            {'\0'}
210         },
211         { /* DefaultGuiFont */
212          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
213            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
214            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
215         },
216     },
217     {   TURKISH_CHARSET,
218         { /* System */
219           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
220            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
221            {'S','y','s','t','e','m','\0'}
222         },
223         { /* Device Default */
224           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
225            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
226            {'\0'}
227         },
228         { /* System Fixed */
229           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
230            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
231            {'\0'}
232         },
233         { /* DefaultGuiFont */
234          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
235            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
236            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
237         },
238     },
239     {   HEBREW_CHARSET,
240         { /* System */
241           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
242            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
243            {'S','y','s','t','e','m','\0'}
244         },
245         { /* Device Default */
246           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
247            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
248            {'\0'}
249         },
250         { /* System Fixed */
251           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
252            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
253            {'\0'}
254         },
255         { /* DefaultGuiFont */
256          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
257            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
258            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
259         },
260     },
261     {   ARABIC_CHARSET,
262         { /* System */
263           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
264            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
265            {'S','y','s','t','e','m','\0'}
266         },
267         { /* Device Default */
268           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
269            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
270            {'\0'}
271         },
272         { /* System Fixed */
273           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
274            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
275            {'\0'}
276         },
277         { /* DefaultGuiFont */
278          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
279            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
280            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
281         },
282     },
283     {   BALTIC_CHARSET,
284         { /* System */
285           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
286            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
287            {'S','y','s','t','e','m','\0'}
288         },
289         { /* Device Default */
290           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
291            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
292            {'\0'}
293         },
294         { /* System Fixed */
295           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
296            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
297            {'\0'}
298         },
299         { /* DefaultGuiFont */
300          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
301            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
302            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
303         },
304     },
305     {   THAI_CHARSET,
306         { /* System */
307           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
308            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
309            {'S','y','s','t','e','m','\0'}
310         },
311         { /* Device Default */
312           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
313            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
314            {'\0'}
315         },
316         { /* System Fixed */
317           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
318            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
319            {'\0'}
320         },
321         { /* DefaultGuiFont */
322          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
323            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
324            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
325         },
326     },
327     {   SHIFTJIS_CHARSET,
328         { /* System */
329           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
330            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
331            {'S','y','s','t','e','m','\0'}
332         },
333         { /* Device Default */
334           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
335            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
336            {'\0'}
337         },
338         { /* System Fixed */
339           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
340            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
341            {'\0'}
342         },
343         { /* DefaultGuiFont */
344          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
345            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
346            {'M','S',' ','P',' ','g','o','t','h','i','c','\0'} /* FIXME: Is this correct? */
347         },
348     },
349     {   GB2312_CHARSET,
350         { /* System */
351           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
352            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
353            {'S','y','s','t','e','m','\0'}
354         },
355         { /* Device Default */
356           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
357            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
358            {'\0'}
359         },
360         { /* System Fixed */
361           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
362            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
363            {'\0'}
364         },
365         { /* DefaultGuiFont */
366          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
367            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
368            {'M','S',' ','S','o','n','g','\0'}   /* FIXME: Is this correct? */
369         },
370     },
371     {   HANGEUL_CHARSET,
372         { /* System */
373           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
374            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
375            {'S','y','s','t','e','m','\0'}
376         },
377         { /* Device Default */
378           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
379            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
380            {'\0'}
381         },
382         { /* System Fixed */
383           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
384            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
385            {'\0'}
386         },
387         { /* DefaultGuiFont */
388          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
389            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
390            {'G','u','l','i','m'},
391         },
392     },
393     {   CHINESEBIG5_CHARSET,
394         { /* System */
395           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
396            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
397            {'S','y','s','t','e','m','\0'}
398         },
399         { /* Device Default */
400           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
401            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
402            {'\0'}
403         },
404         { /* System Fixed */
405           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
406            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
407            {'\0'}
408         },
409         { /* DefaultGuiFont */
410          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
411            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
412            {'\0'}       /* FIXME - what is the native font??? */
413         },
414     },
415     {   JOHAB_CHARSET,
416         { /* System */
417           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
418            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
419            {'S','y','s','t','e','m','\0'}
420         },
421         { /* Device Default */
422           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
423            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
424            {'\0'}
425         },
426         { /* System Fixed */
427           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
428            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
429            {'\0'}
430         },
431         { /* DefaultGuiFont */
432          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
433            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
434            {'M','S',' ','M','i','n','g','l','i','u','\0'} /* FIXME: Is this correct? */
435         },
436     },
437 };
438
439
440 /******************************************************************************
441  *      get_default_fonts
442  */
443 static const struct DefaultFontInfo* get_default_fonts(UINT charset)
444 {
445         int     n;
446
447         for(n=0;n<(sizeof(default_fonts)/sizeof(default_fonts[0]));n++)
448         {
449                 if ( default_fonts[n].charset == charset )
450                         return &default_fonts[n];
451         }
452
453         FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
454         return &default_fonts[0];
455 }
456
457
458 /******************************************************************************
459  *      get_default_charset    (internal)
460  *
461  * get the language-dependent charset that can handle CP_ACP correctly.
462  */
463 static UINT get_default_charset( void )
464 {
465     CHARSETINFO     csi;
466     UINT    uACP;
467
468     uACP = GetACP();
469     csi.ciCharset = ANSI_CHARSET;
470     if ( ! TranslateCharsetInfo( (LPDWORD)uACP, &csi, TCI_SRCCODEPAGE ) )
471     {
472         FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", uACP );
473         return ANSI_CHARSET;
474     }
475
476     return csi.ciCharset;
477 }
478
479
480 /******************************************************************************
481  *           create_stock_font
482  */
483 static HFONT create_stock_font( char const *fontName, const LOGFONTW *font, HKEY hkey )
484 {
485     LOGFONTW lf;
486     char  key[256];
487     char buffer[MAX_PATH];
488     DWORD type, count;
489
490     if (!hkey) return CreateFontIndirectW( font );
491
492     lf = *font;
493     sprintf(key, "%s.Height", fontName);
494     count = sizeof(buffer);
495     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
496         lf.lfHeight = atoi(buffer);
497
498     sprintf(key, "%s.Bold", fontName);
499     count = sizeof(buffer);
500     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
501         lf.lfWeight = get_bool(buffer) ? FW_BOLD : FW_NORMAL;
502
503     sprintf(key, "%s.Italic", fontName);
504     count = sizeof(buffer);
505     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
506         lf.lfItalic = get_bool(buffer);
507
508     sprintf(key, "%s.Underline", fontName);
509     count = sizeof(buffer);
510     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
511         lf.lfUnderline = get_bool(buffer);
512
513     sprintf(key, "%s.StrikeOut", fontName);
514     count = sizeof(buffer);
515     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
516         lf.lfStrikeOut = get_bool(buffer);
517     return CreateFontIndirectW( &lf );
518 }
519
520
521 #define TRACE_SEC(handle,text) \
522    TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
523
524
525 /***********************************************************************
526  *           inc_ref_count
527  *
528  * Increment the reference count of a GDI object.
529  */
530 inline static void inc_ref_count( HGDIOBJ handle )
531 {
532     GDIOBJHDR *header;
533
534     if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
535     {
536         header->dwCount++;
537         GDI_ReleaseObj( handle );
538     }
539 }
540
541
542 /***********************************************************************
543  *           dec_ref_count
544  *
545  * Decrement the reference count of a GDI object.
546  */
547 inline static void dec_ref_count( HGDIOBJ handle )
548 {
549     GDIOBJHDR *header;
550
551     if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
552     {
553         if (header->dwCount) header->dwCount--;
554         if (header->dwCount != 0x80000000) GDI_ReleaseObj( handle );
555         else
556         {
557             /* handle delayed DeleteObject*/
558             header->dwCount = 0;
559             GDI_ReleaseObj( handle );
560             TRACE( "executing delayed DeleteObject for %04x\n", handle );
561             DeleteObject( handle );
562         }
563     }
564 }
565
566
567 /***********************************************************************
568  *           GDI_Init
569  *
570  * GDI initialization.
571  */
572 BOOL GDI_Init(void)
573 {
574     HINSTANCE16 instance;
575     HKEY hkey;
576     GDIOBJHDR *ptr;
577     const struct DefaultFontInfo* deffonts;
578     int i;
579
580     if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Tweak.Fonts", &hkey))
581         hkey = 0;
582
583     /* create GDI heap */
584     if ((instance = LoadLibrary16( "GDI.EXE" )) >= 32) GDI_HeapSel = instance | 7;
585
586     /* create stock objects */
587     stock_objects[WHITE_BRUSH]  = CreateBrushIndirect( &WhiteBrush );
588     stock_objects[LTGRAY_BRUSH] = CreateBrushIndirect( &LtGrayBrush );
589     stock_objects[GRAY_BRUSH]   = CreateBrushIndirect( &GrayBrush );
590     stock_objects[DKGRAY_BRUSH] = CreateBrushIndirect( &DkGrayBrush );
591     stock_objects[BLACK_BRUSH]  = CreateBrushIndirect( &BlackBrush );
592     stock_objects[NULL_BRUSH]   = CreateBrushIndirect( &NullBrush );
593
594     stock_objects[WHITE_PEN]    = CreatePenIndirect( &WhitePen );
595     stock_objects[BLACK_PEN]    = CreatePenIndirect( &BlackPen );
596     stock_objects[NULL_PEN]     = CreatePenIndirect( &NullPen );
597
598     stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
599     stock_objects[DEFAULT_BITMAP]  = CreateBitmap( 1, 1, 1, 1, NULL );
600
601     /* language-independent stock fonts */
602     stock_objects[OEM_FIXED_FONT]      = create_stock_font( "OEMFixed", &OEMFixedFont, hkey );
603     stock_objects[ANSI_FIXED_FONT]     = create_stock_font( "AnsiFixed", &AnsiFixedFont, hkey );
604     stock_objects[ANSI_VAR_FONT]       = create_stock_font( "AnsiVar", &AnsiVarFont, hkey );
605
606     /* language-dependent stock fonts */
607     deffonts = get_default_fonts(get_default_charset());
608     stock_objects[SYSTEM_FONT]         = create_stock_font( "System", &deffonts->SystemFont, hkey );
609     stock_objects[DEVICE_DEFAULT_FONT] = create_stock_font( "DeviceDefault", &deffonts->DeviceDefaultFont, hkey );
610     stock_objects[SYSTEM_FIXED_FONT]   = create_stock_font( "SystemFixed", &deffonts->SystemFixedFont, hkey );
611     stock_objects[DEFAULT_GUI_FONT]    = create_stock_font( "DefaultGui", &deffonts->DefaultGuiFont, hkey );
612
613
614     /* clear the NOSYSTEM bit on all stock objects*/
615     for (i = 0; i < NB_STOCK_OBJECTS; i++)
616     {
617         if (!stock_objects[i])
618         {
619             if (i == 9) continue;  /* there's no stock object 9 */
620             ERR( "could not create stock object %d\n", i );
621             return FALSE;
622         }
623         ptr = GDI_GetObjPtr( stock_objects[i], MAGIC_DONTCARE );
624         ptr->wMagic &= ~OBJECT_NOSYSTEM;
625         GDI_ReleaseObj( stock_objects[i] );
626     }
627
628     if (hkey) RegCloseKey( hkey );
629
630     WineEngInit();
631
632     return TRUE;
633 }
634
635 #define FIRST_LARGE_HANDLE 16
636 #define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
637 static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
638 static int next_large_handle;
639
640 /***********************************************************************
641  *           alloc_large_heap
642  *
643  * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
644  */
645 inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
646 {
647     int i;
648     GDIOBJHDR *obj;
649
650     for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
651         if (!large_handles[i]) goto found;
652     for (i = 0; i <= next_large_handle; i++)
653         if (!large_handles[i]) goto found;
654     *handle = 0;
655     return NULL;
656
657  found:
658     if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
659     {
660         large_handles[i] = obj;
661         *handle = (HGDIOBJ)(ULONG_PTR)((i + FIRST_LARGE_HANDLE) << 2);
662         next_large_handle = i;
663     }
664     return obj;
665 }
666
667
668 /***********************************************************************
669  *           GDI_AllocObject
670  */
671 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle, const struct gdi_obj_funcs *funcs )
672 {
673     GDIOBJHDR *obj;
674     HLOCAL16 hlocal;
675
676     _EnterSysLevel( &GDI_level );
677     switch(magic)
678     {
679     default:
680         if (GDI_HeapSel)
681         {
682             if (!(hlocal = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
683             assert( hlocal & 2 );
684             obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hlocal );
685             *handle = (HGDIOBJ)(ULONG_PTR)hlocal;
686             break;
687         }
688         /* fall through */
689     case DC_MAGIC:
690     case DISABLED_DC_MAGIC:
691     case META_DC_MAGIC:
692     case METAFILE_MAGIC:
693     case METAFILE_DC_MAGIC:
694     case ENHMETAFILE_MAGIC:
695     case ENHMETAFILE_DC_MAGIC:
696     case BITMAP_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 %x\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 %x\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 %x\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 %04x\n", obj);
874         GDI_ReleaseObj( obj );
875         return TRUE;
876     }
877
878     if (header->dwCount)
879     {
880         TRACE("delayed for %04x 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("%04x\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 %4x\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("%04x %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("%08x %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("%08x %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("%08x\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("(%08x,%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=%04x %04x\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("%04x\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("%04x %d %08lx %08lx\n",
1133                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
1134     switch(nObjType)
1135     {
1136     case OBJ_PEN:
1137         /* Enumerate solid pens */
1138         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1139         {
1140             pen.lopnStyle   = PS_SOLID;
1141             pen.lopnWidth.x = 1;
1142             pen.lopnWidth.y = 0;
1143             pen.lopnColor   = solid_colors[i];
1144             retval = lpEnumFunc( &pen, lParam );
1145             TRACE("solid pen %08lx, ret=%d\n",
1146                          solid_colors[i], retval);
1147             if (!retval) break;
1148         }
1149         break;
1150
1151     case OBJ_BRUSH:
1152         /* Enumerate solid brushes */
1153         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1154         {
1155             brush.lbStyle = BS_SOLID;
1156             brush.lbColor = solid_colors[i];
1157             brush.lbHatch = 0;
1158             retval = lpEnumFunc( &brush, lParam );
1159             TRACE("solid brush %08lx, ret=%d\n",
1160                          solid_colors[i], retval);
1161             if (!retval) break;
1162         }
1163
1164         /* Now enumerate hatched brushes */
1165         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1166         {
1167             brush.lbStyle = BS_HATCHED;
1168             brush.lbColor = RGB(0,0,0);
1169             brush.lbHatch = i;
1170             retval = lpEnumFunc( &brush, lParam );
1171             TRACE("hatched brush %d, ret=%d\n",
1172                          i, retval);
1173             if (!retval) break;
1174         }
1175         break;
1176
1177     default:
1178         /* FIXME: implement Win32 types */
1179         WARN("(%d): Invalid type\n", nObjType );
1180         break;
1181     }
1182     return retval;
1183 }
1184
1185
1186 /***********************************************************************
1187  *           IsGDIObject    (GDI.462)
1188  *
1189  * returns type of object if valid (W95 system programming secrets p. 264-5)
1190  */
1191 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle16 )
1192 {
1193     UINT16 magic = 0;
1194     HGDIOBJ handle = HGDIOBJ_32( handle16 );
1195
1196     GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1197     if (object)
1198     {
1199         magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1200         GDI_ReleaseObj( handle );
1201     }
1202     return magic;
1203 }
1204
1205
1206 /***********************************************************************
1207  *           SetObjectOwner    (GDI32.@)
1208  */
1209 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1210 {
1211     /* Nothing to do */
1212 }
1213
1214
1215 /***********************************************************************
1216  *           MakeObjectPrivate    (GDI.463)
1217  *
1218  * What does that mean ?
1219  * Some little docu can be found in "Undocumented Windows",
1220  * but this is basically useless.
1221  * At least we know that this flags the GDI object's wMagic
1222  * with 0x2000 (OBJECT_PRIVATE), so we just do it.
1223  * But Wine doesn't react on that yet.
1224  */
1225 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle16, BOOL16 private )
1226 {
1227     HGDIOBJ handle = HGDIOBJ_32( handle16 );
1228     GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1229     if (!ptr)
1230     {
1231         ERR("invalid GDI object %04x !\n", handle);
1232         return;
1233     }
1234     ptr->wMagic |= OBJECT_PRIVATE;
1235     GDI_ReleaseObj( handle );
1236 }
1237
1238
1239 /***********************************************************************
1240  *           GdiFlush    (GDI32.@)
1241  */
1242 BOOL WINAPI GdiFlush(void)
1243 {
1244     return TRUE;  /* FIXME */
1245 }
1246
1247
1248 /***********************************************************************
1249  *           GdiGetBatchLimit    (GDI32.@)
1250  */
1251 DWORD WINAPI GdiGetBatchLimit(void)
1252 {
1253     return 1;  /* FIXME */
1254 }
1255
1256
1257 /***********************************************************************
1258  *           GdiSetBatchLimit    (GDI32.@)
1259  */
1260 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1261 {
1262     return 1; /* FIXME */
1263 }
1264
1265
1266 /***********************************************************************
1267  *           GdiSeeGdiDo   (GDI.452)
1268  */
1269 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1270                           WORD wParam3 )
1271 {
1272     switch (wReqType)
1273     {
1274     case 0x0001:  /* LocalAlloc */
1275         return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1276     case 0x0002:  /* LocalFree */
1277         return LOCAL_Free( GDI_HeapSel, wParam1 );
1278     case 0x0003:  /* LocalCompact */
1279         return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1280     case 0x0103:  /* LocalHeap */
1281         return GDI_HeapSel;
1282     default:
1283         WARN("(wReqType=%04x): Unknown\n", wReqType);
1284         return (DWORD)-1;
1285     }
1286 }
1287
1288 /***********************************************************************
1289  *           GdiSignalProc32     (GDI.610)
1290  */
1291 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1292                            DWORD dwFlags, HMODULE16 hModule )
1293 {
1294     return 0;
1295 }
1296
1297 /***********************************************************************
1298  *           GdiInit2     (GDI.403)
1299  *
1300  * See "Undocumented Windows"
1301  */
1302 HANDLE16 WINAPI GdiInit216(
1303     HANDLE16 h1, /* [in] GDI object */
1304     HANDLE16 h2  /* [in] global data */
1305 )
1306 {
1307     FIXME("(%04x, %04x), stub.\n", h1, h2);
1308     if (h2 == 0xffff)
1309         return 0xffff; /* undefined return value */
1310     return h1; /* FIXME: should be the memory handle of h1 */
1311 }
1312
1313 /***********************************************************************
1314  *           FinalGdiInit     (GDI.405)
1315  */
1316 void WINAPI FinalGdiInit16( HBRUSH16 hPattern /* [in] fill pattern of desktop */ )
1317 {
1318 }
1319
1320 /***********************************************************************
1321  *           GdiFreeResources   (GDI.609)
1322  */
1323 WORD WINAPI GdiFreeResources16( DWORD reserve )
1324 {
1325    return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1326                   (int)LOCAL_HeapSize( GDI_HeapSel ) );
1327 }
1328
1329
1330 /*******************************************************************
1331  *      GetColorAdjustment [GDI32.@]
1332  *
1333  *
1334  */
1335 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1336 {
1337         FIXME("GetColorAdjustment, stub\n");
1338         return 0;
1339 }
1340
1341 /*******************************************************************
1342  *      GetMiterLimit [GDI32.@]
1343  *
1344  *
1345  */
1346 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1347 {
1348         FIXME("GetMiterLimit, stub\n");
1349         return 0;
1350 }
1351
1352 /*******************************************************************
1353  *      SetMiterLimit [GDI32.@]
1354  *
1355  *
1356  */
1357 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1358 {
1359         FIXME("SetMiterLimit, stub\n");
1360         return 0;
1361 }
1362
1363 /*******************************************************************
1364  *      GdiComment [GDI32.@]
1365  *
1366  *
1367  */
1368 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1369 {
1370         FIXME("GdiComment, stub\n");
1371         return 0;
1372 }
1373 /*******************************************************************
1374  *      SetColorAdjustment [GDI32.@]
1375  *
1376  *
1377  */
1378 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1379 {
1380         FIXME("SetColorAdjustment, stub\n");
1381         return 0;
1382 }