gdi32: Fixed localized font style name.
[wine] / dlls / gdi32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winreg.h"
32 #include "winnls.h"
33 #include "winerror.h"
34 #include "winternl.h"
35
36 #include "gdi_private.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
40
41 #define HGDIOBJ_32(h16)   ((HGDIOBJ)(ULONG_PTR)(h16))
42
43 #define GDI_HEAP_SIZE 0xffe0
44
45 HMODULE gdi32_module = 0;
46
47 /***********************************************************************
48  *          GDI stock objects
49  */
50
51 static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
52 static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
53 static const LOGBRUSH NullBrush  = { BS_NULL, 0, 0 };
54
55 static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
56 static const LOGBRUSH GrayBrush   = { BS_SOLID, RGB(128,128,128), 0 };
57 static const LOGBRUSH DkGrayBrush = { BS_SOLID, RGB(64,64,64), 0 };
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 static const LOGBRUSH DCBrush = { BS_SOLID, RGB(255,255,255), 0 };
64 static const LOGPEN DCPen     = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
65
66 /* reserve one extra entry for the stock default bitmap */
67 /* this is what Windows does too */
68 #define NB_STOCK_OBJECTS (STOCK_LAST+2)
69
70 static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
71
72 static CRITICAL_SECTION gdi_section;
73 static CRITICAL_SECTION_DEBUG critsect_debug =
74 {
75     0, 0, &gdi_section,
76     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
77       0, 0, { (DWORD_PTR)(__FILE__ ": gdi_section") }
78 };
79 static CRITICAL_SECTION gdi_section = { &critsect_debug, -1, 0, 0, 0, 0 };
80
81
82 /****************************************************************************
83  *
84  *      language-independent stock fonts
85  *
86  */
87
88 static const LOGFONTW OEMFixedFont =
89 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
90   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
91
92 static const LOGFONTW AnsiFixedFont =
93 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
94   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
95   {'C','o','u','r','i','e','r','\0'} };
96
97 static const LOGFONTW AnsiVarFont =
98 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
99   0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
100   {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'} };
101
102 /******************************************************************************
103  *
104  *      language-dependent stock fonts
105  *
106  *      'ANSI' charset and 'DEFAULT' charset is not same.
107  *      The chars in CP_ACP should be drawn with 'DEFAULT' charset.
108  *      'ANSI' charset seems to be identical with ISO-8859-1.
109  *      'DEFAULT' charset is a language-dependent charset.
110  *
111  *      'System' font seems to be an alias for language-dependent font.
112  */
113
114 /*
115  * language-dependent stock fonts for all known charsets
116  * please see TranslateCharsetInfo (dlls/gdi/font.c) and
117  * CharsetBindingInfo (dlls/x11drv/xfont.c),
118  * and modify entries for your language if needed.
119  */
120 struct DefaultFontInfo
121 {
122         UINT            charset;
123         LOGFONTW        SystemFont;
124         LOGFONTW        DeviceDefaultFont;
125         LOGFONTW        SystemFixedFont;
126         LOGFONTW        DefaultGuiFont;
127 };
128
129 static const struct DefaultFontInfo default_fonts[] =
130 {
131     {   ANSI_CHARSET,
132         { /* System */
133           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
134            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
135            {'S','y','s','t','e','m','\0'}
136         },
137         { /* Device Default */
138           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
139            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
140            {'S','y','s','t','e','m','\0'}
141         },
142         { /* System Fixed */
143           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
144            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
145            {'C','o','u','r','i','e','r','\0'}
146         },
147         { /* DefaultGuiFont */
148           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
149            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
150            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
151         },
152     },
153     {   EASTEUROPE_CHARSET,
154         { /* System */
155           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
156            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
157            {'S','y','s','t','e','m','\0'}
158         },
159         { /* Device Default */
160           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
161            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
162            {'S','y','s','t','e','m','\0'}
163         },
164         { /* System Fixed */
165           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
166            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
167            {'C','o','u','r','i','e','r','\0'}
168         },
169         { /* DefaultGuiFont */
170           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
171            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
172            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
173         },
174     },
175     {   RUSSIAN_CHARSET,
176         { /* System */
177           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
178            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
179            {'S','y','s','t','e','m','\0'}
180         },
181         { /* Device Default */
182           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
183            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
184            {'S','y','s','t','e','m','\0'}
185         },
186         { /* System Fixed */
187           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
188            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
189            {'C','o','u','r','i','e','r','\0'}
190         },
191         { /* DefaultGuiFont */
192           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
193            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
194            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
195         },
196     },
197     {   GREEK_CHARSET,
198         { /* System */
199           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GREEK_CHARSET,
200            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
201            {'S','y','s','t','e','m','\0'}
202         },
203         { /* Device Default */
204           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GREEK_CHARSET,
205            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
206            {'S','y','s','t','e','m','\0'}
207         },
208         { /* System Fixed */
209           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
210            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
211            {'C','o','u','r','i','e','r','\0'}
212         },
213         { /* DefaultGuiFont */
214           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
215            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
216            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
217         },
218     },
219     {   TURKISH_CHARSET,
220         { /* System */
221           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, TURKISH_CHARSET,
222            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
223            {'S','y','s','t','e','m','\0'}
224         },
225         { /* Device Default */
226           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, TURKISH_CHARSET,
227            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
228            {'S','y','s','t','e','m','\0'}
229         },
230         { /* System Fixed */
231           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
232            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
233            {'C','o','u','r','i','e','r','\0'}
234         },
235         { /* DefaultGuiFont */
236           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
237            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
238            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
239         },
240     },
241     {   HEBREW_CHARSET,
242         { /* System */
243           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, HEBREW_CHARSET,
244            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
245            {'S','y','s','t','e','m','\0'}
246         },
247         { /* Device Default */
248           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, HEBREW_CHARSET,
249            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
250            {'S','y','s','t','e','m','\0'}
251         },
252         { /* System Fixed */
253           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
254            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
255            {'C','o','u','r','i','e','r','\0'}
256         },
257         { /* DefaultGuiFont */
258           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
259            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
260            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
261         },
262     },
263     {   ARABIC_CHARSET,
264         { /* System */
265           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ARABIC_CHARSET,
266            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
267            {'S','y','s','t','e','m','\0'}
268         },
269         { /* Device Default */
270           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ARABIC_CHARSET,
271            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
272            {'S','y','s','t','e','m','\0'}
273         },
274         { /* System Fixed */
275           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
276            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
277            {'C','o','u','r','i','e','r','\0'}
278         },
279         { /* DefaultGuiFont */
280           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
281            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
282            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
283         },
284     },
285     {   BALTIC_CHARSET,
286         { /* System */
287           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, BALTIC_CHARSET,
288            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
289            {'S','y','s','t','e','m','\0'}
290         },
291         { /* Device Default */
292           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, BALTIC_CHARSET,
293            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
294            {'S','y','s','t','e','m','\0'}
295         },
296         { /* System Fixed */
297           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
298            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
299            {'C','o','u','r','i','e','r','\0'}
300         },
301         { /* DefaultGuiFont */
302           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
303            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
304            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
305         },
306     },
307     {   THAI_CHARSET,
308         { /* System */
309           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, THAI_CHARSET,
310            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
311            {'S','y','s','t','e','m','\0'}
312         },
313         { /* Device Default */
314           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, THAI_CHARSET,
315            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
316            {'S','y','s','t','e','m','\0'}
317         },
318         { /* System Fixed */
319           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
320            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
321            {'C','o','u','r','i','e','r','\0'}
322         },
323         { /* DefaultGuiFont */
324           -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
325            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
326            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
327         },
328     },
329     {   SHIFTJIS_CHARSET,
330         { /* System */
331           18, 8, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
332            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
333            {'S','y','s','t','e','m','\0'}
334         },
335         { /* Device Default */
336           18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
337            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
338            {'S','y','s','t','e','m','\0'}
339         },
340         { /* System Fixed */
341           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
342            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
343            {'C','o','u','r','i','e','r','\0'}
344         },
345         { /* DefaultGuiFont */
346           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
347            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
348            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
349         },
350     },
351     {   GB2312_CHARSET,
352         { /* System */
353           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET,
354            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
355            {'S','y','s','t','e','m','\0'}
356         },
357         { /* Device Default */
358           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET,
359            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
360            {'S','y','s','t','e','m','\0'}
361         },
362         { /* System Fixed */
363           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
364            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
365            {'C','o','u','r','i','e','r','\0'}
366         },
367         { /* DefaultGuiFont */
368           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
369            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
370            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
371         },
372     },
373     {   HANGEUL_CHARSET,
374         { /* System */
375           16, 8, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
376            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
377            {'S','y','s','t','e','m','\0'}
378         },
379         { /* Device Default */
380           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
381            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
382            {'S','y','s','t','e','m','\0'}
383         },
384         { /* System Fixed */
385           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
386            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
387            {'C','o','u','r','i','e','r','\0'}
388         },
389         { /* DefaultGuiFont */
390           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
391            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
392            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
393         },
394     },
395     {   CHINESEBIG5_CHARSET,
396         { /* System */
397           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
398            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
399            {'S','y','s','t','e','m','\0'}
400         },
401         { /* Device Default */
402           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
403            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
404            {'S','y','s','t','e','m','\0'}
405         },
406         { /* System Fixed */
407           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
408            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
409            {'C','o','u','r','i','e','r','\0'}
410         },
411         { /* DefaultGuiFont */
412           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
413            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
414            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
415         },
416     },
417     {   JOHAB_CHARSET,
418         { /* System */
419           16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, JOHAB_CHARSET,
420            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
421            {'S','y','s','t','e','m','\0'}
422         },
423         { /* Device Default */
424           16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, JOHAB_CHARSET,
425            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
426            {'S','y','s','t','e','m','\0'}
427         },
428         { /* System Fixed */
429           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
430            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
431            {'C','o','u','r','i','e','r','\0'}
432         },
433         { /* DefaultGuiFont */
434           -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
435            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
436            {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
437         },
438     },
439 };
440
441
442 /*************************************************************************
443  * __wine_make_gdi_object_system    (GDI32.@)
444  *
445  * USER has to tell GDI that its system brushes and pens are non-deletable.
446  * For a description of the GDI object magics and their flags,
447  * see "Undocumented Windows" (wrong about the OBJECT_NOSYSTEM flag, though).
448  */
449 void CDECL __wine_make_gdi_object_system( HGDIOBJ handle, BOOL set)
450 {
451     GDIOBJHDR *ptr = GDI_GetObjPtr( handle, 0 );
452     ptr->system = !!set;
453     GDI_ReleaseObj( handle );
454 }
455
456 /******************************************************************************
457  *      get_default_fonts
458  */
459 static const struct DefaultFontInfo* get_default_fonts(UINT charset)
460 {
461         unsigned int n;
462
463         for(n=0;n<(sizeof(default_fonts)/sizeof(default_fonts[0]));n++)
464         {
465                 if ( default_fonts[n].charset == charset )
466                         return &default_fonts[n];
467         }
468
469         FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
470         return &default_fonts[0];
471 }
472
473
474 /******************************************************************************
475  *      get_default_charset    (internal)
476  *
477  * get the language-dependent charset that can handle CP_ACP correctly.
478  */
479 static UINT get_default_charset( void )
480 {
481     CHARSETINFO     csi;
482     UINT    uACP;
483
484     uACP = GetACP();
485     csi.ciCharset = ANSI_CHARSET;
486     if ( !TranslateCharsetInfo( ULongToPtr(uACP), &csi, TCI_SRCCODEPAGE ) )
487     {
488         FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", uACP );
489         return ANSI_CHARSET;
490     }
491
492     return csi.ciCharset;
493 }
494
495
496 /***********************************************************************
497  *           GDI_inc_ref_count
498  *
499  * Increment the reference count of a GDI object.
500  */
501 HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle )
502 {
503     GDIOBJHDR *header;
504
505     if ((header = GDI_GetObjPtr( handle, 0 )))
506     {
507         header->selcount++;
508         GDI_ReleaseObj( handle );
509     }
510     else handle = 0;
511
512     return handle;
513 }
514
515
516 /***********************************************************************
517  *           GDI_dec_ref_count
518  *
519  * Decrement the reference count of a GDI object.
520  */
521 BOOL GDI_dec_ref_count( HGDIOBJ handle )
522 {
523     GDIOBJHDR *header;
524
525     if ((header = GDI_GetObjPtr( handle, 0 )))
526     {
527         assert( header->selcount );
528         if (!--header->selcount && header->deleted)
529         {
530             /* handle delayed DeleteObject*/
531             header->deleted = 0;
532             GDI_ReleaseObj( handle );
533             TRACE( "executing delayed DeleteObject for %p\n", handle );
534             DeleteObject( handle );
535         }
536         else GDI_ReleaseObj( handle );
537     }
538     return header != NULL;
539 }
540
541
542 /***********************************************************************
543  *           DllMain
544  *
545  * GDI initialization.
546  */
547 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
548 {
549     const struct DefaultFontInfo* deffonts;
550     int i;
551
552     if (reason != DLL_PROCESS_ATTACH) return TRUE;
553
554     gdi32_module = inst;
555     DisableThreadLibraryCalls( inst );
556     WineEngInit();
557
558     /* create stock objects */
559     stock_objects[WHITE_BRUSH]  = CreateBrushIndirect( &WhiteBrush );
560     stock_objects[LTGRAY_BRUSH] = CreateBrushIndirect( &LtGrayBrush );
561     stock_objects[GRAY_BRUSH]   = CreateBrushIndirect( &GrayBrush );
562     stock_objects[DKGRAY_BRUSH] = CreateBrushIndirect( &DkGrayBrush );
563     stock_objects[BLACK_BRUSH]  = CreateBrushIndirect( &BlackBrush );
564     stock_objects[NULL_BRUSH]   = CreateBrushIndirect( &NullBrush );
565
566     stock_objects[WHITE_PEN]    = CreatePenIndirect( &WhitePen );
567     stock_objects[BLACK_PEN]    = CreatePenIndirect( &BlackPen );
568     stock_objects[NULL_PEN]     = CreatePenIndirect( &NullPen );
569
570     stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
571     stock_objects[DEFAULT_BITMAP]  = CreateBitmap( 1, 1, 1, 1, NULL );
572
573     /* language-independent stock fonts */
574     stock_objects[OEM_FIXED_FONT]      = CreateFontIndirectW( &OEMFixedFont );
575     stock_objects[ANSI_FIXED_FONT]     = CreateFontIndirectW( &AnsiFixedFont );
576     stock_objects[ANSI_VAR_FONT]       = CreateFontIndirectW( &AnsiVarFont );
577
578     /* language-dependent stock fonts */
579     deffonts = get_default_fonts(get_default_charset());
580     stock_objects[SYSTEM_FONT]         = CreateFontIndirectW( &deffonts->SystemFont );
581     stock_objects[DEVICE_DEFAULT_FONT] = CreateFontIndirectW( &deffonts->DeviceDefaultFont );
582     stock_objects[SYSTEM_FIXED_FONT]   = CreateFontIndirectW( &deffonts->SystemFixedFont );
583     stock_objects[DEFAULT_GUI_FONT]    = CreateFontIndirectW( &deffonts->DefaultGuiFont );
584
585     stock_objects[DC_BRUSH]     = CreateBrushIndirect( &DCBrush );
586     stock_objects[DC_PEN]       = CreatePenIndirect( &DCPen );
587
588     /* clear the NOSYSTEM bit on all stock objects*/
589     for (i = 0; i < NB_STOCK_OBJECTS; i++)
590     {
591         if (!stock_objects[i])
592         {
593             if (i == 9) continue;  /* there's no stock object 9 */
594             ERR( "could not create stock object %d\n", i );
595             return FALSE;
596         }
597         __wine_make_gdi_object_system( stock_objects[i], TRUE );
598     }
599
600     return TRUE;
601 }
602
603 #define FIRST_LARGE_HANDLE 16
604 #define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
605 static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
606 static int next_large_handle;
607 static LONG debug_count;
608
609 static const char *gdi_obj_type( unsigned type )
610 {
611     switch ( type )
612     {
613         case OBJ_PEN: return "OBJ_PEN";
614         case OBJ_BRUSH: return "OBJ_BRUSH";
615         case OBJ_DC: return "OBJ_DC";
616         case OBJ_METADC: return "OBJ_METADC";
617         case OBJ_PAL: return "OBJ_PAL";
618         case OBJ_FONT: return "OBJ_FONT";
619         case OBJ_BITMAP: return "OBJ_BITMAP";
620         case OBJ_REGION: return "OBJ_REGION";
621         case OBJ_METAFILE: return "OBJ_METAFILE";
622         case OBJ_MEMDC: return "OBJ_MEMDC";
623         case OBJ_EXTPEN: return "OBJ_EXTPEN";
624         case OBJ_ENHMETADC: return "OBJ_ENHMETADC";
625         case OBJ_ENHMETAFILE: return "OBJ_ENHMETAFILE";
626         case OBJ_COLORSPACE: return "OBJ_COLORSPACE";
627         default: return "UNKNOWN";
628     }
629 }
630
631 static void dump_gdi_objects( void )
632 {
633     int i;
634
635     TRACE( "%u objects:\n", MAX_LARGE_HANDLES );
636
637     EnterCriticalSection( &gdi_section );
638     for (i = 0; i < MAX_LARGE_HANDLES; i++)
639     {
640         if (!large_handles[i])
641         {
642             TRACE( "index %d handle %p FREE\n", i, (HGDIOBJ)(ULONG_PTR)((i + FIRST_LARGE_HANDLE) << 2) );
643             continue;
644         }
645         TRACE( "handle %p obj %p type %s selcount %u deleted %u\n",
646                (HGDIOBJ)(ULONG_PTR)((i + FIRST_LARGE_HANDLE) << 2),
647                large_handles[i], gdi_obj_type( large_handles[i]->type ),
648                large_handles[i]->selcount, large_handles[i]->deleted );
649     }
650     LeaveCriticalSection( &gdi_section );
651 }
652
653 /***********************************************************************
654  *           alloc_gdi_handle
655  *
656  * Allocate a GDI handle for an object, which must have been allocated on the process heap.
657  */
658 HGDIOBJ alloc_gdi_handle( GDIOBJHDR *obj, WORD type, const struct gdi_obj_funcs *funcs )
659 {
660     int i;
661
662     /* initialize the object header */
663     obj->type     = type;
664     obj->system   = 0;
665     obj->deleted  = 0;
666     obj->selcount = 0;
667     obj->funcs    = funcs;
668     obj->hdcs     = NULL;
669
670     EnterCriticalSection( &gdi_section );
671     for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
672         if (!large_handles[i]) goto found;
673     for (i = 0; i <= next_large_handle; i++)
674         if (!large_handles[i]) goto found;
675     LeaveCriticalSection( &gdi_section );
676
677     ERR( "out of GDI object handles, expect a crash\n" );
678     if (TRACE_ON(gdi)) dump_gdi_objects();
679     return 0;
680
681  found:
682     large_handles[i] = obj;
683     next_large_handle = i;
684     LeaveCriticalSection( &gdi_section );
685     TRACE( "allocated %s %p %u/%u\n",
686            gdi_obj_type(type), (HGDIOBJ)(ULONG_PTR)((i + FIRST_LARGE_HANDLE) << 2),
687            InterlockedIncrement( &debug_count ), MAX_LARGE_HANDLES );
688     return (HGDIOBJ)(ULONG_PTR)((i + FIRST_LARGE_HANDLE) << 2);
689 }
690
691
692 /***********************************************************************
693  *           free_gdi_handle
694  *
695  * Free a GDI handle and return a pointer to the object.
696  */
697 void *free_gdi_handle( HGDIOBJ handle )
698 {
699     GDIOBJHDR *object = NULL;
700     int i;
701
702     i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
703     if (i >= 0 && i < MAX_LARGE_HANDLES)
704     {
705         EnterCriticalSection( &gdi_section );
706         object = large_handles[i];
707         large_handles[i] = NULL;
708         LeaveCriticalSection( &gdi_section );
709     }
710     if (object)
711     {
712         TRACE( "freed %s %p %u/%u\n", gdi_obj_type( object->type ), handle,
713                InterlockedDecrement( &debug_count ) + 1, MAX_LARGE_HANDLES );
714         object->type  = 0;  /* mark it as invalid */
715         object->funcs = NULL;
716     }
717     return object;
718 }
719
720
721 /***********************************************************************
722  *           GDI_GetObjPtr
723  *
724  * Return a pointer to the GDI object associated to the handle.
725  * Return NULL if the object has the wrong magic number.
726  * The object must be released with GDI_ReleaseObj.
727  */
728 void *GDI_GetObjPtr( HGDIOBJ handle, WORD type )
729 {
730     GDIOBJHDR *ptr = NULL;
731     int i;
732
733     EnterCriticalSection( &gdi_section );
734
735     i = ((UINT_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
736     if (i >= 0 && i < MAX_LARGE_HANDLES)
737     {
738         ptr = large_handles[i];
739         if (ptr && type && ptr->type != type) ptr = NULL;
740     }
741
742     if (!ptr)
743     {
744         LeaveCriticalSection( &gdi_section );
745         WARN( "Invalid handle %p\n", handle );
746     }
747
748     return ptr;
749 }
750
751
752 /***********************************************************************
753  *           GDI_ReleaseObj
754  *
755  */
756 void GDI_ReleaseObj( HGDIOBJ handle )
757 {
758     LeaveCriticalSection( &gdi_section );
759 }
760
761
762 /***********************************************************************
763  *           GDI_CheckNotLock
764  */
765 void GDI_CheckNotLock(void)
766 {
767     if (gdi_section.OwningThread == ULongToHandle(GetCurrentThreadId()) && gdi_section.RecursionCount)
768     {
769         ERR( "BUG: holding GDI lock\n" );
770         DebugBreak();
771     }
772 }
773
774
775 /***********************************************************************
776  *           DeleteObject    (GDI32.@)
777  *
778  * Delete a Gdi object.
779  *
780  * PARAMS
781  *  obj [I] Gdi object to delete
782  *
783  * RETURNS
784  *  Success: TRUE. If obj was not returned from GetStockObject(), any resources
785  *           it consumed are released.
786  *  Failure: FALSE, if obj is not a valid Gdi object, or is currently selected
787  *           into a DC.
788  */
789 BOOL WINAPI DeleteObject( HGDIOBJ obj )
790 {
791       /* Check if object is valid */
792
793     struct hdc_list *hdcs_head;
794     const struct gdi_obj_funcs *funcs;
795     GDIOBJHDR * header;
796
797     if (HIWORD(obj)) return FALSE;
798
799     if (!(header = GDI_GetObjPtr( obj, 0 ))) return FALSE;
800
801     if (header->system)
802     {
803         TRACE("Preserving system object %p\n", obj);
804         GDI_ReleaseObj( obj );
805         return TRUE;
806     }
807
808     while ((hdcs_head = header->hdcs) != NULL)
809     {
810         DC *dc = get_dc_ptr(hdcs_head->hdc);
811
812         header->hdcs = hdcs_head->next;
813         TRACE("hdc %p has interest in %p\n", hdcs_head->hdc, obj);
814
815         if(dc)
816         {
817             PHYSDEV physdev = GET_DC_PHYSDEV( dc, pDeleteObject );
818             GDI_ReleaseObj( obj );  /* release the GDI lock */
819             physdev->funcs->pDeleteObject( physdev, obj );
820             header = GDI_GetObjPtr( obj, 0 );  /* and grab it again */
821             release_dc_ptr( dc );
822         }
823         HeapFree(GetProcessHeap(), 0, hdcs_head);
824         if (!header) return FALSE;
825     }
826
827     if (header->selcount)
828     {
829         TRACE("delayed for %p because object in use, count %u\n", obj, header->selcount );
830         header->deleted = 1;  /* mark for delete */
831         GDI_ReleaseObj( obj );
832         return TRUE;
833     }
834
835     TRACE("%p\n", obj );
836
837       /* Delete object */
838
839     funcs = header->funcs;
840     GDI_ReleaseObj( obj );
841     if (funcs && funcs->pDeleteObject)
842         return funcs->pDeleteObject( obj );
843     else
844         return FALSE;
845 }
846
847 /***********************************************************************
848  *           GDI_hdc_using_object
849  *
850  * Call this if the dc requires DeleteObject notification
851  */
852 BOOL GDI_hdc_using_object(HGDIOBJ obj, HDC hdc)
853 {
854     GDIOBJHDR * header;
855     struct hdc_list **pphdc;
856
857     TRACE("obj %p hdc %p\n", obj, hdc);
858
859     if (!(header = GDI_GetObjPtr( obj, 0 ))) return FALSE;
860
861     if (header->system)
862     {
863         GDI_ReleaseObj(obj);
864         return FALSE;
865     }
866
867     for(pphdc = &header->hdcs; *pphdc; pphdc = &(*pphdc)->next)
868         if((*pphdc)->hdc == hdc)
869             break;
870
871     if(!*pphdc) {
872         *pphdc = HeapAlloc(GetProcessHeap(), 0, sizeof(**pphdc));
873         (*pphdc)->hdc = hdc;
874         (*pphdc)->next = NULL;
875     }
876
877     GDI_ReleaseObj(obj);
878     return TRUE;
879 }
880
881 /***********************************************************************
882  *           GDI_hdc_not_using_object
883  *
884  */
885 BOOL GDI_hdc_not_using_object(HGDIOBJ obj, HDC hdc)
886 {
887     GDIOBJHDR * header;
888     struct hdc_list *phdc, **prev;
889
890     TRACE("obj %p hdc %p\n", obj, hdc);
891
892     if (!(header = GDI_GetObjPtr( obj, 0 ))) return FALSE;
893
894     if (header->system)
895     {
896         GDI_ReleaseObj(obj);
897         return FALSE;
898     }
899
900     phdc = header->hdcs;
901     prev = &header->hdcs;
902
903     while(phdc) {
904         if(phdc->hdc == hdc) {
905             *prev = phdc->next;
906             HeapFree(GetProcessHeap(), 0, phdc);
907             phdc = *prev;
908         } else {
909             prev = &phdc->next;
910             phdc = phdc->next;
911         }
912     }
913
914     GDI_ReleaseObj(obj);
915     return TRUE;
916 }
917
918 /***********************************************************************
919  *           GetStockObject    (GDI32.@)
920  */
921 HGDIOBJ WINAPI GetStockObject( INT obj )
922 {
923     HGDIOBJ ret;
924     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
925     ret = stock_objects[obj];
926     TRACE("returning %p\n", ret );
927     return ret;
928 }
929
930
931 /***********************************************************************
932  *           GetObjectA    (GDI32.@)
933  */
934 INT WINAPI GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
935 {
936     const struct gdi_obj_funcs *funcs;
937     GDIOBJHDR * ptr;
938     INT result = 0;
939
940     TRACE("%p %d %p\n", handle, count, buffer );
941
942     if (!(ptr = GDI_GetObjPtr( handle, 0 ))) return 0;
943     funcs = ptr->funcs;
944     GDI_ReleaseObj( handle );
945
946     if (funcs && funcs->pGetObjectA)
947     {
948         if (buffer && ((ULONG_PTR)buffer >> 16) == 0) /* catch apps getting argument order wrong */
949             SetLastError( ERROR_NOACCESS );
950         else
951             result = funcs->pGetObjectA( handle, count, buffer );
952     }
953     else
954         SetLastError( ERROR_INVALID_HANDLE );
955
956     return result;
957 }
958
959 /***********************************************************************
960  *           GetObjectW    (GDI32.@)
961  */
962 INT WINAPI GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
963 {
964     const struct gdi_obj_funcs *funcs;
965     GDIOBJHDR * ptr;
966     INT result = 0;
967     TRACE("%p %d %p\n", handle, count, buffer );
968
969     if (!(ptr = GDI_GetObjPtr( handle, 0 ))) return 0;
970     funcs = ptr->funcs;
971     GDI_ReleaseObj( handle );
972
973     if (funcs && funcs->pGetObjectW)
974     {
975         if (buffer && ((ULONG_PTR)buffer >> 16) == 0) /* catch apps getting argument order wrong */
976             SetLastError( ERROR_NOACCESS );
977         else
978             result = funcs->pGetObjectW( handle, count, buffer );
979     }
980     else
981         SetLastError( ERROR_INVALID_HANDLE );
982
983     return result;
984 }
985
986 /***********************************************************************
987  *           GetObjectType    (GDI32.@)
988  */
989 DWORD WINAPI GetObjectType( HGDIOBJ handle )
990 {
991     GDIOBJHDR * ptr;
992     DWORD result;
993
994     if (!(ptr = GDI_GetObjPtr( handle, 0 )))
995     {
996         SetLastError( ERROR_INVALID_HANDLE );
997         return 0;
998     }
999     result = ptr->type;
1000     GDI_ReleaseObj( handle );
1001     TRACE("%p -> %u\n", handle, result );
1002     return result;
1003 }
1004
1005 /***********************************************************************
1006  *           GetCurrentObject           (GDI32.@)
1007  *
1008  * Get the currently selected object of a given type in a device context.
1009  *
1010  * PARAMS
1011  *  hdc  [I] Device context to get the current object from
1012  *  type [I] Type of current object to get (OBJ_* defines from "wingdi.h")
1013  *
1014  * RETURNS
1015  *  Success: The current object of the given type selected in hdc.
1016  *  Failure: A NULL handle.
1017  *
1018  * NOTES
1019  * - only the following object types are supported:
1020  *| OBJ_PEN
1021  *| OBJ_BRUSH
1022  *| OBJ_PAL
1023  *| OBJ_FONT
1024  *| OBJ_BITMAP
1025  */
1026 HGDIOBJ WINAPI GetCurrentObject(HDC hdc,UINT type)
1027 {
1028     HGDIOBJ ret = 0;
1029     DC * dc = get_dc_ptr( hdc );
1030
1031     if (!dc) return 0;
1032
1033     switch (type) {
1034         case OBJ_EXTPEN: /* fall through */
1035         case OBJ_PEN:    ret = dc->hPen; break;
1036         case OBJ_BRUSH:  ret = dc->hBrush; break;
1037         case OBJ_PAL:    ret = dc->hPalette; break;
1038         case OBJ_FONT:   ret = dc->hFont; break;
1039         case OBJ_BITMAP: ret = dc->hBitmap; break;
1040
1041         /* tests show that OBJ_REGION is explicitly ignored */
1042         case OBJ_REGION: break;
1043         default:
1044             /* the SDK only mentions those above */
1045             FIXME("(%p,%d): unknown type.\n",hdc,type);
1046             break;
1047     }
1048     release_dc_ptr( dc );
1049     return ret;
1050 }
1051
1052
1053 /***********************************************************************
1054  *           SelectObject    (GDI32.@)
1055  *
1056  * Select a Gdi object into a device context.
1057  *
1058  * PARAMS
1059  *  hdc  [I] Device context to associate the object with
1060  *  hObj [I] Gdi object to associate with hdc
1061  *
1062  * RETURNS
1063  *  Success: A non-NULL handle representing the previously selected object of
1064  *           the same type as hObj.
1065  *  Failure: A NULL object. If hdc is invalid, GetLastError() returns ERROR_INVALID_HANDLE.
1066  *           if hObj is not a valid object handle, no last error is set. In either
1067  *           case, hdc is unaffected by the call.
1068  */
1069 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj )
1070 {
1071     HGDIOBJ ret = 0;
1072     GDIOBJHDR *header;
1073
1074     TRACE( "(%p,%p)\n", hdc, hObj );
1075
1076     header = GDI_GetObjPtr( hObj, 0 );
1077     if (header)
1078     {
1079         const struct gdi_obj_funcs *funcs = header->funcs;
1080         GDI_ReleaseObj( hObj );
1081         if (funcs && funcs->pSelectObject) ret = funcs->pSelectObject( hObj, hdc );
1082     }
1083     return ret;
1084 }
1085
1086
1087 /***********************************************************************
1088  *           UnrealizeObject    (GDI32.@)
1089  */
1090 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
1091 {
1092     BOOL result = FALSE;
1093     GDIOBJHDR * header = GDI_GetObjPtr( obj, 0 );
1094
1095     if (header)
1096     {
1097         const struct gdi_obj_funcs *funcs = header->funcs;
1098
1099         GDI_ReleaseObj( obj );
1100         if (funcs && funcs->pUnrealizeObject)
1101             result = header->funcs->pUnrealizeObject( obj );
1102         else
1103             result = TRUE;
1104     }
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     UINT i;
1129     INT retval = 0;
1130     LOGPEN pen;
1131     LOGBRUSH brush;
1132
1133     TRACE("%p %d %p %08lx\n", hdc, nObjType, 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 %08x, 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 %08x, 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  *           SetObjectOwner    (GDI32.@)
1188  */
1189 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1190 {
1191     /* Nothing to do */
1192 }
1193
1194 /***********************************************************************
1195  *           GdiInitializeLanguagePack    (GDI32.@)
1196  */
1197 DWORD WINAPI GdiInitializeLanguagePack( DWORD arg )
1198 {
1199     FIXME("stub\n");
1200     return 0;
1201 }
1202
1203 /***********************************************************************
1204  *           GdiFlush    (GDI32.@)
1205  */
1206 BOOL WINAPI GdiFlush(void)
1207 {
1208     return TRUE;  /* FIXME */
1209 }
1210
1211
1212 /***********************************************************************
1213  *           GdiGetBatchLimit    (GDI32.@)
1214  */
1215 DWORD WINAPI GdiGetBatchLimit(void)
1216 {
1217     return 1;  /* FIXME */
1218 }
1219
1220
1221 /***********************************************************************
1222  *           GdiSetBatchLimit    (GDI32.@)
1223  */
1224 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1225 {
1226     return 1; /* FIXME */
1227 }
1228
1229
1230 /*******************************************************************
1231  *      GetColorAdjustment [GDI32.@]
1232  *
1233  *
1234  */
1235 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1236 {
1237         FIXME("stub\n");
1238         return 0;
1239 }
1240
1241 /*******************************************************************
1242  *      GdiComment [GDI32.@]
1243  *
1244  *
1245  */
1246 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1247 {
1248     DC *dc = get_dc_ptr(hdc);
1249     BOOL ret = FALSE;
1250
1251     if(dc)
1252     {
1253         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGdiComment );
1254         ret = physdev->funcs->pGdiComment( physdev, cbSize, lpData );
1255         release_dc_ptr( dc );
1256     }
1257     return ret;
1258 }
1259
1260 /*******************************************************************
1261  *      SetColorAdjustment [GDI32.@]
1262  *
1263  *
1264  */
1265 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1266 {
1267         FIXME("stub\n");
1268         return 0;
1269 }