dc.c 40.2 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * GDI Device Context functions
 *
 * Copyright 1993 Alexandre Julliard
Alexandre Julliard's avatar
Alexandre Julliard committed
5
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
6 7
 */

8 9
#include "config.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
10
#include <stdlib.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
11
#include <string.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
12
#include "dc.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
13
#include "gdi.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
14
#include "heap.h"
15
#include "debugtools.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
16
#include "font.h"
17
#include "callback.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
18
#include "winerror.h"
19 20
#include "windef.h"
#include "wingdi.h"
21
#include "wine/winuser16.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
22

23
DEFAULT_DEBUG_CHANNEL(dc);
24

Alexandre Julliard's avatar
Alexandre Julliard committed
25 26 27 28 29 30 31
/***********************************************************************
 *           DC_Init_DC_INFO
 *
 * Fill the WIN_DC_INFO structure.
 */
static void DC_Init_DC_INFO( WIN_DC_INFO *win_dc_info )
{
Alexandre Julliard's avatar
Alexandre Julliard committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
    win_dc_info->flags               = 0;
    win_dc_info->devCaps             = NULL;
    win_dc_info->hClipRgn            = 0;
    win_dc_info->hVisRgn             = 0;
    win_dc_info->hGCClipRgn          = 0;
    win_dc_info->hPen                = STOCK_BLACK_PEN;
    win_dc_info->hBrush              = STOCK_WHITE_BRUSH;
    win_dc_info->hFont               = STOCK_SYSTEM_FONT;
    win_dc_info->hBitmap             = 0;
    win_dc_info->hDevice             = 0;
    win_dc_info->hPalette            = STOCK_DEFAULT_PALETTE;
    win_dc_info->ROPmode             = R2_COPYPEN;
    win_dc_info->polyFillMode        = ALTERNATE;
    win_dc_info->stretchBltMode      = BLACKONWHITE;
    win_dc_info->relAbsMode          = ABSOLUTE;
    win_dc_info->backgroundMode      = OPAQUE;
    win_dc_info->backgroundColor     = RGB( 255, 255, 255 );
    win_dc_info->textColor           = RGB( 0, 0, 0 );
    win_dc_info->brushOrgX           = 0;
    win_dc_info->brushOrgY           = 0;
    win_dc_info->textAlign           = TA_LEFT | TA_TOP | TA_NOUPDATECP;
    win_dc_info->charExtra           = 0;
    win_dc_info->breakTotalExtra     = 0;
    win_dc_info->breakCount          = 0;
    win_dc_info->breakExtra          = 0;
    win_dc_info->breakRem            = 0;
    win_dc_info->bitsPerPixel        = 1;
    win_dc_info->MapMode             = MM_TEXT;
    win_dc_info->GraphicsMode        = GM_COMPATIBLE;
    win_dc_info->DCOrgX              = 0;
    win_dc_info->DCOrgY              = 0;
63
    win_dc_info->pAbortProc          = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
64 65 66 67 68 69 70 71 72 73 74 75
    win_dc_info->CursPosX            = 0;
    win_dc_info->CursPosY            = 0;
    win_dc_info->ArcDirection        = AD_COUNTERCLOCKWISE;
    win_dc_info->xformWorld2Wnd.eM11 = 1.0f;
    win_dc_info->xformWorld2Wnd.eM12 = 0.0f;
    win_dc_info->xformWorld2Wnd.eM21 = 0.0f;
    win_dc_info->xformWorld2Wnd.eM22 = 1.0f;
    win_dc_info->xformWorld2Wnd.eDx  = 0.0f;
    win_dc_info->xformWorld2Wnd.eDy  = 0.0f;
    win_dc_info->xformWorld2Vport    = win_dc_info->xformWorld2Wnd;
    win_dc_info->xformVport2World    = win_dc_info->xformWorld2Wnd;
    win_dc_info->vport2WorldValid    = TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
76 77 78 79 80

    PATH_InitGdiPath(&win_dc_info->path);
}


Alexandre Julliard's avatar
Alexandre Julliard committed
81 82 83 84 85 86 87 88 89
/***********************************************************************
 *           DC_AllocDC
 */
