Release 951105
[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 #include "xmalloc.h"
22
23 LPSTR GDI_Heap = NULL;
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
157 /***********************************************************************
158  *           GDI_Init
159  *
160  * GDI initialisation.
161  */
162 BOOL GDI_Init(void)
163 {
164     HPALETTE hpalette;
165
166 #ifndef WINELIB
167       /* Create GDI heap */
168
169     if (!(GDI_HeapSel = GlobalAlloc(GMEM_FIXED, GDI_HEAP_SIZE))) return FALSE;
170     GDI_Heap = GlobalLock( GDI_HeapSel );
171     LocalInit( GDI_HeapSel, 0, GDI_HEAP_SIZE-1 );
172 #endif
173     
174       /* Create default palette */
175
176     if (!(hpalette = COLOR_Init())) return FALSE;
177     StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( hpalette );
178
179       /* Create default bitmap */
180
181     if (!BITMAP_Init()) return FALSE;
182
183       /* Initialise brush dithering */
184
185     if (!BRUSH_Init()) return FALSE;
186
187       /* Initialise fonts */
188
189     if (!FONT_Init()) return FALSE;
190
191     return TRUE;
192 }
193
194
195 /***********************************************************************
196  *           GDI_AppendToPenBrushList
197  */
198 BOOL GDI_AppendToPenBrushList(HANDLE hNewObj)
199 {
200         HANDLE          *lphObj;
201         int             i = 1;
202         if (hNewObj == 0) return FALSE;
203         if (lpPenBrushList == NULL) {
204                 lpPenBrushList = xmalloc(MAX_OBJ * sizeof(HANDLE));
205                 lpPenBrushList[0] = 0;
206                 dprintf_gdi(stddeb,"GDI_AppendToPenBrushList() lpPenBrushList allocated !\n");
207         }
208         for (lphObj = lpPenBrushList; i < MAX_OBJ; i++) {
209                 if (*lphObj == 0) {
210                         *lphObj = hNewObj;
211                         *(lphObj + 1) = 0;
212                         dprintf_gdi(stddeb,"GDI_AppendToPenBrushList("NPFMT") appended (count=%d)\n", hNewObj, i);
213                         return TRUE;
214                 }
215                 lphObj++;
216         }
217         return FALSE;
218 }
219
220
221 /***********************************************************************
222  *           GDI_AllocObject
223  */
224 HANDLE GDI_AllocObject( WORD size, WORD magic )
225 {
226     static DWORD count = 0;
227     GDIOBJHDR * obj;
228     HANDLE handle = GDI_HEAP_ALLOC( size );
229     if (!handle) return 0;
230     obj = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
231     obj->hNext   = 0;
232     obj->wMagic  = magic;
233     obj->dwCount = ++count;
234     if (magic == PEN_MAGIC || magic == BRUSH_MAGIC) {
235       GDI_AppendToPenBrushList(handle);
236     }
237     return handle;
238 }
239
240
241 /***********************************************************************
242  *           GDI_FreeObject
243  */
244 BOOL GDI_FreeObject( HANDLE handle )
245 {
246     GDIOBJHDR * object;
247
248       /* Can't free stock objects */
249     if ((DWORD)handle >= FIRST_STOCK_HANDLE &&
250         (DWORD)handle <= LAST_STOCK_HANDLE   ) return TRUE;
251     
252     object = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
253     if (!object) return FALSE;
254     object->wMagic = 0;  /* Mark it as invalid */
255
256       /* Free object */
257     
258     GDI_HEAP_FREE( handle );
259     return TRUE;
260 }
261
262 /***********************************************************************
263  *           GDI_GetObjPtr
264  *
265  * Return a pointer to the GDI object associated to the handle.
266  * Return NULL if the object has the wrong magic number.
267  */
268 GDIOBJHDR * GDI_GetObjPtr( HANDLE handle, WORD magic )
269 {
270     GDIOBJHDR * ptr = NULL;
271
272     if ((DWORD)handle >= FIRST_STOCK_HANDLE &&
273         (DWORD)handle <= LAST_STOCK_HANDLE   )
274       ptr = StockObjects[(DWORD)handle - FIRST_STOCK_HANDLE];
275     else 
276       ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
277     if (!ptr) return NULL;
278     if (ptr->wMagic != magic) return NULL;
279     return ptr;
280 }
281
282
283 /***********************************************************************
284  *           DeleteObject    (GDI.69)
285  */
286 BOOL DeleteObject( HANDLE obj )
287 {
288       /* Check if object is valid */
289
290     GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( obj );
291     if (!header) return FALSE;
292
293     dprintf_gdi(stddeb, "DeleteObject: "NPFMT"\n", obj );
294
295       /* Delete object */
296
297     switch(header->wMagic)
298     {
299       case PEN_MAGIC:     return GDI_FreeObject( obj );
300       case BRUSH_MAGIC:   return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
301       case FONT_MAGIC:    return GDI_FreeObject( obj );
302       case PALETTE_MAGIC: return GDI_FreeObject( obj );
303       case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
304       case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
305     }
306     return FALSE;
307 }
308
309
310 /***********************************************************************
311  *           GetStockObject    (GDI.87)
312  */
313 HANDLE GetStockObject( int obj )
314 {
315     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
316     if (!StockObjects[obj]) return 0;
317     dprintf_gdi(stddeb, "GetStockObject: returning %ld\n",
318                 (DWORD)FIRST_STOCK_HANDLE + obj );
319     return (HANDLE)((DWORD)FIRST_STOCK_HANDLE + obj);
320 }
321
322
323 /***********************************************************************
324  *           GetObject    (GDI.82)
325  */
326 int GetObject( HANDLE handle, int count, LPSTR buffer )
327 {
328     GDIOBJHDR * ptr = NULL;
329     dprintf_gdi(stddeb, "GetObject: "NPFMT" %d %p\n", handle, count, buffer );
330     if (!count) return 0;
331
332     if ((DWORD)handle >= FIRST_STOCK_HANDLE &&
333         (DWORD)handle <= LAST_STOCK_HANDLE   )
334       ptr = StockObjects[(DWORD)handle - FIRST_STOCK_HANDLE];
335     else
336       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: "NPFMT" "NPFMT"\n", hdc, handle );
365     if ((DWORD)handle >= FIRST_STOCK_HANDLE &&
366         (DWORD)handle <= LAST_STOCK_HANDLE   )
367       ptr = StockObjects[(DWORD)handle - FIRST_STOCK_HANDLE];
368     else 
369       ptr = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR( handle );
370     if (!ptr) return 0;
371     
372     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
373     if (!dc) 
374     {
375         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
376         if (!dc) return 0;
377     }
378     
379     switch(ptr->wMagic)
380     {
381       case PEN_MAGIC:
382           return PEN_SelectObject( dc, handle, (PENOBJ *)ptr );
383       case BRUSH_MAGIC:
384           return BRUSH_SelectObject( hdc, dc, handle, (BRUSHOBJ *)ptr );
385       case BITMAP_MAGIC:
386           return BITMAP_SelectObject( hdc, dc, handle, (BITMAPOBJ *)ptr );
387       case FONT_MAGIC:
388           return FONT_SelectObject( dc, handle, (FONTOBJ *)ptr );         
389       case REGION_MAGIC:
390           return (HANDLE)SelectClipRgn( hdc, handle );
391     }
392     return 0;
393 }
394
395
396 /***********************************************************************
397  *           UnrealizeObject    (GDI.150)
398  */
399 BOOL UnrealizeObject( HANDLE handle )
400 {
401     dprintf_gdi(stdnimp, "UnrealizeObject: "NPFMT"\n", handle );
402     return TRUE;
403 }
404
405
406 /***********************************************************************
407  *           EnumObjects    (GDI.71)
408  */
409 int EnumObjects(HDC hDC, int nObjType, FARPROC lpEnumFunc, LPSTR lpData)
410 {
411   /*    HANDLE          handle;
412    DC                   *dc;*/
413   HANDLE        *lphObj;
414   GDIOBJHDR     *header;
415   WORD          wMagic;
416   LPSTR         lpLog;          /* Point to a LOGBRUSH or LOGPEN struct */
417   HANDLE        hLog;
418   int           nRet = 0;
419   
420   if (lpEnumFunc == NULL) {
421     fprintf(stderr,"EnumObjects // Bad EnumProc callback address !\n");
422     return 0;
423   }
424   switch (nObjType) {
425    case OBJ_PEN:
426     wMagic = PEN_MAGIC;
427     dprintf_gdi(stddeb,"EnumObjects("NPFMT", OBJ_PEN, %08lx, %p);\n",
428                 hDC, (LONG)lpEnumFunc, lpData);
429     hLog = GDI_HEAP_ALLOC( sizeof(LOGPEN) );
430     lpLog = (LPSTR) GDI_HEAP_LIN_ADDR(hLog);
431     if (lpLog == NULL) {
432       fprintf(stderr,"EnumObjects // Unable to alloc LOGPEN struct !\n");
433       return 0;
434     }
435     break;
436    case OBJ_BRUSH:
437     wMagic = BRUSH_MAGIC;
438     dprintf_gdi(stddeb,"EnumObjects("NPFMT", OBJ_BRUSH, %08lx, %p);\n",
439                 hDC, (LONG)lpEnumFunc, lpData);
440     hLog = GDI_HEAP_ALLOC( sizeof(LOGBRUSH) );
441     lpLog = (LPSTR) GDI_HEAP_LIN_ADDR(hLog);
442     if (lpLog == NULL) {
443       fprintf(stderr,"EnumObjects // Unable to alloc LOGBRUSH struct !\n");
444       return 0;
445     }
446     break;
447    default:
448     fprintf(stderr,"EnumObjects("NPFMT", %04X, %08lx, %p); // Unknown OBJ type !\n", 
449             hDC, nObjType, (LONG)lpEnumFunc, lpData);
450     return 0;
451   }
452 #ifdef notdef  /* FIXME: stock object ptr won't work in callback */
453   dprintf_gdi(stddeb,"EnumObjects // Stock Objects first !\n");
454   for (i = 0; i < NB_STOCK_OBJECTS; i++) {
455     header = StockObjects[i];
456     if (header->wMagic == wMagic) {
457       PEN_GetObject( (PENOBJ *)header, sizeof(LOGPEN), lpLog);
458       BRUSH_GetObject( (BRUSHOBJ *)header, sizeof(LOGBRUSH),lpLog);
459       dprintf_gdi(stddeb,"EnumObjects // StockObj lpLog=%p lpData=%p\n", lpLog, lpData);
460       if (header->wMagic == BRUSH_MAGIC) {
461         dprintf_gdi(stddeb,"EnumObjects // StockBrush lbStyle=%04X\n", ((LPLOGBRUSH)lpLog)->lbStyle);
462         dprintf_gdi(stddeb,"EnumObjects // StockBrush lbColor=%08lX\n", ((LPLOGBRUSH)lpLog)->lbColor);
463         dprintf_gdi(stddeb,"EnumObjects // StockBrush lbHatch=%04X\n", ((LPLOGBRUSH)lpLog)->lbHatch);
464       }
465       if (header->wMagic == PEN_MAGIC) {
466         dprintf_gdi(stddeb,"EnumObjects // StockPen lopnStyle=%04X\n", ((LPLOGPEN)lpLog)->lopnStyle);
467         dprintf_gdi(stddeb,"EnumObjects // StockPen lopnWidth=%d\n", ((LPLOGPEN)lpLog)->lopnWidth.x);
468         dprintf_gdi(stddeb,"EnumObjects // StockPen lopnColor=%08lX\n", ((LPLOGPEN)lpLog)->lopnColor);
469       }
470       nRet = CallEnumObjectsProc( lpEnumFunc,
471                                  GDI_HEAP_SEG_ADDR(hLog),
472                                  (int)lpData );
473       dprintf_gdi(stddeb,"EnumObjects // after Callback!\n");
474       if (nRet == 0) {
475         GDI_HEAP_FREE(hLog);
476         dprintf_gdi(stddeb,"EnumObjects // EnumEnd requested by application !\n");
477         return 0;
478       }
479     }
480   }
481   dprintf_gdi(stddeb,"EnumObjects // Now DC owned objects %p !\n", header);
482 #endif  /* notdef */
483   
484   if (lpPenBrushList == NULL) return 0;
485   for (lphObj = lpPenBrushList; *lphObj != 0; ) {
486     dprintf_gdi(stddeb,"EnumObjects // *lphObj="NPFMT"\n", *lphObj);
487     header = (GDIOBJHDR *) GDI_HEAP_LIN_ADDR(*lphObj++);
488     if (header->wMagic == wMagic) {
489       dprintf_gdi(stddeb,"EnumObjects // DC_Obj lpLog=%p lpData=%p\n", lpLog, lpData);
490       if (header->wMagic == BRUSH_MAGIC) {
491         BRUSH_GetObject( (BRUSHOBJ *)header, sizeof(LOGBRUSH), lpLog);
492         dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbStyle=%04X\n", ((LPLOGBRUSH)lpLog)->lbStyle);
493         dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbColor=%08lX\n", ((LPLOGBRUSH)lpLog)->lbColor);
494         dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbHatch=%04lX\n", (LONG)((LPLOGBRUSH)lpLog)->lbHatch);
495       }
496       if (header->wMagic == PEN_MAGIC) {
497         PEN_GetObject( (PENOBJ *)header, sizeof(LOGPEN), lpLog);
498         dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnStyle=%04X\n", ((LPLOGPEN)lpLog)->lopnStyle);
499         dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnWidth=%ld\n", (LONG)((LPLOGPEN)lpLog)->lopnWidth.x);
500         dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnColor=%08lX\n", ((LPLOGPEN)lpLog)->lopnColor);
501       }
502       nRet = CallEnumObjectsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
503                                  (LONG)lpData);
504       if (nRet == 0)
505         break;
506     }
507   }
508   GDI_HEAP_FREE(hLog);
509   dprintf_gdi(stddeb,"EnumObjects // End of enumeration !\n");
510   return nRet;
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         if (object)
522                 return TRUE;
523         else
524                 return FALSE;
525 }