No longer directly accessing debuggee memory.
[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 HGDIOBJ 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( HGDIOBJ 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( HGDIOBJ handle, WORD magic )
424 {
425     GDIOBJHDR * ptr = NULL;
426
427     if (handle >= FIRST_STOCK_HANDLE)
428     {
429         if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
430     }
431     else 
432       ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
433     if (!ptr) return NULL;
434     if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic)) 
435     {
436       GDI_HEAP_UNLOCK( handle );
437       return NULL;
438     }
439     return ptr;
440 }
441
442
443 /***********************************************************************
444  *           DeleteObject16    (GDI.69)
445  */
446 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
447 {
448     return DeleteObject( obj );
449 }
450
451
452 /***********************************************************************
453  *           DeleteObject32    (GDI32.70)
454  */
455 BOOL WINAPI DeleteObject( HGDIOBJ obj )
456 {
457       /* Check if object is valid */
458
459     GDIOBJHDR * header;
460     if (HIWORD(obj)) return FALSE;
461     if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
462         return TRUE;
463     if (obj == hPseudoStockBitmap) return TRUE;
464     if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
465
466     TRACE("%04x\n", obj );
467
468       /* Delete object */
469
470     switch(header->wMagic)
471     {
472       case PEN_MAGIC:     return GDI_FreeObject( obj );
473       case BRUSH_MAGIC:   return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
474       case FONT_MAGIC:    return GDI_FreeObject( obj );
475       case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
476       case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
477       case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
478       case DC_MAGIC:      return DeleteDC(obj);
479       case 0 :
480         WARN("Already deleted\n");
481         break;
482       default:
483         WARN("Unknown magic number (%d)\n",header->wMagic);
484     }
485     return FALSE;
486 }
487
488 /***********************************************************************
489  *           GetStockObject16    (GDI.87)
490  */
491 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
492 {
493     return (HGDIOBJ16)GetStockObject( obj );
494 }
495
496
497 /***********************************************************************
498  *           GetStockObject32    (GDI32.220)
499  */
500 HGDIOBJ WINAPI GetStockObject( INT obj )
501 {
502     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
503     if (!StockObjects[obj]) return 0;
504     TRACE("returning %d\n",
505                 FIRST_STOCK_HANDLE + obj );
506     return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
507 }
508
509
510 /***********************************************************************
511  *           GetObject16    (GDI.82)
512  */
513 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
514 {
515     GDIOBJHDR * ptr;
516     INT16 result = 0;
517     TRACE("%04x %d %p\n", handle, count, buffer );
518     if (!count) return 0;
519
520     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
521     
522     switch(ptr->wMagic)
523       {
524       case PEN_MAGIC:
525         result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
526         break;
527       case BRUSH_MAGIC: 
528         result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
529         break;
530       case BITMAP_MAGIC: 
531         result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
532         break;
533       case FONT_MAGIC:
534         result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
535         
536         /*
537          * Fix the LOGFONT structure for the stock fonts
538          */
539         if ( (handle >= FIRST_STOCK_HANDLE) && 
540              (handle <= LAST_STOCK_HANDLE) )
541           FixStockFontSize16(handle, count, buffer);    
542         break;
543       case PALETTE_MAGIC:
544         result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
545         break;
546       }
547     GDI_HEAP_UNLOCK( handle );
548     return result;
549 }
550
551
552 /***********************************************************************
553  *           GetObject32A    (GDI32.204)
554  */
555 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
556 {
557     GDIOBJHDR * ptr;
558     INT result = 0;
559     TRACE("%08x %d %p\n", handle, count, buffer );
560     if (!count) return 0;
561
562     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
563
564     switch(ptr->wMagic)
565     {
566       case PEN_MAGIC:
567           result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
568           break;
569       case BRUSH_MAGIC: 
570           result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
571           break;
572       case BITMAP_MAGIC: 
573           result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
574           break;
575       case FONT_MAGIC:
576           result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
577           
578           /*
579            * Fix the LOGFONT structure for the stock fonts
580            */
581           if ( (handle >= FIRST_STOCK_HANDLE) && 
582                (handle <= LAST_STOCK_HANDLE) )
583             FixStockFontSizeA(handle, count, buffer);
584           break;
585       case PALETTE_MAGIC:
586           result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
587           break;
588
589       case REGION_MAGIC:
590       case DC_MAGIC:
591       case DISABLED_DC_MAGIC:
592       case META_DC_MAGIC:
593       case METAFILE_MAGIC:
594       case METAFILE_DC_MAGIC:
595       case ENHMETAFILE_MAGIC:
596       case ENHMETAFILE_DC_MAGIC:
597           FIXME("Magic %04x not implemented\n",
598                    ptr->wMagic );
599           break;
600
601       default:
602           ERR("Invalid GDI Magic %04x\n", ptr->wMagic);
603           return 0;
604     }
605     GDI_HEAP_UNLOCK( handle );
606     return result;
607 }
608
609 /***********************************************************************
610  *           GetObject32W    (GDI32.206)
611  */
612 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
613 {
614     GDIOBJHDR * ptr;
615     INT result = 0;
616     TRACE("%08x %d %p\n", handle, count, buffer );
617     if (!count) return 0;
618
619     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
620
621     switch(ptr->wMagic)
622     {
623       case PEN_MAGIC:
624           result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
625           break;
626       case BRUSH_MAGIC: 
627           result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
628           break;
629       case BITMAP_MAGIC: 
630           result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
631           break;
632       case FONT_MAGIC:
633           result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
634
635           /*
636            * Fix the LOGFONT structure for the stock fonts
637            */
638           if ( (handle >= FIRST_STOCK_HANDLE) && 
639                (handle <= LAST_STOCK_HANDLE) )
640             FixStockFontSizeW(handle, count, buffer);
641           break;
642       case PALETTE_MAGIC:
643           result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
644           break;
645       default:
646           FIXME("Magic %04x not implemented\n",
647                    ptr->wMagic );
648           break;
649     }
650     GDI_HEAP_UNLOCK( handle );
651     return result;
652 }
653
654 /***********************************************************************
655  *           GetObjectType    (GDI32.205)
656  */
657 DWORD WINAPI GetObjectType( HANDLE handle )
658 {
659     GDIOBJHDR * ptr;
660     INT result = 0;
661     TRACE("%08x\n", handle );
662
663     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
664     
665     switch(ptr->wMagic)
666     {
667       case PEN_MAGIC:
668           result = OBJ_PEN;
669           break;
670       case BRUSH_MAGIC: 
671           result = OBJ_BRUSH;
672           break;
673       case BITMAP_MAGIC: 
674           result = OBJ_BITMAP;
675           break;
676       case FONT_MAGIC:
677           result = OBJ_FONT;
678           break;
679       case PALETTE_MAGIC:
680           result = OBJ_PAL;
681           break;
682       case REGION_MAGIC:
683           result = OBJ_REGION;
684           break;
685       case DC_MAGIC:
686           result = OBJ_DC;
687           break;
688       case META_DC_MAGIC:
689           result = OBJ_METADC;
690           break;
691       case METAFILE_MAGIC:
692           result = OBJ_METAFILE;
693           break;
694       case METAFILE_DC_MAGIC:
695           result = OBJ_METADC;
696           break;
697       case ENHMETAFILE_MAGIC:
698           result = OBJ_ENHMETAFILE;
699           break;
700       case ENHMETAFILE_DC_MAGIC:
701           result = OBJ_ENHMETADC;
702           break;
703       default:
704           FIXME("Magic %04x not implemented\n",
705                            ptr->wMagic );
706           break;
707     }
708     GDI_HEAP_UNLOCK( handle );
709     return result;
710 }
711
712 /***********************************************************************
713  *           GetCurrentObject           (GDI32.166)
714  */
715 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
716 {
717     DC * dc = DC_GetDCPtr( hdc );
718
719     if (!dc) 
720         return 0;
721     switch (type) {
722     case OBJ_PEN:       return dc->w.hPen;
723     case OBJ_BRUSH:     return dc->w.hBrush;
724     case OBJ_PAL:       return dc->w.hPalette;
725     case OBJ_FONT:      return dc->w.hFont;
726     case OBJ_BITMAP:    return dc->w.hBitmap;
727     default:
728         /* the SDK only mentions those above */
729         WARN("(%08x,%d): unknown type.\n",hdc,type);
730         return 0;
731     }
732 }
733
734
735 /***********************************************************************
736  *           SelectObject16    (GDI.45)
737  */
738 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
739 {
740     return (HGDIOBJ16)SelectObject( hdc, handle );
741 }
742
743
744 /***********************************************************************
745  *           SelectObject32    (GDI32.299)
746  */
747 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
748 {
749     DC * dc = DC_GetDCPtr( hdc );
750     if (!dc || !dc->funcs->pSelectObject) return 0;
751     TRACE("hdc=%04x %04x\n", hdc, handle );
752     return dc->funcs->pSelectObject( dc, handle );
753 }
754
755
756 /***********************************************************************
757  *           UnrealizeObject16    (GDI.150)
758  */
759 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
760 {
761     return UnrealizeObject( obj );
762 }
763
764
765 /***********************************************************************
766  *           UnrealizeObject    (GDI32.358)
767  */
768 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
769 {
770     BOOL result = TRUE;
771   /* Check if object is valid */
772
773     GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
774     if (!header) return FALSE;
775
776     TRACE("%04x\n", obj );
777
778       /* Unrealize object */
779
780     switch(header->wMagic)
781     {
782     case PALETTE_MAGIC: 
783         result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
784         break;
785
786     case BRUSH_MAGIC:
787         /* Windows resets the brush origin. We don't need to. */
788         break;
789     }
790     GDI_HEAP_UNLOCK( obj );
791     return result;
792 }
793
794
795 /***********************************************************************
796  *           EnumObjects16    (GDI.71)
797  */
798 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
799                             GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
800 {
801     /* Solid colors to enumerate */
802     static const COLORREF solid_colors[] =
803     { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
804       RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
805       RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
806       RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
807       RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
808       RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
809       RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
810       RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
811     };
812     
813     INT16 i, retval = 0;
814     LOGPEN16 *pen;
815     LOGBRUSH16 *brush = NULL;
816
817     TRACE("%04x %d %08lx %08lx\n",
818                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
819     switch(nObjType)
820     {
821     case OBJ_PEN:
822         /* Enumerate solid pens */
823         if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
824         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
825         {
826             pen->lopnStyle   = PS_SOLID;
827             pen->lopnWidth.x = 1;
828             pen->lopnWidth.y = 0;
829             pen->lopnColor   = solid_colors[i];
830             retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
831             TRACE("solid pen %08lx, ret=%d\n",
832                          solid_colors[i], retval);
833             if (!retval) break;
834         }
835         SEGPTR_FREE(pen);
836         break;
837
838     case OBJ_BRUSH:
839         /* Enumerate solid brushes */
840         if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
841         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
842         {
843             brush->lbStyle = BS_SOLID;
844             brush->lbColor = solid_colors[i];
845             brush->lbHatch = 0;
846             retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
847             TRACE("solid brush %08lx, ret=%d\n",
848                          solid_colors[i], retval);
849             if (!retval) break;
850         }
851
852         /* Now enumerate hatched brushes */
853         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
854         {
855             brush->lbStyle = BS_HATCHED;
856             brush->lbColor = RGB(0,0,0);
857             brush->lbHatch = i;
858             retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
859             TRACE("hatched brush %d, ret=%d\n",
860                          i, retval);
861             if (!retval) break;
862         }
863         SEGPTR_FREE(brush);
864         break;
865
866     default:
867         WARN("(%d): Invalid type\n", nObjType );
868         break;
869     }
870     return retval;
871 }
872
873
874 /***********************************************************************
875  *           EnumObjects32    (GDI32.89)
876  */
877 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
878                             GOBJENUMPROC lpEnumFunc, LPARAM lParam )
879 {
880     /* Solid colors to enumerate */
881     static const COLORREF solid_colors[] =
882     { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
883       RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
884       RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
885       RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
886       RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
887       RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
888       RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
889       RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
890     };
891     
892     INT i, retval = 0;
893     LOGPEN pen;
894     LOGBRUSH brush;
895
896     TRACE("%04x %d %08lx %08lx\n",
897                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
898     switch(nObjType)
899     {
900     case OBJ_PEN:
901         /* Enumerate solid pens */
902         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
903         {
904             pen.lopnStyle   = PS_SOLID;
905             pen.lopnWidth.x = 1;
906             pen.lopnWidth.y = 0;
907             pen.lopnColor   = solid_colors[i];
908             retval = lpEnumFunc( &pen, lParam );
909             TRACE("solid pen %08lx, ret=%d\n",
910                          solid_colors[i], retval);
911             if (!retval) break;
912         }
913         break;
914
915     case OBJ_BRUSH:
916         /* Enumerate solid brushes */
917         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
918         {
919             brush.lbStyle = BS_SOLID;
920             brush.lbColor = solid_colors[i];
921             brush.lbHatch = 0;
922             retval = lpEnumFunc( &brush, lParam );
923             TRACE("solid brush %08lx, ret=%d\n",
924                          solid_colors[i], retval);
925             if (!retval) break;
926         }
927
928         /* Now enumerate hatched brushes */
929         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
930         {
931             brush.lbStyle = BS_HATCHED;
932             brush.lbColor = RGB(0,0,0);
933             brush.lbHatch = i;
934             retval = lpEnumFunc( &brush, lParam );
935             TRACE("hatched brush %d, ret=%d\n",
936                          i, retval);
937             if (!retval) break;
938         }
939         break;
940
941     default:
942         /* FIXME: implement Win32 types */
943         WARN("(%d): Invalid type\n", nObjType );
944         break;
945     }
946     return retval;
947 }
948
949
950 /***********************************************************************
951  *           IsGDIObject    (GDI.462)
952  * 
953  * returns type of object if valid (W95 system programming secrets p. 264-5)
954  */
955 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
956 {
957     UINT16 magic = 0;
958
959     if (handle >= FIRST_STOCK_HANDLE ) 
960     {
961         switch (handle)
962         {
963         case STOCK_WHITE_BRUSH:
964         case STOCK_LTGRAY_BRUSH:
965         case STOCK_GRAY_BRUSH:
966         case STOCK_DKGRAY_BRUSH:
967         case STOCK_BLACK_BRUSH:
968         case STOCK_HOLLOW_BRUSH:
969             magic = BRUSH_MAGIC;
970             break;
971
972         case STOCK_WHITE_PEN:
973         case STOCK_BLACK_PEN:
974         case STOCK_NULL_PEN :
975             magic = PEN_MAGIC;
976             break;
977
978         case STOCK_OEM_FIXED_FONT:
979         case STOCK_ANSI_FIXED_FONT:
980         case STOCK_ANSI_VAR_FONT:
981         case STOCK_SYSTEM_FONT:
982         case STOCK_DEVICE_DEFAULT_FONT:
983         case STOCK_SYSTEM_FIXED_FONT:
984         case STOCK_DEFAULT_GUI_FONT:
985             magic = FONT_MAGIC;
986             break;
987
988         case STOCK_DEFAULT_PALETTE:
989             magic = PALETTE_MAGIC;
990             break;
991         }
992     }
993     else
994     {
995         GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
996         if (object)
997         {
998             magic = object->wMagic;
999             GDI_HEAP_UNLOCK( handle );
1000         }
1001     }
1002
1003     if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
1004         return magic - PEN_MAGIC + 1;
1005     else
1006         return FALSE;
1007 }
1008
1009
1010 /***********************************************************************
1011  *           SetObjectOwner16    (GDI.461)
1012  */
1013 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1014 {
1015     /* Nothing to do */
1016 }
1017
1018
1019 /***********************************************************************
1020  *           SetObjectOwner32    (GDI32.386)
1021  */
1022 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1023 {
1024     /* Nothing to do */
1025 }
1026
1027 /***********************************************************************
1028  *           MakeObjectPrivate    (GDI.463)
1029  */
1030 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1031 {
1032     /* FIXME */
1033 }
1034
1035
1036 /***********************************************************************
1037  *           GdiFlush    (GDI32.128)
1038  */
1039 BOOL WINAPI GdiFlush(void)
1040 {
1041     return TRUE;  /* FIXME */
1042 }
1043
1044
1045 /***********************************************************************
1046  *           GdiGetBatchLimit    (GDI32.129)
1047  */
1048 DWORD WINAPI GdiGetBatchLimit(void)
1049 {
1050     return 1;  /* FIXME */
1051 }
1052
1053
1054 /***********************************************************************
1055  *           GdiSetBatchLimit    (GDI32.139)
1056  */
1057 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1058 {
1059     return 1; /* FIXME */
1060 }
1061
1062
1063 /***********************************************************************
1064  *           GdiSeeGdiDo   (GDI.452)
1065  */
1066 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1067                           WORD wParam3 )
1068 {
1069     switch (wReqType)
1070     {
1071     case 0x0001:  /* LocalAlloc */
1072         return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1073     case 0x0002:  /* LocalFree */
1074         return LOCAL_Free( GDI_HeapSel, wParam1 );
1075     case 0x0003:  /* LocalCompact */
1076         return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1077     case 0x0103:  /* LocalHeap */
1078         return GDI_HeapSel;
1079     default:
1080         WARN("(wReqType=%04x): Unknown\n", wReqType);
1081         return (DWORD)-1;
1082     }
1083 }
1084
1085 /***********************************************************************
1086  *           GdiSignalProc     (GDI.610)
1087  */
1088 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1089                            DWORD dwFlags, HMODULE16 hModule )
1090 {
1091     return 0;
1092 }
1093
1094 /***********************************************************************
1095  *           FinalGdiInit16     (GDI.405)
1096  */
1097 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1098 {
1099 }
1100
1101 /***********************************************************************
1102  *           GdiFreeResources   (GDI.609)
1103  */
1104 WORD WINAPI GdiFreeResources16( DWORD reserve )
1105 {
1106    return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1107                   (int)LOCAL_HeapSize( GDI_HeapSel ) );
1108 }
1109
1110 /***********************************************************************
1111  *           MulDiv16   (GDI.128)
1112  */
1113 INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
1114 {
1115     INT ret;
1116     if (!baz) return -32768;
1117     ret = (foo * bar) / baz;
1118     if ((ret > 32767) || (ret < -32767)) return -32768;
1119     return ret;
1120 }
1121
1122
1123 /***********************************************************************
1124  *           MulDiv32   (KERNEL32.391)
1125  * RETURNS
1126  *      Result of multiplication and division
1127  *      -1: Overflow occurred or Divisor was 0
1128  */
1129 INT WINAPI MulDiv(
1130              INT nMultiplicand, 
1131              INT nMultiplier,
1132              INT nDivisor
1133 ) {
1134 #if SIZEOF_LONG_LONG >= 8
1135     long long ret;
1136
1137     if (!nDivisor) return -1;
1138
1139     /* We want to deal with a positive divisor to simplify the logic. */
1140     if (nDivisor < 0)
1141     {
1142       nMultiplicand = - nMultiplicand;
1143       nDivisor = -nDivisor;
1144     }
1145
1146     /* If the result is positive, we "add" to round. else, we subtract to round. */
1147     if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
1148          ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1149       ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1150     else
1151       ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1152
1153     if ((ret > 2147483647) || (ret < -2147483647)) return -1;
1154     return ret;
1155 #else
1156     if (!nDivisor) return -1;
1157
1158     /* We want to deal with a positive divisor to simplify the logic. */
1159     if (nDivisor < 0)
1160     {
1161       nMultiplicand = - nMultiplicand;
1162       nDivisor = -nDivisor;
1163     }
1164
1165     /* If the result is positive, we "add" to round. else, we subtract to round. */
1166     if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
1167          ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1168       return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1169  
1170     return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1171     
1172 #endif
1173 }
1174 /*******************************************************************
1175  *      GetColorAdjustment [GDI32.164]
1176  *
1177  *
1178  */
1179 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1180 {
1181         FIXME("GetColorAdjustment, stub\n");
1182         return 0;
1183 }
1184
1185 /*******************************************************************
1186  *      GetMiterLimit [GDI32.201]
1187  *
1188  *
1189  */
1190 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1191 {
1192         FIXME("GetMiterLimit, stub\n");
1193         return 0;
1194 }
1195
1196 /*******************************************************************
1197  *      SetMiterLimit [GDI32.325]
1198  *
1199  *
1200  */
1201 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1202 {
1203         FIXME("SetMiterLimit, stub\n");
1204         return 0;
1205 }
1206
1207 /*******************************************************************
1208  *      GdiComment [GDI32.109]
1209  *
1210  *
1211  */
1212 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1213 {
1214         FIXME("GdiComment, stub\n");
1215         return 0;
1216 }
1217 /*******************************************************************
1218  *      SetColorAdjustment [GDI32.309]
1219  *
1220  *
1221  */
1222 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1223 {
1224         FIXME("SetColorAdjustment, stub\n");
1225         return 0;
1226 }
1227