DC *DC_AllocDC( const DC_FUNCTIONS *funcs )
{
    HDC16 hdc;
    DC *dc;

    if (!(hdc = GDI_AllocObject( sizeof(DC), DC_MAGIC ))) return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
90
    dc = (DC *) GDI_HEAP_LOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
91 92 93 94 95 96 97

    dc->hSelf      = hdc;
    dc->funcs      = funcs;
    dc->physDev    = NULL;
    dc->saveLevel  = 0;
    dc->dwHookData = 0L;
    dc->hookProc   = NULL;
98
    dc->hookThunk  = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
99 100 101 102 103 104 105 106
    dc->wndOrgX    = 0;
    dc->wndOrgY    = 0;
    dc->wndExtX    = 1;
    dc->wndExtY    = 1;
    dc->vportOrgX  = 0;
    dc->vportOrgY  = 0;
    dc->vportExtX  = 1;
    dc->vportExtY  = 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
107

Alexandre Julliard's avatar
Alexandre Julliard committed
108 109
    DC_Init_DC_INFO( &dc->w );

Alexandre Julliard's avatar
Alexandre Julliard committed
110 111 112 113
    return dc;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
114

Alexandre Julliard's avatar
Alexandre Julliard committed
115 116 117
/***********************************************************************
 *           DC_GetDCPtr
 */
118
DC *DC_GetDCPtr( HDC hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
119
{
Alexandre Julliard's avatar
Alexandre Julliard committed
120
    GDIOBJHDR *ptr = (GDIOBJHDR *)GDI_HEAP_LOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
121
    if (!ptr) return NULL;
122 123
    if ((ptr->wMagic == DC_MAGIC) || (ptr->wMagic == METAFILE_DC_MAGIC) ||
	(ptr->wMagic == ENHMETAFILE_DC_MAGIC))
Alexandre Julliard's avatar
Alexandre Julliard committed
124
        return (DC *)ptr;
Alexandre Julliard's avatar
Alexandre Julliard committed
125
    GDI_HEAP_UNLOCK( hdc );
126
    SetLastError( ERROR_INVALID_HANDLE );
Alexandre Julliard's avatar
Alexandre Julliard committed
127 128 129 130
    return NULL;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
131
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
132
 *           DC_InitDC
Alexandre Julliard's avatar
Alexandre Julliard committed
133
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
134
 * Setup device-specific DC values for a newly created DC.
Alexandre Julliard's avatar
Alexandre Julliard committed
135
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
136
void DC_InitDC( DC* dc )
Alexandre Julliard's avatar
Alexandre Julliard committed
137
{
138 139 140 141 142 143
    RealizeDefaultPalette16( dc->hSelf );
    SetTextColor( dc->hSelf, dc->w.textColor );
    SetBkColor( dc->hSelf, dc->w.backgroundColor );
    SelectObject( dc->hSelf, dc->w.hPen );
    SelectObject( dc->hSelf, dc->w.hBrush );
    SelectObject( dc->hSelf, dc->w.hFont );
Alexandre Julliard's avatar
Alexandre Julliard committed
144
    CLIPPING_UpdateGCRegion( dc );
Alexandre Julliard's avatar
Alexandre Julliard committed
145 146 147
}


Alexandre Julliard's avatar
Alexandre Julliard committed
148 149 150 151 152 153 154
/***********************************************************************
 *           DC_InvertXform
 *
 * Computes the inverse of the transformation xformSrc and stores it to
 * xformDest. Returns TRUE if successful or FALSE if the xformSrc matrix
 * is singular.
 */
155
static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
Alexandre Julliard's avatar
Alexandre Julliard committed
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 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
{
    FLOAT determinant;
    
    determinant = xformSrc->eM11*xformSrc->eM22 -
        xformSrc->eM12*xformSrc->eM21;
    if (determinant > -1e-12 && determinant < 1e-12)
        return FALSE;

    xformDest->eM11 =  xformSrc->eM22 / determinant;
    xformDest->eM12 = -xformSrc->eM12 / determinant;
    xformDest->eM21 = -xformSrc->eM21 / determinant;
    xformDest->eM22 =  xformSrc->eM11 / determinant;
    xformDest->eDx  = -xformSrc->eDx * xformDest->eM11 -
                       xformSrc->eDy * xformDest->eM21;
    xformDest->eDy  = -xformSrc->eDx * xformDest->eM12 -
                       xformSrc->eDy * xformDest->eM22;

    return TRUE;
}


/***********************************************************************
 *           DC_UpdateXforms
 *
 * Updates the xformWorld2Vport, xformVport2World and vport2WorldValid
 * fields of the specified DC by creating a transformation that
 * represents the current mapping mode and combining it with the DC's
 * world transform. This function should be called whenever the
 * parameters associated with the mapping mode (window and viewport
 * extents and origins) or the world transform change.
 */
void DC_UpdateXforms( DC *dc )
{
    XFORM xformWnd2Vport;
    FLOAT scaleX, scaleY;
    
    /* Construct a transformation to do the window-to-viewport conversion */
    scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
    scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
    xformWnd2Vport.eM11 = scaleX;
    xformWnd2Vport.eM12 = 0.0;
    xformWnd2Vport.eM21 = 0.0;
    xformWnd2Vport.eM22 = scaleY;
    xformWnd2Vport.eDx  = (FLOAT)dc->vportOrgX -
        scaleX * (FLOAT)dc->wndOrgX;
    xformWnd2Vport.eDy  = (FLOAT)dc->vportOrgY -
        scaleY * (FLOAT)dc->wndOrgY;

    /* Combine with the world transformation */
    CombineTransform( &dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd,
        &xformWnd2Vport );

    /* Create inverse of world-to-viewport transformation */
    dc->w.vport2WorldValid = DC_InvertXform( &dc->w.xformWorld2Vport,
        &dc->w.xformVport2World );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
214 215 216
/***********************************************************************
 *           GetDCState    (GDI.179)
 */
217
HDC16 WINAPI GetDCState16( HDC16 hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
218 219
{
    DC * newdc, * dc;
Alexandre Julliard's avatar
Alexandre Julliard committed
220
    HGDIOBJ16 handle;
Alexandre Julliard's avatar
Alexandre Julliard committed
221 222
    
    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
223 224 225 226 227 228
    if (!(handle = GDI_AllocObject( sizeof(DC), DC_MAGIC )))
    {
      GDI_HEAP_UNLOCK( hdc );
      return 0;
    }
    newdc = (DC *) GDI_HEAP_LOCK( handle );
Alexandre Julliard's avatar
Alexandre Julliard committed
229

230
    TRACE("(%04x): returning %04x\n", hdc, handle );
Alexandre Julliard's avatar
Alexandre Julliard committed
231

Alexandre Julliard's avatar
Alexandre Julliard committed
232 233 234 235 236 237 238 239
    newdc->w.flags            = dc->w.flags | DC_SAVED;
    newdc->w.devCaps          = dc->w.devCaps;
    newdc->w.hPen             = dc->w.hPen;       
    newdc->w.hBrush           = dc->w.hBrush;     
    newdc->w.hFont            = dc->w.hFont;      
    newdc->w.hBitmap          = dc->w.hBitmap;    
    newdc->w.hDevice          = dc->w.hDevice;
    newdc->w.hPalette         = dc->w.hPalette;   
240
    newdc->w.totalExtent      = dc->w.totalExtent;
Alexandre Julliard's avatar
Alexandre Julliard committed
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
    newdc->w.bitsPerPixel     = dc->w.bitsPerPixel;
    newdc->w.ROPmode          = dc->w.ROPmode;
    newdc->w.polyFillMode     = dc->w.polyFillMode;
    newdc->w.stretchBltMode   = dc->w.stretchBltMode;
    newdc->w.relAbsMode       = dc->w.relAbsMode;
    newdc->w.backgroundMode   = dc->w.backgroundMode;
    newdc->w.backgroundColor  = dc->w.backgroundColor;
    newdc->w.textColor        = dc->w.textColor;
    newdc->w.brushOrgX        = dc->w.brushOrgX;
    newdc->w.brushOrgY        = dc->w.brushOrgY;
    newdc->w.textAlign        = dc->w.textAlign;
    newdc->w.charExtra        = dc->w.charExtra;
    newdc->w.breakTotalExtra  = dc->w.breakTotalExtra;
    newdc->w.breakCount       = dc->w.breakCount;
    newdc->w.breakExtra       = dc->w.breakExtra;
    newdc->w.breakRem         = dc->w.breakRem;
    newdc->w.MapMode          = dc->w.MapMode;
    newdc->w.GraphicsMode     = dc->w.GraphicsMode;
259 260
#if 0
    /* Apparently, the DC origin is not changed by [GS]etDCState */
Alexandre Julliard's avatar
Alexandre Julliard committed
261 262
    newdc->w.DCOrgX           = dc->w.DCOrgX;
    newdc->w.DCOrgY           = dc->w.DCOrgY;
263
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
    newdc->w.CursPosX         = dc->w.CursPosX;
    newdc->w.CursPosY         = dc->w.CursPosY;
    newdc->w.ArcDirection     = dc->w.ArcDirection;
    newdc->w.xformWorld2Wnd   = dc->w.xformWorld2Wnd;
    newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
    newdc->w.xformVport2World = dc->w.xformVport2World;
    newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
    newdc->wndOrgX            = dc->wndOrgX;
    newdc->wndOrgY            = dc->wndOrgY;
    newdc->wndExtX            = dc->wndExtX;
    newdc->wndExtY            = dc->wndExtY;
    newdc->vportOrgX          = dc->vportOrgX;
    newdc->vportOrgY          = dc->vportOrgY;
    newdc->vportExtX          = dc->vportExtX;
    newdc->vportExtY          = dc->vportExtY;
Alexandre Julliard's avatar
Alexandre Julliard committed
279

280
    newdc->hSelf = (HDC)handle;
Alexandre Julliard's avatar
Alexandre Julliard committed
281 282
    newdc->saveLevel = 0;

Alexandre Julliard's avatar
Alexandre Julliard committed
283 284
    PATH_InitGdiPath( &newdc->w.path );
    
285
    newdc->w.pAbortProc = NULL;
286
    newdc->hookThunk  = NULL;
287

Alexandre Julliard's avatar
Alexandre Julliard committed
288 289 290
    /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */

    newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
291 292
    if (dc->w.hClipRgn)
    {
293 294
	newdc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
	CombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
Alexandre Julliard's avatar
Alexandre Julliard committed
295
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
296 297
    else
	newdc->w.hClipRgn = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
298 299
    GDI_HEAP_UNLOCK( handle );
    GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
300 301 302 303 304 305 306
    return handle;
}


/***********************************************************************
 *           SetDCState    (GDI.180)
 */
307
void WINAPI SetDCState16( HDC16 hdc, HDC16 hdcs )
Alexandre Julliard's avatar
Alexandre Julliard committed
308
{
Alexandre Julliard's avatar
Alexandre Julliard committed
309
    DC *dc, *dcs;
Alexandre Julliard's avatar
Alexandre Julliard committed
310
    
Alexandre Julliard's avatar
Alexandre Julliard committed
311
    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
Alexandre Julliard's avatar
Alexandre Julliard committed
312 313 314 315 316 317 318 319 320 321 322
    if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC )))
    {
      GDI_HEAP_UNLOCK( hdc );
      return;
    }
    if (!dcs->w.flags & DC_SAVED)
    {
      GDI_HEAP_UNLOCK( hdc );
      GDI_HEAP_UNLOCK( hdcs );
      return;
    }
323
    TRACE("%04x %04x\n", hdc, hdcs );
Alexandre Julliard's avatar
Alexandre Julliard committed
324

Alexandre Julliard's avatar
Alexandre Julliard committed
325 326 327
    dc->w.flags            = dcs->w.flags & ~DC_SAVED;
    dc->w.devCaps          = dcs->w.devCaps;
    dc->w.hDevice          = dcs->w.hDevice;
328
    dc->w.totalExtent      = dcs->w.totalExtent;
Alexandre Julliard's avatar
Alexandre Julliard committed
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    dc->w.ROPmode          = dcs->w.ROPmode;
    dc->w.polyFillMode     = dcs->w.polyFillMode;
    dc->w.stretchBltMode   = dcs->w.stretchBltMode;
    dc->w.relAbsMode       = dcs->w.relAbsMode;
    dc->w.backgroundMode   = dcs->w.backgroundMode;
    dc->w.backgroundColor  = dcs->w.backgroundColor;
    dc->w.textColor        = dcs->w.textColor;
    dc->w.brushOrgX        = dcs->w.brushOrgX;
    dc->w.brushOrgY        = dcs->w.brushOrgY;
    dc->w.textAlign        = dcs->w.textAlign;
    dc->w.charExtra        = dcs->w.charExtra;
    dc->w.breakTotalExtra  = dcs->w.breakTotalExtra;
    dc->w.breakCount       = dcs->w.breakCount;
    dc->w.breakExtra       = dcs->w.breakExtra;
    dc->w.breakRem         = dcs->w.breakRem;
    dc->w.MapMode          = dcs->w.MapMode;
    dc->w.GraphicsMode     = dcs->w.GraphicsMode;
346 347
#if 0
    /* Apparently, the DC origin is not changed by [GS]etDCState */
Alexandre Julliard's avatar
Alexandre Julliard committed
348 349
    dc->w.DCOrgX           = dcs->w.DCOrgX;
    dc->w.DCOrgY           = dcs->w.DCOrgY;
350
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
    dc->w.CursPosX         = dcs->w.CursPosX;
    dc->w.CursPosY         = dcs->w.CursPosY;
    dc->w.ArcDirection     = dcs->w.ArcDirection;
    dc->w.xformWorld2Wnd   = dcs->w.xformWorld2Wnd;
    dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
    dc->w.xformVport2World = dcs->w.xformVport2World;
    dc->w.vport2WorldValid = dcs->w.vport2WorldValid;

    dc->wndOrgX            = dcs->wndOrgX;
    dc->wndOrgY            = dcs->wndOrgY;
    dc->wndExtX            = dcs->wndExtX;
    dc->wndExtY            = dcs->wndExtY;
    dc->vportOrgX          = dcs->vportOrgX;
    dc->vportOrgY          = dcs->vportOrgY;
    dc->vportExtX          = dcs->vportExtX;
    dc->vportExtY          = dcs->vportExtY;
Alexandre Julliard's avatar
Alexandre Julliard committed
367 368

    if (!(dc->w.flags & DC_MEMORY)) dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
369 370 371

    if (dcs->w.hClipRgn)
    {
372 373
        if (!dc->w.hClipRgn) dc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
        CombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
374 375
    }
    else
376 377
    {
        if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
378
        dc->w.hClipRgn = 0;
379 380
    }
    CLIPPING_UpdateGCRegion( dc );
Alexandre Julliard's avatar
Alexandre Julliard committed
381

382 383 384 385 386 387 388
    SelectObject( hdc, dcs->w.hBitmap );
    SelectObject( hdc, dcs->w.hBrush );
    SelectObject( hdc, dcs->w.hFont );
    SelectObject( hdc, dcs->w.hPen );
    SetBkColor( hdc, dcs->w.backgroundColor);
    SetTextColor( hdc, dcs->w.textColor);
    GDISelectPalette16( hdc, dcs->w.hPalette, FALSE );
Alexandre Julliard's avatar
Alexandre Julliard committed
389 390
    GDI_HEAP_UNLOCK( hdc );
    GDI_HEAP_UNLOCK( hdcs );
Alexandre Julliard's avatar
Alexandre Julliard committed
391 392 393 394
}


/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
395 396
 *           SaveDC16    (GDI.30)
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
397
INT16 WINAPI SaveDC16( HDC16 hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
398
{
399
    return (INT16)SaveDC( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
400 401 402 403
}


/***********************************************************************
404
 *           SaveDC    (GDI32.292)
Alexandre Julliard's avatar
Alexandre Julliard committed
405
 */
406
INT WINAPI SaveDC( HDC hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
407
{
408
    HDC hdcs;
Alexandre Julliard's avatar
Alexandre Julliard committed
409
    DC * dc, * dcs;
410
    INT ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
411

412 413 414 415 416 417
    dc = DC_GetDCPtr( hdc );
    if (!dc) return 0;

    if(dc->funcs->pSaveDC)
        return dc->funcs->pSaveDC( dc );

418
    if (!(hdcs = GetDCState16( hdc )))
Alexandre Julliard's avatar
Alexandre Julliard committed
419 420 421 422 423
    {
      GDI_HEAP_UNLOCK( hdc );
      return 0;
    }
    dcs = (DC *) GDI_HEAP_LOCK( hdcs );
Alexandre Julliard's avatar
Alexandre Julliard committed
424 425 426 427 428 429 430 431 432 433 434

    /* Copy path. The reason why path saving / restoring is in SaveDC/
     * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
     * functions are only in Win16 (which doesn't have paths) and that
     * SetDCState doesn't allow us to signal an error (which can happen
     * when copying paths).
     */
    if (!PATH_AssignGdiPath( &dcs->w.path, &dc->w.path ))
    {
        GDI_HEAP_UNLOCK( hdc );
	GDI_HEAP_UNLOCK( hdcs );
435
	DeleteDC( hdcs );
Alexandre Julliard's avatar
Alexandre Julliard committed
436 437 438
	return 0;
    }
    
Alexandre Julliard's avatar
Alexandre Julliard committed
439 440
    dcs->header.hNext = dc->header.hNext;
    dc->header.hNext = hdcs;
441
    TRACE("(%04x): returning %d\n", hdc, dc->saveLevel+1 );
Alexandre Julliard's avatar
Alexandre Julliard committed
442 443 444 445
    ret = ++dc->saveLevel;
    GDI_HEAP_UNLOCK( hdcs );
    GDI_HEAP_UNLOCK( hdc );
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
446 447 448 449
}


/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
450 451
 *           RestoreDC16    (GDI.39)
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
452
BOOL16 WINAPI RestoreDC16( HDC16 hdc, INT16 level )
Alexandre Julliard's avatar
Alexandre Julliard committed
453
{
454
    return RestoreDC( hdc, level );
Alexandre Julliard's avatar
Alexandre Julliard committed
455 456 457 458
}


/***********************************************************************
459
 *           RestoreDC    (GDI32.290)
Alexandre Julliard's avatar
Alexandre Julliard committed
460
 */
461
BOOL WINAPI RestoreDC( HDC hdc, INT level )
Alexandre Julliard's avatar
Alexandre Julliard committed
462 463
{
    DC * dc, * dcs;
464
    BOOL success;
Alexandre Julliard's avatar
Alexandre Julliard committed
465

466
    TRACE("%04x %d\n", hdc, level );
467 468 469 470 471
    dc = DC_GetDCPtr( hdc );
    if(!dc) return FALSE;
    if(dc->funcs->pRestoreDC)
        return dc->funcs->pRestoreDC( dc, level );

Alexandre Julliard's avatar
Alexandre Julliard committed
472
    if (level == -1) level = dc->saveLevel;
Alexandre Julliard's avatar
Alexandre Julliard committed
473 474 475 476 477
    if ((level < 1) || (level > dc->saveLevel))
    {
      GDI_HEAP_UNLOCK( hdc );
      return FALSE;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
478
    
Alexandre Julliard's avatar
Alexandre Julliard committed
479
    success=TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
480
    while (dc->saveLevel >= level)
Alexandre Julliard's avatar
Alexandre Julliard committed
481
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
482
	HDC16 hdcs = dc->header.hNext;
Alexandre Julliard's avatar
Alexandre Julliard committed
483 484 485 486 487
	if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC )))
	{
	  GDI_HEAP_UNLOCK( hdc );
	  return FALSE;
	}	
Alexandre Julliard's avatar
Alexandre Julliard committed
488
	dc->header.hNext = dcs->header.hNext;
Alexandre Julliard's avatar
Alexandre Julliard committed
489 490
	if (--dc->saveLevel < level)
	{
491
	    SetDCState16( hdc, hdcs );
Alexandre Julliard's avatar
Alexandre Julliard committed
492 493 494 495 496
            if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
		/* FIXME: This might not be quite right, since we're
		 * returning FALSE but still destroying the saved DC state */
	        success=FALSE;
	}
497
	DeleteDC( hdcs );
Alexandre Julliard's avatar
Alexandre Julliard committed
498
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
499
    GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
500
    return success;
Alexandre Julliard's avatar
Alexandre Julliard committed
501 502 503 504
}


/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
505
 *           CreateDC16    (GDI.53)
Alexandre Julliard's avatar
Alexandre Julliard committed
506
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
507
HDC16 WINAPI CreateDC16( LPCSTR driver, LPCSTR device, LPCSTR output,
508
                         const DEVMODEA *initData )
Alexandre Julliard's avatar
Alexandre Julliard committed
509 510
{
    DC * dc;
Alexandre Julliard's avatar
Alexandre Julliard committed
511
    const DC_FUNCTIONS *funcs;
512
    char buf[300];
Alexandre Julliard's avatar
Alexandre Julliard committed
513

514 515 516 517 518 519
    if (device) {
	if(!DRIVER_GetDriverName( device, buf, sizeof(buf) )) return 0;
    } else
        strcpy(buf, driver);

    if (!(funcs = DRIVER_FindDriver( buf ))) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
520 521
    if (!(dc = DC_AllocDC( funcs ))) return 0;
    dc->w.flags = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
522

523
    TRACE("(driver=%s, device=%s, output=%s): returning %04x\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
524
               debugstr_a(driver), debugstr_a(device), debugstr_a(output), dc->hSelf );
Alexandre Julliard's avatar
Alexandre Julliard committed
525 526

    if (dc->funcs->pCreateDC &&
527
        !dc->funcs->pCreateDC( dc, buf, device, output, initData ))
Alexandre Julliard's avatar
Alexandre Julliard committed
528
    {
529
        WARN("creation aborted by device\n" );
Alexandre Julliard's avatar
Alexandre Julliard committed
530
        GDI_HEAP_FREE( dc->hSelf );
Alexandre Julliard's avatar
Alexandre Julliard committed
531 532
        return 0;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
533

Alexandre Julliard's avatar
Alexandre Julliard committed
534
    DC_InitDC( dc );
Alexandre Julliard's avatar
Alexandre Julliard committed
535
    GDI_HEAP_UNLOCK( dc->hSelf );
Alexandre Julliard's avatar
Alexandre Julliard committed
536
    return dc->hSelf;
Alexandre Julliard's avatar
Alexandre Julliard committed
537 538 539
}


Alexandre Julliard's avatar
Alexandre Julliard committed
540
/***********************************************************************
541
 *           CreateDCA    (GDI32.)
Alexandre Julliard's avatar
Alexandre Julliard committed
542
 */
543 544
HDC WINAPI CreateDCA( LPCSTR driver, LPCSTR device, LPCSTR output,
                          const DEVMODEA *initData )
Alexandre Julliard's avatar
Alexandre Julliard committed
545
{
546
    return CreateDC16( driver, device, output, (const DEVMODEA *)initData );
Alexandre Julliard's avatar
Alexandre Julliard committed
547 548 549 550
}


/***********************************************************************
551
 *           CreateDCW    (GDI32.)
Alexandre Julliard's avatar
Alexandre Julliard committed
552
 */
553 554
HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
                          const DEVMODEW *initData )
Alexandre Julliard's avatar
Alexandre Julliard committed
555
{ 
Alexandre Julliard's avatar
Alexandre Julliard committed
556 557 558
    LPSTR driverA = HEAP_strdupWtoA( GetProcessHeap(), 0, driver );
    LPSTR deviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, device );
    LPSTR outputA = HEAP_strdupWtoA( GetProcessHeap(), 0, output );
559
    HDC res = CreateDC16( driverA, deviceA, outputA,
560
                            (const DEVMODEA *)initData /*FIXME*/ );
Alexandre Julliard's avatar
Alexandre Julliard committed
561 562 563
    HeapFree( GetProcessHeap(), 0, driverA );
    HeapFree( GetProcessHeap(), 0, deviceA );
    HeapFree( GetProcessHeap(), 0, outputA );
Alexandre Julliard's avatar
Alexandre Julliard committed
564 565 566 567
    return res;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
568
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
569
 *           CreateIC16    (GDI.153)
Alexandre Julliard's avatar
Alexandre Julliard committed
570
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
571
HDC16 WINAPI CreateIC16( LPCSTR driver, LPCSTR device, LPCSTR output,
572
                         const DEVMODEA* initData )
Alexandre Julliard's avatar
Alexandre Julliard committed
573 574
{
      /* Nothing special yet for ICs */
Alexandre Julliard's avatar
Alexandre Julliard committed
575
    return CreateDC16( driver, device, output, initData );
Alexandre Julliard's avatar
Alexandre Julliard committed
576 577 578
}


Alexandre Julliard's avatar
Alexandre Julliard committed
579
/***********************************************************************
580
 *           CreateICA    (GDI32.49)
Alexandre Julliard's avatar
Alexandre Julliard committed
581
 */
582 583
HDC WINAPI CreateICA( LPCSTR driver, LPCSTR device, LPCSTR output,
                          const DEVMODEA* initData )
Alexandre Julliard's avatar
Alexandre Julliard committed
584 585
{
      /* Nothing special yet for ICs */
586
    return CreateDCA( driver, device, output, initData );
Alexandre Julliard's avatar
Alexandre Julliard committed
587 588 589 590
}


/***********************************************************************
591
 *           CreateICW    (GDI32.50)
Alexandre Julliard's avatar
Alexandre Julliard committed
592
 */
593 594
HDC WINAPI CreateICW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
                          const DEVMODEW* initData )
Alexandre Julliard's avatar
Alexandre Julliard committed
595 596
{
      /* Nothing special yet for ICs */
597
    return CreateDCW( driver, device, output, initData );
Alexandre Julliard's avatar
Alexandre Julliard committed
598 599 600 601 602 603
}


/***********************************************************************
 *           CreateCompatibleDC16    (GDI.52)
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
604
HDC16 WINAPI CreateCompatibleDC16( HDC16 hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
605
{
606
    return (HDC16)CreateCompatibleDC( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
607 608 609 610
}


/***********************************************************************
611
 *           CreateCompatibleDC   (GDI32.31)
Alexandre Julliard's avatar
Alexandre Julliard committed
612
 */
613
HDC WINAPI CreateCompatibleDC( HDC hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
614
{
Alexandre Julliard's avatar
Alexandre Julliard committed
615 616 617 618 619 620
    DC *dc, *origDC;
    const DC_FUNCTIONS *funcs;

    if ((origDC = (DC *)GDI_GetObjPtr( hdc, DC_MAGIC ))) funcs = origDC->funcs;
    else funcs = DRIVER_FindDriver( "DISPLAY" );
    if (!funcs) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
621

Alexandre Julliard's avatar
Alexandre Julliard committed
622
    if (!(dc = DC_AllocDC( funcs ))) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
623

624
    TRACE("(%04x): returning %04x\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
625
               hdc, dc->hSelf );
Alexandre Julliard's avatar
Alexandre Julliard committed
626 627 628

    dc->w.flags        = DC_MEMORY;
    dc->w.bitsPerPixel = 1;
629
    dc->w.hBitmap      = hPseudoStockBitmap;
Alexandre Julliard's avatar
Alexandre Julliard committed
630

631 632 633 634 635 636
    /* Copy the driver-specific physical device info into
     * the new DC. The driver may use this read-only info
     * while creating the compatible DC below. */
    if (origDC)
        dc->physDev = origDC->physDev;

Alexandre Julliard's avatar
Alexandre Julliard committed
637 638
    if (dc->funcs->pCreateDC &&
        !dc->funcs->pCreateDC( dc, NULL, NULL, NULL, NULL ))
Alexandre Julliard's avatar
Alexandre Julliard committed
639
    {
640
        WARN("creation aborted by device\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
641
        GDI_HEAP_FREE( dc->hSelf );
Alexandre Julliard's avatar
Alexandre Julliard committed
642 643
        return 0;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
644

Alexandre Julliard's avatar
Alexandre Julliard committed
645
    DC_InitDC( dc );
Alexandre Julliard's avatar
Alexandre Julliard committed
646
    GDI_HEAP_UNLOCK( dc->hSelf );
Alexandre Julliard's avatar
Alexandre Julliard committed
647
    return dc->hSelf;
Alexandre Julliard's avatar
Alexandre Julliard committed
648 649 650 651
}


/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
652
 *           DeleteDC16    (GDI.68)
Alexandre Julliard's avatar
Alexandre Julliard committed
653
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
654
BOOL16 WINAPI DeleteDC16( HDC16 hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
655
{
656
    return DeleteDC( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
657 658 659 660
}


/***********************************************************************
661
 *           DeleteDC    (GDI32.67)
Alexandre Julliard's avatar
Alexandre Julliard committed
662
 */
663
BOOL WINAPI DeleteDC( HDC hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
664
{
665
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
Alexandre Julliard's avatar
Alexandre Julliard committed
666 667
    if (!dc) return FALSE;

668
    TRACE("%04x\n", hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
669

670
    /* Call hook procedure to check whether is it OK to delete this DC */
671 672
    if (    dc->hookThunk && !(dc->w.flags & (DC_SAVED | DC_MEMORY))
         && dc->hookThunk( hdc, DCHC_DELETEDC, dc->dwHookData, 0 ) == FALSE )
673 674 675 676 677
    {
        GDI_HEAP_UNLOCK( hdc );
        return FALSE;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
678 679 680
    while (dc->saveLevel)
    {
	DC * dcs;
Alexandre Julliard's avatar
Alexandre Julliard committed
681
	HDC16 hdcs = dc->header.hNext;
Alexandre Julliard's avatar
Alexandre Julliard committed
682 683 684
	if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
	dc->header.hNext = dcs->header.hNext;
	dc->saveLevel--;
685
	DeleteDC( hdcs );
Alexandre Julliard's avatar
Alexandre Julliard committed
686 687 688 689
    }
    
    if (!(dc->w.flags & DC_SAVED))
    {
690 691 692
	SelectObject( hdc, STOCK_BLACK_PEN );
	SelectObject( hdc, STOCK_WHITE_BRUSH );
	SelectObject( hdc, STOCK_SYSTEM_FONT );
Alexandre Julliard's avatar
Alexandre Julliard committed
693
        if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc);
Alexandre Julliard's avatar
Alexandre Julliard committed
694
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
695

696 697 698
    if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
    if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
    if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
699
    if (dc->w.pAbortProc) THUNK_Free( (FARPROC)dc->w.pAbortProc );
700
    if (dc->hookThunk) THUNK_Free( (FARPROC)dc->hookThunk );
Alexandre Julliard's avatar
Alexandre Julliard committed
701 702
    PATH_DestroyGdiPath(&dc->w.path);
    
Alexandre Julliard's avatar
Alexandre Julliard committed
703 704 705 706
    return GDI_FreeObject( hdc );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
707
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
708 709
 *           ResetDC16    (GDI.376)
 */
710
HDC16 WINAPI ResetDC16( HDC16 hdc, const DEVMODEA *devmode )
Alexandre Julliard's avatar
Alexandre Julliard committed
711
{
712
    FIXME("stub\n" );
Alexandre Julliard's avatar
Alexandre Julliard committed
713 714 715 716 717
    return hdc;
}


/***********************************************************************
718
 *           ResetDCA    (GDI32.287)
Alexandre Julliard's avatar
Alexandre Julliard committed
719
 */
720
HDC WINAPI ResetDCA( HDC hdc, const DEVMODEA *devmode )
Alexandre Julliard's avatar
Alexandre Julliard committed
721
{
722
    FIXME("stub\n" );
Alexandre Julliard's avatar
Alexandre Julliard committed
723 724 725 726 727
    return hdc;
}


/***********************************************************************
728
 *           ResetDCW    (GDI32.288)
Alexandre Julliard's avatar
Alexandre Julliard committed
729
 */
730
HDC WINAPI ResetDCW( HDC hdc, const DEVMODEW *devmode )
Alexandre Julliard's avatar
Alexandre Julliard committed
731
{
732
    FIXME("stub\n" );
Alexandre Julliard's avatar
Alexandre Julliard committed
733 734 735 736
    return hdc;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
737
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
738
 *           GetDeviceCaps16    (GDI.80)
Alexandre Julliard's avatar
Alexandre Julliard committed
739
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
740
INT16 WINAPI GetDeviceCaps16( HDC16 hdc, INT16 cap )
Alexandre Julliard's avatar
Alexandre Julliard committed
741
{
742
    return GetDeviceCaps( hdc, cap );
Alexandre Julliard's avatar
Alexandre Julliard committed
743 744 745 746
}


/***********************************************************************
747
 *           GetDeviceCaps    (GDI32.171)
Alexandre Julliard's avatar
Alexandre Julliard committed
748
 */
749
INT WINAPI GetDeviceCaps( HDC hdc, INT cap )
Alexandre Julliard's avatar
Alexandre Julliard committed
750 751
{
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
752
    INT ret;
753
    POINT pt;
Alexandre Julliard's avatar
Alexandre Julliard committed
754

Alexandre Julliard's avatar
Alexandre Julliard committed
755 756
    if (!dc) return 0;

757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
    /* Device capabilities for the printer */
    switch (cap)
    {
    case PHYSICALWIDTH:
        if(Escape(hdc, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
	    return pt.x;
    case PHYSICALHEIGHT:
	if(Escape(hdc, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
	    return pt.y;
    case PHYSICALOFFSETX:
	if(Escape(hdc, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
	    return pt.x;
    case PHYSICALOFFSETY:
	if(Escape(hdc, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
	    return pt.y;
    case SCALINGFACTORX:
	if(Escape(hdc, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
	    return pt.x;
    case SCALINGFACTORY:
	if(Escape(hdc, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
	    return pt.y;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
780 781 782 783 784
    if ((cap < 0) || (cap > sizeof(DeviceCaps)-sizeof(WORD)))
    {
      GDI_HEAP_UNLOCK( hdc );
      return 0;
    }
785 786 787 788 789

    if (((cap>=46) && (cap<88)) || ((cap>=92) && (cap<104)))
	FIXME("(%04x,%d): unsupported DeviceCaps capability, will yield 0!\n",
		hdc,cap
	);
790
    TRACE("(%04x,%d): returning %d\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
791
	    hdc, cap, *(WORD *)(((char *)dc->w.devCaps) + cap) );
Alexandre Julliard's avatar
Alexandre Julliard committed
792 793 794
    ret = *(WORD *)(((char *)dc->w.devCaps) + cap);
    GDI_HEAP_UNLOCK( hdc );
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
795 796 797 798
}


/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
799
 *           SetBkColor16    (GDI.1)
Alexandre Julliard's avatar
Alexandre Julliard committed
800
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
801
COLORREF WINAPI SetBkColor16( HDC16 hdc, COLORREF color )
Alexandre Julliard's avatar
Alexandre Julliard committed
802
{
803
    return SetBkColor( hdc, color );
Alexandre Julliard's avatar
Alexandre Julliard committed
804 805 806 807
}


/***********************************************************************
808
 *           SetBkColor    (GDI32.305)
Alexandre Julliard's avatar
Alexandre Julliard committed
809
 */
810
COLORREF WINAPI SetBkColor( HDC hdc, COLORREF color )
Alexandre Julliard's avatar
Alexandre Julliard committed
811 812
{
    COLORREF oldColor;
Alexandre Julliard's avatar
Alexandre Julliard committed
813 814 815 816 817 818 819 820
    DC * dc = DC_GetDCPtr( hdc );
  
    if (!dc) return 0x80000000;
    if (dc->funcs->pSetBkColor)
        oldColor = dc->funcs->pSetBkColor(dc, color);
    else {
	oldColor = dc->w.backgroundColor;
	dc->w.backgroundColor = color;
Alexandre Julliard's avatar
Alexandre Julliard committed
821
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
822
    GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
823 824 825 826 827
    return oldColor;
}


/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
828 829
 *           SetTextColor16    (GDI.9)
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
830
COLORREF WINAPI SetTextColor16( HDC16 hdc, COLORREF color )
Alexandre Julliard's avatar
Alexandre Julliard committed
831
{
832
    return SetTextColor( hdc, color );
Alexandre Julliard's avatar
Alexandre Julliard committed
833 834 835 836
}


/***********************************************************************
837
 *           SetTextColor    (GDI32.338)
Alexandre Julliard's avatar
Alexandre Julliard committed
838
 */
839
COLORREF WINAPI SetTextColor( HDC hdc, COLORREF color )
Alexandre Julliard's avatar
Alexandre Julliard committed
840 841
{
    COLORREF oldColor;
Alexandre Julliard's avatar
Alexandre Julliard committed
842 843 844 845 846 847 848 849
    DC * dc = DC_GetDCPtr( hdc );
  
    if (!dc) return 0x80000000;
    if (dc->funcs->pSetTextColor)
        oldColor = dc->funcs->pSetTextColor(dc, color);
    else {
	oldColor = dc->w.textColor;
	dc->w.textColor = color;
Alexandre Julliard's avatar
Alexandre Julliard committed
850
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
851
    GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
852 853 854
    return oldColor;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
855
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
856
 *           SetTextAlign16    (GDI.346)
Alexandre Julliard's avatar
Alexandre Julliard committed
857
 */
858
UINT16 WINAPI SetTextAlign16( HDC16 hdc, UINT16 align )
Alexandre Julliard's avatar
Alexandre Julliard committed
859
{
860
    return SetTextAlign( hdc, align );
Alexandre Julliard's avatar
Alexandre Julliard committed
861 862 863 864
}


/***********************************************************************
865
 *           SetTextAlign    (GDI32.336)
Alexandre Julliard's avatar
Alexandre Julliard committed
866
 */
867
UINT WINAPI SetTextAlign( HDC hdc, UINT align )
Alexandre Julliard's avatar
Alexandre Julliard committed
868
{
869
    UINT prevAlign;
870 871 872 873 874 875 876
    DC *dc = DC_GetDCPtr( hdc );
    if (!dc) return 0x0;
    if (dc->funcs->pSetTextAlign)
        prevAlign = dc->funcs->pSetTextAlign(dc, align);
    else {
	prevAlign = dc->w.textAlign;
	dc->w.textAlign = align;
Alexandre Julliard's avatar
Alexandre Julliard committed
877
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
878
    GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
879 880 881
    return prevAlign;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
882 883 884
/***********************************************************************
 *           GetDCOrgEx  (GDI32.168)
 */
885
BOOL WINAPI GetDCOrgEx( HDC hDC, LPPOINT lpp )
Alexandre Julliard's avatar
Alexandre Julliard committed
886
{
Alexandre Julliard's avatar
Alexandre Julliard committed
887
    DC * dc;
888

Alexandre Julliard's avatar
Alexandre Julliard committed
889 890
    if (!lpp) return FALSE;
    if (!(dc = (DC *) GDI_GetObjPtr( hDC, DC_MAGIC ))) return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
891

892 893 894 895
    lpp->x = lpp->y = 0;
    if (dc->funcs->pGetDCOrgEx) dc->funcs->pGetDCOrgEx( dc, lpp );
    lpp->x += dc->w.DCOrgX;
    lpp->y += dc->w.DCOrgY;
Alexandre Julliard's avatar
Alexandre Julliard committed
896
    GDI_HEAP_UNLOCK( hDC );
Alexandre Julliard's avatar
Alexandre Julliard committed
897 898 899 900
    return TRUE;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
901 902 903
/***********************************************************************
 *           GetDCOrg    (GDI.79)
 */
904
DWORD WINAPI GetDCOrg16( HDC16 hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
905
{
906
    POINT	pt;
Alexandre Julliard's avatar
Alexandre Julliard committed
907 908 909
    if( GetDCOrgEx( hdc, &pt) )
  	return MAKELONG( (WORD)pt.x, (WORD)pt.y );    
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
910 911 912
}


Alexandre Julliard's avatar
Alexandre Julliard committed
913 914 915
/***********************************************************************
 *           SetDCOrg    (GDI.117)
 */
916
DWORD WINAPI SetDCOrg16( HDC16 hdc, INT16 x, INT16 y )
Alexandre Julliard's avatar
Alexandre Julliard committed
917 918 919 920 921 922 923
{
    DWORD prevOrg;
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
    if (!dc) return 0;
    prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
    dc->w.DCOrgX = x;
    dc->w.DCOrgY = y;
Alexandre Julliard's avatar
Alexandre Julliard committed
924
    GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
925 926
    return prevOrg;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
927 928


Alexandre Julliard's avatar
Alexandre Julliard committed
929 930 931
/***********************************************************************
 *           GetGraphicsMode    (GDI32.188)
 */
932
INT WINAPI GetGraphicsMode( HDC hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
933 934 935 936 937 938 939 940 941 942
{
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
    if (!dc) return 0;
    return dc->w.GraphicsMode;
}


/***********************************************************************
 *           SetGraphicsMode    (GDI32.317)
 */
943
INT WINAPI SetGraphicsMode( HDC hdc, INT mode )
Alexandre Julliard's avatar
Alexandre Julliard committed
944
{
945
    INT ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
946
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
Alexandre Julliard's avatar
Alexandre Julliard committed
947 948 949 950 951 952 953

    /* One would think that setting the graphics mode to GM_COMPATIBLE
     * would also reset the world transformation matrix to the unity
     * matrix. However, in Windows, this is not the case. This doesn't
     * make a lot of sense to me, but that's the way it is.
     */
    
Alexandre Julliard's avatar
Alexandre Julliard committed
954 955 956 957 958 959 960 961
    if (!dc) return 0;
    if ((mode <= 0) || (mode > GM_LAST)) return 0;
    ret = dc->w.GraphicsMode;
    dc->w.GraphicsMode = mode;
    return ret;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
962 963 964 965 966
/***********************************************************************
 *           GetArcDirection16    (GDI.524)
 */
INT16 WINAPI GetArcDirection16( HDC16 hdc )
{
967
    return GetArcDirection( (HDC)hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
968 969 970 971
}


/***********************************************************************
972
 *           GetArcDirection    (GDI32.141)
Alexandre Julliard's avatar
Alexandre Julliard committed
973
 */
974
INT WINAPI GetArcDirection( HDC hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
{
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
    
    if (!dc)
        return 0;

    return dc->w.ArcDirection;
}


/***********************************************************************
 *           SetArcDirection16    (GDI.525)
 */
INT16 WINAPI SetArcDirection16( HDC16 hdc, INT16 nDirection )
{
990
    return SetArcDirection( (HDC)hdc, (INT)nDirection );
Alexandre Julliard's avatar
Alexandre Julliard committed
991 992 993 994
}


/***********************************************************************
995
 *           SetArcDirection    (GDI32.302)
Alexandre Julliard's avatar
Alexandre Julliard committed
996
 */
997
INT WINAPI SetArcDirection( HDC hdc, INT nDirection )
Alexandre Julliard's avatar
Alexandre Julliard committed
998 999
{
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1000
    INT nOldDirection;
Alexandre Julliard's avatar
Alexandre Julliard committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
    
    if (!dc)
        return 0;

    if (nDirection!=AD_COUNTERCLOCKWISE && nDirection!=AD_CLOCKWISE)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
	return 0;
    }

    nOldDirection = dc->w.ArcDirection;
    dc->w.ArcDirection = nDirection;

    return nOldDirection;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1018 1019 1020
/***********************************************************************
 *           GetWorldTransform    (GDI32.244)
 */
1021
BOOL WINAPI GetWorldTransform( HDC hdc, LPXFORM xform )
Alexandre Julliard's avatar
Alexandre Julliard committed
1022
{
Alexandre Julliard's avatar
Alexandre Julliard committed
1023 1024 1025 1026 1027 1028 1029
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
    
    if (!dc)
        return FALSE;
    if (!xform)
	return FALSE;

Alexandre Julliard's avatar
Alexandre Julliard committed
1030
    *xform = dc->w.xformWorld2Wnd;
Alexandre Julliard's avatar
Alexandre Julliard committed
1031 1032 1033 1034 1035 1036 1037 1038
    
    return TRUE;
}


/***********************************************************************
 *           SetWorldTransform    (GDI32.346)
 */
1039
BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
Alexandre Julliard's avatar
Alexandre Julliard committed
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
{
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
    
    if (!dc)
    {
        SetLastError( ERROR_INVALID_HANDLE );
        return FALSE;
    }

    if (!xform)
	return FALSE;
    
    /* Check that graphics mode is GM_ADVANCED */
    if (dc->w.GraphicsMode!=GM_ADVANCED)
       return FALSE;

Alexandre Julliard's avatar
Alexandre Julliard committed
1056 1057 1058
    dc->w.xformWorld2Wnd = *xform;
    
    DC_UpdateXforms( dc );
Alexandre Julliard's avatar
Alexandre Julliard committed
1059

Alexandre Julliard's avatar
Alexandre Julliard committed
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
    return TRUE;
}


/****************************************************************************
 * ModifyWorldTransform [GDI32.253]
 * Modifies the world transformation for a device context.
 *
 * PARAMS
 *    hdc   [I] Handle to device context
 *    xform [I] XFORM structure that will be used to modify the world
 *              transformation
 *    iMode [I] Specifies in what way to modify the world transformation
 *              Possible values:
 *              MWT_IDENTITY
 *                 Resets the world transformation to the identity matrix.
 *                 The parameter xform is ignored.
 *              MWT_LEFTMULTIPLY
 *                 Multiplies xform into the world transformation matrix from
 *                 the left.
 *              MWT_RIGHTMULTIPLY
 *                 Multiplies xform into the world transformation matrix from
 *                 the right.
 *
 * RETURNS STD
 */
1086
BOOL WINAPI ModifyWorldTransform( HDC hdc, const XFORM *xform,
Alexandre Julliard's avatar
Alexandre Julliard committed
1087 1088 1089
    DWORD iMode )
{
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
Alexandre Julliard's avatar
Alexandre Julliard committed
1090
    
Alexandre Julliard's avatar
Alexandre Julliard committed
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145
    /* Check for illegal parameters */
    if (!dc)
    {
        SetLastError( ERROR_INVALID_HANDLE );
        return FALSE;
    }
    if (!xform)
	return FALSE;
    
    /* Check that graphics mode is GM_ADVANCED */
    if (dc->w.GraphicsMode!=GM_ADVANCED)
       return FALSE;
       
    switch (iMode)
    {
        case MWT_IDENTITY:
	    dc->w.xformWorld2Wnd.eM11 = 1.0f;
	    dc->w.xformWorld2Wnd.eM12 = 0.0f;
	    dc->w.xformWorld2Wnd.eM21 = 0.0f;
	    dc->w.xformWorld2Wnd.eM22 = 1.0f;
	    dc->w.xformWorld2Wnd.eDx  = 0.0f;
	    dc->w.xformWorld2Wnd.eDy  = 0.0f;
	    break;
        case MWT_LEFTMULTIPLY:
	    CombineTransform( &dc->w.xformWorld2Wnd, xform,
	        &dc->w.xformWorld2Wnd );
	    break;
	case MWT_RIGHTMULTIPLY:
	    CombineTransform( &dc->w.xformWorld2Wnd, &dc->w.xformWorld2Wnd,
	        xform );
	    break;
        default:
	    return FALSE;
    }

    DC_UpdateXforms( dc );

    return TRUE;
}


/****************************************************************************
 * CombineTransform [GDI32.20]
 * Combines two transformation matrices.
 *
 * PARAMS
 *    xformResult [O] Stores the result of combining the two matrices
 *    xform1      [I] Specifies the first matrix to apply
 *    xform2      [I] Specifies the second matrix to apply
 *
 * REMARKS
 *    The same matrix can be passed in for more than one of the parameters.
 *
 * RETURNS STD
 */
1146
BOOL WINAPI CombineTransform( LPXFORM xformResult, const XFORM *xform1,
Alexandre Julliard's avatar
Alexandre Julliard committed
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
    const XFORM *xform2 )
{
    XFORM xformTemp;
    
    /* Check for illegal parameters */
    if (!xformResult || !xform1 || !xform2)
        return FALSE;

    /* Create the result in a temporary XFORM, since xformResult may be
     * equal to xform1 or xform2 */
    xformTemp.eM11 = xform1->eM11 * xform2->eM11 +
                     xform1->eM12 * xform2->eM21;
    xformTemp.eM12 = xform1->eM11 * xform2->eM12 +
                     xform1->eM12 * xform2->eM22;
    xformTemp.eM21 = xform1->eM21 * xform2->eM11 +
                     xform1->eM22 * xform2->eM21;
    xformTemp.eM22 = xform1->eM21 * xform2->eM12 +
                     xform1->eM22 * xform2->eM22;
    xformTemp.eDx  = xform1->eDx  * xform2->eM11 +
                     xform1->eDy  * xform2->eM21 +
                     xform2->eDx;
    xformTemp.eDy  = xform1->eDx  * xform2->eM12 +
                     xform1->eDy  * xform2->eM22 +
                     xform2->eDy;

    /* Copy the result to xformResult */
    *xformResult = xformTemp;

Alexandre Julliard's avatar
Alexandre Julliard committed
1175
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1176 1177 1178
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1179 1180 1181
/***********************************************************************
 *           SetDCHook   (GDI.190)
 */
1182 1183 1184
/* ### start build ### */
extern WORD CALLBACK GDI_CallTo16_word_wwll(FARPROC16,WORD,WORD,LONG,LONG);
/* ### stop build ### */
Alexandre Julliard's avatar
Alexandre Julliard committed
1185
BOOL16 WINAPI SetDCHook( HDC16 hdc, FARPROC16 hookProc, DWORD dwHookData )
Alexandre Julliard's avatar
Alexandre Julliard committed
1186
{
Alexandre Julliard's avatar
Alexandre Julliard committed
1187
    DC *dc = (DC *)GDI_GetObjPtr( hdc, DC_MAGIC );
1188
    if (!dc) return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1189

1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
    /*
     * Note: We store the original SEGPTR 'hookProc' as we need to be
     *       able to return it verbatim in GetDCHook,
     *
     *       On the other hand, we still call THUNK_Alloc and store the
     *       32-bit thunk into another DC member, because THUNK_Alloc
     *       recognizes the (typical) case that the 'hookProc' is indeed
     *       the 16-bit API entry point of a built-in routine (e.g. DCHook16)
     *
     *       We could perform that test every time the hook is about to
     *       be called (or else we could live with the 32->16->32 detour),
     *       but this way is the most efficient ...
     */
Alexandre Julliard's avatar
Alexandre Julliard committed
1203 1204 1205

    dc->hookProc = hookProc;
    dc->dwHookData = dwHookData;
1206 1207 1208 1209 1210

    THUNK_Free( (FARPROC)dc->hookThunk );
    dc->hookThunk = (DCHOOKPROC)
                    THUNK_Alloc( hookProc, (RELAY)GDI_CallTo16_word_wwll );

Alexandre Julliard's avatar
Alexandre Julliard committed
1211
    GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
1212 1213 1214 1215 1216 1217 1218
    return TRUE;
}


/***********************************************************************
 *           GetDCHook   (GDI.191)
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
1219
DWORD WINAPI GetDCHook( HDC16 hdc, FARPROC16 *phookProc )
Alexandre Julliard's avatar
Alexandre Julliard committed
1220
{
Alexandre Julliard's avatar
Alexandre Julliard committed
1221
    DC *dc = (DC *)GDI_GetObjPtr( hdc, DC_MAGIC );
Alexandre Julliard's avatar
Alexandre Julliard committed
1222 1223
    if (!dc) return 0;
    *phookProc = dc->hookProc;
Alexandre Julliard's avatar
Alexandre Julliard committed
1224
    GDI_HEAP_UNLOCK( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
1225 1226 1227 1228 1229 1230 1231
    return dc->dwHookData;
}


/***********************************************************************
 *           SetHookFlags       (GDI.192)
 */
1232
WORD WINAPI SetHookFlags16(HDC16 hDC, WORD flags)
Alexandre Julliard's avatar
Alexandre Julliard committed
1233
{
Alexandre Julliard's avatar
Alexandre Julliard committed
1234
    DC* dc = (DC*)GDI_GetObjPtr( hDC, DC_MAGIC );
Alexandre Julliard's avatar
Alexandre Julliard committed
1235

Alexandre Julliard's avatar
Alexandre Julliard committed
1236
    if( dc )
Alexandre Julliard's avatar
Alexandre Julliard committed
1237 1238 1239
    {
        WORD wRet = dc->w.flags & DC_DIRTY;

Alexandre Julliard's avatar
Alexandre Julliard committed
1240
        /* "Undocumented Windows" info is slightly confusing.
Alexandre Julliard's avatar
Alexandre Julliard committed
1241 1242
         */

1243
        TRACE("hDC %04x, flags %04x\n",hDC,flags);
Alexandre Julliard's avatar
Alexandre Julliard committed
1244 1245 1246 1247 1248

        if( flags & DCHF_INVALIDATEVISRGN )
            dc->w.flags |= DC_DIRTY;
        else if( flags & DCHF_VALIDATEVISRGN || !flags )
            dc->w.flags &= ~DC_DIRTY;
Alexandre Julliard's avatar
Alexandre Julliard committed
1249
	GDI_HEAP_UNLOCK( hDC );
Alexandre Julliard's avatar
Alexandre Julliard committed
1250 1251
        return wRet;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1252
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
1253 1254
}

Alexandre Julliard's avatar
Alexandre Julliard committed
1255 1256 1257
/***********************************************************************
 *           SetICMMode    (GDI32.318)
 */
1258
INT WINAPI SetICMMode(HDC hdc, INT iEnableICM)
Alexandre Julliard's avatar
Alexandre Julliard committed
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270
{
/*FIXME  Asuming that ICM is always off, and cannot be turned on */
    if (iEnableICM == ICM_OFF) return ICM_OFF;
    if (iEnableICM == ICM_ON) return 0;
    if (iEnableICM == ICM_QUERY) return ICM_OFF;
    return 0;
}


/***********************************************************************
 *           GetColorSpace    (GDI32.165)
 */
1271
HCOLORSPACE WINAPI GetColorSpace(HDC hdc)
Alexandre Julliard's avatar
Alexandre Julliard committed
1272 1273 1274 1275
{
/*FIXME    Need to to whatever GetColorSpace actually does */
    return 0;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
1276

1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
/***********************************************************************
 *           CreateColorSpaceA    (GDI32.???)
 */
HCOLORSPACE WINAPI CreateColorSpaceA( LPLOGCOLORSPACEA lpLogColorSpace )
{
  FIXME( "stub\n" );
  return 0; 
}

/***********************************************************************
 *           CreateColorSpaceW    (GDI32.???)
 */
HCOLORSPACE WINAPI CreateColorSpaceW( LPLOGCOLORSPACEW lpLogColorSpace )
{
  FIXME( "stub\n" );
  return 0;
}

/***********************************************************************
 *           DeleteColorSpace     (GDI32.???)
 */
BOOL WINAPI DeleteColorSpace( HCOLORSPACE hColorSpace )
{
  FIXME( "stub\n" );
  
1302
  return TRUE;
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314
}

/***********************************************************************
 *           SetColorSpace     (GDI32.???)
 */
HCOLORSPACE WINAPI SetColorSpace( HDC hDC, HCOLORSPACE hColorSpace )
{
  FIXME( "stub\n" );

  return hColorSpace;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
1315 1316 1317 1318 1319
/***********************************************************************
 *           GetBoundsRect16    (GDI.194)
 */
UINT16 WINAPI GetBoundsRect16(HDC16 hdc, LPRECT16 rect, UINT16 flags)
{
1320
    return DCB_RESET | DCB_DISABLE; /* bounding rectangle always empty and disabled*/
Alexandre Julliard's avatar
Alexandre Julliard committed
1321 1322
}

1323
/***********************************************************************
1324
 *           GetBoundsRect    (GDI32.147)
1325
 */
1326
UINT WINAPI GetBoundsRect(HDC hdc, LPRECT rect, UINT flags)
1327
{
1328
    FIXME("(): stub\n");
1329 1330 1331
    return DCB_RESET;   /* bounding rectangle always empty */
}
 
1332 1333 1334
/***********************************************************************
 *           SetBoundsRect16    (GDI.193)
 */
1335
UINT16 WINAPI SetBoundsRect16(HDC16 hdc, const RECT16* rect, UINT16 flags)
1336
{
1337
    if ( (flags & DCB_ACCUMULATE) || (flags & DCB_ENABLE) )
1338
        FIXME("(%04x, %p, %04x): stub\n", hdc, rect, flags );
1339 1340

    return DCB_RESET | DCB_DISABLE; /* bounding rectangle always empty and disabled*/
1341 1342
}

1343
/***********************************************************************
1344
 *           SetBoundsRect    (GDI32.307)
1345
 */
1346
UINT WINAPI SetBoundsRect(HDC hdc, const RECT* rect, UINT flags)
1347
{
1348
    FIXME("(): stub\n");
1349 1350 1351
    return DCB_DISABLE;   /* bounding rectangle always empty */
}

1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362

/***********************************************************************
 *		GetRelAbs		(GDI32.218)
 */
INT WINAPI GetRelAbs( HDC hdc, DWORD dwIgnore )
{
    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
    if (!dc) return 0;
    return dc->w.relAbsMode;
}

1363 1364 1365 1366 1367 1368 1369
/***********************************************************************
 *           Death    (GDI.121)
 *
 * Disables GDI, switches back to text mode.
 * We don't have to do anything here,
 * just let console support handle everything
 */
1370
void WINAPI Death16(HDC16 hDC)
1371
{
1372
    MESSAGE("Death(%04x) called. Application enters text mode...\n", hDC);
1373 1374 1375 1376 1377 1378 1379
}

/***********************************************************************
 *           Resurrection    (GDI.122)
 *
 * Restores GDI functionality
 */
1380
void WINAPI Resurrection16(HDC16 hDC,
1381 1382
                           WORD w1, WORD w2, WORD w3, WORD w4, WORD w5, WORD w6)
{
1383
    MESSAGE("Resurrection(%04x, %04x, %04x, %04x, %04x, %04x, %04x) called. Application left text mode.\n", hDC, w1, w2, w3, w4, w5, w6);
1384
}
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412

/***********************************************************************
 *           GetLayout    (GDI32.321)
 *
 * Gets left->right or right->left text layout flags of a dc.
 * win98 just returns 0 and sets ERROR_CALL_NOT_IMPLEMENTED so we do the same
 *
 */
DWORD WINAPI GetLayout(HDC hdc)
{
    FIXME("(%08x): stub\n", hdc);
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return 0;
}

/***********************************************************************
 *           SetLayout    (GDI32.450)
 *
 * Sets left->right or right->left text layout flags of a dc.
 * win98 just returns 0 and sets ERROR_CALL_NOT_IMPLEMENTED so we do the same
 *
 */
DWORD WINAPI SetLayout(HDC hdc, DWORD layout)
{
    FIXME("(%08x,%08lx): stub\n", hdc, layout);
    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    return 0;
}