driver.c 22.2 KB
Newer Older
1 2 3
/*
 * Graphics driver management functions
 *
4 5
 * Copyright 1994 Bob Amstadt
 * Copyright 1996, 2001 Alexandre Julliard
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21
 */

22 23 24
#include "config.h"
#include "wine/port.h"

25
#include <stdarg.h>
26
#include <string.h>
27
#include <stdio.h>
28
#include "windef.h"
29 30 31
#include "winbase.h"
#include "winreg.h"

32
#include "gdi_private.h"
33
#include "wine/unicode.h"
34
#include "wine/debug.h"
35

36
WINE_DEFAULT_DEBUG_CHANNEL(driver);
37 38 39 40 41 42 43 44 45 46 47 48

struct graphics_driver
{
    struct graphics_driver *next;
    struct graphics_driver *prev;
    HMODULE                 module;  /* module handle */
    unsigned int            count;   /* reference count */
    DC_FUNCTIONS            funcs;
};

static struct graphics_driver *first_driver;
static struct graphics_driver *display_driver;
49 50 51 52 53 54

static CRITICAL_SECTION driver_section;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
    0, 0, &driver_section,
    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
55
      0, 0, { (DWORD_PTR)(__FILE__ ": driver_section") }
56 57
};
static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 };
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

/**********************************************************************
 *	     create_driver
 *
 * Allocate and fill the driver structure for a given module.
 */
static struct graphics_driver *create_driver( HMODULE module )
{
    struct graphics_driver *driver;

    if (!(driver = HeapAlloc( GetProcessHeap(), 0, sizeof(*driver)))) return NULL;
    driver->next   = NULL;
    driver->prev   = NULL;
    driver->module = module;
    driver->count  = 1;

