Include config.h.
[wine/gsoc_dplay.git] / objects / gdiobj.c
blobf84ad5f39c3571dfaec276a093cbc03ec8b850fb
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 "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"
30 DEFAULT_DEBUG_CHANNEL(gdi);
33 /***********************************************************************
34 * GDI stock objects
37 static BRUSHOBJ WhiteBrush =
39 { 0, BRUSH_MAGIC, 1 }, /* header */
40 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
43 static BRUSHOBJ LtGrayBrush =
45 { 0, BRUSH_MAGIC, 1 }, /* header */
46 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
47 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
50 static BRUSHOBJ GrayBrush =
52 { 0, BRUSH_MAGIC, 1 }, /* header */
53 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
54 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
57 static BRUSHOBJ DkGrayBrush =
59 { 0, BRUSH_MAGIC, 1 }, /* header */
60 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
61 /* NB_HATCH_STYLES is an index into HatchBrushes */
62 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
65 static BRUSHOBJ BlackBrush =
67 { 0, BRUSH_MAGIC, 1 }, /* header */
68 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
71 static BRUSHOBJ NullBrush =
73 { 0, BRUSH_MAGIC, 1 }, /* header */
74 { BS_NULL, 0, 0 } /* logbrush */
77 static PENOBJ WhitePen =
79 { 0, PEN_MAGIC, 1 }, /* header */
80 { PS_SOLID, { 0, 0 }, RGB(255,255,255) } /* logpen */
83 static PENOBJ BlackPen =
85 { 0, PEN_MAGIC, 1 }, /* header */
86 { PS_SOLID, { 0, 0 }, RGB(0,0,0) } /* logpen */
89 static PENOBJ NullPen =
91 { 0, PEN_MAGIC, 1 }, /* header */
92 { PS_NULL, { 0, 0 }, 0 } /* logpen */
95 static FONTOBJ OEMFixedFont =
97 { 0, FONT_MAGIC, 1 }, /* header */
98 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
99 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
101 /* Filler to make the location counter dword aligned again. This is necessary
102 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
103 segment, and (c) Solaris assembler is stupid. */
104 static UINT16 align_OEMFixedFont = 1;
106 static FONTOBJ AnsiFixedFont =
108 { 0, FONT_MAGIC, 1 }, /* header */
109 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
110 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
112 static UINT16 align_AnsiFixedFont = 1;
114 static FONTOBJ AnsiVarFont =
116 { 0, FONT_MAGIC, 1 }, /* header */
117 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
118 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
120 static UINT16 align_AnsiVarFont = 1;
122 static FONTOBJ SystemFont =
124 { 0, FONT_MAGIC, 1 },
125 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
126 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
128 static UINT16 align_SystemFont = 1;
130 static FONTOBJ DeviceDefaultFont =
132 { 0, FONT_MAGIC, 1 }, /* header */
133 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
134 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
136 static UINT16 align_DeviceDefaultFont = 1;
138 static FONTOBJ SystemFixedFont =
140 { 0, FONT_MAGIC, 1 }, /* header */
141 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
142 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
144 static UINT16 align_SystemFixedFont = 1;
146 /* FIXME: Is this correct? */
147 static FONTOBJ DefaultGuiFont =
149 { 0, FONT_MAGIC, 1 }, /* header */
150 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
151 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
153 static UINT16 align_DefaultGuiFont = 1;
156 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
158 (GDIOBJHDR *) &WhiteBrush,
159 (GDIOBJHDR *) &LtGrayBrush,
160 (GDIOBJHDR *) &GrayBrush,
161 (GDIOBJHDR *) &DkGrayBrush,
162 (GDIOBJHDR *) &BlackBrush,
163 (GDIOBJHDR *) &NullBrush,
164 (GDIOBJHDR *) &WhitePen,
165 (GDIOBJHDR *) &BlackPen,
166 (GDIOBJHDR *) &NullPen,
167 NULL,
168 (GDIOBJHDR *) &OEMFixedFont,
169 (GDIOBJHDR *) &AnsiFixedFont,
170 (GDIOBJHDR *) &AnsiVarFont,
171 (GDIOBJHDR *) &SystemFont,
172 (GDIOBJHDR *) &DeviceDefaultFont,
173 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
174 (GDIOBJHDR *) &SystemFixedFont,
175 (GDIOBJHDR *) &DefaultGuiFont
178 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
180 static SYSLEVEL GDI_level = { CRITICAL_SECTION_INIT, 3 };
181 static WORD GDI_HeapSel;
184 /******************************************************************************
186 * void ReadFontInformation(
187 * char const *fontName,
188 * FONTOBJ *font,
189 * int defHeight,
190 * int defBold,
191 * int defItalic,
192 * int defUnderline,
193 * int defStrikeOut )
195 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
196 * section for entries containing fontName.Height, fontName.Bold, etc.,
197 * where fontName is the name specified in the call (e.g., "System"). It
198 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
199 * the first character in the boolean attributes (bold, italic, and
200 * underline).
201 *****************************************************************************/
203 static void ReadFontInformation(
204 char const *fontName,
205 FONTOBJ *font,
206 int defHeight,
207 int defBold,
208 int defItalic,
209 int defUnderline,
210 int defStrikeOut )
212 char key[256];
214 /* In order for the stock fonts to be independent of
215 * mapping mode, the height (& width) must be 0
217 sprintf(key, "%s.Height", fontName);
218 font->logfont.lfHeight =
219 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
221 sprintf(key, "%s.Bold", fontName);
222 font->logfont.lfWeight =
223 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
224 FW_BOLD : FW_NORMAL;
226 sprintf(key, "%s.Italic", fontName);
227 font->logfont.lfItalic =
228 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
230 sprintf(key, "%s.Underline", fontName);
231 font->logfont.lfUnderline =
232 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
234 sprintf(key, "%s.StrikeOut", fontName);
235 font->logfont.lfStrikeOut =
236 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
238 return;
241 /***********************************************************************
242 * Because the stock fonts have their structure initialized with
243 * a height of 0 to keep them independent of mapping mode, simply
244 * returning the LOGFONT as is will not work correctly.
245 * These "FixStockFontSizeXXX()" methods will get the correct
246 * size for the fonts.
248 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
250 HDC hdc;
251 HFONT hOldFont;
253 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
255 hOldFont = (HFONT)SelectObject(hdc, handle);
257 GetTextMetricsA(hdc, lptm);
259 SelectObject(hdc, hOldFont);
261 DeleteDC(hdc);
264 static inline void FixStockFontSize16(
265 HFONT handle,
266 INT16 count,
267 LPVOID buffer)
269 TEXTMETRICA tm;
270 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
273 * Was the lfHeight field copied (it's the first field)?
274 * If it was and it was null, replace the height.
276 if ( (count >= 2*sizeof(INT16)) &&
277 (pLogFont->lfHeight == 0) )
279 GetFontMetrics(handle, &tm);
281 pLogFont->lfHeight = tm.tmHeight;
282 pLogFont->lfWidth = tm.tmAveCharWidth;
286 static inline void FixStockFontSizeA(
287 HFONT handle,
288 INT count,
289 LPVOID buffer)
291 TEXTMETRICA tm;
292 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
295 * Was the lfHeight field copied (it's the first field)?
296 * If it was and it was null, replace the height.
298 if ( (count >= 2*sizeof(INT)) &&
299 (pLogFont->lfHeight == 0) )
301 GetFontMetrics(handle, &tm);
303 pLogFont->lfHeight = tm.tmHeight;
304 pLogFont->lfWidth = tm.tmAveCharWidth;
309 * Since the LOGFONTA and LOGFONTW structures are identical up to the
310 * lfHeight member (the one of interest in this case) we simply define
311 * the W version as the A version.
313 #define FixStockFontSizeW FixStockFontSizeA
315 #define TRACE_SEC(handle,text) \
316 TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
318 /***********************************************************************
319 * GDI_Init
321 * GDI initialization.
323 BOOL GDI_Init(void)
325 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
326 HPALETTE16 hpalette;
327 HINSTANCE16 instance;
329 /* create GDI heap */
330 if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
331 GDI_HeapSel = GlobalHandleToSel16( instance );
333 /* Kill some warnings. */
334 (void)align_OEMFixedFont;
335 (void)align_AnsiFixedFont;
336 (void)align_AnsiVarFont;
337 (void)align_SystemFont;
338 (void)align_DeviceDefaultFont;
339 (void)align_SystemFixedFont;
340 (void)align_DefaultGuiFont;
342 /* TWEAK: Initialize font hints */
343 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
344 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
345 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
346 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
347 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
348 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
349 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
351 /* Create default palette */
353 /* DR well *this* palette can't be moveable (?) */
354 hpalette = PALETTE_Init();
355 if( !hpalette ) return FALSE;
356 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hpalette );
358 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
359 return TRUE;
362 #define FIRST_LARGE_HANDLE 16
363 #define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
364 static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
365 static int next_large_handle;
367 /***********************************************************************
368 * alloc_large_heap
370 * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
372 inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
374 int i;
375 GDIOBJHDR *obj;
377 for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
378 if (!large_handles[i]) goto found;
379 for (i = 0; i <= next_large_handle; i++)
380 if (!large_handles[i]) goto found;
381 *handle = 0;
382 return NULL;
384 found:
385 if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
387 large_handles[i] = obj;
388 *handle = (i + FIRST_LARGE_HANDLE) << 2;
389 next_large_handle = i;
391 return obj;
395 /***********************************************************************
396 * GDI_AllocObject
398 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
400 static DWORD count = 0;
401 GDIOBJHDR *obj;
403 _EnterSysLevel( &GDI_level );
404 switch(magic)
406 /* allocate DCs on the larger heap */
407 case DC_MAGIC:
408 case DISABLED_DC_MAGIC:
409 case META_DC_MAGIC:
410 case METAFILE_MAGIC:
411 case METAFILE_DC_MAGIC:
412 case ENHMETAFILE_MAGIC:
413 case ENHMETAFILE_DC_MAGIC:
414 if (!(obj = alloc_large_heap( size, handle ))) goto error;
415 break;
416 default:
417 if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
418 assert( *handle & 2 );
419 obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
420 break;
423 obj->hNext = 0;
424 obj->wMagic = magic|OBJECT_NOSYSTEM;
425 obj->dwCount = ++count;
427 TRACE_SEC( *handle, "enter" );
428 return obj;
430 error:
431 _LeaveSysLevel( &GDI_level );
432 *handle = 0;
433 return NULL;
437 /***********************************************************************
438 * GDI_ReallocObject
440 * The object ptr must have been obtained with GDI_GetObjPtr.
441 * The new pointer must be released with GDI_ReleaseObj.
443 void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
445 HGDIOBJ new_handle;
447 assert( handle & 2 ); /* no realloc for large handles */
448 LOCAL_Unlock( GDI_HeapSel, handle );
449 if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
451 TRACE_SEC( handle, "leave" );
452 _LeaveSysLevel( &GDI_level );
453 return NULL;
455 assert( new_handle == handle ); /* moveable handle cannot change */
456 return LOCAL_Lock( GDI_HeapSel, handle );
460 /***********************************************************************
461 * GDI_FreeObject
463 BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
465 GDIOBJHDR *object = ptr;
467 /* can't free stock objects */
468 if (handle < FIRST_STOCK_HANDLE)
470 object->wMagic = 0; /* Mark it as invalid */
471 if (handle & 2) /* GDI heap handle */
473 LOCAL_Unlock( GDI_HeapSel, handle );
474 LOCAL_Free( GDI_HeapSel, handle );
476 else /* large heap handle */
478 int i = (handle >> 2) - FIRST_LARGE_HANDLE;
479 if (i >= 0 && large_handles[i])
481 HeapFree( GetProcessHeap(), 0, large_handles[i] );
482 large_handles[i] = NULL;
486 TRACE_SEC( handle, "leave" );
487 _LeaveSysLevel( &GDI_level );
488 return TRUE;
492 /***********************************************************************
493 * GDI_GetObjPtr
495 * Return a pointer to the GDI object associated to the handle.
496 * Return NULL if the object has the wrong magic number.
497 * The object must be released with GDI_ReleaseObj.
499 void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
501 GDIOBJHDR *ptr = NULL;
503 _EnterSysLevel( &GDI_level );
505 if (handle >= FIRST_STOCK_HANDLE)
507 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
508 if (ptr && (magic != MAGIC_DONTCARE)
509 && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
511 else if (handle & 2) /* GDI heap handle */
513 ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
514 if (ptr &&
515 (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic))
517 LOCAL_Unlock( GDI_HeapSel, handle );
518 ptr = NULL;
521 else /* large heap handle */
523 int i = (handle >> 2) - FIRST_LARGE_HANDLE;
524 if (i >= 0)
526 ptr = large_handles[i];
527 if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
531 if (!ptr)
533 _LeaveSysLevel( &GDI_level );
534 SetLastError( ERROR_INVALID_HANDLE );
536 else TRACE_SEC( handle, "enter" );
538 return ptr;
542 /***********************************************************************
543 * GDI_ReleaseObj
546 void GDI_ReleaseObj( HGDIOBJ handle )
548 if (handle < FIRST_STOCK_HANDLE && (handle & 2)) LOCAL_Unlock( GDI_HeapSel, handle );
549 TRACE_SEC( handle, "leave" );
550 _LeaveSysLevel( &GDI_level );
554 /***********************************************************************
555 * DeleteObject16 (GDI.69)
557 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
559 return DeleteObject( obj );
563 /***********************************************************************
564 * DeleteObject (GDI32.70)
566 BOOL WINAPI DeleteObject( HGDIOBJ obj )
568 /* Check if object is valid */
570 GDIOBJHDR * header;
571 if (HIWORD(obj)) return FALSE;
572 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE)) {
573 TRACE("Preserving Stock object %04x\n", obj );
574 /* NOTE: No GDI_Release is necessary */
575 return TRUE;
577 if (obj == hPseudoStockBitmap) return TRUE;
578 if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
580 if (!(header->wMagic & OBJECT_NOSYSTEM)
581 && (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
583 TRACE("Preserving system object %04x\n", obj);
584 GDI_ReleaseObj( obj );
585 return TRUE;
588 TRACE("%04x\n", obj );
590 /* Delete object */
592 switch(GDIMAGIC(header->wMagic))
594 case PEN_MAGIC: return GDI_FreeObject( obj, header );
595 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
596 case FONT_MAGIC: return GDI_FreeObject( obj, header );
597 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
598 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
599 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
600 case DC_MAGIC:
601 GDI_ReleaseObj( obj );
602 return DeleteDC(obj);
603 case 0 :
604 WARN("Already deleted\n");
605 break;
606 default:
607 WARN("Unknown magic number (%d)\n",GDIMAGIC(header->wMagic));
609 GDI_ReleaseObj( obj );
610 return FALSE;
613 /***********************************************************************
614 * GetStockObject16 (GDI.87)
616 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
618 return (HGDIOBJ16)GetStockObject( obj );
622 /***********************************************************************
623 * GetStockObject (GDI32.220)
625 HGDIOBJ WINAPI GetStockObject( INT obj )
627 HGDIOBJ ret;
628 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
629 if (!StockObjects[obj]) return 0;
630 ret = (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
631 TRACE("returning %4x\n", ret );
632 return ret;
636 /***********************************************************************
637 * GetObject16 (GDI.82)
639 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
641 GDIOBJHDR * ptr;
642 INT16 result = 0;
643 TRACE("%04x %d %p\n", handle, count, buffer );
644 if (!count) return 0;
646 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
648 switch(GDIMAGIC(ptr->wMagic))
650 case PEN_MAGIC:
651 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
652 break;
653 case BRUSH_MAGIC:
654 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
655 break;
656 case BITMAP_MAGIC:
657 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
658 break;
659 case FONT_MAGIC:
660 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
663 * Fix the LOGFONT structure for the stock fonts
665 if ( (handle >= FIRST_STOCK_HANDLE) &&
666 (handle <= LAST_STOCK_HANDLE) )
667 FixStockFontSize16(handle, count, buffer);
668 break;
669 case PALETTE_MAGIC:
670 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
671 break;
673 GDI_ReleaseObj( handle );
674 return result;
678 /***********************************************************************
679 * GetObjectA (GDI32.204)
681 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
683 GDIOBJHDR * ptr;
684 INT result = 0;
685 TRACE("%08x %d %p\n", handle, count, buffer );
686 if (!count) return 0;
688 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
690 switch(GDIMAGIC(ptr->wMagic))
692 case PEN_MAGIC:
693 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
694 break;
695 case BRUSH_MAGIC:
696 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
697 break;
698 case BITMAP_MAGIC:
699 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
700 break;
701 case FONT_MAGIC:
702 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
705 * Fix the LOGFONT structure for the stock fonts
707 if ( (handle >= FIRST_STOCK_HANDLE) &&
708 (handle <= LAST_STOCK_HANDLE) )
709 FixStockFontSizeA(handle, count, buffer);
710 break;
711 case PALETTE_MAGIC:
712 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
713 break;
715 case REGION_MAGIC:
716 case DC_MAGIC:
717 case DISABLED_DC_MAGIC:
718 case META_DC_MAGIC:
719 case METAFILE_MAGIC:
720 case METAFILE_DC_MAGIC:
721 case ENHMETAFILE_MAGIC:
722 case ENHMETAFILE_DC_MAGIC:
723 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
724 break;
726 default:
727 ERR("Invalid GDI Magic %04x\n", GDIMAGIC(ptr->wMagic));
728 break;
730 GDI_ReleaseObj( handle );
731 return result;
734 /***********************************************************************
735 * GetObjectW (GDI32.206)
737 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
739 GDIOBJHDR * ptr;
740 INT result = 0;
741 TRACE("%08x %d %p\n", handle, count, buffer );
742 if (!count) return 0;
744 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
746 switch(GDIMAGIC(ptr->wMagic))
748 case PEN_MAGIC:
749 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
750 break;
751 case BRUSH_MAGIC:
752 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
753 break;
754 case BITMAP_MAGIC:
755 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
756 break;
757 case FONT_MAGIC:
758 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
761 * Fix the LOGFONT structure for the stock fonts
763 if ( (handle >= FIRST_STOCK_HANDLE) &&
764 (handle <= LAST_STOCK_HANDLE) )
765 FixStockFontSizeW(handle, count, buffer);
766 break;
767 case PALETTE_MAGIC:
768 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
769 break;
770 default:
771 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
772 break;
774 GDI_ReleaseObj( handle );
775 return result;
778 /***********************************************************************
779 * GetObjectType (GDI32.205)
781 DWORD WINAPI GetObjectType( HANDLE handle )
783 GDIOBJHDR * ptr;
784 INT result = 0;
785 TRACE("%08x\n", handle );
787 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
789 switch(GDIMAGIC(ptr->wMagic))
791 case PEN_MAGIC:
792 result = OBJ_PEN;
793 break;
794 case BRUSH_MAGIC:
795 result = OBJ_BRUSH;
796 break;
797 case BITMAP_MAGIC:
798 result = OBJ_BITMAP;
799 break;
800 case FONT_MAGIC:
801 result = OBJ_FONT;
802 break;
803 case PALETTE_MAGIC:
804 result = OBJ_PAL;
805 break;
806 case REGION_MAGIC:
807 result = OBJ_REGION;
808 break;
809 case DC_MAGIC:
810 result = OBJ_DC;
811 break;
812 case META_DC_MAGIC:
813 result = OBJ_METADC;
814 break;
815 case METAFILE_MAGIC:
816 result = OBJ_METAFILE;
817 break;
818 case METAFILE_DC_MAGIC:
819 result = OBJ_METADC;
820 break;
821 case ENHMETAFILE_MAGIC:
822 result = OBJ_ENHMETAFILE;
823 break;
824 case ENHMETAFILE_DC_MAGIC:
825 result = OBJ_ENHMETADC;
826 break;
827 default:
828 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
829 break;
831 GDI_ReleaseObj( handle );
832 return result;
835 /***********************************************************************
836 * GetCurrentObject (GDI32.166)
838 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
840 HANDLE ret = 0;
841 DC * dc = DC_GetDCPtr( hdc );
843 if (dc)
845 switch (type) {
846 case OBJ_PEN: ret = dc->hPen; break;
847 case OBJ_BRUSH: ret = dc->hBrush; break;
848 case OBJ_PAL: ret = dc->hPalette; break;
849 case OBJ_FONT: ret = dc->hFont; break;
850 case OBJ_BITMAP: ret = dc->hBitmap; break;
851 default:
852 /* the SDK only mentions those above */
853 FIXME("(%08x,%d): unknown type.\n",hdc,type);
854 break;
856 GDI_ReleaseObj( hdc );
858 return ret;
862 /***********************************************************************
863 * SelectObject16 (GDI.45)
865 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
867 return (HGDIOBJ16)SelectObject( hdc, handle );
871 /***********************************************************************
872 * SelectObject (GDI32.299)
874 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
876 HGDIOBJ ret = 0;
877 DC * dc = DC_GetDCUpdate( hdc );
878 if (!dc) return 0;
879 TRACE("hdc=%04x %04x\n", hdc, handle );
880 if (dc->funcs->pSelectObject)
881 ret = dc->funcs->pSelectObject( dc, handle );
882 GDI_ReleaseObj( hdc );
883 return ret;
887 /***********************************************************************
888 * UnrealizeObject16 (GDI.150)
890 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
892 return UnrealizeObject( obj );
896 /***********************************************************************
897 * UnrealizeObject (GDI32.358)
899 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
901 BOOL result = TRUE;
902 /* Check if object is valid */
904 GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
905 if (!header) return FALSE;
907 TRACE("%04x\n", obj );
909 /* Unrealize object */
911 switch(GDIMAGIC(header->wMagic))
913 case PALETTE_MAGIC:
914 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
915 break;
917 case BRUSH_MAGIC:
918 /* Windows resets the brush origin. We don't need to. */
919 break;
921 GDI_ReleaseObj( obj );
922 return result;
926 /***********************************************************************
927 * EnumObjects16 (GDI.71)
929 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
930 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
932 /* Solid colors to enumerate */
933 static const COLORREF solid_colors[] =
934 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
935 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
936 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
937 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
938 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
939 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
940 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
941 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
944 INT16 i, retval = 0;
945 LOGPEN16 *pen;
946 LOGBRUSH16 *brush = NULL;
948 TRACE("%04x %d %08lx %08lx\n",
949 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
950 switch(nObjType)
952 case OBJ_PEN:
953 /* Enumerate solid pens */
954 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
955 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
957 pen->lopnStyle = PS_SOLID;
958 pen->lopnWidth.x = 1;
959 pen->lopnWidth.y = 0;
960 pen->lopnColor = solid_colors[i];
961 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
962 TRACE("solid pen %08lx, ret=%d\n",
963 solid_colors[i], retval);
964 if (!retval) break;
966 SEGPTR_FREE(pen);
967 break;
969 case OBJ_BRUSH:
970 /* Enumerate solid brushes */
971 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
972 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
974 brush->lbStyle = BS_SOLID;
975 brush->lbColor = solid_colors[i];
976 brush->lbHatch = 0;
977 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
978 TRACE("solid brush %08lx, ret=%d\n",
979 solid_colors[i], retval);
980 if (!retval) break;
983 /* Now enumerate hatched brushes */
984 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
986 brush->lbStyle = BS_HATCHED;
987 brush->lbColor = RGB(0,0,0);
988 brush->lbHatch = i;
989 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
990 TRACE("hatched brush %d, ret=%d\n",
991 i, retval);
992 if (!retval) break;
994 SEGPTR_FREE(brush);
995 break;
997 default:
998 WARN("(%d): Invalid type\n", nObjType );
999 break;
1001 return retval;
1005 /***********************************************************************
1006 * EnumObjects (GDI32.89)
1008 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
1009 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
1011 /* Solid colors to enumerate */
1012 static const COLORREF solid_colors[] =
1013 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1014 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1015 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1016 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1017 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1018 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1019 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1020 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1023 INT i, retval = 0;
1024 LOGPEN pen;
1025 LOGBRUSH brush;
1027 TRACE("%04x %d %08lx %08lx\n",
1028 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
1029 switch(nObjType)
1031 case OBJ_PEN:
1032 /* Enumerate solid pens */
1033 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1035 pen.lopnStyle = PS_SOLID;
1036 pen.lopnWidth.x = 1;
1037 pen.lopnWidth.y = 0;
1038 pen.lopnColor = solid_colors[i];
1039 retval = lpEnumFunc( &pen, lParam );
1040 TRACE("solid pen %08lx, ret=%d\n",
1041 solid_colors[i], retval);
1042 if (!retval) break;
1044 break;
1046 case OBJ_BRUSH:
1047 /* Enumerate solid brushes */
1048 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1050 brush.lbStyle = BS_SOLID;
1051 brush.lbColor = solid_colors[i];
1052 brush.lbHatch = 0;
1053 retval = lpEnumFunc( &brush, lParam );
1054 TRACE("solid brush %08lx, ret=%d\n",
1055 solid_colors[i], retval);
1056 if (!retval) break;
1059 /* Now enumerate hatched brushes */
1060 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1062 brush.lbStyle = BS_HATCHED;
1063 brush.lbColor = RGB(0,0,0);
1064 brush.lbHatch = i;
1065 retval = lpEnumFunc( &brush, lParam );
1066 TRACE("hatched brush %d, ret=%d\n",
1067 i, retval);
1068 if (!retval) break;
1070 break;
1072 default:
1073 /* FIXME: implement Win32 types */
1074 WARN("(%d): Invalid type\n", nObjType );
1075 break;
1077 return retval;
1081 /***********************************************************************
1082 * IsGDIObject (GDI.462)
1084 * returns type of object if valid (W95 system programming secrets p. 264-5)
1086 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
1088 UINT16 magic = 0;
1090 GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1091 if (object)
1093 magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1094 GDI_ReleaseObj( handle );
1096 return magic;
1100 /***********************************************************************
1101 * SetObjectOwner16 (GDI.461)
1103 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1105 /* Nothing to do */
1109 /***********************************************************************
1110 * SetObjectOwner (GDI32.386)
1112 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1114 /* Nothing to do */
1118 /***********************************************************************
1119 * MakeObjectPrivate (GDI.463)
1121 * What does that mean ?
1122 * Some little docu can be found in "Undocumented Windows",
1123 * but this is basically useless.
1124 * At least we know that this flags the GDI object's wMagic
1125 * with 0x2000 (OBJECT_PRIVATE), so we just do it.
1126 * But Wine doesn't react on that yet.
1128 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1130 GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1131 if (!ptr)
1133 ERR("invalid GDI object %04x !\n", handle);
1134 return;
1136 ptr->wMagic |= OBJECT_PRIVATE;
1137 GDI_ReleaseObj( handle );
1141 /***********************************************************************
1142 * GdiFlush (GDI32.128)
1144 BOOL WINAPI GdiFlush(void)
1146 return TRUE; /* FIXME */
1150 /***********************************************************************
1151 * GdiGetBatchLimit (GDI32.129)
1153 DWORD WINAPI GdiGetBatchLimit(void)
1155 return 1; /* FIXME */
1159 /***********************************************************************
1160 * GdiSetBatchLimit (GDI32.139)
1162 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1164 return 1; /* FIXME */
1168 /***********************************************************************
1169 * GdiSeeGdiDo (GDI.452)
1171 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1172 WORD wParam3 )
1174 switch (wReqType)
1176 case 0x0001: /* LocalAlloc */
1177 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1178 case 0x0002: /* LocalFree */
1179 return LOCAL_Free( GDI_HeapSel, wParam1 );
1180 case 0x0003: /* LocalCompact */
1181 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1182 case 0x0103: /* LocalHeap */
1183 return GDI_HeapSel;
1184 default:
1185 WARN("(wReqType=%04x): Unknown\n", wReqType);
1186 return (DWORD)-1;
1190 /***********************************************************************
1191 * GdiSignalProc (GDI.610)
1193 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1194 DWORD dwFlags, HMODULE16 hModule )
1196 return 0;
1199 /***********************************************************************
1200 * FinalGdiInit16 (GDI.405)
1202 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1206 /***********************************************************************
1207 * GdiFreeResources (GDI.609)
1209 WORD WINAPI GdiFreeResources16( DWORD reserve )
1211 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1212 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1215 /***********************************************************************
1216 * MulDiv16 (GDI.128)
1218 INT16 WINAPI MulDiv16(
1219 INT16 nMultiplicand,
1220 INT16 nMultiplier,
1221 INT16 nDivisor)
1223 INT ret;
1224 if (!nDivisor) return -32768;
1225 /* We want to deal with a positive divisor to simplify the logic. */
1226 if (nDivisor < 0)
1228 nMultiplicand = - nMultiplicand;
1229 nDivisor = -nDivisor;
1231 /* If the result is positive, we "add" to round. else,
1232 * we subtract to round. */
1233 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1234 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1235 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1236 else
1237 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1238 if ((ret > 32767) || (ret < -32767)) return -32768;
1239 return (INT16) ret;
1243 /*******************************************************************
1244 * GetColorAdjustment [GDI32.164]
1248 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1250 FIXME("GetColorAdjustment, stub\n");
1251 return 0;
1254 /*******************************************************************
1255 * GetMiterLimit [GDI32.201]
1259 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1261 FIXME("GetMiterLimit, stub\n");
1262 return 0;
1265 /*******************************************************************
1266 * SetMiterLimit [GDI32.325]
1270 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1272 FIXME("SetMiterLimit, stub\n");
1273 return 0;
1276 /*******************************************************************
1277 * GdiComment [GDI32.109]
1281 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1283 FIXME("GdiComment, stub\n");
1284 return 0;
1286 /*******************************************************************
1287 * SetColorAdjustment [GDI32.309]
1291 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1293 FIXME("SetColorAdjustment, stub\n");
1294 return 0;