4 * Copyright 1993 Alexandre Julliard
16 #include "wine/winbase16.h"
27 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(gdi);
34 /**********************************************************************/
36 GDI_DRIVER *GDI_Driver = NULL;
38 /***********************************************************************
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,
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,
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
206 *****************************************************************************/
208 static void ReadFontInformation(
209 char const *fontName,
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)) ?
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);
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)
258 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
260 hOldFont = (HFONT)SelectObject(hdc, handle);
262 GetTextMetricsA(hdc, lptm);
264 SelectObject(hdc, hOldFont);
269 static inline void FixStockFontSize16(
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(
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 /***********************************************************************
326 * GDI initialization.
330 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
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 );
370 /***********************************************************************
373 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
375 static DWORD count = 0;
378 _EnterSysLevel( &GDI_level );
379 if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size )))
381 _LeaveSysLevel( &GDI_level );
384 obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
386 obj->wMagic = magic|OBJECT_NOSYSTEM;
387 obj->dwCount = ++count;
389 TRACE_SEC( *handle, "enter" );
394 /***********************************************************************
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 )
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 );
411 assert( new_handle == handle ); /* moveable handle cannot change */
412 return LOCAL_Lock( GDI_HeapSel, handle );
416 /***********************************************************************
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 );
436 /***********************************************************************
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;
457 ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
459 (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic))
461 LOCAL_Unlock( GDI_HeapSel, handle );
468 _LeaveSysLevel( &GDI_level );
469 SetLastError( ERROR_INVALID_HANDLE );
471 else TRACE_SEC( handle, "enter" );
477 /***********************************************************************
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 */
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 */
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 );
523 TRACE("%04x\n", obj );
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 );
536 GDI_ReleaseObj( obj );
537 return DeleteDC(obj);
539 WARN("Already deleted\n");
542 WARN("Unknown magic number (%d)\n",GDIMAGIC(header->wMagic));
544 GDI_ReleaseObj( obj );
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 )
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 );
571 /***********************************************************************
572 * GetObject16 (GDI.82)
574 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
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))
586 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
589 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
592 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
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);
605 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
608 GDI_ReleaseObj( handle );
613 /***********************************************************************
614 * GetObjectA (GDI32.204)
616 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
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))
628 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
631 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
634 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
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);
647 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
652 case DISABLED_DC_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) );
662 ERR("Invalid GDI Magic %04x\n", GDIMAGIC(ptr->wMagic));
665 GDI_ReleaseObj( handle );
669 /***********************************************************************
670 * GetObjectW (GDI32.206)
672 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
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))
684 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
687 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
690 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
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);
703 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
706 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
709 GDI_ReleaseObj( handle );
713 /***********************************************************************
714 * GetObjectType (GDI32.205)
716 DWORD WINAPI GetObjectType( HANDLE handle )
720 TRACE("%08x\n", handle );
722 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
724 switch(GDIMAGIC(ptr->wMagic))
751 result = OBJ_METAFILE;
753 case METAFILE_DC_MAGIC:
756 case ENHMETAFILE_MAGIC:
757 result = OBJ_ENHMETAFILE;
759 case ENHMETAFILE_DC_MAGIC:
760 result = OBJ_ENHMETADC;
763 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
766 GDI_ReleaseObj( handle );
770 /***********************************************************************
771 * GetCurrentObject (GDI32.166)
773 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
776 DC * dc = DC_GetDCPtr( hdc );
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;
787 /* the SDK only mentions those above */
788 FIXME("(%08x,%d): unknown type.\n",hdc,type);
791 GDI_ReleaseObj( hdc );
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 )
812 DC * dc = DC_GetDCUpdate( hdc );
814 TRACE("hdc=%04x %04x\n", hdc, handle );
815 if (dc->funcs->pSelectObject)
816 ret = dc->funcs->pSelectObject( dc, handle );
817 GDI_ReleaseObj( hdc );
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 )
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))
849 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
853 /* Windows resets the brush origin. We don't need to. */
856 GDI_ReleaseObj( obj );
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)
881 LOGBRUSH16 *brush = NULL;
883 TRACE("%04x %d %08lx %08lx\n",
884 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
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);
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];
912 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
913 TRACE("solid brush %08lx, ret=%d\n",
914 solid_colors[i], retval);
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);
924 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
925 TRACE("hatched brush %d, ret=%d\n",
933 WARN("(%d): Invalid type\n", nObjType );
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)
962 TRACE("%04x %d %08lx %08lx\n",
963 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
967 /* Enumerate solid pens */
968 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
970 pen.lopnStyle = PS_SOLID;
973 pen.lopnColor = solid_colors[i];
974 retval = lpEnumFunc( &pen, lParam );
975 TRACE("solid pen %08lx, ret=%d\n",
976 solid_colors[i], retval);
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];
988 retval = lpEnumFunc( &brush, lParam );
989 TRACE("solid brush %08lx, ret=%d\n",
990 solid_colors[i], retval);
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);
1000 retval = lpEnumFunc( &brush, lParam );
1001 TRACE("hatched brush %d, ret=%d\n",
1008 /* FIXME: implement Win32 types */
1009 WARN("(%d): Invalid type\n", nObjType );
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 )
1025 GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1028 magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1029 GDI_ReleaseObj( handle );
1035 /***********************************************************************
1036 * SetObjectOwner16 (GDI.461)
1038 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1044 /***********************************************************************
1045 * SetObjectOwner (GDI32.386)
1047 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
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 );
1068 ERR("invalid GDI object %04x !\n", handle);
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,
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 */
1120 WARN("(wReqType=%04x): Unknown\n", wReqType);
1125 /***********************************************************************
1126 * GdiSignalProc (GDI.610)
1128 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1129 DWORD dwFlags, HMODULE16 hModule )
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,
1159 if (!nDivisor) return -32768;
1160 /* We want to deal with a positive divisor to simplify the logic. */
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;
1172 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1173 if ((ret > 32767) || (ret < -32767)) return -32768;
1178 /*******************************************************************
1179 * GetColorAdjustment [GDI32.164]
1183 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1185 FIXME("GetColorAdjustment, stub\n");
1189 /*******************************************************************
1190 * GetMiterLimit [GDI32.201]
1194 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1196 FIXME("GetMiterLimit, stub\n");
1200 /*******************************************************************
1201 * SetMiterLimit [GDI32.325]
1205 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1207 FIXME("SetMiterLimit, stub\n");
1211 /*******************************************************************
1212 * GdiComment [GDI32.109]
1216 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1218 FIXME("GdiComment, stub\n");
1221 /*******************************************************************
1222 * SetColorAdjustment [GDI32.309]
1226 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1228 FIXME("SetColorAdjustment, stub\n");