    /* fill the function table */
75 76
    if (module)
    {
77
#define GET_FUNC(name) driver->funcs.p##name = (void*)GetProcAddress( module, #name )
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
        GET_FUNC(AbortDoc);
        GET_FUNC(AbortPath);
        GET_FUNC(AlphaBlend);
        GET_FUNC(AngleArc);
        GET_FUNC(Arc);
        GET_FUNC(ArcTo);
        GET_FUNC(BeginPath);
        GET_FUNC(BitBlt);
        GET_FUNC(ChoosePixelFormat);
        GET_FUNC(Chord);
        GET_FUNC(CloseFigure);
        GET_FUNC(CreateBitmap);
        GET_FUNC(CreateDC);
        GET_FUNC(CreateDIBSection);
        GET_FUNC(DeleteBitmap);
        GET_FUNC(DeleteDC);
        GET_FUNC(DescribePixelFormat);
        GET_FUNC(DeviceCapabilities);
        GET_FUNC(Ellipse);
        GET_FUNC(EndDoc);
        GET_FUNC(EndPage);
        GET_FUNC(EndPath);
        GET_FUNC(EnumDeviceFonts);
        GET_FUNC(ExcludeClipRect);
        GET_FUNC(ExtDeviceMode);
        GET_FUNC(ExtEscape);
        GET_FUNC(ExtFloodFill);
        GET_FUNC(ExtSelectClipRgn);
        GET_FUNC(ExtTextOut);
        GET_FUNC(FillPath);
        GET_FUNC(FillRgn);
        GET_FUNC(FlattenPath);
        GET_FUNC(FrameRgn);
        GET_FUNC(GdiComment);
        GET_FUNC(GetBitmapBits);
        GET_FUNC(GetCharWidth);
        GET_FUNC(GetDCOrgEx);
        GET_FUNC(GetDIBColorTable);
        GET_FUNC(GetDIBits);
        GET_FUNC(GetDeviceCaps);
        GET_FUNC(GetDeviceGammaRamp);
119
        GET_FUNC(GetICMProfile);
120 121 122 123
        GET_FUNC(GetNearestColor);
        GET_FUNC(GetPixel);
        GET_FUNC(GetPixelFormat);
        GET_FUNC(GetSystemPaletteEntries);
124
        GET_FUNC(GetTextExtentExPoint);
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
        GET_FUNC(GetTextMetrics);
        GET_FUNC(IntersectClipRect);
        GET_FUNC(InvertRgn);
        GET_FUNC(LineTo);
        GET_FUNC(MoveTo);
        GET_FUNC(ModifyWorldTransform);
        GET_FUNC(OffsetClipRgn);
        GET_FUNC(OffsetViewportOrg);
        GET_FUNC(OffsetWindowOrg);
        GET_FUNC(PaintRgn);
        GET_FUNC(PatBlt);
        GET_FUNC(Pie);
        GET_FUNC(PolyBezier);
        GET_FUNC(PolyBezierTo);
        GET_FUNC(PolyDraw);
        GET_FUNC(PolyPolygon);
        GET_FUNC(PolyPolyline);
        GET_FUNC(Polygon);
        GET_FUNC(Polyline);
        GET_FUNC(PolylineTo);
        GET_FUNC(RealizeDefaultPalette);
        GET_FUNC(RealizePalette);
        GET_FUNC(Rectangle);
        GET_FUNC(ResetDC);
        GET_FUNC(RestoreDC);
        GET_FUNC(RoundRect);
        GET_FUNC(SaveDC);
        GET_FUNC(ScaleViewportExt);
        GET_FUNC(ScaleWindowExt);
        GET_FUNC(SelectBitmap);
        GET_FUNC(SelectBrush);
        GET_FUNC(SelectClipPath);
        GET_FUNC(SelectFont);
        GET_FUNC(SelectPalette);
        GET_FUNC(SelectPen);
        GET_FUNC(SetArcDirection);
        GET_FUNC(SetBitmapBits);
        GET_FUNC(SetBkColor);
        GET_FUNC(SetBkMode);
        GET_FUNC(SetDCBrushColor);
        GET_FUNC(SetDCOrg);
        GET_FUNC(SetDCPenColor);
        GET_FUNC(SetDIBColorTable);
        GET_FUNC(SetDIBits);
        GET_FUNC(SetDIBitsToDevice);
        GET_FUNC(SetDeviceClipping);
        GET_FUNC(SetDeviceGammaRamp);
        GET_FUNC(SetMapMode);
        GET_FUNC(SetMapperFlags);
        GET_FUNC(SetPixel);
        GET_FUNC(SetPixelFormat);
        GET_FUNC(SetPolyFillMode);
        GET_FUNC(SetROP2);
        GET_FUNC(SetRelAbs);
        GET_FUNC(SetStretchBltMode);
        GET_FUNC(SetTextAlign);
        GET_FUNC(SetTextCharacterExtra);
        GET_FUNC(SetTextColor);
        GET_FUNC(SetTextJustification);
        GET_FUNC(SetViewportExt);
        GET_FUNC(SetViewportOrg);
        GET_FUNC(SetWindowExt);
        GET_FUNC(SetWindowOrg);
        GET_FUNC(SetWorldTransform);
        GET_FUNC(StartDoc);
        GET_FUNC(StartPage);
        GET_FUNC(StretchBlt);
        GET_FUNC(StretchDIBits);
        GET_FUNC(StrokeAndFillPath);
        GET_FUNC(StrokePath);
        GET_FUNC(SwapBuffers);
196
        GET_FUNC(UnrealizePalette);
197
        GET_FUNC(WidenPath);
198 199 200

        /* OpenGL32 */
        GET_FUNC(wglCreateContext);
201
        GET_FUNC(wglDeleteContext);
202
        GET_FUNC(wglGetProcAddress);
203
        GET_FUNC(wglGetPbufferDCARB);
204
        GET_FUNC(wglMakeContextCurrentARB);
205
        GET_FUNC(wglMakeCurrent);
206
        GET_FUNC(wglSetPixelFormatWINE);
207
        GET_FUNC(wglShareLists);
208 209
        GET_FUNC(wglUseFontBitmapsA);
        GET_FUNC(wglUseFontBitmapsW);
210
#undef GET_FUNC
211 212
    }
    else memset( &driver->funcs, 0, sizeof(driver->funcs) );
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

