Avoid deleting of the default 1x1 bitmap for memory DCs.
[wine/multimedia.git] / objects / gdiobj.c
blob16357ea0a0d5386f40beba36f2096367d72de2d4
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 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
184 /******************************************************************************
186 * void ReadFontInformation(
187 * char const *fontName,
188 * FONTOBJ *font,
189 * int defHeight,
190 * int defBold,
191 * int defItalic,
192 * int defUnderline,
193 * int defStrikeOut )
195 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
196 * section for entries containing fontName.Height, fontName.Bold, etc.,
197 * where fontName is the name specified in the call (e.g., "System"). It
198 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
199 * the first character in the boolean attributes (bold, italic, and
200 * underline).
201 *****************************************************************************/
203 static void ReadFontInformation(
204 char const *fontName,
205 FONTOBJ *font,
206 int defHeight,
207 int defBold,
208 int defItalic,
209 int defUnderline,
210 int defStrikeOut )
212 char key[256];
214 /* In order for the stock fonts to be independent of
215 * mapping mode, the height (& width) must be 0
217 sprintf(key, "%s.Height", fontName);
218 font->logfont.lfHeight =
219 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
221 sprintf(key, "%s.Bold", fontName);
222 font->logfont.lfWeight =
223 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
224 FW_BOLD : FW_NORMAL;
226 sprintf(key, "%s.Italic", fontName);
227 font->logfont.lfItalic =
228 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
230 sprintf(key, "%s.Underline", fontName);
231 font->logfont.lfUnderline =
232 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
234 sprintf(key, "%s.StrikeOut", fontName);
235 font->logfont.lfStrikeOut =
236 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
238 return;
241 /***********************************************************************
242 * Because the stock fonts have their structure initialized with
243 * a height of 0 to keep them independent of mapping mode, simply
244 * returning the LOGFONT as is will not work correctly.
245 * These "FixStockFontSizeXXX()" methods will get the correct
246 * size for the fonts.
248 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
250 HDC hdc;
251 HFONT hOldFont;
253 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
255 hOldFont = (HFONT)SelectObject(hdc, handle);
257 GetTextMetricsA(hdc, lptm);
259 SelectObject(hdc, hOldFont);
261 DeleteDC(hdc);
264 static inline void FixStockFontSize16(
265 HFONT handle,
266 INT16 count,
267 LPVOID buffer)
269 TEXTMETRICA tm;
270 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
273 * Was the lfHeight field copied (it's the first field)?
274 * If it was and it was null, replace the height.
276 if ( (count >= 2*sizeof(INT16)) &&
277 (pLogFont->lfHeight == 0) )
279 GetFontMetrics(handle, &tm);
281 pLogFont->lfHeight = tm.tmHeight;
282 pLogFont->lfWidth = tm.tmAveCharWidth;
286 static inline void FixStockFontSizeA(
287 HFONT handle,
288 INT count,
289 LPVOID buffer)
291 TEXTMETRICA tm;
292 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
295 * Was the lfHeight field copied (it's the first field)?
296 * If it was and it was null, replace the height.
298 if ( (count >= 2*sizeof(INT)) &&
299 (pLogFont->lfHeight == 0) )
301 GetFontMetrics(handle, &tm);
303 pLogFont->lfHeight = tm.tmHeight;
304 pLogFont->lfWidth = tm.tmAveCharWidth;
309 * Since the LOGFONTA and LOGFONTW structures are identical up to the
310 * lfHeight member (the one of interest in this case) we simply define
311 * the W version as the A version.
313 #define FixStockFontSizeW FixStockFontSizeA
317 /***********************************************************************
318 * GDI_Init
320 * GDI initialization.
322 BOOL GDI_Init(void)
324 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
326 /* Kill some warnings. */
327 (void)align_OEMFixedFont;
328 (void)align_AnsiFixedFont;
329 (void)align_AnsiVarFont;
330 (void)align_SystemFont;
331 (void)align_DeviceDefaultFont;
332 (void)align_SystemFixedFont;
333 (void)align_DefaultGuiFont;
335 /* TWEAK: Initialize font hints */
336 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
337 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
338 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
339 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
340 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
341 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
342 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
344 /* Initialize drivers */
346 #ifndef X_DISPLAY_MISSING
347 GDI_Driver = &X11DRV_GDI_Driver;
348 #else /* !defined(X_DISPLAY_MISSING) */
349 GDI_Driver = &TTYDRV_GDI_Driver;
350 #endif /* !defined(X_DISPLAY_MISSING */
352 GDI_Driver->pInitialize();
354 /* Create default palette */
356 /* DR well *this* palette can't be moveable (?) */
358 HPALETTE16 hpalette = PALETTE_Init();
359 if( !hpalette )
360 return FALSE;
361 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
364 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
365 return TRUE;
369 /***********************************************************************
370 * GDI_AllocObject
372 HGDIOBJ16 GDI_AllocObject( WORD size, WORD magic )
374 static DWORD count = 0;
375 GDIOBJHDR * obj;
376 HGDIOBJ16 handle;
377 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
378 handle = GDI_HEAP_ALLOC( size );
379 else
380 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
381 if (!handle) return 0;
382 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
383 obj->hNext = 0;
384 obj->wMagic = magic;
385 obj->dwCount = ++count;
386 GDI_HEAP_UNLOCK( handle );
387 return handle;
391 /***********************************************************************
392 * GDI_FreeObject
394 BOOL GDI_FreeObject( HGDIOBJ16 handle )
396 GDIOBJHDR * object;
398 /* Can't free stock objects */
399 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
400 return TRUE;
402 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
403 if (!object) return FALSE;
404 object->wMagic = 0; /* Mark it as invalid */
406 /* Free object */
408 GDI_HEAP_FREE( handle );
409 return TRUE;
412 /***********************************************************************
413 * GDI_GetObjPtr
415 * Return a pointer to the GDI object associated to the handle.
416 * Return NULL if the object has the wrong magic number.
417 * Movable GDI objects are locked in memory: it is up to the caller to unlock
418 * it after the caller is done with the pointer.
420 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16 handle, WORD magic )
422 GDIOBJHDR * ptr = NULL;
424 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
425 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
426 else
427 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
428 if (!ptr) return NULL;
429 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
431 GDI_HEAP_UNLOCK( handle );
432 return NULL;
434 return ptr;
438 /***********************************************************************
439 * DeleteObject16 (GDI.69)
441 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
443 return DeleteObject( obj );
447 /***********************************************************************
448 * DeleteObject32 (GDI32.70)
450 BOOL WINAPI DeleteObject( HGDIOBJ obj )
452 /* Check if object is valid */
454 GDIOBJHDR * header;
455 if (HIWORD(obj)) return FALSE;
456 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
457 return TRUE;
458 if (obj == hPseudoStockBitmap) return TRUE;
459 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
461 TRACE("%04x\n", obj );
463 /* Delete object */
465 switch(header->wMagic)
467 case PEN_MAGIC: return GDI_FreeObject( obj );
468 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
469 case FONT_MAGIC: return GDI_FreeObject( obj );
470 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
471 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
472 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
473 case DC_MAGIC: return DeleteDC(obj);
474 case 0 :
475 WARN("Already deleted\n");
476 break;
477 default:
478 WARN("Unknown magic number (%d)\n",header->wMagic);
480 return FALSE;
483 /***********************************************************************
484 * GetStockObject16 (GDI.87)
486 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
488 return (HGDIOBJ16)GetStockObject( obj );
492 /***********************************************************************
493 * GetStockObject32 (GDI32.220)
495 HGDIOBJ WINAPI GetStockObject( INT obj )
497 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
498 if (!StockObjects[obj]) return 0;
499 TRACE("returning %d\n",
500 FIRST_STOCK_HANDLE + obj );
501 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
505 /***********************************************************************
506 * GetObject16 (GDI.82)
508 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
510 GDIOBJHDR * ptr = NULL;
511 INT16 result = 0;
512 TRACE("%04x %d %p\n", handle, count, buffer );
513 if (!count) return 0;
515 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
516 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
517 else
518 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
519 if (!ptr) return 0;
521 switch(ptr->wMagic)
523 case PEN_MAGIC:
524 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
525 break;
526 case BRUSH_MAGIC:
527 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
528 break;
529 case BITMAP_MAGIC:
530 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
531 break;
532 case FONT_MAGIC:
533 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
536 * Fix the LOGFONT structure for the stock fonts
538 if ( (handle >= FIRST_STOCK_HANDLE) &&
539 (handle <= LAST_STOCK_HANDLE) )
540 FixStockFontSize16(handle, count, buffer);
541 break;
542 case PALETTE_MAGIC:
543 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
544 break;
546 GDI_HEAP_UNLOCK( handle );
547 return result;
551 /***********************************************************************
552 * GetObject32A (GDI32.204)
554 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
556 GDIOBJHDR * ptr = NULL;
557 INT result = 0;
558 TRACE("%08x %d %p\n", handle, count, buffer );
559 if (!count) return 0;
561 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
562 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
563 else
564 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
565 if (!ptr) return 0;
567 switch(ptr->wMagic)
569 case PEN_MAGIC:
570 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
571 break;
572 case BRUSH_MAGIC:
573 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
574 break;
575 case BITMAP_MAGIC:
576 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
577 break;
578 case FONT_MAGIC:
579 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
582 * Fix the LOGFONT structure for the stock fonts
584 if ( (handle >= FIRST_STOCK_HANDLE) &&
585 (handle <= LAST_STOCK_HANDLE) )
586 FixStockFontSizeA(handle, count, buffer);
587 break;
588 case PALETTE_MAGIC:
589 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
590 break;
591 default:
592 FIXME("Magic %04x not implemented\n",
593 ptr->wMagic );
594 break;
596 GDI_HEAP_UNLOCK( handle );
597 return result;
599 /***********************************************************************
600 * GetObject32W (GDI32.206)
602 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
604 GDIOBJHDR * ptr = NULL;
605 INT result = 0;
606 TRACE("%08x %d %p\n", handle, count, buffer );
607 if (!count) return 0;
609 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
610 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
611 else
612 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
613 if (!ptr) return 0;
615 switch(ptr->wMagic)
617 case PEN_MAGIC:
618 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
619 break;
620 case BRUSH_MAGIC:
621 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
622 break;
623 case BITMAP_MAGIC:
624 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
625 break;
626 case FONT_MAGIC:
627 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
630 * Fix the LOGFONT structure for the stock fonts
632 if ( (handle >= FIRST_STOCK_HANDLE) &&
633 (handle <= LAST_STOCK_HANDLE) )
634 FixStockFontSizeW(handle, count, buffer);
635 break;
636 case PALETTE_MAGIC:
637 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
638 break;
639 default:
640 FIXME("Magic %04x not implemented\n",
641 ptr->wMagic );
642 break;
644 GDI_HEAP_UNLOCK( handle );
645 return result;
648 /***********************************************************************
649 * GetObjectType (GDI32.205)
651 DWORD WINAPI GetObjectType( HANDLE handle )
653 GDIOBJHDR * ptr = NULL;
654 INT result = 0;
655 TRACE("%08x\n", handle );
657 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
658 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
659 else
660 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
661 if (!ptr) return 0;
663 switch(ptr->wMagic)
665 case PEN_MAGIC:
666 result = OBJ_PEN;
667 break;
668 case BRUSH_MAGIC:
669 result = OBJ_BRUSH;
670 break;
671 case BITMAP_MAGIC:
672 result = OBJ_BITMAP;
673 break;
674 case FONT_MAGIC:
675 result = OBJ_FONT;
676 break;
677 case PALETTE_MAGIC:
678 result = OBJ_PAL;
679 break;
680 case REGION_MAGIC:
681 result = OBJ_REGION;
682 break;
683 case DC_MAGIC:
684 result = OBJ_DC;
685 break;
686 case META_DC_MAGIC:
687 result = OBJ_METADC;
688 break;
689 case METAFILE_MAGIC:
690 result = OBJ_METAFILE;
691 break;
692 case METAFILE_DC_MAGIC:
693 result = OBJ_METADC;
694 break;
695 case ENHMETAFILE_MAGIC:
696 result = OBJ_ENHMETAFILE;
697 break;
698 case ENHMETAFILE_DC_MAGIC:
699 result = OBJ_ENHMETADC;
700 break;
701 default:
702 FIXME("Magic %04x not implemented\n",
703 ptr->wMagic );
704 break;
706 GDI_HEAP_UNLOCK( handle );
707 return result;
710 /***********************************************************************
711 * GetCurrentObject (GDI32.166)
713 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
715 DC * dc = DC_GetDCPtr( hdc );
717 if (!dc)
718 return 0;
719 switch (type) {
720 case OBJ_PEN: return dc->w.hPen;
721 case OBJ_BRUSH: return dc->w.hBrush;
722 case OBJ_PAL: return dc->w.hPalette;
723 case OBJ_FONT: return dc->w.hFont;
724 case OBJ_BITMAP: return dc->w.hBitmap;
725 default:
726 /* the SDK only mentions those above */
727 WARN("(%08x,%d): unknown type.\n",hdc,type);
728 return 0;
733 /***********************************************************************
734 * SelectObject16 (GDI.45)
736 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
738 return (HGDIOBJ16)SelectObject( hdc, handle );
742 /***********************************************************************
743 * SelectObject32 (GDI32.299)
745 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
747 DC * dc = DC_GetDCPtr( hdc );
748 if (!dc || !dc->funcs->pSelectObject) return 0;
749 TRACE("hdc=%04x %04x\n", hdc, handle );
750 return dc->funcs->pSelectObject( dc, handle );
754 /***********************************************************************
755 * UnrealizeObject16 (GDI.150)
757 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
759 return UnrealizeObject( obj );
763 /***********************************************************************
764 * UnrealizeObject (GDI32.358)
766 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
768 BOOL result = TRUE;
769 /* Check if object is valid */
771 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
772 if (!header) return FALSE;
774 TRACE("%04x\n", obj );
776 /* Unrealize object */
778 switch(header->wMagic)
780 case PALETTE_MAGIC:
781 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
782 break;
784 case BRUSH_MAGIC:
785 /* Windows resets the brush origin. We don't need to. */
786 break;
788 GDI_HEAP_UNLOCK( obj );
789 return result;
793 /***********************************************************************
794 * EnumObjects16 (GDI.71)
796 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
797 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
799 /* Solid colors to enumerate */
800 static const COLORREF solid_colors[] =
801 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
802 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
803 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
804 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
805 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
806 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
807 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
808 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
811 INT16 i, retval = 0;
812 LOGPEN16 *pen;
813 LOGBRUSH16 *brush = NULL;
815 TRACE("%04x %d %08lx %08lx\n",
816 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
817 switch(nObjType)
819 case OBJ_PEN:
820 /* Enumerate solid pens */
821 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
822 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
824 pen->lopnStyle = PS_SOLID;
825 pen->lopnWidth.x = 1;
826 pen->lopnWidth.y = 0;
827 pen->lopnColor = solid_colors[i];
828 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
829 TRACE("solid pen %08lx, ret=%d\n",
830 solid_colors[i], retval);
831 if (!retval) break;
833 SEGPTR_FREE(pen);
834 break;
836 case OBJ_BRUSH:
837 /* Enumerate solid brushes */
838 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
839 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
841 brush->lbStyle = BS_SOLID;
842 brush->lbColor = solid_colors[i];
843 brush->lbHatch = 0;
844 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
845 TRACE("solid brush %08lx, ret=%d\n",
846 solid_colors[i], retval);
847 if (!retval) break;
850 /* Now enumerate hatched brushes */
851 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
853 brush->lbStyle = BS_HATCHED;
854 brush->lbColor = RGB(0,0,0);
855 brush->lbHatch = i;
856 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
857 TRACE("hatched brush %d, ret=%d\n",
858 i, retval);
859 if (!retval) break;
861 SEGPTR_FREE(brush);
862 break;
864 default:
865 WARN("(%d): Invalid type\n", nObjType );
866 break;
868 return retval;
872 /***********************************************************************
873 * EnumObjects32 (GDI32.89)
875 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
876 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
878 /* Solid colors to enumerate */
879 static const COLORREF solid_colors[] =
880 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
881 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
882 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
883 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
884 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
885 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
886 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
887 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
890 INT i, retval = 0;
891 LOGPEN pen;
892 LOGBRUSH brush;
894 TRACE("%04x %d %08lx %08lx\n",
895 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
896 switch(nObjType)
898 case OBJ_PEN:
899 /* Enumerate solid pens */
900 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
902 pen.lopnStyle = PS_SOLID;
903 pen.lopnWidth.x = 1;
904 pen.lopnWidth.y = 0;
905 pen.lopnColor = solid_colors[i];
906 retval = lpEnumFunc( &pen, lParam );
907 TRACE("solid pen %08lx, ret=%d\n",
908 solid_colors[i], retval);
909 if (!retval) break;
911 break;
913 case OBJ_BRUSH:
914 /* Enumerate solid brushes */
915 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
917 brush.lbStyle = BS_SOLID;
918 brush.lbColor = solid_colors[i];
919 brush.lbHatch = 0;
920 retval = lpEnumFunc( &brush, lParam );
921 TRACE("solid brush %08lx, ret=%d\n",
922 solid_colors[i], retval);
923 if (!retval) break;
926 /* Now enumerate hatched brushes */
927 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
929 brush.lbStyle = BS_HATCHED;
930 brush.lbColor = RGB(0,0,0);
931 brush.lbHatch = i;
932 retval = lpEnumFunc( &brush, lParam );
933 TRACE("hatched brush %d, ret=%d\n",
934 i, retval);
935 if (!retval) break;
937 break;
939 default:
940 /* FIXME: implement Win32 types */
941 WARN("(%d): Invalid type\n", nObjType );
942 break;
944 return retval;
948 /***********************************************************************
949 * IsGDIObject (GDI.462)
951 * returns type of object if valid (W95 system programming secrets p. 264-5)
953 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
955 UINT16 magic = 0;
957 if (handle >= FIRST_STOCK_HANDLE )
959 switch (handle)
961 case STOCK_WHITE_BRUSH:
962 case STOCK_LTGRAY_BRUSH:
963 case STOCK_GRAY_BRUSH:
964 case STOCK_DKGRAY_BRUSH:
965 case STOCK_BLACK_BRUSH:
966 case STOCK_HOLLOW_BRUSH:
967 magic = BRUSH_MAGIC;
968 break;
970 case STOCK_WHITE_PEN:
971 case STOCK_BLACK_PEN:
972 case STOCK_NULL_PEN :
973 magic = PEN_MAGIC;
974 break;
976 case STOCK_OEM_FIXED_FONT:
977 case STOCK_ANSI_FIXED_FONT:
978 case STOCK_ANSI_VAR_FONT:
979 case STOCK_SYSTEM_FONT:
980 case STOCK_DEVICE_DEFAULT_FONT:
981 case STOCK_SYSTEM_FIXED_FONT:
982 case STOCK_DEFAULT_GUI_FONT:
983 magic = FONT_MAGIC;
984 break;
986 case STOCK_DEFAULT_PALETTE:
987 magic = PALETTE_MAGIC;
988 break;
991 else
993 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
994 if (object)
996 magic = object->wMagic;
997 GDI_HEAP_UNLOCK( handle );
1001 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
1002 return magic - PEN_MAGIC + 1;
1003 else
1004 return FALSE;
1008 /***********************************************************************
1009 * SetObjectOwner16 (GDI.461)
1011 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1013 /* Nothing to do */
1017 /***********************************************************************
1018 * SetObjectOwner32 (GDI32.386)
1020 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1022 /* Nothing to do */
1025 /***********************************************************************
1026 * MakeObjectPrivate (GDI.463)
1028 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1030 /* FIXME */
1034 /***********************************************************************
1035 * GdiFlush (GDI32.128)
1037 BOOL WINAPI GdiFlush(void)
1039 return TRUE; /* FIXME */
1043 /***********************************************************************
1044 * GdiGetBatchLimit (GDI32.129)
1046 DWORD WINAPI GdiGetBatchLimit(void)
1048 return 1; /* FIXME */
1052 /***********************************************************************
1053 * GdiSetBatchLimit (GDI32.139)
1055 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1057 return 1; /* FIXME */
1061 /***********************************************************************
1062 * GdiSeeGdiDo (GDI.452)
1064 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1065 WORD wParam3 )
1067 switch (wReqType)
1069 case 0x0001: /* LocalAlloc */
1070 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1071 case 0x0002: /* LocalFree */
1072 return LOCAL_Free( GDI_HeapSel, wParam1 );
1073 case 0x0003: /* LocalCompact */
1074 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1075 case 0x0103: /* LocalHeap */
1076 return GDI_HeapSel;
1077 default:
1078 WARN("(wReqType=%04x): Unknown\n", wReqType);
1079 return (DWORD)-1;
1083 /***********************************************************************
1084 * GdiSignalProc (GDI.610)
1086 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1087 DWORD dwFlags, HMODULE16 hModule )
1089 return 0;
1092 /***********************************************************************
1093 * FinalGdiInit16 (GDI.405)
1095 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1099 /***********************************************************************
1100 * GdiFreeResources (GDI.609)
1102 WORD WINAPI GdiFreeResources16( DWORD reserve )
1104 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1105 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1108 /***********************************************************************
1109 * MulDiv16 (GDI.128)
1111 INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
1113 INT ret;
1114 if (!baz) return -32768;
1115 ret = (foo * bar) / baz;
1116 if ((ret > 32767) || (ret < -32767)) return -32768;
1117 return ret;
1121 /***********************************************************************
1122 * MulDiv32 (KERNEL32.391)
1123 * RETURNS
1124 * Result of multiplication and division
1125 * -1: Overflow occurred or Divisor was 0
1127 INT WINAPI MulDiv(
1128 INT nMultiplicand,
1129 INT nMultiplier,
1130 INT nDivisor
1132 #if SIZEOF_LONG_LONG >= 8
1133 long long ret;
1135 if (!nDivisor) return -1;
1137 /* We want to deal with a positive divisor to simplify the logic. */
1138 if (nDivisor < 0)
1140 nMultiplicand = - nMultiplicand;
1141 nDivisor = -nDivisor;
1144 /* If the result is positive, we "add" to round. else, we subtract to round. */
1145 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1146 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1147 ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1148 else
1149 ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1151 if ((ret > 2147483647) || (ret < -2147483647)) return -1;
1152 return ret;
1153 #else
1154 if (!nDivisor) return -1;
1156 /* We want to deal with a positive divisor to simplify the logic. */
1157 if (nDivisor < 0)
1159 nMultiplicand = - nMultiplicand;
1160 nDivisor = -nDivisor;
1163 /* If the result is positive, we "add" to round. else, we subtract to round. */
1164 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1165 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1166 return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1168 return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1170 #endif
1172 /*******************************************************************
1173 * GetColorAdjustment [GDI32.164]
1177 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1179 FIXME("GetColorAdjustment, stub\n");
1180 return 0;
1183 /*******************************************************************
1184 * GetMiterLimit [GDI32.201]
1188 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1190 FIXME("GetMiterLimit, stub\n");
1191 return 0;
1194 /*******************************************************************
1195 * SetMiterLimit [GDI32.325]
1199 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1201 FIXME("SetMiterLimit, stub\n");
1202 return 0;
1205 /*******************************************************************
1206 * GdiComment [GDI32.109]
1210 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1212 FIXME("GdiComment, stub\n");
1213 return 0;
1215 /*******************************************************************
1216 * SetColorAdjustment [GDI32.309]
1220 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1222 FIXME("SetColorAdjustment, stub\n");
1223 return 0;