Release 950901
[wine] / objects / dc.c
1 /*
2  * GDI Device Context functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  */
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include "gdi.h"
11 #include "bitmap.h"
12 #include "metafile.h"
13 #include "stddebug.h"
14 #include "color.h"
15 #include "debug.h"
16 #include "font.h"
17
18 static DeviceCaps * displayDevCaps = NULL;
19
20 extern void CLIPPING_UpdateGCRegion( DC * dc );     /* objects/clipping.c */
21
22   /* Default DC values */
23 static const WIN_DC_INFO DC_defaultValues =
24 {
25     0,                      /* flags */
26     NULL,                   /* devCaps */
27     0,                      /* hMetaFile */
28     0,                      /* hClipRgn */
29     0,                      /* hVisRgn */
30     0,                      /* hGCClipRgn */
31     STOCK_BLACK_PEN,        /* hPen */
32     STOCK_WHITE_BRUSH,      /* hBrush */
33     STOCK_SYSTEM_FONT,      /* hFont */
34     0,                      /* hBitmap */
35     0,                      /* hFirstBitmap */
36     0,                      /* hDevice */
37     STOCK_DEFAULT_PALETTE,  /* hPalette */
38     R2_COPYPEN,             /* ROPmode */
39     ALTERNATE,              /* polyFillMode */
40     BLACKONWHITE,           /* stretchBltMode */
41     ABSOLUTE,               /* relAbsMode */
42     OPAQUE,                 /* backgroundMode */
43     RGB( 255, 255, 255 ),   /* backgroundColor */
44     RGB( 0, 0, 0 ),         /* textColor */
45     0,                      /* backgroundPixel */
46     0,                      /* textPixel */
47     0,                      /* brushOrgX */
48     0,                      /* brushOrgY */
49     TA_LEFT | TA_TOP | TA_NOUPDATECP,  /* textAlign */
50     0,                      /* charExtra */
51     0,                      /* breakTotalExtra */
52     0,                      /* breakCount */
53     0,                      /* breakExtra */
54     0,                      /* breakRem */
55     1,                      /* bitsPerPixel */
56     MM_TEXT,                /* MapMode */
57     0,                      /* DCOrgX */
58     0,                      /* DCOrgY */
59     0,                      /* CursPosX */
60     0,                      /* CursPosY */
61     0,                      /* WndOrgX */
62     0,                      /* WndOrgY */
63     1,                      /* WndExtX */
64     1,                      /* WndExtY */
65     0,                      /* VportOrgX */
66     0,                      /* VportOrgY */
67     1,                      /* VportExtX */
68     1                       /* VportExtY */
69 };
70
71   /* ROP code to GC function conversion */
72 const int DC_XROPfunction[16] =
73 {
74     GXclear,        /* R2_BLACK */
75     GXnor,          /* R2_NOTMERGEPEN */
76     GXandInverted,  /* R2_MASKNOTPEN */
77     GXcopyInverted, /* R2_NOTCOPYPEN */
78     GXandReverse,   /* R2_MASKPENNOT */
79     GXinvert,       /* R2_NOT */
80     GXxor,          /* R2_XORPEN */
81     GXnand,         /* R2_NOTMASKPEN */
82     GXand,          /* R2_MASKPEN */
83     GXequiv,        /* R2_NOTXORPEN */
84     GXnoop,         /* R2_NOP */
85     GXorInverted,   /* R2_MERGENOTPEN */
86     GXcopy,         /* R2_COPYPEN */
87     GXorReverse,    /* R2_MERGEPENNOT */
88     GXor,           /* R2_MERGEPEN */
89     GXset           /* R2_WHITE */
90 };
91
92
93 /***********************************************************************
94  *           DC_FillDevCaps
95  *
96  * Fill the device caps structure.
97  */
98 void DC_FillDevCaps( DeviceCaps * caps )
99 {
100     caps->version       = 0x300; 
101     caps->technology    = DT_RASDISPLAY;
102     caps->horzSize      = WidthMMOfScreen(screen) * screenWidth / WidthOfScreen(screen);
103     caps->vertSize      = HeightMMOfScreen(screen) * screenHeight / HeightOfScreen(screen);
104     caps->horzRes       = screenWidth;
105     caps->vertRes       = screenHeight;
106     caps->bitsPixel     = screenDepth;
107     caps->planes        = 1;
108     caps->numBrushes    = 0;
109     caps->numPens       = 0;
110     caps->numMarkers    = 0;
111     caps->numFonts      = 0;
112     caps->numColors     = 1 << caps->bitsPixel;
113     caps->pdeviceSize   = 0;
114     caps->curveCaps     = CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES |
115                           CC_WIDE | CC_STYLED | CC_WIDESTYLED | 
116                           CC_INTERIORS | CC_ROUNDRECT;
117     caps->lineCaps      = LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
118                           LC_STYLED | LC_WIDESTYLED | LC_INTERIORS;
119     caps->polygonalCaps = PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON |
120                           PC_SCANLINE | PC_WIDE | PC_STYLED | 
121                           PC_WIDESTYLED | PC_INTERIORS;
122     caps->textCaps      = TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
123                           TC_IA_ABLE | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE;
124     caps->clipCaps      = CP_REGION;
125     caps->rasterCaps    = RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 |
126                           RC_DI_BITMAP | RC_PALETTE | RC_DIBTODEV | RC_BIGFONT|
127                           RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS;
128     caps->aspectX       = 36;  /* ?? */
129     caps->aspectY       = 36;  /* ?? */
130     caps->aspectXY      = 51;
131     caps->logPixelsX    = (int)(caps->horzRes * 25.4 / caps->horzSize);
132     caps->logPixelsY    = (int)(caps->vertRes * 25.4 / caps->vertSize);
133     caps->sizePalette   = DefaultVisual(display,DefaultScreen(display))->map_entries;
134     caps->numReserved   = 0;
135     caps->colorRes      = 0;
136 }
137
138
139 /***********************************************************************
140  *           DC_InitDC
141  *
142  * Setup device-specific DC values for a newly created DC.
143  */
144 void DC_InitDC( HDC hdc )
145 {
146     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
147     RealizeDefaultPalette( hdc );
148     SetTextColor( hdc, dc->w.textColor );
149     SetBkColor( hdc, dc->w.backgroundColor );
150     SelectObject( hdc, dc->w.hPen );
151     SelectObject( hdc, dc->w.hBrush );
152     SelectObject( hdc, dc->w.hFont );
153     XSetGraphicsExposures( display, dc->u.x.gc, False );
154     XSetSubwindowMode( display, dc->u.x.gc, IncludeInferiors );
155     CLIPPING_UpdateGCRegion( dc );
156 }
157
158
159 /***********************************************************************
160  *           DC_SetupDCForPatBlt
161  *
162  * Setup the GC for a PatBlt operation using current brush.
163  * If fMapColors is TRUE, X pixels are mapped to Windows colors.
164  * Return FALSE if brush is BS_NULL, TRUE otherwise.
165  */
166 BOOL DC_SetupGCForPatBlt( DC * dc, GC gc, BOOL fMapColors )
167 {
168     XGCValues val;
169     unsigned long mask;
170     Pixmap pixmap = 0;
171
172     if (dc->u.x.brush.style == BS_NULL) return FALSE;
173     if (dc->u.x.brush.pixel == -1)
174     {
175         /* Special case used for monochrome pattern brushes.
176          * We need to swap foreground and background because
177          * Windows does it the wrong way...
178          */
179         val.foreground = dc->w.backgroundPixel;
180         val.background = dc->w.textPixel;
181     }
182     else
183     {
184         val.foreground = dc->u.x.brush.pixel;
185         val.background = dc->w.backgroundPixel;
186     }
187     if (fMapColors && COLOR_PixelToPalette)
188     {
189         val.foreground = COLOR_PixelToPalette[val.foreground];
190         val.background = COLOR_PixelToPalette[val.background];
191     }
192
193     val.function = DC_XROPfunction[dc->w.ROPmode-1];
194     val.fill_style = dc->u.x.brush.fillStyle;
195     switch(val.fill_style)
196     {
197     case FillStippled:
198     case FillOpaqueStippled:
199         if (dc->w.backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
200         val.stipple = dc->u.x.brush.pixmap;
201         mask = GCStipple;
202         break;
203
204     case FillTiled:
205         if (fMapColors && COLOR_PixelToPalette)
206         {
207             register int x, y;
208             XImage *image;
209             pixmap = XCreatePixmap( display, rootWindow, 8, 8, screenDepth );
210             image = XGetImage( display, dc->u.x.brush.pixmap, 0, 0, 8, 8,
211                                AllPlanes, ZPixmap );
212             for (y = 0; y < 8; y++)
213                 for (x = 0; x < 8; x++)
214                     XPutPixel( image, x, y,
215                                COLOR_PixelToPalette[XGetPixel( image, x, y)] );
216             XPutImage( display, pixmap, gc, image, 0, 0, 0, 0, 8, 8 );
217             XDestroyImage( image );
218             val.tile = pixmap;
219         }
220         else val.tile = dc->u.x.brush.pixmap;
221         mask = GCTile;
222         break;
223
224     default:
225         mask = 0;
226         break;
227     }
228     val.ts_x_origin = dc->w.DCOrgX + dc->w.brushOrgX;
229     val.ts_y_origin = dc->w.DCOrgY + dc->w.brushOrgY;
230     val.fill_rule = (dc->w.polyFillMode==WINDING) ? WindingRule : EvenOddRule;
231     XChangeGC( display, gc, 
232                GCFunction | GCForeground | GCBackground | GCFillStyle |
233                GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
234                &val );
235     if (pixmap) XFreePixmap( display, pixmap );
236     return TRUE;
237 }
238
239
240 /***********************************************************************
241  *           DC_SetupDCForBrush
242  *
243  * Setup dc->u.x.gc for drawing operations using current brush.
244  * Return FALSE if brush is BS_NULL, TRUE otherwise.
245  */
246 BOOL DC_SetupGCForBrush( DC * dc )
247 {
248     return DC_SetupGCForPatBlt( dc, dc->u.x.gc, FALSE );
249 }
250
251
252 /***********************************************************************
253  *           DC_SetupDCForPen
254  *
255  * Setup dc->u.x.gc for drawing operations using current pen.
256  * Return FALSE if pen is PS_NULL, TRUE otherwise.
257  */
258 BOOL DC_SetupGCForPen( DC * dc )
259 {
260     XGCValues val;
261
262     if (dc->u.x.pen.style == PS_NULL) return FALSE;
263
264     if ((screenDepth <= 8) &&  /* FIXME: Should check for palette instead */
265         ((dc->w.ROPmode == R2_BLACK) || (dc->w.ROPmode == R2_WHITE)))
266     {
267         val.function   = GXcopy;
268         val.foreground = COLOR_ToPhysical( NULL, (dc->w.ROPmode == R2_BLACK) ?
269                                                RGB(0,0,0) : RGB(255,255,255) );
270     }
271     else
272     {
273         val.function   = DC_XROPfunction[dc->w.ROPmode-1];
274         val.foreground = dc->u.x.pen.pixel;
275     }
276     val.background = dc->w.backgroundPixel;
277     val.fill_style = FillSolid;
278     if ((dc->u.x.pen.style!=PS_SOLID) && (dc->u.x.pen.style!=PS_INSIDEFRAME))
279     {
280         XSetDashes( display, dc->u.x.gc, 0,
281                     dc->u.x.pen.dashes, dc->u.x.pen.dash_len );
282         val.line_style = (dc->w.backgroundMode == OPAQUE) ?
283                               LineDoubleDash : LineOnOffDash;
284     }
285     else val.line_style = LineSolid;
286     val.line_width = dc->u.x.pen.width;
287     val.cap_style  = CapRound;
288     val.join_style = JoinBevel;
289     XChangeGC( display, dc->u.x.gc, 
290                GCFunction | GCForeground | GCBackground | GCLineWidth |
291                GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
292     return TRUE;
293 }
294
295
296 /***********************************************************************
297  *           DC_SetupGCForText
298  *
299  * Setup dc->u.x.gc for text drawing operations.
300  * Return FALSE if the font is null, TRUE otherwise.
301  */
302 BOOL DC_SetupGCForText( DC * dc )
303 {
304     XGCValues val;
305
306     if (!dc->u.x.font.fstruct)
307     {
308         fprintf( stderr, "DC_SetupGCForText: fstruct is NULL. Please report this\n" );
309         return FALSE;
310     }
311     val.function   = GXcopy;  /* Text is always GXcopy */
312     val.foreground = dc->w.textPixel;
313     val.background = dc->w.backgroundPixel;
314     val.fill_style = FillSolid;
315     val.font       = dc->u.x.font.fstruct->fid;
316     XChangeGC( display, dc->u.x.gc, 
317                GCFunction | GCForeground | GCBackground | GCFillStyle |
318                GCFont, &val );
319     return TRUE;
320 }
321
322
323 /***********************************************************************
324  *           GetDCState    (GDI.179)
325  */
326 HDC GetDCState( HDC hdc )
327 {
328     DC * newdc, * dc;
329     HANDLE handle;
330     
331     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
332     if (!(handle = GDI_AllocObject( sizeof(DC), DC_MAGIC ))) return 0;
333     newdc = (DC *) GDI_HEAP_LIN_ADDR( handle );
334
335     dprintf_dc(stddeb, "GetDCState(%d): returning %d\n", hdc, handle );
336
337     memset( &newdc->u.x, 0, sizeof(newdc->u.x) );
338     memcpy( &newdc->w, &dc->w, sizeof(dc->w) );
339     memcpy( &newdc->u.x.pen, &dc->u.x.pen, sizeof(dc->u.x.pen) );
340     newdc->saveLevel = 0;
341     newdc->w.flags |= DC_SAVED;
342
343     newdc->w.hGCClipRgn = 0;
344     newdc->w.hVisRgn = CreateRectRgn( 0, 0, 0, 0 );
345     CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY ); 
346     if (dc->w.hClipRgn)
347     {
348         newdc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
349         CombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
350     }
351     COLOR_SetMapping( newdc, dc->u.x.pal.hMapping,
352                       dc->u.x.pal.hRevMapping, dc->u.x.pal.mappingSize );
353     return handle;
354 }
355
356
357 /***********************************************************************
358  *           SetDCState    (GDI.180)
359  */
360 void SetDCState( HDC hdc, HDC hdcs )
361 {
362     DC * dc, * dcs;
363     HRGN hVisRgn, hClipRgn, hGCClipRgn;
364
365     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
366     if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return;
367     if (!dcs->w.flags & DC_SAVED) return;
368     dprintf_dc(stddeb, "SetDCState: %d %d\n", hdc, hdcs );
369
370       /* Save the regions before overwriting everything */
371     hVisRgn    = dc->w.hVisRgn;
372     hClipRgn   = dc->w.hClipRgn;
373     hGCClipRgn = dc->w.hGCClipRgn;
374     memcpy( &dc->w, &dcs->w, sizeof(dc->w) );
375     memcpy( &dc->u.x.pen, &dcs->u.x.pen, sizeof(dc->u.x.pen) );
376     dc->w.flags &= ~DC_SAVED;
377
378       /* Restore the regions */
379     dc->w.hVisRgn    = hVisRgn;
380     dc->w.hClipRgn   = hClipRgn;
381     dc->w.hGCClipRgn = hGCClipRgn;
382     CombineRgn( dc->w.hVisRgn, dcs->w.hVisRgn, 0, RGN_COPY );
383     SelectClipRgn( hdc, dcs->w.hClipRgn );
384
385     SelectObject( hdc, dcs->w.hBrush );
386     SelectObject( hdc, dcs->w.hFont );
387     COLOR_SetMapping( dc, dcs->u.x.pal.hMapping,
388                       dcs->u.x.pal.hRevMapping, dcs->u.x.pal.mappingSize );
389 }
390
391
392 /***********************************************************************
393  *           SaveDC    (GDI.30)
394  */
395 int SaveDC( HDC hdc )
396 {
397     HDC hdcs;
398     DC * dc, * dcs;
399
400     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
401     if (!dc) 
402     {
403         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
404         if (!dc) return 0;
405         MF_MetaParam0(dc, META_SAVEDC);
406         return 1;  /* ?? */
407     }
408     if (!(hdcs = GetDCState( hdc ))) return 0;
409     dcs = (DC *) GDI_HEAP_LIN_ADDR( hdcs );
410     dcs->header.hNext = dc->header.hNext;
411     dc->header.hNext = hdcs;
412     dprintf_dc(stddeb, "SaveDC(%d): returning %d\n", hdc, dc->saveLevel+1 );
413     return ++dc->saveLevel;
414 }
415
416
417 /***********************************************************************
418  *           RestoreDC    (GDI.39)
419  */
420 BOOL RestoreDC( HDC hdc, short level )
421 {
422     DC * dc, * dcs;
423
424     dprintf_dc(stddeb, "RestoreDC: %d %d\n", hdc, level );
425     dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
426     if (!dc) 
427     {
428         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
429         if (!dc) return FALSE;
430         if (level != -1) return FALSE;
431         MF_MetaParam1(dc, META_RESTOREDC, level);
432         return TRUE;
433     }
434     if (level == -1) level = dc->saveLevel;
435     if ((level < 1) || (level > (short)dc->saveLevel)) return FALSE;
436     
437     while ((short)dc->saveLevel >= level)
438     {
439         HDC hdcs = dc->header.hNext;
440         if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return FALSE;
441         dc->header.hNext = dcs->header.hNext;
442         if ((short)--dc->saveLevel < level) SetDCState( hdc, hdcs );
443         DeleteDC( hdcs );
444     }
445     return TRUE;
446 }
447
448
449 /***********************************************************************
450  *           CreateDC    (GDI.53)
451  */
452 HDC CreateDC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
453 {
454     DC * dc;
455     HANDLE handle;
456     
457     handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
458     if (!handle) return 0;
459     dc = (DC *) GDI_HEAP_LIN_ADDR( handle );
460
461     dprintf_dc(stddeb, "CreateDC(%s %s %s): returning %d\n", 
462             driver, device, output, handle );
463
464     if (!displayDevCaps)
465     {
466         displayDevCaps = (DeviceCaps *) malloc( sizeof(DeviceCaps) );
467         DC_FillDevCaps( displayDevCaps );
468     }
469
470     dc->saveLevel = 0;
471     memcpy( &dc->w, &DC_defaultValues, sizeof(DC_defaultValues) );
472     memset( &dc->u.x, 0, sizeof(dc->u.x) );
473
474     dc->u.x.drawable   = rootWindow;
475     dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
476     dc->w.flags        = 0;
477     dc->w.devCaps      = displayDevCaps;
478     dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
479     dc->w.hVisRgn      = CreateRectRgn( 0, 0, displayDevCaps->horzRes,
480                                         displayDevCaps->vertRes );
481     if (!dc->w.hVisRgn)
482     {
483         GDI_HEAP_FREE( handle );
484         return 0;
485     }
486
487     DC_InitDC( handle );
488
489     return handle;
490 }
491
492
493 /***********************************************************************
494  *           CreateIC    (GDI.153)
495  */
496 HDC CreateIC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
497 {
498       /* Nothing special yet for ICs */
499     return CreateDC( driver, device, output, initData );
500 }
501
502
503 /***********************************************************************
504  *           CreateCompatibleDC    (GDI.52)
505  */
506 HDC CreateCompatibleDC( HDC hdc )
507 {
508     DC * dc;
509     HANDLE handle;
510     HBITMAP hbitmap;
511     BITMAPOBJ *bmp;
512
513     handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
514     if (!handle) return 0;
515     dc = (DC *) GDI_HEAP_LIN_ADDR( handle );
516
517     dprintf_dc(stddeb, "CreateCompatibleDC(%d): returning %d\n", hdc, handle );
518
519       /* Create default bitmap */
520     if (!(hbitmap = CreateBitmap( 1, 1, 1, 1, NULL )))
521     {
522         GDI_HEAP_FREE( handle );
523         return 0;
524     }
525     bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
526     
527     dc->saveLevel = 0;
528     memcpy( &dc->w, &DC_defaultValues, sizeof(DC_defaultValues) );
529     memset( &dc->u.x, 0, sizeof(dc->u.x) );
530
531     dc->u.x.drawable   = bmp->pixmap;
532     dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
533     dc->w.flags        = DC_MEMORY;
534     dc->w.bitsPerPixel = 1;
535     dc->w.devCaps      = displayDevCaps;
536     dc->w.hBitmap      = hbitmap;
537     dc->w.hFirstBitmap = hbitmap;
538     dc->w.hVisRgn      = CreateRectRgn( 0, 0, 1, 1 );
539
540     if (!dc->w.hVisRgn)
541     {
542         DeleteObject( hbitmap );
543         GDI_HEAP_FREE( handle );
544         return 0;
545     }
546
547     DC_InitDC( handle );
548
549     return handle;
550 }
551
552
553 /***********************************************************************
554  *           DeleteDC    (GDI.68)
555  */
556 BOOL DeleteDC( HDC hdc )
557 {
558     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
559     if (!dc) return FALSE;
560
561     dprintf_dc(stddeb, "DeleteDC: %d\n", hdc );
562
563     while (dc->saveLevel)
564     {
565         DC * dcs;
566         HDC hdcs = dc->header.hNext;
567         if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
568         dc->header.hNext = dcs->header.hNext;
569         dc->saveLevel--;
570         DeleteDC( hdcs );
571     }
572     
573     if (!(dc->w.flags & DC_SAVED))
574     {
575         SelectObject( hdc, STOCK_BLACK_PEN );
576         SelectObject( hdc, STOCK_WHITE_BRUSH );
577         SelectObject( hdc, STOCK_SYSTEM_FONT );
578         XFreeGC( display, dc->u.x.gc );
579     }
580
581     if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hFirstBitmap );
582     if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
583     if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
584     if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
585     
586     return GDI_FreeObject( hdc );
587 }
588
589
590 /***********************************************************************
591  *           GetDeviceCaps    (GDI.80)
592  */
593 int GetDeviceCaps( HDC hdc, WORD cap )
594 {
595     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
596     if (!dc) return 0;
597
598     if (cap > sizeof(DeviceCaps)-sizeof(WORD)) return 0;
599     
600     dprintf_dc(stddeb, "GetDeviceCaps(%d,%d): returning %d\n",
601             hdc, cap, *(WORD *)(((char *)dc->w.devCaps) + cap) );
602     return *(WORD *)(((char *)dc->w.devCaps) + cap);
603 }
604
605
606 /***********************************************************************
607  *           SetBkColor    (GDI.1)
608  */
609 COLORREF SetBkColor( HDC hdc, COLORREF color )
610 {
611     COLORREF oldColor;
612     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
613     if (!dc) 
614     {
615         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
616         if (!dc) return 0x80000000;
617         MF_MetaParam2(dc, META_SETBKCOLOR, HIWORD(color), LOWORD(color));
618         return 0;  /* ?? */
619     }
620
621     oldColor = dc->w.backgroundColor;
622     dc->w.backgroundColor = color;
623     dc->w.backgroundPixel = COLOR_ToPhysical( dc, color );
624     return oldColor;
625 }
626
627
628 /***********************************************************************
629  *           SetTextColor    (GDI.9)
630  */
631 COLORREF SetTextColor( HDC hdc, COLORREF color )
632 {
633     COLORREF oldColor;
634     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
635     if (!dc) 
636     {
637         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
638         if (!dc) return 0x80000000;
639         MF_MetaParam2(dc, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color));
640         return 0;  /* ?? */
641     }
642
643     oldColor = dc->w.textColor;
644     dc->w.textColor = color;
645     dc->w.textPixel = COLOR_ToPhysical( dc, color );
646     return oldColor;
647 }
648
649
650 /***********************************************************************
651  *           GetDCOrg    (GDI.79)
652  */
653 DWORD GetDCOrg( HDC hdc )
654 {
655     Window root;
656     int x, y, w, h, border, depth;
657
658     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
659     if (!dc) return 0;
660     if (dc->w.flags & DC_MEMORY) return 0;
661     XGetGeometry( display, dc->u.x.drawable, &root,
662                   &x, &y, &w, &h, &border, &depth );
663     return MAKELONG( dc->w.DCOrgX + (WORD)x, dc->w.DCOrgY + (WORD)y );
664 }
665
666
667 /***********************************************************************
668  *           SetDCOrg    (GDI.117)
669  */
670 DWORD SetDCOrg( HDC hdc, short x, short y )
671 {
672     DWORD prevOrg;
673     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
674     if (!dc) return 0;
675     prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
676     dc->w.DCOrgX = x;
677     dc->w.DCOrgY = y;
678     return prevOrg;
679 }