    /* add it to the list */
    driver->prev = NULL;
    if ((driver->next = first_driver)) driver->next->prev = driver;
    first_driver = driver;
    return driver;
}


/**********************************************************************
 *	     load_display_driver
 *
 * Special case for loading the display driver: get the name from the config file
 */
static struct graphics_driver *load_display_driver(void)
{
229
    char buffer[MAX_PATH], libname[32], *name, *next;
230
    HMODULE module = 0;
231 232 233 234 235 236 237 238
    HKEY hkey;

    if (display_driver)  /* already loaded */
    {
        display_driver->count++;
        return display_driver;
    }

239
    strcpy( buffer, "x11" );  /* default value */
240 241
    /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
    if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
242 243
    {
        DWORD type, count = sizeof(buffer);
244
        RegQueryValueExA( hkey, "Graphics", 0, &type, (LPBYTE) buffer, &count );
245 246 247
        RegCloseKey( hkey );
    }

248 249 250 251 252 253
    name = buffer;
    while (name)
    {
        next = strchr( name, ',' );
        if (next) *next++ = 0;

254 255
        snprintf( libname, sizeof(libname), "wine%s.drv", name );
        if ((module = LoadLibraryA( libname )) != 0) break;
256 257
        name = next;
    }
258 259 260 261 262

    if (!(display_driver = create_driver( module )))
    {
        MESSAGE( "Could not create graphics driver '%s'\n", buffer );
        FreeLibrary( module );
263
        ExitProcess(1);
264 265 266 267 268 269 270 271 272 273
    }

    display_driver->count++;  /* we don't want to free it */
    return display_driver;
}


/**********************************************************************
 *	     DRIVER_load_driver
 */
274
const DC_FUNCTIONS *DRIVER_load_driver( LPCWSTR name )
275 276 277
{
    HMODULE module;
    struct graphics_driver *driver;
278
    static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
279
    static const WCHAR display1W[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','1',0};
280

Alexandre Julliard's avatar
Alexandre Julliard committed
281
    EnterCriticalSection( &driver_section );
282 283

    /* display driver is a special case */
284 285
    if (!strcmpiW( name, displayW ) || 
        !strcmpiW( name, display1W ))
286 287
    {
        driver = load_display_driver();
Alexandre Julliard's avatar
Alexandre Julliard committed
288
        LeaveCriticalSection( &driver_section );
289 290 291
        return &driver->funcs;
    }

292
    if ((module = GetModuleHandleW( name )))
293 294 295 296 297 298
    {
        for (driver = first_driver; driver; driver = driver->next)
        {
            if (driver->module == module)
            {
                driver->count++;
Alexandre Julliard's avatar
Alexandre Julliard committed
299
                LeaveCriticalSection( &driver_section );
300 301 302 303 304
                return &driver->funcs;
            }
        }
    }

305
    if (!(module = LoadLibraryW( name )))
306
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
307
        LeaveCriticalSection( &driver_section );
308
        return NULL;
309 310 311 312 313
    }

    if (!(driver = create_driver( module )))
    {
        FreeLibrary( module );
Alexandre Julliard's avatar
Alexandre Julliard committed
314
        LeaveCriticalSection( &driver_section );
315 316 317
        return NULL;
    }

318
    TRACE( "loaded driver %p for %s\n", driver, debugstr_w(name) );
Alexandre Julliard's avatar
Alexandre Julliard committed
319
    LeaveCriticalSection( &driver_section );
320 321 322 323 324 325 326 327 328 329 330 331 332
    return &driver->funcs;
}


/**********************************************************************
 *	     DRIVER_get_driver
 *
 * Get a new copy of an existing driver.
 */
