Change the callback declarations to a safer format.
[wine.git] / objects / gdiobj.c
blobe938de84a552b41c7547706506d91447fc977c3e
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"
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 HPALETTE16 hpalette;
326 HINSTANCE16 instance;
328 /* create GDI heap */
329 if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
330 GDI_HeapSel = GlobalHandleToSel16( instance );
332 /* Kill some warnings. */
333 (void)align_OEMFixedFont;
334 (void)align_AnsiFixedFont;
335 (void)align_AnsiVarFont;
336 (void)align_SystemFont;
337 (void)align_DeviceDefaultFont;
338 (void)align_SystemFixedFont;
339 (void)align_DefaultGuiFont;
341 /* TWEAK: Initialize font hints */
342 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
343 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
344 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
345 ReadFontInformation("System", &SystemFont, 0, 0, 0, 0, 0);
346 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
347 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, 0, 0, 0, 0);
348 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
350 /* Create default palette */
352 /* DR well *this* palette can't be moveable (?) */
353 hpalette = PALETTE_Init();
354 if( !hpalette ) return FALSE;
355 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hpalette );
357 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
358 return TRUE;
361 #define FIRST_LARGE_HANDLE 16
362 #define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
363 static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
364 static int next_large_handle;
366 /***********************************************************************
367 * alloc_large_heap
369 * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
371 inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
373 int i;
374 GDIOBJHDR *obj;
376 for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
377 if (!large_handles[i]) goto found;
378 for (i = 0; i <= next_large_handle; i++)
379 if (!large_handles[i]) goto found;
380 *handle = 0;
381 return NULL;
383 found:
384 if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
386 large_handles[i] = obj;
387 *handle = (i + FIRST_LARGE_HANDLE) << 2;
388 next_large_handle = i;
390 return obj;
394 /***********************************************************************
395 * GDI_AllocObject
397 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
399 static DWORD count = 0;
400 GDIOBJHDR *obj;
402 _EnterSysLevel( &GDI_level );
403 switch(magic)
405 /* allocate DCs on the larger heap */
406 case DC_MAGIC:
407 case DISABLED_DC_MAGIC:
408 case META_DC_MAGIC:
409 case METAFILE_MAGIC:
410 case METAFILE_DC_MAGIC:
411 case ENHMETAFILE_MAGIC:
412 case ENHMETAFILE_DC_MAGIC:
413 if (!(obj = alloc_large_heap( size, handle ))) goto error;
414 break;
415 default:
416 if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
417 assert( *handle & 2 );
418 obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
419 break;
422 obj->hNext = 0;
423 obj->wMagic = magic|OBJECT_NOSYSTEM;
424 obj->dwCount = ++count;
426 TRACE_SEC( *handle, "enter" );
427 return obj;
429 error:
430 _LeaveSysLevel( &GDI_level );
431 *handle = 0;
432 return NULL;
436 /***********************************************************************
437 * GDI_ReallocObject
439 * The object ptr must have been obtained with GDI_GetObjPtr.
440 * The new pointer must be released with GDI_ReleaseObj.
442 void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
444 HGDIOBJ new_handle;
446 assert( handle & 2 ); /* no realloc for large handles */
447 LOCAL_Unlock( GDI_HeapSel, handle );
448 if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
450 TRACE_SEC( handle, "leave" );
451 _LeaveSysLevel( &GDI_level );
452 return NULL;
454 assert( new_handle == handle ); /* moveable handle cannot change */
455 return LOCAL_Lock( GDI_HeapSel, handle );
459 /***********************************************************************
460 * GDI_FreeObject
462 BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
464 GDIOBJHDR *object = ptr;
466 /* can't free stock objects */
467 if (handle < FIRST_STOCK_HANDLE)
469 object->wMagic = 0; /* Mark it as invalid */
470 if (handle & 2) /* GDI heap handle */
472 LOCAL_Unlock( GDI_HeapSel, handle );
473 LOCAL_Free( GDI_HeapSel, handle );
475 else /* large heap handle */
477 int i = (handle >> 2) - FIRST_LARGE_HANDLE;
478 if (i >= 0 && large_handles[i])
480 HeapFree( GetProcessHeap(), 0, large_handles[i] );
481 large_handles[i] = NULL;
485 TRACE_SEC( handle, "leave" );
486 _LeaveSysLevel( &GDI_level );
487 return TRUE;
491 /***********************************************************************
492 * GDI_GetObjPtr
494 * Return a pointer to the GDI object associated to the handle.
495 * Return NULL if the object has the wrong magic number.
496 * The object must be released with GDI_ReleaseObj.
498 void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
500 GDIOBJHDR *ptr = NULL;
502 _EnterSysLevel( &GDI_level );
504 if (handle >= FIRST_STOCK_HANDLE)
506 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
507 if (ptr && (magic != MAGIC_DONTCARE)
508 && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
510 else if (handle & 2) /* GDI heap handle */
512 ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
513 if (ptr &&
514 (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic))
516 LOCAL_Unlock( GDI_HeapSel, handle );
517 ptr = NULL;
520 else /* large heap handle */
522 int i = (handle >> 2) - FIRST_LARGE_HANDLE;
523 if (i >= 0)
525 ptr = large_handles[i];
526 if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
530 if (!ptr)
532 _LeaveSysLevel( &GDI_level );
533 SetLastError( ERROR_INVALID_HANDLE );
535 else TRACE_SEC( handle, "enter" );
537 return ptr;
541 /***********************************************************************
542 * GDI_ReleaseObj
545 void GDI_ReleaseObj( HGDIOBJ handle )
547 if (handle < FIRST_STOCK_HANDLE && (handle & 2)) LOCAL_Unlock( GDI_HeapSel, handle );
548 TRACE_SEC( handle, "leave" );
549 _LeaveSysLevel( &GDI_level );
553 /***********************************************************************
554 * DeleteObject16 (GDI.69)
556 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
558 return DeleteObject( obj );
562 /***********************************************************************
563 * DeleteObject (GDI32.70)
565 BOOL WINAPI DeleteObject( HGDIOBJ obj )
567 /* Check if object is valid */
569 GDIOBJHDR * header;
570 if (HIWORD(obj)) return FALSE;
571 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE)) {
572 TRACE("Preserving Stock object %04x\n", obj );
573 /* NOTE: No GDI_Release is necessary */
574 return TRUE;
576 if (obj == hPseudoStockBitmap) return TRUE;
577 if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
579 if (!(header->wMagic & OBJECT_NOSYSTEM)
580 && (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
582 TRACE("Preserving system object %04x\n", obj);
583 GDI_ReleaseObj( obj );
584 return TRUE;
587 TRACE("%04x\n", obj );
589 /* Delete object */
591 switch(GDIMAGIC(header->wMagic))
593 case PEN_MAGIC: return GDI_FreeObject( obj, header );
594 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
595 case FONT_MAGIC: return GDI_FreeObject( obj, header );
596 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
597 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
598 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
599 case DC_MAGIC:
600 GDI_ReleaseObj( obj );
601 return DeleteDC(obj);
602 case 0 :
603 WARN("Already deleted\n");
604 break;
605 default:
606 WARN("Unknown magic number (%d)\n",GDIMAGIC(header->wMagic));
608 GDI_ReleaseObj( obj );
609 return FALSE;
612 /***********************************************************************
613 * GetStockObject16 (GDI.87)
615 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
617 return (HGDIOBJ16)GetStockObject( obj );
621 /***********************************************************************
622 * GetStockObject (GDI32.220)
624 HGDIOBJ WINAPI GetStockObject( INT obj )
626 HGDIOBJ ret;
627 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
628 if (!StockObjects[obj]) return 0;
629 ret = (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
630 TRACE("returning %4x\n", ret );
631 return ret;
635 /***********************************************************************
636 * GetObject16 (GDI.82)
638 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
640 GDIOBJHDR * ptr;
641 INT16 result = 0;
642 TRACE("%04x %d %p\n", handle, count, buffer );
643 if (!count) return 0;
645 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
647 switch(GDIMAGIC(ptr->wMagic))
649 case PEN_MAGIC:
650 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
651 break;
652 case BRUSH_MAGIC:
653 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
654 break;
655 case BITMAP_MAGIC:
656 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
657 break;
658 case FONT_MAGIC:
659 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
662 * Fix the LOGFONT structure for the stock fonts
664 if ( (handle >= FIRST_STOCK_HANDLE) &&
665 (handle <= LAST_STOCK_HANDLE) )
666 FixStockFontSize16(handle, count, buffer);
667 break;
668 case PALETTE_MAGIC:
669 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
670 break;
672 GDI_ReleaseObj( handle );
673 return result;
677 /***********************************************************************
678 * GetObjectA (GDI32.204)
680 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
682 GDIOBJHDR * ptr;
683 INT result = 0;
684 TRACE("%08x %d %p\n", handle, count, buffer );
685 if (!count) return 0;
687 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
689 switch(GDIMAGIC(ptr->wMagic))
691 case PEN_MAGIC:
692 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
693 break;
694 case BRUSH_MAGIC:
695 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
696 break;
697 case BITMAP_MAGIC:
698 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
699 break;
700 case FONT_MAGIC:
701 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
704 * Fix the LOGFONT structure for the stock fonts
706 if ( (handle >= FIRST_STOCK_HANDLE) &&
707 (handle <= LAST_STOCK_HANDLE) )
708 FixStockFontSizeA(handle, count, buffer);
709 break;
710 case PALETTE_MAGIC:
711 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
712 break;
714 case REGION_MAGIC:
715 case DC_MAGIC:
716 case DISABLED_DC_MAGIC:
717 case META_DC_MAGIC:
718 case METAFILE_MAGIC:
719 case METAFILE_DC_MAGIC:
720 case ENHMETAFILE_MAGIC:
721 case ENHMETAFILE_DC_MAGIC:
722 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
723 break;
725 default:
726 ERR("Invalid GDI Magic %04x\n", GDIMAGIC(ptr->wMagic));
727 break;
729 GDI_ReleaseObj( handle );
730 return result;
733 /***********************************************************************
734 * GetObjectW (GDI32.206)
736 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
738 GDIOBJHDR * ptr;
739 INT result = 0;
740 TRACE("%08x %d %p\n", handle, count, buffer );
741 if (!count) return 0;
743 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
745 switch(GDIMAGIC(ptr->wMagic))
747 case PEN_MAGIC:
748 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
749 break;
750 case BRUSH_MAGIC:
751 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
752 break;
753 case BITMAP_MAGIC:
754 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
755 break;
756 case FONT_MAGIC:
757 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
760 * Fix the LOGFONT structure for the stock fonts
762 if ( (handle >= FIRST_STOCK_HANDLE) &&
763 (handle <= LAST_STOCK_HANDLE) )
764 FixStockFontSizeW(handle, count, buffer);
765 break;
766 case PALETTE_MAGIC:
767 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
768 break;
769 default:
770 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
771 break;
773 GDI_ReleaseObj( handle );
774 return result;
777 /***********************************************************************
778 * GetObjectType (GDI32.205)
780 DWORD WINAPI GetObjectType( HANDLE handle )
782 GDIOBJHDR * ptr;
783 INT result = 0;
784 TRACE("%08x\n", handle );
786 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
788 switch(GDIMAGIC(ptr->wMagic))
790 case PEN_MAGIC:
791 result = OBJ_PEN;
792 break;
793 case BRUSH_MAGIC:
794 result = OBJ_BRUSH;
795 break;
796 case BITMAP_MAGIC:
797 result = OBJ_BITMAP;
798 break;
799 case FONT_MAGIC:
800 result = OBJ_FONT;
801 break;
802 case PALETTE_MAGIC:
803 result = OBJ_PAL;
804 break;
805 case REGION_MAGIC:
806 result = OBJ_REGION;
807 break;
808 case DC_MAGIC:
809 result = OBJ_DC;
810 break;
811 case META_DC_MAGIC:
812 result = OBJ_METADC;
813 break;
814 case METAFILE_MAGIC:
815 result = OBJ_METAFILE;
816 break;
817 case METAFILE_DC_MAGIC:
818 result = OBJ_METADC;
819 break;
820 case ENHMETAFILE_MAGIC:
821 result = OBJ_ENHMETAFILE;
822 break;
823 case ENHMETAFILE_DC_MAGIC:
824 result = OBJ_ENHMETADC;
825 break;
826 default:
827 FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
828 break;
830 GDI_ReleaseObj( handle );
831 return result;
834 /***********************************************************************
835 * GetCurrentObject (GDI32.166)
837 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
839 HANDLE ret = 0;
840 DC * dc = DC_GetDCPtr( hdc );
842 if (dc)
844 switch (type) {
845 case OBJ_PEN: ret = dc->hPen; break;
846 case OBJ_BRUSH: ret = dc->hBrush; break;
847 case OBJ_PAL: ret = dc->hPalette; break;
848 case OBJ_FONT: ret = dc->hFont; break;
849 case OBJ_BITMAP: ret = dc->hBitmap; break;
850 default:
851 /* the SDK only mentions those above */
852 FIXME("(%08x,%d): unknown type.\n",hdc,type);
853 break;
855 GDI_ReleaseObj( hdc );
857 return ret;
861 /***********************************************************************
862 * SelectObject16 (GDI.45)
864 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
866 return (HGDIOBJ16)SelectObject( hdc, handle );
870 /***********************************************************************
871 * SelectObject (GDI32.299)
873 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
875 HGDIOBJ ret = 0;
876 DC * dc = DC_GetDCUpdate( hdc );
877 if (!dc) return 0;
878 TRACE("hdc=%04x %04x\n", hdc, handle );
879 if (dc->funcs->pSelectObject)
880 ret = dc->funcs->pSelectObject( dc, handle );
881 GDI_ReleaseObj( hdc );
882 return ret;
886 /***********************************************************************
887 * UnrealizeObject16 (GDI.150)
889 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
891 return UnrealizeObject( obj );
895 /***********************************************************************
896 * UnrealizeObject (GDI32.358)
898 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
900 BOOL result = TRUE;
901 /* Check if object is valid */
903 GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
904 if (!header) return FALSE;
906 TRACE("%04x\n", obj );
908 /* Unrealize object */
910 switch(GDIMAGIC(header->wMagic))
912 case PALETTE_MAGIC:
913 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
914 break;
916 case BRUSH_MAGIC:
917 /* Windows resets the brush origin. We don't need to. */
918 break;
920 GDI_ReleaseObj( obj );
921 return result;
925 /***********************************************************************
926 * EnumObjects16 (GDI.71)
928 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
929 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
931 /* Solid colors to enumerate */
932 static const COLORREF solid_colors[] =
933 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
934 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
935 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
936 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
937 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
938 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
939 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
940 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
943 INT16 i, retval = 0;
944 LOGPEN16 *pen;
945 LOGBRUSH16 *brush = NULL;
947 TRACE("%04x %d %08lx %08lx\n",
948 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
949 switch(nObjType)
951 case OBJ_PEN:
952 /* Enumerate solid pens */
953 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
954 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
956 pen->lopnStyle = PS_SOLID;
957 pen->lopnWidth.x = 1;
958 pen->lopnWidth.y = 0;
959 pen->lopnColor = solid_colors[i];
960 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
961 TRACE("solid pen %08lx, ret=%d\n",
962 solid_colors[i], retval);
963 if (!retval) break;
965 SEGPTR_FREE(pen);
966 break;
968 case OBJ_BRUSH:
969 /* Enumerate solid brushes */
970 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
971 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
973 brush->lbStyle = BS_SOLID;
974 brush->lbColor = solid_colors[i];
975 brush->lbHatch = 0;
976 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
977 TRACE("solid brush %08lx, ret=%d\n",
978 solid_colors[i], retval);
979 if (!retval) break;
982 /* Now enumerate hatched brushes */
983 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
985 brush->lbStyle = BS_HATCHED;
986 brush->lbColor = RGB(0,0,0);
987 brush->lbHatch = i;
988 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
989 TRACE("hatched brush %d, ret=%d\n",
990 i, retval);
991 if (!retval) break;
993 SEGPTR_FREE(brush);
994 break;
996 default:
997 WARN("(%d): Invalid type\n", nObjType );
998 break;
1000 return retval;
1004 /***********************************************************************
1005 * EnumObjects (GDI32.89)
1007 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
1008 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
1010 /* Solid colors to enumerate */
1011 static const COLORREF solid_colors[] =
1012 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1013 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1014 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1015 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1016 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1017 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1018 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1019 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1022 INT i, retval = 0;
1023 LOGPEN pen;
1024 LOGBRUSH brush;
1026 TRACE("%04x %d %08lx %08lx\n",
1027 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
1028 switch(nObjType)
1030 case OBJ_PEN:
1031 /* Enumerate solid pens */
1032 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1034 pen.lopnStyle = PS_SOLID;
1035 pen.lopnWidth.x = 1;
1036 pen.lopnWidth.y = 0;
1037 pen.lopnColor = solid_colors[i];
1038 retval = lpEnumFunc( &pen, lParam );
1039 TRACE("solid pen %08lx, ret=%d\n",
1040 solid_colors[i], retval);
1041 if (!retval) break;
1043 break;
1045 case OBJ_BRUSH:
1046 /* Enumerate solid brushes */
1047 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
1049 brush.lbStyle = BS_SOLID;
1050 brush.lbColor = solid_colors[i];
1051 brush.lbHatch = 0;
1052 retval = lpEnumFunc( &brush, lParam );
1053 TRACE("solid brush %08lx, ret=%d\n",
1054 solid_colors[i], retval);
1055 if (!retval) break;
1058 /* Now enumerate hatched brushes */
1059 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1061 brush.lbStyle = BS_HATCHED;
1062 brush.lbColor = RGB(0,0,0);
1063 brush.lbHatch = i;
1064 retval = lpEnumFunc( &brush, lParam );
1065 TRACE("hatched brush %d, ret=%d\n",
1066 i, retval);
1067 if (!retval) break;
1069 break;
1071 default:
1072 /* FIXME: implement Win32 types */
1073 WARN("(%d): Invalid type\n", nObjType );
1074 break;
1076 return retval;
1080 /***********************************************************************
1081 * IsGDIObject (GDI.462)
1083 * returns type of object if valid (W95 system programming secrets p. 264-5)
1085 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
1087 UINT16 magic = 0;
1089 GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1090 if (object)
1092 magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
1093 GDI_ReleaseObj( handle );
1095 return magic;
1099 /***********************************************************************
1100 * SetObjectOwner16 (GDI.461)
1102 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1104 /* Nothing to do */
1108 /***********************************************************************
1109 * SetObjectOwner (GDI32.386)
1111 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1113 /* Nothing to do */
1117 /***********************************************************************
1118 * MakeObjectPrivate (GDI.463)
1120 * What does that mean ?
1121 * Some little docu can be found in "Undocumented Windows",
1122 * but this is basically useless.
1123 * At least we know that this flags the GDI object's wMagic
1124 * with 0x2000 (OBJECT_PRIVATE), so we just do it.
1125 * But Wine doesn't react on that yet.
1127 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1129 GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1130 if (!ptr)
1132 ERR("invalid GDI object %04x !\n", handle);
1133 return;
1135 ptr->wMagic |= OBJECT_PRIVATE;
1136 GDI_ReleaseObj( handle );
1140 /***********************************************************************
1141 * GdiFlush (GDI32.128)
1143 BOOL WINAPI GdiFlush(void)
1145 return TRUE; /* FIXME */
1149 /***********************************************************************
1150 * GdiGetBatchLimit (GDI32.129)
1152 DWORD WINAPI GdiGetBatchLimit(void)
1154 return 1; /* FIXME */
1158 /***********************************************************************
1159 * GdiSetBatchLimit (GDI32.139)
1161 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1163 return 1; /* FIXME */
1167 /***********************************************************************
1168 * GdiSeeGdiDo (GDI.452)
1170 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1171 WORD wParam3 )
1173 switch (wReqType)
1175 case 0x0001: /* LocalAlloc */
1176 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1177 case 0x0002: /* LocalFree */
1178 return LOCAL_Free( GDI_HeapSel, wParam1 );
1179 case 0x0003: /* LocalCompact */
1180 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1181 case 0x0103: /* LocalHeap */
1182 return GDI_HeapSel;
1183 default:
1184 WARN("(wReqType=%04x): Unknown\n", wReqType);
1185 return (DWORD)-1;
1189 /***********************************************************************
1190 * GdiSignalProc (GDI.610)
1192 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1193 DWORD dwFlags, HMODULE16 hModule )
1195 return 0;
1198 /***********************************************************************
1199 * FinalGdiInit16 (GDI.405)
1201 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1205 /***********************************************************************
1206 * GdiFreeResources (GDI.609)
1208 WORD WINAPI GdiFreeResources16( DWORD reserve )
1210 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1211 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1214 /***********************************************************************
1215 * MulDiv16 (GDI.128)
1217 INT16 WINAPI MulDiv16(
1218 INT16 nMultiplicand,
1219 INT16 nMultiplier,
1220 INT16 nDivisor)
1222 INT ret;
1223 if (!nDivisor) return -32768;
1224 /* We want to deal with a positive divisor to simplify the logic. */
1225 if (nDivisor < 0)
1227 nMultiplicand = - nMultiplicand;
1228 nDivisor = -nDivisor;
1230 /* If the result is positive, we "add" to round. else,
1231 * we subtract to round. */
1232 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1233 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1234 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1235 else
1236 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1237 if ((ret > 32767) || (ret < -32767)) return -32768;
1238 return (INT16) ret;
1242 /*******************************************************************
1243 * GetColorAdjustment [GDI32.164]
1247 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1249 FIXME("GetColorAdjustment, stub\n");
1250 return 0;
1253 /*******************************************************************
1254 * GetMiterLimit [GDI32.201]
1258 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1260 FIXME("GetMiterLimit, stub\n");
1261 return 0;
1264 /*******************************************************************
1265 * SetMiterLimit [GDI32.325]
1269 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1271 FIXME("SetMiterLimit, stub\n");
1272 return 0;
1275 /*******************************************************************
1276 * GdiComment [GDI32.109]
1280 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1282 FIXME("GdiComment, stub\n");
1283 return 0;
1285 /*******************************************************************
1286 * SetColorAdjustment [GDI32.309]
1290 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1292 FIXME("SetColorAdjustment, stub\n");
1293 return 0;