Unlock win16 crst while thunking up to 32 bit dll.
[wine.git] / objects / gdiobj.c
blob94a61da46f4c9c1e03c985ec3d8dd72e337df4f8
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <assert.h>
10 #include <stdlib.h>
11 #include <stdio.h>
13 #include "windef.h"
14 #include "wingdi.h"
15 #include "winerror.h"
16 #include "wine/winbase16.h"
18 #include "bitmap.h"
19 #include "brush.h"
20 #include "dc.h"
21 #include "font.h"
22 #include "heap.h"
23 #include "options.h"
24 #include "palette.h"
25 #include "pen.h"
26 #include "region.h"
27 #include "debugtools.h"
28 #include "gdi.h"
29 #include "tweak.h"
30 #include "syslevel.h"
32 DEFAULT_DEBUG_CHANNEL(gdi);
34 /**********************************************************************/
36 GDI_DRIVER *GDI_Driver = NULL;
38 /***********************************************************************
39 * GDI stock objects
42 static BRUSHOBJ WhiteBrush =
44 { 0, BRUSH_MAGIC, 1 }, /* header */
45 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
48 static BRUSHOBJ LtGrayBrush =
50 { 0, BRUSH_MAGIC, 1 }, /* header */
51 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
52 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
55 static BRUSHOBJ GrayBrush =
57 { 0, BRUSH_MAGIC, 1 }, /* header */
58 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
59 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
62 static BRUSHOBJ DkGrayBrush =
64 { 0, BRUSH_MAGIC, 1 }, /* header */
65 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
66 /* NB_HATCH_STYLES is an index into HatchBrushes */
67 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
70 static BRUSHOBJ BlackBrush =
72 { 0, BRUSH_MAGIC, 1 }, /* header */
73 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
76 static BRUSHOBJ NullBrush =
78 { 0, BRUSH_MAGIC, 1 }, /* header */
79 { BS_NULL, 0, 0 } /* logbrush */
82 static PENOBJ WhitePen =
84 { 0, PEN_MAGIC, 1 }, /* header */
85 { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
88 static PENOBJ BlackPen =
90 { 0, PEN_MAGIC, 1 }, /* header */
91 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
94 static PENOBJ NullPen =
96 { 0, PEN_MAGIC, 1 }, /* header */
97 { PS_NULL, { 1, 0 }, 0 } /* logpen */
100 static FONTOBJ OEMFixedFont =
102 { 0, FONT_MAGIC, 1 }, /* header */
103 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
104 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
106 /* Filler to make the location counter dword aligned again. This is necessary
107 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
108 segment, and (c) Solaris assembler is stupid. */
109 static UINT16 align_OEMFixedFont = 1;
111 static FONTOBJ AnsiFixedFont =
113 { 0, FONT_MAGIC, 1 }, /* header */
114 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
115 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
117 static UINT16 align_AnsiFixedFont = 1;
119 static FONTOBJ AnsiVarFont =
121 { 0, FONT_MAGIC, 1 }, /* header */
122 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
123 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
125 static UINT16 align_AnsiVarFont = 1;
127 static FONTOBJ SystemFont =
129 { 0, FONT_MAGIC, 1 },
130 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
131 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
133 static UINT16 align_SystemFont = 1;
135 static FONTOBJ DeviceDefaultFont =
137 { 0, FONT_MAGIC, 1 }, /* header */
138 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
139 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
141 static UINT16 align_DeviceDefaultFont = 1;
143 static FONTOBJ SystemFixedFont =
145 { 0, FONT_MAGIC, 1 }, /* header */
146 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
147 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
149 static UINT16 align_SystemFixedFont = 1;
151 /* FIXME: Is this correct? */
152 static FONTOBJ DefaultGuiFont =
154 { 0, FONT_MAGIC, 1 }, /* header */
155 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
156 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
158 static UINT16 align_DefaultGuiFont = 1;
161 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
163 (GDIOBJHDR *) &WhiteBrush,
164 (GDIOBJHDR *) &LtGrayBrush,
165 (GDIOBJHDR *) &GrayBrush,
166 (GDIOBJHDR *) &DkGrayBrush,
167 (GDIOBJHDR *) &BlackBrush,
168 (GDIOBJHDR *) &NullBrush,
169 (GDIOBJHDR *) &WhitePen,
170 (GDIOBJHDR *) &BlackPen,
171 (GDIOBJHDR *) &NullPen,
172 NULL,
173 (GDIOBJHDR *) &OEMFixedFont,
174 (GDIOBJHDR *) &AnsiFixedFont,
175 (GDIOBJHDR *) &AnsiVarFont,
176 (GDIOBJHDR *) &SystemFont,
177 (GDIOBJHDR *) &DeviceDefaultFont,
178 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
179 (GDIOBJHDR *) &SystemFixedFont,
180 (GDIOBJHDR *) &DefaultGuiFont
183 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
185 static SYSLEVEL GDI_level;
186 static WORD GDI_HeapSel;
189 /******************************************************************************
191 * void ReadFontInformation(
192 * char const *fontName,
193 * FONTOBJ *font,
194 * int defHeight,
195 * int defBold,
196 * int defItalic,
197 * int defUnderline,
198 * int defStrikeOut )
200 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
201 * section for entries containing fontName.Height, fontName.Bold, etc.,
202 * where fontName is the name specified in the call (e.g., "System"). It
203 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
204 * the first character in the boolean attributes (bold, italic, and
205 * underline).
206 *****************************************************************************/
208 static void ReadFontInformation(
209 char const *fontName,
210 FONTOBJ *font,
211 int defHeight,
212 int defBold,
213 int defItalic,
214 int defUnderline,
215 int defStrikeOut )
217 char key[256];
219 /* In order for the stock fonts to be independent of
220 * mapping mode, the height (& width) must be 0
222 sprintf(key, "%s.Height", fontName);
223 font->logfont.lfHeight =
224 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
226 sprintf(key, "%s.Bold", fontName);
227 font->logfont.lfWeight =
228 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
229 FW_BOLD : FW_NORMAL;
231 sprintf(key, "%s.Italic", fontName);
232 font->logfont.lfItalic =
233 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
235 sprintf(key, "%s.Underline", fontName);
236 font->logfont.lfUnderline =
237 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
239 sprintf(key, "%s.StrikeOut", fontName);
240 font->logfont.lfStrikeOut =
241 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
243 return;
246 /***********************************************************************
247 * Because the stock fonts have their structure initialized with
248 * a height of 0 to keep them independent of mapping mode, simply
249 * returning the LOGFONT as is will not work correctly.
250 * These "FixStockFontSizeXXX()" methods will get the correct
251 * size for the fonts.
253 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
255 HDC hdc;
256 HFONT hOldFont;
258 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
260 hOldFont = (HFONT)SelectObject(hdc, handle);
262 GetTextMetricsA(hdc, lptm);
264 SelectObject(hdc, hOldFont);
266 DeleteDC(hdc);
269 static inline void FixStockFontSize16(
270 HFONT handle,
271 INT16 count,
272 LPVOID buffer)
274 TEXTMETRICA tm;
275 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
278 * Was the lfHeight field copied (it's the first field)?
279 * If it was and it was null, replace the height.
281 if ( (count >= 2*sizeof(INT16)) &&
282 (pLogFont->lfHeight == 0) )
284 GetFontMetrics(handle, &tm);
286 pLogFont->lfHeight = tm.tmHeight;
287 pLogFont->lfWidth = tm.tmAveCharWidth;
291 static inline void FixStockFontSizeA(
292 HFONT handle,
293 INT count,
294 LPVOID buffer)
296 TEXTMETRICA tm;
297 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
300 * Was the lfHeight field copied (it's the first field)?
301 * If it was and it was null, replace the height.
303 if ( (count >= 2*sizeof(INT)) &&
304 (pLogFont->lfHeight == 0) )
306 GetFontMetrics(handle, &tm);
308 pLogFont->lfHeight = tm.tmHeight;
309 pLogFont->lfWidth = tm.tmAveCharWidth;
314 * Since the LOGFONTA and LOGFONTW structures are identical up to the
315 * lfHeight member (the one of interest in this case) we simply define
316 * the W version as the A version.
318 #define FixStockFontSizeW FixStockFontSizeA
320 #define TRACE_SEC(handle,text) \
321 TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
323 /***********************************************************************
324 * GDI_Init
326 * GDI initialization.
328 BOOL GDI_Init(void)
330 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
331 HPALETTE16 hpalette;
332 HINSTANCE16 instance;
334 _CreateSysLevel( &GDI_level, 3 );
336 /* create GDI heap */
337 if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
338 GDI_HeapSel = GlobalHandleToSel16( instance );
340 /* Kill some warnings. */
341 (void)align_OEMFixedFont;
342 (void)align_AnsiFixedFont;
343 (void)align_AnsiVarFont;
344 (void)align_SystemFont;
345 (void)align_DeviceDefaultFont;
346 (void)align_SystemFixedFont;
347 (void)align_DefaultGuiFont;
349 /* TWEAK: Initialize font hints */
350 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
351 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
352 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
353 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
354 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
355 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
356 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
358 /* Create default palette */
360 /* DR well *this* palette can't be moveable (?) */
361 hpalette = PALETTE_Init();
362 if( !hpalette ) return FALSE;
363 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hpalette );
365 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
366 return TRUE;
370 /***********************************************************************
371 * GDI_AllocObject
373 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
375 static DWORD count = 0;
376 GDIOBJHDR *obj;
378 _EnterSysLevel( &GDI_level );
379 if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size )))
381 _LeaveSysLevel( &GDI_level );
382 return NULL;
384 obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
385 obj->hNext = 0;
386 obj->wMagic = magic|OBJECT_NOSYSTEM;
387 obj->dwCount = ++count;
389 TRACE_SEC( *handle, "enter" );
390 return obj;
394 /***********************************************************************
395 * GDI_ReallocObject
397 * The object ptr must have been obtained with GDI_GetObjPtr.
398 * The new pointer must be released with GDI_ReleaseObj.
400 void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
402 HGDIOBJ new_handle;
404 LOCAL_Unlock( GDI_HeapSel, handle );
405 if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
407 TRACE_SEC( handle, "leave" );
408 _LeaveSysLevel( &GDI_level );
409 return NULL;
411 assert( new_handle == handle ); /* moveable handle cannot change */
412 return LOCAL_Lock( GDI_HeapSel, handle );
416 /***********************************************************************
417 * GDI_FreeObject
419 BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
421 GDIOBJHDR *object = ptr;
423 /* can't free stock objects */
424 if (handle < FIRST_STOCK_HANDLE)
426 object->wMagic = 0; /* Mark it as invalid */
427 LOCAL_Unlock( GDI_HeapSel, handle );
428 LOCAL_Free( GDI_HeapSel, handle );
430 TRACE_SEC( handle, "leave" );
431 _LeaveSysLevel( &GDI_level );
432 return TRUE;
436 /***********************************************************************
437 * GDI_GetObjPtr
439 * Return a pointer to the GDI object associated to the handle.
440 * Return NULL if the object has the wrong magic number.
441 * The object must be released with GDI_ReleaseObj.
443 void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
445 GDIOBJHDR *ptr = NULL;
447 _EnterSysLevel( &GDI_level );
449 if (handle >= FIRST_STOCK_HANDLE)
451 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
452 if (ptr && (magic != MAGIC_DONTCARE)
453 && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
455 else
457 ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
458 if (ptr &&
459 (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic))
461 LOCAL_Unlock( GDI_HeapSel, handle );
462 ptr = NULL;
466 if (!ptr)
468 _LeaveSysLevel( &GDI_level );
469 SetLastError( ERROR_INVALID_HANDLE );
471 else TRACE_SEC( handle, "enter" );
473 return ptr;
477 /***********************************************************************
478 * GDI_ReleaseObj
481 void GDI_ReleaseObj( HGDIOBJ handle )
483 if (handle < FIRST_STOCK_HANDLE) LOCAL_Unlock( GDI_HeapSel, handle );
484 TRACE_SEC( handle, "leave" );
485 _LeaveSysLevel( &GDI_level );
489 /***********************************************************************
490 * DeleteObject16 (GDI.69)
492 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
494 return DeleteObject( obj );
498 /***********************************************************************
499 * DeleteObject (GDI32.70)
501 BOOL WINAPI DeleteObject( HGDIOBJ obj )
503 /* Check if object is valid */
505 GDIOBJHDR * header;
506 if (HIWORD(obj)) return FALSE;
507 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE)) {
508 TRACE("Preserving Stock object %04x\n", obj );
509 /* NOTE: No GDI_Release is necessary */
510 return TRUE;
512 if (obj == hPseudoStockBitmap) return TRUE;
513 if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
515 if (!(header->wMagic & OBJECT_NOSYSTEM)
516 && (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
518 TRACE("Preserving system object %04x\n", obj);
519 GDI_ReleaseObj( obj );
520 return TRUE;
523 TRACE("%04x\n", obj );
525 /* Delete object */
527 switch(GDIMAGIC(header->wMagic))
529 case PEN_MAGIC: return GDI_FreeObject( obj, header );
530 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
531 case FONT_MAGIC: return GDI_FreeObject( obj, header );
532 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
533 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
534 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
535 case DC_MAGIC:
536 GDI_ReleaseObj( obj );
537 return DeleteDC(obj);
538 case 0 :
539 WARN("Already deleted\n");
540 break;
541 default:
542 WARN("Unknown magic number (%d)\n",GDIMAGIC(header->wMagic));
544 GDI_ReleaseObj( obj );
545 return FALSE;
548 /***********************************************************************
549 * GetStockObject16 (GDI.87)
551 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
553 return (HGDIOBJ16)GetStockObject( obj );
557 /***********************************************************************
558 * GetStockObject (GDI32.220)
560 HGDIOBJ WINAPI GetStockObject( INT obj )
562 HGDIOBJ ret;
563 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
564 if (!StockObjects[obj]) return 0;
565 ret = (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
566 TRACE("returning %4x\n", ret );
567 return ret;
571 /***********************************************************************
572 * GetObject16 (GDI.82)
574 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
576 GDIOBJHDR * ptr;
577 INT16 result = 0;
578 TRACE("%04x %d %p\n", handle, count, buffer );
579 if (!count) return 0;
581 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
583 switch(GDIMAGIC(ptr->wMagic))
585 case PEN_MAGIC:
586 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
587 break;
588 case BRUSH_MAGIC:
589 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
590 break;
591 case BITMAP_MAGIC:
592 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
593 break;
594 case FONT_MAGIC:
595 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
598 * Fix the LOGFONT structure for the stock fonts
600 if ( (handle >= FIRST_STOCK_HANDLE) &&
601 (handle <= LAST_STOCK_HANDLE) )
602 FixStockFontSize16(handle, count, buffer);
603 break;
604 case PALETTE_MAGIC:
605 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
606 break;
608 GDI_ReleaseObj( handle );
609 return result;
613 /***********************************************************************
614 * GetObjectA (GDI32.204)
616 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
618 GDIOBJHDR * ptr;
619 INT result = 0;
620 TRACE("%08x %d %p\n", handle, count, buffer );
621 if (!count) return 0;
623 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
625 switch(GDIMAGIC(ptr->wMagic))
627 case PEN_MAGIC:
628 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
629 break;
630 case BRUSH_MAGIC:
631 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
632 break;
633 case BITMAP_MAGIC:
634 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
635 break;
636 case FONT_MAGIC:
637 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
640 * Fix the LOGFONT structure for the stock fonts
642 if ( (handle >= FIRST_STOCK_HANDLE) &&
643 (handle <= LAST_STOCK_HANDLE) )
644 FixStockFontSizeA(handle, count, buffer);
645 break;
646 case PALETTE_MAGIC:
647 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
648 break;
650 case REGION_MAGIC:
651 case DC_MAGIC:
652 case DISABLED_DC_MAGIC:
653 case META_DC_MAGIC:
654 case METAFILE_MAGIC:
655 case METAFILE_DC_MAGIC:
656 case ENHMETAFILE_MAGIC:
657 case ENHMETAFILE_DC_MAGIC:
658 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
659 break;
661 default:
662 ERR("Invalid GDI Magic %04x\n", GDIMAGIC(ptr->wMagic));
663 break;
665 GDI_ReleaseObj( handle );
666 return result;
669 /***********************************************************************
670 * GetObjectW (GDI32.206)
672 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
674 GDIOBJHDR * ptr;
675 INT result = 0;
676 TRACE("%08x %d %p\n", handle, count, buffer );
677 if (!count) return 0;
679 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
681 switch(GDIMAGIC(ptr->wMagic))
683 case PEN_MAGIC:
684 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
685 break;
686 case BRUSH_MAGIC:
687 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
688 break;
689 case BITMAP_MAGIC:
690 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
691 break;
692 case FONT_MAGIC:
693 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
696 * Fix the LOGFONT structure for the stock fonts
698 if ( (handle >= FIRST_STOCK_HANDLE) &&
699 (handle <= LAST_STOCK_HANDLE) )
700 FixStockFontSizeW(handle, count, buffer);
701 break;
702 case PALETTE_MAGIC:
703 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
704 break;
705 default:
706 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
707 break;
709 GDI_ReleaseObj( handle );
710 return result;
713 /***********************************************************************
714 * GetObjectType (GDI32.205)
716 DWORD WINAPI GetObjectType( HANDLE handle )
718 GDIOBJHDR * ptr;
719 INT result = 0;
720 TRACE("%08x\n", handle );
722 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
724 switch(GDIMAGIC(ptr->wMagic))
726 case PEN_MAGIC:
727 result = OBJ_PEN;
728 break;
729 case BRUSH_MAGIC:
730 result = OBJ_BRUSH;
731 break;
732 case BITMAP_MAGIC:
733 result = OBJ_BITMAP;
734 break;
735 case FONT_MAGIC:
736 result = OBJ_FONT;
737 break;
738 case PALETTE_MAGIC:
739 result = OBJ_PAL;
740 break;
741 case REGION_MAGIC:
742 result = OBJ_REGION;
743 break;
744 case DC_MAGIC:
745 result = OBJ_DC;
746 break;
747 case META_DC_MAGIC:
748 result = OBJ_METADC;
749 break;
750 case METAFILE_MAGIC:
751 result = OBJ_METAFILE;
752 break;
753 case METAFILE_DC_MAGIC:
754 result = OBJ_METADC;
755 break;
756 case ENHMETAFILE_MAGIC:
757 result = OBJ_ENHMETAFILE;
758 break;
759 case ENHMETAFILE_DC_MAGIC:
760 result = OBJ_ENHMETADC;
761 break;
762 default:
763 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
764 break;
766 GDI_ReleaseObj( handle );
767 return result;
770 /***********************************************************************
771 * GetCurrentObject (GDI32.166)
773 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
775 HANDLE ret = 0;
776 DC * dc = DC_GetDCPtr( hdc );
778 if (dc)
780 switch (type) {
781 case OBJ_PEN: ret = dc->w.hPen; break;
782 case OBJ_BRUSH: ret = dc->w.hBrush; break;
783 case OBJ_PAL: ret = dc->w.hPalette; break;
784 case OBJ_FONT: ret = dc->w.hFont; break;
785 case OBJ_BITMAP: ret = dc->w.hBitmap; break;
786 default:
787 /* the SDK only mentions those above */
788 FIXME("(%08x,%d): unknown type.\n",hdc,type);
789 break;
791 GDI_ReleaseObj( hdc );
793 return ret;
797 /***********************************************************************
798 * SelectObject16 (GDI.45)
800 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
802 return (HGDIOBJ16)SelectObject( hdc, handle );
806 /***********************************************************************
807 * SelectObject (GDI32.299)
809 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
811 HGDIOBJ ret = 0;
812 DC * dc = DC_GetDCUpdate( hdc );
813 if (!dc) return 0;
814 TRACE("hdc=%04x %04x\n", hdc, handle );
815 if (dc->funcs->pSelectObject)
816 ret = dc->funcs->pSelectObject( dc, handle );
817 GDI_ReleaseObj( hdc );
818 return ret;
822 /***********************************************************************
823 * UnrealizeObject16 (GDI.150)
825 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
827 return UnrealizeObject( obj );
831 /***********************************************************************
832 * UnrealizeObject (GDI32.358)
834 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
836 BOOL result = TRUE;
837 /* Check if object is valid */
839 GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
840 if (!header) return FALSE;
842 TRACE("%04x\n", obj );
844 /* Unrealize object */
846 switch(GDIMAGIC(header->wMagic))
848 case PALETTE_MAGIC:
849 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
850 break;
852 case BRUSH_MAGIC:
853 /* Windows resets the brush origin. We don't need to. */
854 break;
856 GDI_ReleaseObj( obj );
857 return result;
861 /***********************************************************************
862 * EnumObjects16 (GDI.71)
864 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
865 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
867 /* Solid colors to enumerate */
868 static const COLORREF solid_colors[] =
869 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
870 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
871 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
872 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
873 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
874 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
875 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
876 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
879 INT16 i, retval = 0;
880 LOGPEN16 *pen;
881 LOGBRUSH16 *brush = NULL;
883 TRACE("%04x %d %08lx %08lx\n",
884 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
885 switch(nObjType)
887 case OBJ_PEN:
888 /* Enumerate solid pens */
889 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
890 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
892 pen->lopnStyle = PS_SOLID;
893 pen->lopnWidth.x = 1;
894 pen->lopnWidth.y = 0;
895 pen->lopnColor = solid_colors[i];
896 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
897 TRACE("solid pen %08lx, ret=%d\n",
898 solid_colors[i], retval);
899 if (!retval) break;
901 SEGPTR_FREE(pen);
902 break;
904 case OBJ_BRUSH:
905 /* Enumerate solid brushes */
906 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
907 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
909 brush->lbStyle = BS_SOLID;
910 brush->lbColor = solid_colors[i];
911 brush->lbHatch = 0;
912 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
913 TRACE("solid brush %08lx, ret=%d\n",
914 solid_colors[i], retval);
915 if (!retval) break;
918 /* Now enumerate hatched brushes */
919 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
921 brush->lbStyle = BS_HATCHED;
922 brush->lbColor = RGB(0,0,0);
923 brush->lbHatch = i;
924 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
925 TRACE("hatched brush %d, ret=%d\n",
926 i, retval);
927 if (!retval) break;
929 SEGPTR_FREE(brush);
930 break;
932 default:
933 WARN("(%d): Invalid type\n", nObjType );
934 break;
936 return retval;
940 /***********************************************************************
941 * EnumObjects (GDI32.89)
943 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
944 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
946 /* Solid colors to enumerate */
947 static const COLORREF solid_colors[] =
948 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
949 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
950 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
951 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
952 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
953 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
954 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
955 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
958 INT i, retval = 0;
959 LOGPEN pen;
960 LOGBRUSH brush;
962 TRACE("%04x %d %08lx %08lx\n",
963 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
964 switch(nObjType)
966 case OBJ_PEN:
967 /* Enumerate solid pens */
968 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
970 pen.lopnStyle = PS_SOLID;
971 pen.lopnWidth.x = 1;
972 pen.lopnWidth.y = 0;
973 pen.lopnColor = solid_colors[i];
974 retval = lpEnumFunc( &pen, lParam );
975 TRACE("solid pen %08lx, ret=%d\n",
976 solid_colors[i], retval);
977 if (!retval) break;
979 break;
981 case OBJ_BRUSH:
982 /* Enumerate solid brushes */
983 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
985 brush.lbStyle = BS_SOLID;
986 brush.lbColor = solid_colors[i];
987 brush.lbHatch = 0;
988 retval = lpEnumFunc( &brush, lParam );
989 TRACE("solid brush %08lx, ret=%d\n",
990 solid_colors[i], retval);
991 if (!retval) break;
994 /* Now enumerate hatched brushes */
995 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
997 brush.lbStyle = BS_HATCHED;
998 brush.lbColor = RGB(0,0,0);
999 brush.lbHatch = i;
1000 retval = lpEnumFunc( &brush, lParam );
1001 TRACE("hatched brush %d, ret=%d\n",
1002 i, retval);
1003 if (!retval) break;
1005 break;
1007 default:
1008 /* FIXME: implement Win32 types */
1009 WARN("(%d): Invalid type\n", nObjType );
1010 break;
1012 return retval;
1016 /***********************************************************************
1017 * IsGDIObject (GDI.462)
1019 * returns type of object if valid (W95 system programming secrets p. 264-5)
1021 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
1023 UINT16 magic = 0;
1025 GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1026 if (object)
1028 magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1029 GDI_ReleaseObj( handle );
1031 return magic;
1035 /***********************************************************************
1036 * SetObjectOwner16 (GDI.461)
1038 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1040 /* Nothing to do */
1044 /***********************************************************************
1045 * SetObjectOwner (GDI32.386)
1047 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1049 /* Nothing to do */
1053 /***********************************************************************
1054 * MakeObjectPrivate (GDI.463)
1056 * What does that mean ?
1057 * Some little docu can be found in "Undocumented Windows",
1058 * but this is basically useless.
1059 * At least we know that this flags the GDI object's wMagic
1060 * with 0x2000 (OBJECT_PRIVATE), so we just do it.
1061 * But Wine doesn't react on that yet.
1063 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1065 GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1066 if (!ptr)
1068 ERR("invalid GDI object %04x !\n", handle);
1069 return;
1071 ptr->wMagic |= OBJECT_PRIVATE;
1072 GDI_ReleaseObj( handle );
1076 /***********************************************************************
1077 * GdiFlush (GDI32.128)
1079 BOOL WINAPI GdiFlush(void)
1081 return TRUE; /* FIXME */
1085 /***********************************************************************
1086 * GdiGetBatchLimit (GDI32.129)
1088 DWORD WINAPI GdiGetBatchLimit(void)
1090 return 1; /* FIXME */
1094 /***********************************************************************
1095 * GdiSetBatchLimit (GDI32.139)
1097 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1099 return 1; /* FIXME */
1103 /***********************************************************************
1104 * GdiSeeGdiDo (GDI.452)
1106 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1107 WORD wParam3 )
1109 switch (wReqType)
1111 case 0x0001: /* LocalAlloc */
1112 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1113 case 0x0002: /* LocalFree */
1114 return LOCAL_Free( GDI_HeapSel, wParam1 );
1115 case 0x0003: /* LocalCompact */
1116 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1117 case 0x0103: /* LocalHeap */
1118 return GDI_HeapSel;
1119 default:
1120 WARN("(wReqType=%04x): Unknown\n", wReqType);
1121 return (DWORD)-1;
1125 /***********************************************************************
1126 * GdiSignalProc (GDI.610)
1128 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1129 DWORD dwFlags, HMODULE16 hModule )
1131 return 0;
1134 /***********************************************************************
1135 * FinalGdiInit16 (GDI.405)
1137 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1141 /***********************************************************************
1142 * GdiFreeResources (GDI.609)
1144 WORD WINAPI GdiFreeResources16( DWORD reserve )
1146 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1147 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1150 /***********************************************************************
1151 * MulDiv16 (GDI.128)
1153 INT16 WINAPI MulDiv16(
1154 INT16 nMultiplicand,
1155 INT16 nMultiplier,
1156 INT16 nDivisor)
1158 INT ret;
1159 if (!nDivisor) return -32768;
1160 /* We want to deal with a positive divisor to simplify the logic. */
1161 if (nDivisor < 0)
1163 nMultiplicand = - nMultiplicand;
1164 nDivisor = -nDivisor;
1166 /* If the result is positive, we "add" to round. else,
1167 * we subtract to round. */
1168 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1169 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1170 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1171 else
1172 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1173 if ((ret > 32767) || (ret < -32767)) return -32768;
1174 return (INT16) ret;
1178 /*******************************************************************
1179 * GetColorAdjustment [GDI32.164]
1183 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1185 FIXME("GetColorAdjustment, stub\n");
1186 return 0;
1189 /*******************************************************************
1190 * GetMiterLimit [GDI32.201]
1194 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1196 FIXME("GetMiterLimit, stub\n");
1197 return 0;
1200 /*******************************************************************
1201 * SetMiterLimit [GDI32.325]
1205 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1207 FIXME("SetMiterLimit, stub\n");
1208 return 0;
1211 /*******************************************************************
1212 * GdiComment [GDI32.109]
1216 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1218 FIXME("GdiComment, stub\n");
1219 return 0;
1221 /*******************************************************************
1222 * SetColorAdjustment [GDI32.309]
1226 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1228 FIXME("SetColorAdjustment, stub\n");
1229 return 0;