const DC_FUNCTIONS *DRIVER_get_driver( const DC_FUNCTIONS *funcs )
{
    struct graphics_driver *driver;

Alexandre Julliard's avatar
Alexandre Julliard committed
333
    EnterCriticalSection( &driver_section );
334 335 336 337
    for (driver = first_driver; driver; driver = driver->next)
        if (&driver->funcs == funcs) break;
    if (!driver) ERR( "driver not found, trouble ahead\n" );
    driver->count++;
Alexandre Julliard's avatar
Alexandre Julliard committed
338
    LeaveCriticalSection( &driver_section );
339 340 341 342 343 344 345 346 347 348 349 350 351
    return funcs;
}


/**********************************************************************
 *	     DRIVER_release_driver
 *
 * Release a driver by decrementing ref count and freeing it if needed.
 */
void DRIVER_release_driver( const DC_FUNCTIONS *funcs )
{
    struct graphics_driver *driver;

Alexandre Julliard's avatar
Alexandre Julliard committed
352
    EnterCriticalSection( &driver_section );
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368

    for (driver = first_driver; driver; driver = driver->next)
        if (&driver->funcs == funcs) break;

    if (!driver) goto done;
    if (--driver->count) goto done;

    /* removed last reference, free it */
    if (driver->next) driver->next->prev = driver->prev;
    if (driver->prev) driver->prev->next = driver->next;
    else first_driver = driver->next;
    if (driver == display_driver) display_driver = NULL;

    FreeLibrary( driver->module );
    HeapFree( GetProcessHeap(), 0, driver );
 done:
Alexandre Julliard's avatar
Alexandre Julliard committed
369
    LeaveCriticalSection( &driver_section );
370 371 372 373 374 375 376
}


/*****************************************************************************
 *      DRIVER_GetDriverName
 *
 */
377
BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size )
378
{
379 380
    static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
    static const WCHAR devicesW[] = { 'd','e','v','i','c','e','s',0 };
381
    static const WCHAR display1W[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','1',0};
382 383
    static const WCHAR empty_strW[] = { 0 };
    WCHAR *p;
384 385

    /* display is a special case */
386 387
    if (!strcmpiW( device, displayW ) ||
        !strcmpiW( device, display1W ))
388
    {
389
        lstrcpynW( driver, displayW, size );
390 391 392
        return TRUE;
    }

393
    size = GetProfileStringW(devicesW, device, empty_strW, driver, size);
394
    if(!size) {
395
        WARN("Unable to find %s in [devices] section of win.ini\n", debugstr_w(device));
396 397
        return FALSE;
    }
398
    p = strchrW(driver, ',');
399 400
    if(!p)
    {
401
        WARN("%s entry in [devices] section of win.ini is malformed.\n", debugstr_w(device));
402 403
        return FALSE;
    }
404 405
    *p = 0;
    TRACE("Found %s for %s\n", debugstr_w(driver), debugstr_w(device));
406 407 408
    return TRUE;
}

409 410 411 412 413 414 415

/***********************************************************************
 *           GdiConvertToDevmodeW    (GDI32.@)
 */
DEVMODEW * WINAPI GdiConvertToDevmodeW(const DEVMODEA *dmA)
{
    DEVMODEW *dmW;
416
    WORD dmW_size, dmA_size;
417

418
    dmA_size = dmA->dmSize;
419 420 421 422 423

    /* this is the minimal dmSize that XP accepts */
    if (dmA_size < FIELD_OFFSET(DEVMODEA, dmFields))
        return NULL;

424 425
    if (dmA_size > sizeof(DEVMODEA))
        dmA_size = sizeof(DEVMODEA);
426

427 428
    dmW_size = dmA_size + CCHDEVICENAME;
    if (dmA_size >= FIELD_OFFSET(DEVMODEA, dmFormName) + CCHFORMNAME)
429 430 431 432 433
        dmW_size += CCHFORMNAME;

    dmW = HeapAlloc(GetProcessHeap(), 0, dmW_size + dmA->dmDriverExtra);
    if (!dmW) return NULL;

434
    MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmDeviceName, -1,
435 436
                                   dmW->dmDeviceName, CCHDEVICENAME);
    /* copy slightly more, to avoid long computations */
437
    memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion, dmA_size - CCHDEVICENAME);
