gdiobj.c 39.9 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * GDI functions
 *
 * Copyright 1993 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
19
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
20

21 22
#include "config.h"

23
#include <assert.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
24
#include <stdlib.h>
25
#include <stdarg.h>
26
#include <stdio.h>
27

28
#include "windef.h"
29
#include "winbase.h"
30
#include "wingdi.h"
31
#include "winreg.h"
32
#include "winerror.h"
33
#include "winternl.h"
34

35
#include "gdi_private.h"
36
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
37

38
WINE_DEFAULT_DEBUG_CHANNEL(gdi);
39

40
#define HGDIOBJ_32(h16)   ((HGDIOBJ)(ULONG_PTR)(h16))
41

42 43
#define GDI_HEAP_SIZE 0xffe0

Alexandre Julliard's avatar
Alexandre Julliard committed
44
/***********************************************************************
45
 *          GDI stock objects
Alexandre Julliard's avatar
Alexandre Julliard committed
46 47
 */

48 49 50
static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
static const LOGBRUSH NullBrush  = { BS_NULL, 0, 0 };
Alexandre Julliard's avatar
Alexandre Julliard committed
51

52 53
static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
static const LOGBRUSH GrayBrush   = { BS_SOLID, RGB(128,128,128), 0 };
54
static const LOGBRUSH DkGrayBrush = { BS_SOLID, RGB(64,64,64), 0 };
Alexandre Julliard's avatar
Alexandre Julliard committed
55

56 57 58
static const LOGPEN WhitePen = { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
static const LOGPEN BlackPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
static const LOGPEN NullPen  = { PS_NULL,  { 0, 0 }, 0 };
Alexandre Julliard's avatar
Alexandre Julliard committed
59

60 61
static const LOGBRUSH DCBrush = { BS_SOLID, RGB(255,255,255), 0 };
static const LOGPEN DCPen     = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
62 63 64 65 66 67 68

/* reserve one extra entry for the stock default bitmap */
/* this is what Windows does too */
#define NB_STOCK_OBJECTS (STOCK_LAST+2)

static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];

69 70 71 72 73
static SYSLEVEL GDI_level;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
    0, 0, &GDI_level.crst,
    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
74
      0, 0, { (DWORD_PTR)(__FILE__ ": GDI_level") }
75 76 77
};
static SYSLEVEL GDI_level = { { &critsect_debug, -1, 0, 0, 0, 0 }, 3 };

78 79 80 81 82 83 84

/****************************************************************************
 *
 *	language-independent stock fonts
 *
 */

85 86 87
static const LOGFONTW OEMFixedFont =
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
  0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
Alexandre Julliard's avatar
Alexandre Julliard committed
88

89 90 91
static const LOGFONTW AnsiFixedFont =
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
  0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
Alexandre Julliard's avatar
Alexandre Julliard committed
92

