Fixed segmented/linear buffers manipulation.
[wine.git] / objects / gdiobj.c
blob7295647ed4d11fa45ef859a7079aaa08ec5f3ad0
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <stdio.h>
12 #include "bitmap.h"
13 #include "brush.h"
14 #include "dc.h"
15 #include "font.h"
16 #include "heap.h"
17 #include "options.h"
18 #include "palette.h"
19 #include "pen.h"
20 #include "region.h"
21 #include "debugtools.h"
22 #include "gdi.h"
23 #include "tweak.h"
24 #include "windef.h"
25 #include "wingdi.h"
26 #include "winuser.h"
28 DEFAULT_DEBUG_CHANNEL(gdi)
30 /**********************************************************************/
32 GDI_DRIVER *GDI_Driver = NULL;
34 /***********************************************************************
35 * GDI stock objects
38 static BRUSHOBJ WhiteBrush =
40 { 0, BRUSH_MAGIC, 1 }, /* header */
41 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
44 static BRUSHOBJ LtGrayBrush =
46 { 0, BRUSH_MAGIC, 1 }, /* header */
47 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
48 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
51 static BRUSHOBJ GrayBrush =
53 { 0, BRUSH_MAGIC, 1 }, /* header */
54 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
55 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
58 static BRUSHOBJ DkGrayBrush =
60 { 0, BRUSH_MAGIC, 1 }, /* header */
61 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
62 /* NB_HATCH_STYLES is an index into HatchBrushes */
63 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
66 static BRUSHOBJ BlackBrush =
68 { 0, BRUSH_MAGIC, 1 }, /* header */
69 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
72 static BRUSHOBJ NullBrush =
74 { 0, BRUSH_MAGIC, 1 }, /* header */
75 { BS_NULL, 0, 0 } /* logbrush */
78 static PENOBJ WhitePen =
80 { 0, PEN_MAGIC, 1 }, /* header */
81 { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
84 static PENOBJ BlackPen =
86 { 0, PEN_MAGIC, 1 }, /* header */
87 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
90 static PENOBJ NullPen =
92 { 0, PEN_MAGIC, 1 }, /* header */
93 { PS_NULL, { 1, 0 }, 0 } /* logpen */
96 static FONTOBJ OEMFixedFont =
98 { 0, FONT_MAGIC, 1 }, /* header */
99 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
100 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
102 /* Filler to make the location counter dword aligned again. This is necessary
103 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
104 segment, and (c) Solaris assembler is stupid. */
105 static UINT16 align_OEMFixedFont = 1;
107 static FONTOBJ AnsiFixedFont =
109 { 0, FONT_MAGIC, 1 }, /* header */
110 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
111 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
113 static UINT16 align_AnsiFixedFont = 1;
115 static FONTOBJ AnsiVarFont =
117 { 0, FONT_MAGIC, 1 }, /* header */
118 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
119 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
121 static UINT16 align_AnsiVarFont = 1;
123 static FONTOBJ SystemFont =
125 { 0, FONT_MAGIC, 1 },
126 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
127 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
129 static UINT16 align_SystemFont = 1;
131 static FONTOBJ DeviceDefaultFont =
133 { 0, FONT_MAGIC, 1 }, /* header */
134 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
135 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
137 static UINT16 align_DeviceDefaultFont = 1;
139 static FONTOBJ SystemFixedFont =
141 { 0, FONT_MAGIC, 1 }, /* header */
142 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
143 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
145 static UINT16 align_SystemFixedFont = 1;
147 /* FIXME: Is this correct? */
148 static FONTOBJ DefaultGuiFont =
150 { 0, FONT_MAGIC, 1 }, /* header */
151 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
152 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
154 static UINT16 align_DefaultGuiFont = 1;
157 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
159 (GDIOBJHDR *) &WhiteBrush,
160 (GDIOBJHDR *) &LtGrayBrush,
161 (GDIOBJHDR *) &GrayBrush,
162 (GDIOBJHDR *) &DkGrayBrush,
163 (GDIOBJHDR *) &BlackBrush,
164 (GDIOBJHDR *) &NullBrush,
165 (GDIOBJHDR *) &WhitePen,
166 (GDIOBJHDR *) &BlackPen,
167 (GDIOBJHDR *) &NullPen,
168 NULL,
169 (GDIOBJHDR *) &OEMFixedFont,
170 (GDIOBJHDR *) &AnsiFixedFont,
171 (GDIOBJHDR *) &AnsiVarFont,
172 (GDIOBJHDR *) &SystemFont,
173 (GDIOBJHDR *) &DeviceDefaultFont,
174 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
175 (GDIOBJHDR *) &SystemFixedFont,
176 (GDIOBJHDR *) &DefaultGuiFont
179 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
181 /******************************************************************************
183 * void ReadFontInformation(
184 * char const *fontName,
185 * FONTOBJ *font,
186 * int defHeight,
187 * int defBold,
188 * int defItalic,
189 * int defUnderline,
190 * int defStrikeOut )
192 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
193 * section for entries containing fontName.Height, fontName.Bold, etc.,
194 * where fontName is the name specified in the call (e.g., "System"). It
195 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
196 * the first character in the boolean attributes (bold, italic, and
197 * underline).
198 *****************************************************************************/
200 static void ReadFontInformation(
201 char const *fontName,
202 FONTOBJ *font,
203 int defHeight,
204 int defBold,
205 int defItalic,
206 int defUnderline,
207 int defStrikeOut )
209 char key[256];
211 /* In order for the stock fonts to be independent of
212 * mapping mode, the height (& width) must be 0
214 sprintf(key, "%s.Height", fontName);
215 font->logfont.lfHeight =
216 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
218 sprintf(key, "%s.Bold", fontName);
219 font->logfont.lfWeight =
220 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
221 FW_BOLD : FW_NORMAL;
223 sprintf(key, "%s.Italic", fontName);
224 font->logfont.lfItalic =
225 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
227 sprintf(key, "%s.Underline", fontName);
228 font->logfont.lfUnderline =
229 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
231 sprintf(key, "%s.StrikeOut", fontName);
232 font->logfont.lfStrikeOut =
233 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
235 return;
238 /***********************************************************************
239 * Because the stock fonts have their structure initialized with
240 * a height of 0 to keep them independent of mapping mode, simply
241 * returning the LOGFONT as is will not work correctly.
242 * These "FixStockFontSizeXXX()" methods will get the correct
243 * size for the fonts.
245 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
247 HDC hdc;
248 HFONT hOldFont;
250 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
252 hOldFont = (HFONT)SelectObject(hdc, handle);
254 GetTextMetricsA(hdc, lptm);
256 SelectObject(hdc, hOldFont);
258 DeleteDC(hdc);
261 static inline void FixStockFontSize16(
262 HFONT handle,
263 INT16 count,
264 LPVOID buffer)
266 TEXTMETRICA tm;
267 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
270 * Was the lfHeight field copied (it's the first field)?
271 * If it was and it was null, replace the height.
273 if ( (count >= 2*sizeof(INT16)) &&
274 (pLogFont->lfHeight == 0) )
276 GetFontMetrics(handle, &tm);
278 pLogFont->lfHeight = tm.tmHeight;
279 pLogFont->lfWidth = tm.tmAveCharWidth;
283 static inline void FixStockFontSizeA(
284 HFONT handle,
285 INT count,
286 LPVOID buffer)
288 TEXTMETRICA tm;
289 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
292 * Was the lfHeight field copied (it's the first field)?
293 * If it was and it was null, replace the height.
295 if ( (count >= 2*sizeof(INT)) &&
296 (pLogFont->lfHeight == 0) )
298 GetFontMetrics(handle, &tm);
300 pLogFont->lfHeight = tm.tmHeight;
301 pLogFont->lfWidth = tm.tmAveCharWidth;
306 * Since the LOGFONTA and LOGFONTW structures are identical up to the
307 * lfHeight member (the one of interest in this case) we simply define
308 * the W version as the A version.
310 #define FixStockFontSizeW FixStockFontSizeA
314 /***********************************************************************
315 * GDI_Init
317 * GDI initialization.
319 BOOL GDI_Init(void)
321 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
323 /* Kill some warnings. */
324 (void)align_OEMFixedFont;
325 (void)align_AnsiFixedFont;
326 (void)align_AnsiVarFont;
327 (void)align_SystemFont;
328 (void)align_DeviceDefaultFont;
329 (void)align_SystemFixedFont;
330 (void)align_DefaultGuiFont;
332 /* TWEAK: Initialize font hints */
333 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
334 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
335 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
336 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
337 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
338 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
339 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
341 /* Initialize drivers */
343 GDI_Driver->pInitialize();
345 /* Create default palette */
347 /* DR well *this* palette can't be moveable (?) */
349 HPALETTE16 hpalette = PALETTE_Init();
350 if( !hpalette )
351 return FALSE;
352 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
355 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
356 return TRUE;
360 /***********************************************************************
361 * GDI_AllocObject
363 HGDIOBJ GDI_AllocObject( WORD size, WORD magic )
365 static DWORD count = 0;
366 GDIOBJHDR * obj;
367 HGDIOBJ16 handle;
368 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
369 handle = GDI_HEAP_ALLOC( size );
370 else
371 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
372 if (!handle) return 0;
373 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
374 obj->hNext = 0;
375 obj->wMagic = magic;
376 obj->dwCount = ++count;
377 GDI_HEAP_UNLOCK( handle );
378 return handle;
382 /***********************************************************************
383 * GDI_FreeObject
385 BOOL GDI_FreeObject( HGDIOBJ handle )
387 GDIOBJHDR * object;
389 /* Can't free stock objects */
390 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
391 return TRUE;
393 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
394 if (!object) return FALSE;
395 object->wMagic = 0; /* Mark it as invalid */
397 /* Free object */
399 GDI_HEAP_FREE( handle );
400 return TRUE;
403 /***********************************************************************
404 * GDI_GetObjPtr
406 * Return a pointer to the GDI object associated to the handle.
407 * Return NULL if the object has the wrong magic number.
408 * Movable GDI objects are locked in memory: it is up to the caller to unlock
409 * it after the caller is done with the pointer.
411 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
413 GDIOBJHDR * ptr = NULL;
415 if (handle >= FIRST_STOCK_HANDLE)
417 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
419 else
420 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
421 if (!ptr) return NULL;
422 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
424 GDI_HEAP_UNLOCK( handle );
425 return NULL;
427 return ptr;
431 /***********************************************************************
432 * DeleteObject16 (GDI.69)
434 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
436 return DeleteObject( obj );
440 /***********************************************************************
441 * DeleteObject32 (GDI32.70)
443 BOOL WINAPI DeleteObject( HGDIOBJ obj )
445 /* Check if object is valid */
447 GDIOBJHDR * header;
448 if (HIWORD(obj)) return FALSE;
449 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
450 return TRUE;
451 if (obj == hPseudoStockBitmap) return TRUE;
452 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
454 TRACE("%04x\n", obj );
456 /* Delete object */
458 switch(header->wMagic)
460 case PEN_MAGIC: return GDI_FreeObject( obj );
461 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
462 case FONT_MAGIC: return GDI_FreeObject( obj );
463 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
464 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
465 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
466 case DC_MAGIC: return DeleteDC(obj);
467 case 0 :
468 WARN("Already deleted\n");
469 break;
470 default:
471 WARN("Unknown magic number (%d)\n",header->wMagic);
473 return FALSE;
476 /***********************************************************************
477 * GetStockObject16 (GDI.87)
479 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
481 return (HGDIOBJ16)GetStockObject( obj );
485 /***********************************************************************
486 * GetStockObject32 (GDI32.220)
488 HGDIOBJ WINAPI GetStockObject( INT obj )
490 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
491 if (!StockObjects[obj]) return 0;
492 TRACE("returning %d\n",
493 FIRST_STOCK_HANDLE + obj );
494 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
498 /***********************************************************************
499 * GetObject16 (GDI.82)
501 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
503 GDIOBJHDR * ptr;
504 INT16 result = 0;
505 TRACE("%04x %d %p\n", handle, count, buffer );
506 if (!count) return 0;
508 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
510 switch(ptr->wMagic)
512 case PEN_MAGIC:
513 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
514 break;
515 case BRUSH_MAGIC:
516 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
517 break;
518 case BITMAP_MAGIC:
519 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
520 break;
521 case FONT_MAGIC:
522 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
525 * Fix the LOGFONT structure for the stock fonts
527 if ( (handle >= FIRST_STOCK_HANDLE) &&
528 (handle <= LAST_STOCK_HANDLE) )
529 FixStockFontSize16(handle, count, buffer);
530 break;
531 case PALETTE_MAGIC:
532 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
533 break;
535 GDI_HEAP_UNLOCK( handle );
536 return result;
540 /***********************************************************************
541 * GetObject32A (GDI32.204)
543 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
545 GDIOBJHDR * ptr;
546 INT result = 0;
547 TRACE("%08x %d %p\n", handle, count, buffer );
548 if (!count) return 0;
550 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
552 switch(ptr->wMagic)
554 case PEN_MAGIC:
555 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
556 break;
557 case BRUSH_MAGIC:
558 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
559 break;
560 case BITMAP_MAGIC:
561 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
562 break;
563 case FONT_MAGIC:
564 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
567 * Fix the LOGFONT structure for the stock fonts
569 if ( (handle >= FIRST_STOCK_HANDLE) &&
570 (handle <= LAST_STOCK_HANDLE) )
571 FixStockFontSizeA(handle, count, buffer);
572 break;
573 case PALETTE_MAGIC:
574 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
575 break;
577 case REGION_MAGIC:
578 case DC_MAGIC:
579 case DISABLED_DC_MAGIC:
580 case META_DC_MAGIC:
581 case METAFILE_MAGIC:
582 case METAFILE_DC_MAGIC:
583 case ENHMETAFILE_MAGIC:
584 case ENHMETAFILE_DC_MAGIC:
585 FIXME("Magic %04x not implemented\n",
586 ptr->wMagic );
587 break;
589 default:
590 ERR("Invalid GDI Magic %04x\n", ptr->wMagic);
591 return 0;
593 GDI_HEAP_UNLOCK( handle );
594 return result;
597 /***********************************************************************
598 * GetObject32W (GDI32.206)
600 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
602 GDIOBJHDR * ptr;
603 INT result = 0;
604 TRACE("%08x %d %p\n", handle, count, buffer );
605 if (!count) return 0;
607 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
609 switch(ptr->wMagic)
611 case PEN_MAGIC:
612 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
613 break;
614 case BRUSH_MAGIC:
615 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
616 break;
617 case BITMAP_MAGIC:
618 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
619 break;
620 case FONT_MAGIC:
621 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
624 * Fix the LOGFONT structure for the stock fonts
626 if ( (handle >= FIRST_STOCK_HANDLE) &&
627 (handle <= LAST_STOCK_HANDLE) )
628 FixStockFontSizeW(handle, count, buffer);
629 break;
630 case PALETTE_MAGIC:
631 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
632 break;
633 default:
634 FIXME("Magic %04x not implemented\n",
635 ptr->wMagic );
636 break;
638 GDI_HEAP_UNLOCK( handle );
639 return result;
642 /***********************************************************************
643 * GetObjectType (GDI32.205)
645 DWORD WINAPI GetObjectType( HANDLE handle )
647 GDIOBJHDR * ptr;
648 INT result = 0;
649 TRACE("%08x\n", handle );
651 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
653 switch(ptr->wMagic)
655 case PEN_MAGIC:
656 result = OBJ_PEN;
657 break;
658 case BRUSH_MAGIC:
659 result = OBJ_BRUSH;
660 break;
661 case BITMAP_MAGIC:
662 result = OBJ_BITMAP;
663 break;
664 case FONT_MAGIC:
665 result = OBJ_FONT;
666 break;
667 case PALETTE_MAGIC:
668 result = OBJ_PAL;
669 break;
670 case REGION_MAGIC:
671 result = OBJ_REGION;
672 break;
673 case DC_MAGIC:
674 result = OBJ_DC;
675 break;
676 case META_DC_MAGIC:
677 result = OBJ_METADC;
678 break;
679 case METAFILE_MAGIC:
680 result = OBJ_METAFILE;
681 break;
682 case METAFILE_DC_MAGIC:
683 result = OBJ_METADC;
684 break;
685 case ENHMETAFILE_MAGIC:
686 result = OBJ_ENHMETAFILE;
687 break;
688 case ENHMETAFILE_DC_MAGIC:
689 result = OBJ_ENHMETADC;
690 break;
691 default:
692 FIXME("Magic %04x not implemented\n",
693 ptr->wMagic );
694 break;
696 GDI_HEAP_UNLOCK( handle );
697 return result;
700 /***********************************************************************
701 * GetCurrentObject (GDI32.166)
703 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
705 DC * dc = DC_GetDCPtr( hdc );
707 if (!dc)
708 return 0;
709 switch (type) {
710 case OBJ_PEN: return dc->w.hPen;
711 case OBJ_BRUSH: return dc->w.hBrush;
712 case OBJ_PAL: return dc->w.hPalette;
713 case OBJ_FONT: return dc->w.hFont;
714 case OBJ_BITMAP: return dc->w.hBitmap;
715 default:
716 /* the SDK only mentions those above */
717 WARN("(%08x,%d): unknown type.\n",hdc,type);
718 return 0;
723 /***********************************************************************
724 * SelectObject16 (GDI.45)
726 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
728 return (HGDIOBJ16)SelectObject( hdc, handle );
732 /***********************************************************************
733 * SelectObject32 (GDI32.299)
735 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
737 DC * dc = DC_GetDCPtr( hdc );
738 if (!dc || !dc->funcs->pSelectObject) return 0;
739 TRACE("hdc=%04x %04x\n", hdc, handle );
740 return dc->funcs->pSelectObject( dc, handle );
744 /***********************************************************************
745 * UnrealizeObject16 (GDI.150)
747 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
749 return UnrealizeObject( obj );
753 /***********************************************************************
754 * UnrealizeObject (GDI32.358)
756 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
758 BOOL result = TRUE;
759 /* Check if object is valid */
761 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
762 if (!header) return FALSE;
764 TRACE("%04x\n", obj );
766 /* Unrealize object */
768 switch(header->wMagic)
770 case PALETTE_MAGIC:
771 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
772 break;
774 case BRUSH_MAGIC:
775 /* Windows resets the brush origin. We don't need to. */
776 break;
778 GDI_HEAP_UNLOCK( obj );
779 return result;
783 /***********************************************************************
784 * EnumObjects16 (GDI.71)
786 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
787 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
789 /* Solid colors to enumerate */
790 static const COLORREF solid_colors[] =
791 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
792 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
793 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
794 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
795 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
796 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
797 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
798 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
801 INT16 i, retval = 0;
802 LOGPEN16 *pen;
803 LOGBRUSH16 *brush = NULL;
805 TRACE("%04x %d %08lx %08lx\n",
806 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
807 switch(nObjType)
809 case OBJ_PEN:
810 /* Enumerate solid pens */
811 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
812 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
814 pen->lopnStyle = PS_SOLID;
815 pen->lopnWidth.x = 1;
816 pen->lopnWidth.y = 0;
817 pen->lopnColor = solid_colors[i];
818 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
819 TRACE("solid pen %08lx, ret=%d\n",
820 solid_colors[i], retval);
821 if (!retval) break;
823 SEGPTR_FREE(pen);
824 break;
826 case OBJ_BRUSH:
827 /* Enumerate solid brushes */
828 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
829 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
831 brush->lbStyle = BS_SOLID;
832 brush->lbColor = solid_colors[i];
833 brush->lbHatch = 0;
834 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
835 TRACE("solid brush %08lx, ret=%d\n",
836 solid_colors[i], retval);
837 if (!retval) break;
840 /* Now enumerate hatched brushes */
841 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
843 brush->lbStyle = BS_HATCHED;
844 brush->lbColor = RGB(0,0,0);
845 brush->lbHatch = i;
846 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
847 TRACE("hatched brush %d, ret=%d\n",
848 i, retval);
849 if (!retval) break;
851 SEGPTR_FREE(brush);
852 break;
854 default:
855 WARN("(%d): Invalid type\n", nObjType );
856 break;
858 return retval;
862 /***********************************************************************
863 * EnumObjects32 (GDI32.89)
865 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
866 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
868 /* Solid colors to enumerate */
869 static const COLORREF solid_colors[] =
870 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
871 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
872 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
873 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
874 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
875 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
876 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
877 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
880 INT i, retval = 0;
881 LOGPEN pen;
882 LOGBRUSH brush;
884 TRACE("%04x %d %08lx %08lx\n",
885 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
886 switch(nObjType)
888 case OBJ_PEN:
889 /* Enumerate solid pens */
890 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
892 pen.lopnStyle = PS_SOLID;
893 pen.lopnWidth.x = 1;
894 pen.lopnWidth.y = 0;
895 pen.lopnColor = solid_colors[i];
896 retval = lpEnumFunc( &pen, lParam );
897 TRACE("solid pen %08lx, ret=%d\n",
898 solid_colors[i], retval);
899 if (!retval) break;
901 break;
903 case OBJ_BRUSH:
904 /* Enumerate solid brushes */
905 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
907 brush.lbStyle = BS_SOLID;
908 brush.lbColor = solid_colors[i];
909 brush.lbHatch = 0;
910 retval = lpEnumFunc( &brush, lParam );
911 TRACE("solid brush %08lx, ret=%d\n",
912 solid_colors[i], retval);
913 if (!retval) break;
916 /* Now enumerate hatched brushes */
917 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
919 brush.lbStyle = BS_HATCHED;
920 brush.lbColor = RGB(0,0,0);
921 brush.lbHatch = i;
922 retval = lpEnumFunc( &brush, lParam );
923 TRACE("hatched brush %d, ret=%d\n",
924 i, retval);
925 if (!retval) break;
927 break;
929 default:
930 /* FIXME: implement Win32 types */
931 WARN("(%d): Invalid type\n", nObjType );
932 break;
934 return retval;
938 /***********************************************************************
939 * IsGDIObject (GDI.462)
941 * returns type of object if valid (W95 system programming secrets p. 264-5)
943 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
945 UINT16 magic = 0;
947 if (handle >= FIRST_STOCK_HANDLE )
949 switch (handle)
951 case STOCK_WHITE_BRUSH:
952 case STOCK_LTGRAY_BRUSH:
953 case STOCK_GRAY_BRUSH:
954 case STOCK_DKGRAY_BRUSH:
955 case STOCK_BLACK_BRUSH:
956 case STOCK_HOLLOW_BRUSH:
957 magic = BRUSH_MAGIC;
958 break;
960 case STOCK_WHITE_PEN:
961 case STOCK_BLACK_PEN:
962 case STOCK_NULL_PEN :
963 magic = PEN_MAGIC;
964 break;
966 case STOCK_OEM_FIXED_FONT:
967 case STOCK_ANSI_FIXED_FONT:
968 case STOCK_ANSI_VAR_FONT:
969 case STOCK_SYSTEM_FONT:
970 case STOCK_DEVICE_DEFAULT_FONT:
971 case STOCK_SYSTEM_FIXED_FONT:
972 case STOCK_DEFAULT_GUI_FONT:
973 magic = FONT_MAGIC;
974 break;
976 case STOCK_DEFAULT_PALETTE:
977 magic = PALETTE_MAGIC;
978 break;
981 else
983 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
984 if (object)
986 magic = object->wMagic;
987 GDI_HEAP_UNLOCK( handle );
991 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
992 return magic - PEN_MAGIC + 1;
993 else
994 return FALSE;
998 /***********************************************************************
999 * SetObjectOwner16 (GDI.461)
1001 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
1003 /* Nothing to do */
1007 /***********************************************************************
1008 * SetObjectOwner32 (GDI32.386)
1010 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1012 /* Nothing to do */
1015 /***********************************************************************
1016 * MakeObjectPrivate (GDI.463)
1018 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1020 /* FIXME */
1024 /***********************************************************************
1025 * GdiFlush (GDI32.128)
1027 BOOL WINAPI GdiFlush(void)
1029 return TRUE; /* FIXME */
1033 /***********************************************************************
1034 * GdiGetBatchLimit (GDI32.129)
1036 DWORD WINAPI GdiGetBatchLimit(void)
1038 return 1; /* FIXME */
1042 /***********************************************************************
1043 * GdiSetBatchLimit (GDI32.139)
1045 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1047 return 1; /* FIXME */
1051 /***********************************************************************
1052 * GdiSeeGdiDo (GDI.452)
1054 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1055 WORD wParam3 )
1057 switch (wReqType)
1059 case 0x0001: /* LocalAlloc */
1060 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1061 case 0x0002: /* LocalFree */
1062 return LOCAL_Free( GDI_HeapSel, wParam1 );
1063 case 0x0003: /* LocalCompact */
1064 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1065 case 0x0103: /* LocalHeap */
1066 return GDI_HeapSel;
1067 default:
1068 WARN("(wReqType=%04x): Unknown\n", wReqType);
1069 return (DWORD)-1;
1073 /***********************************************************************
1074 * GdiSignalProc (GDI.610)
1076 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1077 DWORD dwFlags, HMODULE16 hModule )
1079 return 0;
1082 /***********************************************************************
1083 * FinalGdiInit16 (GDI.405)
1085 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1089 /***********************************************************************
1090 * GdiFreeResources (GDI.609)
1092 WORD WINAPI GdiFreeResources16( DWORD reserve )
1094 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1095 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1098 /***********************************************************************
1099 * MulDiv16 (GDI.128)
1101 INT16 WINAPI MulDiv16(
1102 INT16 nMultiplicand,
1103 INT16 nMultiplier,
1104 INT16 nDivisor)
1106 INT ret;
1107 if (!nDivisor) return -32768;
1108 /* We want to deal with a positive divisor to simplify the logic. */
1109 if (nDivisor < 0)
1111 nMultiplicand = - nMultiplicand;
1112 nDivisor = -nDivisor;
1114 /* If the result is positive, we "add" to round. else,
1115 * we subtract to round. */
1116 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1117 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1118 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1119 else
1120 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1121 if ((ret > 32767) || (ret < -32767)) return -32768;
1122 return (INT16) ret;
1126 /***********************************************************************
1127 * MulDiv32 (KERNEL32.391)
1128 * RETURNS
1129 * Result of multiplication and division
1130 * -1: Overflow occurred or Divisor was 0
1132 INT WINAPI MulDiv(
1133 INT nMultiplicand,
1134 INT nMultiplier,
1135 INT nDivisor)
1137 #if SIZEOF_LONG_LONG >= 8
1138 long long ret;
1140 if (!nDivisor) return -1;
1142 /* We want to deal with a positive divisor to simplify the logic. */
1143 if (nDivisor < 0)
1145 nMultiplicand = - nMultiplicand;
1146 nDivisor = -nDivisor;
1149 /* If the result is positive, we "add" to round. else, we subtract to round. */
1150 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1151 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1152 ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1153 else
1154 ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1156 if ((ret > 2147483647) || (ret < -2147483647)) return -1;
1157 return ret;
1158 #else
1159 if (!nDivisor) return -1;
1161 /* We want to deal with a positive divisor to simplify the logic. */
1162 if (nDivisor < 0)
1164 nMultiplicand = - nMultiplicand;
1165 nDivisor = -nDivisor;
1168 /* If the result is positive, we "add" to round. else, we subtract to round. */
1169 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1170 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1171 return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1173 return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1175 #endif
1177 /*******************************************************************
1178 * GetColorAdjustment [GDI32.164]
1182 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1184 FIXME("GetColorAdjustment, stub\n");
1185 return 0;
1188 /*******************************************************************
1189 * GetMiterLimit [GDI32.201]
1193 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1195 FIXME("GetMiterLimit, stub\n");
1196 return 0;
1199 /*******************************************************************
1200 * SetMiterLimit [GDI32.325]
1204 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1206 FIXME("SetMiterLimit, stub\n");
1207 return 0;
1210 /*******************************************************************
1211 * GdiComment [GDI32.109]
1215 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1217 FIXME("GdiComment, stub\n");
1218 return 0;
1220 /*******************************************************************
1221 * SetColorAdjustment [GDI32.309]
1225 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1227 FIXME("SetColorAdjustment, stub\n");
1228 return 0;