438

439
    if (dmA_size >= FIELD_OFFSET(DEVMODEA, dmFormName) + CCHFORMNAME)
440
    {
441 442
        if (dmA->dmFields & DM_FORMNAME)
            MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmFormName, -1,
443
                                       dmW->dmFormName, CCHFORMNAME);
444 445 446
        else
            dmW->dmFormName[0] = 0;

447 448
        if (dmA_size > FIELD_OFFSET(DEVMODEA, dmLogPixels))
            memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA_size - FIELD_OFFSET(DEVMODEA, dmLogPixels));
449 450 451
    }

    if (dmA->dmDriverExtra)
452
        memcpy((char *)dmW + dmW_size, (const char *)dmA + dmA_size, dmA->dmDriverExtra);
453 454 455 456 457 458 459

    dmW->dmSize = dmW_size;

    return dmW;
}


460 461 462 463 464 465 466 467
/*****************************************************************************
 *      @ [GDI32.100]
 *
 * This should thunk to 16-bit and simply call the proc with the given args.
 */
INT WINAPI GDI_CallDevInstall16( FARPROC16 lpfnDevInstallProc, HWND hWnd,
                                 LPSTR lpModelName, LPSTR OldPort, LPSTR NewPort )
{
468
    FIXME("(%p, %p, %s, %s, %s)\n", lpfnDevInstallProc, hWnd, lpModelName, OldPort, NewPort );
469 470 471 472 473 474 475
    return -1;
}

/*****************************************************************************
 *      @ [GDI32.101]
 *
 * This should load the correct driver for lpszDevice and calls this driver's
476
 * ExtDeviceModePropSheet proc.
477
 *
478
 * Note: The driver calls a callback routine for each property sheet page; these
479 480
 * pages are supposed to be filled into the structure pointed to by lpPropSheet.
 * The layout of this structure is:
481
 *
482 483 484 485 486 487 488 489 490 491
 * struct
 * {
 *   DWORD  nPages;
 *   DWORD  unknown;
 *   HPROPSHEETPAGE  pages[10];
 * };
 */
INT WINAPI GDI_CallExtDeviceModePropSheet16( HWND hWnd, LPCSTR lpszDevice,
                                             LPCSTR lpszPort, LPVOID lpPropSheet )
{
492
    FIXME("(%p, %s, %s, %p)\n", hWnd, lpszDevice, lpszPort, lpPropSheet );
493 494 495 496 497 498 499 500
    return -1;
}

/*****************************************************************************
 *      @ [GDI32.102]
 *
 * This should load the correct driver for lpszDevice and calls this driver's
 * ExtDeviceMode proc.
501 502
 *
 * FIXME: convert ExtDeviceMode to unicode in the driver interface
503 504 505 506 507 508
 */
INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd,
                                    LPDEVMODEA lpdmOutput, LPSTR lpszDevice,
                                    LPSTR lpszPort, LPDEVMODEA lpdmInput,
                                    LPSTR lpszProfile, DWORD fwMode )
{
509 510
    WCHAR deviceW[300];
    WCHAR bufW[300];
511 512 513 514 515
    char buf[300];
    HDC hdc;
    DC *dc;
    INT ret = -1;

516
    TRACE("(%p, %p, %s, %s, %p, %s, %d)\n",
517 518
          hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile, fwMode );

519 520 521 522 523 524
    if (!lpszDevice) return -1;
    if (!MultiByteToWideChar(CP_ACP, 0, lpszDevice, -1, deviceW, 300)) return -1;

    if(!DRIVER_GetDriverName( deviceW, bufW, 300 )) return -1;

    if (!WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, 300, NULL, NULL)) return -1;
