Changed the GDI driver interface to pass an opaque PHYSDEV pointer
[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 #include "wine/winbase16.h"
32
33 #include "bitmap.h"
34 #include "brush.h"
35 #include "font.h"
36 #include "local.h"
37 #include "palette.h"
38 #include "pen.h"
39 #include "region.h"
40 #include "wine/debug.h"
41 #include "gdi.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
44
45 /* ### start build ### */
46 extern WORD CALLBACK GDI_CallTo16_word_ll(GOBJENUMPROC16,LONG,LONG);
47 /* ### stop build ### */
48
49 /***********************************************************************
50  *          GDI stock objects 
51  */
52
53 static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
54 static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
55 static const LOGBRUSH NullBrush  = { BS_NULL, 0, 0 };
56
57 /* FIXME: these should perhaps be BS_HATCHED, at least for 1 bitperpixel */
58 static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
59 static const LOGBRUSH GrayBrush   = { BS_SOLID, RGB(128,128,128), 0 };
60
61 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
62 /* NB_HATCH_STYLES is an index into HatchBrushes */
63 static const LOGBRUSH DkGrayBrush = { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES };
64
65 static const LOGPEN WhitePen = { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
66 static const LOGPEN BlackPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
67 static const LOGPEN NullPen  = { PS_NULL,  { 0, 0 }, 0 };
68
69
70 /* reserve one extra entry for the stock default bitmap */
71 /* this is what Windows does too */
72 #define NB_STOCK_OBJECTS (STOCK_LAST+2)
73
74 static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
75
76 static SYSLEVEL GDI_level = { CRITICAL_SECTION_INIT("GDI_level"), 3 };
77 static WORD GDI_HeapSel;
78
79 inline static BOOL get_bool(char *buffer)
80 {
81     return (buffer[0] == 'y' || buffer[0] == 'Y' ||
82             buffer[0] == 't' || buffer[0] == 'T' ||
83             buffer[0] == '1');
84 }
85
86
87 /****************************************************************************
88  *
89  *      language-independent stock fonts
90  *
91  */
92
93 static const LOGFONTW OEMFixedFont =
94 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
95   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
96
97 static const LOGFONTW AnsiFixedFont =
98 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
99   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
100
101 static const LOGFONTW AnsiVarFont =
102 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
103   0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
104   {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'} };
105
106 /******************************************************************************
107  *
108  *      language-dependent stock fonts
109  *
110  *      'ANSI' charset and 'DEFAULT' charset is not same.
111  *      The chars in CP_ACP should be drawn with 'DEFAULT' charset.
112  *      'ANSI' charset seems to be identical with ISO-8859-1.
113  *      'DEFAULT' charset is a language-dependent charset.
114  *
115  *      'System' font seems to be an alias for language-dependent font.
116  */
117
118 /*
119  * language-dependenet stock fonts for all known charsets
120  * please see TranslateCharsetInfo (objects/font.c) and
121  * CharsetBindingInfo (graphics/x11drv/xfont.c),
122  * and modify entries for your language if needed.
123  */
124 struct DefaultFontInfo
125 {
126         UINT            charset;
127         LOGFONTW        SystemFont;
128         LOGFONTW        DeviceDefaultFont;
129         LOGFONTW        SystemFixedFont;
130         LOGFONTW        DefaultGuiFont;
131 };
132
133 static const struct DefaultFontInfo default_fonts[] =
134 {
135     {   ANSI_CHARSET,
136         { /* System */
137           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
138            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
139            {'S','y','s','t','e','m','\0'}
140         },
141         { /* Device Default */
142           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
143            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
144            {'\0'}
145         },
146         { /* System Fixed */
147           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
148            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
149            {'\0'}
150         },
151         { /* DefaultGuiFont */
152          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
153            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
154            {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
155         },
156     },
157     {   EASTEUROPE_CHARSET,
158         { /* System */
159           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
160            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
161            {'S','y','s','t','e','m','\0'}
162         },
163         { /* Device Default */
164           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
165            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
166            {'\0'}
167         },
168         { /* System Fixed */
169           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
170            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
171            {'\0'}
172         },
173         { /* DefaultGuiFont */
174          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
175            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
176            {'\0'}       /* FIXME - what is the native font??? */
177         },
178     },
179     {   RUSSIAN_CHARSET,
180         { /* System */
181           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
182            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
183            {'S','y','s','t','e','m','\0'}
184         },
185         { /* Device Default */
186           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
187            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
188            {'\0'}
189         },
190         { /* System Fixed */
191           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
192            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
193            {'\0'}
194         },
195         { /* DefaultGuiFont */
196          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
197            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
198            {'\0'}       /* FIXME - what is the native font??? */
199         },
200     },
201     {   GREEK_CHARSET,
202         { /* System */
203           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
204            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
205            {'S','y','s','t','e','m','\0'}
206         },
207         { /* Device Default */
208           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
209            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
210            {'\0'}
211         },
212         { /* System Fixed */
213           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
214            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
215            {'\0'}
216         },
217         { /* DefaultGuiFont */
218          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
219            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
220            {'\0'}       /* FIXME - what is the native font??? */
221         },
222     },
223     {   TURKISH_CHARSET,
224         { /* System */
225           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
226            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
227            {'S','y','s','t','e','m','\0'}
228         },
229         { /* Device Default */
230           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
231            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
232            {'\0'}
233         },
234         { /* System Fixed */
235           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
236            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
237            {'\0'}
238         },
239         { /* DefaultGuiFont */
240          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
241            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
242            {'\0'}       /* FIXME - what is the native font??? */
243         },
244     },
245     {   HEBREW_CHARSET,
246         { /* System */
247           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
248            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
249            {'S','y','s','t','e','m','\0'}
250         },
251         { /* Device Default */
252           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
253            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
254            {'\0'}
255         },
256         { /* System Fixed */
257           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
258            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
259            {'\0'}
260         },
261         { /* DefaultGuiFont */
262          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
263            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
264            {'\0'}       /* FIXME - what is the native font??? */
265         },
266     },
267     {   ARABIC_CHARSET,
268         { /* System */
269           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
270            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
271            {'S','y','s','t','e','m','\0'}
272         },
273         { /* Device Default */
274           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
275            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
276            {'\0'}
277         },
278         { /* System Fixed */
279           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
280            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
281            {'\0'}
282         },
283         { /* DefaultGuiFont */
284          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
285            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
286            {'\0'}       /* FIXME - what is the native font??? */
287         },
288     },
289     {   BALTIC_CHARSET,
290         { /* System */
291           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
292            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
293            {'S','y','s','t','e','m','\0'}
294         },
295         { /* Device Default */
296           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
297            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
298            {'\0'}
299         },
300         { /* System Fixed */
301           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
302            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
303            {'\0'}
304         },
305         { /* DefaultGuiFont */
306          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
307            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
308            {'\0'}       /* FIXME - what is the native font??? */
309         },
310     },
311
312     {   THAI_CHARSET,
313         { /* System */
314           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
315            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
316            {'S','y','s','t','e','m','\0'}
317         },
318         { /* Device Default */
319           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
320            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
321            {'\0'}
322         },
323         { /* System Fixed */
324           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
325            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
326            {'\0'}
327         },
328         { /* DefaultGuiFont */
329          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
330            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
331            {'\0'}       /* FIXME - what is the native font??? */
332         },
333     },
334     {   SHIFTJIS_CHARSET,
335         { /* System */
336           16, 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         { /* Device Default */
341           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
342            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
343            {'\0'}
344         },
345         { /* System Fixed */
346           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
347            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
348            {'\0'}
349         },
350         { /* DefaultGuiFont */
351          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
352            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
353            {'\0'}       /* FIXME - mbtowc of native ("MS P gothic") */
354         },
355     },
356     {   GB2312_CHARSET,
357         { /* System */
358           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
359            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
360            {'S','y','s','t','e','m','\0'}
361         },
362         { /* Device Default */
363           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
364            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
365            {'\0'}
366         },
367         { /* System Fixed */
368           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
369            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
370            {'\0'}
371         },
372         { /* DefaultGuiFont */
373          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
374            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
375            {'M','S',' ','S','o','n','g','\0'}   /* FIXME: Is this correct? */
376         },
377     },
378     {   HANGEUL_CHARSET,
379         { /* System */
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         { /* Device Default */
385           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
386            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
387            {'\0'}
388         },
389         { /* System Fixed */
390           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
391            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
392            {'\0'}
393         },
394         { /* DefaultGuiFont */
395          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
396            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
397            {'G','u','l','i','m','C','h','e'}, /* FIXME: Is this correct? */
398         },
399     },
400     {   CHINESEBIG5_CHARSET,
401         { /* System */
402           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
403            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
404            {'S','y','s','t','e','m','\0'}
405         },
406         { /* Device Default */
407           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
408            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
409            {'\0'}
410         },
411         { /* System Fixed */
412           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
413            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
414            {'\0'}
415         },
416         { /* DefaultGuiFont */
417          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
418            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
419            {'\0'}       /* FIXME - what is the native font??? */
420         },
421     },
422     {   JOHAB_CHARSET,
423         { /* System */
424           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
425            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
426            {'S','y','s','t','e','m','\0'}
427         },
428         { /* Device Default */
429           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
430            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
431            {'\0'}
432         },
433         { /* System Fixed */
434           16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
435            0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
436            {'\0'}
437         },
438         { /* DefaultGuiFont */
439          -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
440            0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
441            {'\0'}       /* FIXME - what is the native font??? mbtowc of native ("MS Mingliu")??? */
442         },
443     },
444 };
445
446
447 /******************************************************************************
448  *      get_default_fonts
449  */
450 static const struct DefaultFontInfo* get_default_fonts(UINT charset)
451 {
452         int     n;
453
454         for(n=0;n<(sizeof(default_fonts)/sizeof(default_fonts[0]));n++)
455         {
456                 if ( default_fonts[n].charset == charset )
457                         return &default_fonts[n];
458         }
459
460         FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
461         return &default_fonts[0];
462 }
463
464
465 /******************************************************************************
466  *      get_default_charset    (internal)
467  *
468  * get the language-dependent charset that can handle CP_ACP correctly.
469  */
470 static UINT get_default_charset( void )
471 {
472     CHARSETINFO     csi;
473     UINT    uACP;
474
475     uACP = GetACP();
476     csi.ciCharset = ANSI_CHARSET;
477     if ( ! TranslateCharsetInfo( (LPDWORD)uACP, &csi, TCI_SRCCODEPAGE ) )
478     {
479         FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", uACP );
480         return ANSI_CHARSET;
481     }
482
483     return csi.ciCharset;
484 }
485
486
487 /******************************************************************************
488  *           create_stock_font
489  */
490 static HFONT create_stock_font( char const *fontName, const LOGFONTW *font, HKEY hkey )
491 {
492     LOGFONTW lf;
493     char  key[256];
494     char buffer[MAX_PATH];
495     DWORD type, count;
496
497     if (!hkey) return CreateFontIndirectW( font );
498
499     lf = *font;
500     sprintf(key, "%s.Height", fontName);
501     count = sizeof(buffer);
502     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
503         lf.lfHeight = atoi(buffer);
504
505     sprintf(key, "%s.Bold", fontName);
506     count = sizeof(buffer);
507     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
508         lf.lfWeight = get_bool(buffer) ? FW_BOLD : FW_NORMAL;
509
510     sprintf(key, "%s.Italic", fontName);
511     count = sizeof(buffer);
512     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
513         lf.lfItalic = get_bool(buffer);
514
515     sprintf(key, "%s.Underline", fontName);
516     count = sizeof(buffer);
517     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
518         lf.lfUnderline = get_bool(buffer);
519
520     sprintf(key, "%s.StrikeOut", fontName);
521     count = sizeof(buffer);
522     if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
523         lf.lfStrikeOut = get_bool(buffer);
524     return CreateFontIndirectW( &lf );
525 }
526
527
528 #define TRACE_SEC(handle,text) \
529    TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
530
531
532 /***********************************************************************
533  *           inc_ref_count
534  *
535  * Increment the reference count of a GDI object.
536  */
537 inline static void inc_ref_count( HGDIOBJ handle )
538 {
539     GDIOBJHDR *header;
540
541     if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
542     {
543         header->dwCount++;
544         GDI_ReleaseObj( handle );
545     }
546 }
547
548
549 /***********************************************************************
550  *           dec_ref_count
551  *
552  * Decrement the reference count of a GDI object.
553  */
554 inline static void dec_ref_count( HGDIOBJ handle )
555 {
556     GDIOBJHDR *header;
557
558     if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
559     {
560         if (header->dwCount) header->dwCount--;
561         if (header->dwCount != 0x80000000) GDI_ReleaseObj( handle );
562         else
563         {
564             /* handle delayed DeleteObject*/
565             header->dwCount = 0;
566             GDI_ReleaseObj( handle );
567             TRACE( "executing delayed DeleteObject for %04x\n", handle );
568             DeleteObject( handle );
569         }
570     }
571 }
572
573
574 /***********************************************************************
575  *           GDI_Init
576  *
577  * GDI initialization.
578  */
579 BOOL GDI_Init(void)
580 {
581     HINSTANCE16 instance;
582     HKEY hkey;
583     GDIOBJHDR *ptr;
584     const struct DefaultFontInfo* deffonts;
585     int i;
586
587     if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Tweak.Fonts", &hkey))
588         hkey = 0;
589
590     /* create GDI heap */
591     if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
592     GDI_HeapSel = instance | 7;
593
594     /* create stock objects */
595     stock_objects[WHITE_BRUSH]  = CreateBrushIndirect( &WhiteBrush );
596     stock_objects[LTGRAY_BRUSH] = CreateBrushIndirect( &LtGrayBrush );
597     stock_objects[GRAY_BRUSH]   = CreateBrushIndirect( &GrayBrush );
598     stock_objects[DKGRAY_BRUSH] = CreateBrushIndirect( &DkGrayBrush );
599     stock_objects[BLACK_BRUSH]  = CreateBrushIndirect( &BlackBrush );
600     stock_objects[NULL_BRUSH]   = CreateBrushIndirect( &NullBrush );
601
602     stock_objects[WHITE_PEN]    = CreatePenIndirect( &WhitePen );
603     stock_objects[BLACK_PEN]    = CreatePenIndirect( &BlackPen );
604     stock_objects[NULL_PEN]     = CreatePenIndirect( &NullPen );
605
606     stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
607     stock_objects[DEFAULT_BITMAP]  = CreateBitmap( 1, 1, 1, 1, NULL );
608
609     /* language-independent stock fonts */
610     stock_objects[OEM_FIXED_FONT]      = create_stock_font( "OEMFixed", &OEMFixedFont, hkey );
611     stock_objects[ANSI_FIXED_FONT]     = create_stock_font( "AnsiFixed", &AnsiFixedFont, hkey );
612     stock_objects[ANSI_VAR_FONT]       = create_stock_font( "AnsiVar", &AnsiVarFont, hkey );
613
614     /* language-dependent stock fonts */
615     deffonts = get_default_fonts(get_default_charset());
616     stock_objects[SYSTEM_FONT]         = create_stock_font( "System", &deffonts->SystemFont, hkey );
617     stock_objects[DEVICE_DEFAULT_FONT] = create_stock_font( "DeviceDefault", &deffonts->DeviceDefaultFont, hkey );
618     stock_objects[SYSTEM_FIXED_FONT]   = create_stock_font( "SystemFixed", &deffonts->SystemFixedFont, hkey );
619     stock_objects[DEFAULT_GUI_FONT]    = create_stock_font( "DefaultGui", &deffonts->DefaultGuiFont, hkey );
620
621
622     /* clear the NOSYSTEM bit on all stock objects*/
623     for (i = 0; i < NB_STOCK_OBJECTS; i++)
624     {
625         if (!stock_objects[i])
626         {
627             if (i == 9) continue;  /* there's no stock object 9 */
628             ERR( "could not create stock object %d\n", i );
629             return FALSE;
630         }
631         ptr = GDI_GetObjPtr( stock_objects[i], MAGIC_DONTCARE );
632         ptr->wMagic &= ~OBJECT_NOSYSTEM;
633         GDI_ReleaseObj( stock_objects[i] );
634     }
635
636     if (hkey) RegCloseKey( hkey );
637
638     WineEngInit();
639
640     return TRUE;
641 }
642
643 #define FIRST_LARGE_HANDLE 16
644 #define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
645 static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
646 static int next_large_handle;
647
648 /***********************************************************************
649  *           alloc_large_heap
650  *
651  * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
652  */
653 inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
654 {
655     int i;
656     GDIOBJHDR *obj;
657
658     for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
659         if (!large_handles[i]) goto found;
660     for (i = 0; i <= next_large_handle; i++)
661         if (!large_handles[i]) goto found;
662     *handle = 0;
663     return NULL;
664
665  found:
666     if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
667     {
668         large_handles[i] = obj;
669         *handle = (i + FIRST_LARGE_HANDLE) << 2;
670         next_large_handle = i;
671     }
672     return obj;
673 }
674
675
676 /***********************************************************************
677  *           GDI_AllocObject
678  */
679 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
680 {
681     GDIOBJHDR *obj;
682
683     _EnterSysLevel( &GDI_level );
684     switch(magic)
685     {
686         /* allocate DCs on the larger heap */
687     case DC_MAGIC:
688     case DISABLED_DC_MAGIC:
689     case META_DC_MAGIC:
690     case METAFILE_MAGIC:
691     case METAFILE_DC_MAGIC:
692     case ENHMETAFILE_MAGIC:
693     case ENHMETAFILE_DC_MAGIC:
694     case BITMAP_MAGIC:   
695         if (!(obj = alloc_large_heap( size, handle ))) goto error;
696         break;
697     default:
698         if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
699         assert( *handle & 2 );
700         obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
701         break;
702     }
703
704     obj->hNext   = 0;
705     obj->wMagic  = magic|OBJECT_NOSYSTEM;
706     obj->dwCount = 0;
707
708     TRACE_SEC( *handle, "enter" );
709     return obj;
710
711 error:
712     _LeaveSysLevel( &GDI_level );
713     *handle = 0;
714     return NULL;
715 }
716
717
718 /***********************************************************************
719  *           GDI_ReallocObject
720  *
721  * The object ptr must have been obtained with GDI_GetObjPtr.
722  * The new pointer must be released with GDI_ReleaseObj.
723  */
724 void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
725 {
726     HGDIOBJ new_handle;
727
728     assert( handle & 2 );  /* no realloc for large handles */
729     LOCAL_Unlock( GDI_HeapSel, handle );
730     if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
731     {
732         TRACE_SEC( handle, "leave" );
733         _LeaveSysLevel( &GDI_level );
734         return NULL;
735     }
736     assert( new_handle == handle );  /* moveable handle cannot change */
737     return LOCAL_Lock( GDI_HeapSel, handle );
738 }
739  
740
741 /***********************************************************************
742  *           GDI_FreeObject
743  */
744 BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
745 {
746     GDIOBJHDR *object = ptr;
747
748     object->wMagic = 0;  /* Mark it as invalid */
749     if (handle & 2)  /* GDI heap handle */
750     {
751         LOCAL_Unlock( GDI_HeapSel, handle );
752         LOCAL_Free( GDI_HeapSel, handle );
753     }
754     else  /* large heap handle */
755     {
756         int i = (handle >> 2) - FIRST_LARGE_HANDLE;
757         if (i >= 0 && i < MAX_LARGE_HANDLES && large_handles[i])
758         {
759             HeapFree( GetProcessHeap(), 0, large_handles[i] );
760             large_handles[i] = NULL;
761         }
762         else ERR( "Invalid handle %x\n", handle );
763     }
764     TRACE_SEC( handle, "leave" );
765     _LeaveSysLevel( &GDI_level );
766     return TRUE;
767 }
768
769
770 /***********************************************************************
771  *           GDI_GetObjPtr
772  *
773  * Return a pointer to the GDI object associated to the handle.
774  * Return NULL if the object has the wrong magic number.
775  * The object must be released with GDI_ReleaseObj.
776  */
777 void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
778 {
779     GDIOBJHDR *ptr = NULL;
780
781     _EnterSysLevel( &GDI_level );
782
783     if (handle & 2)  /* GDI heap handle */
784     {
785         ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
786         if (ptr)
787         {
788             if (((magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ||
789                 (GDIMAGIC(ptr->wMagic) < FIRST_MAGIC) ||
790                 (GDIMAGIC(ptr->wMagic) > LAST_MAGIC))
791             {
792                 LOCAL_Unlock( GDI_HeapSel, handle );
793                 ptr = NULL;
794             }
795         }
796     }
797     else  /* large heap handle */
798     {
799         int i = (handle >> 2) - FIRST_LARGE_HANDLE;
800         if (i >= 0 && i < MAX_LARGE_HANDLES)
801         {
802             ptr = large_handles[i];
803             if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
804         }
805     }
806
807     if (!ptr)
808     {
809         _LeaveSysLevel( &GDI_level );
810         SetLastError( ERROR_INVALID_HANDLE );
811         WARN( "Invalid handle %x\n", handle );
812     }
813     else TRACE_SEC( handle, "enter" );
814
815     return ptr;
816 }
817
818
819 /***********************************************************************
820  *           GDI_ReleaseObj
821  *
822  */
823 void GDI_ReleaseObj( HGDIOBJ handle )
824 {
825     if (handle & 2) LOCAL_Unlock( GDI_HeapSel, handle );
826     TRACE_SEC( handle, "leave" );
827     _LeaveSysLevel( &GDI_level );
828 }
829
830
831 /***********************************************************************
832  *           GDI_CheckNotLock
833  */
834 void GDI_CheckNotLock(void)
835 {
836     _CheckNotSysLevel( &GDI_level );
837 }
838
839
840 /***********************************************************************
841  *           FONT_DeleteObject
842  *
843  */
844 static BOOL FONT_DeleteObject(HGDIOBJ hfont, FONTOBJ *fontobj)
845 {
846     WineEngDestroyFontInstance( hfont );
847     return GDI_FreeObject( hfont, fontobj );
848 }
849
850
851 /***********************************************************************
852  *           DeleteObject    (GDI.69)
853  *           SysDeleteObject (GDI.605)
854  */
855 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
856 {
857     return DeleteObject( obj );
858 }
859
860
861 /***********************************************************************
862  *           DeleteObject    (GDI32.@)
863  */
864 BOOL WINAPI DeleteObject( HGDIOBJ obj )
865 {
866       /* Check if object is valid */
867
868     GDIOBJHDR * header;
869     if (HIWORD(obj)) return FALSE;
870
871     if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
872
873     if (!(header->wMagic & OBJECT_NOSYSTEM)
874     &&   (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
875     {
876         TRACE("Preserving system object %04x\n", obj);
877         GDI_ReleaseObj( obj );
878         return TRUE;
879     }
880
881     if (header->dwCount)
882     {
883         TRACE("delayed for %04x because object in use, count %ld\n", obj, header->dwCount );
884         header->dwCount |= 0x80000000; /* mark for delete */
885         GDI_ReleaseObj( obj );
886         return TRUE;
887     }
888
889     TRACE("%04x\n", obj );
890
891       /* Delete object */
892
893     switch(GDIMAGIC(header->wMagic))
894     {
895       case PEN_MAGIC:     return GDI_FreeObject( obj, header );
896       case BRUSH_MAGIC:   return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
897       case FONT_MAGIC:    return FONT_DeleteObject( obj, (FONTOBJ*)header );
898       case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
899       case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
900       case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
901       case DC_MAGIC:
902           GDI_ReleaseObj( obj );
903           return DeleteDC(obj);
904       case 0 :
905         WARN("Already deleted\n");
906         break;
907       default:
908         WARN("Unknown magic number (%04x)\n",GDIMAGIC(header->wMagic));
909     }
910     GDI_ReleaseObj( obj );
911     return FALSE;
912 }
913
914 /***********************************************************************
915  *           GetStockObject    (GDI.87)
916  */
917 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
918 {
919     return (HGDIOBJ16)GetStockObject( obj );
920 }
921
922
923 /***********************************************************************
924  *           GetStockObject    (GDI32.@)
925  */
926 HGDIOBJ WINAPI GetStockObject( INT obj )
927 {
928     HGDIOBJ ret;
929     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
930     ret = stock_objects[obj];
931     TRACE("returning %4x\n", ret );
932     return ret;
933 }
934
935
936 /***********************************************************************
937  *           GetObject    (GDI.82)
938  */
939 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
940 {
941     GDIOBJHDR * ptr;
942     INT16 result = 0;
943     TRACE("%04x %d %p\n", handle, count, buffer );
944     if (!count) return 0;
945
946     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
947     
948     switch(GDIMAGIC(ptr->wMagic))
949       {
950       case PEN_MAGIC:
951         result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
952         break;
953       case BRUSH_MAGIC: 
954         result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
955         break;
956       case BITMAP_MAGIC: 
957         result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
958         break;
959       case FONT_MAGIC:
960         result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
961         break;
962       case PALETTE_MAGIC:
963         result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
964         break;
965       }
966     GDI_ReleaseObj( handle );
967     return result;
968 }
969
970
971 /***********************************************************************
972  *           GetObjectA    (GDI32.@)
973  */
974 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
975 {
976     GDIOBJHDR * ptr;
977     INT result = 0;
978     TRACE("%08x %d %p\n", handle, count, buffer );
979     if (!count) return 0;
980
981     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
982
983     switch(GDIMAGIC(ptr->wMagic))
984     {
985       case PEN_MAGIC:
986           result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
987           break;
988       case BRUSH_MAGIC: 
989           result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
990           break;
991       case BITMAP_MAGIC: 
992           result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
993           break;
994       case FONT_MAGIC:
995           result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
996           break;
997       case PALETTE_MAGIC:
998           result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
999           break;
1000
1001       case REGION_MAGIC:
1002       case DC_MAGIC:
1003       case DISABLED_DC_MAGIC:
1004       case META_DC_MAGIC:
1005       case METAFILE_MAGIC:
1006       case METAFILE_DC_MAGIC:
1007       case ENHMETAFILE_MAGIC:
1008       case ENHMETAFILE_DC_MAGIC:
1009           FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
1010           break;
1011
1012       default:
1013           ERR("Invalid GDI Magic %04x\n", GDIMAGIC(ptr->wMagic));
1014           break;
1015     }
1016     GDI_ReleaseObj( handle );
1017     return result;
1018 }
1019
1020 /***********************************************************************
1021  *           GetObjectW    (GDI32.@)
1022  */
1023 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
1024 {
1025     GDIOBJHDR * ptr;
1026     INT result = 0;
1027     TRACE("%08x %d %p\n", handle, count, buffer );
1028     if (!count) return 0;
1029
1030     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
1031
1032     switch(GDIMAGIC(ptr->wMagic))
1033     {
1034       case PEN_MAGIC:
1035           result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
1036           break;
1037       case BRUSH_MAGIC: 
1038           result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
1039           break;
1040       case BITMAP_MAGIC: 
1041           result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
1042           break;
1043       case FONT_MAGIC:
1044           result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
1045           break;
1046       case PALETTE_MAGIC:
1047           result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
1048           break;
1049       default:
1050           FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
1051           break;
1052     }
1053     GDI_ReleaseObj( handle );
1054     return result;
1055 }
1056
1057 /***********************************************************************
1058  *           GetObjectType    (GDI32.@)
1059  */
1060 DWORD WINAPI GetObjectType( HANDLE handle )
1061 {
1062     GDIOBJHDR * ptr;
1063     INT result = 0;
1064     TRACE("%08x\n", handle );
1065
1066     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
1067     
1068     switch(GDIMAGIC(ptr->wMagic))
1069     {
1070       case PEN_MAGIC:
1071           result = OBJ_PEN;
1072           break;
1073       case BRUSH_MAGIC: 
1074           result = OBJ_BRUSH;
1075           break;
1076       case BITMAP_MAGIC: 
1077           result = OBJ_BITMAP;
1078           break;
1079       case FONT_MAGIC:
1080           result = OBJ_FONT;
1081           break;
1082       case PALETTE_MAGIC:
1083           result = OBJ_PAL;
1084           break;
1085       case REGION_MAGIC:
1086           result = OBJ_REGION;
1087           break;
1088       case DC_MAGIC:
1089           result = OBJ_DC;
1090           break;
1091       case META_DC_MAGIC:
1092           result = OBJ_METADC;
1093           break;
1094       case METAFILE_MAGIC:
1095           result = OBJ_METAFILE;
1096           break;
1097       case METAFILE_DC_MAGIC:
1098           result = OBJ_METADC;
1099           break;
1100       case ENHMETAFILE_MAGIC:
1101           result = OBJ_ENHMETAFILE;
1102           break;
1103       case ENHMETAFILE_DC_MAGIC:
1104           result = OBJ_ENHMETADC;
1105           break;
1106       default:
1107           FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
1108           break;
1109     }
1110     GDI_ReleaseObj( handle );
1111     return result;
1112 }
1113
1114 /***********************************************************************
1115  *           GetCurrentObject           (GDI32.@)
1116  */
1117 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
1118 {
1119     HANDLE ret = 0;
1120     DC * dc = DC_GetDCPtr( hdc );
1121
1122     if (dc) 
1123     {
1124     switch (type) {
1125         case OBJ_PEN:    ret = dc->hPen; break;
1126         case OBJ_BRUSH:  ret = dc->hBrush; break;
1127         case OBJ_PAL:    ret = dc->hPalette; break;
1128         case OBJ_FONT:   ret = dc->hFont; break;
1129         case OBJ_BITMAP: ret = dc->hBitmap; break;
1130     default:
1131         /* the SDK only mentions those above */
1132         FIXME("(%08x,%d): unknown type.\n",hdc,type);
1133             break;
1134         }
1135         GDI_ReleaseObj( hdc );
1136     }
1137     return ret;
1138 }
1139 /***********************************************************************
1140  *           FONT_SelectObject
1141  *
1142  * If the driver supports vector fonts we create a gdi font first and
1143  * then call the driver to give it a chance to supply its own device
1144  * font.  If the driver wants to do this it returns TRUE and we can
1145  * delete the gdi font, if the driver wants to use the gdi font it
1146  * should return FALSE, to signal an error return GDI_ERROR.  For
1147  * drivers that don't support vector fonts they must supply their own
1148  * font.
1149  */
1150 static HGDIOBJ FONT_SelectObject(DC *dc, HGDIOBJ hFont)
1151 {
1152     HGDIOBJ ret = FALSE;
1153
1154     if(dc->hFont != hFont || dc->gdiFont == NULL) {
1155         if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
1156             dc->gdiFont = WineEngCreateFontInstance(hFont);
1157     }
1158
1159     if(dc->funcs->pSelectFont)
1160         ret = dc->funcs->pSelectFont(dc->physDev, hFont);
1161
1162     if(ret && dc->gdiFont) {
1163         dc->gdiFont = 0;
1164     }
1165
1166     if(ret == GDI_ERROR)
1167         ret = FALSE; /* SelectObject returns FALSE on error */
1168     else {
1169         ret = dc->hFont;
1170         dc->hFont = hFont;
1171     }
1172
1173     return ret;
1174 }
1175
1176 /***********************************************************************
1177  *           SelectObject    (GDI.45)
1178  */
1179 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
1180 {
1181     return (HGDIOBJ16)SelectObject( hdc, handle );
1182 }
1183
1184
1185 /***********************************************************************
1186  *           SelectObject    (GDI32.@)
1187  */
1188 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
1189 {
1190     HGDIOBJ ret = 0;
1191     DC * dc = DC_GetDCPtr( hdc );
1192     if (!dc) return 0;
1193     TRACE("hdc=%04x %04x\n", hdc, handle );
1194
1195     /* Fonts get a rather different treatment so we'll handle them
1196        separately */
1197     switch(GetObjectType( handle ))
1198     {
1199     case OBJ_BITMAP:
1200         ret = dc->hBitmap;
1201         if (dc->funcs->pSelectBitmap) handle = dc->funcs->pSelectBitmap( dc->physDev, handle );
1202         if (handle) dc->hBitmap = handle;
1203         else ret = 0;
1204         break;
1205     case OBJ_BRUSH:
1206         ret = dc->hBrush;
1207         if (dc->funcs->pSelectBrush) handle = dc->funcs->pSelectBrush( dc->physDev, handle );
1208         if (handle) dc->hBrush = handle;
1209         else ret = 0;
1210         break;
1211     case OBJ_PEN:
1212         ret = dc->hPen;
1213         if (dc->funcs->pSelectPen) handle = dc->funcs->pSelectPen( dc->physDev, handle );
1214         if (handle) dc->hPen = handle;
1215         else ret = 0;
1216         break;
1217     case OBJ_FONT:
1218         ret = FONT_SelectObject(dc, handle);
1219         break;
1220     case OBJ_REGION:
1221         GDI_ReleaseObj( hdc );
1222         return (HGDIOBJ)SelectClipRgn( hdc, handle );
1223     }
1224     GDI_ReleaseObj( hdc );
1225
1226     if (ret && ret != handle)
1227     {
1228         inc_ref_count( handle );
1229         dec_ref_count( ret );
1230     }
1231     return ret;
1232 }
1233
1234
1235 /***********************************************************************
1236  *           UnrealizeObject    (GDI.150)
1237  */
1238 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
1239 {
1240     return UnrealizeObject( obj );
1241 }
1242
1243
1244 /***********************************************************************
1245  *           UnrealizeObject    (GDI32.@)
1246  */
1247 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
1248 {
1249     BOOL result = TRUE;
1250   /* Check if object is valid */
1251
1252     GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
1253     if (!header) return FALSE;
1254
1255     TRACE("%04x\n", obj );
1256
1257       /* Unrealize object */
1258
1259     switch(GDIMAGIC(header->wMagic))
1260     {
1261     case PALETTE_MAGIC: 
1262         result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
1263         break;
1264
1265     case BRUSH_MAGIC:
1266         /* Windows resets the brush origin. We don't need to. */
1267         break;
1268     }
1269     GDI_ReleaseObj( obj );
1270     return result;
1271 }
1272
1273
1274 /* Solid colors to enumerate */
1275 static const COLORREF solid_colors[] =
1276 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1277 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1278 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1279 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1280 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1281 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1282 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1283 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1284 };
1285     
1286 /***********************************************************************
1287  *           EnumObjects    (GDI.71)
1288  */
1289 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
1290                             GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
1291 {
1292     INT16 i, retval = 0;
1293     LOGPEN16 pen;
1294     LOGBRUSH16 brush;
1295     SEGPTR segptr;
1296
1297     TRACE("%04x %d %08lx %08lx\n",
1298                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
1299     switch(nObjType)
1300     {
1301     case OBJ_PEN:
1302         /* Enumerate solid pens */
1303         segptr = MapLS( &pen );
1304         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1305         {
1306             pen.lopnStyle   = PS_SOLID;
1307             pen.lopnWidth.x = 1;
1308             pen.lopnWidth.y = 0;
1309             pen.lopnColor   = solid_colors[i];
1310             retval = GDI_CallTo16_word_ll( lpEnumFunc, segptr, lParam );
1311             TRACE("solid pen %08lx, ret=%d\n", solid_colors[i], retval);
1312             if (!retval) break;
1313         }
1314         UnMapLS( segptr );
1315         break;
1316
1317     case OBJ_BRUSH:
1318         /* Enumerate solid brushes */
1319         segptr = MapLS( &brush );
1320         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1321         {
1322             brush.lbStyle = BS_SOLID;
1323             brush.lbColor = solid_colors[i];
1324             brush.lbHatch = 0;
1325             retval = GDI_CallTo16_word_ll( lpEnumFunc, segptr, lParam );
1326             TRACE("solid brush %08lx, ret=%d\n", solid_colors[i], retval);
1327             if (!retval) break;
1328         }
1329
1330         /* Now enumerate hatched brushes */
1331         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1332         {
1333             brush.lbStyle = BS_HATCHED;
1334             brush.lbColor = RGB(0,0,0);
1335             brush.lbHatch = i;
1336             retval = GDI_CallTo16_word_ll( lpEnumFunc, segptr, lParam );
1337             TRACE("hatched brush %d, ret=%d\n", i, retval);
1338             if (!retval) break;
1339         }
1340         UnMapLS( segptr );
1341         break;
1342
1343     default:
1344         WARN("(%d): Invalid type\n", nObjType );
1345         break;
1346     }
1347     return retval;
1348 }
1349
1350
1351 /***********************************************************************
1352  *           EnumObjects    (GDI32.@)
1353  */
1354 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
1355                             GOBJENUMPROC lpEnumFunc, LPARAM lParam )
1356 {
1357     INT i, retval = 0;
1358     LOGPEN pen;
1359     LOGBRUSH brush;
1360
1361     TRACE("%04x %d %08lx %08lx\n",
1362                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
1363     switch(nObjType)
1364     {
1365     case OBJ_PEN:
1366         /* Enumerate solid pens */
1367         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1368         {
1369             pen.lopnStyle   = PS_SOLID;
1370             pen.lopnWidth.x = 1;
1371             pen.lopnWidth.y = 0;
1372             pen.lopnColor   = solid_colors[i];
1373             retval = lpEnumFunc( &pen, lParam );
1374             TRACE("solid pen %08lx, ret=%d\n",
1375                          solid_colors[i], retval);
1376             if (!retval) break;
1377         }
1378         break;
1379
1380     case OBJ_BRUSH:
1381         /* Enumerate solid brushes */
1382         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1383         {
1384             brush.lbStyle = BS_SOLID;
1385             brush.lbColor = solid_colors[i];
1386             brush.lbHatch = 0;
1387             retval = lpEnumFunc( &brush, lParam );
1388             TRACE("solid brush %08lx, ret=%d\n",
1389                          solid_colors[i], retval);
1390             if (!retval) break;
1391         }
1392
1393         /* Now enumerate hatched brushes */
1394         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1395         {
1396             brush.lbStyle = BS_HATCHED;
1397             brush.lbColor = RGB(0,0,0);
1398             brush.lbHatch = i;
1399             retval = lpEnumFunc( &brush, lParam );
1400             TRACE("hatched brush %d, ret=%d\n",
1401                          i, retval);
1402             if (!retval) break;
1403         }
1404         break;
1405
1406     default:
1407         /* FIXME: implement Win32 types */
1408         WARN("(%d): Invalid type\n", nObjType );
1409         break;
1410     }
1411     return retval;
1412 }
1413
1414
1415 /***********************************************************************
1416  *           IsGDIObject    (GDI.462)
1417  * 
1418  * returns type of object if valid (W95 system programming secrets p. 264-5)
1419  */
1420 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
1421 {
1422     UINT16 magic = 0;
1423
1424     GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1425     if (object)
1426     {
1427         magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1428         GDI_ReleaseObj( handle );
1429     }
1430     return magic;
1431 }
1432
1433
1434 /***********************************************************************
1435  *           SetObjectOwner    (GDI.461)
1436  */
1437 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1438 {
1439     /* Nothing to do */
1440 }
1441
1442
1443 /***********************************************************************
1444  *           SetObjectOwner    (GDI32.@)
1445  */
1446 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1447 {
1448     /* Nothing to do */
1449 }
1450
1451
1452 /***********************************************************************
1453  *           MakeObjectPrivate    (GDI.463)
1454  *
1455  * What does that mean ?
1456  * Some little docu can be found in "Undocumented Windows",
1457  * but this is basically useless.
1458  * At least we know that this flags the GDI object's wMagic
1459  * with 0x2000 (OBJECT_PRIVATE), so we just do it.
1460  * But Wine doesn't react on that yet.
1461  */
1462 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1463 {
1464     GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1465     if (!ptr)
1466     {
1467         ERR("invalid GDI object %04x !\n", handle);
1468         return;
1469     }
1470     ptr->wMagic |= OBJECT_PRIVATE;
1471     GDI_ReleaseObj( handle );
1472 }
1473
1474
1475 /***********************************************************************
1476  *           GdiFlush    (GDI32.@)
1477  */
1478 BOOL WINAPI GdiFlush(void)
1479 {
1480     return TRUE;  /* FIXME */
1481 }
1482
1483
1484 /***********************************************************************
1485  *           GdiGetBatchLimit    (GDI32.@)
1486  */
1487 DWORD WINAPI GdiGetBatchLimit(void)
1488 {
1489     return 1;  /* FIXME */
1490 }
1491
1492
1493 /***********************************************************************
1494  *           GdiSetBatchLimit    (GDI32.@)
1495  */
1496 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1497 {
1498     return 1; /* FIXME */
1499 }
1500
1501
1502 /***********************************************************************
1503  *           GdiSeeGdiDo   (GDI.452)
1504  */
1505 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1506                           WORD wParam3 )
1507 {
1508     switch (wReqType)
1509     {
1510     case 0x0001:  /* LocalAlloc */
1511         return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1512     case 0x0002:  /* LocalFree */
1513         return LOCAL_Free( GDI_HeapSel, wParam1 );
1514     case 0x0003:  /* LocalCompact */
1515         return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1516     case 0x0103:  /* LocalHeap */
1517         return GDI_HeapSel;
1518     default:
1519         WARN("(wReqType=%04x): Unknown\n", wReqType);
1520         return (DWORD)-1;
1521     }
1522 }
1523
1524 /***********************************************************************
1525  *           GdiSignalProc32     (GDI.610)
1526  */
1527 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1528                            DWORD dwFlags, HMODULE16 hModule )
1529 {
1530     return 0;
1531 }
1532
1533 /***********************************************************************
1534  *           GdiInit2     (GDI.403)
1535  *
1536  * See "Undocumented Windows"
1537  */
1538 HANDLE16 WINAPI GdiInit216(
1539     HANDLE16 h1, /* [in] GDI object */
1540     HANDLE16 h2  /* [in] global data */
1541 )
1542 {
1543     FIXME("(%04x, %04x), stub.\n", h1, h2);
1544     if (h2 == 0xffff)
1545         return 0xffff; /* undefined return value */
1546     return h1; /* FIXME: should be the memory handle of h1 */
1547 }
1548
1549 /***********************************************************************
1550  *           FinalGdiInit     (GDI.405)
1551  */
1552 void WINAPI FinalGdiInit16( HBRUSH16 hPattern /* [in] fill pattern of desktop */ )
1553 {
1554 }
1555
1556 /***********************************************************************
1557  *           GdiFreeResources   (GDI.609)
1558  */
1559 WORD WINAPI GdiFreeResources16( DWORD reserve )
1560 {
1561    return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1562                   (int)LOCAL_HeapSize( GDI_HeapSel ) );
1563 }
1564
1565 /***********************************************************************
1566  *           MulDiv   (GDI.128)
1567  */
1568 INT16 WINAPI MulDiv16(
1569              INT16 nMultiplicand, 
1570              INT16 nMultiplier,
1571              INT16 nDivisor)
1572 {
1573     INT ret;
1574     if (!nDivisor) return -32768;
1575     /* We want to deal with a positive divisor to simplify the logic. */
1576     if (nDivisor < 0)
1577     {
1578       nMultiplicand = - nMultiplicand;
1579       nDivisor = -nDivisor;
1580     }
1581     /* If the result is positive, we "add" to round. else, 
1582      * we subtract to round. */
1583     if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
1584          ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1585         ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1586     else
1587         ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1588     if ((ret > 32767) || (ret < -32767)) return -32768;
1589     return (INT16) ret;
1590 }
1591
1592
1593 /*******************************************************************
1594  *      GetColorAdjustment [GDI32.@]
1595  *
1596  *
1597  */
1598 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1599 {
1600         FIXME("GetColorAdjustment, stub\n");
1601         return 0;
1602 }
1603
1604 /*******************************************************************
1605  *      GetMiterLimit [GDI32.@]
1606  *
1607  *
1608  */
1609 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1610 {
1611         FIXME("GetMiterLimit, stub\n");
1612         return 0;
1613 }
1614
1615 /*******************************************************************
1616  *      SetMiterLimit [GDI32.@]
1617  *
1618  *
1619  */
1620 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1621 {
1622         FIXME("SetMiterLimit, stub\n");
1623         return 0;
1624 }
1625
1626 /*******************************************************************
1627  *      GdiComment [GDI32.@]
1628  *
1629  *
1630  */
1631 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1632 {
1633         FIXME("GdiComment, stub\n");
1634         return 0;
1635 }
1636 /*******************************************************************
1637  *      SetColorAdjustment [GDI32.@]
1638  *
1639  *
1640  */
1641 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1642 {
1643         FIXME("SetColorAdjustment, stub\n");
1644         return 0;
1645 }
1646