93 94 95 96
static const LOGFONTW AnsiVarFont =
{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
  0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
  {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'} };
Alexandre Julliard's avatar
Alexandre Julliard committed
97

98 99 100 101 102 103 104 105 106 107 108
/******************************************************************************
 *
 *      language-dependent stock fonts
 *
 *      'ANSI' charset and 'DEFAULT' charset is not same.
 *      The chars in CP_ACP should be drawn with 'DEFAULT' charset.
 *      'ANSI' charset seems to be identical with ISO-8859-1.
 *      'DEFAULT' charset is a language-dependent charset.
 *
 *      'System' font seems to be an alias for language-dependent font.
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
109

110
/*
Vitaly Lipatov's avatar
Vitaly Lipatov committed
111 112 113
 * language-dependent stock fonts for all known charsets
 * please see TranslateCharsetInfo (dlls/gdi/font.c) and
 * CharsetBindingInfo (dlls/x11drv/xfont.c),
114 115 116 117 118 119 120 121
 * and modify entries for your language if needed.
 */
struct DefaultFontInfo
{
        UINT            charset;
        LOGFONTW        SystemFont;
        LOGFONTW        DeviceDefaultFont;
        LOGFONTW        SystemFixedFont;
122
        LOGFONTW        DefaultGuiFont; /* Note for this font the lfHeight member should be the point size */
123 124 125 126 127 128
};

static const struct DefaultFontInfo default_fonts[] =
{
    {   ANSI_CHARSET,
        { /* System */
129
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
130 131 132 133 134 135 136 137 138 139 140 141 142 143
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
144
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
145
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
146
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
147 148 149 150
        },
    },
    {   EASTEUROPE_CHARSET,
        { /* System */
151
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
152 153 154 155 156 157 158 159 160 161 162 163 164 165
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
166
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
167
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
168
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
169 170 171 172
        },
    },
    {   RUSSIAN_CHARSET,
        { /* System */
173
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
174 175 176 177 178 179 180 181 182 183 184 185 186 187
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
188
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
189
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
190
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
191 192 193 194
        },
    },
    {   GREEK_CHARSET,
        { /* System */
195
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
196 197 198 199 200 201 202 203 204 205 206 207 208 209
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
210
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
211
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
212
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
213 214 215 216
        },
    },
    {   TURKISH_CHARSET,
        { /* System */
217
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
218 219 220 221 222 223 224 225 226 227 228 229 230 231
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
232
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
233
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
234
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
235 236 237 238
        },
    },
    {   HEBREW_CHARSET,
        { /* System */
239
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
240 241 242 243 244 245 246 247 248 249 250 251 252 253
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
254
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
255
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
256
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
257 258 259 260
        },
    },
    {   ARABIC_CHARSET,
        { /* System */
261
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
262 263 264 265 266 267 268 269 270 271 272 273 274 275
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
276
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
277
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
278
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
279 280 281 282
        },
    },
    {   BALTIC_CHARSET,
        { /* System */
283
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
284 285 286 287 288 289 290 291 292 293 294 295 296 297
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
298
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
299
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
300
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
301 302 303 304
        },
    },
    {   THAI_CHARSET,
        { /* System */
305
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
306 307 308 309 310 311 312 313 314 315 316 317 318 319
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
320
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
321
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
322
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
323 324 325 326
        },
    },
    {   SHIFTJIS_CHARSET,
        { /* System */
327
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
328 329 330 331 332 333 334 335 336 337 338 339 340 341
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
342
           9, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
343
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
344
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
345 346 347 348
        },
    },
    {   GB2312_CHARSET,
        { /* System */
349
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
350 351 352 353 354 355 356 357 358 359 360 361 362 363
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
364
           9, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
365
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
366
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
367 368 369 370
        },
    },
    {   HANGEUL_CHARSET,
        { /* System */
371
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
372 373 374 375 376 377 378 379 380 381 382 383 384 385
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
386
           9, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
387
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
388
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
389 390 391 392
        },
    },
    {   CHINESEBIG5_CHARSET,
        { /* System */
393
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
394 395 396 397 398 399 400 401 402 403 404 405 406 407
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
408
           9, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
409
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
410
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
411 412 413 414
        },
    },
    {   JOHAB_CHARSET,
        { /* System */
415
          16, 7, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
416 417 418 419 420 421 422 423 424 425 426 427 428 429
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'S','y','s','t','e','m','\0'}
        },
        { /* Device Default */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
           {'\0'}
        },
        { /* System Fixed */
          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
           {'\0'}
        },
        { /* DefaultGuiFont */
430
           8, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
431
           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
432
           {'M','S',' ','S','h','e','l','l',' ','D','l','g','\0'}
433 434 435
        },
    },
};
Alexandre Julliard's avatar
Alexandre Julliard committed
436

Alexandre Julliard's avatar
Alexandre Julliard committed
437

438 439 440 441 442 443 444
/*************************************************************************
 * __wine_make_gdi_object_system    (GDI32.@)
 *
 * USER has to tell GDI that its system brushes and pens are non-deletable.
 * For a description of the GDI object magics and their flags,
 * see "Undocumented Windows" (wrong about the OBJECT_NOSYSTEM flag, though).
 */
445
void CDECL __wine_make_gdi_object_system( HGDIOBJ handle, BOOL set)
446 447 448 449 450 451 452 453 454 455 456 457
{
    GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );

    /* touch the "system" bit of the wMagic field of a GDIOBJHDR */
    if (set)
        ptr->wMagic &= ~OBJECT_NOSYSTEM;
    else
        ptr->wMagic |= OBJECT_NOSYSTEM;

    GDI_ReleaseObj( handle );
}

458 459 460 461 462
/******************************************************************************
 *      get_default_fonts
 */
