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