Removed direct calls to TREEVIEW_Refresh().
[wine/wine64.git] / objects / gdiobj.c
bloba94cd15192744f2356d2bc728f980441f6678319
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <assert.h>
10 #include <stdlib.h>
11 #include <stdio.h>
13 #include "windef.h"
14 #include "wingdi.h"
15 #include "winerror.h"
16 #include "wine/winbase16.h"
18 #include "bitmap.h"
19 #include "brush.h"
20 #include "dc.h"
21 #include "font.h"
22 #include "heap.h"
23 #include "options.h"
24 #include "palette.h"
25 #include "pen.h"
26 #include "region.h"
27 #include "debugtools.h"
28 #include "gdi.h"
29 #include "tweak.h"
30 #include "syslevel.h"
32 DEFAULT_DEBUG_CHANNEL(gdi);
34 /**********************************************************************/
36 GDI_DRIVER *GDI_Driver = NULL;
38 /***********************************************************************
39 * GDI stock objects
42 static BRUSHOBJ WhiteBrush =
44 { 0, BRUSH_MAGIC, 1 }, /* header */
45 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
48 static BRUSHOBJ LtGrayBrush =
50 { 0, BRUSH_MAGIC, 1 }, /* header */
51 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
52 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
55 static BRUSHOBJ GrayBrush =
57 { 0, BRUSH_MAGIC, 1 }, /* header */
58 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
59 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
62 static BRUSHOBJ DkGrayBrush =
64 { 0, BRUSH_MAGIC, 1 }, /* header */
65 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
66 /* NB_HATCH_STYLES is an index into HatchBrushes */
67 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
70 static BRUSHOBJ BlackBrush =
72 { 0, BRUSH_MAGIC, 1 }, /* header */
73 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
76 static BRUSHOBJ NullBrush =
78 { 0, BRUSH_MAGIC, 1 }, /* header */
79 { BS_NULL, 0, 0 } /* logbrush */
82 static PENOBJ WhitePen =
84 { 0, PEN_MAGIC, 1 }, /* header */
85 { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
88 static PENOBJ BlackPen =
90 { 0, PEN_MAGIC, 1 }, /* header */
91 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
94 static PENOBJ NullPen =
96 { 0, PEN_MAGIC, 1 }, /* header */
97 { PS_NULL, { 1, 0 }, 0 } /* logpen */
100 static FONTOBJ OEMFixedFont =
102 { 0, FONT_MAGIC, 1 }, /* header */
103 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
104 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
106 /* Filler to make the location counter dword aligned again. This is necessary
107 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
108 segment, and (c) Solaris assembler is stupid. */
109 static UINT16 align_OEMFixedFont = 1;
111 static FONTOBJ AnsiFixedFont =
113 { 0, FONT_MAGIC, 1 }, /* header */
114 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
115 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
117 static UINT16 align_AnsiFixedFont = 1;
119 static FONTOBJ AnsiVarFont =
121 { 0, FONT_MAGIC, 1 }, /* header */
122 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
123 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
125 static UINT16 align_AnsiVarFont = 1;
127 static FONTOBJ SystemFont =
129 { 0, FONT_MAGIC, 1 },
130 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
131 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
133 static UINT16 align_SystemFont = 1;
135 static FONTOBJ DeviceDefaultFont =
137 { 0, FONT_MAGIC, 1 }, /* header */
138 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
139 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
141 static UINT16 align_DeviceDefaultFont = 1;
143 static FONTOBJ SystemFixedFont =
145 { 0, FONT_MAGIC, 1 }, /* header */
146 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
147 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
149 static UINT16 align_SystemFixedFont = 1;
151 /* FIXME: Is this correct? */
152 static FONTOBJ DefaultGuiFont =
154 { 0, FONT_MAGIC, 1 }, /* header */
155 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
156 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
158 static UINT16 align_DefaultGuiFont = 1;
161 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
163 (GDIOBJHDR *) &WhiteBrush,
164 (GDIOBJHDR *) &LtGrayBrush,
165 (GDIOBJHDR *) &GrayBrush,
166 (GDIOBJHDR *) &DkGrayBrush,
167 (GDIOBJHDR *) &BlackBrush,
168 (GDIOBJHDR *) &NullBrush,
169 (GDIOBJHDR *) &WhitePen,
170 (GDIOBJHDR *) &BlackPen,
171 (GDIOBJHDR *) &NullPen,
172 NULL,
173 (GDIOBJHDR *) &OEMFixedFont,
174 (GDIOBJHDR *) &AnsiFixedFont,
175 (GDIOBJHDR *) &AnsiVarFont,
176 (GDIOBJHDR *) &SystemFont,
177 (GDIOBJHDR *) &DeviceDefaultFont,
178 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
179 (GDIOBJHDR *) &SystemFixedFont,
180 (GDIOBJHDR *) &DefaultGuiFont
183 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
185 static SYSLEVEL GDI_level;
186 static WORD GDI_HeapSel;
189 /******************************************************************************
191 * void ReadFontInformation(
192 * char const *fontName,
193 * FONTOBJ *font,
194 * int defHeight,
195 * int defBold,
196 * int defItalic,
197 * int defUnderline,
198 * int defStrikeOut )
200 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
201 * section for entries containing fontName.Height, fontName.Bold, etc.,
202 * where fontName is the name specified in the call (e.g., "System"). It
203 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
204 * the first character in the boolean attributes (bold, italic, and
205 * underline).
206 *****************************************************************************/
208 static void ReadFontInformation(
209 char const *fontName,
210 FONTOBJ *font,
211 int defHeight,
212 int defBold,
213 int defItalic,
214 int defUnderline,
215 int defStrikeOut )
217 char key[256];
219 /* In order for the stock fonts to be independent of
220 * mapping mode, the height (& width) must be 0
222 sprintf(key, "%s.Height", fontName);
223 font->logfont.lfHeight =
224 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
226 sprintf(key, "%s.Bold", fontName);
227 font->logfont.lfWeight =
228 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
229 FW_BOLD : FW_NORMAL;
231 sprintf(key, "%s.Italic", fontName);
232 font->logfont.lfItalic =
233 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
235 sprintf(key, "%s.Underline", fontName);
236 font->logfont.lfUnderline =
237 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
239 sprintf(key, "%s.StrikeOut", fontName);
240 font->logfont.lfStrikeOut =
241 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
243 return;
246 /***********************************************************************
247 * Because the stock fonts have their structure initialized with
248 * a height of 0 to keep them independent of mapping mode, simply
249 * returning the LOGFONT as is will not work correctly.
250 * These "FixStockFontSizeXXX()" methods will get the correct
251 * size for the fonts.
253 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
255 HDC hdc;
256 HFONT hOldFont;
258 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
260 hOldFont = (HFONT)SelectObject(hdc, handle);
262 GetTextMetricsA(hdc, lptm);
264 SelectObject(hdc, hOldFont);
266 DeleteDC(hdc);
269 static inline void FixStockFontSize16(
270 HFONT handle,
271 INT16 count,
272 LPVOID buffer)
274 TEXTMETRICA tm;
275 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
278 * Was the lfHeight field copied (it's the first field)?
279 * If it was and it was null, replace the height.
281 if ( (count >= 2*sizeof(INT16)) &&
282 (pLogFont->lfHeight == 0) )
284 GetFontMetrics(handle, &tm);
286 pLogFont->lfHeight = tm.tmHeight;
287 pLogFont->lfWidth = tm.tmAveCharWidth;
291 static inline void FixStockFontSizeA(
292 HFONT handle,
293 INT count,
294 LPVOID buffer)
296 TEXTMETRICA tm;
297 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
300 * Was the lfHeight field copied (it's the first field)?
301 * If it was and it was null, replace the height.
303 if ( (count >= 2*sizeof(INT)) &&
304 (pLogFont->lfHeight == 0) )
306 GetFontMetrics(handle, &tm);
308 pLogFont->lfHeight = tm.tmHeight;
309 pLogFont->lfWidth = tm.tmAveCharWidth;
314 * Since the LOGFONTA and LOGFONTW structures are identical up to the
315 * lfHeight member (the one of interest in this case) we simply define
316 * the W version as the A version.
318 #define FixStockFontSizeW FixStockFontSizeA
320 #define TRACE_SEC(handle,text) \
321 TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
323 /***********************************************************************
324 * GDI_Init
326 * GDI initialization.
328 BOOL GDI_Init(void)
330 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
331 HPALETTE16 hpalette;
332 HINSTANCE16 instance;
334 _CreateSysLevel( &GDI_level, 3 );
336 /* create GDI heap */
337 if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
338 GDI_HeapSel = GlobalHandleToSel16( instance );
340 /* Kill some warnings. */
341 (void)align_OEMFixedFont;
342 (void)align_AnsiFixedFont;
343 (void)align_AnsiVarFont;
344 (void)align_SystemFont;
345 (void)align_DeviceDefaultFont;
346 (void)align_SystemFixedFont;
347 (void)align_DefaultGuiFont;
349 /* TWEAK: Initialize font hints */
350 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
351 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
352 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
353 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
354 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
355 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
356 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
358 /* Create default palette */
360 /* DR well *this* palette can't be moveable (?) */
361 hpalette = PALETTE_Init();
362 if( !hpalette ) return FALSE;
363 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hpalette );
365 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
366 return TRUE;
370 /***********************************************************************
371 * GDI_AllocObject
373 void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
375 static DWORD count = 0;
376 GDIOBJHDR *obj;
378 _EnterSysLevel( &GDI_level );
379 if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size )))
381 _LeaveSysLevel( &GDI_level );
382 return NULL;
384 obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
385 obj->hNext = 0;
386 obj->wMagic = magic;
387 obj->dwCount = ++count;
389 TRACE_SEC( *handle, "enter" );
390 return obj;
394 /***********************************************************************
395 * GDI_ReallocObject
397 * The object ptr must have been obtained with GDI_GetObjPtr.
398 * The new pointer must be released with GDI_ReleaseObj.
400 void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
402 HGDIOBJ new_handle;
404 LOCAL_Unlock( GDI_HeapSel, handle );
405 if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
407 TRACE_SEC( handle, "leave" );
408 _LeaveSysLevel( &GDI_level );
409 return NULL;
411 assert( new_handle == handle ); /* moveable handle cannot change */
412 return LOCAL_Lock( GDI_HeapSel, handle );
416 /***********************************************************************
417 * GDI_FreeObject
419 BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
421 GDIOBJHDR *object = ptr;
423 /* can't free stock objects */
424 if (handle < FIRST_STOCK_HANDLE)
426 object->wMagic = 0; /* Mark it as invalid */
427 LOCAL_Unlock( GDI_HeapSel, handle );
428 LOCAL_Free( GDI_HeapSel, handle );
430 TRACE_SEC( handle, "leave" );
431 _LeaveSysLevel( &GDI_level );
432 return TRUE;
436 /***********************************************************************
437 * GDI_GetObjPtr
439 * Return a pointer to the GDI object associated to the handle.
440 * Return NULL if the object has the wrong magic number.
441 * The object must be released with GDI_ReleaseObj.
443 void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
445 GDIOBJHDR *ptr = NULL;
447 _EnterSysLevel( &GDI_level );
449 if (handle >= FIRST_STOCK_HANDLE)
451 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
452 if (ptr && (magic != MAGIC_DONTCARE) && (ptr->wMagic != magic)) ptr = NULL;
454 else
456 ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
457 if (ptr && (magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
459 LOCAL_Unlock( GDI_HeapSel, handle );
460 ptr = NULL;
464 if (!ptr)
466 _LeaveSysLevel( &GDI_level );
467 SetLastError( ERROR_INVALID_HANDLE );
469 else TRACE_SEC( handle, "enter" );
471 return ptr;
475 /***********************************************************************
476 * GDI_ReleaseObj
479 void GDI_ReleaseObj( HGDIOBJ handle )
481 if (handle < FIRST_STOCK_HANDLE) LOCAL_Unlock( GDI_HeapSel, handle );
482 TRACE_SEC( handle, "leave" );
483 _LeaveSysLevel( &GDI_level );
487 /***********************************************************************
488 * DeleteObject16 (GDI.69)
490 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
492 return DeleteObject( obj );
496 /***********************************************************************
497 * DeleteObject (GDI32.70)
499 BOOL WINAPI DeleteObject( HGDIOBJ obj )
501 /* Check if object is valid */
503 GDIOBJHDR * header;
504 if (HIWORD(obj)) return FALSE;
505 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE)) {
506 TRACE("Preserving Stock object %04x\n", obj );
507 /* NOTE: No GDI_Release is necessary */
508 return TRUE;
510 if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
512 TRACE("%04x\n", obj );
514 /* Delete object */
516 switch(header->wMagic)
518 case PEN_MAGIC: return GDI_FreeObject( obj, header );
519 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
520 case FONT_MAGIC: return GDI_FreeObject( obj, header );
521 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
522 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
523 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
524 case DC_MAGIC:
525 GDI_ReleaseObj( obj );
526 return DeleteDC(obj);
527 case 0 :
528 WARN("Already deleted\n");
529 break;
530 default:
531 WARN("Unknown magic number (%d)\n",header->wMagic);
533 GDI_ReleaseObj( obj );
534 return FALSE;
537 /***********************************************************************
538 * GetStockObject16 (GDI.87)
540 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
542 return (HGDIOBJ16)GetStockObject( obj );
546 /***********************************************************************
547 * GetStockObject (GDI32.220)
549 HGDIOBJ WINAPI GetStockObject( INT obj )
551 HGDIOBJ ret;
552 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
553 if (!StockObjects[obj]) return 0;
554 ret = (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
555 TRACE("returning %4x\n", ret );
556 return ret;
560 /***********************************************************************
561 * GetObject16 (GDI.82)
563 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
565 GDIOBJHDR * ptr;
566 INT16 result = 0;
567 TRACE("%04x %d %p\n", handle, count, buffer );
568 if (!count) return 0;
570 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
572 switch(ptr->wMagic)
574 case PEN_MAGIC:
575 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
576 break;
577 case BRUSH_MAGIC:
578 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
579 break;
580 case BITMAP_MAGIC:
581 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
582 break;
583 case FONT_MAGIC:
584 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
587 * Fix the LOGFONT structure for the stock fonts
589 if ( (handle >= FIRST_STOCK_HANDLE) &&
590 (handle <= LAST_STOCK_HANDLE) )
591 FixStockFontSize16(handle, count, buffer);
592 break;
593 case PALETTE_MAGIC:
594 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
595 break;
597 GDI_ReleaseObj( handle );
598 return result;
602 /***********************************************************************
603 * GetObjectA (GDI32.204)
605 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
607 GDIOBJHDR * ptr;
608 INT result = 0;
609 TRACE("%08x %d %p\n", handle, count, buffer );
610 if (!count) return 0;
612 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
614 switch(ptr->wMagic)
616 case PEN_MAGIC:
617 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
618 break;
619 case BRUSH_MAGIC:
620 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
621 break;
622 case BITMAP_MAGIC:
623 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
624 break;
625 case FONT_MAGIC:
626 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
629 * Fix the LOGFONT structure for the stock fonts
631 if ( (handle >= FIRST_STOCK_HANDLE) &&
632 (handle <= LAST_STOCK_HANDLE) )
633 FixStockFontSizeA(handle, count, buffer);
634 break;
635 case PALETTE_MAGIC:
636 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
637 break;
639 case REGION_MAGIC:
640 case DC_MAGIC:
641 case DISABLED_DC_MAGIC:
642 case META_DC_MAGIC:
643 case METAFILE_MAGIC:
644 case METAFILE_DC_MAGIC:
645 case ENHMETAFILE_MAGIC:
646 case ENHMETAFILE_DC_MAGIC:
647 FIXME("Magic %04x not implemented\n",
648 ptr->wMagic );
649 break;
651 default:
652 ERR("Invalid GDI Magic %04x\n", ptr->wMagic);
653 return 0;
655 GDI_ReleaseObj( handle );
656 return result;
659 /***********************************************************************
660 * GetObjectW (GDI32.206)
662 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
664 GDIOBJHDR * ptr;
665 INT result = 0;
666 TRACE("%08x %d %p\n", handle, count, buffer );
667 if (!count) return 0;
669 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
671 switch(ptr->wMagic)
673 case PEN_MAGIC:
674 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
675 break;
676 case BRUSH_MAGIC:
677 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
678 break;
679 case BITMAP_MAGIC:
680 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
681 break;
682 case FONT_MAGIC:
683 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
686 * Fix the LOGFONT structure for the stock fonts
688 if ( (handle >= FIRST_STOCK_HANDLE) &&
689 (handle <= LAST_STOCK_HANDLE) )
690 FixStockFontSizeW(handle, count, buffer);
691 break;
692 case PALETTE_MAGIC:
693 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
694 break;
695 default:
696 FIXME("Magic %04x not implemented\n",
697 ptr->wMagic );
698 break;
700 GDI_ReleaseObj( handle );
701 return result;
704 /***********************************************************************
705 * GetObjectType (GDI32.205)
707 DWORD WINAPI GetObjectType( HANDLE handle )
709 GDIOBJHDR * ptr;
710 INT result = 0;
711 TRACE("%08x\n", handle );
713 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
715 switch(ptr->wMagic)
717 case PEN_MAGIC:
718 result = OBJ_PEN;
719 break;
720 case BRUSH_MAGIC:
721 result = OBJ_BRUSH;
722 break;
723 case BITMAP_MAGIC:
724 result = OBJ_BITMAP;
725 break;
726 case FONT_MAGIC:
727 result = OBJ_FONT;
728 break;
729 case PALETTE_MAGIC:
730 result = OBJ_PAL;
731 break;
732 case REGION_MAGIC:
733 result = OBJ_REGION;
734 break;
735 case DC_MAGIC:
736 result = OBJ_DC;
737 break;
738 case META_DC_MAGIC:
739 result = OBJ_METADC;
740 break;
741 case METAFILE_MAGIC:
742 result = OBJ_METAFILE;
743 break;
744 case METAFILE_DC_MAGIC:
745 result = OBJ_METADC;
746 break;
747 case ENHMETAFILE_MAGIC:
748 result = OBJ_ENHMETAFILE;
749 break;
750 case ENHMETAFILE_DC_MAGIC:
751 result = OBJ_ENHMETADC;
752 break;
753 default:
754 FIXME("Magic %04x not implemented\n",
755 ptr->wMagic );
756 break;
758 GDI_ReleaseObj( handle );
759 return result;
762 /***********************************************************************
763 * GetCurrentObject (GDI32.166)
765 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
767 HANDLE ret = 0;
768 DC * dc = DC_GetDCPtr( hdc );
770 if (dc)
772 switch (type) {
773 case OBJ_PEN: ret = dc->w.hPen; break;
774 case OBJ_BRUSH: ret = dc->w.hBrush; break;
775 case OBJ_PAL: ret = dc->w.hPalette; break;
776 case OBJ_FONT: ret = dc->w.hFont; break;
777 case OBJ_BITMAP: ret = dc->w.hBitmap; break;
778 default:
779 /* the SDK only mentions those above */
780 WARN("(%08x,%d): unknown type.\n",hdc,type);
781 break;
783 GDI_ReleaseObj( hdc );
785 return ret;
789 /***********************************************************************
790 * SelectObject16 (GDI.45)
792 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
794 return (HGDIOBJ16)SelectObject( hdc, handle );
798 /***********************************************************************
799 * SelectObject (GDI32.299)
801 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
803 HGDIOBJ ret = 0;
804 DC * dc = DC_GetDCUpdate( hdc );
805 if (!dc) return 0;
806 TRACE("hdc=%04x %04x\n", hdc, handle );
807 if (dc->funcs->pSelectObject)
808 ret = dc->funcs->pSelectObject( dc, handle );
809 GDI_ReleaseObj( hdc );
810 return ret;
814 /***********************************************************************
815 * UnrealizeObject16 (GDI.150)
817 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
819 return UnrealizeObject( obj );
823 /***********************************************************************
824 * UnrealizeObject (GDI32.358)
826 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
828 BOOL result = TRUE;
829 /* Check if object is valid */
831 GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
832 if (!header) return FALSE;
834 TRACE("%04x\n", obj );
836 /* Unrealize object */
838 switch(header->wMagic)
840 case PALETTE_MAGIC:
841 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
842 break;
844 case BRUSH_MAGIC:
845 /* Windows resets the brush origin. We don't need to. */
846 break;
848 GDI_ReleaseObj( obj );
849 return result;
853 /***********************************************************************
854 * EnumObjects16 (GDI.71)
856 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
857 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
859 /* Solid colors to enumerate */
860 static const COLORREF solid_colors[] =
861 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
862 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
863 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
864 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
865 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
866 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
867 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
868 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
871 INT16 i, retval = 0;
872 LOGPEN16 *pen;
873 LOGBRUSH16 *brush = NULL;
875 TRACE("%04x %d %08lx %08lx\n",
876 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
877 switch(nObjType)
879 case OBJ_PEN:
880 /* Enumerate solid pens */
881 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
882 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
884 pen->lopnStyle = PS_SOLID;
885 pen->lopnWidth.x = 1;
886 pen->lopnWidth.y = 0;
887 pen->lopnColor = solid_colors[i];
888 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
889 TRACE("solid pen %08lx, ret=%d\n",
890 solid_colors[i], retval);
891 if (!retval) break;
893 SEGPTR_FREE(pen);
894 break;
896 case OBJ_BRUSH:
897 /* Enumerate solid brushes */
898 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
899 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
901 brush->lbStyle = BS_SOLID;
902 brush->lbColor = solid_colors[i];
903 brush->lbHatch = 0;
904 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
905 TRACE("solid brush %08lx, ret=%d\n",
906 solid_colors[i], retval);
907 if (!retval) break;
910 /* Now enumerate hatched brushes */
911 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
913 brush->lbStyle = BS_HATCHED;
914 brush->lbColor = RGB(0,0,0);
915 brush->lbHatch = i;
916 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
917 TRACE("hatched brush %d, ret=%d\n",
918 i, retval);
919 if (!retval) break;
921 SEGPTR_FREE(brush);
922 break;
924 default:
925 WARN("(%d): Invalid type\n", nObjType );
926 break;
928 return retval;
932 /***********************************************************************
933 * EnumObjects (GDI32.89)
935 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
936 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
938 /* Solid colors to enumerate */
939 static const COLORREF solid_colors[] =
940 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
941 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
942 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
943 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
944 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
945 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
946 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
947 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
950 INT i, retval = 0;
951 LOGPEN pen;
952 LOGBRUSH brush;
954 TRACE("%04x %d %08lx %08lx\n",
955 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
956 switch(nObjType)
958 case OBJ_PEN:
959 /* Enumerate solid pens */
960 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
962 pen.lopnStyle = PS_SOLID;
963 pen.lopnWidth.x = 1;
964 pen.lopnWidth.y = 0;
965 pen.lopnColor = solid_colors[i];
966 retval = lpEnumFunc( &pen, lParam );
967 TRACE("solid pen %08lx, ret=%d\n",
968 solid_colors[i], retval);
969 if (!retval) break;
971 break;
973 case OBJ_BRUSH:
974 /* Enumerate solid brushes */
975 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
977 brush.lbStyle = BS_SOLID;
978 brush.lbColor = solid_colors[i];
979 brush.lbHatch = 0;
980 retval = lpEnumFunc( &brush, lParam );
981 TRACE("solid brush %08lx, ret=%d\n",
982 solid_colors[i], retval);
983 if (!retval) break;
986 /* Now enumerate hatched brushes */
987 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
989 brush.lbStyle = BS_HATCHED;
990 brush.lbColor = RGB(0,0,0);
991 brush.lbHatch = i;
992 retval = lpEnumFunc( &brush, lParam );
993 TRACE("hatched brush %d, ret=%d\n",
994 i, retval);
995 if (!retval) break;
997 break;
999 default:
1000 /* FIXME: implement Win32 types */
1001 WARN("(%d): Invalid type\n", nObjType );
1002 break;
1004 return retval;
1008 /***********************************************************************
1009 * IsGDIObject (GDI.462)
1011 * returns type of object if valid (W95 system programming secrets p. 264-5)
1013 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
1015 UINT16 magic = 0;
1017 GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
1018 if (object)
1020 magic = object->wMagic - PEN_MAGIC + 1;
1021 GDI_ReleaseObj( handle );
1023 return magic;
1027 /***********************************************************************
1028 * SetObjectOwner16 (GDI.461)
1030 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1032 /* Nothing to do */
1036 /***********************************************************************
1037 * SetObjectOwner (GDI32.386)
1039 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1041 /* Nothing to do */
1044 /***********************************************************************
1045 * MakeObjectPrivate (GDI.463)
1047 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1049 /* FIXME */
1053 /***********************************************************************
1054 * GdiFlush (GDI32.128)
1056 BOOL WINAPI GdiFlush(void)
1058 return TRUE; /* FIXME */
1062 /***********************************************************************
1063 * GdiGetBatchLimit (GDI32.129)
1065 DWORD WINAPI GdiGetBatchLimit(void)
1067 return 1; /* FIXME */
1071 /***********************************************************************
1072 * GdiSetBatchLimit (GDI32.139)
1074 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1076 return 1; /* FIXME */
1080 /***********************************************************************
1081 * GdiSeeGdiDo (GDI.452)
1083 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1084 WORD wParam3 )
1086 switch (wReqType)
1088 case 0x0001: /* LocalAlloc */
1089 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1090 case 0x0002: /* LocalFree */
1091 return LOCAL_Free( GDI_HeapSel, wParam1 );
1092 case 0x0003: /* LocalCompact */
1093 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1094 case 0x0103: /* LocalHeap */
1095 return GDI_HeapSel;
1096 default:
1097 WARN("(wReqType=%04x): Unknown\n", wReqType);
1098 return (DWORD)-1;
1102 /***********************************************************************
1103 * GdiSignalProc (GDI.610)
1105 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1106 DWORD dwFlags, HMODULE16 hModule )
1108 return 0;
1111 /***********************************************************************
1112 * FinalGdiInit16 (GDI.405)
1114 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1118 /***********************************************************************
1119 * GdiFreeResources (GDI.609)
1121 WORD WINAPI GdiFreeResources16( DWORD reserve )
1123 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1124 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1127 /***********************************************************************
1128 * MulDiv16 (GDI.128)
1130 INT16 WINAPI MulDiv16(
1131 INT16 nMultiplicand,
1132 INT16 nMultiplier,
1133 INT16 nDivisor)
1135 INT ret;
1136 if (!nDivisor) return -32768;
1137 /* We want to deal with a positive divisor to simplify the logic. */
1138 if (nDivisor < 0)
1140 nMultiplicand = - nMultiplicand;
1141 nDivisor = -nDivisor;
1143 /* If the result is positive, we "add" to round. else,
1144 * we subtract to round. */
1145 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1146 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1147 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1148 else
1149 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1150 if ((ret > 32767) || (ret < -32767)) return -32768;
1151 return (INT16) ret;
1155 /*******************************************************************
1156 * GetColorAdjustment [GDI32.164]
1160 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1162 FIXME("GetColorAdjustment, stub\n");
1163 return 0;
1166 /*******************************************************************
1167 * GetMiterLimit [GDI32.201]
1171 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1173 FIXME("GetMiterLimit, stub\n");
1174 return 0;
1177 /*******************************************************************
1178 * SetMiterLimit [GDI32.325]
1182 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1184 FIXME("SetMiterLimit, stub\n");
1185 return 0;
1188 /*******************************************************************
1189 * GdiComment [GDI32.109]
1193 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1195 FIXME("GdiComment, stub\n");
1196 return 0;
1198 /*******************************************************************
1199 * SetColorAdjustment [GDI32.309]
1203 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1205 FIXME("SetColorAdjustment, stub\n");
1206 return 0;