Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbeyj@wpi.edu>
[wine.git] / objects / gdiobj.c
bloba2bad9740764552ffc3df01cbc9ee074be011077
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #ifndef X_DISPLAY_MISSING
8 #include "x11drv.h"
9 #else /* !defined(X_DISPLAY_MISSING) */
10 #include "ttydrv.h"
11 #endif /* !defined(X_DISPLAY_MISSING */
13 #include <stdlib.h>
15 #include "bitmap.h"
16 #include "brush.h"
17 #include "dc.h"
18 #include "font.h"
19 #include "heap.h"
20 #include "options.h"
21 #include "palette.h"
22 #include "pen.h"
23 #include "region.h"
24 #include "debug.h"
25 #include "gdi.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 { 12, 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 { 12, 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 { 12, 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 { 16, 0, 0, 0, FW_BOLD, 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 { 12, 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 { 12, 0, 0, 0, FW_BOLD, 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 { 9, FONT_MAGIC, 1 }, /* header */
150 { 12, 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 /******************************************************************************
180 * void ReadFontInformation(
181 * char const *fontName,
182 * FONTOBJ *font,
183 * int defHeight,
184 * int defBold,
185 * int defItalic,
186 * int defUnderline,
187 * int defStrikeOut )
189 * ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
190 * section for entries containing fontName.Height, fontName.Bold, etc.,
191 * where fontName is the name specified in the call (e.g., "System"). It
192 * attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
193 * the first character in the boolean attributes (bold, italic, and
194 * underline).
195 *****************************************************************************/
197 static void ReadFontInformation(
198 char const *fontName,
199 FONTOBJ *font,
200 int defHeight,
201 int defBold,
202 int defItalic,
203 int defUnderline,
204 int defStrikeOut )
206 char key[256];
208 sprintf(key, "%s.Height", fontName);
209 font->logfont.lfHeight =
210 PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
212 sprintf(key, "%s.Bold", fontName);
213 font->logfont.lfWeight =
214 (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
215 FW_BOLD : FW_NORMAL;
217 sprintf(key, "%s.Italic", fontName);
218 font->logfont.lfItalic =
219 PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
221 sprintf(key, "%s.Underline", fontName);
222 font->logfont.lfUnderline =
223 PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
225 sprintf(key, "%s.StrikeOut", fontName);
226 font->logfont.lfStrikeOut =
227 PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
229 return;
233 /***********************************************************************
234 * GDI_Init
236 * GDI initialization.
238 BOOL GDI_Init(void)
240 /* Kill some warnings. */
241 (void)align_OEMFixedFont;
242 (void)align_AnsiFixedFont;
243 (void)align_AnsiVarFont;
244 (void)align_SystemFont;
245 (void)align_DeviceDefaultFont;
246 (void)align_SystemFixedFont;
247 (void)align_DefaultGuiFont;
249 /* TWEAK: Initialize font hints */
250 ReadFontInformation("OEMFixed", &OEMFixedFont, 12, 0, 0, 0, 0);
251 ReadFontInformation("AnsiFixed", &AnsiFixedFont, 12, 0, 0, 0, 0);
252 ReadFontInformation("AnsiVar", &AnsiVarFont, 12, 0, 0, 0, 0);
253 ReadFontInformation("System", &SystemFont, 16, 1, 0, 0, 0);
254 ReadFontInformation("SystemFixed", &SystemFixedFont, 12, 1, 0, 0, 0);
256 /* Initialize drivers */
258 #ifndef X_DISPLAY_MISSING
259 GDI_Driver = &X11DRV_GDI_Driver;
260 #else /* !defined(X_DISPLAY_MISSING) */
261 GDI_Driver = &TTYDRV_GDI_Driver;
262 #endif /* !defined(X_DISPLAY_MISSING */
264 GDI_Driver->pInitialize();
266 /* Create default palette */
268 /* DR well *this* palette can't be moveable (?) */
270 HPALETTE16 hpalette = PALETTE_Init();
271 if( !hpalette )
272 return FALSE;
273 StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
276 return TRUE;
280 /***********************************************************************
281 * GDI_AllocObject
283 HGDIOBJ16 GDI_AllocObject( WORD size, WORD magic )
285 static DWORD count = 0;
286 GDIOBJHDR * obj;
287 HGDIOBJ16 handle;
288 if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
289 handle = GDI_HEAP_ALLOC( size );
290 else
291 handle = GDI_HEAP_ALLOC_MOVEABLE( size );
292 if (!handle) return 0;
293 obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
294 obj->hNext = 0;
295 obj->wMagic = magic;
296 obj->dwCount = ++count;
297 GDI_HEAP_UNLOCK( handle );
298 return handle;
302 /***********************************************************************
303 * GDI_FreeObject
305 BOOL GDI_FreeObject( HGDIOBJ16 handle )
307 GDIOBJHDR * object;
309 /* Can't free stock objects */
310 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
311 return TRUE;
313 object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
314 if (!object) return FALSE;
315 object->wMagic = 0; /* Mark it as invalid */
317 /* Free object */
319 GDI_HEAP_FREE( handle );
320 return TRUE;
323 /***********************************************************************
324 * GDI_GetObjPtr
326 * Return a pointer to the GDI object associated to the handle.
327 * Return NULL if the object has the wrong magic number.
328 * Movable GDI objects are locked in memory: it is up to the caller to unlock
329 * it after the caller is done with the pointer.
331 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16 handle, WORD magic )
333 GDIOBJHDR * ptr = NULL;
335 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
336 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
337 else
338 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
339 if (!ptr) return NULL;
340 if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
342 GDI_HEAP_UNLOCK( handle );
343 return NULL;
345 return ptr;
349 /***********************************************************************
350 * DeleteObject16 (GDI.69)
352 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
354 return DeleteObject( obj );
358 /***********************************************************************
359 * DeleteObject32 (GDI32.70)
361 BOOL WINAPI DeleteObject( HGDIOBJ obj )
363 /* Check if object is valid */
365 GDIOBJHDR * header;
366 if (HIWORD(obj)) return FALSE;
367 if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
368 return TRUE;
369 if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
371 TRACE(gdi, "%04x\n", obj );
373 /* Delete object */
375 switch(header->wMagic)
377 case PEN_MAGIC: return GDI_FreeObject( obj );
378 case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
379 case FONT_MAGIC: return GDI_FreeObject( obj );
380 case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
381 case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
382 case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
383 case DC_MAGIC: return DeleteDC(obj);
384 case 0 :
385 WARN(gdi, "Already deleted\n");
386 break;
387 default:
388 WARN(gdi, "Unknown magic number (%d)\n",header->wMagic);
390 return FALSE;
393 /***********************************************************************
394 * GetStockObject16 (GDI.87)
396 HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
398 return (HGDIOBJ16)GetStockObject( obj );
402 /***********************************************************************
403 * GetStockObject32 (GDI32.220)
405 HGDIOBJ WINAPI GetStockObject( INT obj )
407 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
408 if (!StockObjects[obj]) return 0;
409 TRACE(gdi, "returning %d\n",
410 FIRST_STOCK_HANDLE + obj );
411 return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
415 /***********************************************************************
416 * GetObject16 (GDI.82)
418 INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
420 GDIOBJHDR * ptr = NULL;
421 INT16 result = 0;
422 TRACE(gdi, "%04x %d %p\n", handle, count, buffer );
423 if (!count) return 0;
425 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
426 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
427 else
428 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
429 if (!ptr) return 0;
431 switch(ptr->wMagic)
433 case PEN_MAGIC:
434 result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
435 break;
436 case BRUSH_MAGIC:
437 result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
438 break;
439 case BITMAP_MAGIC:
440 result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
441 break;
442 case FONT_MAGIC:
443 result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
444 break;
445 case PALETTE_MAGIC:
446 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
447 break;
449 GDI_HEAP_UNLOCK( handle );
450 return result;
454 /***********************************************************************
455 * GetObject32A (GDI32.204)
457 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
459 GDIOBJHDR * ptr = NULL;
460 INT result = 0;
461 TRACE(gdi, "%08x %d %p\n", handle, count, buffer );
462 if (!count) return 0;
464 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
465 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
466 else
467 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
468 if (!ptr) return 0;
470 switch(ptr->wMagic)
472 case PEN_MAGIC:
473 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
474 break;
475 case BRUSH_MAGIC:
476 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
477 break;
478 case BITMAP_MAGIC:
479 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
480 break;
481 case FONT_MAGIC:
482 result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
483 break;
484 case PALETTE_MAGIC:
485 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
486 break;
487 default:
488 FIXME(gdi, "Magic %04x not implemented\n",
489 ptr->wMagic );
490 break;
492 GDI_HEAP_UNLOCK( handle );
493 return result;
495 /***********************************************************************
496 * GetObject32W (GDI32.206)
498 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
500 GDIOBJHDR * ptr = NULL;
501 INT result = 0;
502 TRACE(gdi, "%08x %d %p\n", handle, count, buffer );
503 if (!count) return 0;
505 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
506 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
507 else
508 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
509 if (!ptr) return 0;
511 switch(ptr->wMagic)
513 case PEN_MAGIC:
514 result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
515 break;
516 case BRUSH_MAGIC:
517 result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
518 break;
519 case BITMAP_MAGIC:
520 result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
521 break;
522 case FONT_MAGIC:
523 result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
524 break;
525 case PALETTE_MAGIC:
526 result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
527 break;
528 default:
529 FIXME(gdi, "Magic %04x not implemented\n",
530 ptr->wMagic );
531 break;
533 GDI_HEAP_UNLOCK( handle );
534 return result;
537 /***********************************************************************
538 * GetObjectType (GDI32.205)
540 DWORD WINAPI GetObjectType( HANDLE handle )
542 GDIOBJHDR * ptr = NULL;
543 INT result = 0;
544 TRACE(gdi, "%08x\n", handle );
546 if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
547 ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
548 else
549 ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
550 if (!ptr) return 0;
552 switch(ptr->wMagic)
554 case PEN_MAGIC:
555 result = OBJ_PEN;
556 break;
557 case BRUSH_MAGIC:
558 result = OBJ_BRUSH;
559 break;
560 case BITMAP_MAGIC:
561 result = OBJ_BITMAP;
562 break;
563 case FONT_MAGIC:
564 result = OBJ_FONT;
565 break;
566 case PALETTE_MAGIC:
567 result = OBJ_PAL;
568 break;
569 case REGION_MAGIC:
570 result = OBJ_REGION;
571 break;
572 case DC_MAGIC:
573 result = OBJ_DC;
574 break;
575 case META_DC_MAGIC:
576 result = OBJ_METADC;
577 break;
578 case METAFILE_MAGIC:
579 result = OBJ_METAFILE;
580 break;
581 case METAFILE_DC_MAGIC:
582 result = OBJ_METADC;
583 break;
584 case ENHMETAFILE_MAGIC:
585 result = OBJ_ENHMETAFILE;
586 break;
587 case ENHMETAFILE_DC_MAGIC:
588 result = OBJ_ENHMETADC;
589 break;
590 default:
591 FIXME(gdi, "Magic %04x not implemented\n",
592 ptr->wMagic );
593 break;
595 GDI_HEAP_UNLOCK( handle );
596 return result;
599 /***********************************************************************
600 * GetCurrentObject (GDI32.166)
602 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
604 DC * dc = DC_GetDCPtr( hdc );
606 if (!dc)
607 return 0;
608 switch (type) {
609 case OBJ_PEN: return dc->w.hPen;
610 case OBJ_BRUSH: return dc->w.hBrush;
611 case OBJ_PAL: return dc->w.hPalette;
612 case OBJ_FONT: return dc->w.hFont;
613 case OBJ_BITMAP: return dc->w.hBitmap;
614 default:
615 /* the SDK only mentions those above */
616 WARN(gdi,"(%08x,%d): unknown type.\n",hdc,type);
617 return 0;
622 /***********************************************************************
623 * SelectObject16 (GDI.45)
625 HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
627 return (HGDIOBJ16)SelectObject( hdc, handle );
631 /***********************************************************************
632 * SelectObject32 (GDI32.299)
634 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
636 DC * dc = DC_GetDCPtr( hdc );
637 if (!dc || !dc->funcs->pSelectObject) return 0;
638 TRACE(gdi, "hdc=%04x %04x\n", hdc, handle );
639 return dc->funcs->pSelectObject( dc, handle );
643 /***********************************************************************
644 * UnrealizeObject16 (GDI.150)
646 BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
648 return UnrealizeObject( obj );
652 /***********************************************************************
653 * UnrealizeObject (GDI32.358)
655 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
657 BOOL result = TRUE;
658 /* Check if object is valid */
660 GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
661 if (!header) return FALSE;
663 TRACE(gdi, "%04x\n", obj );
665 /* Unrealize object */
667 switch(header->wMagic)
669 case PALETTE_MAGIC:
670 result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
671 break;
673 case BRUSH_MAGIC:
674 /* Windows resets the brush origin. We don't need to. */
675 break;
677 GDI_HEAP_UNLOCK( obj );
678 return result;
682 /***********************************************************************
683 * EnumObjects16 (GDI.71)
685 INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
686 GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
688 /* Solid colors to enumerate */
689 static const COLORREF solid_colors[] =
690 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
691 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
692 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
693 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
694 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
695 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
696 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
697 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
700 INT16 i, retval = 0;
701 LOGPEN16 *pen;
702 LOGBRUSH16 *brush = NULL;
704 TRACE(gdi, "%04x %d %08lx %08lx\n",
705 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
706 switch(nObjType)
708 case OBJ_PEN:
709 /* Enumerate solid pens */
710 if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
711 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
713 pen->lopnStyle = PS_SOLID;
714 pen->lopnWidth.x = 1;
715 pen->lopnWidth.y = 0;
716 pen->lopnColor = solid_colors[i];
717 retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
718 TRACE(gdi, "solid pen %08lx, ret=%d\n",
719 solid_colors[i], retval);
720 if (!retval) break;
722 SEGPTR_FREE(pen);
723 break;
725 case OBJ_BRUSH:
726 /* Enumerate solid brushes */
727 if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
728 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
730 brush->lbStyle = BS_SOLID;
731 brush->lbColor = solid_colors[i];
732 brush->lbHatch = 0;
733 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
734 TRACE(gdi, "solid brush %08lx, ret=%d\n",
735 solid_colors[i], retval);
736 if (!retval) break;
739 /* Now enumerate hatched brushes */
740 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
742 brush->lbStyle = BS_HATCHED;
743 brush->lbColor = RGB(0,0,0);
744 brush->lbHatch = i;
745 retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
746 TRACE(gdi, "hatched brush %d, ret=%d\n",
747 i, retval);
748 if (!retval) break;
750 SEGPTR_FREE(brush);
751 break;
753 default:
754 WARN(gdi, "(%d): Invalid type\n", nObjType );
755 break;
757 return retval;
761 /***********************************************************************
762 * EnumObjects32 (GDI32.89)
764 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
765 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
767 /* Solid colors to enumerate */
768 static const COLORREF solid_colors[] =
769 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
770 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
771 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
772 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
773 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
774 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
775 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
776 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
779 INT i, retval = 0;
780 LOGPEN pen;
781 LOGBRUSH brush;
783 TRACE(gdi, "%04x %d %08lx %08lx\n",
784 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
785 switch(nObjType)
787 case OBJ_PEN:
788 /* Enumerate solid pens */
789 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
791 pen.lopnStyle = PS_SOLID;
792 pen.lopnWidth.x = 1;
793 pen.lopnWidth.y = 0;
794 pen.lopnColor = solid_colors[i];
795 retval = lpEnumFunc( &pen, lParam );
796 TRACE(gdi, "solid pen %08lx, ret=%d\n",
797 solid_colors[i], retval);
798 if (!retval) break;
800 break;
802 case OBJ_BRUSH:
803 /* Enumerate solid brushes */
804 for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
806 brush.lbStyle = BS_SOLID;
807 brush.lbColor = solid_colors[i];
808 brush.lbHatch = 0;
809 retval = lpEnumFunc( &brush, lParam );
810 TRACE(gdi, "solid brush %08lx, ret=%d\n",
811 solid_colors[i], retval);
812 if (!retval) break;
815 /* Now enumerate hatched brushes */
816 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
818 brush.lbStyle = BS_HATCHED;
819 brush.lbColor = RGB(0,0,0);
820 brush.lbHatch = i;
821 retval = lpEnumFunc( &brush, lParam );
822 TRACE(gdi, "hatched brush %d, ret=%d\n",
823 i, retval);
824 if (!retval) break;
826 break;
828 default:
829 /* FIXME: implement Win32 types */
830 WARN( gdi, "(%d): Invalid type\n", nObjType );
831 break;
833 return retval;
837 /***********************************************************************
838 * IsGDIObject (GDI.462)
840 * returns type of object if valid (W95 system programming secrets p. 264-5)
842 BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
844 UINT16 magic = 0;
846 if (handle >= FIRST_STOCK_HANDLE )
848 switch (handle)
850 case STOCK_WHITE_BRUSH:
851 case STOCK_LTGRAY_BRUSH:
852 case STOCK_GRAY_BRUSH:
853 case STOCK_DKGRAY_BRUSH:
854 case STOCK_BLACK_BRUSH:
855 case STOCK_HOLLOW_BRUSH:
856 magic = BRUSH_MAGIC;
857 break;
859 case STOCK_WHITE_PEN:
860 case STOCK_BLACK_PEN:
861 case STOCK_NULL_PEN :
862 magic = PEN_MAGIC;
863 break;
865 case STOCK_OEM_FIXED_FONT:
866 case STOCK_ANSI_FIXED_FONT:
867 case STOCK_ANSI_VAR_FONT:
868 case STOCK_SYSTEM_FONT:
869 case STOCK_DEVICE_DEFAULT_FONT:
870 case STOCK_SYSTEM_FIXED_FONT:
871 case STOCK_DEFAULT_GUI_FONT:
872 magic = FONT_MAGIC;
873 break;
875 case STOCK_DEFAULT_PALETTE:
876 magic = PALETTE_MAGIC;
877 break;
880 else
882 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
883 if (object)
885 magic = object->wMagic;
886 GDI_HEAP_UNLOCK( handle );
890 if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
891 return magic - PEN_MAGIC + 1;
892 else
893 return FALSE;
897 /***********************************************************************
898 * SetObjectOwner16 (GDI.461)
900 void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
902 /* Nothing to do */
906 /***********************************************************************
907 * SetObjectOwner32 (GDI32.386)
909 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
911 /* Nothing to do */
914 /***********************************************************************
915 * MakeObjectPrivate (GDI.463)
917 void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
919 /* FIXME */
923 /***********************************************************************
924 * GdiFlush (GDI32.128)
926 BOOL WINAPI GdiFlush(void)
928 return TRUE; /* FIXME */
932 /***********************************************************************
933 * GdiGetBatchLimit (GDI32.129)
935 DWORD WINAPI GdiGetBatchLimit(void)
937 return 1; /* FIXME */
941 /***********************************************************************
942 * GdiSetBatchLimit (GDI32.139)
944 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
946 return 1; /* FIXME */
950 /***********************************************************************
951 * GdiSeeGdiDo (GDI.452)
953 DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
954 WORD wParam3 )
956 switch (wReqType)
958 case 0x0001: /* LocalAlloc */
959 return LOCAL_Alloc( GDI_HeapSel, wParam1, wParam3 );
960 case 0x0002: /* LocalFree */
961 return LOCAL_Free( GDI_HeapSel, wParam1 );
962 case 0x0003: /* LocalCompact */
963 return LOCAL_Compact( GDI_HeapSel, wParam3, 0 );
964 case 0x0103: /* LocalHeap */
965 return GDI_HeapSel;
966 default:
967 WARN(gdi, "(wReqType=%04x): Unknown\n", wReqType);
968 return (DWORD)-1;
972 /***********************************************************************
973 * GdiSignalProc (GDI.610)
975 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
976 DWORD dwFlags, HMODULE16 hModule )
978 return 0;
982 /***********************************************************************
983 * GdiFreeResources (GDI.609)
985 WORD WINAPI GdiFreeResources16( DWORD reserve )
987 return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
988 (int)LOCAL_HeapSize( GDI_HeapSel ) );
991 /***********************************************************************
992 * MulDiv16 (GDI.128)
994 INT16 WINAPI MulDiv16( INT16 foo, INT16 bar, INT16 baz )
996 INT ret;
997 if (!baz) return -32768;
998 ret = (foo * bar) / baz;
999 if ((ret > 32767) || (ret < -32767)) return -32768;
1000 return ret;
1004 /***********************************************************************
1005 * MulDiv32 (KERNEL32.391)
1006 * RETURNS
1007 * Result of multiplication and division
1008 * -1: Overflow occurred or Divisor was 0
1010 INT WINAPI MulDiv(
1011 INT nMultiplicand,
1012 INT nMultiplier,
1013 INT nDivisor
1015 #if (SIZEOF_LONG_LONG >= 8)
1016 long long ret;
1017 if (!nDivisor) return -1;
1018 ret = ((long long)nMultiplicand * nMultiplier) / nDivisor;
1019 if ((ret > 2147483647) || (ret < -2147483647)) return -1;
1020 return ret;
1021 #else
1022 if (!nDivisor) return -1;
1023 return (nMultiplicand * nMultiplier) / nDivisor;
1024 #endif
1026 /*******************************************************************
1027 * GetColorAdjustment [GDI32.164]
1031 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1033 FIXME(gdi, "GetColorAdjustment, stub\n");
1034 return 0;
1037 /*******************************************************************
1038 * GetMiterLimit [GDI32.201]
1042 BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
1044 FIXME(gdi, "GetMiterLimit, stub\n");
1045 return 0;
1048 /*******************************************************************
1049 * SetMiterLimit [GDI32.325]
1053 BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
1055 FIXME(gdi, "SetMiterLimit, stub\n");
1056 return 0;
1059 /*******************************************************************
1060 * GdiComment [GDI32.109]
1064 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1066 FIXME(gdi, "GdiComment, stub\n");
1067 return 0;
1069 /*******************************************************************
1070 * SetColorAdjustment [GDI32.309]
1074 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1076 FIXME(gdi, "SetColorAdjustment, stub\n");
1077 return 0;