Initialize the output buffer parameters to 0 in RegQueryValue*
[wine.git] / objects / clipping.c
blob172acda3875ddce54f712bce5cc1d32af92e347e
1 /*
2 * DC clipping functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include "dc.h"
9 #include "metafiledrv.h"
10 #include "region.h"
11 #include "debug.h"
12 #include "wine/winuser16.h"
14 DECLARE_DEBUG_CHANNEL(clipping)
15 DECLARE_DEBUG_CHANNEL(region)
17 #define UPDATE_DIRTY_DC(dc) \
18 do { \
19 if ((dc)->hookProc && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
20 (dc)->hookProc( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
21 } while(0)
25 /***********************************************************************
26 * CLIPPING_UpdateGCRegion
28 * Update the GC clip region when the ClipRgn or VisRgn have changed.
30 void CLIPPING_UpdateGCRegion( DC * dc )
32 if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
34 if (!dc->w.hVisRgn)
36 ERR(region, "hVisRgn is zero. Please report this.\n" );
37 exit(1);
40 if (dc->w.flags & DC_DIRTY)
42 UPDATE_DIRTY_DC(dc);
43 dc->w.flags &= ~DC_DIRTY;
46 if (!dc->w.hClipRgn)
47 CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
48 else
49 CombineRgn(dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND);
50 if (dc->funcs->pSetDeviceClipping) dc->funcs->pSetDeviceClipping( dc );
54 /***********************************************************************
55 * SelectClipRgn16 (GDI.44)
57 INT16 WINAPI SelectClipRgn16( HDC16 hdc, HRGN16 hrgn )
59 return (INT16)SelectClipRgn( hdc, hrgn );
63 /***********************************************************************
64 * SelectClipRgn32 (GDI32.297)
66 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
68 return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
71 /******************************************************************************
72 * ExtSelectClipRgn [GDI32.97]
74 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
76 INT retval;
77 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
78 if (!dc) return ERROR;
80 TRACE( clipping, "%04x %04x %d\n", hdc, hrgn, fnMode );
82 if (!hrgn)
84 if (fnMode == RGN_COPY)
86 if (dc->w.hClipRgn) DeleteObject16( dc->w.hClipRgn );
87 dc->w.hClipRgn = 0;
88 retval = SIMPLEREGION; /* Clip region == whole DC */
90 else
92 FIXME(clipping, "Unimplemented: hrgn NULL in mode: %d\n", fnMode);
93 return ERROR;
96 else
98 if (!dc->w.hClipRgn)
100 RECT rect;
101 GetRgnBox( dc->w.hVisRgn, &rect );
102 dc->w.hClipRgn = CreateRectRgnIndirect( &rect );
105 OffsetRgn( dc->w.hClipRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
106 if(fnMode == RGN_COPY)
107 retval = CombineRgn( dc->w.hClipRgn, hrgn, 0, fnMode );
108 else
109 retval = CombineRgn( dc->w.hClipRgn, dc->w.hClipRgn, hrgn, fnMode);
110 OffsetRgn( dc->w.hClipRgn, dc->w.DCOrgX, dc->w.DCOrgY );
114 CLIPPING_UpdateGCRegion( dc );
115 GDI_HEAP_UNLOCK( hdc );
116 return retval;
119 /***********************************************************************
120 * SelectVisRgn (GDI.105)
122 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
124 int retval;
125 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
126 if (!dc || !hrgn) return ERROR;
128 TRACE(clipping, "%04x %04x\n", hdc, hrgn );
130 dc->w.flags &= ~DC_DIRTY;
132 retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
133 CLIPPING_UpdateGCRegion( dc );
134 GDI_HEAP_UNLOCK( hdc );
135 return retval;
139 /***********************************************************************
140 * OffsetClipRgn16 (GDI.32)
142 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
144 return (INT16)OffsetClipRgn( hdc, x, y );
148 /***********************************************************************
149 * OffsetClipRgn32 (GDI32.255)
151 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
153 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
154 if (!dc)
156 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
157 if (!dc) return ERROR;
158 MFDRV_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
159 GDI_HEAP_UNLOCK( hdc );
160 return NULLREGION; /* ?? */
163 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
165 if (dc->w.hClipRgn)
167 INT ret = OffsetRgn( dc->w.hClipRgn, XLPTODP(dc,x), YLPTODP(dc,y));
168 CLIPPING_UpdateGCRegion( dc );
169 GDI_HEAP_UNLOCK( hdc );
170 return ret;
172 GDI_HEAP_UNLOCK( hdc );
173 return SIMPLEREGION; /* Clip region == client area */
177 /***********************************************************************
178 * OffsetVisRgn (GDI.102)
180 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
182 INT16 retval;
183 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
184 if (!dc) return ERROR;
185 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
186 retval = OffsetRgn( dc->w.hVisRgn, x, y );
187 CLIPPING_UpdateGCRegion( dc );
188 GDI_HEAP_UNLOCK( hdc );
189 return retval;
193 /***********************************************************************
194 * CLIPPING_IntersectClipRect
196 * Helper function for {Intersect,Exclude}ClipRect, can be called from
197 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
198 * coordinate conversion.
200 INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
201 INT right, INT bottom, UINT flags )
203 HRGN newRgn;
204 INT ret;
206 left += dc->w.DCOrgX;
207 right += dc->w.DCOrgX;
208 top += dc->w.DCOrgY;
209 bottom += dc->w.DCOrgY;
211 if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
212 if (!dc->w.hClipRgn)
214 if( flags & CLIP_INTERSECT )
216 dc->w.hClipRgn = newRgn;
217 CLIPPING_UpdateGCRegion( dc );
218 return SIMPLEREGION;
220 else if( flags & CLIP_EXCLUDE )
222 dc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
223 CombineRgn( dc->w.hClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
225 else WARN(clipping,"No hClipRgn and flags are %x\n",flags);
228 ret = CombineRgn( newRgn, dc->w.hClipRgn, newRgn,
229 (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
230 if (ret != ERROR)
232 if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->w.hClipRgn );
233 dc->w.hClipRgn = newRgn;
234 CLIPPING_UpdateGCRegion( dc );
236 else DeleteObject( newRgn );
237 return ret;
241 /***********************************************************************
242 * ExcludeClipRect16 (GDI.21)
244 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
245 INT16 right, INT16 bottom )
247 return (INT16)ExcludeClipRect( hdc, left, top, right, bottom );
251 /***********************************************************************
252 * ExcludeClipRect32 (GDI32.92)
254 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
255 INT right, INT bottom )
257 INT ret;
258 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
259 if (!dc)
261 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
262 if (!dc) return ERROR;
263 MFDRV_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
264 GDI_HEAP_UNLOCK( hdc );
265 return NULLREGION; /* ?? */
268 left = XLPTODP( dc, left );
269 right = XLPTODP( dc, right );
270 top = YLPTODP( dc, top );
271 bottom = YLPTODP( dc, bottom );
273 TRACE(clipping, "%04x %dx%d,%dx%d\n",
274 hdc, left, top, right, bottom );
275 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
276 GDI_HEAP_UNLOCK( hdc );
277 return ret;
281 /***********************************************************************
282 * IntersectClipRect16 (GDI.22)
284 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
285 INT16 right, INT16 bottom )
287 return (INT16)IntersectClipRect( hdc, left, top, right, bottom );
291 /***********************************************************************
292 * IntersectClipRect32 (GDI32.245)
294 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top,
295 INT right, INT bottom )
297 INT ret;
298 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
299 if (!dc)
301 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
302 if (!dc) return ERROR;
303 MFDRV_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
304 GDI_HEAP_UNLOCK( hdc );
305 return NULLREGION; /* ?? */
308 left = XLPTODP( dc, left );
309 right = XLPTODP( dc, right );
310 top = YLPTODP( dc, top );
311 bottom = YLPTODP( dc, bottom );
313 TRACE(clipping, "%04x %dx%d,%dx%d\n",
314 hdc, left, top, right, bottom );
315 ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
316 GDI_HEAP_UNLOCK( hdc );
317 return ret;
321 /***********************************************************************
322 * CLIPPING_IntersectVisRect
324 * Helper function for {Intersect,Exclude}VisRect, can be called from
325 * elsewhere (like ExtTextOut()) to skip redundant metafile update and
326 * coordinate conversion.
328 INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
329 INT right, INT bottom,
330 BOOL exclude )
332 HRGN tempRgn, newRgn;
333 INT ret;
335 left += dc->w.DCOrgX;
336 right += dc->w.DCOrgX;
337 top += dc->w.DCOrgY;
338 bottom += dc->w.DCOrgY;
340 if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
341 if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
343 DeleteObject( newRgn );
344 return ERROR;
346 ret = CombineRgn( newRgn, dc->w.hVisRgn, tempRgn,
347 exclude ? RGN_DIFF : RGN_AND );
348 DeleteObject( tempRgn );
350 if (ret != ERROR)
352 RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
353 RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
354 if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
355 DeleteObject( dc->w.hVisRgn );
356 dc->w.hVisRgn = newRgn;
357 CLIPPING_UpdateGCRegion( dc );
358 GDI_HEAP_UNLOCK( newRgn );
360 else DeleteObject( newRgn );
361 return ret;
365 /***********************************************************************
366 * ExcludeVisRect (GDI.73)
368 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
369 INT16 right, INT16 bottom )
371 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
372 if (!dc) return ERROR;
374 left = XLPTODP( dc, left );
375 right = XLPTODP( dc, right );
376 top = YLPTODP( dc, top );
377 bottom = YLPTODP( dc, bottom );
379 TRACE(clipping, "%04x %dx%d,%dx%d\n",
380 hdc, left, top, right, bottom );
382 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
386 /***********************************************************************
387 * IntersectVisRect (GDI.98)
389 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
390 INT16 right, INT16 bottom )
392 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
393 if (!dc) return ERROR;
395 left = XLPTODP( dc, left );
396 right = XLPTODP( dc, right );
397 top = YLPTODP( dc, top );
398 bottom = YLPTODP( dc, bottom );
400 TRACE(clipping, "%04x %dx%d,%dx%d\n",
401 hdc, left, top, right, bottom );
403 return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
407 /***********************************************************************
408 * PtVisible16 (GDI.103)
410 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
412 return PtVisible( hdc, x, y );
416 /***********************************************************************
417 * PtVisible32 (GDI32.279)
419 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
421 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
422 if (!dc) return ERROR;
424 TRACE(clipping, "%04x %d,%d\n", hdc, x, y );
425 if (!dc->w.hGCClipRgn) return FALSE;
427 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
428 dc->w.flags &= ~DC_DIRTY;
430 return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX,
431 YLPTODP(dc,y) + dc->w.DCOrgY );
435 /***********************************************************************
436 * RectVisible16 (GDI.104)
438 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
440 RECT16 tmpRect;
441 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
442 if (!dc) return FALSE;
443 TRACE(clipping,"%04x %d,%dx%d,%d\n",
444 hdc, rect->left, rect->top, rect->right, rect->bottom );
445 if (!dc->w.hGCClipRgn) return FALSE;
446 /* copy rectangle to avoid overwriting by LPtoDP */
447 tmpRect = *rect;
448 LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
449 OffsetRect16( &tmpRect, dc->w.DCOrgX, dc->w.DCOrgY );
450 return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
454 /***********************************************************************
455 * RectVisible32 (GDI32.282)
457 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
459 RECT16 rect16;
460 CONV_RECT32TO16( rect, &rect16 );
461 return RectVisible16( (HDC16)hdc, &rect16 );
465 /***********************************************************************
466 * GetClipBox16 (GDI.77)
468 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
470 int ret;
471 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
472 if (!dc) return ERROR;
473 ret = GetRgnBox16( dc->w.hGCClipRgn, rect );
474 OffsetRect16( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
475 DPtoLP16( hdc, (LPPOINT16)rect, 2 );
476 TRACE(clipping, "%d,%d-%d,%d\n",
477 rect->left,rect->top,rect->right,rect->bottom );
478 return ret;
482 /***********************************************************************
483 * GetClipBox32 (GDI32.162)
485 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
487 INT ret;
488 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
489 if (!dc) return ERROR;
490 ret = GetRgnBox( dc->w.hGCClipRgn, rect );
491 OffsetRect( rect, -dc->w.DCOrgX, -dc->w.DCOrgY );
492 DPtoLP( hdc, (LPPOINT)rect, 2 );
493 return ret;
497 /***********************************************************************
498 * GetClipRgn32 (GDI32.163)
500 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
502 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
503 if( dc && hRgn )
505 if( dc->w.hClipRgn )
507 /* this assumes that dc->w.hClipRgn is in coordinates
508 relative to the device (not DC origin) */
510 if( CombineRgn(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
512 OffsetRgn( hRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
513 return 1;
516 else return 0;
518 return -1;
521 /***********************************************************************
522 * SaveVisRgn (GDI.129)
524 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
526 HRGN copy;
527 RGNOBJ *obj, *copyObj;
528 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
529 if (!dc) return 0;
530 TRACE(clipping, "%04x\n", hdc );
531 if (!dc->w.hVisRgn)
533 ERR(region, "hVisRgn is zero. Please report this.\n" );
534 exit(1);
536 if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
537 dc->w.flags &= ~DC_DIRTY;
539 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
541 GDI_HEAP_UNLOCK( hdc );
542 return 0;
544 if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
546 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
547 GDI_HEAP_UNLOCK( hdc );
548 return 0;
550 CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
551 if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
553 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
554 GDI_HEAP_UNLOCK( hdc );
555 return 0;
557 copyObj->header.hNext = obj->header.hNext;
558 obj->header.hNext = copy;
559 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
560 GDI_HEAP_UNLOCK( hdc );
561 GDI_HEAP_UNLOCK( copy );
562 return copy;
566 /***********************************************************************
567 * RestoreVisRgn (GDI.130)
569 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
571 HRGN saved;
572 RGNOBJ *obj, *savedObj;
573 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
574 INT16 ret;
576 if (!dc) return ERROR;
577 if (!dc->w.hVisRgn)
579 GDI_HEAP_UNLOCK( hdc );
580 return ERROR;
582 TRACE(clipping, "%04x\n", hdc );
583 if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
585 GDI_HEAP_UNLOCK( hdc );
586 return ERROR;
588 if (!(saved = obj->header.hNext))
590 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
591 GDI_HEAP_UNLOCK( hdc );
592 return ERROR;
594 if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
596 GDI_HEAP_UNLOCK( dc->w.hVisRgn );
597 GDI_HEAP_UNLOCK( hdc );
598 return ERROR;
600 DeleteObject( dc->w.hVisRgn );
601 dc->w.hVisRgn = saved;
602 CLIPPING_UpdateGCRegion( dc );
603 GDI_HEAP_UNLOCK( hdc );
604 ret = savedObj->rgn->type; /* FIXME */
605 GDI_HEAP_UNLOCK( saved );
606 return ret;