Merged clipboard driver into USER driver.
[wine/multimedia.git] / objects / gdiobj.c
blobb08f395f2634996fe743e18c9625de0c27e18fec
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"
27 DEFAULT_DEBUG_CHANNEL(gdi);
29 /**********************************************************************/
31 GDI_DRIVER *GDI_Driver = NULL;
33 /***********************************************************************
34 * GDI stock objects
37 static BRUSHOBJ WhiteBrush =
39 { 0, BRUSH_MAGIC, 1 }, /* header */
40 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
43 static BRUSHOBJ LtGrayBrush =
45 { 0, BRUSH_MAGIC, 1 }, /* header */
46 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
47 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
50 static BRUSHOBJ GrayBrush =
52 { 0, BRUSH_MAGIC, 1 }, /* header */
53 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
54 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
57 static BRUSHOBJ DkGrayBrush =
59 { 0, BRUSH_MAGIC, 1 }, /* header */
60 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
61 /* NB_HATCH_STYLES is an index into HatchBrushes */
62 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
65 static BRUSHOBJ BlackBrush =
67 { 0, BRUSH_MAGIC, 1 }, /* header */
68 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
71 static BRUSHOBJ NullBrush =
73 { 0, BRUSH_MAGIC, 1 }, /* header */
74 { BS_NULL, 0, 0 } /* logbrush */
77 static PENOBJ WhitePen =
79 { 0, PEN_MAGIC, 1 }, /* header */
80 { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
83 static PENOBJ BlackPen =
85 { 0, PEN_MAGIC, 1 }, /* header */
86 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
89 static PENOBJ NullPen =
91 { 0, PEN_MAGIC, 1 }, /* header */
92 { PS_NULL, { 1, 0 }, 0 } /* logpen */
95 static FONTOBJ OEMFixedFont =
97 { 0, FONT_MAGIC, 1 }, /* header */
98 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
99 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
101 /* Filler to make the location counter dword aligned again. This is necessary
102 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
103 segment, and (c) Solaris assembler is stupid. */
104 static UINT16 align_OEMFixedFont = 1;
106 static FONTOBJ AnsiFixedFont =
108 { 0, FONT_MAGIC, 1 }, /* header */
109 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
110 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
112 static UINT16 align_AnsiFixedFont = 1;
114 static FONTOBJ AnsiVarFont =
116 { 0, FONT_MAGIC, 1 }, /* header */
117 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
118 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
120 static UINT16 align_AnsiVarFont = 1;
122 static FONTOBJ SystemFont =
124 { 0, FONT_MAGIC, 1 },
125 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
126 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
128 static UINT16 align_SystemFont = 1;
130 static FONTOBJ DeviceDefaultFont =
132 { 0, FONT_MAGIC, 1 }, /* header */
133 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
134 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
136 static UINT16 align_DeviceDefaultFont = 1;
138 static FONTOBJ SystemFixedFont =
140 { 0, FONT_MAGIC, 1 }, /* header */
141 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
142 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
144 static UINT16 align_SystemFixedFont = 1;
146 /* FIXME: Is this correct? */
147 static FONTOBJ DefaultGuiFont =
149 { 0, FONT_MAGIC, 1 }, /* header */
150 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
151 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
153 static UINT16 align_DefaultGuiFont = 1;
156 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
158 (GDIOBJHDR *) &WhiteBrush,
159 (GDIOBJHDR *) &LtGrayBrush,
160 (GDIOBJHDR *) &GrayBrush,
161 (GDIOBJHDR *) &DkGrayBrush,
162 (GDIOBJHDR *) &BlackBrush,
163 (GDIOBJHDR *) &NullBrush,
164 (GDIOBJHDR *) &WhitePen,
165 (GDIOBJHDR *) &BlackPen,
166 (GDIOBJHDR *) &NullPen,
167 NULL,
168 (GDIOBJHDR *) &OEMFixedFont,
169 (GDIOBJHDR *) &AnsiFixedFont,
170 (GDIOBJHDR *) &AnsiVarFont,
171 (GDIOBJHDR *) &SystemFont,
172 (GDIOBJHDR *) &DeviceDefaultFont,
173 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
174 (GDIOBJHDR *) &SystemFixedFont,
175 (GDIOBJHDR *) &DefaultGuiFont
178 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
180 /******************************************************************************
182 * void ReadFontInformation(
183 * char const *fontName,
184 * FONTOBJ *font,
185 * int defHeight,
186 * int defBold,
187 * int defItalic,
188 * int defUnderline,
189 * int defStrikeOut )
191 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
192 * section for entries containing fontName.Height, fontName.Bold, etc.,
193 * where fontName is the name specified in the call (e.g., "System"). It
194 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
195 * the first character in the boolean attributes (bold, italic, and
196 * underline).
197 *****************************************************************************/
199 static void ReadFontInformation(
200 char const *fontName,
201 FONTOBJ *font,
202 int defHeight,
203 int defBold,
204 int defItalic,
205 int defUnderline,
206 int defStrikeOut )
208 char key[256];
210 /* In order for the stock fonts to be independent of
211 * mapping mode, the height (& width) must be 0
213 sprintf(key, "%s.Height", fontName);
214 font->logfont.lfHeight =
215 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
217 sprintf(key, "%s.Bold", fontName);
218 font->logfont.lfWeight =
219 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
220 FW_BOLD : FW_NORMAL;
222 sprintf(key, "%s.Italic", fontName);
223 font->logfont.lfItalic =
224 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
226 sprintf(key, "%s.Underline", fontName);
227 font->logfont.lfUnderline =
228 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
230 sprintf(key, "%s.StrikeOut", fontName);
231 font->logfont.lfStrikeOut =
232 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
234 return;
237 /***********************************************************************
238 * Because the stock fonts have their structure initialized with
239 * a height of 0 to keep them independent of mapping mode, simply
240 * returning the LOGFONT as is will not work correctly.
241 * These "FixStockFontSizeXXX()" methods will get the correct
242 * size for the fonts.
244 static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
246 HDC hdc;
247 HFONT hOldFont;
249 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
251 hOldFont = (HFONT)SelectObject(hdc, handle);
253 GetTextMetricsA(hdc, lptm);
255 SelectObject(hdc, hOldFont);
257 DeleteDC(hdc);
260 static inline void FixStockFontSize16(
261 HFONT handle,
262 INT16 count,
263 LPVOID buffer)
265 TEXTMETRICA tm;
266 LOGFONT16* pLogFont = (LOGFONT16*)buffer;
269 * Was the lfHeight field copied (it's the first field)?
270 * If it was and it was null, replace the height.
272 if ( (count >= 2*sizeof(INT16)) &&
273 (pLogFont->lfHeight == 0) )
275 GetFontMetrics(handle, &tm);
277 pLogFont->lfHeight = tm.tmHeight;
278 pLogFont->lfWidth = tm.tmAveCharWidth;
282 static inline void FixStockFontSizeA(
283 HFONT handle,
284 INT count,
285 LPVOID buffer)
287 TEXTMETRICA tm;
288 LOGFONTA* pLogFont = (LOGFONTA*)buffer;
291 * Was the lfHeight field copied (it's the first field)?
292 * If it was and it was null, replace the height.
294 if ( (count >= 2*sizeof(INT)) &&
295 (pLogFont->lfHeight == 0) )
297 GetFontMetrics(handle, &tm);
299 pLogFont->lfHeight = tm.tmHeight;
300 pLogFont->lfWidth = tm.tmAveCharWidth;
305 * Since the LOGFONTA and LOGFONTW structures are identical up to the
306 * lfHeight member (the one of interest in this case) we simply define
307 * the W version as the A version.
309 #define FixStockFontSizeW FixStockFontSizeA
313 /***********************************************************************
314 * GDI_Init
316 * GDI initialization.
318 BOOL GDI_Init(void)
320 BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
322 /* Kill some warnings. */
323 (void)align_OEMFixedFont;
324 (void)align_AnsiFixedFont;
325 (void)align_AnsiVarFont;
326 (void)align_SystemFont;
327 (void)align_DeviceDefaultFont;
328 (void)align_SystemFixedFont;
329 (void)align_DefaultGuiFont;
331 /* TWEAK: Initialize font hints */
332 ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
333 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
334 ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
335 ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
336 ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
337 ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
338 ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
340 /* Create default palette */
342 /* DR well *this* palette can't be moveable (?) */
344 HPALETTE16 hpalette = PALETTE_Init();
345 if( !hpalette )
346 return FALSE;
347 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
350 hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL );
351 return TRUE;
355 /***********************************************************************
356 * GDI_AllocObject
358 HGDIOBJ GDI_AllocObject( WORD size, WORD magic )
360 static DWORD count = 0;
361 GDIOBJHDR * obj;
362 HGDIOBJ16 handle;
363 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
364 handle = GDI_HEAP_ALLOC( size );
365 else
366 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
367 if (!handle) return 0;
368 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
369 obj->hNext = 0;
370 obj->wMagic = magic;
371 obj->dwCount = ++count;
372 GDI_HEAP_UNLOCK( handle );
373 return handle;
377 /***********************************************************************
378 * GDI_FreeObject
380 BOOL GDI_FreeObject( HGDIOBJ handle )
382 GDIOBJHDR * object;
384 /* Can't free stock objects */
385 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
386 return TRUE;
388 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
389 if (!object) return FALSE;
390 object->wMagic = 0; /* Mark it as invalid */
392 /* Free object */
394 GDI_HEAP_FREE( handle );
395 return TRUE;
398 /***********************************************************************
399 * GDI_GetObjPtr
401 * Return a pointer to the GDI object associated to the handle.
402 * Return NULL if the object has the wrong magic number.
403 * Movable GDI objects are locked in memory: it is up to the caller to unlock
404 * it after the caller is done with the pointer.
406 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
408 GDIOBJHDR * ptr = NULL;
410 if (handle >= FIRST_STOCK_HANDLE)
412 if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
414 else
415 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
416 if (!ptr) return NULL;
417 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
419 GDI_HEAP_UNLOCK( handle );
420 return NULL;
422 return ptr;
426 /***********************************************************************
427 * DeleteObject16 (GDI.69)
429 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
431 return DeleteObject( obj );
435 /***********************************************************************
436 * DeleteObject (GDI32.70)
438 BOOL WINAPI DeleteObject( HGDIOBJ obj )
440 /* Check if object is valid */
442 GDIOBJHDR * header;
443 if (HIWORD(obj)) return FALSE;
444 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
445 return TRUE;
446 if (obj == hPseudoStockBitmap) return TRUE;
447 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
449 TRACE("%04x\n", obj );
451 /* Delete object */
453 switch(header->wMagic)
455 case PEN_MAGIC: return GDI_FreeObject( obj );
456 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
457 case FONT_MAGIC: return GDI_FreeObject( obj );
458 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
459 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
460 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
461 case DC_MAGIC: return DeleteDC(obj);
462 case 0 :
463 WARN("Already deleted\n");
464 break;
465 default:
466 WARN("Unknown magic number (%d)\n",header->wMagic);
468 return FALSE;
471 /***********************************************************************
472 * GetStockObject16 (GDI.87)
474 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
476 return (HGDIOBJ16)GetStockObject( obj );
480 /***********************************************************************
481 * GetStockObject (GDI32.220)
483 HGDIOBJ WINAPI GetStockObject( INT obj )
485 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
486 if (!StockObjects[obj]) return 0;
487 TRACE("returning %d\n",
488 FIRST_STOCK_HANDLE + obj );
489 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
493 /***********************************************************************
494 * GetObject16 (GDI.82)
496 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
498 GDIOBJHDR * ptr;
499 INT16 result = 0;
500 TRACE("%04x %d %p\n", handle, count, buffer );
501 if (!count) return 0;
503 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
505 switch(ptr->wMagic)
507 case PEN_MAGIC:
508 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
509 break;
510 case BRUSH_MAGIC:
511 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
512 break;
513 case BITMAP_MAGIC:
514 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
515 break;
516 case FONT_MAGIC:
517 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
520 * Fix the LOGFONT structure for the stock fonts
522 if ( (handle >= FIRST_STOCK_HANDLE) &&
523 (handle <= LAST_STOCK_HANDLE) )
524 FixStockFontSize16(handle, count, buffer);
525 break;
526 case PALETTE_MAGIC:
527 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
528 break;
530 GDI_HEAP_UNLOCK( handle );
531 return result;
535 /***********************************************************************
536 * GetObjectA (GDI32.204)
538 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
540 GDIOBJHDR * ptr;
541 INT result = 0;
542 TRACE("%08x %d %p\n", handle, count, buffer );
543 if (!count) return 0;
545 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
547 switch(ptr->wMagic)
549 case PEN_MAGIC:
550 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
551 break;
552 case BRUSH_MAGIC:
553 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
554 break;
555 case BITMAP_MAGIC:
556 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
557 break;
558 case FONT_MAGIC:
559 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
562 * Fix the LOGFONT structure for the stock fonts
564 if ( (handle >= FIRST_STOCK_HANDLE) &&
565 (handle <= LAST_STOCK_HANDLE) )
566 FixStockFontSizeA(handle, count, buffer);
567 break;
568 case PALETTE_MAGIC:
569 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
570 break;
572 case REGION_MAGIC:
573 case DC_MAGIC:
574 case DISABLED_DC_MAGIC:
575 case META_DC_MAGIC:
576 case METAFILE_MAGIC:
577 case METAFILE_DC_MAGIC:
578 case ENHMETAFILE_MAGIC:
579 case ENHMETAFILE_DC_MAGIC:
580 FIXME("Magic %04x not implemented\n",
581 ptr->wMagic );
582 break;
584 default:
585 ERR("Invalid GDI Magic %04x\n", ptr->wMagic);
586 return 0;
588 GDI_HEAP_UNLOCK( handle );
589 return result;
592 /***********************************************************************
593 * GetObjectW (GDI32.206)
595 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
597 GDIOBJHDR * ptr;
598 INT result = 0;
599 TRACE("%08x %d %p\n", handle, count, buffer );
600 if (!count) return 0;
602 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
604 switch(ptr->wMagic)
606 case PEN_MAGIC:
607 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
608 break;
609 case BRUSH_MAGIC:
610 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
611 break;
612 case BITMAP_MAGIC:
613 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
614 break;
615 case FONT_MAGIC:
616 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
619 * Fix the LOGFONT structure for the stock fonts
621 if ( (handle >= FIRST_STOCK_HANDLE) &&
622 (handle <= LAST_STOCK_HANDLE) )
623 FixStockFontSizeW(handle, count, buffer);
624 break;
625 case PALETTE_MAGIC:
626 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
627 break;
628 default:
629 FIXME("Magic %04x not implemented\n",
630 ptr->wMagic );
631 break;
633 GDI_HEAP_UNLOCK( handle );
634 return result;
637 /***********************************************************************
638 * GetObjectType (GDI32.205)
640 DWORD WINAPI GetObjectType( HANDLE handle )
642 GDIOBJHDR * ptr;
643 INT result = 0;
644 TRACE("%08x\n", handle );
646 if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
648 switch(ptr->wMagic)
650 case PEN_MAGIC:
651 result = OBJ_PEN;
652 break;
653 case BRUSH_MAGIC:
654 result = OBJ_BRUSH;
655 break;
656 case BITMAP_MAGIC:
657 result = OBJ_BITMAP;
658 break;
659 case FONT_MAGIC:
660 result = OBJ_FONT;
661 break;
662 case PALETTE_MAGIC:
663 result = OBJ_PAL;
664 break;
665 case REGION_MAGIC:
666 result = OBJ_REGION;
667 break;
668 case DC_MAGIC:
669 result = OBJ_DC;
670 break;
671 case META_DC_MAGIC:
672 result = OBJ_METADC;
673 break;
674 case METAFILE_MAGIC:
675 result = OBJ_METAFILE;
676 break;
677 case METAFILE_DC_MAGIC:
678 result = OBJ_METADC;
679 break;
680 case ENHMETAFILE_MAGIC:
681 result = OBJ_ENHMETAFILE;
682 break;
683 case ENHMETAFILE_DC_MAGIC:
684 result = OBJ_ENHMETADC;
685 break;
686 default:
687 FIXME("Magic %04x not implemented\n",
688 ptr->wMagic );
689 break;
691 GDI_HEAP_UNLOCK( handle );
692 return result;
695 /***********************************************************************
696 * GetCurrentObject (GDI32.166)
698 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
700 DC * dc = DC_GetDCPtr( hdc );
702 if (!dc)
703 return 0;
704 switch (type) {
705 case OBJ_PEN: return dc->w.hPen;
706 case OBJ_BRUSH: return dc->w.hBrush;
707 case OBJ_PAL: return dc->w.hPalette;
708 case OBJ_FONT: return dc->w.hFont;
709 case OBJ_BITMAP: return dc->w.hBitmap;
710 default:
711 /* the SDK only mentions those above */
712 WARN("(%08x,%d): unknown type.\n",hdc,type);
713 return 0;
718 /***********************************************************************
719 * SelectObject16 (GDI.45)
721 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
723 return (HGDIOBJ16)SelectObject( hdc, handle );
727 /***********************************************************************
728 * SelectObject (GDI32.299)
730 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
732 DC * dc = DC_GetDCPtr( hdc );
733 if (!dc || !dc->funcs->pSelectObject) return 0;
734 TRACE("hdc=%04x %04x\n", hdc, handle );
735 return dc->funcs->pSelectObject( dc, handle );
739 /***********************************************************************
740 * UnrealizeObject16 (GDI.150)
742 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
744 return UnrealizeObject( obj );
748 /***********************************************************************
749 * UnrealizeObject (GDI32.358)
751 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
753 BOOL result = TRUE;
754 /* Check if object is valid */
756 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
757 if (!header) return FALSE;
759 TRACE("%04x\n", obj );
761 /* Unrealize object */
763 switch(header->wMagic)
765 case PALETTE_MAGIC:
766 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
767 break;
769 case BRUSH_MAGIC:
770 /* Windows resets the brush origin. We don't need to. */
771 break;
773 GDI_HEAP_UNLOCK( obj );
774 return result;
778 /***********************************************************************
779 * EnumObjects16 (GDI.71)
781 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
782 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
784 /* Solid colors to enumerate */
785 static const COLORREF solid_colors[] =
786 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
787 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
788 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
789 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
790 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
791 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
792 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
793 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
796 INT16 i, retval = 0;
797 LOGPEN16 *pen;
798 LOGBRUSH16 *brush = NULL;
800 TRACE("%04x %d %08lx %08lx\n",
801 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
802 switch(nObjType)
804 case OBJ_PEN:
805 /* Enumerate solid pens */
806 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
807 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
809 pen->lopnStyle = PS_SOLID;
810 pen->lopnWidth.x = 1;
811 pen->lopnWidth.y = 0;
812 pen->lopnColor = solid_colors[i];
813 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
814 TRACE("solid pen %08lx, ret=%d\n",
815 solid_colors[i], retval);
816 if (!retval) break;
818 SEGPTR_FREE(pen);
819 break;
821 case OBJ_BRUSH:
822 /* Enumerate solid brushes */
823 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
824 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
826 brush->lbStyle = BS_SOLID;
827 brush->lbColor = solid_colors[i];
828 brush->lbHatch = 0;
829 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
830 TRACE("solid brush %08lx, ret=%d\n",
831 solid_colors[i], retval);
832 if (!retval) break;
835 /* Now enumerate hatched brushes */
836 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
838 brush->lbStyle = BS_HATCHED;
839 brush->lbColor = RGB(0,0,0);
840 brush->lbHatch = i;
841 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
842 TRACE("hatched brush %d, ret=%d\n",
843 i, retval);
844 if (!retval) break;
846 SEGPTR_FREE(brush);
847 break;
849 default:
850 WARN("(%d): Invalid type\n", nObjType );
851 break;
853 return retval;
857 /***********************************************************************
858 * EnumObjects (GDI32.89)
860 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
861 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
863 /* Solid colors to enumerate */
864 static const COLORREF solid_colors[] =
865 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
866 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
867 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
868 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
869 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
870 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
871 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
872 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
875 INT i, retval = 0;
876 LOGPEN pen;
877 LOGBRUSH brush;
879 TRACE("%04x %d %08lx %08lx\n",
880 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
881 switch(nObjType)
883 case OBJ_PEN:
884 /* Enumerate solid pens */
885 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
887 pen.lopnStyle = PS_SOLID;
888 pen.lopnWidth.x = 1;
889 pen.lopnWidth.y = 0;
890 pen.lopnColor = solid_colors[i];
891 retval = lpEnumFunc( &pen, lParam );
892 TRACE("solid pen %08lx, ret=%d\n",
893 solid_colors[i], retval);
894 if (!retval) break;
896 break;
898 case OBJ_BRUSH:
899 /* Enumerate solid brushes */
900 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
902 brush.lbStyle = BS_SOLID;
903 brush.lbColor = solid_colors[i];
904 brush.lbHatch = 0;
905 retval = lpEnumFunc( &brush, lParam );
906 TRACE("solid brush %08lx, ret=%d\n",
907 solid_colors[i], retval);
908 if (!retval) break;
911 /* Now enumerate hatched brushes */
912 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
914 brush.lbStyle = BS_HATCHED;
915 brush.lbColor = RGB(0,0,0);
916 brush.lbHatch = i;
917 retval = lpEnumFunc( &brush, lParam );
918 TRACE("hatched brush %d, ret=%d\n",
919 i, retval);
920 if (!retval) break;
922 break;
924 default:
925 /* FIXME: implement Win32 types */
926 WARN("(%d): Invalid type\n", nObjType );
927 break;
929 return retval;
933 /***********************************************************************
934 * IsGDIObject (GDI.462)
936 * returns type of object if valid (W95 system programming secrets p. 264-5)
938 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
940 UINT16 magic = 0;
942 if (handle >= FIRST_STOCK_HANDLE )
944 switch (handle)
946 case STOCK_WHITE_BRUSH:
947 case STOCK_LTGRAY_BRUSH:
948 case STOCK_GRAY_BRUSH:
949 case STOCK_DKGRAY_BRUSH:
950 case STOCK_BLACK_BRUSH:
951 case STOCK_HOLLOW_BRUSH:
952 magic = BRUSH_MAGIC;
953 break;
955 case STOCK_WHITE_PEN:
956 case STOCK_BLACK_PEN:
957 case STOCK_NULL_PEN :
958 magic = PEN_MAGIC;
959 break;
961 case STOCK_OEM_FIXED_FONT:
962 case STOCK_ANSI_FIXED_FONT:
963 case STOCK_ANSI_VAR_FONT:
964 case STOCK_SYSTEM_FONT:
965 case STOCK_DEVICE_DEFAULT_FONT:
966 case STOCK_SYSTEM_FIXED_FONT:
967 case STOCK_DEFAULT_GUI_FONT:
968 magic = FONT_MAGIC;
969 break;
971 case STOCK_DEFAULT_PALETTE:
972 magic = PALETTE_MAGIC;
973 break;
976 else
978 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
979 if (object)
981 magic = object->wMagic;
982 GDI_HEAP_UNLOCK( handle );
986 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
987 return magic - PEN_MAGIC + 1;
988 else
989 return FALSE;
993 /***********************************************************************
994 * SetObjectOwner16 (GDI.461)
996 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
998 /* Nothing to do */
1002 /***********************************************************************
1003 * SetObjectOwner (GDI32.386)
1005 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1007 /* Nothing to do */
1010 /***********************************************************************
1011 * MakeObjectPrivate (GDI.463)
1013 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
1015 /* FIXME */
1019 /***********************************************************************
1020 * GdiFlush (GDI32.128)
1022 BOOL WINAPI GdiFlush(void)
1024 return TRUE; /* FIXME */
1028 /***********************************************************************
1029 * GdiGetBatchLimit (GDI32.129)
1031 DWORD WINAPI GdiGetBatchLimit(void)
1033 return 1; /* FIXME */
1037 /***********************************************************************
1038 * GdiSetBatchLimit (GDI32.139)
1040 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1042 return 1; /* FIXME */
1046 /***********************************************************************
1047 * GdiSeeGdiDo (GDI.452)
1049 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
1050 WORD wParam3 )
1052 switch (wReqType)
1054 case 0x0001: /* LocalAlloc */
1055 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
1056 case 0x0002: /* LocalFree */
1057 return LOCAL_Free( GDI_HeapSel, wParam1 );
1058 case 0x0003: /* LocalCompact */
1059 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
1060 case 0x0103: /* LocalHeap */
1061 return GDI_HeapSel;
1062 default:
1063 WARN("(wReqType=%04x): Unknown\n", wReqType);
1064 return (DWORD)-1;
1068 /***********************************************************************
1069 * GdiSignalProc (GDI.610)
1071 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
1072 DWORD dwFlags, HMODULE16 hModule )
1074 return 0;
1077 /***********************************************************************
1078 * FinalGdiInit16 (GDI.405)
1080 void WINAPI FinalGdiInit16( HANDLE16 unknown )
1084 /***********************************************************************
1085 * GdiFreeResources (GDI.609)
1087 WORD WINAPI GdiFreeResources16( DWORD reserve )
1089 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
1090 (int)LOCAL_HeapSize( GDI_HeapSel ) );
1093 /***********************************************************************
1094 * MulDiv16 (GDI.128)
1096 INT16 WINAPI MulDiv16(
1097 INT16 nMultiplicand,
1098 INT16 nMultiplier,
1099 INT16 nDivisor)
1101 INT ret;
1102 if (!nDivisor) return -32768;
1103 /* We want to deal with a positive divisor to simplify the logic. */
1104 if (nDivisor < 0)
1106 nMultiplicand = - nMultiplicand;
1107 nDivisor = -nDivisor;
1109 /* If the result is positive, we "add" to round. else,
1110 * we subtract to round. */
1111 if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
1112 ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
1113 ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
1114 else
1115 ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
1116 if ((ret > 32767) || (ret < -32767)) return -32768;
1117 return (INT16) ret;
1121 /*******************************************************************
1122 * GetColorAdjustment [GDI32.164]
1126 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1128 FIXME("GetColorAdjustment, stub\n");
1129 return 0;
1132 /*******************************************************************
1133 * GetMiterLimit [GDI32.201]
1137 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1139 FIXME("GetMiterLimit, stub\n");
1140 return 0;
1143 /*******************************************************************
1144 * SetMiterLimit [GDI32.325]
1148 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1150 FIXME("SetMiterLimit, stub\n");
1151 return 0;
1154 /*******************************************************************
1155 * GdiComment [GDI32.109]
1159 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1161 FIXME("GdiComment, stub\n");
1162 return 0;
1164 /*******************************************************************
1165 * SetColorAdjustment [GDI32.309]
1169 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1171 FIXME("SetColorAdjustment, stub\n");
1172 return 0;