Fix MultiByteToWideChar and WideCharToMultiByte when called with code
[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 <stdarg.h>
22 #include <stdlib.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "wownt32.h"
27 #include "wine/winuser16.h"
28 #include "gdi.h"
29 #include "gdi_private.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(clipping);
33
34
35 /***********************************************************************
36  *           CLIPPING_UpdateGCRegion
37  *
38  * Update the GC clip region when the ClipRgn or VisRgn have changed.
39  */
40 void CLIPPING_UpdateGCRegion( DC * dc )
41 {
42     if (!dc->hGCClipRgn) dc->hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
43
44     if (!dc->hVisRgn)
45     {
46         ERR("hVisRgn is zero. Please report this.\n" );
47         exit(1);
48     }
49
50     if (dc->flags & DC_DIRTY) ERR( "DC is dirty. Please report this.\n" );
51
52     if (!dc->hClipRgn)
53         CombineRgn( dc->hGCClipRgn, dc->hVisRgn, 0, RGN_COPY );
54     else
55         CombineRgn(dc->hGCClipRgn, dc->hClipRgn, dc->hVisRgn, RGN_AND);
56     if (dc->funcs->pSetDeviceClipping)
57         dc->funcs->pSetDeviceClipping( dc->physDev, dc->hGCClipRgn );
58 }
59
60
61 /***********************************************************************
62  *           SelectClipRgn    (GDI32.@)
63  */
64 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
65 {
66     return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
67 }
68
69
70 /******************************************************************************
71  *              ExtSelectClipRgn        [GDI32.@]
72  */
73 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
74 {
75     INT retval;
76     RECT rect;
77     DC * dc = DC_GetDCUpdate( hdc );
78     if (!dc) return ERROR;
79
80     TRACE("%p %p %d\n", hdc, hrgn, fnMode );
81
82     if (dc->funcs->pExtSelectClipRgn)
83     {
84         retval = dc->funcs->pExtSelectClipRgn( dc->physDev, hrgn, fnMode );
85         GDI_ReleaseObj( hdc );
86         return retval;
87     }
88
89     if (!hrgn)
90     {
91         if (fnMode == RGN_COPY)
92         {
93             if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
94             dc->hClipRgn = 0;
95         }
96         else
97         {
98             FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
99             GDI_ReleaseObj( hdc );
100             return ERROR;
101         }
102     }
103     else
104     {
105         if (!dc->hClipRgn)
106         {
107             RECT rect;
108             GetRgnBox( dc->hVisRgn, &rect );
109             dc->hClipRgn = CreateRectRgnIndirect( &rect );
110         }
111
112         if(fnMode == RGN_COPY)
113             CombineRgn( dc->hClipRgn, hrgn, 0, fnMode );
114         else
115             CombineRgn( dc->hClipRgn, dc->hClipRgn, hrgn, fnMode);
116     }
117
118     CLIPPING_UpdateGCRegion( dc );
119     GDI_ReleaseObj( hdc );
120
121     return GetClipBox(hdc, &rect);
122 }
123
124 /***********************************************************************
125  *           SelectVisRgn   (GDI.105)
126  */
127 INT16 WINAPI SelectVisRgn16( HDC16 hdc16, HRGN16 hrgn )
128 {
129     int retval;
130     HDC hdc = HDC_32( hdc16 );
131     DC * dc;
132
133     if (!hrgn) return ERROR;
134     if (!(dc = DC_GetDCPtr( hdc ))) return ERROR;
135
136     TRACE("%p %04x\n", hdc, hrgn );
137
138     dc->flags &= ~DC_DIRTY;
139
140     retval = CombineRgn( dc->hVisRgn, HRGN_32(hrgn), 0, RGN_COPY );
141     CLIPPING_UpdateGCRegion( dc );
142     GDI_ReleaseObj( hdc );
143     return retval;
144 }
145
146
147 /***********************************************************************
148  *           OffsetClipRgn    (GDI32.@)
149  */
150 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
151 {
152     INT ret = SIMPLEREGION;
153     DC *dc = DC_GetDCUpdate( hdc );
154     if (!dc) return ERROR;
155
156     TRACE("%p %d,%d\n", hdc, x, y );
157
158     if(dc->funcs->pOffsetClipRgn)
159         ret = dc->funcs->pOffsetClipRgn( dc->physDev, x, y );
160     else if (dc->hClipRgn) {
161         ret = OffsetRgn( dc->hClipRgn, MulDiv( x, dc->vportExtX, dc->wndExtX ),
162                          MulDiv( y, dc->vportExtY, dc->wndExtY ) );
163         CLIPPING_UpdateGCRegion( dc );
164     }
165     GDI_ReleaseObj( hdc );
166     return ret;
167 }
168
169
170 /***********************************************************************
171  *           OffsetVisRgn    (GDI.102)
172  */
173 INT16 WINAPI OffsetVisRgn16( HDC16 hdc16, INT16 x, INT16 y )
174 {
175     INT16 retval;
176     HDC hdc = HDC_32( hdc16 );
177     DC * dc = DC_GetDCUpdate( hdc );
178     if (!dc) return ERROR;
179     TRACE("%p %d,%d\n", hdc, x, y );
180     retval = OffsetRgn( dc->hVisRgn, x, y );
181     CLIPPING_UpdateGCRegion( dc );
182     GDI_ReleaseObj( hdc );
183     return retval;
184 }
185
186
187 /***********************************************************************
188  *           ExcludeClipRect    (GDI32.@)
189  */
190 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
191                                 INT right, INT bottom )
192 {
193     HRGN newRgn;
194     INT ret;
195     DC *dc = DC_GetDCUpdate( hdc );
196     if (!dc) return ERROR;
197
198     TRACE("%p %dx%d,%dx%d\n", hdc, left, top, right, bottom );
199
200     if(dc->funcs->pExcludeClipRect)
201         ret = dc->funcs->pExcludeClipRect( dc->physDev, left, top, right, bottom );
202     else
203     {
204         POINT pt[2];
205
206         pt[0].x = left;
207         pt[0].y = top;
208         pt[1].x = right;
209         pt[1].y = bottom;
210         LPtoDP( hdc, pt, 2 );
211         if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
212         else
213         {
214             if (!dc->hClipRgn)
215             {
216                 dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
217                 CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
218             }
219             ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_DIFF );
220             DeleteObject( newRgn );
221         }
222         if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
223     }
224     GDI_ReleaseObj( hdc );
225     return ret;
226 }
227
228
229 /***********************************************************************
230  *           IntersectClipRect    (GDI32.@)
231  */
232 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom )
233 {
234     INT ret;
235     DC *dc = DC_GetDCUpdate( hdc );
236     if (!dc) return ERROR;
237
238     TRACE("%p %d,%d - %d,%d\n", hdc, left, top, right, bottom );
239
240     if(dc->funcs->pIntersectClipRect)
241         ret = dc->funcs->pIntersectClipRect( dc->physDev, left, top, right, bottom );
242     else
243     {
244         POINT pt[2];
245
246         pt[0].x = left;
247         pt[0].y = top;
248         pt[1].x = right;
249         pt[1].y = bottom;
250
251         LPtoDP( hdc, pt, 2 );
252
253         if (!dc->hClipRgn)
254         {
255             dc->hClipRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y );
256             ret = SIMPLEREGION;
257         }
258         else
259         {
260             HRGN newRgn;
261
262             if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
263             else
264             {
265                 ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
266                 DeleteObject( newRgn );
267             }
268         }
269         if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
270     }
271     GDI_ReleaseObj( hdc );
272     return ret;
273 }
274
275
276 /***********************************************************************
277  *           ExcludeVisRect   (GDI.73)
278  */
279 INT16 WINAPI ExcludeVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right, INT16 bottom )
280 {
281     HRGN tempRgn;
282     INT16 ret;
283     POINT pt[2];
284     HDC hdc = HDC_32( hdc16 );
285     DC * dc = DC_GetDCUpdate( hdc );
286     if (!dc) return ERROR;
287
288     pt[0].x = left;
289     pt[0].y = top;
290     pt[1].x = right;
291     pt[1].y = bottom;
292
293     LPtoDP( hdc, pt, 2 );
294
295     TRACE("%p %ld,%ld - %ld,%ld\n", hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
296
297     if (!(tempRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
298     else
299     {
300         ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_DIFF );
301         DeleteObject( tempRgn );
302     }
303     if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
304     GDI_ReleaseObj( hdc );
305     return ret;
306 }
307
308
309 /***********************************************************************
310  *           IntersectVisRect   (GDI.98)
311  */
312 INT16 WINAPI IntersectVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right, INT16 bottom )
313 {
314     HRGN tempRgn;
315     INT16 ret;
316     POINT pt[2];
317     HDC hdc = HDC_32( hdc16 );
318     DC * dc = DC_GetDCUpdate( hdc );
319     if (!dc) return ERROR;
320
321     pt[0].x = left;
322     pt[0].y = top;
323     pt[1].x = right;
324     pt[1].y = bottom;
325
326     LPtoDP( hdc, pt, 2 );
327
328     TRACE("%p %ld,%ld - %ld,%ld\n", hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
329
330
331     if (!(tempRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
332     else
333     {
334         ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_AND );
335         DeleteObject( tempRgn );
336     }
337     if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
338     GDI_ReleaseObj( hdc );
339     return ret;
340 }
341
342
343 /***********************************************************************
344  *           PtVisible    (GDI32.@)
345  */
346 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
347 {
348     BOOL ret = FALSE;
349     DC *dc = DC_GetDCUpdate( hdc );
350
351     TRACE("%p %d,%d\n", hdc, x, y );
352     if (!dc) return FALSE;
353     if (dc->hGCClipRgn)
354     {
355         POINT pt;
356
357         pt.x = x;
358         pt.y = y;
359         LPtoDP( hdc, &pt, 1 );
360         ret = PtInRegion( dc->hGCClipRgn, pt.x, pt.y );
361     }
362     GDI_ReleaseObj( hdc );
363     return ret;
364 }
365
366
367 /***********************************************************************
368  *           RectVisible    (GDI32.@)
369  */
370 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
371 {
372     BOOL ret = FALSE;
373     DC *dc = DC_GetDCUpdate( hdc );
374     if (!dc) return FALSE;
375     TRACE("%p %ld,%ldx%ld,%ld\n", hdc, rect->left, rect->top, rect->right, rect->bottom );
376     if (dc->hGCClipRgn)
377     {
378         POINT pt[2];
379         RECT tmpRect;
380
381         pt[0].x = rect->left;
382         pt[0].y = rect->top;
383         pt[1].x = rect->right;
384         pt[1].y = rect->bottom;
385         LPtoDP( hdc, pt, 2 );
386         tmpRect.left    = pt[0].x;
387         tmpRect.top     = pt[0].y;
388         tmpRect.right   = pt[1].x;
389         tmpRect.bottom  = pt[1].y;
390         ret = RectInRegion( dc->hGCClipRgn, &tmpRect );
391     }
392     GDI_ReleaseObj( hdc );
393     return ret;
394 }
395
396
397 /***********************************************************************
398  *           GetClipBox    (GDI32.@)
399  */
400 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
401 {
402     INT ret;
403     DC *dc = DC_GetDCUpdate( hdc );
404     if (!dc) return ERROR;
405     ret = GetRgnBox( dc->hGCClipRgn, rect );
406     DPtoLP( hdc, (LPPOINT)rect, 2 );
407     GDI_ReleaseObj( hdc );
408     return ret;
409 }
410
411
412 /***********************************************************************
413  *           GetClipRgn  (GDI32.@)
414  */
415 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
416 {
417     INT ret = -1;
418     DC * dc;
419     if (hRgn && (dc = DC_GetDCPtr( hdc )))
420     {
421       if( dc->hClipRgn )
422       {
423           if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR ) ret = 1;
424       }
425       else ret = 0;
426       GDI_ReleaseObj( hdc );
427     }
428     return ret;
429 }
430
431 /***********************************************************************
432  *           SaveVisRgn   (GDI.129)
433  */
434 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc16 )
435 {
436     HRGN copy;
437     GDIOBJHDR *obj, *copyObj;
438     HDC hdc = HDC_32( hdc16 );
439     DC *dc = DC_GetDCUpdate( hdc );
440
441     if (!dc) return 0;
442     TRACE("%p\n", hdc );
443
444     if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
445     {
446         GDI_ReleaseObj( hdc );
447         return 0;
448     }
449     if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
450     {
451         GDI_ReleaseObj( dc->hVisRgn );
452         GDI_ReleaseObj( hdc );
453         return 0;
454     }
455     CombineRgn( copy, dc->hVisRgn, 0, RGN_COPY );
456     if (!(copyObj = GDI_GetObjPtr( copy, REGION_MAGIC )))
457     {
458         DeleteObject( copy );
459         GDI_ReleaseObj( dc->hVisRgn );
460         GDI_ReleaseObj( hdc );
461         return 0;
462     }
463     copyObj->hNext = obj->hNext;
464     obj->hNext = HRGN_16(copy);
465     GDI_ReleaseObj( copy );
466     GDI_ReleaseObj( dc->hVisRgn );
467     GDI_ReleaseObj( hdc );
468     return HRGN_16(copy);
469 }
470
471
472 /***********************************************************************
473  *           RestoreVisRgn   (GDI.130)
474  */
475 INT16 WINAPI RestoreVisRgn16( HDC16 hdc16 )
476 {
477     HRGN saved;
478     GDIOBJHDR *obj, *savedObj;
479     HDC hdc = HDC_32( hdc16 );
480     DC *dc = DC_GetDCPtr( hdc );
481     INT16 ret = ERROR;
482
483     if (!dc) return ERROR;
484
485     TRACE("%p\n", hdc );
486
487     if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
488     saved = HRGN_32(obj->hNext);
489
490     if ((savedObj = GDI_GetObjPtr( saved, REGION_MAGIC )))
491     {
492         ret = CombineRgn( dc->hVisRgn, saved, 0, RGN_COPY );
493         obj->hNext = savedObj->hNext;
494         GDI_ReleaseObj( saved );
495         DeleteObject( saved );
496         dc->flags &= ~DC_DIRTY;
497         CLIPPING_UpdateGCRegion( dc );
498     }
499     GDI_ReleaseObj( dc->hVisRgn );
500  done:
501     GDI_ReleaseObj( hdc );
502     return ret;
503 }
504
505
506 /***********************************************************************
507  * GetRandomRgn [GDI32.@]
508  *
509  * NOTES
510  *     This function is documented in MSDN online for the case of
511  *     dwCode == SYSRGN (4).
512  *
513  *     For dwCode == 1 it should return the clip region
514  *                   2 "    "       "   the meta region
515  *                   3 "    "       "   the intersection of the clip with
516  *                                      the meta region (== 'Rao' region).
517  *
518  *     See http://www.codeproject.com/gdi/cliprgnguide.asp
519  */
520 INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, DWORD dwCode)
521 {
522     switch (dwCode)
523     {
524     case SYSRGN: /* == 4 */
525         {
526             DC *dc = DC_GetDCPtr (hDC);
527             if (!dc) return -1;
528
529             CombineRgn (hRgn, dc->hVisRgn, 0, RGN_COPY);
530             GDI_ReleaseObj( hDC );
531             /*
532              *     On Windows NT/2000,
533              *           the region returned is in screen coordinates.
534              *     On Windows 95/98,
535              *           the region returned is in window coordinates
536              */
537             if (!(GetVersion() & 0x80000000))
538             {
539                 POINT org;
540                 GetDCOrgEx(hDC, &org);
541                 OffsetRgn(hRgn, org.x, org.y);
542             }
543             return 1;
544         }
545
546     case 1: /* clip region */
547             return GetClipRgn (hDC, hRgn);
548
549     default:
550         WARN("Unknown dwCode %ld\n", dwCode);
551         return -1;
552     }
553
554     return -1;
555 }
556
557
558 /***********************************************************************
559  *           GetMetaRgn    (GDI32.@)
560  */
561 INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
562 {
563     FIXME( "stub\n" );
564
565     return 0;
566 }
567
568
569 /***********************************************************************
570  *           SetMetaRgn    (GDI32.@)
571  */
572 INT WINAPI SetMetaRgn( HDC hdc )
573 {
574     FIXME( "stub\n" );
575
576     return ERROR;
577 }