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