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