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