Initialize the NONCLIENTMETRICS with 0 (helps moorhuhn.exe).
[wine] / objects / gdiobj.c
1 /*
2  * GDI functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #ifndef X_DISPLAY_MISSING
10 #include "x11drv.h"
11 #else /* !defined(X_DISPLAY_MISSING) */
12 #include "ttydrv.h"
13 #endif /* !defined(X_DISPLAY_MISSING */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17
18 #include "bitmap.h"
19 #include "brush.h"
20 #include "dc.h"
21 #include "font.h"
22 #include "heap.h"
23 #include "options.h"
24 #include "palette.h"
25 #include "pen.h"
26 #include "region.h"
27 #include "debugtools.h"
28 #include "gdi.h"
29 #include "tweak.h"
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33
34 DEFAULT_DEBUG_CHANNEL(gdi)
35
36 /**********************************************************************/
37
38 GDI_DRIVER *GDI_Driver = NULL;
39
40 /***********************************************************************
41  *          GDI stock objects 
42  */
43
44 static BRUSHOBJ WhiteBrush =
45 {
46     { 0, BRUSH_MAGIC, 1 },             /* header */
47     { BS_SOLID, RGB(255,255,255), 0 }  /* logbrush */
48 };
49
50 static BRUSHOBJ LtGrayBrush =
51 {
52     { 0, BRUSH_MAGIC, 1 },             /* header */
53 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
54     { BS_SOLID, RGB(192,192,192), 0 }  /* logbrush */
55 };
56
57 static BRUSHOBJ GrayBrush =
58 {
59     { 0, BRUSH_MAGIC, 1 },             /* header */
60 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
61     { BS_SOLID, RGB(128,128,128), 0 }  /* logbrush */
62 };
63
64 static BRUSHOBJ DkGrayBrush =
65 {
66     { 0, BRUSH_MAGIC, 1 },          /* header */
67 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
68 /* NB_HATCH_STYLES is an index into HatchBrushes */
69     { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES }  /* logbrush */
70 };
71
72 static BRUSHOBJ BlackBrush =
73 {
74     { 0, BRUSH_MAGIC, 1 },       /* header */
75     { BS_SOLID, RGB(0,0,0), 0 }  /* logbrush */
76 };
77
78 static BRUSHOBJ NullBrush =
79 {
80     { 0, BRUSH_MAGIC, 1 },  /* header */
81     { BS_NULL, 0, 0 }       /* logbrush */
82 };
83
84 static PENOBJ WhitePen =
85 {
86     { 0, PEN_MAGIC, 1 },                     /* header */
87     { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
88 };
89
90 static PENOBJ BlackPen =
91 {
92     { 0, PEN_MAGIC, 1 },               /* header */
93     { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
94 };
95
96 static PENOBJ NullPen =
97 {
98     { 0, PEN_MAGIC, 1 },      /* header */
99     { PS_NULL, { 1, 0 }, 0 }  /* logpen */
100 };
101
102 static FONTOBJ OEMFixedFont =
103 {
104     { 0, FONT_MAGIC, 1 },   /* header */
105     { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
106       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
107 };
108 /* Filler to make the location counter dword aligned again.  This is necessary
109    since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
110    segment, and (c) Solaris assembler is stupid.  */
111 static UINT16 align_OEMFixedFont = 1;
112
113 static FONTOBJ AnsiFixedFont =
114 {
115     { 0, FONT_MAGIC, 1 },   /* header */
116     { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
117       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
118 };
119 static UINT16 align_AnsiFixedFont = 1;
120
121 static FONTOBJ AnsiVarFont =
122 {
123     { 0, FONT_MAGIC, 1 },   /* header */
124     { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
125       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
126 };
127 static UINT16 align_AnsiVarFont = 1;
128
129 static FONTOBJ SystemFont =
130 {
131     { 0, FONT_MAGIC, 1 },
132     { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
133       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
134 };
135 static UINT16 align_SystemFont = 1;
136
137 static FONTOBJ DeviceDefaultFont =
138 {
139     { 0, FONT_MAGIC, 1 },   /* header */
140     { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
141       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
142 };
143 static UINT16 align_DeviceDefaultFont = 1;
144
145 static FONTOBJ SystemFixedFont =
146 {
147     { 0, FONT_MAGIC, 1 },   /* header */
148     { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
149       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
150 };
151 static UINT16 align_SystemFixedFont = 1;
152
153 /* FIXME: Is this correct? */
154 static FONTOBJ DefaultGuiFont =
155 {
156     { 0, FONT_MAGIC, 1 },   /* header */
157     { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
158       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
159 };
160 static UINT16 align_DefaultGuiFont = 1;
161
162
163 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
164 {
165     (GDIOBJHDR *) &WhiteBrush,
166     (GDIOBJHDR *) &LtGrayBrush,
167     (GDIOBJHDR *) &GrayBrush,
168     (GDIOBJHDR *) &DkGrayBrush,
169     (GDIOBJHDR *) &BlackBrush,
170     (GDIOBJHDR *) &NullBrush,
171     (GDIOBJHDR *) &WhitePen,
172     (GDIOBJHDR *) &BlackPen,
173     (GDIOBJHDR *) &NullPen,
174     NULL,
175     (GDIOBJHDR *) &OEMFixedFont,
176     (GDIOBJHDR *) &AnsiFixedFont,
177     (GDIOBJHDR *) &AnsiVarFont,
178     (GDIOBJHDR *) &SystemFont,
179     (GDIOBJHDR *) &DeviceDefaultFont,
180     NULL,            /* DEFAULT_PALETTE created by PALETTE_Init */
181     (GDIOBJHDR *) &SystemFixedFont,
182     (GDIOBJHDR *) &DefaultGuiFont
183 };
184
185 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
186
187 /******************************************************************************
188  *
189  *   void  ReadFontInformation(
190  *      char const  *fontName,
191  *      FONTOBJ  *font,
192  *      int  defHeight,
193  *      int  defBold,
194  *      int  defItalic,
195  *      int  defUnderline,
196  *      int  defStrikeOut )
197  *
198  *   ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
199  *   section for entries containing fontName.Height, fontName.Bold, etc.,
200  *   where fontName is the name specified in the call (e.g., "System").  It
201  *   attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
202  *   the first character in the boolean attributes (bold, italic, and
203  *   underline).
204  *****************************************************************************/
205
206 static void  ReadFontInformation(
207     char const *fontName,
208     FONTOBJ *font,
209     int  defHeight,
210     int  defBold,
211     int  defItalic,
212     int  defUnderline,
213     int  defStrikeOut )
214 {
215     char  key[256];
216
217     /* In order for the stock fonts to be independent of 
218      * mapping mode, the height (& width) must be 0
219      */
220     sprintf(key, "%s.Height", fontName);
221     font->logfont.lfHeight =
222         PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
223
224     sprintf(key, "%s.Bold", fontName);
225     font->logfont.lfWeight =
226         (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
227         FW_BOLD : FW_NORMAL;
228
229     sprintf(key, "%s.Italic", fontName);
230     font->logfont.lfItalic =
231         PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
232
233     sprintf(key, "%s.Underline", fontName);
234     font->logfont.lfUnderline =
235         PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
236
237     sprintf(key, "%s.StrikeOut", fontName);
238     font->logfont.lfStrikeOut =
239         PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
240
241     return;
242 }
243
244 /***********************************************************************
245  * Because the stock fonts have their structure initialized with
246  * a height of 0 to keep them independent of mapping mode, simply
247  * returning the LOGFONT as is will not work correctly.
248  * These "FixStockFontSizeXXX()" methods will get the correct
249  * size for the fonts.
250  */
251 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
252 {
253   HDC         hdc;
254   HFONT       hOldFont;
255
256   hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
257
258   hOldFont = (HFONT)SelectObject(hdc, handle);
259
260   GetTextMetricsA(hdc, lptm);
261
262   SelectObject(hdc, hOldFont);
263
264   DeleteDC(hdc);
265 }
266
267 static inline void FixStockFontSize16(
268   HFONT  handle, 
269   INT16  count, 
270   LPVOID buffer)
271 {
272   TEXTMETRICA tm;
273   LOGFONT16*  pLogFont = (LOGFONT16*)buffer;
274
275   /*
276    * Was the lfHeight field copied (it's the first field)?
277    * If it was and it was null, replace the height.
278    */
279   if ( (count >= 2*sizeof(INT16)) &&
280        (pLogFont->lfHeight == 0) )
281   {
282     GetFontMetrics(handle, &tm);
283     
284     pLogFont->lfHeight = tm.tmHeight;
285     pLogFont->lfWidth  = tm.tmAveCharWidth;
286   }
287 }
288
289 static inline void FixStockFontSizeA(
290   HFONT  handle, 
291   INT    count, 
292   LPVOID buffer)
293 {
294   TEXTMETRICA tm;
295   LOGFONTA*  pLogFont = (LOGFONTA*)buffer;
296
297   /*
298    * Was the lfHeight field copied (it's the first field)?
299    * If it was and it was null, replace the height.
300    */
301   if ( (count >= 2*sizeof(INT)) &&
302        (pLogFont->lfHeight == 0) )
303   {
304     GetFontMetrics(handle, &tm);
305
306     pLogFont->lfHeight = tm.tmHeight;
307     pLogFont->lfWidth  = tm.tmAveCharWidth;
308   }
309 }
310
311 /**
312  * Since the LOGFONTA and LOGFONTW structures are identical up to the 
313  * lfHeight member (the one of interest in this case) we simply define
314  * the W version as the A version. 
315  */
316 #define FixStockFontSizeW FixStockFontSizeA
317
318
319
320 /***********************************************************************
321  *           GDI_Init
322  *
323  * GDI initialization.
324  */
325 BOOL GDI_Init(void)
326 {
327     BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
328
329     /* Kill some warnings.  */
330     (void)align_OEMFixedFont;
331     (void)align_AnsiFixedFont;
332     (void)align_AnsiVarFont;
333     (void)align_SystemFont;
334     (void)align_DeviceDefaultFont;
335     (void)align_SystemFixedFont;
336     (void)align_DefaultGuiFont;
337
338     /* TWEAK: Initialize font hints */
339     ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
340     ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
341     ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
342     ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
343     ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
344     ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
345     ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
346
347     /* Initialize drivers */
348
349 #ifndef X_DISPLAY_MISSING
350     GDI_Driver = &X11DRV_GDI_Driver;
351 #else /* !defined(X_DISPLAY_MISSING) */
352     GDI_Driver = &TTYDRV_GDI_Driver;
353 #endif /* !defined(X_DISPLAY_MISSING */
354
355     GDI_Driver->pInitialize();
356
357     /* Create default palette */
358
359     /* DR well *this* palette can't be moveable (?) */
360     {
361     HPALETTE16 hpalette = PALETTE_Init();
362     if( !hpalette )
363         return FALSE;
364     StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
365     }
366
367     hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL ); 
368     return TRUE;
369 }
370
371
372 /***********************************************************************
373  *           GDI_AllocObject
374  */
375 HGDIOBJ16 GDI_AllocObject( WORD size, WORD magic )
376 {
377     static DWORD count = 0;
378     GDIOBJHDR * obj;
379     HGDIOBJ16 handle;
380     if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
381       handle = GDI_HEAP_ALLOC( size );
382     else 
383       handle = GDI_HEAP_ALLOC_MOVEABLE( size );
384     if (!handle) return 0;
385     obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
386     obj->hNext   = 0;
387     obj->wMagic  = magic;
388     obj->dwCount = ++count;
389     GDI_HEAP_UNLOCK( handle );
390     return handle;
391 }
392
393
394 /***********************************************************************
395  *           GDI_FreeObject
396  */
397 BOOL GDI_FreeObject( HGDIOBJ16 handle )
398 {
399     GDIOBJHDR * object;
400
401       /* Can't free stock objects */
402     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
403         return TRUE;
404     
405     object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
406     if (!object) return FALSE;
407     object->wMagic = 0;  /* Mark it as invalid */
408  
409       /* Free object */
410     
411     GDI_HEAP_FREE( handle );
412     return TRUE;
413 }
414
415 /***********************************************************************
416  *           GDI_GetObjPtr
417  *
418  * Return a pointer to the GDI object associated to the handle.
419  * Return NULL if the object has the wrong magic number.
420  * Movable GDI objects are locked in memory: it is up to the caller to unlock
421  * it after the caller is done with the pointer.
422  */
423 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16 handle, WORD magic )
424 {
425     GDIOBJHDR * ptr = NULL;
426
427     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
428       ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
429     else 
430       ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
431     if (!ptr) return NULL;
432     if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic)) 
433     {
434       GDI_HEAP_UNLOCK( handle );
435       return NULL;
436     }
437     return ptr;
438 }
439
440
441 /***********************************************************************
442  *           DeleteObject16    (GDI.69)
443  */
444 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
445 {
446     return DeleteObject( obj );
447 }
448
449
450 /***********************************************************************
451  *           DeleteObject32    (GDI32.70)
452  */
453 BOOL WINAPI DeleteObject( HGDIOBJ obj )
454 {
455       /* Check if object is valid */
456
457     GDIOBJHDR * header;
458     if (HIWORD(obj)) return FALSE;
459     if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
460         return TRUE;
461     if (obj == hPseudoStockBitmap) return TRUE;
462     if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
463
464     TRACE("%04x\n", obj );
465
466       /* Delete object */
467
468     switch(header->wMagic)
469     {
470       case PEN_MAGIC:     return GDI_FreeObject( obj );
471       case BRUSH_MAGIC:   return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
472       case FONT_MAGIC:    return GDI_FreeObject( obj );
473       case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
474       case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
475       case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
476       case DC_MAGIC:      return DeleteDC(obj);
477       case 0 :
478         WARN("Already deleted\n");
479         break;
480       default:
481         WARN("Unknown magic number (%d)\n",header->wMagic);
482     }
483     return FALSE;
484 }
485
486 /***********************************************************************
487  *           GetStockObject16    (GDI.87)
488  */
489 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
490 {
491     return (HGDIOBJ16)GetStockObject( obj );
492 }
493
494
495 /***********************************************************************
496  *           GetStockObject32    (GDI32.220)
497  */
498 HGDIOBJ WINAPI GetStockObject( INT obj )
499 {
500     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
501     if (!StockObjects[obj]) return 0;
502     TRACE("returning %d\n",
503                 FIRST_STOCK_HANDLE + obj );
504     return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
505 }
506
507
508 /***********************************************************************
509  *           GetObject16    (GDI.82)
510  */
511 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
512 {
513     GDIOBJHDR * ptr = NULL;
514     INT16 result = 0;
515     TRACE("%04x %d %p\n", handle, count, buffer );
516     if (!count) return 0;
517
518     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
519       ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
520     else
521       ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
522     if (!ptr) return 0;
523     
524     switch(ptr->wMagic)
525       {
526       case PEN_MAGIC:
527         result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
528         break;
529       case BRUSH_MAGIC: 
530         result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
531         break;
532       case BITMAP_MAGIC: 
533         result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
534         break;
535       case FONT_MAGIC:
536         result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
537         
538         /*
539          * Fix the LOGFONT structure for the stock fonts
540          */
541         if ( (handle >= FIRST_STOCK_HANDLE) && 
542              (handle <= LAST_STOCK_HANDLE) )
543           FixStockFontSize16(handle, count, buffer);    
544         break;
545       case PALETTE_MAGIC:
546         result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
547         break;
548       }
549     GDI_HEAP_UNLOCK( handle );
550     return result;
551 }
552
553
554 /***********************************************************************
555  *           GetObject32A    (GDI32.204)
556  */
557 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
558 {
559     GDIOBJHDR * ptr = NULL;
560     INT result = 0;
561     TRACE("%08x %d %p\n", handle, count, buffer );
562     if (!count) return 0;
563
564     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
565       ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
566     else
567       ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
568     if (!ptr) return 0;
569     
570     switch(ptr->wMagic)
571     {
572       case PEN_MAGIC:
573           result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
574           break;
575       case BRUSH_MAGIC: 
576           result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
577           break;
578       case BITMAP_MAGIC: 
579           result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
580           break;
581       case FONT_MAGIC:
582           result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
583           
584           /*
585            * Fix the LOGFONT structure for the stock fonts
586            */
587           if ( (handle >= FIRST_STOCK_HANDLE) && 
588                (handle <= LAST_STOCK_HANDLE) )
589             FixStockFontSizeA(handle, count, buffer);
590           break;
591       case PALETTE_MAGIC:
592           result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
593           break;
594       default:
595           FIXME("Magic %04x not implemented\n",
596                    ptr->wMagic );
597           break;
598     }
599     GDI_HEAP_UNLOCK( handle );
600     return result;
601 }
602 /***********************************************************************
603  *           GetObject32W    (GDI32.206)
604  */
605 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
606 {
607     GDIOBJHDR * ptr = NULL;
608     INT result = 0;
609     TRACE("%08x %d %p\n", handle, count, buffer );
610     if (!count) return 0;
611
612     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
613       ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
614     else
615       ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
616     if (!ptr) return 0;
617     
618     switch(ptr->wMagic)
619     {
620       case PEN_MAGIC:
621           result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
622           break;
623       case BRUSH_MAGIC: 
624           result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
625           break;
626       case BITMAP_MAGIC: 
627           result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
628           break;
629       case FONT_MAGIC:
630           result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
631
632           /*
633            * Fix the LOGFONT structure for the stock fonts
634            */
635           if ( (handle >= FIRST_STOCK_HANDLE) && 
636                (handle <= LAST_STOCK_HANDLE) )
637             FixStockFontSizeW(handle, count, buffer);
638           break;
639       case PALETTE_MAGIC:
640           result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
641           break;
642       default:
643           FIXME("Magic %04x not implemented\n",
644                    ptr->wMagic );
645           break;
646     }
647     GDI_HEAP_UNLOCK( handle );
648     return result;
649 }
650
651 /***********************************************************************
652  *           GetObjectType    (GDI32.205)
653  */
654 DWORD WINAPI GetObjectType( HANDLE handle )
655 {
656     GDIOBJHDR * ptr = NULL;
657     INT result = 0;
658     TRACE("%08x\n", handle );
659
660     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
661       ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
662     else
663       ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
664     if (!ptr) return 0;
665     
666     switch(ptr->wMagic)
667     {
668       case PEN_MAGIC:
669           result = OBJ_PEN;
670           break;
671       case BRUSH_MAGIC: 
672           result = OBJ_BRUSH;
673           break;
674       case BITMAP_MAGIC: 
675           result = OBJ_BITMAP;
676           break;
677       case FONT_MAGIC:
678           result = OBJ_FONT;
679           break;
680       case PALETTE_MAGIC:
681           result = OBJ_PAL;
682           break;
683       case REGION_MAGIC:
684           result = OBJ_REGION;
685           break;
686       case DC_MAGIC:
687           result = OBJ_DC;
688           break;
689       case META_DC_MAGIC:
690           result = OBJ_METADC;
691           break;
692       case METAFILE_MAGIC:
693           result = OBJ_METAFILE;
694           break;
695       case METAFILE_DC_MAGIC:
696           result = OBJ_METADC;
697           break;
698       case ENHMETAFILE_MAGIC:
699           result = OBJ_ENHMETAFILE;
700           break;
701       case ENHMETAFILE_DC_MAGIC:
702           result = OBJ_ENHMETADC;
703           break;
704       default:
705           FIXME("Magic %04x not implemented\n",
706                            ptr->wMagic );
707           break;
708     }
709     GDI_HEAP_UNLOCK( handle );
710     return result;
711 }
712
713 /***********************************************************************
714  *           GetCurrentObject           (GDI32.166)
715  */
716 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
717 {
718     DC * dc = DC_GetDCPtr( hdc );
719
720     if (!dc) 
721         return 0;
722     switch (type) {
723     case OBJ_PEN:       return dc->w.hPen;
724     case OBJ_BRUSH:     return dc->w.hBrush;
725     case OBJ_PAL:       return dc->w.hPalette;
726     case OBJ_FONT:      return dc->w.hFont;
727     case OBJ_BITMAP:    return dc->w.hBitmap;
728     default:
729         /* the SDK only mentions those above */
730         WARN("(%08x,%d): unknown type.\n",hdc,type);
731         return 0;
732     }
733 }
734
735
736 /***********************************************************************
737  *           SelectObject16    (GDI.45)
738  */
739 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
740 {
741     return (HGDIOBJ16)SelectObject( hdc, handle );
742 }
743
744
745 /***********************************************************************
746  *           SelectObject32    (GDI32.299)
747  */
748 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
749 {
750     DC * dc = DC_GetDCPtr( hdc );
751     if (!dc || !dc->funcs->pSelectObject) return 0;
752     TRACE("hdc=%04x %04x\n", hdc, handle );
753     return dc->funcs->pSelectObject( dc, handle );
754 }
755
756
757 /***********************************************************************
758  *           UnrealizeObject16    (GDI.150)
759  */
760 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
761 {
762     return UnrealizeObject( obj );
763 }
764
765
766 /***********************************************************************
767  *           UnrealizeObject    (GDI32.358)
768  */
769 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
770 {
771     BOOL result = TRUE;
772   /* Check if object is valid */
773
774     GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
775     if (!header) return FALSE;
776
777     TRACE("%04x\n", obj );
778
779       /* Unrealize object */
780
781     switch(header->wMagic)
782     {
783     case PALETTE_MAGIC: 
784         result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
785         break;
786
787     case BRUSH_MAGIC:
788         /* Windows resets the brush origin. We don't need to. */
789         break;
790     }
791     GDI_HEAP_UNLOCK( obj );
792     return result;
793 }
794
795
796 /***********************************************************************
797  *           EnumObjects16    (GDI.71)
798  */
799 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
800                             GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
801 {
802     /* Solid colors to enumerate */
803     static const COLORREF solid_colors[] =
804     { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
805       RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
806       RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
807       RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
808       RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
809       RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
810       RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
811       RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
812     };
813     
814     INT16 i, retval = 0;
815     LOGPEN16 *pen;
816     LOGBRUSH16 *brush = NULL;
817
818     TRACE("%04x %d %08lx %08lx\n",
819                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
820     switch(nObjType)
821     {
822     case OBJ_PEN:
823         /* Enumerate solid pens */
824         if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
825         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
826         {
827             pen->lopnStyle   = PS_SOLID;
828             pen->lopnWidth.x = 1;
829             pen->lopnWidth.y = 0;
830             pen->lopnColor   = solid_colors[i];
831             retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
832             TRACE("solid pen %08lx, ret=%d\n",
833                          solid_colors[i], retval);
834             if (!retval) break;
835         }
836         SEGPTR_FREE(pen);
837         break;
838
839     case OBJ_BRUSH:
840         /* Enumerate solid brushes */
841         if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
842         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
843         {
844             brush->lbStyle = BS_SOLID;
845             brush->lbColor = solid_colors[i];
846             brush->lbHatch = 0;
847             retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
848             TRACE("solid brush %08lx, ret=%d\n",
849                          solid_colors[i], retval);
850             if (!retval) break;
851         }
852
853         /* Now enumerate hatched brushes */
854         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
855         {
856             brush->lbStyle = BS_HATCHED;
857             brush->lbColor = RGB(0,0,0);
858             brush->lbHatch = i;
859             retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
860             TRACE("hatched brush %d, ret=%d\n",
861                          i, retval);
862             if (!retval) break;
863         }
864         SEGPTR_FREE(brush);
865         break;
866
867     default:
868         WARN("(%d): Invalid type\n", nObjType );
869         break;
870     }
871     return retval;
872 }
873
874
875 /***********************************************************************
876  *           EnumObjects32    (GDI32.89)
877  */
878 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
879                             GOBJENUMPROC lpEnumFunc, LPARAM lParam )
880 {
881     /* Solid colors to enumerate */
882     static const COLORREF solid_colors[] =
883     { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
884       RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
885       RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
886       RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
887       RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
888       RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
889       RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
890       RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
891     };
892     
893     INT i, retval = 0;
894     LOGPEN pen;
895     LOGBRUSH brush;
896
897     TRACE("%04x %d %08lx %08lx\n",
898                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
899     switch(nObjType)
900     {
901     case OBJ_PEN:
902         /* Enumerate solid pens */
903         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
904         {
905             pen.lopnStyle   = PS_SOLID;
906             pen.lopnWidth.x = 1;
907             pen.lopnWidth.y = 0;
908             pen.lopnColor   = solid_colors[i];
909             retval = lpEnumFunc( &pen, lParam );
910             TRACE("solid pen %08lx, ret=%d\n",
911                          solid_colors[i], retval);
912             if (!retval) break;
913         }
914         break;
915
916     case OBJ_BRUSH:
917         /* Enumerate solid brushes */
918         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
919         {
920             brush.lbStyle = BS_SOLID;
921             brush.lbColor = solid_colors[i];
922             brush.lbHatch = 0;
923             retval = lpEnumFunc( &brush, lParam );
924             TRACE("solid brush %08lx, ret=%d\n",
925                          solid_colors[i], retval);
926             if (!retval) break;
927         }
928
929         /* Now enumerate hatched brushes */
930         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
931         {
932             brush.lbStyle = BS_HATCHED;
933             brush.lbColor = RGB(0,0,0);
934             brush.lbHatch = i;
935             retval = lpEnumFunc( &brush, lParam );
936             TRACE("hatched brush %d, ret=%d\n",
937                          i, retval);
938             if (!retval) break;
939         }
940         break;
941
942     default:
943         /* FIXME: implement Win32 types */
944         WARN("(%d): Invalid type\n", nObjType );
945         break;
946     }
947     return retval;
948 }
949
950
951 /***********************************************************************
952  *           IsGDIObject    (GDI.462)
953  * 
954  * returns type of object if valid (W95 system programming secrets p. 264-5)
955  */
956 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
957 {
958     UINT16 magic = 0;
959
960     if (handle >= FIRST_STOCK_HANDLE ) 
961     {
962         switch (handle)
963         {
964         case STOCK_WHITE_BRUSH:
965         case STOCK_LTGRAY_BRUSH:
966         case STOCK_GRAY_BRUSH:
967         case STOCK_DKGRAY_BRUSH:
968         case STOCK_BLACK_BRUSH:
969         case STOCK_HOLLOW_BRUSH:
970             magic = BRUSH_MAGIC;
971             break;
972
973         case STOCK_WHITE_PEN:
974         case STOCK_BLACK_PEN:
975         case STOCK_NULL_PEN :
976             magic = PEN_MAGIC;
977             break;
978
979         case STOCK_OEM_FIXED_FONT:
980         case STOCK_ANSI_FIXED_FONT:
981         case STOCK_ANSI_VAR_FONT:
982         case STOCK_SYSTEM_FONT:
983         case STOCK_DEVICE_DEFAULT_FONT:
984         case STOCK_SYSTEM_FIXED_FONT:
985         case STOCK_DEFAULT_GUI_FONT:
986             magic = FONT_MAGIC;
987             break;
988
989         case STOCK_DEFAULT_PALETTE:
990             magic = PALETTE_MAGIC;
991             break;
992         }
993     }
994     else
995     {
996         GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
997         if (object)
998         {
999             magic = object->wMagic;
1000             GDI_HEAP_UNLOCK( handle );
1001         }
1002     }
1003
1004     if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
1005         return magic - PEN_MAGIC + 1;
1006     else
1007         return FALSE;
1008 }
1009
1010
1011 /***********************************************************************
1012  *           SetObjectOwner16    (GDI.461)
1013  */
1014 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1015 {
1016     /* Nothing to do */
1017 }
1018
1019
1020 /***********************************************************************
1021  *           SetObjectOwner32    (GDI32.386)
1022  */
1023 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1024 {
1025     /* Nothing to do */
1026 }
1027
1028 /***********************************************************************
1029  *           MakeObjectPrivate    (GDI.463)
1030  */
1031 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1032 {
1033     /* FIXME */
1034 }
1035
1036
1037 /***********************************************************************
1038  *           GdiFlush    (GDI32.128)
1039  */
1040 BOOL WINAPI GdiFlush(void)
1041 {
1042     return TRUE;  /* FIXME */
1043 }
1044
1045
1046 /***********************************************************************
1047  *           GdiGetBatchLimit    (GDI32.129)
1048  */
1049 DWORD WINAPI GdiGetBatchLimit(void)
1050 {
1051     return 1;  /* FIXME */
1052 }
1053
1054
1055 /***********************************************************************
1056  *           GdiSetBatchLimit    (GDI32.139)
1057  */
1058 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1059 {
1060     return 1; /* FIXME */
1061 }
1062
1063
1064 /***********************************************************************
1065  *           GdiSeeGdiDo   (GDI.452)
1066  */
1067 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1068                           WORD wParam3 )
1069 {
1070     switch (wReqType)
1071     {
1072     case 0x0001:  /* LocalAlloc */
1073         return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1074     case 0x0002:  /* LocalFree */
1075         return LOCAL_Free( GDI_HeapSel, wParam1 );
1076     case 0x0003:  /* LocalCompact */
1077         return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1078     case 0x0103:  /* LocalHeap */
1079         return GDI_HeapSel;
1080     default:
1081         WARN("(wReqType=%04x): Unknown\n", wReqType);
1082         return (DWORD)-1;
1083     }
1084 }
1085
1086 /***********************************************************************
1087  *           GdiSignalProc     (GDI.610)
1088  */
1089 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1090                            DWORD dwFlags, HMODULE16 hModule )
1091 {
1092     return 0;
1093 }
1094
1095 /***********************************************************************
1096  *           FinalGdiInit16     (GDI.405)
1097  */
1098 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1099 {
1100 }
1101
1102 /***********************************************************************
1103  *           GdiFreeResources   (GDI.609)
1104  */
1105 WORD WINAPI GdiFreeResources16( DWORD reserve )
1106 {
1107    return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1108                   (int)LOCAL_HeapSize( GDI_HeapSel ) );
1109 }
1110
1111 /***********************************************************************
1112  *           MulDiv16   (GDI.128)
1113  */
1114 INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
1115 {
1116     INT ret;
1117     if (!baz) return -32768;
1118     ret = (foo * bar) / baz;
1119     if ((ret > 32767) || (ret < -32767)) return -32768;
1120     return ret;
1121 }
1122
1123
1124 /***********************************************************************
1125  *           MulDiv32   (KERNEL32.391)
1126  * RETURNS
1127  *      Result of multiplication and division
1128  *      -1: Overflow occurred or Divisor was 0
1129  */
1130 INT WINAPI MulDiv(
1131              INT nMultiplicand, 
1132              INT nMultiplier,
1133              INT nDivisor
1134 ) {
1135 #if SIZEOF_LONG_LONG >= 8
1136     long long ret;
1137
1138     if (!nDivisor) return -1;
1139
1140     /* We want to deal with a positive divisor to simplify the logic. */
1141     if (nDivisor < 0)
1142     {
1143       nMultiplicand = - nMultiplicand;
1144       nDivisor = -nDivisor;
1145     }
1146
1147     /* If the result is positive, we "add" to round. else, we subtract to round. */
1148     if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
1149          ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1150       ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1151     else
1152       ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1153
1154     if ((ret > 2147483647) || (ret < -2147483647)) return -1;
1155     return ret;
1156 #else
1157     if (!nDivisor) return -1;
1158
1159     /* We want to deal with a positive divisor to simplify the logic. */
1160     if (nDivisor < 0)
1161     {
1162       nMultiplicand = - nMultiplicand;
1163       nDivisor = -nDivisor;
1164     }
1165
1166     /* If the result is positive, we "add" to round. else, we subtract to round. */
1167     if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
1168          ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1169       return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1170  
1171     return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1172     
1173 #endif
1174 }
1175 /*******************************************************************
1176  *      GetColorAdjustment [GDI32.164]
1177  *
1178  *
1179  */
1180 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1181 {
1182         FIXME("GetColorAdjustment, stub\n");
1183         return 0;
1184 }
1185
1186 /*******************************************************************
1187  *      GetMiterLimit [GDI32.201]
1188  *
1189  *
1190  */
1191 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1192 {
1193         FIXME("GetMiterLimit, stub\n");
1194         return 0;
1195 }
1196
1197 /*******************************************************************
1198  *      SetMiterLimit [GDI32.325]
1199  *
1200  *
1201  */
1202 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1203 {
1204         FIXME("SetMiterLimit, stub\n");
1205         return 0;
1206 }
1207
1208 /*******************************************************************
1209  *      GdiComment [GDI32.109]
1210  *
1211  *
1212  */
1213 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1214 {
1215         FIXME("GdiComment, stub\n");
1216         return 0;
1217 }
1218 /*******************************************************************
1219  *      SetColorAdjustment [GDI32.309]
1220  *
1221  *
1222  */
1223 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1224 {
1225         FIXME("SetColorAdjustment, stub\n");
1226         return 0;
1227 }
1228