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