525

526
    if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1;
527

528
    if ((dc = get_dc_ptr( hdc )))
529
    {
530 531 532 533
        if (dc->funcs->pExtDeviceMode)
	    ret = dc->funcs->pExtDeviceMode( buf, hwnd, lpdmOutput, lpszDevice, lpszPort,
                                             lpdmInput, lpszProfile, fwMode );
	release_dc_ptr( dc );
534 535 536 537 538 539 540 541 542 543 544 545 546 547
    }
    DeleteDC( hdc );
    return ret;
}

/****************************************************************************
 *      @ [GDI32.103]
 *
 * This should load the correct driver for lpszDevice and calls this driver's
 * AdvancedSetupDialog proc.
 */
INT WINAPI GDI_CallAdvancedSetupDialog16( HWND hwnd, LPSTR lpszDevice,
                                          LPDEVMODEA devin, LPDEVMODEA devout )
{
548
    TRACE("(%p, %s, %p, %p)\n", hwnd, lpszDevice, devin, devout );
549 550 551 552 553 554 555 556
    return -1;
}

/*****************************************************************************
 *      @ [GDI32.104]
 *
 * This should load the correct driver for lpszDevice and calls this driver's
 * DeviceCapabilities proc.
557 558
 *
 * FIXME: convert DeviceCapabilities to unicode in the driver interface
559 560 561 562 563
 */
DWORD WINAPI GDI_CallDeviceCapabilities16( LPCSTR lpszDevice, LPCSTR lpszPort,
                                           WORD fwCapability, LPSTR lpszOutput,
                                           LPDEVMODEA lpdm )
{
564 565
    WCHAR deviceW[300];
    WCHAR bufW[300];
566 567 568 569 570 571 572
    char buf[300];
    HDC hdc;
    DC *dc;
    INT ret = -1;

    TRACE("(%s, %s, %d, %p, %p)\n", lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm );

573 574 575 576 577 578
    if (!lpszDevice) return -1;
    if (!MultiByteToWideChar(CP_ACP, 0, lpszDevice, -1, deviceW, 300)) return -1;

    if(!DRIVER_GetDriverName( deviceW, bufW, 300 )) return -1;

    if (!WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, 300, NULL, NULL)) return -1;
579

580
    if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1;
581

582
    if ((dc = get_dc_ptr( hdc )))
583 584 585 586
    {
        if (dc->funcs->pDeviceCapabilities)
            ret = dc->funcs->pDeviceCapabilities( buf, lpszDevice, lpszPort,
                                                  fwCapability, lpszOutput, lpdm );
587
        release_dc_ptr( dc );
588 589 590 591
    }
    DeleteDC( hdc );
    return ret;
}
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657


/************************************************************************
 *             Escape  [GDI32.@]
 */
