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