Added entry for DirectSoundFullDuplexCreate.
[wine] / objects / clipping.c
1 /*
2  * DC clipping functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdlib.h>
22 #include "windef.h"
23 #include "wingdi.h"
24 #include "wownt32.h"
25 #include "wine/winuser16.h"
26 #include "gdi.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(clipping);
30
31
32 /***********************************************************************
33  *           CLIPPING_UpdateGCRegion
34  *
35  * Update the GC clip region when the ClipRgn or VisRgn have changed.
36  */
37 void CLIPPING_UpdateGCRegion( DC * dc )
38 {
39     if (!dc->hGCClipRgn) dc->hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
40
41     if (!dc->hVisRgn)
42     {
43         ERR("hVisRgn is zero. Please report this.\n" );
44         exit(1);
45     }
46
47     if (dc->flags & DC_DIRTY) ERR( "DC is dirty. Please report this.\n" );
48
49     if (!dc->hClipRgn)
50         CombineRgn( dc->hGCClipRgn, dc->hVisRgn, 0, RGN_COPY );
51     else
52         CombineRgn(dc->hGCClipRgn, dc->hClipRgn, dc->hVisRgn, RGN_AND);
53     if (dc->funcs->pSetDeviceClipping)
54         dc->funcs->pSetDeviceClipping( dc->physDev, dc->hGCClipRgn );
55 }
56
57
58 /***********************************************************************
59  *           SelectClipRgn    (GDI32.@)
60  */
61 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
62 {
63     return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
64 }
65
66
67 /******************************************************************************
68  *              ExtSelectClipRgn        [GDI32.@]
69  */
70 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
71 {
72     INT retval;
73     DC * dc = DC_GetDCUpdate( hdc );
74     if (!dc) return ERROR;
75
76     TRACE("%p %p %d\n", hdc, hrgn, fnMode );
77
78     if (dc->funcs->pExtSelectClipRgn)
79     {
80         retval = dc->funcs->pExtSelectClipRgn( dc->physDev, hrgn, fnMode );
81         GDI_ReleaseObj( hdc );
82         return retval;
83     }
84
85     if (!hrgn)
86     {
87         if (fnMode == RGN_COPY)
88         {
89             if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
90             dc->hClipRgn = 0;
91             retval = SIMPLEREGION; /* Clip region == whole DC */
92         }
93         else
94         {
95             FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
96             GDI_ReleaseObj( hdc );
97             return ERROR;
98         }
99     }
100     else
101     {
102         if (!dc->hClipRgn)
103         {
104             RECT rect;
105             GetRgnBox( dc->hVisRgn, &rect );
106             dc->hClipRgn = CreateRectRgnIndirect( &rect );
107         }
108
109         if(fnMode == RGN_COPY)
110             retval = CombineRgn( dc->hClipRgn, hrgn, 0, fnMode );
111         else
112             retval = CombineRgn( dc->hClipRgn, dc->hClipRgn, hrgn, fnMode);
113     }
114
115     CLIPPING_UpdateGCRegion( dc );
116     GDI_ReleaseObj( hdc );
117     return retval;
118 }
119
120 /***********************************************************************
121  *           SelectVisRgn   (GDI.105)
122  */
123 INT16 WINAPI SelectVisRgn16( HDC16 hdc16, HRGN16 hrgn )
124 {
125     int retval;
126     HDC hdc = HDC_32( hdc16 );
127     DC * dc;
128
129     if (!hrgn) return ERROR;
130     if (!(dc = DC_GetDCPtr( hdc ))) return ERROR;
131
132     TRACE("%p %04x\n", hdc, hrgn );
133
134     dc->flags &= ~DC_DIRTY;
135
136     retval = CombineRgn( dc->hVisRgn, HRGN_32(hrgn), 0, RGN_COPY );
137     CLIPPING_UpdateGCRegion( dc );
138     GDI_ReleaseObj( hdc );
139     return retval;
140 }
141
142
143 /***********************************************************************
144  *           OffsetClipRgn    (GDI32.@)
145  */
146 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
147 {
148     INT ret = SIMPLEREGION;
149     DC *dc = DC_GetDCUpdate( hdc );
150     if (!dc) return ERROR;
151
152     TRACE("%p %d,%d\n", hdc, x, y );
153
154     if(dc->funcs->pOffsetClipRgn)
155         ret = dc->funcs->pOffsetClipRgn( dc->physDev, x, y );
156     else if (dc->hClipRgn) {
157         ret = OffsetRgn( dc->hClipRgn, XLSTODS(dc,x), YLSTODS(dc,y));
158         CLIPPING_UpdateGCRegion( dc );
159     }
160     GDI_ReleaseObj( hdc );
161     return ret;
162 }
163
164
165 /***********************************************************************
166  *           OffsetVisRgn    (GDI.102)
167  */
168 INT16 WINAPI OffsetVisRgn16( HDC16 hdc16, INT16 x, INT16 y )
169 {
170     INT16 retval;
171     HDC hdc = HDC_32( hdc16 );
172     DC * dc = DC_GetDCUpdate( hdc );
173     if (!dc) return ERROR;
174     TRACE("%p %d,%d\n", hdc, x, y );
175     retval = OffsetRgn( dc->hVisRgn, x, y );
176     CLIPPING_UpdateGCRegion( dc );
177     GDI_ReleaseObj( hdc );
178     return retval;
179 }
180
181
182 /***********************************************************************
183  *           ExcludeClipRect    (GDI32.@)
184  */
185 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
186                                 INT right, INT bottom )
187 {
188     HRGN newRgn;
189     INT ret;
190     DC *dc = DC_GetDCUpdate( hdc );
191     if (!dc) return ERROR;
192
193     TRACE("%p %dx%d,%dx%d\n", hdc, left, top, right, bottom );
194
195     if(dc->funcs->pExcludeClipRect)
196         ret = dc->funcs->pExcludeClipRect( dc->physDev, left, top, right, bottom );
197     else
198     {
199         POINT pt[2];
200
201         pt[0].x = left;
202         pt[0].y = top;
203         pt[1].x = right;
204         pt[1].y = bottom;
205         LPtoDP( hdc, pt, 2 );
206         if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
207         else
208         {
209             if (!dc->hClipRgn)
210             {
211                 dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
212                 CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
213             }
214             ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_DIFF );
215             DeleteObject( newRgn );
216         }
217         if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
218     }
219     GDI_ReleaseObj( hdc );
220     return ret;
221 }
222
223
224 /***********************************************************************
225  *           IntersectClipRect    (GDI32.@)
226  */
227 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom )
228 {
229     INT ret;
230     DC *dc = DC_GetDCUpdate( hdc );
231     if (!dc) return ERROR;
232
233     TRACE("%p %d,%d - %d,%d\n", hdc, left, top, right, bottom );
234
235     if(dc->funcs->pIntersectClipRect)
236         ret = dc->funcs->pIntersectClipRect( dc->physDev, left, top, right, bottom );
237     else
238     {
239         POINT pt[2];
240
241         pt[0].x = left;
242         pt[0].y = top;
243         pt[1].x = right;
244         pt[1].y = bottom;
245
246         LPtoDP( hdc, pt, 2 );
247
248         if (!dc->hClipRgn)
249         {
250             dc->hClipRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y );
251             ret = SIMPLEREGION;
252         }
253         else
254         {
255             HRGN newRgn;
256
257             if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
258             else
259             {
260                 ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
261                 DeleteObject( newRgn );
262             }
263         }
264         if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
265     }
266     GDI_ReleaseObj( hdc );
267     return ret;
268 }
269
270
271 /***********************************************************************
272  *           ExcludeVisRect   (GDI.73)
273  */
274 INT16 WINAPI ExcludeVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right, INT16 bottom )
275 {
276     HRGN tempRgn;
277     INT16 ret;
278     POINT pt[2];
279     HDC hdc = HDC_32( hdc16 );
280     DC * dc = DC_GetDCUpdate( hdc );
281     if (!dc) return ERROR;
282
283     pt[0].x = left;
284     pt[0].y = top;
285     pt[1].x = right;
286     pt[1].y = bottom;
287
288     LPtoDP( hdc, pt, 2 );
289
290     TRACE("%p %ld,%ld - %ld,%ld\n", hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
291
292     if (!(tempRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
293     else
294     {
295         ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_DIFF );
296         DeleteObject( tempRgn );
297     }
298     if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
299     GDI_ReleaseObj( hdc );
300     return ret;
301 }
302
303
304 /***********************************************************************
305  *           IntersectVisRect   (GDI.98)
306  */
307 INT16 WINAPI IntersectVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right, INT16 bottom )
308 {
309     HRGN tempRgn;
310     INT16 ret;
311     POINT pt[2];
312     HDC hdc = HDC_32( hdc16 );
313     DC * dc = DC_GetDCUpdate( hdc );
314     if (!dc) return ERROR;
315
316     pt[0].x = left;
317     pt[0].y = top;
318     pt[1].x = right;
319     pt[1].y = bottom;
320
321     LPtoDP( hdc, pt, 2 );
322
323     TRACE("%p %ld,%ld - %ld,%ld\n", hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
324
325
326     if (!(tempRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
327     else
328     {
329         ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_AND );
330         DeleteObject( tempRgn );
331     }
332     if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
333     GDI_ReleaseObj( hdc );
334     return ret;
335 }
336
337
338 /***********************************************************************
339  *           PtVisible    (GDI32.@)
340  */
341 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
342 {
343     BOOL ret = FALSE;
344     DC *dc = DC_GetDCUpdate( hdc );
345
346     TRACE("%p %d,%d\n", hdc, x, y );
347     if (!dc) return FALSE;
348     if (dc->hGCClipRgn)
349     {
350         POINT pt;
351
352         pt.x = x;
353         pt.y = y;
354         LPtoDP( hdc, &pt, 1 );
355         ret = PtInRegion( dc->hGCClipRgn, pt.x, pt.y );
356     }
357     GDI_ReleaseObj( hdc );
358     return ret;
359 }
360
361
362 /***********************************************************************
363  *           RectVisible    (GDI32.@)
364  */
365 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
366 {
367     BOOL ret = FALSE;
368     DC *dc = DC_GetDCUpdate( hdc );
369     if (!dc) return FALSE;
370     TRACE("%p %ld,%ldx%ld,%ld\n", hdc, rect->left, rect->top, rect->right, rect->bottom );
371     if (dc->hGCClipRgn)
372     {
373         POINT pt[2];
374         RECT tmpRect;
375
376         pt[0].x = rect->left;
377         pt[0].y = rect->top;
378         pt[1].x = rect->right;
379         pt[1].y = rect->bottom;
380         LPtoDP( hdc, pt, 2 );
381         tmpRect.left    = pt[0].x;
382         tmpRect.top     = pt[0].y;
383         tmpRect.right   = pt[1].x;
384         tmpRect.bottom  = pt[1].y;
385         ret = RectInRegion( dc->hGCClipRgn, &tmpRect );
386     }
387     GDI_ReleaseObj( hdc );
388     return ret;
389 }
390
391
392 /***********************************************************************
393  *           GetClipBox    (GDI32.@)
394  */
395 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
396 {
397     INT ret;
398     DC *dc = DC_GetDCUpdate( hdc );
399     if (!dc) return ERROR;
400     ret = GetRgnBox( dc->hGCClipRgn, rect );
401     DPtoLP( hdc, (LPPOINT)rect, 2 );
402     GDI_ReleaseObj( hdc );
403     return ret;
404 }
405
406
407 /***********************************************************************
408  *           GetClipRgn  (GDI32.@)
409  */
410 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
411 {
412     INT ret = -1;
413     DC * dc;
414     if (hRgn && (dc = DC_GetDCPtr( hdc )))
415     {
416       if( dc->hClipRgn )
417       {
418           if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR ) ret = 1;
419       }
420       else ret = 0;
421       GDI_ReleaseObj( hdc );
422     }
423     return ret;
424 }
425
426 /***********************************************************************
427  *           SaveVisRgn   (GDI.129)
428  */
429 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc16 )
430 {
431     HRGN copy;
432     GDIOBJHDR *obj, *copyObj;
433     HDC hdc = HDC_32( hdc16 );
434     DC *dc = DC_GetDCUpdate( hdc );
435
436     if (!dc) return 0;
437     TRACE("%p\n", hdc );
438
439     if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
440     {
441         GDI_ReleaseObj( hdc );
442         return 0;
443     }
444     if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
445     {
446         GDI_ReleaseObj( dc->hVisRgn );
447         GDI_ReleaseObj( hdc );
448         return 0;
449     }
450     CombineRgn( copy, dc->hVisRgn, 0, RGN_COPY );
451     if (!(copyObj = GDI_GetObjPtr( copy, REGION_MAGIC )))
452     {
453         DeleteObject( copy );
454         GDI_ReleaseObj( dc->hVisRgn );
455         GDI_ReleaseObj( hdc );
456         return 0;
457     }
458     copyObj->hNext = obj->hNext;
459     obj->hNext = HRGN_16(copy);
460     GDI_ReleaseObj( copy );
461     GDI_ReleaseObj( dc->hVisRgn );
462     GDI_ReleaseObj( hdc );
463     return HRGN_16(copy);
464 }
465
466
467 /***********************************************************************
468  *           RestoreVisRgn   (GDI.130)
469  */
470 INT16 WINAPI RestoreVisRgn16( HDC16 hdc16 )
471 {
472     HRGN saved;
473     GDIOBJHDR *obj, *savedObj;
474     HDC hdc = HDC_32( hdc16 );
475     DC *dc = DC_GetDCPtr( hdc );
476     INT16 ret = ERROR;
477
478     if (!dc) return ERROR;
479
480     TRACE("%p\n", hdc );
481
482     if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
483     saved = HRGN_32(obj->hNext);
484
485     if ((savedObj = GDI_GetObjPtr( saved, REGION_MAGIC )))
486     {
487         ret = CombineRgn( dc->hVisRgn, saved, 0, RGN_COPY );
488         obj->hNext = savedObj->hNext;
489         GDI_ReleaseObj( saved );
490         DeleteObject( saved );
491         dc->flags &= ~DC_DIRTY;
492         CLIPPING_UpdateGCRegion( dc );
493     }
494     GDI_ReleaseObj( dc->hVisRgn );
495  done:
496     GDI_ReleaseObj( hdc );
497     return ret;
498 }