Fixed some issues found by winapi_check.
[wine.git] / objects / gdiobj.c
blob057eda0920b7e3ee9e0970a71f187df2d4d6dc81
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 "local.h"
23 #include "options.h"
24 #include "palette.h"
25 #include "pen.h"
26 #include "region.h"
27 #include "debugtools.h"
28 #include "gdi.h"
29 #include "tweak.h"
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 = { CRITICAL_SECTION_INIT, 3 };
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 /* create GDI heap */
331 if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
332 GDI_HeapSel = GlobalHandleToSel16( instance );
334 /* Kill some warnings. */
335 (void)align_OEMFixedFont;
336 (void)align_AnsiFixedFont;
337 (void)align_AnsiVarFont;
338 (void)align_SystemFont;
339 (void)align_DeviceDefaultFont;
340 (void)align_SystemFixedFont;
341 (void)align_DefaultGuiFont;
343 /* TWEAK: Initialize font hints */
344 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
345 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
346 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
347 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
348 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
349 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
350 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
352 /* Create default palette */
354 /* DR well *this* palette can't be moveable (?) */
355 hpalette = PALETTE_Init();
356 if( !hpalette ) return FALSE;
357 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hpalette );
359 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
360 return TRUE;
363 #define FIRST_LARGE_HANDLE 16
364 #define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
365 static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
366 static int next_large_handle;
368 /***********************************************************************
369 * alloc_large_heap
371 * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
373 inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
375 int i;
376 GDIOBJHDR *obj;
378 for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
379 if (!large_handles[i]) goto found;
380 for (i = 0; i <= next_large_handle; i++)
381 if (!large_handles[i]) goto found;
382 *handle = 0;
383 return NULL;
385 found:
386 if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
388 large_handles[i] = obj;
389 *handle = (i + FIRST_LARGE_HANDLE) << 2;
390 next_large_handle = i;
392 return obj;
396 /***********************************************************************
397 * GDI_AllocObject
399 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
401 static DWORD count = 0;
402 GDIOBJHDR *obj;
404 _EnterSysLevel( &GDI_level );
405 switch(magic)
407 /* allocate DCs on the larger heap */
408 case DC_MAGIC:
409 case DISABLED_DC_MAGIC:
410 case META_DC_MAGIC:
411 case METAFILE_MAGIC:
412 case METAFILE_DC_MAGIC:
413 case ENHMETAFILE_MAGIC:
414 case ENHMETAFILE_DC_MAGIC:
415 if (!(obj = alloc_large_heap( size, handle ))) goto error;
416 break;
417 default:
418 if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
419 assert( *handle & 2 );
420 obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
421 break;
424 obj->hNext = 0;
425 obj->wMagic = magic|OBJECT_NOSYSTEM;
426 obj->dwCount = ++count;
428 TRACE_SEC( *handle, "enter" );
429 return obj;
431 error:
432 _LeaveSysLevel( &GDI_level );
433 *handle = 0;
434 return NULL;
438 /***********************************************************************
439 * GDI_ReallocObject
441 * The object ptr must have been obtained with GDI_GetObjPtr.
442 * The new pointer must be released with GDI_ReleaseObj.
444 void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
446 HGDIOBJ new_handle;
448 assert( handle & 2 ); /* no realloc for large handles */
449 LOCAL_Unlock( GDI_HeapSel, handle );
450 if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
452 TRACE_SEC( handle, "leave" );
453 _LeaveSysLevel( &GDI_level );
454 return NULL;
456 assert( new_handle == handle ); /* moveable handle cannot change */
457 return LOCAL_Lock( GDI_HeapSel, handle );
461 /***********************************************************************
462 * GDI_FreeObject
464 BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
466 GDIOBJHDR *object = ptr;
468 /* can't free stock objects */
469 if (handle < FIRST_STOCK_HANDLE)
471 object->wMagic = 0; /* Mark it as invalid */
472 if (handle & 2) /* GDI heap handle */
474 LOCAL_Unlock( GDI_HeapSel, handle );
475 LOCAL_Free( GDI_HeapSel, handle );
477 else /* large heap handle */
479 int i = (handle >> 2) - FIRST_LARGE_HANDLE;
480 if (i >= 0 && large_handles[i])
482 HeapFree( GetProcessHeap(), 0, large_handles[i] );
483 large_handles[i] = NULL;
487 TRACE_SEC( handle, "leave" );
488 _LeaveSysLevel( &GDI_level );
489 return TRUE;
493 /***********************************************************************
494 * GDI_GetObjPtr
496 * Return a pointer to the GDI object associated to the handle.
497 * Return NULL if the object has the wrong magic number.
498 * The object must be released with GDI_ReleaseObj.
500 void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
502 GDIOBJHDR *ptr = NULL;
504 _EnterSysLevel( &GDI_level );
506 if (handle >= FIRST_STOCK_HANDLE)
508 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
509 if (ptr && (magic != MAGIC_DONTCARE)
510 && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
512 else if (handle & 2) /* GDI heap handle */
514 ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
515 if (ptr &&
516 (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic))
518 LOCAL_Unlock( GDI_HeapSel, handle );
519 ptr = NULL;
522 else /* large heap handle */
524 int i = (handle >> 2) - FIRST_LARGE_HANDLE;
525 if (i >= 0)
527 ptr = large_handles[i];
528 if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
532 if (!ptr)
534 _LeaveSysLevel( &GDI_level );
535 SetLastError( ERROR_INVALID_HANDLE );
537 else TRACE_SEC( handle, "enter" );
539 return ptr;
543 /***********************************************************************
544 * GDI_ReleaseObj
547 void GDI_ReleaseObj( HGDIOBJ handle )
549 if (handle < FIRST_STOCK_HANDLE && (handle & 2)) LOCAL_Unlock( GDI_HeapSel, handle );
550 TRACE_SEC( handle, "leave" );
551 _LeaveSysLevel( &GDI_level );
555 /***********************************************************************
556 * DeleteObject16 (GDI.69)
558 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
560 return DeleteObject( obj );
564 /***********************************************************************
565 * DeleteObject (GDI32.70)
567 BOOL WINAPI DeleteObject( HGDIOBJ obj )
569 /* Check if object is valid */
571 GDIOBJHDR * header;
572 if (HIWORD(obj)) return FALSE;
573 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE)) {
574 TRACE("Preserving Stock object %04x\n", obj );
575 /* NOTE: No GDI_Release is necessary */
576 return TRUE;
578 if (obj == hPseudoStockBitmap) return TRUE;
579 if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
581 if (!(header->wMagic & OBJECT_NOSYSTEM)
582 && (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
584 TRACE("Preserving system object %04x\n", obj);
585 GDI_ReleaseObj( obj );
586 return TRUE;
589 TRACE("%04x\n", obj );
591 /* Delete object */
593 switch(GDIMAGIC(header->wMagic))
595 case PEN_MAGIC: return GDI_FreeObject( obj, header );
596 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
597 case FONT_MAGIC: return GDI_FreeObject( obj, header );
598 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
599 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
600 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
601 case DC_MAGIC:
602 GDI_ReleaseObj( obj );
603 return DeleteDC(obj);
604 case 0 :
605 WARN("Already deleted\n");
606 break;
607 default:
608 WARN("Unknown magic number (%d)\n",GDIMAGIC(header->wMagic));
610 GDI_ReleaseObj( obj );
611 return FALSE;
614 /***********************************************************************
615 * GetStockObject16 (GDI.87)
617 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
619 return (HGDIOBJ16)GetStockObject( obj );
623 /***********************************************************************
624 * GetStockObject (GDI32.220)
626 HGDIOBJ WINAPI GetStockObject( INT obj )
628 HGDIOBJ ret;
629 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
630 if (!StockObjects[obj]) return 0;
631 ret = (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
632 TRACE("returning %4x\n", ret );
633 return ret;
637 /***********************************************************************
638 * GetObject16 (GDI.82)
640 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
642 GDIOBJHDR * ptr;
643 INT16 result = 0;
644 TRACE("%04x %d %p\n", handle, count, buffer );
645 if (!count) return 0;
647 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
649 switch(GDIMAGIC(ptr->wMagic))
651 case PEN_MAGIC:
652 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
653 break;
654 case BRUSH_MAGIC:
655 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
656 break;
657 case BITMAP_MAGIC:
658 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
659 break;
660 case FONT_MAGIC:
661 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
664 * Fix the LOGFONT structure for the stock fonts
666 if ( (handle >= FIRST_STOCK_HANDLE) &&
667 (handle <= LAST_STOCK_HANDLE) )
668 FixStockFontSize16(handle, count, buffer);
669 break;
670 case PALETTE_MAGIC:
671 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
672 break;
674 GDI_ReleaseObj( handle );
675 return result;
679 /***********************************************************************
680 * GetObjectA (GDI32.204)
682 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
684 GDIOBJHDR * ptr;
685 INT result = 0;
686 TRACE("%08x %d %p\n", handle, count, buffer );
687 if (!count) return 0;
689 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
691 switch(GDIMAGIC(ptr->wMagic))
693 case PEN_MAGIC:
694 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
695 break;
696 case BRUSH_MAGIC:
697 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
698 break;
699 case BITMAP_MAGIC:
700 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
701 break;
702 case FONT_MAGIC:
703 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
706 * Fix the LOGFONT structure for the stock fonts
708 if ( (handle >= FIRST_STOCK_HANDLE) &&
709 (handle <= LAST_STOCK_HANDLE) )
710 FixStockFontSizeA(handle, count, buffer);
711 break;
712 case PALETTE_MAGIC:
713 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
714 break;
716 case REGION_MAGIC:
717 case DC_MAGIC:
718 case DISABLED_DC_MAGIC:
719 case META_DC_MAGIC:
720 case METAFILE_MAGIC:
721 case METAFILE_DC_MAGIC:
722 case ENHMETAFILE_MAGIC:
723 case ENHMETAFILE_DC_MAGIC:
724 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
725 break;
727 default:
728 ERR("Invalid GDI Magic %04x\n", GDIMAGIC(ptr->wMagic));
729 break;
731 GDI_ReleaseObj( handle );
732 return result;
735 /***********************************************************************
736 * GetObjectW (GDI32.206)
738 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
740 GDIOBJHDR * ptr;
741 INT result = 0;
742 TRACE("%08x %d %p\n", handle, count, buffer );
743 if (!count) return 0;
745 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
747 switch(GDIMAGIC(ptr->wMagic))
749 case PEN_MAGIC:
750 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
751 break;
752 case BRUSH_MAGIC:
753 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
754 break;
755 case BITMAP_MAGIC:
756 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
757 break;
758 case FONT_MAGIC:
759 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
762 * Fix the LOGFONT structure for the stock fonts
764 if ( (handle >= FIRST_STOCK_HANDLE) &&
765 (handle <= LAST_STOCK_HANDLE) )
766 FixStockFontSizeW(handle, count, buffer);
767 break;
768 case PALETTE_MAGIC:
769 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
770 break;
771 default:
772 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
773 break;
775 GDI_ReleaseObj( handle );
776 return result;
779 /***********************************************************************
780 * GetObjectType (GDI32.205)
782 DWORD WINAPI GetObjectType( HANDLE handle )
784 GDIOBJHDR * ptr;
785 INT result = 0;
786 TRACE("%08x\n", handle );
788 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
790 switch(GDIMAGIC(ptr->wMagic))
792 case PEN_MAGIC:
793 result = OBJ_PEN;
794 break;
795 case BRUSH_MAGIC:
796 result = OBJ_BRUSH;
797 break;
798 case BITMAP_MAGIC:
799 result = OBJ_BITMAP;
800 break;
801 case FONT_MAGIC:
802 result = OBJ_FONT;
803 break;
804 case PALETTE_MAGIC:
805 result = OBJ_PAL;
806 break;
807 case REGION_MAGIC:
808 result = OBJ_REGION;
809 break;
810 case DC_MAGIC:
811 result = OBJ_DC;
812 break;
813 case META_DC_MAGIC:
814 result = OBJ_METADC;
815 break;
816 case METAFILE_MAGIC:
817 result = OBJ_METAFILE;
818 break;
819 case METAFILE_DC_MAGIC:
820 result = OBJ_METADC;
821 break;
822 case ENHMETAFILE_MAGIC:
823 result = OBJ_ENHMETAFILE;
824 break;
825 case ENHMETAFILE_DC_MAGIC:
826 result = OBJ_ENHMETADC;
827 break;
828 default:
829 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
830 break;
832 GDI_ReleaseObj( handle );
833 return result;
836 /***********************************************************************
837 * GetCurrentObject (GDI32.166)
839 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
841 HANDLE ret = 0;
842 DC * dc = DC_GetDCPtr( hdc );
844 if (dc)
846 switch (type) {
847 case OBJ_PEN: ret = dc->hPen; break;
848 case OBJ_BRUSH: ret = dc->hBrush; break;
849 case OBJ_PAL: ret = dc->hPalette; break;
850 case OBJ_FONT: ret = dc->hFont; break;
851 case OBJ_BITMAP: ret = dc->hBitmap; break;
852 default:
853 /* the SDK only mentions those above */
854 FIXME("(%08x,%d): unknown type.\n",hdc,type);
855 break;
857 GDI_ReleaseObj( hdc );
859 return ret;
863 /***********************************************************************
864 * SelectObject16 (GDI.45)
866 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
868 return (HGDIOBJ16)SelectObject( hdc, handle );
872 /***********************************************************************
873 * SelectObject (GDI32.299)
875 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
877 HGDIOBJ ret = 0;
878 DC * dc = DC_GetDCUpdate( hdc );
879 if (!dc) return 0;
880 TRACE("hdc=%04x %04x\n", hdc, handle );
881 if (dc->funcs->pSelectObject)
882 ret = dc->funcs->pSelectObject( dc, handle );
883 GDI_ReleaseObj( hdc );
884 return ret;
888 /***********************************************************************
889 * UnrealizeObject16 (GDI.150)
891 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
893 return UnrealizeObject( obj );
897 /***********************************************************************
898 * UnrealizeObject (GDI32.358)
900 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
902 BOOL result = TRUE;
903 /* Check if object is valid */
905 GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
906 if (!header) return FALSE;
908 TRACE("%04x\n", obj );
910 /* Unrealize object */
912 switch(GDIMAGIC(header->wMagic))
914 case PALETTE_MAGIC:
915 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
916 break;
918 case BRUSH_MAGIC:
919 /* Windows resets the brush origin. We don't need to. */
920 break;
922 GDI_ReleaseObj( obj );
923 return result;
927 /***********************************************************************
928 * EnumObjects16 (GDI.71)
930 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
931 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
933 /* Solid colors to enumerate */
934 static const COLORREF solid_colors[] =
935 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
936 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
937 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
938 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
939 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
940 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
941 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
942 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
945 INT16 i, retval = 0;
946 LOGPEN16 *pen;
947 LOGBRUSH16 *brush = NULL;
949 TRACE("%04x %d %08lx %08lx\n",
950 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
951 switch(nObjType)
953 case OBJ_PEN:
954 /* Enumerate solid pens */
955 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
956 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
958 pen->lopnStyle = PS_SOLID;
959 pen->lopnWidth.x = 1;
960 pen->lopnWidth.y = 0;
961 pen->lopnColor = solid_colors[i];
962 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
963 TRACE("solid pen %08lx, ret=%d\n",
964 solid_colors[i], retval);
965 if (!retval) break;
967 SEGPTR_FREE(pen);
968 break;
970 case OBJ_BRUSH:
971 /* Enumerate solid brushes */
972 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
973 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
975 brush->lbStyle = BS_SOLID;
976 brush->lbColor = solid_colors[i];
977 brush->lbHatch = 0;
978 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
979 TRACE("solid brush %08lx, ret=%d\n",
980 solid_colors[i], retval);
981 if (!retval) break;
984 /* Now enumerate hatched brushes */
985 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
987 brush->lbStyle = BS_HATCHED;
988 brush->lbColor = RGB(0,0,0);
989 brush->lbHatch = i;
990 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
991 TRACE("hatched brush %d, ret=%d\n",
992 i, retval);
993 if (!retval) break;
995 SEGPTR_FREE(brush);
996 break;
998 default:
999 WARN("(%d): Invalid type\n", nObjType );
1000 break;
1002 return retval;
1006 /***********************************************************************
1007 * EnumObjects (GDI32.89)
1009 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
1010 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
1012 /* Solid colors to enumerate */
1013 static const COLORREF solid_colors[] =
1014 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1015 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1016 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1017 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1018 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1019 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1020 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1021 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1024 INT i, retval = 0;
1025 LOGPEN pen;
1026 LOGBRUSH brush;
1028 TRACE("%04x %d %08lx %08lx\n",
1029 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
1030 switch(nObjType)
1032 case OBJ_PEN:
1033 /* Enumerate solid pens */
1034 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1036 pen.lopnStyle = PS_SOLID;
1037 pen.lopnWidth.x = 1;
1038 pen.lopnWidth.y = 0;
1039 pen.lopnColor = solid_colors[i];
1040 retval = lpEnumFunc( &pen, lParam );
1041 TRACE("solid pen %08lx, ret=%d\n",
1042 solid_colors[i], retval);
1043 if (!retval) break;
1045 break;
1047 case OBJ_BRUSH:
1048 /* Enumerate solid brushes */
1049 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1051 brush.lbStyle = BS_SOLID;
1052 brush.lbColor = solid_colors[i];
1053 brush.lbHatch = 0;
1054 retval = lpEnumFunc( &brush, lParam );
1055 TRACE("solid brush %08lx, ret=%d\n",
1056 solid_colors[i], retval);
1057 if (!retval) break;
1060 /* Now enumerate hatched brushes */
1061 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1063 brush.lbStyle = BS_HATCHED;
1064 brush.lbColor = RGB(0,0,0);
1065 brush.lbHatch = i;
1066 retval = lpEnumFunc( &brush, lParam );
1067 TRACE("hatched brush %d, ret=%d\n",
1068 i, retval);
1069 if (!retval) break;
1071 break;
1073 default:
1074 /* FIXME: implement Win32 types */
1075 WARN("(%d): Invalid type\n", nObjType );
1076 break;
1078 return retval;
1082 /***********************************************************************
1083 * IsGDIObject (GDI.462)
1085 * returns type of object if valid (W95 system programming secrets p. 264-5)
1087 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
1089 UINT16 magic = 0;
1091 GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1092 if (object)
1094 magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1095 GDI_ReleaseObj( handle );
1097 return magic;
1101 /***********************************************************************
1102 * SetObjectOwner16 (GDI.461)
1104 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1106 /* Nothing to do */
1110 /***********************************************************************
1111 * SetObjectOwner (GDI32.386)
1113 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1115 /* Nothing to do */
1119 /***********************************************************************
1120 * MakeObjectPrivate (GDI.463)
1122 * What does that mean ?
1123 * Some little docu can be found in "Undocumented Windows",
1124 * but this is basically useless.
1125 * At least we know that this flags the GDI object's wMagic
1126 * with 0x2000 (OBJECT_PRIVATE), so we just do it.
1127 * But Wine doesn't react on that yet.
1129 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1131 GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1132 if (!ptr)
1134 ERR("invalid GDI object %04x !\n", handle);
1135 return;
1137 ptr->wMagic |= OBJECT_PRIVATE;
1138 GDI_ReleaseObj( handle );
1142 /***********************************************************************
1143 * GdiFlush (GDI32.128)
1145 BOOL WINAPI GdiFlush(void)
1147 return TRUE; /* FIXME */
1151 /***********************************************************************
1152 * GdiGetBatchLimit (GDI32.129)
1154 DWORD WINAPI GdiGetBatchLimit(void)
1156 return 1; /* FIXME */
1160 /***********************************************************************
1161 * GdiSetBatchLimit (GDI32.139)
1163 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1165 return 1; /* FIXME */
1169 /***********************************************************************
1170 * GdiSeeGdiDo (GDI.452)
1172 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1173 WORD wParam3 )
1175 switch (wReqType)
1177 case 0x0001: /* LocalAlloc */
1178 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1179 case 0x0002: /* LocalFree */
1180 return LOCAL_Free( GDI_HeapSel, wParam1 );
1181 case 0x0003: /* LocalCompact */
1182 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1183 case 0x0103: /* LocalHeap */
1184 return GDI_HeapSel;
1185 default:
1186 WARN("(wReqType=%04x): Unknown\n", wReqType);
1187 return (DWORD)-1;
1191 /***********************************************************************
1192 * GdiSignalProc (GDI.610)
1194 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1195 DWORD dwFlags, HMODULE16 hModule )
1197 return 0;
1200 /***********************************************************************
1201 * FinalGdiInit16 (GDI.405)
1203 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1207 /***********************************************************************
1208 * GdiFreeResources (GDI.609)
1210 WORD WINAPI GdiFreeResources16( DWORD reserve )
1212 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1213 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1216 /***********************************************************************
1217 * MulDiv16 (GDI.128)
1219 INT16 WINAPI MulDiv16(
1220 INT16 nMultiplicand,
1221 INT16 nMultiplier,
1222 INT16 nDivisor)
1224 INT ret;
1225 if (!nDivisor) return -32768;
1226 /* We want to deal with a positive divisor to simplify the logic. */
1227 if (nDivisor < 0)
1229 nMultiplicand = - nMultiplicand;
1230 nDivisor = -nDivisor;
1232 /* If the result is positive, we "add" to round. else,
1233 * we subtract to round. */
1234 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1235 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1236 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1237 else
1238 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1239 if ((ret > 32767) || (ret < -32767)) return -32768;
1240 return (INT16) ret;
1244 /*******************************************************************
1245 * GetColorAdjustment [GDI32.164]
1249 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1251 FIXME("GetColorAdjustment, stub\n");
1252 return 0;
1255 /*******************************************************************
1256 * GetMiterLimit [GDI32.201]
1260 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1262 FIXME("GetMiterLimit, stub\n");
1263 return 0;
1266 /*******************************************************************
1267 * SetMiterLimit [GDI32.325]
1271 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1273 FIXME("SetMiterLimit, stub\n");
1274 return 0;
1277 /*******************************************************************
1278 * GdiComment [GDI32.109]
1282 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1284 FIXME("GdiComment, stub\n");
1285 return 0;
1287 /*******************************************************************
1288 * SetColorAdjustment [GDI32.309]
1292 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1294 FIXME("SetColorAdjustment, stub\n");
1295 return 0;