Release 980315
[wine/multimedia.git] / objects / gdiobj.c
blob283dcd167dd13a9491402e2a1b0e45c7a21c48ca
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include "color.h"
10 #include "bitmap.h"
11 #include "brush.h"
12 #include "dc.h"
13 #include "font.h"
14 #include "heap.h"
15 #include "options.h"
16 #include "palette.h"
17 #include "pen.h"
18 #include "region.h"
19 #include "debug.h"
20 #include "gdi.h"
22 WORD GDI_HeapSel = 0;
24 /***********************************************************************
25 * GDI stock objects
28 static BRUSHOBJ WhiteBrush =
30 { 0, BRUSH_MAGIC, 1 }, /* header */
31 { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
34 static BRUSHOBJ LtGrayBrush =
36 { 0, BRUSH_MAGIC, 1 }, /* header */
37 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
38 { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
41 static BRUSHOBJ GrayBrush =
43 { 0, BRUSH_MAGIC, 1 }, /* header */
44 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
45 { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
48 static BRUSHOBJ DkGrayBrush =
50 { 0, BRUSH_MAGIC, 1 }, /* header */
51 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
52 /* NB_HATCH_STYLES is an index into HatchBrushes */
53 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES } /* logbrush */
56 static BRUSHOBJ BlackBrush =
58 { 0, BRUSH_MAGIC, 1 }, /* header */
59 { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
62 static BRUSHOBJ NullBrush =
64 { 0, BRUSH_MAGIC, 1 }, /* header */
65 { BS_NULL, 0, 0 } /* logbrush */
68 static PENOBJ WhitePen =
70 { 0, PEN_MAGIC, 1 }, /* header */
71 { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
74 static PENOBJ BlackPen =
76 { 0, PEN_MAGIC, 1 }, /* header */
77 { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
80 static PENOBJ NullPen =
82 { 0, PEN_MAGIC, 1 }, /* header */
83 { PS_NULL, { 1, 0 }, 0 } /* logpen */
86 static FONTOBJ OEMFixedFont =
88 { 0, FONT_MAGIC, 1 }, /* header */
89 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
90 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
92 /* Filler to make the location counter dword aligned again. This is necessary
93 since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
94 segment, and (c) Solaris assembler is stupid. */
95 static UINT16 align_OEMFixedFont = 1;
97 static FONTOBJ AnsiFixedFont =
99 { 0, FONT_MAGIC, 1 }, /* header */
100 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
101 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
103 static UINT16 align_AnsiFixedFont = 1;
105 static FONTOBJ AnsiVarFont =
107 { 0, FONT_MAGIC, 1 }, /* header */
108 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
109 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
111 static UINT16 align_AnsiVarFont = 1;
113 static FONTOBJ SystemFont =
115 { 0, FONT_MAGIC, 1 },
116 { 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
117 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
119 static UINT16 align_SystemFont = 1;
121 static FONTOBJ DeviceDefaultFont =
123 { 0, FONT_MAGIC, 1 }, /* header */
124 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
125 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
127 static UINT16 align_DeviceDefaultFont = 1;
129 static FONTOBJ SystemFixedFont =
131 { 0, FONT_MAGIC, 1 }, /* header */
132 { 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
133 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
135 static UINT16 align_SystemFixedFont = 1;
137 /* FIXME: Is this correct? */
138 static FONTOBJ DefaultGuiFont =
140 { 9, FONT_MAGIC, 1 }, /* header */
141 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
142 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
144 static UINT16 align_DefaultGuiFont = 1;
147 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
149 (GDIOBJHDR *) &WhiteBrush,
150 (GDIOBJHDR *) &LtGrayBrush,
151 (GDIOBJHDR *) &GrayBrush,
152 (GDIOBJHDR *) &DkGrayBrush,
153 (GDIOBJHDR *) &BlackBrush,
154 (GDIOBJHDR *) &NullBrush,
155 (GDIOBJHDR *) &WhitePen,
156 (GDIOBJHDR *) &BlackPen,
157 (GDIOBJHDR *) &NullPen,
158 NULL,
159 (GDIOBJHDR *) &OEMFixedFont,
160 (GDIOBJHDR *) &AnsiFixedFont,
161 (GDIOBJHDR *) &AnsiVarFont,
162 (GDIOBJHDR *) &SystemFont,
163 (GDIOBJHDR *) &DeviceDefaultFont,
164 NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
165 (GDIOBJHDR *) &SystemFixedFont,
166 (GDIOBJHDR *) &DefaultGuiFont
169 /******************************************************************************
171 * void ReadFontInformation(
172 * char const *fontName,
173 * FONTOBJ *font,
174 * int defHeight,
175 * int defBold,
176 * int defItalic,
177 * int defUnderline,
178 * int defStrikeOut )
180 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
181 * section for entries containing fontName.Height, fontName.Bold, etc.,
182 * where fontName is the name specified in the call (e.g., "System"). It
183 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
184 * the first character in the boolean attributes (bold, italic, and
185 * underline).
186 *****************************************************************************/
188 static void ReadFontInformation(
189 char const *fontName,
190 FONTOBJ *font,
191 int defHeight,
192 int defBold,
193 int defItalic,
194 int defUnderline,
195 int defStrikeOut )
197 char key[256];
199 sprintf(key, "%s.Height", fontName);
200 font->logfont.lfHeight =
201 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
203 sprintf(key, "%s.Bold", fontName);
204 font->logfont.lfWeight =
205 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
206 FW_BOLD : FW_NORMAL;
208 sprintf(key, "%s.Italic", fontName);
209 font->logfont.lfItalic =
210 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
212 sprintf(key, "%s.Underline", fontName);
213 font->logfont.lfUnderline =
214 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
216 sprintf(key, "%s.StrikeOut", fontName);
217 font->logfont.lfStrikeOut =
218 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
220 return;
224 /***********************************************************************
225 * GDI_Init
227 * GDI initialization.
229 BOOL32 GDI_Init(void)
231 extern BOOL32 X11DRV_Init(void);
232 extern BOOL32 DIB_Init(void);
234 /* Kill some warnings. */
235 (void)align_OEMFixedFont;
236 (void)align_AnsiFixedFont;
237 (void)align_AnsiVarFont;
238 (void)align_SystemFont;
239 (void)align_DeviceDefaultFont;
240 (void)align_SystemFixedFont;
241 (void)align_DefaultGuiFont;
243 /* TWEAK: Initialize font hints */
244 ReadFontInformation("OEMFixed", &OEMFixedFont, 12, 0, 0, 0, 0);
245 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 12, 0, 0, 0, 0);
246 ReadFontInformation("AnsiVar", &AnsiVarFont, 12, 0, 0, 0, 0);
247 ReadFontInformation("System", &SystemFont, 16, 1, 0, 0, 0);
248 ReadFontInformation("SystemFixed", &SystemFixedFont, 12, 1, 0, 0, 0);
250 /* Initialize drivers */
252 DIB_Init(); /* always before X11DRV_Init() */
254 if( X11DRV_Init() )
256 /* Create default palette */
258 /* DR well *this* palette can't be moveable (?) */
260 HPALETTE16 hpalette = PALETTE_Init();
262 if( hpalette )
264 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
265 return TRUE;
268 return FALSE;
272 /***********************************************************************
273 * GDI_AllocObject
275 HGDIOBJ16 GDI_AllocObject( WORD size, WORD magic )
277 static DWORD count = 0;
278 GDIOBJHDR * obj;
279 HGDIOBJ16 handle;
280 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
281 handle = GDI_HEAP_ALLOC( size );
282 else
283 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
284 if (!handle) return 0;
285 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
286 obj->hNext = 0;
287 obj->wMagic = magic;
288 obj->dwCount = ++count;
289 GDI_HEAP_UNLOCK( handle );
290 return handle;
294 /***********************************************************************
295 * GDI_FreeObject
297 BOOL32 GDI_FreeObject( HGDIOBJ16 handle )
299 GDIOBJHDR * object;
301 /* Can't free stock objects */
302 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
303 return TRUE;
305 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
306 if (!object) return FALSE;
307 object->wMagic = 0; /* Mark it as invalid */
309 /* Free object */
311 GDI_HEAP_FREE( handle );
312 return TRUE;
315 /***********************************************************************
316 * GDI_GetObjPtr
318 * Return a pointer to the GDI object associated to the handle.
319 * Return NULL if the object has the wrong magic number.
320 * Movable GDI objects are locked in memory: it is up to the caller to unlock
321 * it after the caller is done with the pointer.
323 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16 handle, WORD magic )
325 GDIOBJHDR * ptr = NULL;
327 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
328 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
329 else
330 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
331 if (!ptr) return NULL;
332 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
334 GDI_HEAP_UNLOCK( handle );
335 return NULL;
337 return ptr;
341 /***********************************************************************
342 * DeleteObject16 (GDI.69)
344 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
346 return DeleteObject32( obj );
350 /***********************************************************************
351 * DeleteObject32 (GDI32.70)
353 BOOL32 WINAPI DeleteObject32( HGDIOBJ32 obj )
355 /* Check if object is valid */
357 GDIOBJHDR * header;
358 if (HIWORD(obj)) return FALSE;
359 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
360 return TRUE;
361 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
363 TRACE(gdi, "%04x\n", obj );
365 /* Delete object */
367 switch(header->wMagic)
369 case PEN_MAGIC: return GDI_FreeObject( obj );
370 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
371 case FONT_MAGIC: return GDI_FreeObject( obj );
372 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
373 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
374 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
376 return FALSE;
380 /***********************************************************************
381 * GetStockObject16 (GDI.87)
383 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
385 return (HGDIOBJ16)GetStockObject32( obj );
389 /***********************************************************************
390 * GetStockObject32 (GDI32.220)
392 HGDIOBJ32 WINAPI GetStockObject32( INT32 obj )
394 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
395 if (!StockObjects[obj]) return 0;
396 TRACE(gdi, "returning %d\n",
397 FIRST_STOCK_HANDLE + obj );
398 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
402 /***********************************************************************
403 * GetObject16 (GDI.82)
405 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
407 GDIOBJHDR * ptr = NULL;
408 INT16 result = 0;
409 TRACE(gdi, "%04x %d %p\n", handle, count, buffer );
410 if (!count) return 0;
412 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
413 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
414 else
415 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
416 if (!ptr) return 0;
418 switch(ptr->wMagic)
420 case PEN_MAGIC:
421 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
422 break;
423 case BRUSH_MAGIC:
424 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
425 break;
426 case BITMAP_MAGIC:
427 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
428 break;
429 case FONT_MAGIC:
430 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
431 break;
432 case PALETTE_MAGIC:
433 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
434 break;
436 GDI_HEAP_UNLOCK( handle );
437 return result;
441 /***********************************************************************
442 * GetObject32A (GDI32.204)
444 INT32 WINAPI GetObject32A( HANDLE32 handle, INT32 count, LPVOID buffer )
446 GDIOBJHDR * ptr = NULL;
447 INT32 result = 0;
448 TRACE(gdi, "%08x %d %p\n", handle, count, buffer );
449 if (!count) return 0;
451 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
452 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
453 else
454 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
455 if (!ptr) return 0;
457 switch(ptr->wMagic)
459 case PEN_MAGIC:
460 result = PEN_GetObject32( (PENOBJ *)ptr, count, buffer );
461 break;
462 case BRUSH_MAGIC:
463 result = BRUSH_GetObject32( (BRUSHOBJ *)ptr, count, buffer );
464 break;
465 case BITMAP_MAGIC:
466 result = BITMAP_GetObject32( (BITMAPOBJ *)ptr, count, buffer );
467 break;
468 case FONT_MAGIC:
469 result = FONT_GetObject32A( (FONTOBJ *)ptr, count, buffer );
470 break;
471 case PALETTE_MAGIC:
472 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
473 break;
474 default:
475 fprintf( stderr, "GetObject32: magic %04x not implemented\n",
476 ptr->wMagic );
477 break;
479 GDI_HEAP_UNLOCK( handle );
480 return result;
483 /***********************************************************************
484 * GetObjectType (GDI32.205)
486 DWORD WINAPI GetObjectType( HANDLE32 handle )
488 GDIOBJHDR * ptr = NULL;
489 INT32 result = 0;
490 TRACE(gdi, "%08x\n", handle );
492 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
493 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
494 else
495 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
496 if (!ptr) return 0;
498 switch(ptr->wMagic)
500 case PEN_MAGIC:
501 result = OBJ_PEN;
502 break;
503 case BRUSH_MAGIC:
504 result = OBJ_BRUSH;
505 break;
506 case BITMAP_MAGIC:
507 result = OBJ_BITMAP;
508 break;
509 case FONT_MAGIC:
510 result = OBJ_FONT;
511 break;
512 case PALETTE_MAGIC:
513 result = OBJ_PAL;
514 break;
515 case REGION_MAGIC:
516 result = OBJ_REGION;
517 break;
518 case DC_MAGIC:
519 result = OBJ_DC;
520 break;
521 case META_DC_MAGIC:
522 result = OBJ_METADC;
523 break;
524 case METAFILE_MAGIC:
525 result = OBJ_METAFILE;
526 break;
527 case METAFILE_DC_MAGIC:
528 result = OBJ_METADC;
529 break;
531 default:
532 fprintf( stderr, "GetObjectType: magic %04x not implemented\n",
533 ptr->wMagic );
534 break;
536 GDI_HEAP_UNLOCK( handle );
537 return result;
540 /***********************************************************************
541 * GetObject32W (GDI32.206)
543 INT32 WINAPI GetObject32W( HANDLE32 handle, INT32 count, LPVOID buffer )
545 return GetObject32A( handle, count, buffer );
548 /***********************************************************************
549 * GetCurrentObject (GDI32.166)
551 HANDLE32 WINAPI GetCurrentObject(HDC32 hdc,UINT32 type)
553 DC * dc = DC_GetDCPtr( hdc );
555 if (!dc)
556 return 0;
557 switch (type) {
558 case OBJ_PEN: return dc->w.hPen;
559 case OBJ_BRUSH: return dc->w.hBrush;
560 case OBJ_PAL: return dc->w.hPalette;
561 case OBJ_FONT: return dc->w.hFont;
562 case OBJ_BITMAP: return dc->w.hBitmap;
563 default:
564 /* the SDK only mentions those above */
565 fprintf(stderr,"GetCurrentObject(%08x,%d), unknown type.\n",hdc,type);
566 return 0;
571 /***********************************************************************
572 * SelectObject16 (GDI.45)
574 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
576 return (HGDIOBJ16)SelectObject32( hdc, handle );
580 /***********************************************************************
581 * SelectObject32 (GDI32.299)
583 HGDIOBJ32 WINAPI SelectObject32( HDC32 hdc, HGDIOBJ32 handle )
585 DC * dc = DC_GetDCPtr( hdc );
586 if (!dc || !dc->funcs->pSelectObject) return 0;
587 TRACE(gdi, "hdc=%04x %04x\n", hdc, handle );
588 return dc->funcs->pSelectObject( dc, handle );
592 /***********************************************************************
593 * UnrealizeObject16 (GDI.150)
595 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
597 return UnrealizeObject32( obj );
601 /***********************************************************************
602 * UnrealizeObject (GDI32.358)
604 BOOL32 WINAPI UnrealizeObject32( HGDIOBJ32 obj )
606 BOOL32 result = TRUE;
607 /* Check if object is valid */
609 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
610 if (!header) return FALSE;
612 TRACE(gdi, "%04x\n", obj );
614 /* Unrealize object */
616 switch(header->wMagic)
618 case PALETTE_MAGIC:
619 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
620 break;
622 case BRUSH_MAGIC:
623 /* Windows resets the brush origin. We don't need to. */
624 break;
626 GDI_HEAP_UNLOCK( obj );
627 return result;
631 /***********************************************************************
632 * EnumObjects16 (GDI.71)
634 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
635 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
637 /* Solid colors to enumerate */
638 static const COLORREF solid_colors[] =
639 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
640 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
641 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
642 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
643 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
644 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
645 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
646 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
649 INT16 i, retval = 0;
650 LOGPEN16 *pen;
651 LOGBRUSH16 *brush = NULL;
653 TRACE(gdi, "%04x %d %08lx %08lx\n",
654 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
655 switch(nObjType)
657 case OBJ_PEN:
658 /* Enumerate solid pens */
659 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
660 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
662 pen->lopnStyle = PS_SOLID;
663 pen->lopnWidth.x = 1;
664 pen->lopnWidth.y = 0;
665 pen->lopnColor = solid_colors[i];
666 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
667 TRACE(gdi, "solid pen %08lx, ret=%d\n",
668 solid_colors[i], retval);
669 if (!retval) break;
671 SEGPTR_FREE(pen);
672 break;
674 case OBJ_BRUSH:
675 /* Enumerate solid brushes */
676 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
677 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
679 brush->lbStyle = BS_SOLID;
680 brush->lbColor = solid_colors[i];
681 brush->lbHatch = 0;
682 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
683 TRACE(gdi, "solid brush %08lx, ret=%d\n",
684 solid_colors[i], retval);
685 if (!retval) break;
688 /* Now enumerate hatched brushes */
689 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
691 brush->lbStyle = BS_HATCHED;
692 brush->lbColor = RGB(0,0,0);
693 brush->lbHatch = i;
694 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
695 TRACE(gdi, "hatched brush %d, ret=%d\n",
696 i, retval);
697 if (!retval) break;
699 SEGPTR_FREE(brush);
700 break;
702 default:
703 fprintf( stderr, "EnumObjects16: invalid type %d\n", nObjType );
704 break;
706 return retval;
710 /***********************************************************************
711 * EnumObjects32 (GDI32.89)
713 INT32 WINAPI EnumObjects32( HDC32 hdc, INT32 nObjType,
714 GOBJENUMPROC32 lpEnumFunc, LPARAM lParam )
716 /* Solid colors to enumerate */
717 static const COLORREF solid_colors[] =
718 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
719 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
720 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
721 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
722 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
723 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
724 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
725 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
728 INT32 i, retval = 0;
729 LOGPEN32 pen;
730 LOGBRUSH32 brush;
732 TRACE(gdi, "%04x %d %08lx %08lx\n",
733 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
734 switch(nObjType)
736 case OBJ_PEN:
737 /* Enumerate solid pens */
738 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
740 pen.lopnStyle = PS_SOLID;
741 pen.lopnWidth.x = 1;
742 pen.lopnWidth.y = 0;
743 pen.lopnColor = solid_colors[i];
744 retval = lpEnumFunc( &pen, lParam );
745 TRACE(gdi, "solid pen %08lx, ret=%d\n",
746 solid_colors[i], retval);
747 if (!retval) break;
749 break;
751 case OBJ_BRUSH:
752 /* Enumerate solid brushes */
753 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
755 brush.lbStyle = BS_SOLID;
756 brush.lbColor = solid_colors[i];
757 brush.lbHatch = 0;
758 retval = lpEnumFunc( &brush, lParam );
759 TRACE(gdi, "solid brush %08lx, ret=%d\n",
760 solid_colors[i], retval);
761 if (!retval) break;
764 /* Now enumerate hatched brushes */
765 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
767 brush.lbStyle = BS_HATCHED;
768 brush.lbColor = RGB(0,0,0);
769 brush.lbHatch = i;
770 retval = lpEnumFunc( &brush, lParam );
771 TRACE(gdi, "hatched brush %d, ret=%d\n",
772 i, retval);
773 if (!retval) break;
775 break;
777 default:
778 /* FIXME: implement Win32 types */
779 fprintf( stderr, "EnumObjects32: invalid type %d\n", nObjType );
780 break;
782 return retval;
786 /***********************************************************************
787 * IsGDIObject (GDI.462)
789 * returns type of object if valid (W95 system programming secrets p. 264-5)
791 BOOL16 WINAPI IsGDIObject( HGDIOBJ16 handle )
793 if (handle >= FIRST_STOCK_HANDLE )
794 return TRUE;
795 else
797 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
798 if (object)
800 UINT16 magic = object->wMagic;
801 GDI_HEAP_UNLOCK( handle );
802 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
803 return magic - PEN_MAGIC + 1;
806 return FALSE;
810 /***********************************************************************
811 * SetObjectOwner16 (GDI.461)
813 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
815 /* Nothing to do */
819 /***********************************************************************
820 * SetObjectOwner32 (GDI32.386)
822 void WINAPI SetObjectOwner32( HGDIOBJ32 handle, HANDLE32 owner )
824 /* Nothing to do */
827 /***********************************************************************
828 * GdiFlush (GDI32.128)
830 BOOL32 WINAPI GdiFlush(void)
832 return TRUE; /* FIXME */
836 /***********************************************************************
837 * GdiGetBatchLimit (GDI32.129)
839 DWORD WINAPI GdiGetBatchLimit(void)
841 return 1; /* FIXME */
845 /***********************************************************************
846 * GdiSetBatchLimit (GDI32.139)
848 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
850 return 1; /* FIXME */
854 /***********************************************************************
855 * GdiSeeGdiDo (GDI.452)
857 DWORD WINAPI GdiSeeGdiDo( WORD wReqType, WORD wParam1, WORD wParam2,
858 WORD wParam3 )
860 switch (wReqType)
862 case 0x0001: /* LocalAlloc */
863 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
864 case 0x0002: /* LocalFree */
865 return LOCAL_Free( GDI_HeapSel, wParam1 );
866 case 0x0003: /* LocalCompact */
867 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
868 case 0x0103: /* LocalHeap */
869 return GDI_HeapSel;
870 default:
871 fprintf(stderr, "GdiSeeGdiDo: wReqType %04x (unknown)", wReqType);
872 return (DWORD)-1;
876 /***********************************************************************
877 * MulDiv16 (GDI.128)
879 INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
881 INT32 ret;
882 if (!baz) return -32768;
883 ret = (foo * bar) / baz;
884 if ((ret > 32767) || (ret < -32767)) return -32768;
885 return ret;
889 /***********************************************************************
890 * MulDiv32 (KERNEL32.391)
891 * RETURNS
892 * Result of multiplication and division
893 * -1: Overflow occurred or Divisor was 0
895 INT32 WINAPI MulDiv32(
896 INT32 nMultiplicand,
897 INT32 nMultiplier,
898 INT32 nDivisor
900 #ifdef __GNUC__
901 long long ret;
902 if (!nDivisor) return -1;
903 ret = ((long long)nMultiplicand * nMultiplier) / nDivisor;
904 if ((ret > 2147483647) || (ret < -2147483647)) return -1;
905 return ret;
906 #else
907 if (!nDivisor) return -1;
908 return (nMultiplicand * nMultiplier) / nDivisor;
909 #endif