Now relying on exception codes to know when debugger is entered for a
[wine.git] / objects / gdiobj.c
blobe930c5a56430ab9a9506784224c2d0c1c83fcbb6
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "config.h"
9 #ifndef X_DISPLAY_MISSING
10 #include "x11drv.h"
11 #else /* !defined(X_DISPLAY_MISSING) */
12 #include "ttydrv.h"
13 #endif /* !defined(X_DISPLAY_MISSING */
15 #include <stdlib.h>
16 #include <stdio.h>
18 #include "bitmap.h"
19 #include "brush.h"
20 #include "dc.h"
21 #include "font.h"
22 #include "heap.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"
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "winuser.h"
34 DEFAULT_DEBUG_CHANNEL(gdi)
36 /**********************************************************************/
38 GDI_DRIVER *GDI_Driver = NULL;
40 /***********************************************************************
41 * GDI stock objects
44 static BRUSHOBJ WhiteBrush =
46 { 0, BRUSH_MAGIC, 1 }, /* header */
47 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
50 static BRUSHOBJ LtGrayBrush =
52 { 0, BRUSH_MAGIC, 1 }, /* header */
53 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
54 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
57 static BRUSHOBJ GrayBrush =
59 { 0, BRUSH_MAGIC, 1 }, /* header */
60 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
61 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
64 static BRUSHOBJ DkGrayBrush =
66 { 0, BRUSH_MAGIC, 1 }, /* header */
67 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
68 /* NB_HATCH_STYLES is an index into HatchBrushes */
69 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
72 static BRUSHOBJ BlackBrush =
74 { 0, BRUSH_MAGIC, 1 }, /* header */
75 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
78 static BRUSHOBJ NullBrush =
80 { 0, BRUSH_MAGIC, 1 }, /* header */
81 { BS_NULL, 0, 0 } /* logbrush */
84 static PENOBJ WhitePen =
86 { 0, PEN_MAGIC, 1 }, /* header */
87 { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
90 static PENOBJ BlackPen =
92 { 0, PEN_MAGIC, 1 }, /* header */
93 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
96 static PENOBJ NullPen =
98 { 0, PEN_MAGIC, 1 }, /* header */
99 { PS_NULL, { 1, 0 }, 0 } /* logpen */
102 static FONTOBJ OEMFixedFont =
104 { 0, FONT_MAGIC, 1 }, /* header */
105 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
106 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
108 /* Filler to make the location counter dword aligned again. This is necessary
109 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
110 segment, and (c) Solaris assembler is stupid. */
111 static UINT16 align_OEMFixedFont = 1;
113 static FONTOBJ AnsiFixedFont =
115 { 0, FONT_MAGIC, 1 }, /* header */
116 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
117 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
119 static UINT16 align_AnsiFixedFont = 1;
121 static FONTOBJ AnsiVarFont =
123 { 0, FONT_MAGIC, 1 }, /* header */
124 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
125 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
127 static UINT16 align_AnsiVarFont = 1;
129 static FONTOBJ SystemFont =
131 { 0, FONT_MAGIC, 1 },
132 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
133 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
135 static UINT16 align_SystemFont = 1;
137 static FONTOBJ DeviceDefaultFont =
139 { 0, FONT_MAGIC, 1 }, /* header */
140 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
141 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
143 static UINT16 align_DeviceDefaultFont = 1;
145 static FONTOBJ SystemFixedFont =
147 { 0, FONT_MAGIC, 1 }, /* header */
148 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
149 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
151 static UINT16 align_SystemFixedFont = 1;
153 /* FIXME: Is this correct? */
154 static FONTOBJ DefaultGuiFont =
156 { 0, FONT_MAGIC, 1 }, /* header */
157 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
158 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
160 static UINT16 align_DefaultGuiFont = 1;
163 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
165 (GDIOBJHDR *) &WhiteBrush,
166 (GDIOBJHDR *) &LtGrayBrush,
167 (GDIOBJHDR *) &GrayBrush,
168 (GDIOBJHDR *) &DkGrayBrush,
169 (GDIOBJHDR *) &BlackBrush,
170 (GDIOBJHDR *) &NullBrush,
171 (GDIOBJHDR *) &WhitePen,
172 (GDIOBJHDR *) &BlackPen,
173 (GDIOBJHDR *) &NullPen,
174 NULL,
175 (GDIOBJHDR *) &OEMFixedFont,
176 (GDIOBJHDR *) &AnsiFixedFont,
177 (GDIOBJHDR *) &AnsiVarFont,
178 (GDIOBJHDR *) &SystemFont,
179 (GDIOBJHDR *) &DeviceDefaultFont,
180 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
181 (GDIOBJHDR *) &SystemFixedFont,
182 (GDIOBJHDR *) &DefaultGuiFont
185 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
187 /******************************************************************************
189 * void ReadFontInformation(
190 * char const *fontName,
191 * FONTOBJ *font,
192 * int defHeight,
193 * int defBold,
194 * int defItalic,
195 * int defUnderline,
196 * int defStrikeOut )
198 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
199 * section for entries containing fontName.Height, fontName.Bold, etc.,
200 * where fontName is the name specified in the call (e.g., "System"). It
201 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
202 * the first character in the boolean attributes (bold, italic, and
203 * underline).
204 *****************************************************************************/
206 static void ReadFontInformation(
207 char const *fontName,
208 FONTOBJ *font,
209 int defHeight,
210 int defBold,
211 int defItalic,
212 int defUnderline,
213 int defStrikeOut )
215 char key[256];
217 /* In order for the stock fonts to be independent of
218 * mapping mode, the height (& width) must be 0
220 sprintf(key, "%s.Height", fontName);
221 font->logfont.lfHeight =
222 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
224 sprintf(key, "%s.Bold", fontName);
225 font->logfont.lfWeight =
226 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
227 FW_BOLD : FW_NORMAL;
229 sprintf(key, "%s.Italic", fontName);
230 font->logfont.lfItalic =
231 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
233 sprintf(key, "%s.Underline", fontName);
234 font->logfont.lfUnderline =
235 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
237 sprintf(key, "%s.StrikeOut", fontName);
238 font->logfont.lfStrikeOut =
239 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
241 return;
244 /***********************************************************************
245 * Because the stock fonts have their structure initialized with
246 * a height of 0 to keep them independent of mapping mode, simply
247 * returning the LOGFONT as is will not work correctly.
248 * These "FixStockFontSizeXXX()" methods will get the correct
249 * size for the fonts.
251 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
253 HDC hdc;
254 HFONT hOldFont;
256 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
258 hOldFont = (HFONT)SelectObject(hdc, handle);
260 GetTextMetricsA(hdc, lptm);
262 SelectObject(hdc, hOldFont);
264 DeleteDC(hdc);
267 static inline void FixStockFontSize16(
268 HFONT handle,
269 INT16 count,
270 LPVOID buffer)
272 TEXTMETRICA tm;
273 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
276 * Was the lfHeight field copied (it's the first field)?
277 * If it was and it was null, replace the height.
279 if ( (count >= 2*sizeof(INT16)) &&
280 (pLogFont->lfHeight == 0) )
282 GetFontMetrics(handle, &tm);
284 pLogFont->lfHeight = tm.tmHeight;
285 pLogFont->lfWidth = tm.tmAveCharWidth;
289 static inline void FixStockFontSizeA(
290 HFONT handle,
291 INT count,
292 LPVOID buffer)
294 TEXTMETRICA tm;
295 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
298 * Was the lfHeight field copied (it's the first field)?
299 * If it was and it was null, replace the height.
301 if ( (count >= 2*sizeof(INT)) &&
302 (pLogFont->lfHeight == 0) )
304 GetFontMetrics(handle, &tm);
306 pLogFont->lfHeight = tm.tmHeight;
307 pLogFont->lfWidth = tm.tmAveCharWidth;
312 * Since the LOGFONTA and LOGFONTW structures are identical up to the
313 * lfHeight member (the one of interest in this case) we simply define
314 * the W version as the A version.
316 #define FixStockFontSizeW FixStockFontSizeA
320 /***********************************************************************
321 * GDI_Init
323 * GDI initialization.
325 BOOL GDI_Init(void)
327 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
329 /* Kill some warnings. */
330 (void)align_OEMFixedFont;
331 (void)align_AnsiFixedFont;
332 (void)align_AnsiVarFont;
333 (void)align_SystemFont;
334 (void)align_DeviceDefaultFont;
335 (void)align_SystemFixedFont;
336 (void)align_DefaultGuiFont;
338 /* TWEAK: Initialize font hints */
339 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
340 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
341 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
342 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
343 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
344 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
345 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
347 /* Initialize drivers */
349 #ifndef X_DISPLAY_MISSING
350 GDI_Driver = &X11DRV_GDI_Driver;
351 #else /* !defined(X_DISPLAY_MISSING) */
352 GDI_Driver = &TTYDRV_GDI_Driver;
353 #endif /* !defined(X_DISPLAY_MISSING */
355 GDI_Driver->pInitialize();
357 /* Create default palette */
359 /* DR well *this* palette can't be moveable (?) */
361 HPALETTE16 hpalette = PALETTE_Init();
362 if( !hpalette )
363 return FALSE;
364 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
367 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
368 return TRUE;
372 /***********************************************************************
373 * GDI_AllocObject
375 HGDIOBJ GDI_AllocObject( WORD size, WORD magic )
377 static DWORD count = 0;
378 GDIOBJHDR * obj;
379 HGDIOBJ16 handle;
380 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
381 handle = GDI_HEAP_ALLOC( size );
382 else
383 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
384 if (!handle) return 0;
385 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
386 obj->hNext = 0;
387 obj->wMagic = magic;
388 obj->dwCount = ++count;
389 GDI_HEAP_UNLOCK( handle );
390 return handle;
394 /***********************************************************************
395 * GDI_FreeObject
397 BOOL GDI_FreeObject( HGDIOBJ handle )
399 GDIOBJHDR * object;
401 /* Can't free stock objects */
402 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
403 return TRUE;
405 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
406 if (!object) return FALSE;
407 object->wMagic = 0; /* Mark it as invalid */
409 /* Free object */
411 GDI_HEAP_FREE( handle );
412 return TRUE;
415 /***********************************************************************
416 * GDI_GetObjPtr
418 * Return a pointer to the GDI object associated to the handle.
419 * Return NULL if the object has the wrong magic number.
420 * Movable GDI objects are locked in memory: it is up to the caller to unlock
421 * it after the caller is done with the pointer.
423 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
425 GDIOBJHDR * ptr = NULL;
427 if (handle >= FIRST_STOCK_HANDLE)
429 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
431 else
432 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
433 if (!ptr) return NULL;
434 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
436 GDI_HEAP_UNLOCK( handle );
437 return NULL;
439 return ptr;
443 /***********************************************************************
444 * DeleteObject16 (GDI.69)
446 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
448 return DeleteObject( obj );
452 /***********************************************************************
453 * DeleteObject32 (GDI32.70)
455 BOOL WINAPI DeleteObject( HGDIOBJ obj )
457 /* Check if object is valid */
459 GDIOBJHDR * header;
460 if (HIWORD(obj)) return FALSE;
461 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
462 return TRUE;
463 if (obj == hPseudoStockBitmap) return TRUE;
464 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
466 TRACE("%04x\n", obj );
468 /* Delete object */
470 switch(header->wMagic)
472 case PEN_MAGIC: return GDI_FreeObject( obj );
473 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
474 case FONT_MAGIC: return GDI_FreeObject( obj );
475 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
476 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
477 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
478 case DC_MAGIC: return DeleteDC(obj);
479 case 0 :
480 WARN("Already deleted\n");
481 break;
482 default:
483 WARN("Unknown magic number (%d)\n",header->wMagic);
485 return FALSE;
488 /***********************************************************************
489 * GetStockObject16 (GDI.87)
491 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
493 return (HGDIOBJ16)GetStockObject( obj );
497 /***********************************************************************
498 * GetStockObject32 (GDI32.220)
500 HGDIOBJ WINAPI GetStockObject( INT obj )
502 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
503 if (!StockObjects[obj]) return 0;
504 TRACE("returning %d\n",
505 FIRST_STOCK_HANDLE + obj );
506 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
510 /***********************************************************************
511 * GetObject16 (GDI.82)
513 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
515 GDIOBJHDR * ptr;
516 INT16 result = 0;
517 TRACE("%04x %d %p\n", handle, count, buffer );
518 if (!count) return 0;
520 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
522 switch(ptr->wMagic)
524 case PEN_MAGIC:
525 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
526 break;
527 case BRUSH_MAGIC:
528 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
529 break;
530 case BITMAP_MAGIC:
531 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
532 break;
533 case FONT_MAGIC:
534 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
537 * Fix the LOGFONT structure for the stock fonts
539 if ( (handle >= FIRST_STOCK_HANDLE) &&
540 (handle <= LAST_STOCK_HANDLE) )
541 FixStockFontSize16(handle, count, buffer);
542 break;
543 case PALETTE_MAGIC:
544 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
545 break;
547 GDI_HEAP_UNLOCK( handle );
548 return result;
552 /***********************************************************************
553 * GetObject32A (GDI32.204)
555 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
557 GDIOBJHDR * ptr;
558 INT result = 0;
559 TRACE("%08x %d %p\n", handle, count, buffer );
560 if (!count) return 0;
562 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
564 switch(ptr->wMagic)
566 case PEN_MAGIC:
567 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
568 break;
569 case BRUSH_MAGIC:
570 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
571 break;
572 case BITMAP_MAGIC:
573 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
574 break;
575 case FONT_MAGIC:
576 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
579 * Fix the LOGFONT structure for the stock fonts
581 if ( (handle >= FIRST_STOCK_HANDLE) &&
582 (handle <= LAST_STOCK_HANDLE) )
583 FixStockFontSizeA(handle, count, buffer);
584 break;
585 case PALETTE_MAGIC:
586 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
587 break;
589 case REGION_MAGIC:
590 case DC_MAGIC:
591 case DISABLED_DC_MAGIC:
592 case META_DC_MAGIC:
593 case METAFILE_MAGIC:
594 case METAFILE_DC_MAGIC:
595 case ENHMETAFILE_MAGIC:
596 case ENHMETAFILE_DC_MAGIC:
597 FIXME("Magic %04x not implemented\n",
598 ptr->wMagic );
599 break;
601 default:
602 ERR("Invalid GDI Magic %04x\n", ptr->wMagic);
603 return 0;
605 GDI_HEAP_UNLOCK( handle );
606 return result;
609 /***********************************************************************
610 * GetObject32W (GDI32.206)
612 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
614 GDIOBJHDR * ptr;
615 INT result = 0;
616 TRACE("%08x %d %p\n", handle, count, buffer );
617 if (!count) return 0;
619 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
621 switch(ptr->wMagic)
623 case PEN_MAGIC:
624 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
625 break;
626 case BRUSH_MAGIC:
627 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
628 break;
629 case BITMAP_MAGIC:
630 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
631 break;
632 case FONT_MAGIC:
633 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
636 * Fix the LOGFONT structure for the stock fonts
638 if ( (handle >= FIRST_STOCK_HANDLE) &&
639 (handle <= LAST_STOCK_HANDLE) )
640 FixStockFontSizeW(handle, count, buffer);
641 break;
642 case PALETTE_MAGIC:
643 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
644 break;
645 default:
646 FIXME("Magic %04x not implemented\n",
647 ptr->wMagic );
648 break;
650 GDI_HEAP_UNLOCK( handle );
651 return result;
654 /***********************************************************************
655 * GetObjectType (GDI32.205)
657 DWORD WINAPI GetObjectType( HANDLE handle )
659 GDIOBJHDR * ptr;
660 INT result = 0;
661 TRACE("%08x\n", handle );
663 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
665 switch(ptr->wMagic)
667 case PEN_MAGIC:
668 result = OBJ_PEN;
669 break;
670 case BRUSH_MAGIC:
671 result = OBJ_BRUSH;
672 break;
673 case BITMAP_MAGIC:
674 result = OBJ_BITMAP;
675 break;
676 case FONT_MAGIC:
677 result = OBJ_FONT;
678 break;
679 case PALETTE_MAGIC:
680 result = OBJ_PAL;
681 break;
682 case REGION_MAGIC:
683 result = OBJ_REGION;
684 break;
685 case DC_MAGIC:
686 result = OBJ_DC;
687 break;
688 case META_DC_MAGIC:
689 result = OBJ_METADC;
690 break;
691 case METAFILE_MAGIC:
692 result = OBJ_METAFILE;
693 break;
694 case METAFILE_DC_MAGIC:
695 result = OBJ_METADC;
696 break;
697 case ENHMETAFILE_MAGIC:
698 result = OBJ_ENHMETAFILE;
699 break;
700 case ENHMETAFILE_DC_MAGIC:
701 result = OBJ_ENHMETADC;
702 break;
703 default:
704 FIXME("Magic %04x not implemented\n",
705 ptr->wMagic );
706 break;
708 GDI_HEAP_UNLOCK( handle );
709 return result;
712 /***********************************************************************
713 * GetCurrentObject (GDI32.166)
715 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
717 DC * dc = DC_GetDCPtr( hdc );
719 if (!dc)
720 return 0;
721 switch (type) {
722 case OBJ_PEN: return dc->w.hPen;
723 case OBJ_BRUSH: return dc->w.hBrush;
724 case OBJ_PAL: return dc->w.hPalette;
725 case OBJ_FONT: return dc->w.hFont;
726 case OBJ_BITMAP: return dc->w.hBitmap;
727 default:
728 /* the SDK only mentions those above */
729 WARN("(%08x,%d): unknown type.\n",hdc,type);
730 return 0;
735 /***********************************************************************
736 * SelectObject16 (GDI.45)
738 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
740 return (HGDIOBJ16)SelectObject( hdc, handle );
744 /***********************************************************************
745 * SelectObject32 (GDI32.299)
747 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
749 DC * dc = DC_GetDCPtr( hdc );
750 if (!dc || !dc->funcs->pSelectObject) return 0;
751 TRACE("hdc=%04x %04x\n", hdc, handle );
752 return dc->funcs->pSelectObject( dc, handle );
756 /***********************************************************************
757 * UnrealizeObject16 (GDI.150)
759 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
761 return UnrealizeObject( obj );
765 /***********************************************************************
766 * UnrealizeObject (GDI32.358)
768 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
770 BOOL result = TRUE;
771 /* Check if object is valid */
773 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
774 if (!header) return FALSE;
776 TRACE("%04x\n", obj );
778 /* Unrealize object */
780 switch(header->wMagic)
782 case PALETTE_MAGIC:
783 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
784 break;
786 case BRUSH_MAGIC:
787 /* Windows resets the brush origin. We don't need to. */
788 break;
790 GDI_HEAP_UNLOCK( obj );
791 return result;
795 /***********************************************************************
796 * EnumObjects16 (GDI.71)
798 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
799 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
801 /* Solid colors to enumerate */
802 static const COLORREF solid_colors[] =
803 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
804 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
805 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
806 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
807 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
808 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
809 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
810 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
813 INT16 i, retval = 0;
814 LOGPEN16 *pen;
815 LOGBRUSH16 *brush = NULL;
817 TRACE("%04x %d %08lx %08lx\n",
818 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
819 switch(nObjType)
821 case OBJ_PEN:
822 /* Enumerate solid pens */
823 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
824 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
826 pen->lopnStyle = PS_SOLID;
827 pen->lopnWidth.x = 1;
828 pen->lopnWidth.y = 0;
829 pen->lopnColor = solid_colors[i];
830 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
831 TRACE("solid pen %08lx, ret=%d\n",
832 solid_colors[i], retval);
833 if (!retval) break;
835 SEGPTR_FREE(pen);
836 break;
838 case OBJ_BRUSH:
839 /* Enumerate solid brushes */
840 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
841 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
843 brush->lbStyle = BS_SOLID;
844 brush->lbColor = solid_colors[i];
845 brush->lbHatch = 0;
846 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
847 TRACE("solid brush %08lx, ret=%d\n",
848 solid_colors[i], retval);
849 if (!retval) break;
852 /* Now enumerate hatched brushes */
853 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
855 brush->lbStyle = BS_HATCHED;
856 brush->lbColor = RGB(0,0,0);
857 brush->lbHatch = i;
858 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
859 TRACE("hatched brush %d, ret=%d\n",
860 i, retval);
861 if (!retval) break;
863 SEGPTR_FREE(brush);
864 break;
866 default:
867 WARN("(%d): Invalid type\n", nObjType );
868 break;
870 return retval;
874 /***********************************************************************
875 * EnumObjects32 (GDI32.89)
877 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
878 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
880 /* Solid colors to enumerate */
881 static const COLORREF solid_colors[] =
882 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
883 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
884 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
885 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
886 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
887 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
888 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
889 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
892 INT i, retval = 0;
893 LOGPEN pen;
894 LOGBRUSH brush;
896 TRACE("%04x %d %08lx %08lx\n",
897 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
898 switch(nObjType)
900 case OBJ_PEN:
901 /* Enumerate solid pens */
902 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
904 pen.lopnStyle = PS_SOLID;
905 pen.lopnWidth.x = 1;
906 pen.lopnWidth.y = 0;
907 pen.lopnColor = solid_colors[i];
908 retval = lpEnumFunc( &pen, lParam );
909 TRACE("solid pen %08lx, ret=%d\n",
910 solid_colors[i], retval);
911 if (!retval) break;
913 break;
915 case OBJ_BRUSH:
916 /* Enumerate solid brushes */
917 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
919 brush.lbStyle = BS_SOLID;
920 brush.lbColor = solid_colors[i];
921 brush.lbHatch = 0;
922 retval = lpEnumFunc( &brush, lParam );
923 TRACE("solid brush %08lx, ret=%d\n",
924 solid_colors[i], retval);
925 if (!retval) break;
928 /* Now enumerate hatched brushes */
929 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
931 brush.lbStyle = BS_HATCHED;
932 brush.lbColor = RGB(0,0,0);
933 brush.lbHatch = i;
934 retval = lpEnumFunc( &brush, lParam );
935 TRACE("hatched brush %d, ret=%d\n",
936 i, retval);
937 if (!retval) break;
939 break;
941 default:
942 /* FIXME: implement Win32 types */
943 WARN("(%d): Invalid type\n", nObjType );
944 break;
946 return retval;
950 /***********************************************************************
951 * IsGDIObject (GDI.462)
953 * returns type of object if valid (W95 system programming secrets p. 264-5)
955 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
957 UINT16 magic = 0;
959 if (handle >= FIRST_STOCK_HANDLE )
961 switch (handle)
963 case STOCK_WHITE_BRUSH:
964 case STOCK_LTGRAY_BRUSH:
965 case STOCK_GRAY_BRUSH:
966 case STOCK_DKGRAY_BRUSH:
967 case STOCK_BLACK_BRUSH:
968 case STOCK_HOLLOW_BRUSH:
969 magic = BRUSH_MAGIC;
970 break;
972 case STOCK_WHITE_PEN:
973 case STOCK_BLACK_PEN:
974 case STOCK_NULL_PEN :
975 magic = PEN_MAGIC;
976 break;
978 case STOCK_OEM_FIXED_FONT:
979 case STOCK_ANSI_FIXED_FONT:
980 case STOCK_ANSI_VAR_FONT:
981 case STOCK_SYSTEM_FONT:
982 case STOCK_DEVICE_DEFAULT_FONT:
983 case STOCK_SYSTEM_FIXED_FONT:
984 case STOCK_DEFAULT_GUI_FONT:
985 magic = FONT_MAGIC;
986 break;
988 case STOCK_DEFAULT_PALETTE:
989 magic = PALETTE_MAGIC;
990 break;
993 else
995 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
996 if (object)
998 magic = object->wMagic;
999 GDI_HEAP_UNLOCK( handle );
1003 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
1004 return magic - PEN_MAGIC + 1;
1005 else
1006 return FALSE;
1010 /***********************************************************************
1011 * SetObjectOwner16 (GDI.461)
1013 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1015 /* Nothing to do */
1019 /***********************************************************************
1020 * SetObjectOwner32 (GDI32.386)
1022 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1024 /* Nothing to do */
1027 /***********************************************************************
1028 * MakeObjectPrivate (GDI.463)
1030 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1032 /* FIXME */
1036 /***********************************************************************
1037 * GdiFlush (GDI32.128)
1039 BOOL WINAPI GdiFlush(void)
1041 return TRUE; /* FIXME */
1045 /***********************************************************************
1046 * GdiGetBatchLimit (GDI32.129)
1048 DWORD WINAPI GdiGetBatchLimit(void)
1050 return 1; /* FIXME */
1054 /***********************************************************************
1055 * GdiSetBatchLimit (GDI32.139)
1057 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1059 return 1; /* FIXME */
1063 /***********************************************************************
1064 * GdiSeeGdiDo (GDI.452)
1066 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1067 WORD wParam3 )
1069 switch (wReqType)
1071 case 0x0001: /* LocalAlloc */
1072 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1073 case 0x0002: /* LocalFree */
1074 return LOCAL_Free( GDI_HeapSel, wParam1 );
1075 case 0x0003: /* LocalCompact */
1076 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1077 case 0x0103: /* LocalHeap */
1078 return GDI_HeapSel;
1079 default:
1080 WARN("(wReqType=%04x): Unknown\n", wReqType);
1081 return (DWORD)-1;
1085 /***********************************************************************
1086 * GdiSignalProc (GDI.610)
1088 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1089 DWORD dwFlags, HMODULE16 hModule )
1091 return 0;
1094 /***********************************************************************
1095 * FinalGdiInit16 (GDI.405)
1097 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1101 /***********************************************************************
1102 * GdiFreeResources (GDI.609)
1104 WORD WINAPI GdiFreeResources16( DWORD reserve )
1106 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1107 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1110 /***********************************************************************
1111 * MulDiv16 (GDI.128)
1113 INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
1115 INT ret;
1116 if (!baz) return -32768;
1117 ret = (foo * bar) / baz;
1118 if ((ret > 32767) || (ret < -32767)) return -32768;
1119 return ret;
1123 /***********************************************************************
1124 * MulDiv32 (KERNEL32.391)
1125 * RETURNS
1126 * Result of multiplication and division
1127 * -1: Overflow occurred or Divisor was 0
1129 INT WINAPI MulDiv(
1130 INT nMultiplicand,
1131 INT nMultiplier,
1132 INT nDivisor
1134 #if SIZEOF_LONG_LONG >= 8
1135 long long ret;
1137 if (!nDivisor) return -1;
1139 /* We want to deal with a positive divisor to simplify the logic. */
1140 if (nDivisor < 0)
1142 nMultiplicand = - nMultiplicand;
1143 nDivisor = -nDivisor;
1146 /* If the result is positive, we "add" to round. else, we subtract to round. */
1147 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1148 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1149 ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1150 else
1151 ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1153 if ((ret > 2147483647) || (ret < -2147483647)) return -1;
1154 return ret;
1155 #else
1156 if (!nDivisor) return -1;
1158 /* We want to deal with a positive divisor to simplify the logic. */
1159 if (nDivisor < 0)
1161 nMultiplicand = - nMultiplicand;
1162 nDivisor = -nDivisor;
1165 /* If the result is positive, we "add" to round. else, we subtract to round. */
1166 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1167 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1168 return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1170 return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1172 #endif
1174 /*******************************************************************
1175 * GetColorAdjustment [GDI32.164]
1179 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1181 FIXME("GetColorAdjustment, stub\n");
1182 return 0;
1185 /*******************************************************************
1186 * GetMiterLimit [GDI32.201]
1190 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1192 FIXME("GetMiterLimit, stub\n");
1193 return 0;
1196 /*******************************************************************
1197 * SetMiterLimit [GDI32.325]
1201 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1203 FIXME("SetMiterLimit, stub\n");
1204 return 0;
1207 /*******************************************************************
1208 * GdiComment [GDI32.109]
1212 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1214 FIXME("GdiComment, stub\n");
1215 return 0;
1217 /*******************************************************************
1218 * SetColorAdjustment [GDI32.309]
1222 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1224 FIXME("SetColorAdjustment, stub\n");
1225 return 0;