Pierre Mageau
[wine/multimedia.git] / objects / gdiobj.c
blobcb686766617c920042cf550bf65ecbd14c12896b
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>
17 #include "bitmap.h"
18 #include "brush.h"
19 #include "dc.h"
20 #include "font.h"
21 #include "heap.h"
22 #include "options.h"
23 #include "palette.h"
24 #include "pen.h"
25 #include "region.h"
26 #include "debugtools.h"
27 #include "gdi.h"
28 #include "tweak.h"
29 #include "winuser.h"
31 DEFAULT_DEBUG_CHANNEL(gdi)
33 /**********************************************************************/
35 GDI_DRIVER *GDI_Driver = NULL;
37 /***********************************************************************
38 * GDI stock objects
41 static BRUSHOBJ WhiteBrush =
43 { 0, BRUSH_MAGIC, 1 }, /* header */
44 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
47 static BRUSHOBJ LtGrayBrush =
49 { 0, BRUSH_MAGIC, 1 }, /* header */
50 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
51 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
54 static BRUSHOBJ GrayBrush =
56 { 0, BRUSH_MAGIC, 1 }, /* header */
57 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
58 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
61 static BRUSHOBJ DkGrayBrush =
63 { 0, BRUSH_MAGIC, 1 }, /* header */
64 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
65 /* NB_HATCH_STYLES is an index into HatchBrushes */
66 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
69 static BRUSHOBJ BlackBrush =
71 { 0, BRUSH_MAGIC, 1 }, /* header */
72 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
75 static BRUSHOBJ NullBrush =
77 { 0, BRUSH_MAGIC, 1 }, /* header */
78 { BS_NULL, 0, 0 } /* logbrush */
81 static PENOBJ WhitePen =
83 { 0, PEN_MAGIC, 1 }, /* header */
84 { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
87 static PENOBJ BlackPen =
89 { 0, PEN_MAGIC, 1 }, /* header */
90 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
93 static PENOBJ NullPen =
95 { 0, PEN_MAGIC, 1 }, /* header */
96 { PS_NULL, { 1, 0 }, 0 } /* logpen */
99 static FONTOBJ OEMFixedFont =
101 { 0, FONT_MAGIC, 1 }, /* header */
102 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
103 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
105 /* Filler to make the location counter dword aligned again. This is necessary
106 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
107 segment, and (c) Solaris assembler is stupid. */
108 static UINT16 align_OEMFixedFont = 1;
110 static FONTOBJ AnsiFixedFont =
112 { 0, FONT_MAGIC, 1 }, /* header */
113 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
114 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
116 static UINT16 align_AnsiFixedFont = 1;
118 static FONTOBJ AnsiVarFont =
120 { 0, FONT_MAGIC, 1 }, /* header */
121 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
122 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
124 static UINT16 align_AnsiVarFont = 1;
126 static FONTOBJ SystemFont =
128 { 0, FONT_MAGIC, 1 },
129 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
130 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
132 static UINT16 align_SystemFont = 1;
134 static FONTOBJ DeviceDefaultFont =
136 { 0, FONT_MAGIC, 1 }, /* header */
137 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
138 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
140 static UINT16 align_DeviceDefaultFont = 1;
142 static FONTOBJ SystemFixedFont =
144 { 0, FONT_MAGIC, 1 }, /* header */
145 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
146 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
148 static UINT16 align_SystemFixedFont = 1;
150 /* FIXME: Is this correct? */
151 static FONTOBJ DefaultGuiFont =
153 { 0, FONT_MAGIC, 1 }, /* header */
154 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
155 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
157 static UINT16 align_DefaultGuiFont = 1;
160 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
162 (GDIOBJHDR *) &WhiteBrush,
163 (GDIOBJHDR *) &LtGrayBrush,
164 (GDIOBJHDR *) &GrayBrush,
165 (GDIOBJHDR *) &DkGrayBrush,
166 (GDIOBJHDR *) &BlackBrush,
167 (GDIOBJHDR *) &NullBrush,
168 (GDIOBJHDR *) &WhitePen,
169 (GDIOBJHDR *) &BlackPen,
170 (GDIOBJHDR *) &NullPen,
171 NULL,
172 (GDIOBJHDR *) &OEMFixedFont,
173 (GDIOBJHDR *) &AnsiFixedFont,
174 (GDIOBJHDR *) &AnsiVarFont,
175 (GDIOBJHDR *) &SystemFont,
176 (GDIOBJHDR *) &DeviceDefaultFont,
177 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
178 (GDIOBJHDR *) &SystemFixedFont,
179 (GDIOBJHDR *) &DefaultGuiFont
182 /******************************************************************************
184 * void ReadFontInformation(
185 * char const *fontName,
186 * FONTOBJ *font,
187 * int defHeight,
188 * int defBold,
189 * int defItalic,
190 * int defUnderline,
191 * int defStrikeOut )
193 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
194 * section for entries containing fontName.Height, fontName.Bold, etc.,
195 * where fontName is the name specified in the call (e.g., "System"). It
196 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
197 * the first character in the boolean attributes (bold, italic, and
198 * underline).
199 *****************************************************************************/
201 static void ReadFontInformation(
202 char const *fontName,
203 FONTOBJ *font,
204 int defHeight,
205 int defBold,
206 int defItalic,
207 int defUnderline,
208 int defStrikeOut )
210 char key[256];
212 /* In order for the stock fonts to be independent of
213 * mapping mode, the height (& width) must be 0
215 sprintf(key, "%s.Height", fontName);
216 font->logfont.lfHeight =
217 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
219 sprintf(key, "%s.Bold", fontName);
220 font->logfont.lfWeight =
221 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
222 FW_BOLD : FW_NORMAL;
224 sprintf(key, "%s.Italic", fontName);
225 font->logfont.lfItalic =
226 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
228 sprintf(key, "%s.Underline", fontName);
229 font->logfont.lfUnderline =
230 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
232 sprintf(key, "%s.StrikeOut", fontName);
233 font->logfont.lfStrikeOut =
234 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
236 return;
239 /***********************************************************************
240 * Because the stock fonts have their structure initialized with
241 * a height of 0 to keep them independent of mapping mode, simply
242 * returning the LOGFONT as is will not work correctly.
243 * These "FixStockFontSizeXXX()" methods will get the correct
244 * size for the fonts.
246 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
248 HDC hdc;
249 HFONT hOldFont;
251 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
253 hOldFont = (HFONT)SelectObject(hdc, handle);
255 GetTextMetricsA(hdc, lptm);
257 SelectObject(hdc, hOldFont);
259 DeleteDC(hdc);
262 static inline void FixStockFontSize16(
263 HFONT handle,
264 INT16 count,
265 LPVOID buffer)
267 TEXTMETRICA tm;
268 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
271 * Was the lfHeight field copied (it's the first field)?
272 * If it was and it was null, replace the height.
274 if ( (count >= 2*sizeof(INT16)) &&
275 (pLogFont->lfHeight == 0) )
277 GetFontMetrics(handle, &tm);
279 pLogFont->lfHeight = tm.tmHeight;
280 pLogFont->lfWidth = tm.tmAveCharWidth;
284 static inline void FixStockFontSizeA(
285 HFONT handle,
286 INT count,
287 LPVOID buffer)
289 TEXTMETRICA tm;
290 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
293 * Was the lfHeight field copied (it's the first field)?
294 * If it was and it was null, replace the height.
296 if ( (count >= 2*sizeof(INT)) &&
297 (pLogFont->lfHeight == 0) )
299 GetFontMetrics(handle, &tm);
301 pLogFont->lfHeight = tm.tmHeight;
302 pLogFont->lfWidth = tm.tmAveCharWidth;
307 * Since the LOGFONTA and LOGFONTW structures are identical up to the
308 * lfHeight member (the one of interest in this case) we simply define
309 * the W version as the A version.
311 #define FixStockFontSizeW FixStockFontSizeA
315 /***********************************************************************
316 * GDI_Init
318 * GDI initialization.
320 BOOL GDI_Init(void)
322 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
324 /* Kill some warnings. */
325 (void)align_OEMFixedFont;
326 (void)align_AnsiFixedFont;
327 (void)align_AnsiVarFont;
328 (void)align_SystemFont;
329 (void)align_DeviceDefaultFont;
330 (void)align_SystemFixedFont;
331 (void)align_DefaultGuiFont;
333 /* TWEAK: Initialize font hints */
334 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
335 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
336 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
337 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
338 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
339 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
340 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
342 /* Initialize drivers */
344 #ifndef X_DISPLAY_MISSING
345 GDI_Driver = &X11DRV_GDI_Driver;
346 #else /* !defined(X_DISPLAY_MISSING) */
347 GDI_Driver = &TTYDRV_GDI_Driver;
348 #endif /* !defined(X_DISPLAY_MISSING */
350 GDI_Driver->pInitialize();
352 /* Create default palette */
354 /* DR well *this* palette can't be moveable (?) */
356 HPALETTE16 hpalette = PALETTE_Init();
357 if( !hpalette )
358 return FALSE;
359 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
362 return TRUE;
366 /***********************************************************************
367 * GDI_AllocObject
369 HGDIOBJ16 GDI_AllocObject( WORD size, WORD magic )
371 static DWORD count = 0;
372 GDIOBJHDR * obj;
373 HGDIOBJ16 handle;
374 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
375 handle = GDI_HEAP_ALLOC( size );
376 else
377 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
378 if (!handle) return 0;
379 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
380 obj->hNext = 0;
381 obj->wMagic = magic;
382 obj->dwCount = ++count;
383 GDI_HEAP_UNLOCK( handle );
384 return handle;
388 /***********************************************************************
389 * GDI_FreeObject
391 BOOL GDI_FreeObject( HGDIOBJ16 handle )
393 GDIOBJHDR * object;
395 /* Can't free stock objects */
396 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
397 return TRUE;
399 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
400 if (!object) return FALSE;
401 object->wMagic = 0; /* Mark it as invalid */
403 /* Free object */
405 GDI_HEAP_FREE( handle );
406 return TRUE;
409 /***********************************************************************
410 * GDI_GetObjPtr
412 * Return a pointer to the GDI object associated to the handle.
413 * Return NULL if the object has the wrong magic number.
414 * Movable GDI objects are locked in memory: it is up to the caller to unlock
415 * it after the caller is done with the pointer.
417 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16 handle, WORD magic )
419 GDIOBJHDR * ptr = NULL;
421 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
422 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
423 else
424 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
425 if (!ptr) return NULL;
426 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
428 GDI_HEAP_UNLOCK( handle );
429 return NULL;
431 return ptr;
435 /***********************************************************************
436 * DeleteObject16 (GDI.69)
438 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
440 return DeleteObject( obj );
444 /***********************************************************************
445 * DeleteObject32 (GDI32.70)
447 BOOL WINAPI DeleteObject( HGDIOBJ obj )
449 /* Check if object is valid */
451 GDIOBJHDR * header;
452 if (HIWORD(obj)) return FALSE;
453 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
454 return TRUE;
455 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
457 TRACE("%04x\n", obj );
459 /* Delete object */
461 switch(header->wMagic)
463 case PEN_MAGIC: return GDI_FreeObject( obj );
464 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
465 case FONT_MAGIC: return GDI_FreeObject( obj );
466 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
467 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
468 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
469 case DC_MAGIC: return DeleteDC(obj);
470 case 0 :
471 WARN("Already deleted\n");
472 break;
473 default:
474 WARN("Unknown magic number (%d)\n",header->wMagic);
476 return FALSE;
479 /***********************************************************************
480 * GetStockObject16 (GDI.87)
482 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
484 return (HGDIOBJ16)GetStockObject( obj );
488 /***********************************************************************
489 * GetStockObject32 (GDI32.220)
491 HGDIOBJ WINAPI GetStockObject( INT obj )
493 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
494 if (!StockObjects[obj]) return 0;
495 TRACE("returning %d\n",
496 FIRST_STOCK_HANDLE + obj );
497 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
501 /***********************************************************************
502 * GetObject16 (GDI.82)
504 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
506 GDIOBJHDR * ptr = NULL;
507 INT16 result = 0;
508 TRACE("%04x %d %p\n", handle, count, buffer );
509 if (!count) return 0;
511 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
512 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
513 else
514 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
515 if (!ptr) return 0;
517 switch(ptr->wMagic)
519 case PEN_MAGIC:
520 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
521 break;
522 case BRUSH_MAGIC:
523 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
524 break;
525 case BITMAP_MAGIC:
526 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
527 break;
528 case FONT_MAGIC:
529 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
532 * Fix the LOGFONT structure for the stock fonts
534 if ( (handle >= FIRST_STOCK_HANDLE) &&
535 (handle <= LAST_STOCK_HANDLE) )
536 FixStockFontSize16(handle, count, buffer);
537 break;
538 case PALETTE_MAGIC:
539 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
540 break;
542 GDI_HEAP_UNLOCK( handle );
543 return result;
547 /***********************************************************************
548 * GetObject32A (GDI32.204)
550 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
552 GDIOBJHDR * ptr = NULL;
553 INT result = 0;
554 TRACE("%08x %d %p\n", handle, count, buffer );
555 if (!count) return 0;
557 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
558 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
559 else
560 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
561 if (!ptr) return 0;
563 switch(ptr->wMagic)
565 case PEN_MAGIC:
566 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
567 break;
568 case BRUSH_MAGIC:
569 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
570 break;
571 case BITMAP_MAGIC:
572 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
573 break;
574 case FONT_MAGIC:
575 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
578 * Fix the LOGFONT structure for the stock fonts
580 if ( (handle >= FIRST_STOCK_HANDLE) &&
581 (handle <= LAST_STOCK_HANDLE) )
582 FixStockFontSizeA(handle, count, buffer);
583 break;
584 case PALETTE_MAGIC:
585 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
586 break;
587 default:
588 FIXME("Magic %04x not implemented\n",
589 ptr->wMagic );
590 break;
592 GDI_HEAP_UNLOCK( handle );
593 return result;
595 /***********************************************************************
596 * GetObject32W (GDI32.206)
598 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
600 GDIOBJHDR * ptr = NULL;
601 INT result = 0;
602 TRACE("%08x %d %p\n", handle, count, buffer );
603 if (!count) return 0;
605 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
606 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
607 else
608 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
609 if (!ptr) return 0;
611 switch(ptr->wMagic)
613 case PEN_MAGIC:
614 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
615 break;
616 case BRUSH_MAGIC:
617 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
618 break;
619 case BITMAP_MAGIC:
620 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
621 break;
622 case FONT_MAGIC:
623 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
626 * Fix the LOGFONT structure for the stock fonts
628 if ( (handle >= FIRST_STOCK_HANDLE) &&
629 (handle <= LAST_STOCK_HANDLE) )
630 FixStockFontSizeW(handle, count, buffer);
631 break;
632 case PALETTE_MAGIC:
633 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
634 break;
635 default:
636 FIXME("Magic %04x not implemented\n",
637 ptr->wMagic );
638 break;
640 GDI_HEAP_UNLOCK( handle );
641 return result;
644 /***********************************************************************
645 * GetObjectType (GDI32.205)
647 DWORD WINAPI GetObjectType( HANDLE handle )
649 GDIOBJHDR * ptr = NULL;
650 INT result = 0;
651 TRACE("%08x\n", handle );
653 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
654 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
655 else
656 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
657 if (!ptr) return 0;
659 switch(ptr->wMagic)
661 case PEN_MAGIC:
662 result = OBJ_PEN;
663 break;
664 case BRUSH_MAGIC:
665 result = OBJ_BRUSH;
666 break;
667 case BITMAP_MAGIC:
668 result = OBJ_BITMAP;
669 break;
670 case FONT_MAGIC:
671 result = OBJ_FONT;
672 break;
673 case PALETTE_MAGIC:
674 result = OBJ_PAL;
675 break;
676 case REGION_MAGIC:
677 result = OBJ_REGION;
678 break;
679 case DC_MAGIC:
680 result = OBJ_DC;
681 break;
682 case META_DC_MAGIC:
683 result = OBJ_METADC;
684 break;
685 case METAFILE_MAGIC:
686 result = OBJ_METAFILE;
687 break;
688 case METAFILE_DC_MAGIC:
689 result = OBJ_METADC;
690 break;
691 case ENHMETAFILE_MAGIC:
692 result = OBJ_ENHMETAFILE;
693 break;
694 case ENHMETAFILE_DC_MAGIC:
695 result = OBJ_ENHMETADC;
696 break;
697 default:
698 FIXME("Magic %04x not implemented\n",
699 ptr->wMagic );
700 break;
702 GDI_HEAP_UNLOCK( handle );
703 return result;
706 /***********************************************************************
707 * GetCurrentObject (GDI32.166)
709 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
711 DC * dc = DC_GetDCPtr( hdc );
713 if (!dc)
714 return 0;
715 switch (type) {
716 case OBJ_PEN: return dc->w.hPen;
717 case OBJ_BRUSH: return dc->w.hBrush;
718 case OBJ_PAL: return dc->w.hPalette;
719 case OBJ_FONT: return dc->w.hFont;
720 case OBJ_BITMAP: return dc->w.hBitmap;
721 default:
722 /* the SDK only mentions those above */
723 WARN("(%08x,%d): unknown type.\n",hdc,type);
724 return 0;
729 /***********************************************************************
730 * SelectObject16 (GDI.45)
732 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
734 return (HGDIOBJ16)SelectObject( hdc, handle );
738 /***********************************************************************
739 * SelectObject32 (GDI32.299)
741 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
743 DC * dc = DC_GetDCPtr( hdc );
744 if (!dc || !dc->funcs->pSelectObject) return 0;
745 TRACE("hdc=%04x %04x\n", hdc, handle );
746 return dc->funcs->pSelectObject( dc, handle );
750 /***********************************************************************
751 * UnrealizeObject16 (GDI.150)
753 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
755 return UnrealizeObject( obj );
759 /***********************************************************************
760 * UnrealizeObject (GDI32.358)
762 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
764 BOOL result = TRUE;
765 /* Check if object is valid */
767 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
768 if (!header) return FALSE;
770 TRACE("%04x\n", obj );
772 /* Unrealize object */
774 switch(header->wMagic)
776 case PALETTE_MAGIC:
777 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
778 break;
780 case BRUSH_MAGIC:
781 /* Windows resets the brush origin. We don't need to. */
782 break;
784 GDI_HEAP_UNLOCK( obj );
785 return result;
789 /***********************************************************************
790 * EnumObjects16 (GDI.71)
792 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
793 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
795 /* Solid colors to enumerate */
796 static const COLORREF solid_colors[] =
797 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
798 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
799 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
800 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
801 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
802 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
803 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
804 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
807 INT16 i, retval = 0;
808 LOGPEN16 *pen;
809 LOGBRUSH16 *brush = NULL;
811 TRACE("%04x %d %08lx %08lx\n",
812 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
813 switch(nObjType)
815 case OBJ_PEN:
816 /* Enumerate solid pens */
817 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
818 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
820 pen->lopnStyle = PS_SOLID;
821 pen->lopnWidth.x = 1;
822 pen->lopnWidth.y = 0;
823 pen->lopnColor = solid_colors[i];
824 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
825 TRACE("solid pen %08lx, ret=%d\n",
826 solid_colors[i], retval);
827 if (!retval) break;
829 SEGPTR_FREE(pen);
830 break;
832 case OBJ_BRUSH:
833 /* Enumerate solid brushes */
834 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
835 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
837 brush->lbStyle = BS_SOLID;
838 brush->lbColor = solid_colors[i];
839 brush->lbHatch = 0;
840 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
841 TRACE("solid brush %08lx, ret=%d\n",
842 solid_colors[i], retval);
843 if (!retval) break;
846 /* Now enumerate hatched brushes */
847 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
849 brush->lbStyle = BS_HATCHED;
850 brush->lbColor = RGB(0,0,0);
851 brush->lbHatch = i;
852 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
853 TRACE("hatched brush %d, ret=%d\n",
854 i, retval);
855 if (!retval) break;
857 SEGPTR_FREE(brush);
858 break;
860 default:
861 WARN("(%d): Invalid type\n", nObjType );
862 break;
864 return retval;
868 /***********************************************************************
869 * EnumObjects32 (GDI32.89)
871 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
872 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
874 /* Solid colors to enumerate */
875 static const COLORREF solid_colors[] =
876 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
877 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
878 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
879 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
880 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
881 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
882 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
883 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
886 INT i, retval = 0;
887 LOGPEN pen;
888 LOGBRUSH brush;
890 TRACE("%04x %d %08lx %08lx\n",
891 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
892 switch(nObjType)
894 case OBJ_PEN:
895 /* Enumerate solid pens */
896 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
898 pen.lopnStyle = PS_SOLID;
899 pen.lopnWidth.x = 1;
900 pen.lopnWidth.y = 0;
901 pen.lopnColor = solid_colors[i];
902 retval = lpEnumFunc( &pen, lParam );
903 TRACE("solid pen %08lx, ret=%d\n",
904 solid_colors[i], retval);
905 if (!retval) break;
907 break;
909 case OBJ_BRUSH:
910 /* Enumerate solid brushes */
911 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
913 brush.lbStyle = BS_SOLID;
914 brush.lbColor = solid_colors[i];
915 brush.lbHatch = 0;
916 retval = lpEnumFunc( &brush, lParam );
917 TRACE("solid brush %08lx, ret=%d\n",
918 solid_colors[i], retval);
919 if (!retval) break;
922 /* Now enumerate hatched brushes */
923 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
925 brush.lbStyle = BS_HATCHED;
926 brush.lbColor = RGB(0,0,0);
927 brush.lbHatch = i;
928 retval = lpEnumFunc( &brush, lParam );
929 TRACE("hatched brush %d, ret=%d\n",
930 i, retval);
931 if (!retval) break;
933 break;
935 default:
936 /* FIXME: implement Win32 types */
937 WARN("(%d): Invalid type\n", nObjType );
938 break;
940 return retval;
944 /***********************************************************************
945 * IsGDIObject (GDI.462)
947 * returns type of object if valid (W95 system programming secrets p. 264-5)
949 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
951 UINT16 magic = 0;
953 if (handle >= FIRST_STOCK_HANDLE )
955 switch (handle)
957 case STOCK_WHITE_BRUSH:
958 case STOCK_LTGRAY_BRUSH:
959 case STOCK_GRAY_BRUSH:
960 case STOCK_DKGRAY_BRUSH:
961 case STOCK_BLACK_BRUSH:
962 case STOCK_HOLLOW_BRUSH:
963 magic = BRUSH_MAGIC;
964 break;
966 case STOCK_WHITE_PEN:
967 case STOCK_BLACK_PEN:
968 case STOCK_NULL_PEN :
969 magic = PEN_MAGIC;
970 break;
972 case STOCK_OEM_FIXED_FONT:
973 case STOCK_ANSI_FIXED_FONT:
974 case STOCK_ANSI_VAR_FONT:
975 case STOCK_SYSTEM_FONT:
976 case STOCK_DEVICE_DEFAULT_FONT:
977 case STOCK_SYSTEM_FIXED_FONT:
978 case STOCK_DEFAULT_GUI_FONT:
979 magic = FONT_MAGIC;
980 break;
982 case STOCK_DEFAULT_PALETTE:
983 magic = PALETTE_MAGIC;
984 break;
987 else
989 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
990 if (object)
992 magic = object->wMagic;
993 GDI_HEAP_UNLOCK( handle );
997 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
998 return magic - PEN_MAGIC + 1;
999 else
1000 return FALSE;
1004 /***********************************************************************
1005 * SetObjectOwner16 (GDI.461)
1007 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1009 /* Nothing to do */
1013 /***********************************************************************
1014 * SetObjectOwner32 (GDI32.386)
1016 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1018 /* Nothing to do */
1021 /***********************************************************************
1022 * MakeObjectPrivate (GDI.463)
1024 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1026 /* FIXME */
1030 /***********************************************************************
1031 * GdiFlush (GDI32.128)
1033 BOOL WINAPI GdiFlush(void)
1035 return TRUE; /* FIXME */
1039 /***********************************************************************
1040 * GdiGetBatchLimit (GDI32.129)
1042 DWORD WINAPI GdiGetBatchLimit(void)
1044 return 1; /* FIXME */
1048 /***********************************************************************
1049 * GdiSetBatchLimit (GDI32.139)
1051 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1053 return 1; /* FIXME */
1057 /***********************************************************************
1058 * GdiSeeGdiDo (GDI.452)
1060 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1061 WORD wParam3 )
1063 switch (wReqType)
1065 case 0x0001: /* LocalAlloc */
1066 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1067 case 0x0002: /* LocalFree */
1068 return LOCAL_Free( GDI_HeapSel, wParam1 );
1069 case 0x0003: /* LocalCompact */
1070 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1071 case 0x0103: /* LocalHeap */
1072 return GDI_HeapSel;
1073 default:
1074 WARN("(wReqType=%04x): Unknown\n", wReqType);
1075 return (DWORD)-1;
1079 /***********************************************************************
1080 * GdiSignalProc (GDI.610)
1082 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1083 DWORD dwFlags, HMODULE16 hModule )
1085 return 0;
1088 /***********************************************************************
1089 * FinalGdiInit16 (GDI.405)
1091 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1095 /***********************************************************************
1096 * GdiFreeResources (GDI.609)
1098 WORD WINAPI GdiFreeResources16( DWORD reserve )
1100 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1101 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1104 /***********************************************************************
1105 * MulDiv16 (GDI.128)
1107 INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
1109 INT ret;
1110 if (!baz) return -32768;
1111 ret = (foo * bar) / baz;
1112 if ((ret > 32767) || (ret < -32767)) return -32768;
1113 return ret;
1117 /***********************************************************************
1118 * MulDiv32 (KERNEL32.391)
1119 * RETURNS
1120 * Result of multiplication and division
1121 * -1: Overflow occurred or Divisor was 0
1123 INT WINAPI MulDiv(
1124 INT nMultiplicand,
1125 INT nMultiplier,
1126 INT nDivisor
1128 #if SIZEOF_LONG_LONG >= 8
1129 long long ret;
1131 if (!nDivisor) return -1;
1133 /* We want to deal with a positive divisor to simplify the logic. */
1134 if (nDivisor < 0)
1136 nMultiplicand = - nMultiplicand;
1137 nDivisor = -nDivisor;
1140 /* If the result is positive, we "add" to round. else, we subtract to round. */
1141 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1142 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1143 ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1144 else
1145 ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1147 if ((ret > 2147483647) || (ret < -2147483647)) return -1;
1148 return ret;
1149 #else
1150 if (!nDivisor) return -1;
1152 /* We want to deal with a positive divisor to simplify the logic. */
1153 if (nDivisor < 0)
1155 nMultiplicand = - nMultiplicand;
1156 nDivisor = -nDivisor;
1159 /* If the result is positive, we "add" to round. else, we subtract to round. */
1160 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1161 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1162 return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1164 return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1166 #endif
1168 /*******************************************************************
1169 * GetColorAdjustment [GDI32.164]
1173 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1175 FIXME("GetColorAdjustment, stub\n");
1176 return 0;
1179 /*******************************************************************
1180 * GetMiterLimit [GDI32.201]
1184 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1186 FIXME("GetMiterLimit, stub\n");
1187 return 0;
1190 /*******************************************************************
1191 * SetMiterLimit [GDI32.325]
1195 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1197 FIXME("SetMiterLimit, stub\n");
1198 return 0;
1201 /*******************************************************************
1202 * GdiComment [GDI32.109]
1206 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1208 FIXME("GdiComment, stub\n");
1209 return 0;
1211 /*******************************************************************
1212 * SetColorAdjustment [GDI32.309]
1216 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1218 FIXME("SetColorAdjustment, stub\n");
1219 return 0;