Implemented TOOLBAR_MouseLeave to handle WM_MOUSELEAVE messages.
[wine/multimedia.git] / objects / gdiobj.c
blob40a0b4e2145f7214caa6f75cf2a93854c3a89d93
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <stdio.h>
12 #include "bitmap.h"
13 #include "brush.h"
14 #include "dc.h"
15 #include "font.h"
16 #include "heap.h"
17 #include "options.h"
18 #include "palette.h"
19 #include "pen.h"
20 #include "region.h"
21 #include "debugtools.h"
22 #include "gdi.h"
23 #include "tweak.h"
24 #include "windef.h"
25 #include "wingdi.h"
26 #include "winuser.h"
28 DEFAULT_DEBUG_CHANNEL(gdi)
30 /**********************************************************************/
32 GDI_DRIVER *GDI_Driver = NULL;
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, { 1, 0 }, RGB(255,255,255) } /* logpen */
84 static PENOBJ BlackPen =
86 { 0, PEN_MAGIC, 1 }, /* header */
87 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
90 static PENOBJ NullPen =
92 { 0, PEN_MAGIC, 1 }, /* header */
93 { PS_NULL, { 1, 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 /******************************************************************************
183 * void ReadFontInformation(
184 * char const *fontName,
185 * FONTOBJ *font,
186 * int defHeight,
187 * int defBold,
188 * int defItalic,
189 * int defUnderline,
190 * int defStrikeOut )
192 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
193 * section for entries containing fontName.Height, fontName.Bold, etc.,
194 * where fontName is the name specified in the call (e.g., "System"). It
195 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
196 * the first character in the boolean attributes (bold, italic, and
197 * underline).
198 *****************************************************************************/
200 static void ReadFontInformation(
201 char const *fontName,
202 FONTOBJ *font,
203 int defHeight,
204 int defBold,
205 int defItalic,
206 int defUnderline,
207 int defStrikeOut )
209 char key[256];
211 /* In order for the stock fonts to be independent of
212 * mapping mode, the height (& width) must be 0
214 sprintf(key, "%s.Height", fontName);
215 font->logfont.lfHeight =
216 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
218 sprintf(key, "%s.Bold", fontName);
219 font->logfont.lfWeight =
220 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
221 FW_BOLD : FW_NORMAL;
223 sprintf(key, "%s.Italic", fontName);
224 font->logfont.lfItalic =
225 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
227 sprintf(key, "%s.Underline", fontName);
228 font->logfont.lfUnderline =
229 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
231 sprintf(key, "%s.StrikeOut", fontName);
232 font->logfont.lfStrikeOut =
233 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
235 return;
238 /***********************************************************************
239 * Because the stock fonts have their structure initialized with
240 * a height of 0 to keep them independent of mapping mode, simply
241 * returning the LOGFONT as is will not work correctly.
242 * These "FixStockFontSizeXXX()" methods will get the correct
243 * size for the fonts.
245 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
247 HDC hdc;
248 HFONT hOldFont;
250 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
252 hOldFont = (HFONT)SelectObject(hdc, handle);
254 GetTextMetricsA(hdc, lptm);
256 SelectObject(hdc, hOldFont);
258 DeleteDC(hdc);
261 static inline void FixStockFontSize16(
262 HFONT handle,
263 INT16 count,
264 LPVOID buffer)
266 TEXTMETRICA tm;
267 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
270 * Was the lfHeight field copied (it's the first field)?
271 * If it was and it was null, replace the height.
273 if ( (count >= 2*sizeof(INT16)) &&
274 (pLogFont->lfHeight == 0) )
276 GetFontMetrics(handle, &tm);
278 pLogFont->lfHeight = tm.tmHeight;
279 pLogFont->lfWidth = tm.tmAveCharWidth;
283 static inline void FixStockFontSizeA(
284 HFONT handle,
285 INT count,
286 LPVOID buffer)
288 TEXTMETRICA tm;
289 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
292 * Was the lfHeight field copied (it's the first field)?
293 * If it was and it was null, replace the height.
295 if ( (count >= 2*sizeof(INT)) &&
296 (pLogFont->lfHeight == 0) )
298 GetFontMetrics(handle, &tm);
300 pLogFont->lfHeight = tm.tmHeight;
301 pLogFont->lfWidth = tm.tmAveCharWidth;
306 * Since the LOGFONTA and LOGFONTW structures are identical up to the
307 * lfHeight member (the one of interest in this case) we simply define
308 * the W version as the A version.
310 #define FixStockFontSizeW FixStockFontSizeA
314 /***********************************************************************
315 * GDI_Init
317 * GDI initialization.
319 BOOL GDI_Init(void)
321 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
323 /* Kill some warnings. */
324 (void)align_OEMFixedFont;
325 (void)align_AnsiFixedFont;
326 (void)align_AnsiVarFont;
327 (void)align_SystemFont;
328 (void)align_DeviceDefaultFont;
329 (void)align_SystemFixedFont;
330 (void)align_DefaultGuiFont;
332 /* TWEAK: Initialize font hints */
333 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
334 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
335 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
336 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
337 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
338 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
339 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
341 /* Create default palette */
343 /* DR well *this* palette can't be moveable (?) */
345 HPALETTE16 hpalette = PALETTE_Init();
346 if( !hpalette )
347 return FALSE;
348 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
351 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
352 return TRUE;
356 /***********************************************************************
357 * GDI_AllocObject
359 HGDIOBJ GDI_AllocObject( WORD size, WORD magic )
361 static DWORD count = 0;
362 GDIOBJHDR * obj;
363 HGDIOBJ16 handle;
364 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
365 handle = GDI_HEAP_ALLOC( size );
366 else
367 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
368 if (!handle) return 0;
369 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
370 obj->hNext = 0;
371 obj->wMagic = magic;
372 obj->dwCount = ++count;
373 GDI_HEAP_UNLOCK( handle );
374 return handle;
378 /***********************************************************************
379 * GDI_FreeObject
381 BOOL GDI_FreeObject( HGDIOBJ handle )
383 GDIOBJHDR * object;
385 /* Can't free stock objects */
386 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
387 return TRUE;
389 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
390 if (!object) return FALSE;
391 object->wMagic = 0; /* Mark it as invalid */
393 /* Free object */
395 GDI_HEAP_FREE( handle );
396 return TRUE;
399 /***********************************************************************
400 * GDI_GetObjPtr
402 * Return a pointer to the GDI object associated to the handle.
403 * Return NULL if the object has the wrong magic number.
404 * Movable GDI objects are locked in memory: it is up to the caller to unlock
405 * it after the caller is done with the pointer.
407 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
409 GDIOBJHDR * ptr = NULL;
411 if (handle >= FIRST_STOCK_HANDLE)
413 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
415 else
416 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
417 if (!ptr) return NULL;
418 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
420 GDI_HEAP_UNLOCK( handle );
421 return NULL;
423 return ptr;
427 /***********************************************************************
428 * DeleteObject16 (GDI.69)
430 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
432 return DeleteObject( obj );
436 /***********************************************************************
437 * DeleteObject (GDI32.70)
439 BOOL WINAPI DeleteObject( HGDIOBJ obj )
441 /* Check if object is valid */
443 GDIOBJHDR * header;
444 if (HIWORD(obj)) return FALSE;
445 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
446 return TRUE;
447 if (obj == hPseudoStockBitmap) return TRUE;
448 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
450 TRACE("%04x\n", obj );
452 /* Delete object */
454 switch(header->wMagic)
456 case PEN_MAGIC: return GDI_FreeObject( obj );
457 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
458 case FONT_MAGIC: return GDI_FreeObject( obj );
459 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
460 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
461 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
462 case DC_MAGIC: return DeleteDC(obj);
463 case 0 :
464 WARN("Already deleted\n");
465 break;
466 default:
467 WARN("Unknown magic number (%d)\n",header->wMagic);
469 return FALSE;
472 /***********************************************************************
473 * GetStockObject16 (GDI.87)
475 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
477 return (HGDIOBJ16)GetStockObject( obj );
481 /***********************************************************************
482 * GetStockObject (GDI32.220)
484 HGDIOBJ WINAPI GetStockObject( INT obj )
486 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
487 if (!StockObjects[obj]) return 0;
488 TRACE("returning %d\n",
489 FIRST_STOCK_HANDLE + obj );
490 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
494 /***********************************************************************
495 * GetObject16 (GDI.82)
497 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
499 GDIOBJHDR * ptr;
500 INT16 result = 0;
501 TRACE("%04x %d %p\n", handle, count, buffer );
502 if (!count) return 0;
504 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
506 switch(ptr->wMagic)
508 case PEN_MAGIC:
509 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
510 break;
511 case BRUSH_MAGIC:
512 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
513 break;
514 case BITMAP_MAGIC:
515 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
516 break;
517 case FONT_MAGIC:
518 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
521 * Fix the LOGFONT structure for the stock fonts
523 if ( (handle >= FIRST_STOCK_HANDLE) &&
524 (handle <= LAST_STOCK_HANDLE) )
525 FixStockFontSize16(handle, count, buffer);
526 break;
527 case PALETTE_MAGIC:
528 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
529 break;
531 GDI_HEAP_UNLOCK( handle );
532 return result;
536 /***********************************************************************
537 * GetObjectA (GDI32.204)
539 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
541 GDIOBJHDR * ptr;
542 INT result = 0;
543 TRACE("%08x %d %p\n", handle, count, buffer );
544 if (!count) return 0;
546 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
548 switch(ptr->wMagic)
550 case PEN_MAGIC:
551 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
552 break;
553 case BRUSH_MAGIC:
554 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
555 break;
556 case BITMAP_MAGIC:
557 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
558 break;
559 case FONT_MAGIC:
560 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
563 * Fix the LOGFONT structure for the stock fonts
565 if ( (handle >= FIRST_STOCK_HANDLE) &&
566 (handle <= LAST_STOCK_HANDLE) )
567 FixStockFontSizeA(handle, count, buffer);
568 break;
569 case PALETTE_MAGIC:
570 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
571 break;
573 case REGION_MAGIC:
574 case DC_MAGIC:
575 case DISABLED_DC_MAGIC:
576 case META_DC_MAGIC:
577 case METAFILE_MAGIC:
578 case METAFILE_DC_MAGIC:
579 case ENHMETAFILE_MAGIC:
580 case ENHMETAFILE_DC_MAGIC:
581 FIXME("Magic %04x not implemented\n",
582 ptr->wMagic );
583 break;
585 default:
586 ERR("Invalid GDI Magic %04x\n", ptr->wMagic);
587 return 0;
589 GDI_HEAP_UNLOCK( handle );
590 return result;
593 /***********************************************************************
594 * GetObjectW (GDI32.206)
596 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
598 GDIOBJHDR * ptr;
599 INT result = 0;
600 TRACE("%08x %d %p\n", handle, count, buffer );
601 if (!count) return 0;
603 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
605 switch(ptr->wMagic)
607 case PEN_MAGIC:
608 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
609 break;
610 case BRUSH_MAGIC:
611 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
612 break;
613 case BITMAP_MAGIC:
614 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
615 break;
616 case FONT_MAGIC:
617 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
620 * Fix the LOGFONT structure for the stock fonts
622 if ( (handle >= FIRST_STOCK_HANDLE) &&
623 (handle <= LAST_STOCK_HANDLE) )
624 FixStockFontSizeW(handle, count, buffer);
625 break;
626 case PALETTE_MAGIC:
627 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
628 break;
629 default:
630 FIXME("Magic %04x not implemented\n",
631 ptr->wMagic );
632 break;
634 GDI_HEAP_UNLOCK( handle );
635 return result;
638 /***********************************************************************
639 * GetObjectType (GDI32.205)
641 DWORD WINAPI GetObjectType( HANDLE handle )
643 GDIOBJHDR * ptr;
644 INT result = 0;
645 TRACE("%08x\n", handle );
647 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
649 switch(ptr->wMagic)
651 case PEN_MAGIC:
652 result = OBJ_PEN;
653 break;
654 case BRUSH_MAGIC:
655 result = OBJ_BRUSH;
656 break;
657 case BITMAP_MAGIC:
658 result = OBJ_BITMAP;
659 break;
660 case FONT_MAGIC:
661 result = OBJ_FONT;
662 break;
663 case PALETTE_MAGIC:
664 result = OBJ_PAL;
665 break;
666 case REGION_MAGIC:
667 result = OBJ_REGION;
668 break;
669 case DC_MAGIC:
670 result = OBJ_DC;
671 break;
672 case META_DC_MAGIC:
673 result = OBJ_METADC;
674 break;
675 case METAFILE_MAGIC:
676 result = OBJ_METAFILE;
677 break;
678 case METAFILE_DC_MAGIC:
679 result = OBJ_METADC;
680 break;
681 case ENHMETAFILE_MAGIC:
682 result = OBJ_ENHMETAFILE;
683 break;
684 case ENHMETAFILE_DC_MAGIC:
685 result = OBJ_ENHMETADC;
686 break;
687 default:
688 FIXME("Magic %04x not implemented\n",
689 ptr->wMagic );
690 break;
692 GDI_HEAP_UNLOCK( handle );
693 return result;
696 /***********************************************************************
697 * GetCurrentObject (GDI32.166)
699 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
701 DC * dc = DC_GetDCPtr( hdc );
703 if (!dc)
704 return 0;
705 switch (type) {
706 case OBJ_PEN: return dc->w.hPen;
707 case OBJ_BRUSH: return dc->w.hBrush;
708 case OBJ_PAL: return dc->w.hPalette;
709 case OBJ_FONT: return dc->w.hFont;
710 case OBJ_BITMAP: return dc->w.hBitmap;
711 default:
712 /* the SDK only mentions those above */
713 WARN("(%08x,%d): unknown type.\n",hdc,type);
714 return 0;
719 /***********************************************************************
720 * SelectObject16 (GDI.45)
722 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
724 return (HGDIOBJ16)SelectObject( hdc, handle );
728 /***********************************************************************
729 * SelectObject (GDI32.299)
731 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
733 DC * dc = DC_GetDCPtr( hdc );
734 if (!dc || !dc->funcs->pSelectObject) return 0;
735 TRACE("hdc=%04x %04x\n", hdc, handle );
736 return dc->funcs->pSelectObject( dc, handle );
740 /***********************************************************************
741 * UnrealizeObject16 (GDI.150)
743 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
745 return UnrealizeObject( obj );
749 /***********************************************************************
750 * UnrealizeObject (GDI32.358)
752 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
754 BOOL result = TRUE;
755 /* Check if object is valid */
757 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
758 if (!header) return FALSE;
760 TRACE("%04x\n", obj );
762 /* Unrealize object */
764 switch(header->wMagic)
766 case PALETTE_MAGIC:
767 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
768 break;
770 case BRUSH_MAGIC:
771 /* Windows resets the brush origin. We don't need to. */
772 break;
774 GDI_HEAP_UNLOCK( obj );
775 return result;
779 /***********************************************************************
780 * EnumObjects16 (GDI.71)
782 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
783 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
785 /* Solid colors to enumerate */
786 static const COLORREF solid_colors[] =
787 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
788 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
789 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
790 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
791 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
792 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
793 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
794 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
797 INT16 i, retval = 0;
798 LOGPEN16 *pen;
799 LOGBRUSH16 *brush = NULL;
801 TRACE("%04x %d %08lx %08lx\n",
802 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
803 switch(nObjType)
805 case OBJ_PEN:
806 /* Enumerate solid pens */
807 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
808 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
810 pen->lopnStyle = PS_SOLID;
811 pen->lopnWidth.x = 1;
812 pen->lopnWidth.y = 0;
813 pen->lopnColor = solid_colors[i];
814 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
815 TRACE("solid pen %08lx, ret=%d\n",
816 solid_colors[i], retval);
817 if (!retval) break;
819 SEGPTR_FREE(pen);
820 break;
822 case OBJ_BRUSH:
823 /* Enumerate solid brushes */
824 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
825 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
827 brush->lbStyle = BS_SOLID;
828 brush->lbColor = solid_colors[i];
829 brush->lbHatch = 0;
830 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
831 TRACE("solid brush %08lx, ret=%d\n",
832 solid_colors[i], retval);
833 if (!retval) break;
836 /* Now enumerate hatched brushes */
837 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
839 brush->lbStyle = BS_HATCHED;
840 brush->lbColor = RGB(0,0,0);
841 brush->lbHatch = i;
842 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
843 TRACE("hatched brush %d, ret=%d\n",
844 i, retval);
845 if (!retval) break;
847 SEGPTR_FREE(brush);
848 break;
850 default:
851 WARN("(%d): Invalid type\n", nObjType );
852 break;
854 return retval;
858 /***********************************************************************
859 * EnumObjects (GDI32.89)
861 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
862 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
864 /* Solid colors to enumerate */
865 static const COLORREF solid_colors[] =
866 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
867 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
868 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
869 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
870 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
871 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
872 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
873 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
876 INT i, retval = 0;
877 LOGPEN pen;
878 LOGBRUSH brush;
880 TRACE("%04x %d %08lx %08lx\n",
881 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
882 switch(nObjType)
884 case OBJ_PEN:
885 /* Enumerate solid pens */
886 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
888 pen.lopnStyle = PS_SOLID;
889 pen.lopnWidth.x = 1;
890 pen.lopnWidth.y = 0;
891 pen.lopnColor = solid_colors[i];
892 retval = lpEnumFunc( &pen, lParam );
893 TRACE("solid pen %08lx, ret=%d\n",
894 solid_colors[i], retval);
895 if (!retval) break;
897 break;
899 case OBJ_BRUSH:
900 /* Enumerate solid brushes */
901 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
903 brush.lbStyle = BS_SOLID;
904 brush.lbColor = solid_colors[i];
905 brush.lbHatch = 0;
906 retval = lpEnumFunc( &brush, lParam );
907 TRACE("solid brush %08lx, ret=%d\n",
908 solid_colors[i], retval);
909 if (!retval) break;
912 /* Now enumerate hatched brushes */
913 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
915 brush.lbStyle = BS_HATCHED;
916 brush.lbColor = RGB(0,0,0);
917 brush.lbHatch = i;
918 retval = lpEnumFunc( &brush, lParam );
919 TRACE("hatched brush %d, ret=%d\n",
920 i, retval);
921 if (!retval) break;
923 break;
925 default:
926 /* FIXME: implement Win32 types */
927 WARN("(%d): Invalid type\n", nObjType );
928 break;
930 return retval;
934 /***********************************************************************
935 * IsGDIObject (GDI.462)
937 * returns type of object if valid (W95 system programming secrets p. 264-5)
939 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
941 UINT16 magic = 0;
943 if (handle >= FIRST_STOCK_HANDLE )
945 switch (handle)
947 case STOCK_WHITE_BRUSH:
948 case STOCK_LTGRAY_BRUSH:
949 case STOCK_GRAY_BRUSH:
950 case STOCK_DKGRAY_BRUSH:
951 case STOCK_BLACK_BRUSH:
952 case STOCK_HOLLOW_BRUSH:
953 magic = BRUSH_MAGIC;
954 break;
956 case STOCK_WHITE_PEN:
957 case STOCK_BLACK_PEN:
958 case STOCK_NULL_PEN :
959 magic = PEN_MAGIC;
960 break;
962 case STOCK_OEM_FIXED_FONT:
963 case STOCK_ANSI_FIXED_FONT:
964 case STOCK_ANSI_VAR_FONT:
965 case STOCK_SYSTEM_FONT:
966 case STOCK_DEVICE_DEFAULT_FONT:
967 case STOCK_SYSTEM_FIXED_FONT:
968 case STOCK_DEFAULT_GUI_FONT:
969 magic = FONT_MAGIC;
970 break;
972 case STOCK_DEFAULT_PALETTE:
973 magic = PALETTE_MAGIC;
974 break;
977 else
979 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
980 if (object)
982 magic = object->wMagic;
983 GDI_HEAP_UNLOCK( handle );
987 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
988 return magic - PEN_MAGIC + 1;
989 else
990 return FALSE;
994 /***********************************************************************
995 * SetObjectOwner16 (GDI.461)
997 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
999 /* Nothing to do */
1003 /***********************************************************************
1004 * SetObjectOwner (GDI32.386)
1006 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1008 /* Nothing to do */
1011 /***********************************************************************
1012 * MakeObjectPrivate (GDI.463)
1014 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1016 /* FIXME */
1020 /***********************************************************************
1021 * GdiFlush (GDI32.128)
1023 BOOL WINAPI GdiFlush(void)
1025 return TRUE; /* FIXME */
1029 /***********************************************************************
1030 * GdiGetBatchLimit (GDI32.129)
1032 DWORD WINAPI GdiGetBatchLimit(void)
1034 return 1; /* FIXME */
1038 /***********************************************************************
1039 * GdiSetBatchLimit (GDI32.139)
1041 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1043 return 1; /* FIXME */
1047 /***********************************************************************
1048 * GdiSeeGdiDo (GDI.452)
1050 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1051 WORD wParam3 )
1053 switch (wReqType)
1055 case 0x0001: /* LocalAlloc */
1056 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1057 case 0x0002: /* LocalFree */
1058 return LOCAL_Free( GDI_HeapSel, wParam1 );
1059 case 0x0003: /* LocalCompact */
1060 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1061 case 0x0103: /* LocalHeap */
1062 return GDI_HeapSel;
1063 default:
1064 WARN("(wReqType=%04x): Unknown\n", wReqType);
1065 return (DWORD)-1;
1069 /***********************************************************************
1070 * GdiSignalProc (GDI.610)
1072 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1073 DWORD dwFlags, HMODULE16 hModule )
1075 return 0;
1078 /***********************************************************************
1079 * FinalGdiInit16 (GDI.405)
1081 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1085 /***********************************************************************
1086 * GdiFreeResources (GDI.609)
1088 WORD WINAPI GdiFreeResources16( DWORD reserve )
1090 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1091 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1094 /***********************************************************************
1095 * MulDiv16 (GDI.128)
1097 INT16 WINAPI MulDiv16(
1098 INT16 nMultiplicand,
1099 INT16 nMultiplier,
1100 INT16 nDivisor)
1102 INT ret;
1103 if (!nDivisor) return -32768;
1104 /* We want to deal with a positive divisor to simplify the logic. */
1105 if (nDivisor < 0)
1107 nMultiplicand = - nMultiplicand;
1108 nDivisor = -nDivisor;
1110 /* If the result is positive, we "add" to round. else,
1111 * we subtract to round. */
1112 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1113 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1114 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1115 else
1116 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1117 if ((ret > 32767) || (ret < -32767)) return -32768;
1118 return (INT16) ret;
1122 /***********************************************************************
1123 * MulDiv (KERNEL32.391)
1124 * RETURNS
1125 * Result of multiplication and division
1126 * -1: Overflow occurred or Divisor was 0
1128 INT WINAPI MulDiv(
1129 INT nMultiplicand,
1130 INT nMultiplier,
1131 INT nDivisor)
1133 #if SIZEOF_LONG_LONG >= 8
1134 long long ret;
1136 if (!nDivisor) return -1;
1138 /* We want to deal with a positive divisor to simplify the logic. */
1139 if (nDivisor < 0)
1141 nMultiplicand = - nMultiplicand;
1142 nDivisor = -nDivisor;
1145 /* If the result is positive, we "add" to round. else, we subtract to round. */
1146 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1147 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1148 ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1149 else
1150 ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1152 if ((ret > 2147483647) || (ret < -2147483647)) return -1;
1153 return ret;
1154 #else
1155 if (!nDivisor) return -1;
1157 /* We want to deal with a positive divisor to simplify the logic. */
1158 if (nDivisor < 0)
1160 nMultiplicand = - nMultiplicand;
1161 nDivisor = -nDivisor;
1164 /* If the result is positive, we "add" to round. else, we subtract to round. */
1165 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1166 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1167 return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1169 return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1171 #endif
1173 /*******************************************************************
1174 * GetColorAdjustment [GDI32.164]
1178 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1180 FIXME("GetColorAdjustment, stub\n");
1181 return 0;
1184 /*******************************************************************
1185 * GetMiterLimit [GDI32.201]
1189 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1191 FIXME("GetMiterLimit, stub\n");
1192 return 0;
1195 /*******************************************************************
1196 * SetMiterLimit [GDI32.325]
1200 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1202 FIXME("SetMiterLimit, stub\n");
1203 return 0;
1206 /*******************************************************************
1207 * GdiComment [GDI32.109]
1211 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1213 FIXME("GdiComment, stub\n");
1214 return 0;
1216 /*******************************************************************
1217 * SetColorAdjustment [GDI32.309]
1221 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1223 FIXME("SetColorAdjustment, stub\n");
1224 return 0;