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