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