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