- Move StgIsStorageFile16's implementation to StgIsStorageFile; port
[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("%04x %04x %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 hdc, HRGN16 hrgn )
124 {
125     int retval;
126     DC * dc;
127
128     if (!hrgn) return ERROR;
129     if (!(dc = DC_GetDCPtr( hdc ))) return ERROR;
130
131     TRACE("%04x %04x\n", hdc, hrgn );
132
133     dc->flags &= ~DC_DIRTY;
134
135     retval = CombineRgn( dc->hVisRgn, HRGN_32(hrgn), 0, RGN_COPY );
136     CLIPPING_UpdateGCRegion( dc );
137     GDI_ReleaseObj( hdc );
138     return retval;
139 }
140
141
142 /***********************************************************************
143  *           OffsetClipRgn    (GDI32.@)
144  */
145 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
146 {
147     INT ret = SIMPLEREGION;
148     DC *dc = DC_GetDCUpdate( hdc );
149     if (!dc) return ERROR;
150
151     TRACE("%04x %d,%d\n", hdc, x, y );
152
153     if(dc->funcs->pOffsetClipRgn)
154         ret = dc->funcs->pOffsetClipRgn( dc->physDev, x, y );
155     else if (dc->hClipRgn) {
156         ret = OffsetRgn( dc->hClipRgn, XLSTODS(dc,x), YLSTODS(dc,y));
157         CLIPPING_UpdateGCRegion( dc );
158     }
159     GDI_ReleaseObj( hdc );
160     return ret;
161 }
162
163
164 /***********************************************************************
165  *           OffsetVisRgn    (GDI.102)
166  */
167 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
168 {
169     INT16 retval;
170     DC * dc = DC_GetDCUpdate( hdc );
171     if (!dc) return ERROR;
172     TRACE("%04x %d,%d\n", hdc, x, y );
173     retval = OffsetRgn( dc->hVisRgn, x, y );
174     CLIPPING_UpdateGCRegion( dc );
175     GDI_ReleaseObj( hdc );
176     return retval;
177 }
178
179
180 /***********************************************************************
181  *           ExcludeClipRect    (GDI32.@)
182  */
183 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
184                                 INT right, INT bottom )
185 {
186     HRGN newRgn;
187     INT ret;
188     DC *dc = DC_GetDCUpdate( hdc );
189     if (!dc) return ERROR;
190
191     TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
192
193     if(dc->funcs->pExcludeClipRect)
194         ret = dc->funcs->pExcludeClipRect( dc->physDev, left, top, right, bottom );
195     else
196     {
197         RECT rect;
198         rect.left = left;
199         rect.top = top;
200         rect.right = right;
201         rect.bottom = bottom;
202         LPtoDP( hdc, (POINT*)&rect, 2 );
203
204         if (!(newRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) ret = ERROR;
205         else
206         {
207             if (!dc->hClipRgn)
208             {
209                 dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
210                 CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
211             }
212             ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_DIFF );
213             DeleteObject( newRgn );
214         }
215         if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
216     }
217     GDI_ReleaseObj( hdc );
218     return ret;
219 }
220
221
222 /***********************************************************************
223  *           IntersectClipRect    (GDI32.@)
224  */
225 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom )
226 {
227     INT ret;
228     DC *dc = DC_GetDCUpdate( hdc );
229     if (!dc) return ERROR;
230
231     TRACE("%04x %d,%d - %d,%d\n", hdc, left, top, right, bottom );
232
233     if(dc->funcs->pIntersectClipRect)
234         ret = dc->funcs->pIntersectClipRect( dc->physDev, left, top, right, bottom );
235     else
236     {
237         RECT rect;
238
239         rect.left   = left;
240         rect.top    = top;
241         rect.right  = right;
242         rect.bottom = bottom;
243         LPtoDP( hdc, (POINT*)&rect, 2 );
244
245         if (!dc->hClipRgn)
246         {
247             dc->hClipRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom );
248             ret = SIMPLEREGION;
249         }
250         else
251         {
252             HRGN newRgn;
253
254             if (!(newRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom))) ret = ERROR;
255             else
256             {
257                 ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
258                 DeleteObject( newRgn );
259             }
260         }
261         if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
262     }
263     GDI_ReleaseObj( hdc );
264     return ret;
265 }
266
267
268 /***********************************************************************
269  *           ExcludeVisRect   (GDI.73)
270  */
271 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
272                              INT16 right, INT16 bottom )
273 {
274     HRGN tempRgn;
275     INT16 ret;
276     RECT rect;
277     DC * dc = DC_GetDCUpdate( hdc );
278     if (!dc) return ERROR;
279
280     rect.left   = left;
281     rect.top    = top;
282     rect.right  = right;
283     rect.bottom = bottom;
284     LPtoDP( hdc, (POINT*)&rect, 2 );
285
286     TRACE("%04x %d,%d - %d,%d\n", hdc, rect.left, rect.top, rect.right, rect.bottom );
287
288     if (!(tempRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) ret = ERROR;
289     else
290     {
291         ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_DIFF );
292         DeleteObject( tempRgn );
293     }
294     if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
295     GDI_ReleaseObj( hdc );
296     return ret;
297 }
298
299
300 /***********************************************************************
301  *           IntersectVisRect   (GDI.98)
302  */
303 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
304                                INT16 right, INT16 bottom )
305 {
306     HRGN tempRgn;
307     INT16 ret;
308     RECT rect;
309     DC * dc = DC_GetDCUpdate( hdc );
310     if (!dc) return ERROR;
311
312     rect.left   = left;
313     rect.top    = top;
314     rect.right  = right;
315     rect.bottom = bottom;
316     LPtoDP( hdc, (POINT*)&rect, 2 );
317
318     TRACE("%04x %d,%d - %d,%d\n", hdc, rect.left, rect.top, rect.right, rect.bottom );
319
320     if (!(tempRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) ret = ERROR;
321     else
322     {
323         ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_AND );
324         DeleteObject( tempRgn );
325     }
326     if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
327     GDI_ReleaseObj( hdc );
328     return ret;
329 }
330
331
332 /***********************************************************************
333  *           PtVisible    (GDI32.@)
334  */
335 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
336 {
337     BOOL ret = FALSE;
338     DC *dc = DC_GetDCUpdate( hdc );
339
340     TRACE("%04x %d,%d\n", hdc, x, y );
341     if (!dc) return FALSE;
342     if (dc->hGCClipRgn)
343     {
344         POINT pt;
345
346         pt.x = x;
347         pt.y = y;
348         LPtoDP( hdc, &pt, 1 );
349         ret = PtInRegion( dc->hGCClipRgn, pt.x, pt.y );
350     }
351     GDI_ReleaseObj( hdc );
352     return ret;
353 }
354
355
356 /***********************************************************************
357  *           RectVisible    (GDI32.@)
358  */
359 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
360 {
361     BOOL ret = FALSE;
362     RECT tmpRect;
363     DC *dc = DC_GetDCUpdate( hdc );
364     if (!dc) return FALSE;
365     TRACE("%04x %d,%dx%d,%d\n",
366           hdc, rect->left, rect->top, rect->right, rect->bottom );
367     if (dc->hGCClipRgn)
368     {
369         /* copy rectangle to avoid overwriting by LPtoDP */
370         tmpRect = *rect;
371         LPtoDP( hdc, (LPPOINT)&tmpRect, 2 );
372         ret = RectInRegion( dc->hGCClipRgn, &tmpRect );
373     }
374     GDI_ReleaseObj( hdc );
375     return ret;
376 }
377
378
379 /***********************************************************************
380  *           GetClipBox    (GDI32.@)
381  */
382 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
383 {
384     INT ret;
385     DC *dc = DC_GetDCUpdate( hdc );
386     if (!dc) return ERROR;
387     ret = GetRgnBox( dc->hGCClipRgn, rect );
388     DPtoLP( hdc, (LPPOINT)rect, 2 );
389     GDI_ReleaseObj( hdc );
390     return ret;
391 }
392
393
394 /***********************************************************************
395  *           GetClipRgn  (GDI32.@)
396  */
397 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
398 {
399     INT ret = -1;
400     DC * dc;
401     if (hRgn && (dc = DC_GetDCPtr( hdc )))
402     {
403       if( dc->hClipRgn )
404       {
405           if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR ) ret = 1;
406       }
407       else ret = 0;
408       GDI_ReleaseObj( hdc );
409     }
410     return ret;
411 }
412
413 /***********************************************************************
414  *           SaveVisRgn   (GDI.129)
415  */
416 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
417 {
418     HRGN copy;
419     GDIOBJHDR *obj, *copyObj;
420     DC *dc = DC_GetDCUpdate( hdc );
421
422     if (!dc) return 0;
423     TRACE("%04x\n", hdc );
424
425     if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
426     {
427         GDI_ReleaseObj( hdc );
428         return 0;
429     }
430     if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
431     {
432         GDI_ReleaseObj( dc->hVisRgn );
433         GDI_ReleaseObj( hdc );
434         return 0;
435     }
436     CombineRgn( copy, dc->hVisRgn, 0, RGN_COPY );
437     if (!(copyObj = GDI_GetObjPtr( copy, REGION_MAGIC )))
438     {
439         DeleteObject( copy );
440         GDI_ReleaseObj( dc->hVisRgn );
441         GDI_ReleaseObj( hdc );
442         return 0;
443     }
444     copyObj->hNext = obj->hNext;
445     obj->hNext = copy;
446     GDI_ReleaseObj( copy );
447     GDI_ReleaseObj( dc->hVisRgn );
448     GDI_ReleaseObj( hdc );
449     return copy;
450 }
451
452
453 /***********************************************************************
454  *           RestoreVisRgn   (GDI.130)
455  */
456 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
457 {
458     HRGN saved;
459     GDIOBJHDR *obj, *savedObj;
460     DC *dc = DC_GetDCPtr( hdc );
461     INT16 ret = ERROR;
462
463     if (!dc) return ERROR;
464
465     TRACE("%04x\n", hdc );
466
467     if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
468     saved = obj->hNext;
469
470     if ((savedObj = GDI_GetObjPtr( saved, REGION_MAGIC )))
471     {
472         ret = CombineRgn( dc->hVisRgn, saved, 0, RGN_COPY );
473         obj->hNext = savedObj->hNext;
474         GDI_ReleaseObj( saved );
475         DeleteObject( saved );
476         dc->flags &= ~DC_DIRTY;
477         CLIPPING_UpdateGCRegion( dc );
478     }
479     GDI_ReleaseObj( dc->hVisRgn );
480  done:
481     GDI_ReleaseObj( hdc );
482     return ret;
483 }