INT WINAPI Escape( HDC hdc, INT escape, INT in_count, LPCSTR in_data, LPVOID out_data )
{
    INT ret;
    POINT *pt;

    switch (escape)
    {
    case ABORTDOC:
        return AbortDoc( hdc );

    case ENDDOC:
        return EndDoc( hdc );

    case GETPHYSPAGESIZE:
        pt = out_data;
        pt->x = GetDeviceCaps( hdc, PHYSICALWIDTH );
        pt->y = GetDeviceCaps( hdc, PHYSICALHEIGHT );
        return 1;

    case GETPRINTINGOFFSET:
        pt = out_data;
        pt->x = GetDeviceCaps( hdc, PHYSICALOFFSETX );
        pt->y = GetDeviceCaps( hdc, PHYSICALOFFSETY );
        return 1;

    case GETSCALINGFACTOR:
        pt = out_data;
        pt->x = GetDeviceCaps( hdc, SCALINGFACTORX );
        pt->y = GetDeviceCaps( hdc, SCALINGFACTORY );
        return 1;

    case NEWFRAME:
        return EndPage( hdc );

    case SETABORTPROC:
        return SetAbortProc( hdc, (ABORTPROC)in_data );

    case STARTDOC:
        {
            DOCINFOA doc;
            char *name = NULL;

            /* in_data may not be 0 terminated so we must copy it */
            if (in_data)
            {
                name = HeapAlloc( GetProcessHeap(), 0, in_count+1 );
                memcpy( name, in_data, in_count );
                name[in_count] = 0;
            }
            /* out_data is actually a pointer to the DocInfo structure and used as
             * a second input parameter */
            if (out_data) doc = *(DOCINFOA *)out_data;
            else
            {
                doc.cbSize = sizeof(doc);
                doc.lpszOutput = NULL;
                doc.lpszDatatype = NULL;
                doc.fwType = 0;
            }
            doc.lpszDocName = name;
            ret = StartDocA( hdc, &doc );
658
            HeapFree( GetProcessHeap(), 0, name );
659 660 661 662 663 664
            if (ret > 0) ret = StartPage( hdc );
            return ret;
        }

    case QUERYESCSUPPORT:
        {
Eric Pouech's avatar
Eric Pouech committed
665
            const INT *ptr = (const INT *)in_data;
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
            if (in_count < sizeof(INT)) return 0;
            switch(*ptr)
            {
            case ABORTDOC:
            case ENDDOC:
            case GETPHYSPAGESIZE:
            case GETPRINTINGOFFSET:
            case GETSCALINGFACTOR:
            case NEWFRAME:
            case QUERYESCSUPPORT:
            case SETABORTPROC:
            case STARTDOC:
                return TRUE;
            }
            break;
        }
    }

    /* if not handled internally, pass it to the driver */
    return ExtEscape( hdc, escape, in_count, in_data, 0, out_data );
}


/******************************************************************************
 *		ExtEscape	[GDI32.@]
 *
692 693
 * Access capabilities of a particular device that are not available through GDI.
 *
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
 * PARAMS
 *    hdc         [I] Handle to device context
 *    nEscape     [I] Escape function
 *    cbInput     [I] Number of bytes in input structure
 *    lpszInData  [I] Pointer to input structure
 *    cbOutput    [I] Number of bytes in output structure
 *    lpszOutData [O] Pointer to output structure
 *
 * RETURNS
 *    Success: >0
 *    Not implemented: 0
 *    Failure: <0
 */
INT WINAPI ExtEscape( HDC hdc, INT nEscape, INT cbInput, LPCSTR lpszInData,
                      INT cbOutput, LPSTR lpszOutData )
{
    INT ret = 0;
711
    DC * dc = get_dc_ptr( hdc );
712 713 714 715
    if (dc)
    {
        if (dc->funcs->pExtEscape)
            ret = dc->funcs->pExtEscape( dc->physDev, nEscape, cbInput, lpszInData, cbOutput, lpszOutData );
716
        release_dc_ptr( dc );
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
    }
    return ret;
}


/*******************************************************************
 *      DrawEscape [GDI32.@]
 *
 *
 */
INT WINAPI DrawEscape(HDC hdc, INT nEscape, INT cbInput, LPCSTR lpszInData)
{
    FIXME("DrawEscape, stub\n");
    return 0;
}
732 733 734 735 736 737 738 739 740 741 742 743

/*******************************************************************
 *      NamedEscape [GDI32.@]
 */
INT WINAPI NamedEscape( HDC hdc, LPCWSTR pDriver, INT nEscape, INT cbInput, LPCSTR lpszInData,
                        INT cbOutput, LPSTR lpszOutData )
{
    FIXME("(%p, %s, %d, %d, %p, %d, %p)\n",
          hdc, wine_dbgstr_w(pDriver), nEscape, cbInput, lpszInData, cbOutput,
          lpszOutData);
    return 0;
}