Release 970202
[wine] / objects / gdiobj.c
1 /*
2  * GDI functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 #define NO_TRANSITION_TYPES  /* This file is Win32-clean */
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include "gdi.h"
11 #include "color.h"
12 #include "bitmap.h"
13 #include "brush.h"
14 #include "font.h"
15 #include "heap.h"
16 #include "palette.h"
17 #include "pen.h"
18 #include "region.h"
19 #include "stddebug.h"
20 #include "debug.h"
21
22 WORD GDI_HeapSel = 0;
23
24 /* Object types for EnumObjects() */
25 #define OBJ_PEN             1
26 #define OBJ_BRUSH           2
27
28 /***********************************************************************
29  *          GDI stock objects 
30  */
31
32 static BRUSHOBJ WhiteBrush =
33 {
34     { 0, BRUSH_MAGIC, 1 },             /* header */
35     { BS_SOLID, RGB(255,255,255), 0 }  /* logbrush */
36 };
37
38 static BRUSHOBJ LtGrayBrush =
39 {
40     { 0, BRUSH_MAGIC, 1 },             /* header */
41     { BS_SOLID, RGB(192,192,192), 0 }  /* logbrush */
42 };
43
44 static BRUSHOBJ GrayBrush =
45 {
46     { 0, BRUSH_MAGIC, 1 },             /* header */
47     { BS_SOLID, RGB(128,128,128), 0 }  /* logbrush */
48 };
49
50 static BRUSHOBJ DkGrayBrush =
51 {
52     { 0, BRUSH_MAGIC, 1 },          /* header */
53     { BS_SOLID, RGB(64,64,64), 0 }  /* logbrush */
54 };
55
56 static BRUSHOBJ BlackBrush =
57 {
58     { 0, BRUSH_MAGIC, 1 },       /* header */
59     { BS_SOLID, RGB(0,0,0), 0 }  /* logbrush */
60 };
61
62 static BRUSHOBJ NullBrush =
63 {
64     { 0, BRUSH_MAGIC, 1 },  /* header */
65     { BS_NULL, 0, 0 }       /* logbrush */
66 };
67
68 static PENOBJ WhitePen =
69 {
70     { 0, PEN_MAGIC, 1 },                     /* header */
71     { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
72 };
73
74 static PENOBJ BlackPen =
75 {
76     { 0, PEN_MAGIC, 1 },               /* header */
77     { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
78 };
79
80 static PENOBJ NullPen =
81 {
82     { 0, PEN_MAGIC, 1 },      /* header */
83     { PS_NULL, { 1, 0 }, 0 }  /* logpen */
84 };
85
86 static FONTOBJ OEMFixedFont =
87 {
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, "" }
91 };
92
93 static FONTOBJ AnsiFixedFont =
94 {
95     { 0, FONT_MAGIC, 1 },   /* header */
96     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
97       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
98 };
99
100 static FONTOBJ AnsiVarFont =
101 {
102     { 0, FONT_MAGIC, 1 },   /* header */
103     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
104       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
105 };
106
107 static FONTOBJ SystemFont =
108 {
109     { 0, FONT_MAGIC, 1 },   /* header */
110     { 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
111       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
112 };
113
114 static FONTOBJ DeviceDefaultFont =
115 {
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, "" }
119 };
120
121 static FONTOBJ SystemFixedFont =
122 {
123     { 0, FONT_MAGIC, 1 },   /* header */
124     { 12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
125       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
126 };
127
128
129 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
130 {
131     (GDIOBJHDR *) &WhiteBrush,
132     (GDIOBJHDR *) &LtGrayBrush,
133     (GDIOBJHDR *) &GrayBrush,
134     (GDIOBJHDR *) &DkGrayBrush,
135     (GDIOBJHDR *) &BlackBrush,
136     (GDIOBJHDR *) &NullBrush,
137     (GDIOBJHDR *) &WhitePen,
138     (GDIOBJHDR *) &BlackPen,
139     (GDIOBJHDR *) &NullPen,
140     NULL,
141     (GDIOBJHDR *) &OEMFixedFont,
142     (GDIOBJHDR *) &AnsiFixedFont,
143     (GDIOBJHDR *) &AnsiVarFont,
144     (GDIOBJHDR *) &SystemFont,
145     (GDIOBJHDR *) &DeviceDefaultFont,
146     NULL,            /* DEFAULT_PALETTE created by COLOR_Init */
147     (GDIOBJHDR *) &SystemFixedFont
148 };
149
150
151 /***********************************************************************
152  *           GDI_Init
153  *
154  * GDI initialization.
155  */
156 BOOL32 GDI_Init(void)
157 {
158     HPALETTE16 hpalette;
159     extern BOOL32 X11DRV_Init(void);
160
161     /* Initialize drivers */
162
163     if (!X11DRV_Init()) return FALSE;
164
165       /* Create default palette */
166
167     if (!(hpalette = COLOR_Init())) return FALSE;
168     StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LIN_ADDR( hpalette );
169
170     return TRUE;
171 }
172
173
174 /***********************************************************************
175  *           GDI_AllocObject
176  */
177 HGDIOBJ16 GDI_AllocObject( WORD size, WORD magic )
178 {
179     static DWORD count = 0;
180     GDIOBJHDR * obj;
181     HGDIOBJ16 handle = GDI_HEAP_ALLOC( size );
182     if (!handle) return 0;
183     obj = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
184     obj->hNext   = 0;
185     obj->wMagic  = magic;
186     obj->dwCount = ++count;
187     return handle;
188 }
189
190
191 /***********************************************************************
192  *           GDI_FreeObject
193  */
194 BOOL32 GDI_FreeObject( HGDIOBJ16 handle )
195 {
196     GDIOBJHDR * object;
197
198       /* Can't free stock objects */
199     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
200         return TRUE;
201     
202     object = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
203     if (!object) return FALSE;
204     object->wMagic = 0;  /* Mark it as invalid */
205
206       /* Free object */
207     
208     GDI_HEAP_FREE( handle );
209     return TRUE;
210 }
211
212 /***********************************************************************
213  *           GDI_GetObjPtr
214  *
215  * Return a pointer to the GDI object associated to the handle.
216  * Return NULL if the object has the wrong magic number.
217  */
218 GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16 handle, WORD magic )
219 {
220     GDIOBJHDR * ptr = NULL;
221
222     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
223       ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
224     else 
225       ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
226     if (!ptr) return NULL;
227     if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic)) return NULL;
228     return ptr;
229 }
230
231
232 /***********************************************************************
233  *           DeleteObject16    (GDI.69)
234  */
235 BOOL16 DeleteObject16( HGDIOBJ16 obj )
236 {
237     return DeleteObject32( obj );
238 }
239
240
241 /***********************************************************************
242  *           DeleteObject32    (GDI32.70)
243  */
244 BOOL32 DeleteObject32( HGDIOBJ32 obj )
245 {
246       /* Check if object is valid */
247
248     GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( obj );
249     if (!header || HIWORD(obj)) return FALSE;
250
251     dprintf_gdi(stddeb, "DeleteObject: %04x\n", obj );
252
253       /* Delete object */
254
255     switch(header->wMagic)
256     {
257       case PEN_MAGIC:     return GDI_FreeObject( obj );
258       case BRUSH_MAGIC:   return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
259       case FONT_MAGIC:    return GDI_FreeObject( obj );
260       case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
261       case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
262       case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
263     }
264     return FALSE;
265 }
266
267
268 /***********************************************************************
269  *           GetStockObject16    (GDI.87)
270  */
271 HGDIOBJ16 GetStockObject16( INT16 obj )
272 {
273     return (HGDIOBJ16)GetStockObject32( obj );
274 }
275
276
277 /***********************************************************************
278  *           GetStockObject32    (GDI32.220)
279  */
280 HGDIOBJ32 GetStockObject32( INT32 obj )
281 {
282     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
283     if (!StockObjects[obj]) return 0;
284     dprintf_gdi(stddeb, "GetStockObject: returning %d\n",
285                 FIRST_STOCK_HANDLE + obj );
286     return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
287 }
288
289
290 /***********************************************************************
291  *           GetObject16    (GDI.82)
292  */
293 INT16 GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
294 {
295     GDIOBJHDR * ptr = NULL;
296     dprintf_gdi(stddeb, "GetObject16: %04x %d %p\n", handle, count, buffer );
297     if (!count) return 0;
298
299     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
300       ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
301     else
302       ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
303     if (!ptr) return 0;
304     
305     switch(ptr->wMagic)
306     {
307       case PEN_MAGIC:
308           return PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
309       case BRUSH_MAGIC: 
310           return BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
311       case BITMAP_MAGIC: 
312           return BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
313       case FONT_MAGIC:
314           return FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
315       case PALETTE_MAGIC:
316           return PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
317     }
318     return 0;
319 }
320
321
322 /***********************************************************************
323  *           GetObject32A    (GDI32.204)
324  */
325 INT32 GetObject32A( HANDLE32 handle, INT32 count, LPVOID buffer )
326 {
327     GDIOBJHDR * ptr = NULL;
328     dprintf_gdi(stddeb, "GetObject32A: %08x %d %p\n", handle, count, buffer );
329     if (!count) return 0;
330
331     if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
332       ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
333     else
334       ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
335     if (!ptr) return 0;
336     
337     switch(ptr->wMagic)
338     {
339       case PEN_MAGIC:
340           return PEN_GetObject32( (PENOBJ *)ptr, count, buffer );
341       case BRUSH_MAGIC: 
342           return BRUSH_GetObject32( (BRUSHOBJ *)ptr, count, buffer );
343       case BITMAP_MAGIC: 
344           return BITMAP_GetObject32( (BITMAPOBJ *)ptr, count, buffer );
345       case FONT_MAGIC:
346           return FONT_GetObject32A( (FONTOBJ *)ptr, count, buffer );
347       case PALETTE_MAGIC:
348           fprintf( stderr, "GetObject32: magic %04x not implemented\n",
349                    ptr->wMagic );
350           break;
351     }
352     return 0;
353 }
354
355
356 /***********************************************************************
357  *           GetObject32W    (GDI32.206)
358  */
359 INT32 GetObject32W( HANDLE32 handle, INT32 count, LPVOID buffer )
360 {
361     return GetObject32A( handle, count, buffer );
362 }
363
364
365 /***********************************************************************
366  *           SelectObject16    (GDI.45)
367  */
368 HGDIOBJ16 SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
369 {
370     return (HGDIOBJ16)SelectObject32( hdc, handle );
371 }
372
373
374 /***********************************************************************
375  *           SelectObject32    (GDI32.299)
376  */
377 HGDIOBJ32 SelectObject32( HDC32 hdc, HGDIOBJ32 handle )
378 {
379     DC * dc = DC_GetDCPtr( hdc );
380     if (!dc || !dc->funcs->pSelectObject) return 0;
381     dprintf_gdi(stddeb, "SelectObject: hdc=%04x %04x\n", hdc, handle );
382     return dc->funcs->pSelectObject( dc, handle );
383 }
384
385
386 /***********************************************************************
387  *           UnrealizeObject16    (GDI.150)
388  */
389 BOOL16 UnrealizeObject16( HGDIOBJ16 obj )
390 {
391     return UnrealizeObject32( obj );
392 }
393
394
395 /***********************************************************************
396  *           UnrealizeObject    (GDI32.358)
397  */
398 BOOL32 UnrealizeObject32( HGDIOBJ32 obj )
399 {
400       /* Check if object is valid */
401
402     GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( obj );
403     if (!header) return FALSE;
404
405     dprintf_gdi( stddeb, "UnrealizeObject: %04x\n", obj );
406
407       /* Unrealize object */
408
409     switch(header->wMagic)
410     {
411     case PALETTE_MAGIC: 
412         return PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
413
414     case BRUSH_MAGIC:
415         /* Windows resets the brush origin. We don't need to. */
416         break;
417     }
418     return TRUE;
419 }
420
421
422 /***********************************************************************
423  *           EnumObjects16    (GDI.71)
424  */
425 INT16 EnumObjects16( HDC16 hdc, INT16 nObjType, GOBJENUMPROC16 lpEnumFunc,
426                      LPARAM lParam )
427 {
428     /* Solid colors to enumerate */
429     static const COLORREF solid_colors[] =
430     { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
431       RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
432       RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
433       RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
434       RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
435       RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
436       RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
437       RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
438     };
439     
440     INT16 i, retval = 0;
441     LOGPEN16 *pen;
442     LOGBRUSH16 *brush = NULL;
443
444     dprintf_gdi( stddeb, "EnumObjects16: %04x %d %08lx %08lx\n",
445                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
446     switch(nObjType)
447     {
448     case OBJ_PEN:
449         /* Enumerate solid pens */
450         if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
451         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
452         {
453             pen->lopnStyle   = PS_SOLID;
454             pen->lopnWidth.x = 1;
455             pen->lopnWidth.y = 0;
456             pen->lopnColor   = solid_colors[i];
457             retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
458             dprintf_gdi( stddeb, "EnumObjects16: solid pen %08lx, ret=%d\n",
459                          solid_colors[i], retval);
460             if (!retval) break;
461         }
462         SEGPTR_FREE(pen);
463         break;
464
465     case OBJ_BRUSH:
466         /* Enumerate solid brushes */
467         if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
468         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
469         {
470             brush->lbStyle = BS_SOLID;
471             brush->lbColor = solid_colors[i];
472             brush->lbHatch = 0;
473             retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
474             dprintf_gdi( stddeb, "EnumObjects16: solid brush %08lx, ret=%d\n",
475                          solid_colors[i], retval);
476             if (!retval) break;
477         }
478
479         /* Now enumerate hatched brushes */
480         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
481         {
482             brush->lbStyle = BS_HATCHED;
483             brush->lbColor = RGB(0,0,0);
484             brush->lbHatch = i;
485             retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
486             dprintf_gdi( stddeb, "EnumObjects16: hatched brush %d, ret=%d\n",
487                          i, retval);
488             if (!retval) break;
489         }
490         SEGPTR_FREE(brush);
491         break;
492
493     default:
494         fprintf( stderr, "EnumObjects16: invalid type %d\n", nObjType );
495         break;
496     }
497     return retval;
498 }
499
500
501 /***********************************************************************
502  *           EnumObjects32    (GDI32.89)
503  */
504 INT32 EnumObjects32( HDC32 hdc, INT32 nObjType, GOBJENUMPROC32 lpEnumFunc,
505                      LPARAM lParam )
506 {
507     /* Solid colors to enumerate */
508     static const COLORREF solid_colors[] =
509     { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
510       RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
511       RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
512       RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
513       RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
514       RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
515       RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
516       RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
517     };
518     
519     INT32 i, retval = 0;
520     LOGPEN32 pen;
521     LOGBRUSH32 brush;
522
523     dprintf_gdi( stddeb, "EnumObjects32: %04x %d %08lx %08lx\n",
524                  hdc, nObjType, (DWORD)lpEnumFunc, lParam );
525     switch(nObjType)
526     {
527     case OBJ_PEN:
528         /* Enumerate solid pens */
529         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
530         {
531             pen.lopnStyle   = PS_SOLID;
532             pen.lopnWidth.x = 1;
533             pen.lopnWidth.y = 0;
534             pen.lopnColor   = solid_colors[i];
535             retval = lpEnumFunc( &pen, lParam );
536             dprintf_gdi( stddeb, "EnumObjects32: solid pen %08lx, ret=%d\n",
537                          solid_colors[i], retval);
538             if (!retval) break;
539         }
540         break;
541
542     case OBJ_BRUSH:
543         /* Enumerate solid brushes */
544         for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
545         {
546             brush.lbStyle = BS_SOLID;
547             brush.lbColor = solid_colors[i];
548             brush.lbHatch = 0;
549             retval = lpEnumFunc( &brush, lParam );
550             dprintf_gdi( stddeb, "EnumObjects32: solid brush %08lx, ret=%d\n",
551                          solid_colors[i], retval);
552             if (!retval) break;
553         }
554
555         /* Now enumerate hatched brushes */
556         if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
557         {
558             brush.lbStyle = BS_HATCHED;
559             brush.lbColor = RGB(0,0,0);
560             brush.lbHatch = i;
561             retval = lpEnumFunc( &brush, lParam );
562             dprintf_gdi( stddeb, "EnumObjects32: hatched brush %d, ret=%d\n",
563                          i, retval);
564             if (!retval) break;
565         }
566         break;
567
568     default:
569         /* FIXME: implement Win32 types */
570         fprintf( stderr, "EnumObjects32: invalid type %d\n", nObjType );
571         break;
572     }
573     return retval;
574 }
575
576
577 /***********************************************************************
578  *           IsGDIObject    (GDI.462)
579  */
580 BOOL16 IsGDIObject( HGDIOBJ16 handle )
581 {
582     GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
583     if (object)
584       return (object->wMagic>=PEN_MAGIC && object->wMagic<= METAFILE_DC_MAGIC);
585     return FALSE;
586 }
587
588
589 /***********************************************************************
590  *           MulDiv16   (GDI.128)
591  */
592 INT16 MulDiv16( INT16 foo, INT16 bar, INT16 baz )
593 {
594     INT32 ret;
595     if (!baz) return -32768;
596     ret = (foo * bar) / baz;
597     if ((ret > 32767) || (ret < -32767)) return -32768;
598     return ret;
599 }
600
601
602 /***********************************************************************
603  *           MulDiv32   (KERNEL32.391)
604  */
605 INT32 MulDiv32( INT32 foo, INT32 bar, INT32 baz )
606 {
607 #ifdef __GNUC__
608     long long ret;
609     if (!baz) return -1;
610     ret = ((long long)foo * bar) / baz;
611     if ((ret > 2147483647) || (ret < -2147483647)) return -1;
612     return ret;
613 #else
614     if (!baz) return -1;
615     return (foo * bar) / baz;
616 #endif
617 }