Release 980927
[wine.git] / objects / gdiobj.c
blobc680ff02db724e633181fc8ce20a39725baa5392
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include "color.h"
9 #include "bitmap.h"
10 #include "brush.h"
11 #include "dc.h"
12 #include "font.h"
13 #include "heap.h"
14 #include "options.h"
15 #include "palette.h"
16 #include "pen.h"
17 #include "region.h"
18 #include "debug.h"
19 #include "gdi.h"
22 /***********************************************************************
23 * GDI stock objects
26 static BRUSHOBJ WhiteBrush =
28 { 0, BRUSH_MAGIC, 1 }, /* header */
29 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
32 static BRUSHOBJ LtGrayBrush =
34 { 0, BRUSH_MAGIC, 1 }, /* header */
35 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
36 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
39 static BRUSHOBJ GrayBrush =
41 { 0, BRUSH_MAGIC, 1 }, /* header */
42 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
43 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
46 static BRUSHOBJ DkGrayBrush =
48 { 0, BRUSH_MAGIC, 1 }, /* header */
49 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
50 /* NB_HATCH_STYLES is an index into HatchBrushes */
51 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
54 static BRUSHOBJ BlackBrush =
56 { 0, BRUSH_MAGIC, 1 }, /* header */
57 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
60 static BRUSHOBJ NullBrush =
62 { 0, BRUSH_MAGIC, 1 }, /* header */
63 { BS_NULL, 0, 0 } /* logbrush */
66 static PENOBJ WhitePen =
68 { 0, PEN_MAGIC, 1 }, /* header */
69 { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
72 static PENOBJ BlackPen =
74 { 0, PEN_MAGIC, 1 }, /* header */
75 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
78 static PENOBJ NullPen =
80 { 0, PEN_MAGIC, 1 }, /* header */
81 { PS_NULL, { 1, 0 }, 0 } /* logpen */
84 static FONTOBJ OEMFixedFont =
86 { 0, FONT_MAGIC, 1 }, /* header */
87 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
88 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
90 /* Filler to make the location counter dword aligned again. This is necessary
91 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
92 segment, and (c) Solaris assembler is stupid. */
93 static UINT16 align_OEMFixedFont = 1;
95 static FONTOBJ AnsiFixedFont =
97 { 0, FONT_MAGIC, 1 }, /* header */
98 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
99 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
101 static UINT16 align_AnsiFixedFont = 1;
103 static FONTOBJ AnsiVarFont =
105 { 0, FONT_MAGIC, 1 }, /* header */
106 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
107 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
109 static UINT16 align_AnsiVarFont = 1;
111 static FONTOBJ SystemFont =
113 { 0, FONT_MAGIC, 1 },
114 { 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
115 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
117 static UINT16 align_SystemFont = 1;
119 static FONTOBJ DeviceDefaultFont =
121 { 0, FONT_MAGIC, 1 }, /* header */
122 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
123 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
125 static UINT16 align_DeviceDefaultFont = 1;
127 static FONTOBJ SystemFixedFont =
129 { 0, FONT_MAGIC, 1 }, /* header */
130 { 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
131 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
133 static UINT16 align_SystemFixedFont = 1;
135 /* FIXME: Is this correct? */
136 static FONTOBJ DefaultGuiFont =
138 { 9, FONT_MAGIC, 1 }, /* header */
139 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
140 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
142 static UINT16 align_DefaultGuiFont = 1;
145 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
147 (GDIOBJHDR *) &WhiteBrush,
148 (GDIOBJHDR *) &LtGrayBrush,
149 (GDIOBJHDR *) &GrayBrush,
150 (GDIOBJHDR *) &DkGrayBrush,
151 (GDIOBJHDR *) &BlackBrush,
152 (GDIOBJHDR *) &NullBrush,
153 (GDIOBJHDR *) &WhitePen,
154 (GDIOBJHDR *) &BlackPen,
155 (GDIOBJHDR *) &NullPen,
156 NULL,
157 (GDIOBJHDR *) &OEMFixedFont,
158 (GDIOBJHDR *) &AnsiFixedFont,
159 (GDIOBJHDR *) &AnsiVarFont,
160 (GDIOBJHDR *) &SystemFont,
161 (GDIOBJHDR *) &DeviceDefaultFont,
162 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
163 (GDIOBJHDR *) &SystemFixedFont,
164 (GDIOBJHDR *) &DefaultGuiFont
167 /******************************************************************************
169 * void ReadFontInformation(
170 * char const *fontName,
171 * FONTOBJ *font,
172 * int defHeight,
173 * int defBold,
174 * int defItalic,
175 * int defUnderline,
176 * int defStrikeOut )
178 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
179 * section for entries containing fontName.Height, fontName.Bold, etc.,
180 * where fontName is the name specified in the call (e.g., "System"). It
181 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
182 * the first character in the boolean attributes (bold, italic, and
183 * underline).
184 *****************************************************************************/
186 static void ReadFontInformation(
187 char const *fontName,
188 FONTOBJ *font,
189 int defHeight,
190 int defBold,
191 int defItalic,
192 int defUnderline,
193 int defStrikeOut )
195 char key[256];
197 sprintf(key, "%s.Height", fontName);
198 font->logfont.lfHeight =
199 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
201 sprintf(key, "%s.Bold", fontName);
202 font->logfont.lfWeight =
203 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
204 FW_BOLD : FW_NORMAL;
206 sprintf(key, "%s.Italic", fontName);
207 font->logfont.lfItalic =
208 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
210 sprintf(key, "%s.Underline", fontName);
211 font->logfont.lfUnderline =
212 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
214 sprintf(key, "%s.StrikeOut", fontName);
215 font->logfont.lfStrikeOut =
216 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
218 return;
222 /***********************************************************************
223 * GDI_Init
225 * GDI initialization.
227 BOOL32 GDI_Init(void)
229 /* Kill some warnings. */
230 (void)align_OEMFixedFont;
231 (void)align_AnsiFixedFont;
232 (void)align_AnsiVarFont;
233 (void)align_SystemFont;
234 (void)align_DeviceDefaultFont;
235 (void)align_SystemFixedFont;
236 (void)align_DefaultGuiFont;
238 /* TWEAK: Initialize font hints */
239 ReadFontInformation("OEMFixed", &OEMFixedFont, 12, 0, 0, 0, 0);
240 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 12, 0, 0, 0, 0);
241 ReadFontInformation("AnsiVar", &AnsiVarFont, 12, 0, 0, 0, 0);
242 ReadFontInformation("System", &SystemFont, 16, 1, 0, 0, 0);
243 ReadFontInformation("SystemFixed", &SystemFixedFont, 12, 1, 0, 0, 0);
245 /* Initialize drivers */
247 DIB_Init(); /* always before X11DRV_Init() */
249 if( ! X11DRV_Init() )
250 return FALSE;
252 /* Create default palette */
254 /* DR well *this* palette can't be moveable (?) */
256 HPALETTE16 hpalette = PALETTE_Init();
257 if( !hpalette )
258 return FALSE;
259 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
262 return TRUE;
266 /***********************************************************************
267 * GDI_AllocObject
269 HGDIOBJ16 GDI_AllocObject( WORD size, WORD magic )
271 static DWORD count = 0;
272 GDIOBJHDR * obj;
273 HGDIOBJ16 handle;
274 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
275 handle = GDI_HEAP_ALLOC( size );
276 else
277 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
278 if (!handle) return 0;
279 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
280 obj->hNext = 0;
281 obj->wMagic = magic;
282 obj->dwCount = ++count;
283 GDI_HEAP_UNLOCK( handle );
284 return handle;
288 /***********************************************************************
289 * GDI_FreeObject
291 BOOL32 GDI_FreeObject( HGDIOBJ16 handle )
293 GDIOBJHDR * object;
295 /* Can't free stock objects */
296 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
297 return TRUE;
299 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
300 if (!object) return FALSE;
301 object->wMagic = 0; /* Mark it as invalid */
303 /* Free object */
305 GDI_HEAP_FREE( handle );
306 return TRUE;
309 /***********************************************************************
310 * GDI_GetObjPtr
312 * Return a pointer to the GDI object associated to the handle.
313 * Return NULL if the object has the wrong magic number.
314 * Movable GDI objects are locked in memory: it is up to the caller to unlock
315 * it after the caller is done with the pointer.
317 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16 handle, WORD magic )
319 GDIOBJHDR * ptr = NULL;
321 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
322 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
323 else
324 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
325 if (!ptr) return NULL;
326 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
328 GDI_HEAP_UNLOCK( handle );
329 return NULL;
331 return ptr;
335 /***********************************************************************
336 * DeleteObject16 (GDI.69)
338 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
340 return DeleteObject32( obj );
344 /***********************************************************************
345 * DeleteObject32 (GDI32.70)
347 BOOL32 WINAPI DeleteObject32( HGDIOBJ32 obj )
349 /* Check if object is valid */
351 GDIOBJHDR * header;
352 if (HIWORD(obj)) return FALSE;
353 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
354 return TRUE;
355 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
357 TRACE(gdi, "%04x\n", obj );
359 /* Delete object */
361 switch(header->wMagic)
363 case PEN_MAGIC: return GDI_FreeObject( obj );
364 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
365 case FONT_MAGIC: return GDI_FreeObject( obj );
366 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
367 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
368 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
369 case 0 :
370 WARN(gdi, "Already deleted\n");
371 break;
372 default:
373 WARN(gdi, "Unknown magic number (%d)\n",header->wMagic);
375 return FALSE;
378 /***********************************************************************
379 * GetStockObject16 (GDI.87)
381 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
383 return (HGDIOBJ16)GetStockObject32( obj );
387 /***********************************************************************
388 * GetStockObject32 (GDI32.220)
390 HGDIOBJ32 WINAPI GetStockObject32( INT32 obj )
392 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
393 if (!StockObjects[obj]) return 0;
394 TRACE(gdi, "returning %d\n",
395 FIRST_STOCK_HANDLE + obj );
396 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
400 /***********************************************************************
401 * GetObject16 (GDI.82)
403 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
405 GDIOBJHDR * ptr = NULL;
406 INT16 result = 0;
407 TRACE(gdi, "%04x %d %p\n", handle, count, buffer );
408 if (!count) return 0;
410 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
411 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
412 else
413 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
414 if (!ptr) return 0;
416 switch(ptr->wMagic)
418 case PEN_MAGIC:
419 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
420 break;
421 case BRUSH_MAGIC:
422 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
423 break;
424 case BITMAP_MAGIC:
425 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
426 break;
427 case FONT_MAGIC:
428 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
429 break;
430 case PALETTE_MAGIC:
431 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
432 break;
434 GDI_HEAP_UNLOCK( handle );
435 return result;
439 /***********************************************************************
440 * GetObject32A (GDI32.204)
442 INT32 WINAPI GetObject32A( HANDLE32 handle, INT32 count, LPVOID buffer )
444 GDIOBJHDR * ptr = NULL;
445 INT32 result = 0;
446 TRACE(gdi, "%08x %d %p\n", handle, count, buffer );
447 if (!count) return 0;
449 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
450 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
451 else
452 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
453 if (!ptr) return 0;
455 switch(ptr->wMagic)
457 case PEN_MAGIC:
458 result = PEN_GetObject32( (PENOBJ *)ptr, count, buffer );
459 break;
460 case BRUSH_MAGIC:
461 result = BRUSH_GetObject32( (BRUSHOBJ *)ptr, count, buffer );
462 break;
463 case BITMAP_MAGIC:
464 result = BITMAP_GetObject32( (BITMAPOBJ *)ptr, count, buffer );
465 break;
466 case FONT_MAGIC:
467 result = FONT_GetObject32A( (FONTOBJ *)ptr, count, buffer );
468 break;
469 case PALETTE_MAGIC:
470 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
471 break;
472 default:
473 FIXME(gdi, "Magic %04x not implemented\n",
474 ptr->wMagic );
475 break;
477 GDI_HEAP_UNLOCK( handle );
478 return result;
481 /***********************************************************************
482 * GetObjectType (GDI32.205)
484 DWORD WINAPI GetObjectType( HANDLE32 handle )
486 GDIOBJHDR * ptr = NULL;
487 INT32 result = 0;
488 TRACE(gdi, "%08x\n", handle );
490 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
491 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
492 else
493 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
494 if (!ptr) return 0;
496 switch(ptr->wMagic)
498 case PEN_MAGIC:
499 result = OBJ_PEN;
500 break;
501 case BRUSH_MAGIC:
502 result = OBJ_BRUSH;
503 break;
504 case BITMAP_MAGIC:
505 result = OBJ_BITMAP;
506 break;
507 case FONT_MAGIC:
508 result = OBJ_FONT;
509 break;
510 case PALETTE_MAGIC:
511 result = OBJ_PAL;
512 break;
513 case REGION_MAGIC:
514 result = OBJ_REGION;
515 break;
516 case DC_MAGIC:
517 result = OBJ_DC;
518 break;
519 case META_DC_MAGIC:
520 result = OBJ_METADC;
521 break;
522 case METAFILE_MAGIC:
523 result = OBJ_METAFILE;
524 break;
525 case METAFILE_DC_MAGIC:
526 result = OBJ_METADC;
527 break;
529 default:
530 FIXME(gdi, "Magic %04x not implemented\n",
531 ptr->wMagic );
532 break;
534 GDI_HEAP_UNLOCK( handle );
535 return result;
538 /***********************************************************************
539 * GetObject32W (GDI32.206)
541 INT32 WINAPI GetObject32W( HANDLE32 handle, INT32 count, LPVOID buffer )
543 return GetObject32A( handle, count, buffer );
546 /***********************************************************************
547 * GetCurrentObject (GDI32.166)
549 HANDLE32 WINAPI GetCurrentObject(HDC32 hdc,UINT32 type)
551 DC * dc = DC_GetDCPtr( hdc );
553 if (!dc)
554 return 0;
555 switch (type) {
556 case OBJ_PEN: return dc->w.hPen;
557 case OBJ_BRUSH: return dc->w.hBrush;
558 case OBJ_PAL: return dc->w.hPalette;
559 case OBJ_FONT: return dc->w.hFont;
560 case OBJ_BITMAP: return dc->w.hBitmap;
561 default:
562 /* the SDK only mentions those above */
563 WARN(gdi,"(%08x,%d): unknown type.\n",hdc,type);
564 return 0;
569 /***********************************************************************
570 * SelectObject16 (GDI.45)
572 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
574 return (HGDIOBJ16)SelectObject32( hdc, handle );
578 /***********************************************************************
579 * SelectObject32 (GDI32.299)
581 HGDIOBJ32 WINAPI SelectObject32( HDC32 hdc, HGDIOBJ32 handle )
583 DC * dc = DC_GetDCPtr( hdc );
584 if (!dc || !dc->funcs->pSelectObject) return 0;
585 TRACE(gdi, "hdc=%04x %04x\n", hdc, handle );
586 return dc->funcs->pSelectObject( dc, handle );
590 /***********************************************************************
591 * UnrealizeObject16 (GDI.150)
593 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
595 return UnrealizeObject32( obj );
599 /***********************************************************************
600 * UnrealizeObject (GDI32.358)
602 BOOL32 WINAPI UnrealizeObject32( HGDIOBJ32 obj )
604 BOOL32 result = TRUE;
605 /* Check if object is valid */
607 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
608 if (!header) return FALSE;
610 TRACE(gdi, "%04x\n", obj );
612 /* Unrealize object */
614 switch(header->wMagic)
616 case PALETTE_MAGIC:
617 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
618 break;
620 case BRUSH_MAGIC:
621 /* Windows resets the brush origin. We don't need to. */
622 break;
624 GDI_HEAP_UNLOCK( obj );
625 return result;
629 /***********************************************************************
630 * EnumObjects16 (GDI.71)
632 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
633 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
635 /* Solid colors to enumerate */
636 static const COLORREF solid_colors[] =
637 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
638 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
639 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
640 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
641 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
642 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
643 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
644 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
647 INT16 i, retval = 0;
648 LOGPEN16 *pen;
649 LOGBRUSH16 *brush = NULL;
651 TRACE(gdi, "%04x %d %08lx %08lx\n",
652 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
653 switch(nObjType)
655 case OBJ_PEN:
656 /* Enumerate solid pens */
657 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
658 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
660 pen->lopnStyle = PS_SOLID;
661 pen->lopnWidth.x = 1;
662 pen->lopnWidth.y = 0;
663 pen->lopnColor = solid_colors[i];
664 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
665 TRACE(gdi, "solid pen %08lx, ret=%d\n",
666 solid_colors[i], retval);
667 if (!retval) break;
669 SEGPTR_FREE(pen);
670 break;
672 case OBJ_BRUSH:
673 /* Enumerate solid brushes */
674 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
675 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
677 brush->lbStyle = BS_SOLID;
678 brush->lbColor = solid_colors[i];
679 brush->lbHatch = 0;
680 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
681 TRACE(gdi, "solid brush %08lx, ret=%d\n",
682 solid_colors[i], retval);
683 if (!retval) break;
686 /* Now enumerate hatched brushes */
687 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
689 brush->lbStyle = BS_HATCHED;
690 brush->lbColor = RGB(0,0,0);
691 brush->lbHatch = i;
692 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
693 TRACE(gdi, "hatched brush %d, ret=%d\n",
694 i, retval);
695 if (!retval) break;
697 SEGPTR_FREE(brush);
698 break;
700 default:
701 WARN(gdi, "(%d): Invalid type\n", nObjType );
702 break;
704 return retval;
708 /***********************************************************************
709 * EnumObjects32 (GDI32.89)
711 INT32 WINAPI EnumObjects32( HDC32 hdc, INT32 nObjType,
712 GOBJENUMPROC32 lpEnumFunc, LPARAM lParam )
714 /* Solid colors to enumerate */
715 static const COLORREF solid_colors[] =
716 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
717 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
718 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
719 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
720 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
721 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
722 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
723 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
726 INT32 i, retval = 0;
727 LOGPEN32 pen;
728 LOGBRUSH32 brush;
730 TRACE(gdi, "%04x %d %08lx %08lx\n",
731 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
732 switch(nObjType)
734 case OBJ_PEN:
735 /* Enumerate solid pens */
736 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
738 pen.lopnStyle = PS_SOLID;
739 pen.lopnWidth.x = 1;
740 pen.lopnWidth.y = 0;
741 pen.lopnColor = solid_colors[i];
742 retval = lpEnumFunc( &pen, lParam );
743 TRACE(gdi, "solid pen %08lx, ret=%d\n",
744 solid_colors[i], retval);
745 if (!retval) break;
747 break;
749 case OBJ_BRUSH:
750 /* Enumerate solid brushes */
751 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
753 brush.lbStyle = BS_SOLID;
754 brush.lbColor = solid_colors[i];
755 brush.lbHatch = 0;
756 retval = lpEnumFunc( &brush, lParam );
757 TRACE(gdi, "solid brush %08lx, ret=%d\n",
758 solid_colors[i], retval);
759 if (!retval) break;
762 /* Now enumerate hatched brushes */
763 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
765 brush.lbStyle = BS_HATCHED;
766 brush.lbColor = RGB(0,0,0);
767 brush.lbHatch = i;
768 retval = lpEnumFunc( &brush, lParam );
769 TRACE(gdi, "hatched brush %d, ret=%d\n",
770 i, retval);
771 if (!retval) break;
773 break;
775 default:
776 /* FIXME: implement Win32 types */
777 WARN( gdi, "(%d): Invalid type\n", nObjType );
778 break;
780 return retval;
784 /***********************************************************************
785 * IsGDIObject (GDI.462)
787 * returns type of object if valid (W95 system programming secrets p. 264-5)
789 BOOL16 WINAPI IsGDIObject( HGDIOBJ16 handle )
791 UINT16 magic = 0;
793 if (handle >= FIRST_STOCK_HANDLE )
795 switch (handle)
797 case STOCK_WHITE_BRUSH:
798 case STOCK_LTGRAY_BRUSH:
799 case STOCK_GRAY_BRUSH:
800 case STOCK_DKGRAY_BRUSH:
801 case STOCK_BLACK_BRUSH:
802 case STOCK_HOLLOW_BRUSH:
803 magic = BRUSH_MAGIC;
804 break;
806 case STOCK_WHITE_PEN:
807 case STOCK_BLACK_PEN:
808 case STOCK_NULL_PEN :
809 magic = PEN_MAGIC;
810 break;
812 case STOCK_OEM_FIXED_FONT:
813 case STOCK_ANSI_FIXED_FONT:
814 case STOCK_ANSI_VAR_FONT:
815 case STOCK_SYSTEM_FONT:
816 case STOCK_DEVICE_DEFAULT_FONT:
817 case STOCK_SYSTEM_FIXED_FONT:
818 case STOCK_DEFAULT_GUI_FONT:
819 magic = FONT_MAGIC;
820 break;
822 case STOCK_DEFAULT_PALETTE:
823 magic = PALETTE_MAGIC;
824 break;
827 else
829 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
830 if (object)
832 magic = object->wMagic;
833 GDI_HEAP_UNLOCK( handle );
837 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
838 return magic - PEN_MAGIC + 1;
839 else
840 return FALSE;
844 /***********************************************************************
845 * SetObjectOwner16 (GDI.461)
847 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
849 /* Nothing to do */
853 /***********************************************************************
854 * SetObjectOwner32 (GDI32.386)
856 void WINAPI SetObjectOwner32( HGDIOBJ32 handle, HANDLE32 owner )
858 /* Nothing to do */
861 /***********************************************************************
862 * MakeObjectPrivate (GDI.463)
864 void WINAPI MakeObjectPrivate( HGDIOBJ16 handle, BOOL16 private )
866 /* FIXME */
870 /***********************************************************************
871 * GdiFlush (GDI32.128)
873 BOOL32 WINAPI GdiFlush(void)
875 return TRUE; /* FIXME */
879 /***********************************************************************
880 * GdiGetBatchLimit (GDI32.129)
882 DWORD WINAPI GdiGetBatchLimit(void)
884 return 1; /* FIXME */
888 /***********************************************************************
889 * GdiSetBatchLimit (GDI32.139)
891 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
893 return 1; /* FIXME */
897 /***********************************************************************
898 * GdiSeeGdiDo (GDI.452)
900 DWORD WINAPI GdiSeeGdiDo( WORD wReqType, WORD wParam1, WORD wParam2,
901 WORD wParam3 )
903 switch (wReqType)
905 case 0x0001: /* LocalAlloc */
906 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
907 case 0x0002: /* LocalFree */
908 return LOCAL_Free( GDI_HeapSel, wParam1 );
909 case 0x0003: /* LocalCompact */
910 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
911 case 0x0103: /* LocalHeap */
912 return GDI_HeapSel;
913 default:
914 WARN(gdi, "(wReqType=%04x): Unknown\n", wReqType);
915 return (DWORD)-1;
919 /***********************************************************************
920 * MulDiv16 (GDI.128)
922 INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
924 INT32 ret;
925 if (!baz) return -32768;
926 ret = (foo * bar) / baz;
927 if ((ret > 32767) || (ret < -32767)) return -32768;
928 return ret;
932 /***********************************************************************
933 * MulDiv32 (KERNEL32.391)
934 * RETURNS
935 * Result of multiplication and division
936 * -1: Overflow occurred or Divisor was 0
938 INT32 WINAPI MulDiv32(
939 INT32 nMultiplicand,
940 INT32 nMultiplier,
941 INT32 nDivisor
943 #if (SIZEOF_LONG_LONG >= 8)
944 long long ret;
945 if (!nDivisor) return -1;
946 ret = ((long long)nMultiplicand * nMultiplier) / nDivisor;
947 if ((ret > 2147483647) || (ret < -2147483647)) return -1;
948 return ret;
949 #else
950 if (!nDivisor) return -1;
951 return (nMultiplicand * nMultiplier) / nDivisor;
952 #endif