widl: Don't make proxy vtbl const in interpreted mode.
[wine.git] / dlls / gdi32 / gdiobj.c
blob083a5045692ed7f0cb9f7c76d40a9e250b8c7b0d
1 /*
2 * GDI functions
4 * Copyright 1993 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winreg.h"
32 #include "winnls.h"
33 #include "winerror.h"
34 #include "winternl.h"
36 #include "gdi_private.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
41 #define FIRST_GDI_HANDLE 32
42 #define MAX_GDI_HANDLES 16384
44 struct hdc_list
46 HDC hdc;
47 struct hdc_list *next;
50 struct gdi_handle_entry
52 void *obj; /* pointer to the object-specific data */
53 const struct gdi_obj_funcs *funcs; /* type-specific functions */
54 struct hdc_list *hdcs; /* list of HDCs interested in this object */
55 WORD generation; /* generation count for reusing handle values */
56 WORD type; /* object type (one of the OBJ_* constants) */
57 WORD selcount; /* number of times the object is selected in a DC */
58 WORD system : 1; /* system object flag */
59 WORD deleted : 1; /* whether DeleteObject has been called on this object */
62 static struct gdi_handle_entry gdi_handles[MAX_GDI_HANDLES];
63 static struct gdi_handle_entry *next_free;
64 static struct gdi_handle_entry *next_unused = gdi_handles;
65 static LONG debug_count;
66 HMODULE gdi32_module = 0;
68 static inline HGDIOBJ entry_to_handle( struct gdi_handle_entry *entry )
70 unsigned int idx = entry - gdi_handles + FIRST_GDI_HANDLE;
71 return LongToHandle( idx | (entry->generation << 16) );
74 static inline struct gdi_handle_entry *handle_entry( HGDIOBJ handle )
76 unsigned int idx = LOWORD(handle) - FIRST_GDI_HANDLE;
78 if (idx < MAX_GDI_HANDLES && gdi_handles[idx].type)
80 if (!HIWORD( handle ) || HIWORD( handle ) == gdi_handles[idx].generation)
81 return &gdi_handles[idx];
83 if (handle) WARN( "invalid handle %p\n", handle );
84 return NULL;
87 /***********************************************************************
88 * GDI stock objects
91 static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
92 static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
93 static const LOGBRUSH NullBrush = { BS_NULL, 0, 0 };
95 static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
96 static const LOGBRUSH GrayBrush = { BS_SOLID, RGB(128,128,128), 0 };
97 static const LOGBRUSH DkGrayBrush = { BS_SOLID, RGB(64,64,64), 0 };
99 static const LOGPEN WhitePen = { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
100 static const LOGPEN BlackPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
101 static const LOGPEN NullPen = { PS_NULL, { 0, 0 }, 0 };
103 static const LOGBRUSH DCBrush = { BS_SOLID, RGB(255,255,255), 0 };
104 static const LOGPEN DCPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
106 /* reserve one extra entry for the stock default bitmap */
107 /* this is what Windows does too */
108 #define NB_STOCK_OBJECTS (STOCK_LAST+2)
110 static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
111 static HGDIOBJ scaled_stock_objects[NB_STOCK_OBJECTS];
113 static CRITICAL_SECTION gdi_section;
114 static CRITICAL_SECTION_DEBUG critsect_debug =
116 0, 0, &gdi_section,
117 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
118 0, 0, { (DWORD_PTR)(__FILE__ ": gdi_section") }
120 static CRITICAL_SECTION gdi_section = { &critsect_debug, -1, 0, 0, 0, 0 };
123 /****************************************************************************
125 * language-independent stock fonts
129 static const LOGFONTW OEMFixedFont =
130 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
131 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
133 static const LOGFONTW AnsiFixedFont =
134 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
135 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
136 {'C','o','u','r','i','e','r','\0'} };
138 static const LOGFONTW AnsiVarFont =
139 { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
140 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
141 {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'} };
143 /******************************************************************************
145 * language-dependent stock fonts
147 * 'ANSI' charset and 'DEFAULT' charset is not same.
148 * The chars in CP_ACP should be drawn with 'DEFAULT' charset.
149 * 'ANSI' charset seems to be identical with ISO-8859-1.
150 * 'DEFAULT' charset is a language-dependent charset.
152 * 'System' font seems to be an alias for language-dependent font.
156 * language-dependent stock fonts for all known charsets
157 * please see TranslateCharsetInfo (dlls/gdi/font.c) and
158 * CharsetBindingInfo (dlls/x11drv/xfont.c),
159 * and modify entries for your language if needed.
161 struct DefaultFontInfo
163 UINT charset;
164 LOGFONTW SystemFont;
165 LOGFONTW DeviceDefaultFont;
166 LOGFONTW SystemFixedFont;
167 LOGFONTW DefaultGuiFont;
170 static const struct DefaultFontInfo default_fonts[] =
172 { ANSI_CHARSET,
173 { /* System */
174 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
175 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
176 {'S','y','s','t','e','m','\0'}
178 { /* Device Default */
179 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
180 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
181 {'S','y','s','t','e','m','\0'}
183 { /* System Fixed */
184 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
185 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
186 {'C','o','u','r','i','e','r','\0'}
188 { /* DefaultGuiFont */
189 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
190 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
191 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
194 { EASTEUROPE_CHARSET,
195 { /* System */
196 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
197 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
198 {'S','y','s','t','e','m','\0'}
200 { /* Device Default */
201 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
202 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
203 {'S','y','s','t','e','m','\0'}
205 { /* System Fixed */
206 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
207 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
208 {'C','o','u','r','i','e','r','\0'}
210 { /* DefaultGuiFont */
211 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
212 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
213 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
216 { RUSSIAN_CHARSET,
217 { /* System */
218 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
219 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
220 {'S','y','s','t','e','m','\0'}
222 { /* Device Default */
223 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
224 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
225 {'S','y','s','t','e','m','\0'}
227 { /* System Fixed */
228 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
229 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
230 {'C','o','u','r','i','e','r','\0'}
232 { /* DefaultGuiFont */
233 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
234 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
235 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
238 { GREEK_CHARSET,
239 { /* System */
240 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GREEK_CHARSET,
241 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
242 {'S','y','s','t','e','m','\0'}
244 { /* Device Default */
245 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GREEK_CHARSET,
246 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
247 {'S','y','s','t','e','m','\0'}
249 { /* System Fixed */
250 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
251 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
252 {'C','o','u','r','i','e','r','\0'}
254 { /* DefaultGuiFont */
255 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
256 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
257 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
260 { TURKISH_CHARSET,
261 { /* System */
262 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, TURKISH_CHARSET,
263 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
264 {'S','y','s','t','e','m','\0'}
266 { /* Device Default */
267 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, TURKISH_CHARSET,
268 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
269 {'S','y','s','t','e','m','\0'}
271 { /* System Fixed */
272 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
273 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
274 {'C','o','u','r','i','e','r','\0'}
276 { /* DefaultGuiFont */
277 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
278 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
279 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
282 { HEBREW_CHARSET,
283 { /* System */
284 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, HEBREW_CHARSET,
285 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
286 {'S','y','s','t','e','m','\0'}
288 { /* Device Default */
289 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, HEBREW_CHARSET,
290 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
291 {'S','y','s','t','e','m','\0'}
293 { /* System Fixed */
294 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
295 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
296 {'C','o','u','r','i','e','r','\0'}
298 { /* DefaultGuiFont */
299 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
300 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
301 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
304 { ARABIC_CHARSET,
305 { /* System */
306 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ARABIC_CHARSET,
307 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
308 {'S','y','s','t','e','m','\0'}
310 { /* Device Default */
311 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ARABIC_CHARSET,
312 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
313 {'S','y','s','t','e','m','\0'}
315 { /* System Fixed */
316 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
317 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
318 {'C','o','u','r','i','e','r','\0'}
320 { /* DefaultGuiFont */
321 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
322 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
323 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
326 { BALTIC_CHARSET,
327 { /* System */
328 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, BALTIC_CHARSET,
329 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
330 {'S','y','s','t','e','m','\0'}
332 { /* Device Default */
333 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, BALTIC_CHARSET,
334 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
335 {'S','y','s','t','e','m','\0'}
337 { /* System Fixed */
338 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
339 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
340 {'C','o','u','r','i','e','r','\0'}
342 { /* DefaultGuiFont */
343 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
344 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
345 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
348 { THAI_CHARSET,
349 { /* System */
350 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, THAI_CHARSET,
351 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
352 {'S','y','s','t','e','m','\0'}
354 { /* Device Default */
355 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, THAI_CHARSET,
356 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
357 {'S','y','s','t','e','m','\0'}
359 { /* System Fixed */
360 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
361 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
362 {'C','o','u','r','i','e','r','\0'}
364 { /* DefaultGuiFont */
365 -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
366 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
367 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
370 { SHIFTJIS_CHARSET,
371 { /* System */
372 18, 8, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
373 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
374 {'S','y','s','t','e','m','\0'}
376 { /* Device Default */
377 18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
378 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
379 {'S','y','s','t','e','m','\0'}
381 { /* System Fixed */
382 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
383 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
384 {'C','o','u','r','i','e','r','\0'}
386 { /* DefaultGuiFont */
387 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
388 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
389 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
392 { GB2312_CHARSET,
393 { /* System */
394 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET,
395 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
396 {'S','y','s','t','e','m','\0'}
398 { /* Device Default */
399 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, GB2312_CHARSET,
400 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
401 {'S','y','s','t','e','m','\0'}
403 { /* System Fixed */
404 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
405 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
406 {'C','o','u','r','i','e','r','\0'}
408 { /* DefaultGuiFont */
409 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
410 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
411 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
414 { HANGEUL_CHARSET,
415 { /* System */
416 16, 8, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
417 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
418 {'S','y','s','t','e','m','\0'}
420 { /* Device Default */
421 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
422 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
423 {'S','y','s','t','e','m','\0'}
425 { /* System Fixed */
426 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
427 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
428 {'C','o','u','r','i','e','r','\0'}
430 { /* DefaultGuiFont */
431 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
432 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
433 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
436 { CHINESEBIG5_CHARSET,
437 { /* System */
438 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
439 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
440 {'S','y','s','t','e','m','\0'}
442 { /* Device Default */
443 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
444 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
445 {'S','y','s','t','e','m','\0'}
447 { /* System Fixed */
448 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
449 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
450 {'C','o','u','r','i','e','r','\0'}
452 { /* DefaultGuiFont */
453 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
454 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
455 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
458 { JOHAB_CHARSET,
459 { /* System */
460 16, 7, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, JOHAB_CHARSET,
461 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
462 {'S','y','s','t','e','m','\0'}
464 { /* Device Default */
465 16, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, JOHAB_CHARSET,
466 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
467 {'S','y','s','t','e','m','\0'}
469 { /* System Fixed */
470 16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
471 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
472 {'C','o','u','r','i','e','r','\0'}
474 { /* DefaultGuiFont */
475 -12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
476 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
477 {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
483 /*************************************************************************
484 * __wine_make_gdi_object_system (GDI32.@)
486 * USER has to tell GDI that its system brushes and pens are non-deletable.
487 * For a description of the GDI object magics and their flags,
488 * see "Undocumented Windows" (wrong about the OBJECT_NOSYSTEM flag, though).
490 void CDECL __wine_make_gdi_object_system( HGDIOBJ handle, BOOL set)
492 struct gdi_handle_entry *entry;
494 EnterCriticalSection( &gdi_section );
495 if ((entry = handle_entry( handle ))) entry->system = !!set;
496 LeaveCriticalSection( &gdi_section );
499 /******************************************************************************
500 * get_default_fonts
502 static const struct DefaultFontInfo* get_default_fonts(UINT charset)
504 unsigned int n;
506 for(n = 0; n < ARRAY_SIZE( default_fonts ); n++)
508 if ( default_fonts[n].charset == charset )
509 return &default_fonts[n];
512 FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
513 return &default_fonts[0];
517 /******************************************************************************
518 * get_default_charset (internal)
520 * get the language-dependent charset that can handle CP_ACP correctly.
522 static UINT get_default_charset( void )
524 CHARSETINFO csi;
525 UINT uACP;
527 uACP = GetACP();
528 csi.ciCharset = ANSI_CHARSET;
529 if ( !TranslateCharsetInfo( ULongToPtr(uACP), &csi, TCI_SRCCODEPAGE ) )
531 FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", uACP );
532 return ANSI_CHARSET;
535 return csi.ciCharset;
539 /***********************************************************************
540 * GDI_get_ref_count
542 * Retrieve the reference count of a GDI object.
543 * Note: the object must be locked otherwise the count is meaningless.
545 UINT GDI_get_ref_count( HGDIOBJ handle )
547 struct gdi_handle_entry *entry;
548 UINT ret = 0;
550 EnterCriticalSection( &gdi_section );
551 if ((entry = handle_entry( handle ))) ret = entry->selcount;
552 LeaveCriticalSection( &gdi_section );
553 return ret;
557 /***********************************************************************
558 * GDI_inc_ref_count
560 * Increment the reference count of a GDI object.
562 HGDIOBJ GDI_inc_ref_count( HGDIOBJ handle )
564 struct gdi_handle_entry *entry;
566 EnterCriticalSection( &gdi_section );
567 if ((entry = handle_entry( handle ))) entry->selcount++;
568 else handle = 0;
569 LeaveCriticalSection( &gdi_section );
570 return handle;
574 /***********************************************************************
575 * GDI_dec_ref_count
577 * Decrement the reference count of a GDI object.
579 BOOL GDI_dec_ref_count( HGDIOBJ handle )
581 struct gdi_handle_entry *entry;
583 EnterCriticalSection( &gdi_section );
584 if ((entry = handle_entry( handle )))
586 assert( entry->selcount );
587 if (!--entry->selcount && entry->deleted)
589 /* handle delayed DeleteObject*/
590 entry->deleted = 0;
591 LeaveCriticalSection( &gdi_section );
592 TRACE( "executing delayed DeleteObject for %p\n", handle );
593 DeleteObject( handle );
594 return TRUE;
597 LeaveCriticalSection( &gdi_section );
598 return entry != NULL;
601 static const WCHAR dpi_key_name[] = {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p','\0'};
602 static const WCHAR def_dpi_key_name[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
603 static const WCHAR dpi_value_name[] = {'L','o','g','P','i','x','e','l','s','\0'};
605 /******************************************************************************
606 * get_reg_dword
608 * Read a DWORD value from the registry
610 static BOOL get_reg_dword(HKEY base, const WCHAR *key_name, const WCHAR *value_name, DWORD *value)
612 HKEY key;
613 DWORD type, data, size = sizeof(data);
614 BOOL ret = FALSE;
616 if (RegOpenKeyW(base, key_name, &key) == ERROR_SUCCESS)
618 if (RegQueryValueExW(key, value_name, NULL, &type, (void *)&data, &size) == ERROR_SUCCESS &&
619 type == REG_DWORD)
621 *value = data;
622 ret = TRUE;
624 RegCloseKey(key);
626 return ret;
629 /******************************************************************************
630 * get_dpi
632 * get the dpi from the registry
634 DWORD get_dpi(void)
636 DWORD dpi;
638 if (get_reg_dword(HKEY_CURRENT_USER, dpi_key_name, dpi_value_name, &dpi))
639 return dpi;
640 if (get_reg_dword(HKEY_CURRENT_CONFIG, def_dpi_key_name, dpi_value_name, &dpi))
641 return dpi;
642 return 0;
645 /******************************************************************************
646 * get_system_dpi
648 * Get the system DPI, based on the DPI awareness mode.
650 DWORD get_system_dpi(void)
652 static UINT (WINAPI *pGetDpiForSystem)(void);
654 if (!pGetDpiForSystem)
656 static const WCHAR user32W[] = {'u','s','e','r','3','2','.','d','l','l',0};
657 HMODULE user = GetModuleHandleW( user32W );
658 if (user) pGetDpiForSystem = (void *)GetProcAddress( user, "GetDpiForSystem" );
660 return pGetDpiForSystem ? pGetDpiForSystem() : 96;
663 static HFONT create_scaled_font( const LOGFONTW *deffont )
665 LOGFONTW lf;
666 static DWORD dpi;
668 if (!dpi)
670 dpi = get_dpi();
671 if (!dpi) dpi = 96;
674 lf = *deffont;
675 lf.lfHeight = MulDiv( lf.lfHeight, dpi, 96 );
676 return CreateFontIndirectW( &lf );
679 /***********************************************************************
680 * DllMain
682 * GDI initialization.
684 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
686 const struct DefaultFontInfo* deffonts;
687 int i;
689 if (reason != DLL_PROCESS_ATTACH) return TRUE;
691 gdi32_module = inst;
692 DisableThreadLibraryCalls( inst );
693 WineEngInit();
695 /* create stock objects */
696 stock_objects[WHITE_BRUSH] = CreateBrushIndirect( &WhiteBrush );
697 stock_objects[LTGRAY_BRUSH] = CreateBrushIndirect( &LtGrayBrush );
698 stock_objects[GRAY_BRUSH] = CreateBrushIndirect( &GrayBrush );
699 stock_objects[DKGRAY_BRUSH] = CreateBrushIndirect( &DkGrayBrush );
700 stock_objects[BLACK_BRUSH] = CreateBrushIndirect( &BlackBrush );
701 stock_objects[NULL_BRUSH] = CreateBrushIndirect( &NullBrush );
703 stock_objects[WHITE_PEN] = CreatePenIndirect( &WhitePen );
704 stock_objects[BLACK_PEN] = CreatePenIndirect( &BlackPen );
705 stock_objects[NULL_PEN] = CreatePenIndirect( &NullPen );
707 stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
708 stock_objects[DEFAULT_BITMAP] = CreateBitmap( 1, 1, 1, 1, NULL );
710 /* language-independent stock fonts */
711 stock_objects[OEM_FIXED_FONT] = CreateFontIndirectW( &OEMFixedFont );
712 stock_objects[ANSI_FIXED_FONT] = CreateFontIndirectW( &AnsiFixedFont );
713 stock_objects[ANSI_VAR_FONT] = CreateFontIndirectW( &AnsiVarFont );
715 /* language-dependent stock fonts */
716 deffonts = get_default_fonts(get_default_charset());
717 stock_objects[SYSTEM_FONT] = CreateFontIndirectW( &deffonts->SystemFont );
718 stock_objects[DEVICE_DEFAULT_FONT] = CreateFontIndirectW( &deffonts->DeviceDefaultFont );
719 stock_objects[SYSTEM_FIXED_FONT] = CreateFontIndirectW( &deffonts->SystemFixedFont );
720 stock_objects[DEFAULT_GUI_FONT] = CreateFontIndirectW( &deffonts->DefaultGuiFont );
722 scaled_stock_objects[OEM_FIXED_FONT] = create_scaled_font( &OEMFixedFont );
723 scaled_stock_objects[SYSTEM_FONT] = create_scaled_font( &deffonts->SystemFont );
724 scaled_stock_objects[SYSTEM_FIXED_FONT] = create_scaled_font( &deffonts->SystemFixedFont );
725 scaled_stock_objects[DEFAULT_GUI_FONT] = create_scaled_font( &deffonts->DefaultGuiFont );
727 stock_objects[DC_BRUSH] = CreateBrushIndirect( &DCBrush );
728 stock_objects[DC_PEN] = CreatePenIndirect( &DCPen );
730 /* clear the NOSYSTEM bit on all stock objects*/
731 for (i = 0; i < NB_STOCK_OBJECTS; i++)
733 if (stock_objects[i]) __wine_make_gdi_object_system( stock_objects[i], TRUE );
734 if (scaled_stock_objects[i]) __wine_make_gdi_object_system( scaled_stock_objects[i], TRUE );
736 return TRUE;
739 static const char *gdi_obj_type( unsigned type )
741 switch ( type )
743 case OBJ_PEN: return "OBJ_PEN";
744 case OBJ_BRUSH: return "OBJ_BRUSH";
745 case OBJ_DC: return "OBJ_DC";
746 case OBJ_METADC: return "OBJ_METADC";
747 case OBJ_PAL: return "OBJ_PAL";
748 case OBJ_FONT: return "OBJ_FONT";
749 case OBJ_BITMAP: return "OBJ_BITMAP";
750 case OBJ_REGION: return "OBJ_REGION";
751 case OBJ_METAFILE: return "OBJ_METAFILE";
752 case OBJ_MEMDC: return "OBJ_MEMDC";
753 case OBJ_EXTPEN: return "OBJ_EXTPEN";
754 case OBJ_ENHMETADC: return "OBJ_ENHMETADC";
755 case OBJ_ENHMETAFILE: return "OBJ_ENHMETAFILE";
756 case OBJ_COLORSPACE: return "OBJ_COLORSPACE";
757 default: return "UNKNOWN";
761 static void dump_gdi_objects( void )
763 struct gdi_handle_entry *entry;
765 TRACE( "%u objects:\n", MAX_GDI_HANDLES );
767 EnterCriticalSection( &gdi_section );
768 for (entry = gdi_handles; entry < next_unused; entry++)
770 if (!entry->type)
771 TRACE( "handle %p FREE\n", entry_to_handle( entry ));
772 else
773 TRACE( "handle %p obj %p type %s selcount %u deleted %u\n",
774 entry_to_handle( entry ), entry->obj, gdi_obj_type( entry->type ),
775 entry->selcount, entry->deleted );
777 LeaveCriticalSection( &gdi_section );
780 /***********************************************************************
781 * alloc_gdi_handle
783 * Allocate a GDI handle for an object, which must have been allocated on the process heap.
785 HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *funcs )
787 struct gdi_handle_entry *entry;
788 HGDIOBJ ret;
790 assert( type ); /* type 0 is reserved to mark free entries */
792 EnterCriticalSection( &gdi_section );
794 entry = next_free;
795 if (entry)
796 next_free = entry->obj;
797 else if (next_unused < gdi_handles + MAX_GDI_HANDLES)
798 entry = next_unused++;
799 else
801 LeaveCriticalSection( &gdi_section );
802 ERR( "out of GDI object handles, expect a crash\n" );
803 if (TRACE_ON(gdi)) dump_gdi_objects();
804 return 0;
806 entry->obj = obj;
807 entry->funcs = funcs;
808 entry->hdcs = NULL;
809 entry->type = type;
810 entry->selcount = 0;
811 entry->system = 0;
812 entry->deleted = 0;
813 if (++entry->generation == 0xffff) entry->generation = 1;
814 ret = entry_to_handle( entry );
815 LeaveCriticalSection( &gdi_section );
816 TRACE( "allocated %s %p %u/%u\n", gdi_obj_type(type), ret,
817 InterlockedIncrement( &debug_count ), MAX_GDI_HANDLES );
818 return ret;
822 /***********************************************************************
823 * free_gdi_handle
825 * Free a GDI handle and return a pointer to the object.
827 void *free_gdi_handle( HGDIOBJ handle )
829 void *object = NULL;
830 struct gdi_handle_entry *entry;
832 EnterCriticalSection( &gdi_section );
833 if ((entry = handle_entry( handle )))
835 TRACE( "freed %s %p %u/%u\n", gdi_obj_type( entry->type ), handle,
836 InterlockedDecrement( &debug_count ) + 1, MAX_GDI_HANDLES );
837 object = entry->obj;
838 entry->type = 0;
839 entry->obj = next_free;
840 next_free = entry;
842 LeaveCriticalSection( &gdi_section );
843 return object;
847 /***********************************************************************
848 * get_full_gdi_handle
850 * Return the full GDI handle from a possibly truncated value.
852 HGDIOBJ get_full_gdi_handle( HGDIOBJ handle )
854 struct gdi_handle_entry *entry;
856 if (!HIWORD( handle ))
858 EnterCriticalSection( &gdi_section );
859 if ((entry = handle_entry( handle ))) handle = entry_to_handle( entry );
860 LeaveCriticalSection( &gdi_section );
862 return handle;
865 /***********************************************************************
866 * get_any_obj_ptr
868 * Return a pointer to, and the type of, the GDI object
869 * associated with the handle.
870 * The object must be released with GDI_ReleaseObj.
872 void *get_any_obj_ptr( HGDIOBJ handle, WORD *type )
874 void *ptr = NULL;
875 struct gdi_handle_entry *entry;
877 EnterCriticalSection( &gdi_section );
879 if ((entry = handle_entry( handle )))
881 ptr = entry->obj;
882 *type = entry->type;
885 if (!ptr) LeaveCriticalSection( &gdi_section );
886 return ptr;
889 /***********************************************************************
890 * GDI_GetObjPtr
892 * Return a pointer to the GDI object associated with the handle.
893 * Return NULL if the object has the wrong type.
894 * The object must be released with GDI_ReleaseObj.
896 void *GDI_GetObjPtr( HGDIOBJ handle, WORD type )
898 WORD ret_type;
899 void *ptr = get_any_obj_ptr( handle, &ret_type );
900 if (ptr && ret_type != type)
902 GDI_ReleaseObj( handle );
903 ptr = NULL;
905 return ptr;
908 /***********************************************************************
909 * GDI_ReleaseObj
912 void GDI_ReleaseObj( HGDIOBJ handle )
914 LeaveCriticalSection( &gdi_section );
918 /***********************************************************************
919 * GDI_CheckNotLock
921 void GDI_CheckNotLock(void)
923 if (RtlIsCriticalSectionLockedByThread(&gdi_section))
925 ERR( "BUG: holding GDI lock\n" );
926 DebugBreak();
931 /***********************************************************************
932 * DeleteObject (GDI32.@)
934 * Delete a Gdi object.
936 * PARAMS
937 * obj [I] Gdi object to delete
939 * RETURNS
940 * Success: TRUE. If obj was not returned from GetStockObject(), any resources
941 * it consumed are released.
942 * Failure: FALSE, if obj is not a valid Gdi object, or is currently selected
943 * into a DC.
945 BOOL WINAPI DeleteObject( HGDIOBJ obj )
947 struct gdi_handle_entry *entry;
948 struct hdc_list *hdcs_head;
949 const struct gdi_obj_funcs *funcs = NULL;
951 EnterCriticalSection( &gdi_section );
952 if (!(entry = handle_entry( obj )))
954 LeaveCriticalSection( &gdi_section );
955 return FALSE;
958 if (entry->system)
960 TRACE("Preserving system object %p\n", obj);
961 LeaveCriticalSection( &gdi_section );
962 return TRUE;
965 obj = entry_to_handle( entry ); /* make it a full handle */
967 hdcs_head = entry->hdcs;
968 entry->hdcs = NULL;
970 if (entry->selcount)
972 TRACE("delayed for %p because object in use, count %u\n", obj, entry->selcount );
973 entry->deleted = 1; /* mark for delete */
975 else funcs = entry->funcs;
977 LeaveCriticalSection( &gdi_section );
979 while (hdcs_head)
981 struct hdc_list *next = hdcs_head->next;
982 DC *dc = get_dc_ptr(hdcs_head->hdc);
984 TRACE("hdc %p has interest in %p\n", hdcs_head->hdc, obj);
985 if(dc)
987 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pDeleteObject );
988 physdev->funcs->pDeleteObject( physdev, obj );
989 release_dc_ptr( dc );
991 HeapFree(GetProcessHeap(), 0, hdcs_head);
992 hdcs_head = next;
995 TRACE("%p\n", obj );
997 if (funcs && funcs->pDeleteObject) return funcs->pDeleteObject( obj );
998 return TRUE;
1001 /***********************************************************************
1002 * GDI_hdc_using_object
1004 * Call this if the dc requires DeleteObject notification
1006 void GDI_hdc_using_object(HGDIOBJ obj, HDC hdc)
1008 struct gdi_handle_entry *entry;
1009 struct hdc_list *phdc;
1011 TRACE("obj %p hdc %p\n", obj, hdc);
1013 EnterCriticalSection( &gdi_section );
1014 if ((entry = handle_entry( obj )) && !entry->system)
1016 for (phdc = entry->hdcs; phdc; phdc = phdc->next)
1017 if (phdc->hdc == hdc) break;
1019 if (!phdc)
1021 phdc = HeapAlloc(GetProcessHeap(), 0, sizeof(*phdc));
1022 phdc->hdc = hdc;
1023 phdc->next = entry->hdcs;
1024 entry->hdcs = phdc;
1027 LeaveCriticalSection( &gdi_section );
1030 /***********************************************************************
1031 * GDI_hdc_not_using_object
1034 void GDI_hdc_not_using_object(HGDIOBJ obj, HDC hdc)
1036 struct gdi_handle_entry *entry;
1037 struct hdc_list **pphdc;
1039 TRACE("obj %p hdc %p\n", obj, hdc);
1041 EnterCriticalSection( &gdi_section );
1042 if ((entry = handle_entry( obj )) && !entry->system)
1044 for (pphdc = &entry->hdcs; *pphdc; pphdc = &(*pphdc)->next)
1045 if ((*pphdc)->hdc == hdc)
1047 struct hdc_list *phdc = *pphdc;
1048 *pphdc = phdc->next;
1049 HeapFree(GetProcessHeap(), 0, phdc);
1050 break;
1053 LeaveCriticalSection( &gdi_section );
1056 /***********************************************************************
1057 * GetStockObject (GDI32.@)
1059 HGDIOBJ WINAPI GetStockObject( INT obj )
1061 if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
1062 switch (obj)
1064 case OEM_FIXED_FONT:
1065 case SYSTEM_FONT:
1066 case SYSTEM_FIXED_FONT:
1067 case DEFAULT_GUI_FONT:
1068 if (get_system_dpi() != 96) return scaled_stock_objects[obj];
1069 break;
1071 return stock_objects[obj];
1075 /***********************************************************************
1076 * GetObjectA (GDI32.@)
1078 INT WINAPI GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
1080 struct gdi_handle_entry *entry;
1081 const struct gdi_obj_funcs *funcs = NULL;
1082 INT result = 0;
1084 TRACE("%p %d %p\n", handle, count, buffer );
1086 EnterCriticalSection( &gdi_section );
1087 if ((entry = handle_entry( handle )))
1089 funcs = entry->funcs;
1090 handle = entry_to_handle( entry ); /* make it a full handle */
1092 LeaveCriticalSection( &gdi_section );
1094 if (funcs)
1096 if (!funcs->pGetObjectA)
1097 SetLastError( ERROR_INVALID_HANDLE );
1098 else if (buffer && ((ULONG_PTR)buffer >> 16) == 0) /* catch apps getting argument order wrong */
1099 SetLastError( ERROR_NOACCESS );
1100 else
1101 result = funcs->pGetObjectA( handle, count, buffer );
1103 return result;
1106 /***********************************************************************
1107 * GetObjectW (GDI32.@)
1109 INT WINAPI GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
1111 struct gdi_handle_entry *entry;
1112 const struct gdi_obj_funcs *funcs = NULL;
1113 INT result = 0;
1115 TRACE("%p %d %p\n", handle, count, buffer );
1117 EnterCriticalSection( &gdi_section );
1118 if ((entry = handle_entry( handle )))
1120 funcs = entry->funcs;
1121 handle = entry_to_handle( entry ); /* make it a full handle */
1123 LeaveCriticalSection( &gdi_section );
1125 if (funcs)
1127 if (!funcs->pGetObjectW)
1128 SetLastError( ERROR_INVALID_HANDLE );
1129 else if (buffer && ((ULONG_PTR)buffer >> 16) == 0) /* catch apps getting argument order wrong */
1130 SetLastError( ERROR_NOACCESS );
1131 else
1132 result = funcs->pGetObjectW( handle, count, buffer );
1134 return result;
1137 /***********************************************************************
1138 * GetObjectType (GDI32.@)
1140 DWORD WINAPI GetObjectType( HGDIOBJ handle )
1142 struct gdi_handle_entry *entry;
1143 DWORD result = 0;
1145 EnterCriticalSection( &gdi_section );
1146 if ((entry = handle_entry( handle ))) result = entry->type;
1147 LeaveCriticalSection( &gdi_section );
1149 TRACE("%p -> %u\n", handle, result );
1150 if (!result) SetLastError( ERROR_INVALID_HANDLE );
1151 return result;
1154 /***********************************************************************
1155 * GetCurrentObject (GDI32.@)
1157 * Get the currently selected object of a given type in a device context.
1159 * PARAMS
1160 * hdc [I] Device context to get the current object from
1161 * type [I] Type of current object to get (OBJ_* defines from "wingdi.h")
1163 * RETURNS
1164 * Success: The current object of the given type selected in hdc.
1165 * Failure: A NULL handle.
1167 * NOTES
1168 * - only the following object types are supported:
1169 *| OBJ_PEN
1170 *| OBJ_BRUSH
1171 *| OBJ_PAL
1172 *| OBJ_FONT
1173 *| OBJ_BITMAP
1175 HGDIOBJ WINAPI GetCurrentObject(HDC hdc,UINT type)
1177 HGDIOBJ ret = 0;
1178 DC * dc = get_dc_ptr( hdc );
1180 if (!dc) return 0;
1182 switch (type) {
1183 case OBJ_EXTPEN: /* fall through */
1184 case OBJ_PEN: ret = dc->hPen; break;
1185 case OBJ_BRUSH: ret = dc->hBrush; break;
1186 case OBJ_PAL: ret = dc->hPalette; break;
1187 case OBJ_FONT: ret = dc->hFont; break;
1188 case OBJ_BITMAP: ret = dc->hBitmap; break;
1190 /* tests show that OBJ_REGION is explicitly ignored */
1191 case OBJ_REGION: break;
1192 default:
1193 /* the SDK only mentions those above */
1194 FIXME("(%p,%d): unknown type.\n",hdc,type);
1195 break;
1197 release_dc_ptr( dc );
1198 return ret;
1202 /***********************************************************************
1203 * SelectObject (GDI32.@)
1205 * Select a Gdi object into a device context.
1207 * PARAMS
1208 * hdc [I] Device context to associate the object with
1209 * hObj [I] Gdi object to associate with hdc
1211 * RETURNS
1212 * Success: A non-NULL handle representing the previously selected object of
1213 * the same type as hObj.
1214 * Failure: A NULL object. If hdc is invalid, GetLastError() returns ERROR_INVALID_HANDLE.
1215 * if hObj is not a valid object handle, no last error is set. In either
1216 * case, hdc is unaffected by the call.
1218 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj )
1220 struct gdi_handle_entry *entry;
1221 const struct gdi_obj_funcs *funcs = NULL;
1223 TRACE( "(%p,%p)\n", hdc, hObj );
1225 EnterCriticalSection( &gdi_section );
1226 if ((entry = handle_entry( hObj )))
1228 funcs = entry->funcs;
1229 hObj = entry_to_handle( entry ); /* make it a full handle */
1231 LeaveCriticalSection( &gdi_section );
1233 if (funcs && funcs->pSelectObject) return funcs->pSelectObject( hObj, hdc );
1234 return 0;
1238 /***********************************************************************
1239 * UnrealizeObject (GDI32.@)
1241 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
1243 const struct gdi_obj_funcs *funcs = NULL;
1244 struct gdi_handle_entry *entry;
1246 EnterCriticalSection( &gdi_section );
1247 if ((entry = handle_entry( obj )))
1249 funcs = entry->funcs;
1250 obj = entry_to_handle( entry ); /* make it a full handle */
1252 LeaveCriticalSection( &gdi_section );
1254 if (funcs && funcs->pUnrealizeObject) return funcs->pUnrealizeObject( obj );
1255 return funcs != NULL;
1259 /* Solid colors to enumerate */
1260 static const COLORREF solid_colors[] =
1261 { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
1262 RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
1263 RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
1264 RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
1265 RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
1266 RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
1267 RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
1268 RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
1272 /***********************************************************************
1273 * EnumObjects (GDI32.@)
1275 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
1276 GOBJENUMPROC lpEnumFunc, LPARAM lParam )
1278 UINT i;
1279 INT retval = 0;
1280 LOGPEN pen;
1281 LOGBRUSH brush;
1283 TRACE("%p %d %p %08lx\n", hdc, nObjType, lpEnumFunc, lParam );
1284 switch(nObjType)
1286 case OBJ_PEN:
1287 /* Enumerate solid pens */
1288 for (i = 0; i < ARRAY_SIZE( solid_colors ); i++)
1290 pen.lopnStyle = PS_SOLID;
1291 pen.lopnWidth.x = 1;
1292 pen.lopnWidth.y = 0;
1293 pen.lopnColor = solid_colors[i];
1294 retval = lpEnumFunc( &pen, lParam );
1295 TRACE("solid pen %08x, ret=%d\n",
1296 solid_colors[i], retval);
1297 if (!retval) break;
1299 break;
1301 case OBJ_BRUSH:
1302 /* Enumerate solid brushes */
1303 for (i = 0; i < ARRAY_SIZE( solid_colors ); i++)
1305 brush.lbStyle = BS_SOLID;
1306 brush.lbColor = solid_colors[i];
1307 brush.lbHatch = 0;
1308 retval = lpEnumFunc( &brush, lParam );
1309 TRACE("solid brush %08x, ret=%d\n",
1310 solid_colors[i], retval);
1311 if (!retval) break;
1314 /* Now enumerate hatched brushes */
1315 if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
1317 brush.lbStyle = BS_HATCHED;
1318 brush.lbColor = RGB(0,0,0);
1319 brush.lbHatch = i;
1320 retval = lpEnumFunc( &brush, lParam );
1321 TRACE("hatched brush %d, ret=%d\n",
1322 i, retval);
1323 if (!retval) break;
1325 break;
1327 default:
1328 /* FIXME: implement Win32 types */
1329 WARN("(%d): Invalid type\n", nObjType );
1330 break;
1332 return retval;
1336 /***********************************************************************
1337 * SetObjectOwner (GDI32.@)
1339 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
1341 /* Nothing to do */
1344 /***********************************************************************
1345 * GdiInitializeLanguagePack (GDI32.@)
1347 DWORD WINAPI GdiInitializeLanguagePack( DWORD arg )
1349 FIXME("stub\n");
1350 return 0;
1353 /***********************************************************************
1354 * GdiFlush (GDI32.@)
1356 BOOL WINAPI GdiFlush(void)
1358 return TRUE; /* FIXME */
1362 /***********************************************************************
1363 * GdiGetBatchLimit (GDI32.@)
1365 DWORD WINAPI GdiGetBatchLimit(void)
1367 return 1; /* FIXME */
1371 /***********************************************************************
1372 * GdiSetBatchLimit (GDI32.@)
1374 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
1376 return 1; /* FIXME */
1380 /*******************************************************************
1381 * GetColorAdjustment [GDI32.@]
1385 BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1387 FIXME("stub\n");
1388 return FALSE;
1391 /*******************************************************************
1392 * GdiComment [GDI32.@]
1396 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1398 DC *dc = get_dc_ptr(hdc);
1399 BOOL ret = FALSE;
1401 if(dc)
1403 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGdiComment );
1404 ret = physdev->funcs->pGdiComment( physdev, cbSize, lpData );
1405 release_dc_ptr( dc );
1407 return ret;
1410 /*******************************************************************
1411 * SetColorAdjustment [GDI32.@]
1415 BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1417 FIXME("stub\n");
1418 return FALSE;