Allocate DC objects on the process heap, and removed WIN_DC_INFO
[wine/multimedia.git] / objects / gdiobj.c
blob58d21a1a758a3d4e4b0ce05815f2ee2dc68d099f
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"
29 #include "syslevel.h"
31 DEFAULT_DEBUG_CHANNEL(gdi);
34 /***********************************************************************
35 * GDI stock objects
38 static BRUSHOBJ WhiteBrush =
40 { 0, BRUSH_MAGIC, 1 }, /* header */
41 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
44 static BRUSHOBJ LtGrayBrush =
46 { 0, BRUSH_MAGIC, 1 }, /* header */
47 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
48 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
51 static BRUSHOBJ GrayBrush =
53 { 0, BRUSH_MAGIC, 1 }, /* header */
54 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
55 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
58 static BRUSHOBJ DkGrayBrush =
60 { 0, BRUSH_MAGIC, 1 }, /* header */
61 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
62 /* NB_HATCH_STYLES is an index into HatchBrushes */
63 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
66 static BRUSHOBJ BlackBrush =
68 { 0, BRUSH_MAGIC, 1 }, /* header */
69 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
72 static BRUSHOBJ NullBrush =
74 { 0, BRUSH_MAGIC, 1 }, /* header */
75 { BS_NULL, 0, 0 } /* logbrush */
78 static PENOBJ WhitePen =
80 { 0, PEN_MAGIC, 1 }, /* header */
81 { PS_SOLID, { 0, 0 }, RGB(255,255,255) } /* logpen */
84 static PENOBJ BlackPen =
86 { 0, PEN_MAGIC, 1 }, /* header */
87 { PS_SOLID, { 0, 0 }, RGB(0,0,0) } /* logpen */
90 static PENOBJ NullPen =
92 { 0, PEN_MAGIC, 1 }, /* header */
93 { PS_NULL, { 0, 0 }, 0 } /* logpen */
96 static FONTOBJ OEMFixedFont =
98 { 0, FONT_MAGIC, 1 }, /* header */
99 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
100 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
102 /* Filler to make the location counter dword aligned again. This is necessary
103 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
104 segment, and (c) Solaris assembler is stupid. */
105 static UINT16 align_OEMFixedFont = 1;
107 static FONTOBJ AnsiFixedFont =
109 { 0, FONT_MAGIC, 1 }, /* header */
110 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
111 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
113 static UINT16 align_AnsiFixedFont = 1;
115 static FONTOBJ AnsiVarFont =
117 { 0, FONT_MAGIC, 1 }, /* header */
118 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
119 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
121 static UINT16 align_AnsiVarFont = 1;
123 static FONTOBJ SystemFont =
125 { 0, FONT_MAGIC, 1 },
126 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
127 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
129 static UINT16 align_SystemFont = 1;
131 static FONTOBJ DeviceDefaultFont =
133 { 0, FONT_MAGIC, 1 }, /* header */
134 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
135 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
137 static UINT16 align_DeviceDefaultFont = 1;
139 static FONTOBJ SystemFixedFont =
141 { 0, FONT_MAGIC, 1 }, /* header */
142 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
143 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
145 static UINT16 align_SystemFixedFont = 1;
147 /* FIXME: Is this correct? */
148 static FONTOBJ DefaultGuiFont =
150 { 0, FONT_MAGIC, 1 }, /* header */
151 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
152 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
154 static UINT16 align_DefaultGuiFont = 1;
157 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
159 (GDIOBJHDR *) &WhiteBrush,
160 (GDIOBJHDR *) &LtGrayBrush,
161 (GDIOBJHDR *) &GrayBrush,
162 (GDIOBJHDR *) &DkGrayBrush,
163 (GDIOBJHDR *) &BlackBrush,
164 (GDIOBJHDR *) &NullBrush,
165 (GDIOBJHDR *) &WhitePen,
166 (GDIOBJHDR *) &BlackPen,
167 (GDIOBJHDR *) &NullPen,
168 NULL,
169 (GDIOBJHDR *) &OEMFixedFont,
170 (GDIOBJHDR *) &AnsiFixedFont,
171 (GDIOBJHDR *) &AnsiVarFont,
172 (GDIOBJHDR *) &SystemFont,
173 (GDIOBJHDR *) &DeviceDefaultFont,
174 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
175 (GDIOBJHDR *) &SystemFixedFont,
176 (GDIOBJHDR *) &DefaultGuiFont
179 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
181 static SYSLEVEL GDI_level;
182 static WORD GDI_HeapSel;
185 /******************************************************************************
187 * void ReadFontInformation(
188 * char const *fontName,
189 * FONTOBJ *font,
190 * int defHeight,
191 * int defBold,
192 * int defItalic,
193 * int defUnderline,
194 * int defStrikeOut )
196 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
197 * section for entries containing fontName.Height, fontName.Bold, etc.,
198 * where fontName is the name specified in the call (e.g., "System"). It
199 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
200 * the first character in the boolean attributes (bold, italic, and
201 * underline).
202 *****************************************************************************/
204 static void ReadFontInformation(
205 char const *fontName,
206 FONTOBJ *font,
207 int defHeight,
208 int defBold,
209 int defItalic,
210 int defUnderline,
211 int defStrikeOut )
213 char key[256];
215 /* In order for the stock fonts to be independent of
216 * mapping mode, the height (& width) must be 0
218 sprintf(key, "%s.Height", fontName);
219 font->logfont.lfHeight =
220 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
222 sprintf(key, "%s.Bold", fontName);
223 font->logfont.lfWeight =
224 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
225 FW_BOLD : FW_NORMAL;
227 sprintf(key, "%s.Italic", fontName);
228 font->logfont.lfItalic =
229 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
231 sprintf(key, "%s.Underline", fontName);
232 font->logfont.lfUnderline =
233 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
235 sprintf(key, "%s.StrikeOut", fontName);
236 font->logfont.lfStrikeOut =
237 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
239 return;
242 /***********************************************************************
243 * Because the stock fonts have their structure initialized with
244 * a height of 0 to keep them independent of mapping mode, simply
245 * returning the LOGFONT as is will not work correctly.
246 * These "FixStockFontSizeXXX()" methods will get the correct
247 * size for the fonts.
249 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
251 HDC hdc;
252 HFONT hOldFont;
254 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
256 hOldFont = (HFONT)SelectObject(hdc, handle);
258 GetTextMetricsA(hdc, lptm);
260 SelectObject(hdc, hOldFont);
262 DeleteDC(hdc);
265 static inline void FixStockFontSize16(
266 HFONT handle,
267 INT16 count,
268 LPVOID buffer)
270 TEXTMETRICA tm;
271 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
274 * Was the lfHeight field copied (it's the first field)?
275 * If it was and it was null, replace the height.
277 if ( (count >= 2*sizeof(INT16)) &&
278 (pLogFont->lfHeight == 0) )
280 GetFontMetrics(handle, &tm);
282 pLogFont->lfHeight = tm.tmHeight;
283 pLogFont->lfWidth = tm.tmAveCharWidth;
287 static inline void FixStockFontSizeA(
288 HFONT handle,
289 INT count,
290 LPVOID buffer)
292 TEXTMETRICA tm;
293 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
296 * Was the lfHeight field copied (it's the first field)?
297 * If it was and it was null, replace the height.
299 if ( (count >= 2*sizeof(INT)) &&
300 (pLogFont->lfHeight == 0) )
302 GetFontMetrics(handle, &tm);
304 pLogFont->lfHeight = tm.tmHeight;
305 pLogFont->lfWidth = tm.tmAveCharWidth;
310 * Since the LOGFONTA and LOGFONTW structures are identical up to the
311 * lfHeight member (the one of interest in this case) we simply define
312 * the W version as the A version.
314 #define FixStockFontSizeW FixStockFontSizeA
316 #define TRACE_SEC(handle,text) \
317 TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
319 /***********************************************************************
320 * GDI_Init
322 * GDI initialization.
324 BOOL GDI_Init(void)
326 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
327 HPALETTE16 hpalette;
328 HINSTANCE16 instance;
330 _CreateSysLevel( &GDI_level, 3 );
332 /* create GDI heap */
333 if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
334 GDI_HeapSel = GlobalHandleToSel16( instance );
336 /* Kill some warnings. */
337 (void)align_OEMFixedFont;
338 (void)align_AnsiFixedFont;
339 (void)align_AnsiVarFont;
340 (void)align_SystemFont;
341 (void)align_DeviceDefaultFont;
342 (void)align_SystemFixedFont;
343 (void)align_DefaultGuiFont;
345 /* TWEAK: Initialize font hints */
346 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
347 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
348 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
349 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
350 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
351 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
352 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
354 /* Create default palette */
356 /* DR well *this* palette can't be moveable (?) */
357 hpalette = PALETTE_Init();
358 if( !hpalette ) return FALSE;
359 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hpalette );
361 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
362 return TRUE;
365 #define FIRST_LARGE_HANDLE 16
366 #define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE - FIRST_LARGE_HANDLE) >> 2)
367 static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
368 static int next_large_handle;
370 /***********************************************************************
371 * alloc_large_heap
373 * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
375 inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
377 int i;
378 GDIOBJHDR *obj;
380 for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
381 if (!large_handles[i]) goto found;
382 for (i = 0; i <= next_large_handle; i++)
383 if (!large_handles[i]) goto found;
384 *handle = 0;
385 return NULL;
387 found:
388 if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
390 large_handles[i] = obj;
391 *handle = (i + FIRST_LARGE_HANDLE) << 2;
392 next_large_handle = i;
394 return obj;
398 /***********************************************************************
399 * GDI_AllocObject
401 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
403 static DWORD count = 0;
404 GDIOBJHDR *obj;
406 _EnterSysLevel( &GDI_level );
407 switch(magic)
409 /* allocate DCs on the larger heap */
410 case DC_MAGIC:
411 case DISABLED_DC_MAGIC:
412 case META_DC_MAGIC:
413 case METAFILE_MAGIC:
414 case METAFILE_DC_MAGIC:
415 case ENHMETAFILE_MAGIC:
416 case ENHMETAFILE_DC_MAGIC:
417 if (!(obj = alloc_large_heap( size, handle ))) goto error;
418 break;
419 default:
420 if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
421 assert( *handle & 2 );
422 obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
423 break;
426 obj->hNext = 0;
427 obj->wMagic = magic|OBJECT_NOSYSTEM;
428 obj->dwCount = ++count;
430 TRACE_SEC( *handle, "enter" );
431 return obj;
433 error:
434 _LeaveSysLevel( &GDI_level );
435 *handle = 0;
436 return NULL;
440 /***********************************************************************
441 * GDI_ReallocObject
443 * The object ptr must have been obtained with GDI_GetObjPtr.
444 * The new pointer must be released with GDI_ReleaseObj.
446 void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
448 HGDIOBJ new_handle;
450 assert( handle & 2 ); /* no realloc for large handles */
451 LOCAL_Unlock( GDI_HeapSel, handle );
452 if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
454 TRACE_SEC( handle, "leave" );
455 _LeaveSysLevel( &GDI_level );
456 return NULL;
458 assert( new_handle == handle ); /* moveable handle cannot change */
459 return LOCAL_Lock( GDI_HeapSel, handle );
463 /***********************************************************************
464 * GDI_FreeObject
466 BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
468 GDIOBJHDR *object = ptr;
470 /* can't free stock objects */
471 if (handle < FIRST_STOCK_HANDLE)
473 object->wMagic = 0; /* Mark it as invalid */
474 if (handle & 2) /* GDI heap handle */
476 LOCAL_Unlock( GDI_HeapSel, handle );
477 LOCAL_Free( GDI_HeapSel, handle );
479 else /* large heap handle */
481 int i = (handle >> 2) - FIRST_LARGE_HANDLE;
482 if (i >= 0 && large_handles[i])
484 HeapFree( GetProcessHeap(), 0, large_handles[i] );
485 large_handles[i] = NULL;
489 TRACE_SEC( handle, "leave" );
490 _LeaveSysLevel( &GDI_level );
491 return TRUE;
495 /***********************************************************************
496 * GDI_GetObjPtr
498 * Return a pointer to the GDI object associated to the handle.
499 * Return NULL if the object has the wrong magic number.
500 * The object must be released with GDI_ReleaseObj.
502 void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
504 GDIOBJHDR *ptr = NULL;
506 _EnterSysLevel( &GDI_level );
508 if (handle >= FIRST_STOCK_HANDLE)
510 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
511 if (ptr && (magic != MAGIC_DONTCARE)
512 && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
514 else if (handle & 2) /* GDI heap handle */
516 ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
517 if (ptr &&
518 (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic))
520 LOCAL_Unlock( GDI_HeapSel, handle );
521 ptr = NULL;
524 else /* large heap handle */
526 int i = (handle >> 2) - FIRST_LARGE_HANDLE;
527 if (i >= 0)
529 ptr = large_handles[i];
530 if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
534 if (!ptr)
536 _LeaveSysLevel( &GDI_level );
537 SetLastError( ERROR_INVALID_HANDLE );
539 else TRACE_SEC( handle, "enter" );
541 return ptr;
545 /***********************************************************************
546 * GDI_ReleaseObj
549 void GDI_ReleaseObj( HGDIOBJ handle )
551 if (handle < FIRST_STOCK_HANDLE && (handle & 2)) LOCAL_Unlock( GDI_HeapSel, handle );
552 TRACE_SEC( handle, "leave" );
553 _LeaveSysLevel( &GDI_level );
557 /***********************************************************************
558 * DeleteObject16 (GDI.69)
560 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
562 return DeleteObject( obj );
566 /***********************************************************************
567 * DeleteObject (GDI32.70)
569 BOOL WINAPI DeleteObject( HGDIOBJ obj )
571 /* Check if object is valid */
573 GDIOBJHDR * header;
574 if (HIWORD(obj)) return FALSE;
575 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE)) {
576 TRACE("Preserving Stock object %04x\n", obj );
577 /* NOTE: No GDI_Release is necessary */
578 return TRUE;
580 if (obj == hPseudoStockBitmap) return TRUE;
581 if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
583 if (!(header->wMagic & OBJECT_NOSYSTEM)
584 && (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
586 TRACE("Preserving system object %04x\n", obj);
587 GDI_ReleaseObj( obj );
588 return TRUE;
591 TRACE("%04x\n", obj );
593 /* Delete object */
595 switch(GDIMAGIC(header->wMagic))
597 case PEN_MAGIC: return GDI_FreeObject( obj, header );
598 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
599 case FONT_MAGIC: return GDI_FreeObject( obj, header );
600 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
601 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
602 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
603 case DC_MAGIC:
604 GDI_ReleaseObj( obj );
605 return DeleteDC(obj);
606 case 0 :
607 WARN("Already deleted\n");
608 break;
609 default:
610 WARN("Unknown magic number (%d)\n",GDIMAGIC(header->wMagic));
612 GDI_ReleaseObj( obj );
613 return FALSE;
616 /***********************************************************************
617 * GetStockObject16 (GDI.87)
619 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
621 return (HGDIOBJ16)GetStockObject( obj );
625 /***********************************************************************
626 * GetStockObject (GDI32.220)
628 HGDIOBJ WINAPI GetStockObject( INT obj )
630 HGDIOBJ ret;
631 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
632 if (!StockObjects[obj]) return 0;
633 ret = (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
634 TRACE("returning %4x\n", ret );
635 return ret;
639 /***********************************************************************
640 * GetObject16 (GDI.82)
642 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
644 GDIOBJHDR * ptr;
645 INT16 result = 0;
646 TRACE("%04x %d %p\n", handle, count, buffer );
647 if (!count) return 0;
649 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
651 switch(GDIMAGIC(ptr->wMagic))
653 case PEN_MAGIC:
654 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
655 break;
656 case BRUSH_MAGIC:
657 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
658 break;
659 case BITMAP_MAGIC:
660 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
661 break;
662 case FONT_MAGIC:
663 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
666 * Fix the LOGFONT structure for the stock fonts
668 if ( (handle >= FIRST_STOCK_HANDLE) &&
669 (handle <= LAST_STOCK_HANDLE) )
670 FixStockFontSize16(handle, count, buffer);
671 break;
672 case PALETTE_MAGIC:
673 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
674 break;
676 GDI_ReleaseObj( handle );
677 return result;
681 /***********************************************************************
682 * GetObjectA (GDI32.204)
684 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
686 GDIOBJHDR * ptr;
687 INT result = 0;
688 TRACE("%08x %d %p\n", handle, count, buffer );
689 if (!count) return 0;
691 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
693 switch(GDIMAGIC(ptr->wMagic))
695 case PEN_MAGIC:
696 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
697 break;
698 case BRUSH_MAGIC:
699 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
700 break;
701 case BITMAP_MAGIC:
702 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
703 break;
704 case FONT_MAGIC:
705 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
708 * Fix the LOGFONT structure for the stock fonts
710 if ( (handle >= FIRST_STOCK_HANDLE) &&
711 (handle <= LAST_STOCK_HANDLE) )
712 FixStockFontSizeA(handle, count, buffer);
713 break;
714 case PALETTE_MAGIC:
715 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
716 break;
718 case REGION_MAGIC:
719 case DC_MAGIC:
720 case DISABLED_DC_MAGIC:
721 case META_DC_MAGIC:
722 case METAFILE_MAGIC:
723 case METAFILE_DC_MAGIC:
724 case ENHMETAFILE_MAGIC:
725 case ENHMETAFILE_DC_MAGIC:
726 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
727 break;
729 default:
730 ERR("Invalid GDI Magic %04x\n", GDIMAGIC(ptr->wMagic));
731 break;
733 GDI_ReleaseObj( handle );
734 return result;
737 /***********************************************************************
738 * GetObjectW (GDI32.206)
740 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
742 GDIOBJHDR * ptr;
743 INT result = 0;
744 TRACE("%08x %d %p\n", handle, count, buffer );
745 if (!count) return 0;
747 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
749 switch(GDIMAGIC(ptr->wMagic))
751 case PEN_MAGIC:
752 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
753 break;
754 case BRUSH_MAGIC:
755 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
756 break;
757 case BITMAP_MAGIC:
758 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
759 break;
760 case FONT_MAGIC:
761 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
764 * Fix the LOGFONT structure for the stock fonts
766 if ( (handle >= FIRST_STOCK_HANDLE) &&
767 (handle <= LAST_STOCK_HANDLE) )
768 FixStockFontSizeW(handle, count, buffer);
769 break;
770 case PALETTE_MAGIC:
771 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
772 break;
773 default:
774 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
775 break;
777 GDI_ReleaseObj( handle );
778 return result;
781 /***********************************************************************
782 * GetObjectType (GDI32.205)
784 DWORD WINAPI GetObjectType( HANDLE handle )
786 GDIOBJHDR * ptr;
787 INT result = 0;
788 TRACE("%08x\n", handle );
790 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
792 switch(GDIMAGIC(ptr->wMagic))
794 case PEN_MAGIC:
795 result = OBJ_PEN;
796 break;
797 case BRUSH_MAGIC:
798 result = OBJ_BRUSH;
799 break;
800 case BITMAP_MAGIC:
801 result = OBJ_BITMAP;
802 break;
803 case FONT_MAGIC:
804 result = OBJ_FONT;
805 break;
806 case PALETTE_MAGIC:
807 result = OBJ_PAL;
808 break;
809 case REGION_MAGIC:
810 result = OBJ_REGION;
811 break;
812 case DC_MAGIC:
813 result = OBJ_DC;
814 break;
815 case META_DC_MAGIC:
816 result = OBJ_METADC;
817 break;
818 case METAFILE_MAGIC:
819 result = OBJ_METAFILE;
820 break;
821 case METAFILE_DC_MAGIC:
822 result = OBJ_METADC;
823 break;
824 case ENHMETAFILE_MAGIC:
825 result = OBJ_ENHMETAFILE;
826 break;
827 case ENHMETAFILE_DC_MAGIC:
828 result = OBJ_ENHMETADC;
829 break;
830 default:
831 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
832 break;
834 GDI_ReleaseObj( handle );
835 return result;
838 /***********************************************************************
839 * GetCurrentObject (GDI32.166)
841 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
843 HANDLE ret = 0;
844 DC * dc = DC_GetDCPtr( hdc );
846 if (dc)
848 switch (type) {
849 case OBJ_PEN: ret = dc->hPen; break;
850 case OBJ_BRUSH: ret = dc->hBrush; break;
851 case OBJ_PAL: ret = dc->hPalette; break;
852 case OBJ_FONT: ret = dc->hFont; break;
853 case OBJ_BITMAP: ret = dc->hBitmap; break;
854 default:
855 /* the SDK only mentions those above */
856 FIXME("(%08x,%d): unknown type.\n",hdc,type);
857 break;
859 GDI_ReleaseObj( hdc );
861 return ret;
865 /***********************************************************************
866 * SelectObject16 (GDI.45)
868 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
870 return (HGDIOBJ16)SelectObject( hdc, handle );
874 /***********************************************************************
875 * SelectObject (GDI32.299)
877 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
879 HGDIOBJ ret = 0;
880 DC * dc = DC_GetDCUpdate( hdc );
881 if (!dc) return 0;
882 TRACE("hdc=%04x %04x\n", hdc, handle );
883 if (dc->funcs->pSelectObject)
884 ret = dc->funcs->pSelectObject( dc, handle );
885 GDI_ReleaseObj( hdc );
886 return ret;
890 /***********************************************************************
891 * UnrealizeObject16 (GDI.150)
893 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
895 return UnrealizeObject( obj );
899 /***********************************************************************
900 * UnrealizeObject (GDI32.358)
902 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
904 BOOL result = TRUE;
905 /* Check if object is valid */
907 GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
908 if (!header) return FALSE;
910 TRACE("%04x\n", obj );
912 /* Unrealize object */
914 switch(GDIMAGIC(header->wMagic))
916 case PALETTE_MAGIC:
917 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
918 break;
920 case BRUSH_MAGIC:
921 /* Windows resets the brush origin. We don't need to. */
922 break;
924 GDI_ReleaseObj( obj );
925 return result;
929 /***********************************************************************
930 * EnumObjects16 (GDI.71)
932 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
933 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
935 /* Solid colors to enumerate */
936 static const COLORREF solid_colors[] =
937 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
938 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
939 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
940 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
941 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
942 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
943 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
944 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
947 INT16 i, retval = 0;
948 LOGPEN16 *pen;
949 LOGBRUSH16 *brush = NULL;
951 TRACE("%04x %d %08lx %08lx\n",
952 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
953 switch(nObjType)
955 case OBJ_PEN:
956 /* Enumerate solid pens */
957 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
958 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
960 pen->lopnStyle = PS_SOLID;
961 pen->lopnWidth.x = 1;
962 pen->lopnWidth.y = 0;
963 pen->lopnColor = solid_colors[i];
964 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
965 TRACE("solid pen %08lx, ret=%d\n",
966 solid_colors[i], retval);
967 if (!retval) break;
969 SEGPTR_FREE(pen);
970 break;
972 case OBJ_BRUSH:
973 /* Enumerate solid brushes */
974 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
975 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
977 brush->lbStyle = BS_SOLID;
978 brush->lbColor = solid_colors[i];
979 brush->lbHatch = 0;
980 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
981 TRACE("solid brush %08lx, ret=%d\n",
982 solid_colors[i], retval);
983 if (!retval) break;
986 /* Now enumerate hatched brushes */
987 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
989 brush->lbStyle = BS_HATCHED;
990 brush->lbColor = RGB(0,0,0);
991 brush->lbHatch = i;
992 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
993 TRACE("hatched brush %d, ret=%d\n",
994 i, retval);
995 if (!retval) break;
997 SEGPTR_FREE(brush);
998 break;
1000 default:
1001 WARN("(%d): Invalid type\n", nObjType );
1002 break;
1004 return retval;
1008 /***********************************************************************
1009 * EnumObjects (GDI32.89)
1011 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
1012 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
1014 /* Solid colors to enumerate */
1015 static const COLORREF solid_colors[] =
1016 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1017 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1018 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1019 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1020 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1021 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1022 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1023 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1026 INT i, retval = 0;
1027 LOGPEN pen;
1028 LOGBRUSH brush;
1030 TRACE("%04x %d %08lx %08lx\n",
1031 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
1032 switch(nObjType)
1034 case OBJ_PEN:
1035 /* Enumerate solid pens */
1036 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1038 pen.lopnStyle = PS_SOLID;
1039 pen.lopnWidth.x = 1;
1040 pen.lopnWidth.y = 0;
1041 pen.lopnColor = solid_colors[i];
1042 retval = lpEnumFunc( &pen, lParam );
1043 TRACE("solid pen %08lx, ret=%d\n",
1044 solid_colors[i], retval);
1045 if (!retval) break;
1047 break;
1049 case OBJ_BRUSH:
1050 /* Enumerate solid brushes */
1051 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1053 brush.lbStyle = BS_SOLID;
1054 brush.lbColor = solid_colors[i];
1055 brush.lbHatch = 0;
1056 retval = lpEnumFunc( &brush, lParam );
1057 TRACE("solid brush %08lx, ret=%d\n",
1058 solid_colors[i], retval);
1059 if (!retval) break;
1062 /* Now enumerate hatched brushes */
1063 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1065 brush.lbStyle = BS_HATCHED;
1066 brush.lbColor = RGB(0,0,0);
1067 brush.lbHatch = i;
1068 retval = lpEnumFunc( &brush, lParam );
1069 TRACE("hatched brush %d, ret=%d\n",
1070 i, retval);
1071 if (!retval) break;
1073 break;
1075 default:
1076 /* FIXME: implement Win32 types */
1077 WARN("(%d): Invalid type\n", nObjType );
1078 break;
1080 return retval;
1084 /***********************************************************************
1085 * IsGDIObject (GDI.462)
1087 * returns type of object if valid (W95 system programming secrets p. 264-5)
1089 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
1091 UINT16 magic = 0;
1093 GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1094 if (object)
1096 magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1097 GDI_ReleaseObj( handle );
1099 return magic;
1103 /***********************************************************************
1104 * SetObjectOwner16 (GDI.461)
1106 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1108 /* Nothing to do */
1112 /***********************************************************************
1113 * SetObjectOwner (GDI32.386)
1115 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1117 /* Nothing to do */
1121 /***********************************************************************
1122 * MakeObjectPrivate (GDI.463)
1124 * What does that mean ?
1125 * Some little docu can be found in "Undocumented Windows",
1126 * but this is basically useless.
1127 * At least we know that this flags the GDI object's wMagic
1128 * with 0x2000 (OBJECT_PRIVATE), so we just do it.
1129 * But Wine doesn't react on that yet.
1131 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1133 GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1134 if (!ptr)
1136 ERR("invalid GDI object %04x !\n", handle);
1137 return;
1139 ptr->wMagic |= OBJECT_PRIVATE;
1140 GDI_ReleaseObj( handle );
1144 /***********************************************************************
1145 * GdiFlush (GDI32.128)
1147 BOOL WINAPI GdiFlush(void)
1149 return TRUE; /* FIXME */
1153 /***********************************************************************
1154 * GdiGetBatchLimit (GDI32.129)
1156 DWORD WINAPI GdiGetBatchLimit(void)
1158 return 1; /* FIXME */
1162 /***********************************************************************
1163 * GdiSetBatchLimit (GDI32.139)
1165 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1167 return 1; /* FIXME */
1171 /***********************************************************************
1172 * GdiSeeGdiDo (GDI.452)
1174 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1175 WORD wParam3 )
1177 switch (wReqType)
1179 case 0x0001: /* LocalAlloc */
1180 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1181 case 0x0002: /* LocalFree */
1182 return LOCAL_Free( GDI_HeapSel, wParam1 );
1183 case 0x0003: /* LocalCompact */
1184 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1185 case 0x0103: /* LocalHeap */
1186 return GDI_HeapSel;
1187 default:
1188 WARN("(wReqType=%04x): Unknown\n", wReqType);
1189 return (DWORD)-1;
1193 /***********************************************************************
1194 * GdiSignalProc (GDI.610)
1196 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1197 DWORD dwFlags, HMODULE16 hModule )
1199 return 0;
1202 /***********************************************************************
1203 * FinalGdiInit16 (GDI.405)
1205 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1209 /***********************************************************************
1210 * GdiFreeResources (GDI.609)
1212 WORD WINAPI GdiFreeResources16( DWORD reserve )
1214 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1215 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1218 /***********************************************************************
1219 * MulDiv16 (GDI.128)
1221 INT16 WINAPI MulDiv16(
1222 INT16 nMultiplicand,
1223 INT16 nMultiplier,
1224 INT16 nDivisor)
1226 INT ret;
1227 if (!nDivisor) return -32768;
1228 /* We want to deal with a positive divisor to simplify the logic. */
1229 if (nDivisor < 0)
1231 nMultiplicand = - nMultiplicand;
1232 nDivisor = -nDivisor;
1234 /* If the result is positive, we "add" to round. else,
1235 * we subtract to round. */
1236 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1237 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1238 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1239 else
1240 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1241 if ((ret > 32767) || (ret < -32767)) return -32768;
1242 return (INT16) ret;
1246 /*******************************************************************
1247 * GetColorAdjustment [GDI32.164]
1251 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1253 FIXME("GetColorAdjustment, stub\n");
1254 return 0;
1257 /*******************************************************************
1258 * GetMiterLimit [GDI32.201]
1262 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1264 FIXME("GetMiterLimit, stub\n");
1265 return 0;
1268 /*******************************************************************
1269 * SetMiterLimit [GDI32.325]
1273 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1275 FIXME("SetMiterLimit, stub\n");
1276 return 0;
1279 /*******************************************************************
1280 * GdiComment [GDI32.109]
1284 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1286 FIXME("GdiComment, stub\n");
1287 return 0;
1289 /*******************************************************************
1290 * SetColorAdjustment [GDI32.309]
1294 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1296 FIXME("SetColorAdjustment, stub\n");
1297 return 0;