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