static const struct DefaultFontInfo* get_default_fonts(UINT charset)
{
463
        unsigned int n;
Alexandre Julliard's avatar
Alexandre Julliard committed
464

465 466 467 468 469
        for(n=0;n<(sizeof(default_fonts)/sizeof(default_fonts[0]));n++)
        {
                if ( default_fonts[n].charset == charset )
                        return &default_fonts[n];
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
470

471 472 473
        FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
        return &default_fonts[0];
}
474

475

476 477 478 479 480 481
/******************************************************************************
 *      get_default_charset    (internal)
 *
 * get the language-dependent charset that can handle CP_ACP correctly.
 */
static UINT get_default_charset( void )
482
{
483 484 485 486 487
    CHARSETINFO     csi;
    UINT    uACP;

    uACP = GetACP();
    csi.ciCharset = ANSI_CHARSET;
488
    if ( !TranslateCharsetInfo( ULongToPtr(uACP), &csi, TCI_SRCCODEPAGE ) )
489 490 491 492 493 494
    {
        FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", uACP );
        return ANSI_CHARSET;
    }

    return csi.ciCharset;
495
}
496

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
static const WCHAR dpi_key_name[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
static const WCHAR dpi_value_name[] = {'L','o','g','P','i','x','e','l','s','\0'};

/******************************************************************************
 *      get_dpi   (internal)
 *
 * get the dpi from the registry
 */
static DWORD get_dpi( void )
{
    DWORD dpi = 96;
    HKEY hkey;

    if (RegOpenKeyW(HKEY_CURRENT_CONFIG, dpi_key_name, &hkey) == ERROR_SUCCESS)
    {
        DWORD type, size, new_dpi;

        size = sizeof(new_dpi);
        if(RegQueryValueExW(hkey, dpi_value_name, NULL, &type, (void *)&new_dpi, &size) == ERROR_SUCCESS)
        {
            if(type == REG_DWORD && new_dpi != 0)
                dpi = new_dpi;
        }
        RegCloseKey(hkey);
    }
    return dpi;
}
524

525

526
/***********************************************************************
527
 *           GDI_inc_ref_count
528 529 530
 *
 * Increment the reference count of a GDI object.
 */
531
BOOL GDI_inc_ref_count( HGDIOBJ handle )
532
{
533 534 535 536 537 538 539 540
    GDIOBJHDR *header;

    if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
    {
        header->dwCount++;
        GDI_ReleaseObj( handle );
    }
    return header != NULL;
541 542 543 544
}


/***********************************************************************
545
 *           GDI_dec_ref_count
546 547 548
 *
 * Decrement the reference count of a GDI object.
 */
549
BOOL GDI_dec_ref_count( HGDIOBJ handle )
550 551 552 553 554 555 556 557 558 559 560 561
{
    GDIOBJHDR *header;

    if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
    {
        if (header->dwCount) header->dwCount--;
        if (header->dwCount != 0x80000000) GDI_ReleaseObj( handle );
        else
        {
            /* handle delayed DeleteObject*/
            header->dwCount = 0;
            GDI_ReleaseObj( handle );
562
            TRACE( "executing delayed DeleteObject for %p\n", handle );
563 564 565
            DeleteObject( handle );
        }
    }
566
    return header != NULL;
567 568 569
}


Alexandre Julliard's avatar
Alexandre Julliard committed
570 571 572
/***********************************************************************
 *           GDI_Init
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
573
 * GDI initialization.
Alexandre Julliard's avatar
Alexandre Julliard committed
574
 */
575
BOOL GDI_Init(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
576
{
577
    LOGFONTW default_gui_font;
578
    const struct DefaultFontInfo* deffonts;
579 580
    int i;

581 582
    WineEngInit();

583 584 585 586 587 588 589 590 591 592 593 594 595 596
    /* create stock objects */
    stock_objects[WHITE_BRUSH]  = CreateBrushIndirect( &WhiteBrush );
    stock_objects[LTGRAY_BRUSH] = CreateBrushIndirect( &LtGrayBrush );
    stock_objects[GRAY_BRUSH]   = CreateBrushIndirect( &GrayBrush );
    stock_objects[DKGRAY_BRUSH] = CreateBrushIndirect( &DkGrayBrush );
    stock_objects[BLACK_BRUSH]  = CreateBrushIndirect( &BlackBrush );
    stock_objects[NULL_BRUSH]   = CreateBrushIndirect( &NullBrush );

    stock_objects[WHITE_PEN]    = CreatePenIndirect( &WhitePen );
    stock_objects[BLACK_PEN]    = CreatePenIndirect( &BlackPen );
    stock_objects[NULL_PEN]     = CreatePenIndirect( &NullPen );

    stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
    stock_objects[DEFAULT_BITMAP]  = CreateBitmap( 1, 1, 1, 1, NULL );
Alexandre Julliard's avatar
Alexandre Julliard committed
597

598
    /* language-independent stock fonts */
599 600 601
    stock_objects[OEM_FIXED_FONT]      = CreateFontIndirectW( &OEMFixedFont );
    stock_objects[ANSI_FIXED_FONT]     = CreateFontIndirectW( &AnsiFixedFont );
    stock_objects[ANSI_VAR_FONT]       = CreateFontIndirectW( &AnsiVarFont );
602 603 604

    /* language-dependent stock fonts */
    deffonts = get_default_fonts(get_default_charset());
605 606 607
    stock_objects[SYSTEM_FONT]         = CreateFontIndirectW( &deffonts->SystemFont );
    stock_objects[DEVICE_DEFAULT_FONT] = CreateFontIndirectW( &deffonts->DeviceDefaultFont );
    stock_objects[SYSTEM_FIXED_FONT]   = CreateFontIndirectW( &deffonts->SystemFixedFont );
608 609 610

    /* For the default gui font, we use the lfHeight member in deffonts as a place-holder
       for the point size so we must convert this into a true height */
611
    default_gui_font = deffonts->DefaultGuiFont;
612
    default_gui_font.lfHeight = -MulDiv(default_gui_font.lfHeight, get_dpi(), 72);
613
    stock_objects[DEFAULT_GUI_FONT]    = CreateFontIndirectW( &default_gui_font );
Alexandre Julliard's avatar
Alexandre Julliard committed
614

615 616
    stock_objects[DC_BRUSH]     = CreateBrushIndirect( &DCBrush );
    stock_objects[DC_PEN]       = CreatePenIndirect( &DCPen );
Alexandre Julliard's avatar
Alexandre Julliard committed
617

618 619 620 621 622 623 624 625 626
    /* clear the NOSYSTEM bit on all stock objects*/
    for (i = 0; i < NB_STOCK_OBJECTS; i++)
    {
        if (!stock_objects[i])
        {
            if (i == 9) continue;  /* there's no stock object 9 */
            ERR( "could not create stock object %d\n", i );
            return FALSE;
        }
627
        __wine_make_gdi_object_system( stock_objects[i], TRUE );
628 629
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
630
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
631 632
}

633
#define FIRST_LARGE_HANDLE 16
634
#define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
635 636 637 638 639 640 641 642
static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
static int next_large_handle;

/***********************************************************************
 *           alloc_large_heap
 *
 * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
 */
643
static inline GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
{
    int i;
    GDIOBJHDR *obj;

    for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
        if (!large_handles[i]) goto found;
    for (i = 0; i <= next_large_handle; i++)
        if (!large_handles[i]) goto found;
    *handle = 0;
    return NULL;

 found:
    if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
    {
        large_handles[i] = obj;
659
        *handle = (HGDIOBJ)(ULONG_PTR)((i + FIRST_LARGE_HANDLE) << 2);
660 661 662 663 664
        next_large_handle = i;
    }
    return obj;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
665 666 667 668

/***********************************************************************
 *           GDI_AllocObject
 */
669
void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle, const struct gdi_obj_funcs *funcs )
Alexandre Julliard's avatar
Alexandre Julliard committed
670
{
671
    GDIOBJHDR *obj = NULL;
672 673

    _EnterSysLevel( &GDI_level );
674
    if (!(obj = alloc_large_heap( size, handle ))) goto error;
675

676
    obj->wMagic  = magic|OBJECT_NOSYSTEM;
677
    obj->dwCount = 0;
678
    obj->funcs   = funcs;
679
    obj->hdcs    = NULL;
680

681
    TRACE("(%p): enter %d\n", *handle, GDI_level.crst.RecursionCount);
682
    return obj;
683 684 685 686 687

error:
    _LeaveSysLevel( &GDI_level );
    *handle = 0;
    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
688 689 690 691
}


/***********************************************************************
692 693 694 695
 *           GDI_ReallocObject
 *
 * The object ptr must have been obtained with GDI_GetObjPtr.
 * The new pointer must be released with GDI_ReleaseObj.
Alexandre Julliard's avatar
Alexandre Julliard committed
696
 */
697
void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
Alexandre Julliard's avatar
Alexandre Julliard committed
698
{
699
    void *new_ptr = NULL;
700
    int i;
Alexandre Julliard's avatar
Alexandre Julliard committed
701

702 703
    i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
    if (i >= 0 && i < MAX_LARGE_HANDLES && large_handles[i])
704
    {
705 706
        new_ptr = HeapReAlloc( GetProcessHeap(), 0, large_handles[i], size );
        if (new_ptr) large_handles[i] = new_ptr;
707
    }
708
    else ERR( "Invalid handle %p\n", handle );
709 710
    if (!new_ptr)
    {
711
        TRACE("(%p): leave %d\n", handle, GDI_level.crst.RecursionCount);
712 713 714
        _LeaveSysLevel( &GDI_level );
    }
    return new_ptr;
715
}
716

717 718 719 720 721 722 723

/***********************************************************************
 *           GDI_FreeObject
 */
BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
{
    GDIOBJHDR *object = ptr;
724
    int i;
725

726
    object->wMagic = 0;  /* Mark it as invalid */
727
    object->funcs  = NULL;
728
    i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
729
    if (i >= 0 && i < MAX_LARGE_HANDLES)
730
    {
731 732
        HeapFree( GetProcessHeap(), 0, large_handles[i] );
        large_handles[i] = NULL;
733
    }
734
    else ERR( "Invalid handle %p\n", handle );
735
    TRACE("(%p): leave %d\n", handle, GDI_level.crst.RecursionCount);
736
    _LeaveSysLevel( &GDI_level );
Alexandre Julliard's avatar
Alexandre Julliard committed
737 738 739
    return TRUE;
}

740

Alexandre Julliard's avatar
Alexandre Julliard committed
741 742 743 744 745
/***********************************************************************
 *           GDI_GetObjPtr
 *
 * Return a pointer to the GDI object associated to the handle.
 * Return NULL if the object has the wrong magic number.
746
 * The object must be released with GDI_ReleaseObj.
Alexandre Julliard's avatar
Alexandre Julliard committed
747
 */
748
void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
Alexandre Julliard's avatar
Alexandre Julliard committed
749
{
750
    GDIOBJHDR *ptr = NULL;
751
    int i;
752 753

    _EnterSysLevel( &GDI_level );
Alexandre Julliard's avatar
Alexandre Julliard committed
754

755 756
    i = ((UINT_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
    if (i >= 0 && i < MAX_LARGE_HANDLES)
Alexandre Julliard's avatar
Alexandre Julliard committed
757
    {
758 759
        ptr = large_handles[i];
        if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
760
    }
761 762 763 764

    if (!ptr)
    {
        _LeaveSysLevel( &GDI_level );
765
        WARN( "Invalid handle %p\n", handle );
766
    }
767
    else TRACE("(%p): enter %d\n", handle, GDI_level.crst.RecursionCount);
768

Alexandre Julliard's avatar
Alexandre Julliard committed
769 770 771 772
    return ptr;
}


773 774 775 776 777 778
/***********************************************************************
 *           GDI_ReleaseObj
 *
 */
void GDI_ReleaseObj( HGDIOBJ handle )
{
779
    TRACE("(%p): leave %d\n", handle, GDI_level.crst.RecursionCount);
780 781 782 783
    _LeaveSysLevel( &GDI_level );
}


784 785 786 787 788 789 790 791 792
/***********************************************************************
 *           GDI_CheckNotLock
 */
void GDI_CheckNotLock(void)
{
    _CheckNotSysLevel( &GDI_level );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
793
/***********************************************************************
794
 *           DeleteObject    (GDI32.@)
795 796 797 798 799 800 801 802 803 804 805
 *
 * Delete a Gdi object.
 *
 * PARAMS
 *  obj [I] Gdi object to delete
 *
 * RETURNS
 *  Success: TRUE. If obj was not returned from GetStockObject(), any resources
 *           it consumed are released.
 *  Failure: FALSE, if obj is not a valid Gdi object, or is currently selected
 *           into a DC.
Alexandre Julliard's avatar
Alexandre Julliard committed
806
 */
807
BOOL WINAPI DeleteObject( HGDIOBJ obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
808 809 810
{
      /* Check if object is valid */

Alexandre Julliard's avatar
Alexandre Julliard committed
811 812
    GDIOBJHDR * header;
    if (HIWORD(obj)) return FALSE;
813

814
    if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
815

816 817 818
    if (!(header->wMagic & OBJECT_NOSYSTEM)
    &&   (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
    {
819
	TRACE("Preserving system object %p\n", obj);
820 821 822
        GDI_ReleaseObj( obj );
	return TRUE;
    }
823

824 825
    while (header->hdcs)
    {
826
        DC *dc = get_dc_ptr(header->hdcs->hdc);
827 828 829 830 831 832 833
        struct hdc_list *tmp;

        TRACE("hdc %p has interest in %p\n", header->hdcs->hdc, obj);
        if(dc)
        {
            if(dc->funcs->pDeleteObject)
                dc->funcs->pDeleteObject( dc->physDev, obj );
834
            release_dc_ptr( dc );
835 836 837 838 839 840
        }
        tmp = header->hdcs;
        header->hdcs = header->hdcs->next;
        HeapFree(GetProcessHeap(), 0, tmp);
    }

841 842
    if (header->dwCount)
    {
843
        TRACE("delayed for %p because object in use, count %d\n", obj, header->dwCount );
844 845 846 847 848
        header->dwCount |= 0x80000000; /* mark for delete */
        GDI_ReleaseObj( obj );
        return TRUE;
    }

849
    TRACE("%p\n", obj );
Alexandre Julliard's avatar
Alexandre Julliard committed
850 851 852

      /* Delete object */

853 854
    if (header->funcs && header->funcs->pDeleteObject)
        return header->funcs->pDeleteObject( obj, header );
855

856
    GDI_ReleaseObj( obj );
Alexandre Julliard's avatar
Alexandre Julliard committed
857 858 859
    return FALSE;
}

860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
/***********************************************************************
 *           GDI_hdc_using_object
 *
 * Call this if the dc requires DeleteObject notification
 */
BOOL GDI_hdc_using_object(HGDIOBJ obj, HDC hdc)
{
    GDIOBJHDR * header;
    struct hdc_list **pphdc;

    TRACE("obj %p hdc %p\n", obj, hdc);

    if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;

    if (!(header->wMagic & OBJECT_NOSYSTEM) &&
         (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
    {
        GDI_ReleaseObj(obj);
        return FALSE;
    }

    for(pphdc = &header->hdcs; *pphdc; pphdc = &(*pphdc)->next)
        if((*pphdc)->hdc == hdc)
            break;

    if(!*pphdc) {
        *pphdc = HeapAlloc(GetProcessHeap(), 0, sizeof(**pphdc));
        (*pphdc)->hdc = hdc;
        (*pphdc)->next = NULL;
    }

    GDI_ReleaseObj(obj);
    return TRUE;
}

/***********************************************************************
 *           GDI_hdc_not_using_object
 *
 */
BOOL GDI_hdc_not_using_object(HGDIOBJ obj, HDC hdc)
{
    GDIOBJHDR * header;
    struct hdc_list *phdc, **prev;

    TRACE("obj %p hdc %p\n", obj, hdc);

    if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;

    if (!(header->wMagic & OBJECT_NOSYSTEM) &&
         (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
    {
        GDI_ReleaseObj(obj);
        return FALSE;
    }

    phdc = header->hdcs;
    prev = &header->hdcs;

    while(phdc) {
        if(phdc->hdc == hdc) {
            *prev = phdc->next;
            HeapFree(GetProcessHeap(), 0, phdc);
            phdc = *prev;
        } else {
            prev = &phdc->next;
            phdc = phdc->next;
        }
    }

    GDI_ReleaseObj(obj);
    return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
932 933

/***********************************************************************
934
 *           GetStockObject    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
935
 */
936
HGDIOBJ WINAPI GetStockObject( INT obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
937
{
938
    HGDIOBJ ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
939
    if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
940
    ret = stock_objects[obj];
941
    TRACE("returning %p\n", ret );
942
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
943 944 945
}


Alexandre Julliard's avatar
Alexandre Julliard committed
946
/***********************************************************************
947
 *           GetObjectA    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
948
 */
949
INT WINAPI GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
Alexandre Julliard's avatar
Alexandre Julliard committed
950
{
951
    GDIOBJHDR * ptr;
952
    INT result = 0;
953
    TRACE("%p %d %p\n", handle, count, buffer );
Alexandre Julliard's avatar
Alexandre Julliard committed
954

955 956
    if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;

957 958 959 960
    if (ptr->funcs && ptr->funcs->pGetObjectA)
        result = ptr->funcs->pGetObjectA( handle, ptr, count, buffer );
    else
        SetLastError( ERROR_INVALID_HANDLE );
961

962
    GDI_ReleaseObj( handle );
Alexandre Julliard's avatar
Alexandre Julliard committed
963
    return result;
Alexandre Julliard's avatar
Alexandre Julliard committed
964
}
965

966
/***********************************************************************
967
 *           GetObjectW    (GDI32.@)
968
 */
969
INT WINAPI GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
970
{
971
    GDIOBJHDR * ptr;
972
    INT result = 0;
973
    TRACE("%p %d %p\n", handle, count, buffer );
974

975 976
    if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;

977 978 979 980 981
    if (ptr->funcs && ptr->funcs->pGetObjectW)
        result = ptr->funcs->pGetObjectW( handle, ptr, count, buffer );
    else
        SetLastError( ERROR_INVALID_HANDLE );

982
    GDI_ReleaseObj( handle );
983 984
    return result;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
985

Alexandre Julliard's avatar
Alexandre Julliard committed
986
/***********************************************************************
987
 *           GetObjectType    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
988
 */
989
DWORD WINAPI GetObjectType( HGDIOBJ handle )
Alexandre Julliard's avatar
Alexandre Julliard committed
990
{
991
    GDIOBJHDR * ptr;
992
    INT result = 0;
993
    TRACE("%p\n", handle );
Alexandre Julliard's avatar
Alexandre Julliard committed
994

995 996 997 998 999
    if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
    {
        SetLastError( ERROR_INVALID_HANDLE );
        return 0;
    }
1000

1001
    switch(GDIMAGIC(ptr->wMagic))
Alexandre Julliard's avatar
Alexandre Julliard committed
1002 1003 1004 1005
    {
      case PEN_MAGIC:
	  result = OBJ_PEN;
	  break;
1006 1007 1008
      case EXT_PEN_MAGIC:
	  result = OBJ_EXTPEN;
	  break;
1009
      case BRUSH_MAGIC:
Alexandre Julliard's avatar
Alexandre Julliard committed
1010 1011
	  result = OBJ_BRUSH;
	  break;
1012
      case BITMAP_MAGIC:
Alexandre Julliard's avatar
Alexandre Julliard committed
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
	  result = OBJ_BITMAP;
	  break;
      case FONT_MAGIC:
	  result = OBJ_FONT;
	  break;
      case PALETTE_MAGIC:
	  result = OBJ_PAL;
	  break;
      case REGION_MAGIC:
	  result = OBJ_REGION;
	  break;
      case DC_MAGIC:
	  result = OBJ_DC;
	  break;
      case META_DC_MAGIC:
	  result = OBJ_METADC;
	  break;
      case METAFILE_MAGIC:
	  result = OBJ_METAFILE;
	  break;
      case METAFILE_DC_MAGIC:
	  result = OBJ_METADC;
	  break;
1036 1037 1038 1039 1040 1041
      case ENHMETAFILE_MAGIC:
	  result = OBJ_ENHMETAFILE;
	  break;
      case ENHMETAFILE_DC_MAGIC:
	  result = OBJ_ENHMETADC;
	  break;
1042 1043 1044
      case MEMORY_DC_MAGIC:
	  result = OBJ_MEMDC;
	  break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1045
      default:
1046
	  FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
Alexandre Julliard's avatar
Alexandre Julliard committed
1047 1048
	  break;
    }
1049
    GDI_ReleaseObj( handle );
Alexandre Julliard's avatar
Alexandre Julliard committed
1050 1051
    return result;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1052

Alexandre Julliard's avatar
Alexandre Julliard committed
1053
/***********************************************************************
1054
 *           GetCurrentObject    	(GDI32.@)
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
 *
 * Get the currently selected object of a given type in a device context.
 *
 * PARAMS
 *  hdc  [I] Device context to get the current object from
 *  type [I] Type of current object to get (OBJ_* defines from "wingdi.h")
 *
 * RETURNS
 *  Success: The current object of the given type selected in hdc.
 *  Failure: A NULL handle.
 *
 * NOTES
 * - only the following object types are supported:
 *| OBJ_PEN
 *| OBJ_BRUSH
 *| OBJ_PAL
 *| OBJ_FONT
 *| OBJ_BITMAP
Alexandre Julliard's avatar
Alexandre Julliard committed
1073
 */
1074
HGDIOBJ WINAPI GetCurrentObject(HDC hdc,UINT type)
Alexandre Julliard's avatar
Alexandre Julliard committed
1075
{
1076
    HGDIOBJ ret = 0;
1077 1078 1079
    DC * dc = get_dc_ptr( hdc );

    if (!dc) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1080 1081

    switch (type) {
1082
	case OBJ_EXTPEN: /* fall through */
1083 1084 1085 1086 1087
	case OBJ_PEN:	 ret = dc->hPen; break;
	case OBJ_BRUSH:	 ret = dc->hBrush; break;
	case OBJ_PAL:	 ret = dc->hPalette; break;
	case OBJ_FONT:	 ret = dc->hFont; break;
	case OBJ_BITMAP: ret = dc->hBitmap; break;
1088 1089 1090

	/* tests show that OBJ_REGION is explicitly ignored */
	case OBJ_REGION: break;
1091 1092 1093
        default:
            /* the SDK only mentions those above */
            FIXME("(%p,%d): unknown type.\n",hdc,type);
1094
	    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1095
    }
1096
    release_dc_ptr( dc );
1097
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
1098
}
1099 1100


Alexandre Julliard's avatar
Alexandre Julliard committed
1101
/***********************************************************************
1102
 *           SelectObject    (GDI32.@)
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
 *
 * Select a Gdi object into a device context.
 *
 * PARAMS
 *  hdc  [I] Device context to associate the object with
 *  hObj [I] Gdi object to associate with hdc
 *
 * RETURNS
 *  Success: A non-NULL handle representing the previously selected object of
 *           the same type as hObj.
 *  Failure: A NULL object. If hdc is invalid, GetLastError() returns ERROR_INVALID_HANDLE.
 *           if hObj is not a valid object handle, no last error is set. In either
 *           case, hdc is unaffected by the call.
Alexandre Julliard's avatar
Alexandre Julliard committed
1116
 */
1117
HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj )
Alexandre Julliard's avatar
Alexandre Julliard committed
1118
{
1119
    HGDIOBJ ret = 0;
1120
    GDIOBJHDR *header;
1121

1122
    TRACE( "(%p,%p)\n", hdc, hObj );
1123

1124 1125
    header = GDI_GetObjPtr( hObj, MAGIC_DONTCARE );
    if (header)
1126
    {
1127 1128 1129
        const struct gdi_obj_funcs *funcs = header->funcs;
        GDI_ReleaseObj( hObj );
        if (funcs && funcs->pSelectObject) ret = funcs->pSelectObject( hObj, hdc );
1130
    }
1131
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
1132 1133 1134
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1135
/***********************************************************************
1136
 *           UnrealizeObject    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1137
 */
1138
BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
1139
{
1140
    BOOL result = TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1141
  /* Check if object is valid */
Alexandre Julliard's avatar
Alexandre Julliard committed
1142

1143
    GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
Alexandre Julliard's avatar
Alexandre Julliard committed
1144 1145
    if (!header) return FALSE;

1146
    TRACE("%p\n", obj );
Alexandre Julliard's avatar
Alexandre Julliard committed
1147 1148 1149

      /* Unrealize object */

1150 1151
    if (header->funcs && header->funcs->pUnrealizeObject)
        result = header->funcs->pUnrealizeObject( obj, header );
Alexandre Julliard's avatar
Alexandre Julliard committed
1152

1153
    GDI_ReleaseObj( obj );
Alexandre Julliard's avatar
Alexandre Julliard committed
1154
    return result;
Alexandre Julliard's avatar
Alexandre Julliard committed
1155
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1156 1157


Andreas Mohr's avatar
Andreas Mohr committed
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
/* Solid colors to enumerate */
static const COLORREF solid_colors[] =
{ RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
};
1169

Alexandre Julliard's avatar
Alexandre Julliard committed
1170 1171

/***********************************************************************
1172
 *           EnumObjects    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1173
 */
1174 1175
INT WINAPI EnumObjects( HDC hdc, INT nObjType,
                            GOBJENUMPROC lpEnumFunc, LPARAM lParam )
Alexandre Julliard's avatar
Alexandre Julliard committed
1176
{
1177 1178
    UINT i;
    INT retval = 0;
1179 1180
    LOGPEN pen;
    LOGBRUSH brush;
Alexandre Julliard's avatar
Alexandre Julliard committed
1181

1182
    TRACE("%p %d %p %08lx\n", hdc, nObjType, lpEnumFunc, lParam );
Alexandre Julliard's avatar
Alexandre Julliard committed
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
    switch(nObjType)
    {
    case OBJ_PEN:
        /* Enumerate solid pens */
        for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
        {
            pen.lopnStyle   = PS_SOLID;
            pen.lopnWidth.x = 1;
            pen.lopnWidth.y = 0;
            pen.lopnColor   = solid_colors[i];
            retval = lpEnumFunc( &pen, lParam );
1194
            TRACE("solid pen %08x, ret=%d\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
                         solid_colors[i], retval);
            if (!retval) break;
        }
        break;

    case OBJ_BRUSH:
        /* Enumerate solid brushes */
        for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
        {
            brush.lbStyle = BS_SOLID;
            brush.lbColor = solid_colors[i];
            brush.lbHatch = 0;
            retval = lpEnumFunc( &brush, lParam );
1208
            TRACE("solid brush %08x, ret=%d\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
                         solid_colors[i], retval);
            if (!retval) break;
        }

        /* Now enumerate hatched brushes */
        if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
        {
            brush.lbStyle = BS_HATCHED;
            brush.lbColor = RGB(0,0,0);
            brush.lbHatch = i;
            retval = lpEnumFunc( &brush, lParam );
1220
            TRACE("hatched brush %d, ret=%d\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
1221 1222 1223 1224 1225 1226 1227
                         i, retval);
            if (!retval) break;
        }
        break;

    default:
        /* FIXME: implement Win32 types */
1228
        WARN("(%d): Invalid type\n", nObjType );
Alexandre Julliard's avatar
Alexandre Julliard committed
1229 1230 1231
        break;
    }
    return retval;
Alexandre Julliard's avatar
Alexandre Julliard committed
1232
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1233

Alexandre Julliard's avatar
Alexandre Julliard committed
1234

Alexandre Julliard's avatar
Alexandre Julliard committed
1235
/***********************************************************************
1236
 *           SetObjectOwner    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1237
 */
1238
void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
Alexandre Julliard's avatar
Alexandre Julliard committed
1239 1240 1241 1242
{
    /* Nothing to do */
}

1243

Alexandre Julliard's avatar
Alexandre Julliard committed
1244 1245
/***********************************************************************
 *           MakeObjectPrivate    (GDI.463)
1246 1247 1248 1249 1250 1251 1252
 *
 * What does that mean ?
 * Some little docu can be found in "Undocumented Windows",
 * but this is basically useless.
 * At least we know that this flags the GDI object's wMagic
 * with 0x2000 (OBJECT_PRIVATE), so we just do it.
 * But Wine doesn't react on that yet.
Alexandre Julliard's avatar
Alexandre Julliard committed
1253
 */
1254
void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle16, BOOL16 private )
Alexandre Julliard's avatar
Alexandre Julliard committed
1255
{
1256
    HGDIOBJ handle = HGDIOBJ_32( handle16 );
1257 1258 1259
    GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
    if (!ptr)
    {
1260
	ERR("invalid GDI object %p !\n", handle);
1261 1262 1263 1264
	return;
    }
    ptr->wMagic |= OBJECT_PRIVATE;
    GDI_ReleaseObj( handle );
Alexandre Julliard's avatar
Alexandre Julliard committed
1265 1266 1267
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1268
/***********************************************************************
1269
 *           GdiFlush    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1270
 */
1271
BOOL WINAPI GdiFlush(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
1272 1273 1274 1275
{
    return TRUE;  /* FIXME */
}

Alexandre Julliard's avatar
Alexandre Julliard committed
1276 1277

/***********************************************************************
1278
 *           GdiGetBatchLimit    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1279 1280 1281 1282 1283 1284 1285 1286
 */
DWORD WINAPI GdiGetBatchLimit(void)
{
    return 1;  /* FIXME */
}


/***********************************************************************
1287
 *           GdiSetBatchLimit    (GDI32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1288 1289 1290 1291 1292 1293 1294
 */
DWORD WINAPI GdiSetBatchLimit( DWORD limit )
{
    return 1; /* FIXME */
}


1295
/*******************************************************************
1296
 *      GetColorAdjustment [GDI32.@]
1297 1298 1299
 *
 *
 */
1300
BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
1301
{
1302
        FIXME("GetColorAdjustment, stub\n");
1303 1304 1305 1306
        return 0;
}

/*******************************************************************
1307
 *      GdiComment [GDI32.@]
1308 1309 1310
 *
 *
 */
1311
BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
1312
{
1313
    DC *dc = get_dc_ptr(hdc);
1314 1315 1316 1317 1318
    BOOL ret = FALSE;
    if(dc)
    {
        if (dc->funcs->pGdiComment)
            ret = dc->funcs->pGdiComment( dc->physDev, cbSize, lpData );
1319
        release_dc_ptr( dc );
1320 1321
    }
    return ret;
1322
}
1323

1324
/*******************************************************************
1325
 *      SetColorAdjustment [GDI32.@]
1326 1327 1328
 *
 *
 */
1329
BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
1330
{
1331
        FIXME("SetColorAdjustment, stub\n");
1332 1333
        return 0;
}