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