Release 950901
[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 "palette.h"
15 #include "pen.h"
16 #include "region.h"
17 #include "callback.h"
18 #include "stddebug.h"
19 /* #define DEBUG_GDI */
20 #include "debug.h"
21
22 LPSTR GDI_Heap = NULL;
23 WORD GDI_HeapSel = 0;
24
25 /* Object types for EnumObjects() */
26 #define OBJ_PEN             1
27 #define OBJ_BRUSH           2
28
29 #define MAX_OBJ                         1024
30 HANDLE *lpPenBrushList = NULL;
31
32
33 /***********************************************************************
34  *          GDI stock objects 
35  */
36
37 static BRUSHOBJ WhiteBrush =
38 {
39     { 0, BRUSH_MAGIC, 1, 0 },          /* header */
40     { BS_SOLID, RGB(255,255,255), 0 }  /* logbrush */
41 };
42
43 static BRUSHOBJ LtGrayBrush =
44 {
45     { 0, BRUSH_MAGIC, 1, 0 },          /* header */
46     { BS_SOLID, RGB(192,192,192), 0 }  /* logbrush */
47 };
48
49 static BRUSHOBJ GrayBrush =
50 {
51     { 0, BRUSH_MAGIC, 1, 0 },          /* header */
52     { BS_SOLID, RGB(128,128,128), 0 }  /* logbrush */
53 };
54
55 static BRUSHOBJ DkGrayBrush =
56 {
57     { 0, BRUSH_MAGIC, 1, 0 },       /* header */
58     { BS_SOLID, RGB(64,64,64), 0 }  /* logbrush */
59 };
60
61 static BRUSHOBJ BlackBrush =
62 {
63     { 0, BRUSH_MAGIC, 1, 0 },    /* header */
64     { BS_SOLID, RGB(0,0,0), 0 }  /* logbrush */
65 };
66
67 static BRUSHOBJ NullBrush =
68 {
69     { 0, BRUSH_MAGIC, 1, 0 },  /* header */
70     { BS_NULL, 0, 0 }          /* logbrush */
71 };
72
73 static PENOBJ WhitePen =
74 {
75     { 0, PEN_MAGIC, 1, 0 },                  /* header */
76     { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
77 };
78
79 static PENOBJ BlackPen =
80 {
81     { 0, PEN_MAGIC, 1, 0 },            /* header */
82     { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
83 };
84
85 static PENOBJ NullPen =
86 {
87     { 0, PEN_MAGIC, 1, 0 },   /* header */
88     { PS_NULL, { 1, 0 }, 0 }  /* logpen */
89 };
90
91 static FONTOBJ OEMFixedFont =
92 {
93     { 0, FONT_MAGIC, 1, 0 },   /* header */
94     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
95       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
96 };
97
98 static FONTOBJ AnsiFixedFont =
99 {
100     { 0, FONT_MAGIC, 1, 0 },   /* header */
101     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
102       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
103 };
104
105 static FONTOBJ AnsiVarFont =
106 {
107     { 0, FONT_MAGIC, 1, 0 },   /* header */
108     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
109       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
110 };
111
112 static FONTOBJ SystemFont =
113 {
114     { 0, FONT_MAGIC, 1, 0 },   /* header */
115     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
116       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
117 };
118
119 static FONTOBJ DeviceDefaultFont =
120 {
121     { 0, FONT_MAGIC, 1, 0 },   /* header */
122     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
123       0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
124 };
125
126 static FONTOBJ SystemFixedFont =
127 {
128     { 0, FONT_MAGIC, 1, 0 },   /* header */
129     { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
130       0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
131 };
132
133
134 static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
135 {
136     (GDIOBJHDR *) &WhiteBrush,
137     (GDIOBJHDR *) &LtGrayBrush,
138     (GDIOBJHDR *) &GrayBrush,
139     (GDIOBJHDR *) &DkGrayBrush,
140     (GDIOBJHDR *) &BlackBrush,
141     (GDIOBJHDR *) &NullBrush,
142     (GDIOBJHDR *) &WhitePen,
143     (GDIOBJHDR *) &BlackPen,
144     (GDIOBJHDR *) &NullPen,
145     NULL,
146     (GDIOBJHDR *) &OEMFixedFont,
147     (GDIOBJHDR *) &AnsiFixedFont,
148     (GDIOBJHDR *) &AnsiVarFont,
149     (GDIOBJHDR *) &SystemFont,
150     (GDIOBJHDR *) &DeviceDefaultFont,
151     NULL,            /* DEFAULT_PALETTE created by COLOR_Init */
152     (GDIOBJHDR *) &SystemFixedFont
153 };
154
155
156 /***********************************************************************
157  *           GDI_Init
158  *
159  * GDI initialisation.
160  */
161 BOOL GDI_Init(void)
162 {
163     HPALETTE hpalette;
164
165 #ifndef WINELIB
166       /* Create GDI heap */
167
168     if (!(GDI_HeapSel = GlobalAlloc(GMEM_FIXED, GDI_HEAP_SIZE))) return FALSE;
169     GDI_Heap = GlobalLock( GDI_HeapSel );
170     LocalInit( GDI_HeapSel, 0, GDI_HEAP_SIZE-1 );
171 #endif
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       /* Initialise brush dithering */
183
184     if (!BRUSH_Init()) return FALSE;
185
186       /* Initialise fonts */
187
188     if (!FONT_Init()) return FALSE;
189
190     return TRUE;
191 }
192
193
194 /***********************************************************************
195  *           GDI_AppendToPenBrushList
196  */
197 BOOL GDI_AppendToPenBrushList(HANDLE hNewObj)
198 {
199         HANDLE          *lphObj;
200         int             i = 1;
201         if (hNewObj == 0) return FALSE;
202         if (lpPenBrushList == NULL) {
203                 lpPenBrushList = malloc(MAX_OBJ * sizeof(HANDLE));
204                 lpPenBrushList[0] = 0;
205                 dprintf_gdi(stddeb,"GDI_AppendToPenBrushList() lpPenBrushList allocated !\n");
206         }
207         for (lphObj = lpPenBrushList; i < MAX_OBJ; i++) {
208                 if (*lphObj == 0) {
209                         *lphObj = hNewObj;
210                         *(lphObj + 1) = 0;
211                         dprintf_gdi(stddeb,"GDI_AppendToPenBrushList(%04X) appended (count=%d)\n", hNewObj, i);
212                         return TRUE;
213                 }
214                 lphObj++;
215         }
216         return FALSE;
217 }
218
219
220 /***********************************************************************
221  *           GDI_AllocObject
222  */
223 HANDLE GDI_AllocObject( WORD size, WORD magic )
224 {
225     static DWORD count = 0;
226     GDIOBJHDR * obj;
227     HANDLE handle = GDI_HEAP_ALLOC( size );
228     if (!handle) return 0;
229     obj = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
230     obj->hNext   = 0;
231     obj->wMagic  = magic;
232     obj->dwCount = ++count;
233     if (magic == PEN_MAGIC || magic == BRUSH_MAGIC) {
234       GDI_AppendToPenBrushList(handle);
235     }
236     return handle;
237 }
238
239
240 /***********************************************************************
241  *           GDI_FreeObject
242  */
243 BOOL GDI_FreeObject( HANDLE handle )
244 {
245     GDIOBJHDR * object;
246
247       /* Can't free stock objects */
248     if (handle >= FIRST_STOCK_HANDLE) return TRUE;
249     
250     object = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
251     if (!object) return FALSE;
252     object->wMagic = 0;  /* Mark it as invalid */
253
254       /* Free object */
255     
256     GDI_HEAP_FREE( handle );
257     return TRUE;
258 }
259
260 /***********************************************************************
261  *           GDI_GetObjPtr
262  *
263  * Return a pointer to the GDI object associated to the handle.
264  * Return NULL if the object has the wrong magic number.
265  */
266 GDIOBJHDR * GDI_GetObjPtr( HANDLE handle, WORD magic )
267 {
268     GDIOBJHDR * ptr = NULL;
269
270     if (handle >= FIRST_STOCK_HANDLE)
271     {
272         if (handle < FIRST_STOCK_HANDLE + NB_STOCK_OBJECTS)
273             ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
274     }
275     else ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
276     if (!ptr) return NULL;
277     if (ptr->wMagic != magic) return NULL;
278     return ptr;
279 }
280
281
282 /***********************************************************************
283  *           DeleteObject    (GDI.69)
284  */
285 BOOL DeleteObject( HANDLE obj )
286 {
287       /* Check if object is valid */
288
289     GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( obj );
290     if (!header) return FALSE;
291
292     dprintf_gdi(stddeb, "DeleteObject: %d\n", obj );
293
294       /* Delete object */
295
296     switch(header->wMagic)
297     {
298       case PEN_MAGIC:     return GDI_FreeObject( obj );
299       case BRUSH_MAGIC:   return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
300       case FONT_MAGIC:    return GDI_FreeObject( obj );
301       case PALETTE_MAGIC: return GDI_FreeObject( obj );
302       case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
303       case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
304     }
305     return FALSE;
306 }
307
308
309 /***********************************************************************
310  *           GetStockObject    (GDI.87)
311  */
312 HANDLE GetStockObject( int obj )
313 {
314     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
315     if (!StockObjects[obj]) return 0;
316     dprintf_gdi(stddeb, "GetStockObject: returning %04x\n", 
317                 FIRST_STOCK_HANDLE + obj );
318     return FIRST_STOCK_HANDLE + obj;
319 }
320
321
322 /***********************************************************************
323  *           GetObject    (GDI.82)
324  */
325 int GetObject( HANDLE handle, int count, LPSTR buffer )
326 {
327     GDIOBJHDR * ptr = NULL;
328     dprintf_gdi(stddeb, "GetObject: %04x %d %p\n", handle, count, buffer );
329     if (!count) return 0;
330
331     if (handle >= FIRST_STOCK_HANDLE)
332     {
333         if (handle < FIRST_STOCK_HANDLE + NB_STOCK_OBJECTS)
334             ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
335     }
336     else ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
337     if (!ptr) return 0;
338     
339     switch(ptr->wMagic)
340     {
341       case PEN_MAGIC:
342           return PEN_GetObject( (PENOBJ *)ptr, count, buffer );
343       case BRUSH_MAGIC: 
344           return BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
345       case BITMAP_MAGIC: 
346           return BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
347       case FONT_MAGIC:
348           return FONT_GetObject( (FONTOBJ *)ptr, count, buffer );
349       case PALETTE_MAGIC:
350           return PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
351     }
352     return 0;
353 }
354
355
356 /***********************************************************************
357  *           SelectObject    (GDI.45)
358  */
359 HANDLE SelectObject( HDC hdc, HANDLE handle )
360 {
361     GDIOBJHDR * ptr = NULL;
362     DC * dc;
363     
364     dprintf_gdi(stddeb, "SelectObject: %d %04x\n", hdc, handle );
365     if (handle >= FIRST_STOCK_HANDLE)
366     {
367         if (handle < FIRST_STOCK_HANDLE + NB_STOCK_OBJECTS)
368             ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
369     }
370     else ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
371     if (!ptr) return 0;
372     
373     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
374     if (!dc) 
375     {
376         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
377         if (!dc) return 0;
378     }
379     
380     switch(ptr->wMagic)
381     {
382       case PEN_MAGIC:
383           return PEN_SelectObject( dc, handle, (PENOBJ *)ptr );
384       case BRUSH_MAGIC:
385           return BRUSH_SelectObject( hdc, dc, handle, (BRUSHOBJ *)ptr );
386       case BITMAP_MAGIC:
387           return BITMAP_SelectObject( hdc, dc, handle, (BITMAPOBJ *)ptr );
388       case FONT_MAGIC:
389           return FONT_SelectObject( dc, handle, (FONTOBJ *)ptr );         
390       case REGION_MAGIC:
391           return SelectClipRgn( hdc, handle );
392     }
393     return 0;
394 }
395
396
397 /***********************************************************************
398  *           UnrealizeObject    (GDI.150)
399  */
400 BOOL UnrealizeObject( HANDLE handle )
401 {
402     dprintf_gdi(stdnimp, "UnrealizeObject: %04x\n", handle );
403     return TRUE;
404 }
405
406
407 /***********************************************************************
408  *           EnumObjects    (GDI.71)
409  */
410 int EnumObjects(HDC hDC, int nObjType, FARPROC lpEnumFunc, LPSTR lpData)
411 {
412   /*    HANDLE          handle;
413    DC                   *dc;*/
414   HANDLE        *lphObj;
415   GDIOBJHDR     *header;
416   WORD          wMagic;
417   LPSTR         lpLog;          /* Point to a LOGBRUSH or LOGPEN struct */
418   HANDLE        hLog;
419   int           nRet = 0;
420   
421   if (lpEnumFunc == NULL) {
422     fprintf(stderr,"EnumObjects // Bad EnumProc callback address !\n");
423     return 0;
424   }
425   switch (nObjType) {
426    case OBJ_PEN:
427     wMagic = PEN_MAGIC;
428     dprintf_gdi(stddeb,"EnumObjects(%04X, OBJ_PEN, %08lx, %p);\n",
429                 hDC, (LONG)lpEnumFunc, lpData);
430     hLog = GDI_HEAP_ALLOC( sizeof(LOGPEN) );
431     lpLog = (LPSTR) GDI_HEAP_LIN_ADDR(hLog);
432     if (lpLog == NULL) {
433       fprintf(stderr,"EnumObjects // Unable to alloc LOGPEN struct !\n");
434       return 0;
435     }
436     break;
437    case OBJ_BRUSH:
438     wMagic = BRUSH_MAGIC;
439     dprintf_gdi(stddeb,"EnumObjects(%04X, OBJ_BRUSH, %08lx, %p);\n",
440                 hDC, (LONG)lpEnumFunc, lpData);
441     hLog = GDI_HEAP_ALLOC( sizeof(LOGBRUSH) );
442     lpLog = (LPSTR) GDI_HEAP_LIN_ADDR(hLog);
443     if (lpLog == NULL) {
444       fprintf(stderr,"EnumObjects // Unable to alloc LOGBRUSH struct !\n");
445       return 0;
446     }
447     break;
448    default:
449     fprintf(stderr,"EnumObjects(%04X, %04X, %08lx, %p); // Unknown OBJ type !\n", 
450             hDC, nObjType, (LONG)lpEnumFunc, lpData);
451     return 0;
452   }
453 #ifdef notdef  /* FIXME: stock object ptr won't work in callback */
454   dprintf_gdi(stddeb,"EnumObjects // Stock Objects first !\n");
455   for (i = 0; i < NB_STOCK_OBJECTS; i++) {
456     header = StockObjects[i];
457     if (header->wMagic == wMagic) {
458       PEN_GetObject( (PENOBJ *)header, sizeof(LOGPEN), lpLog);
459       BRUSH_GetObject( (BRUSHOBJ *)header, sizeof(LOGBRUSH),lpLog);
460       dprintf_gdi(stddeb,"EnumObjects // StockObj lpLog=%p lpData=%p\n", lpLog, lpData);
461       if (header->wMagic == BRUSH_MAGIC) {
462         dprintf_gdi(stddeb,"EnumObjects // StockBrush lbStyle=%04X\n", ((LPLOGBRUSH)lpLog)->lbStyle);
463         dprintf_gdi(stddeb,"EnumObjects // StockBrush lbColor=%08lX\n", ((LPLOGBRUSH)lpLog)->lbColor);
464         dprintf_gdi(stddeb,"EnumObjects // StockBrush lbHatch=%04X\n", ((LPLOGBRUSH)lpLog)->lbHatch);
465       }
466       if (header->wMagic == PEN_MAGIC) {
467         dprintf_gdi(stddeb,"EnumObjects // StockPen lopnStyle=%04X\n", ((LPLOGPEN)lpLog)->lopnStyle);
468         dprintf_gdi(stddeb,"EnumObjects // StockPen lopnWidth=%d\n", ((LPLOGPEN)lpLog)->lopnWidth.x);
469         dprintf_gdi(stddeb,"EnumObjects // StockPen lopnColor=%08lX\n", ((LPLOGPEN)lpLog)->lopnColor);
470       }
471       nRet = CallEnumObjectsProc( lpEnumFunc,
472                                  GDI_HEAP_SEG_ADDR(hLog),
473                                  (int)lpData );
474       dprintf_gdi(stddeb,"EnumObjects // after Callback!\n");
475       if (nRet == 0) {
476         GDI_HEAP_FREE(hLog);
477         dprintf_gdi(stddeb,"EnumObjects // EnumEnd requested by application !\n");
478         return 0;
479       }
480     }
481   }
482   dprintf_gdi(stddeb,"EnumObjects // Now DC owned objects %p !\n", header);
483 #endif  /* notdef */
484   
485   if (lpPenBrushList == NULL) return 0;
486   for (lphObj = lpPenBrushList; *lphObj != 0; ) {
487     dprintf_gdi(stddeb,"EnumObjects // *lphObj=%04X\n", *lphObj);
488     header = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR(*lphObj++);
489     if (header->wMagic == wMagic) {
490       dprintf_gdi(stddeb,"EnumObjects // DC_Obj lpLog=%p lpData=%p\n", lpLog, lpData);
491       if (header->wMagic == BRUSH_MAGIC) {
492         BRUSH_GetObject( (BRUSHOBJ *)header, sizeof(LOGBRUSH), lpLog);
493         dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbStyle=%04X\n", ((LPLOGBRUSH)lpLog)->lbStyle);
494         dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbColor=%08lX\n", ((LPLOGBRUSH)lpLog)->lbColor);
495         dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbHatch=%04X\n", ((LPLOGBRUSH)lpLog)->lbHatch);
496       }
497       if (header->wMagic == PEN_MAGIC) {
498         PEN_GetObject( (PENOBJ *)header, sizeof(LOGPEN), lpLog);
499         dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnStyle=%04X\n", ((LPLOGPEN)lpLog)->lopnStyle);
500         dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnWidth=%d\n", ((LPLOGPEN)lpLog)->lopnWidth.x);
501         dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnColor=%08lX\n", ((LPLOGPEN)lpLog)->lopnColor);
502       }
503       nRet = CallEnumObjectsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
504                                  (LONG)lpData);
505       if (nRet == 0)
506         break;
507     }
508   }
509   GDI_HEAP_FREE(hLog);
510   dprintf_gdi(stddeb,"EnumObjects // End of enumeration !\n");
511   return nRet;
512 }
513
514 /***********************************************************************
515  *              IsGDIObject(GDI.462)
516  */
517 BOOL IsGDIObject(HANDLE handle)
518 {
519         GDIOBJHDR *object;
520
521         object = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
522         if (object)
523                 return TRUE;
524         else
525                 return FALSE;
526 }