Added Norwegian translations.
[wine] / dlls / ddraw / clipper.c
1 /*              DirectDrawClipper implementation
2  *
3  * Copyright 2000 Marcus Meissner
4  * Copyright 2000 TransGaming Technologies Inc.
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 "config.h"
22
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "ddraw.h"
31 #include "winerror.h"
32
33 #include "ddraw_private.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
38
39 /******************************************************************************
40  *                      DirectDrawCreateClipper (DDRAW.@)
41  */
42
43 static const IDirectDrawClipperVtbl DDRAW_Clipper_VTable;
44
45 HRESULT WINAPI DirectDrawCreateClipper(
46     DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, LPUNKNOWN pUnkOuter
47 ) {
48     IDirectDrawClipperImpl* This;
49     TRACE("(%08lx,%p,%p)\n", dwFlags, lplpDDClipper, pUnkOuter);
50
51     if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION;
52
53     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
54                      sizeof(IDirectDrawClipperImpl));
55     if (This == NULL) return E_OUTOFMEMORY;
56
57     ICOM_INIT_INTERFACE(This, IDirectDrawClipper, DDRAW_Clipper_VTable);
58     This->ref = 1;
59     This->hWnd = 0;
60     This->ddraw_owner = NULL;
61
62     *lplpDDClipper = ICOM_INTERFACE(This, IDirectDrawClipper);
63     return DD_OK;
64 }
65
66 /* This is the classfactory implementation. */
67 HRESULT DDRAW_CreateDirectDrawClipper(IUnknown* pUnkOuter, REFIID riid,
68                                       LPVOID* ppObj)
69 {
70     HRESULT hr;
71     LPDIRECTDRAWCLIPPER pClip;
72
73     hr = DirectDrawCreateClipper(0, &pClip, pUnkOuter);
74     if (FAILED(hr)) return hr;
75
76     hr = IDirectDrawClipper_QueryInterface(pClip, riid, ppObj);
77     IDirectDrawClipper_Release(pClip);
78     return hr;
79 }
80
81 /******************************************************************************
82  *                      IDirectDrawClipper
83  */
84 HRESULT WINAPI Main_DirectDrawClipper_SetHwnd(
85     LPDIRECTDRAWCLIPPER iface, DWORD dwFlags, HWND hWnd
86 ) {
87     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
88
89     TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, dwFlags, (DWORD)hWnd);
90     if( dwFlags ) {
91         FIXME("dwFlags = 0x%08lx, not supported.\n",dwFlags);
92         return DDERR_INVALIDPARAMS;
93     }
94
95     This->hWnd = hWnd;
96     return DD_OK;
97 }
98
99 static void Main_DirectDrawClipper_Destroy(IDirectDrawClipperImpl* This)
100 {
101     if (This->ddraw_owner != NULL)
102         Main_DirectDraw_RemoveClipper(This->ddraw_owner, This);
103
104     HeapFree(GetProcessHeap(), 0 ,This);
105 }
106
107 void Main_DirectDrawClipper_ForceDestroy(IDirectDrawClipperImpl* This)
108 {
109     WARN("deleting clipper %p with refcnt %lu\n", This, This->ref);
110     Main_DirectDrawClipper_Destroy(This);
111 }
112
113 ULONG WINAPI Main_DirectDrawClipper_Release(LPDIRECTDRAWCLIPPER iface) {
114     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
115     ULONG ref = InterlockedDecrement(&This->ref);
116
117     TRACE("(%p)->() decrementing from %lu.\n", This, ref + 1);
118
119     if (ref == 0)
120     {
121         Main_DirectDrawClipper_Destroy(This);
122         return 0;
123     }
124     else return ref;
125 }
126
127 /***********************************************************************
128 *           IDirectDrawClipper::GetClipList
129 *
130 * Retrieve a copy of the clip list
131 *
132 * PARAMS
133 *  lpRect  Rectangle to be used to clip the clip list or NULL for the
134 *          entire clip list
135 *  lpClipList structure for the resulting copy of the clip list.
136            If NULL, fills lpdwSize up to the number of bytes necessary to hold
137            the entire clip.
138 *  lpdwSize Size of resulting clip list; size of the buffer at lpClipList
139            or, if lpClipList is NULL, receives the required size of the buffer
140            in bytes
141 * RETURNS
142 *  Either DD_OK or DDERR_*
143 */
144 HRESULT WINAPI Main_DirectDrawClipper_GetClipList(
145     LPDIRECTDRAWCLIPPER iface, LPRECT lpRect, LPRGNDATA lpClipList,
146     LPDWORD lpdwSize)
147 {
148     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
149
150     TRACE("(%p,%p,%p,%p)\n", This, lpRect, lpClipList, lpdwSize);
151
152     if (This->hWnd)
153     {
154         HDC hDC = GetDCEx(This->hWnd, NULL, DCX_WINDOW);
155         if (hDC)
156         {
157             HRGN hRgn = CreateRectRgn(0,0,0,0);
158             if (GetRandomRgn(hDC, hRgn, SYSRGN))
159             {
160                 if (lpRect)
161                 {
162                     HRGN hRgnClip = CreateRectRgn(lpRect->left, lpRect->top,
163                         lpRect->right, lpRect->bottom);
164                     CombineRgn(hRgn, hRgn, hRgnClip, RGN_AND);
165                     DeleteObject(hRgnClip);
166                 }
167                 *lpdwSize = GetRegionData(hRgn, *lpdwSize, lpClipList);
168             }
169             DeleteObject(hRgn);
170             ReleaseDC(This->hWnd, hDC);
171         }
172         return DD_OK;
173     }
174     else
175     {
176         static int warned = 0;
177         if (warned++ < 10)
178             FIXME("(%p,%p,%p,%p),stub!\n",This,lpRect,lpClipList,lpdwSize);
179         if (lpdwSize) *lpdwSize=0;
180         return DDERR_NOCLIPLIST;
181     }
182 }
183
184 /***********************************************************************
185 *           IDirectDrawClipper::SetClipList
186 *
187 * Sets or deletes (if lprgn is NULL) the clip list
188 *
189 * PARAMS
190 *  lprgn   Pointer to a LRGNDATA structure or NULL
191 *  dwFlags not used, must be 0
192 * RETURNS
193 *  Either DD_OK or DDERR_*
194 */
195 HRESULT WINAPI Main_DirectDrawClipper_SetClipList(
196     LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,DWORD dwFlag
197 ) {
198     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
199     static int warned = 0;
200     if (warned++ < 10 || lprgn == NULL)
201         FIXME("(%p,%p,%ld),stub!\n",This,lprgn,dwFlag);
202     return DD_OK;
203 }
204
205 HRESULT WINAPI Main_DirectDrawClipper_QueryInterface(
206     LPDIRECTDRAWCLIPPER iface, REFIID riid, LPVOID* ppvObj
207 ) {
208     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
209
210     if (IsEqualGUID(&IID_IUnknown, riid)
211         || IsEqualGUID(&IID_IDirectDrawClipper, riid))
212     {
213         *ppvObj = ICOM_INTERFACE(This, IDirectDrawClipper);
214         InterlockedIncrement(&This->ref);
215         return S_OK;
216     }
217     else
218     {
219         return E_NOINTERFACE;
220     }
221 }
222
223 ULONG WINAPI Main_DirectDrawClipper_AddRef( LPDIRECTDRAWCLIPPER iface )
224 {
225     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
226     ULONG ref = InterlockedIncrement(&This->ref);
227
228     TRACE("(%p)->() incrementing from %lu.\n", This, ref - 1);
229
230     return ref;
231 }
232
233 HRESULT WINAPI Main_DirectDrawClipper_GetHWnd(
234     LPDIRECTDRAWCLIPPER iface, HWND* hWndPtr
235 ) {
236     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
237     TRACE("(%p)->(%p)\n", This, hWndPtr);
238
239     *hWndPtr = This->hWnd;
240
241     return DD_OK;
242 }
243
244 HRESULT WINAPI Main_DirectDrawClipper_Initialize(
245      LPDIRECTDRAWCLIPPER iface, LPDIRECTDRAW lpDD, DWORD dwFlags
246 ) {
247     IDirectDrawImpl* pOwner;
248     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
249     TRACE("(%p)->(%p,0x%08lx)\n", This, lpDD, dwFlags);
250
251     if (This->ddraw_owner != NULL) return DDERR_ALREADYINITIALIZED;
252
253     pOwner = ICOM_OBJECT(IDirectDrawImpl, IDirectDraw, lpDD);
254     This->ddraw_owner = pOwner;
255     Main_DirectDraw_AddClipper(pOwner, This);
256
257     return DD_OK;
258 }
259
260 HRESULT WINAPI Main_DirectDrawClipper_IsClipListChanged(
261     LPDIRECTDRAWCLIPPER iface, BOOL* lpbChanged
262 ) {
263     IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface;
264     FIXME("(%p)->(%p),stub!\n",This,lpbChanged);
265
266     /* XXX What is safest? */
267     *lpbChanged = FALSE;
268
269     return DD_OK;
270 }
271
272 static const IDirectDrawClipperVtbl DDRAW_Clipper_VTable =
273 {
274     Main_DirectDrawClipper_QueryInterface,
275     Main_DirectDrawClipper_AddRef,
276     Main_DirectDrawClipper_Release,
277     Main_DirectDrawClipper_GetClipList,
278     Main_DirectDrawClipper_GetHWnd,
279     Main_DirectDrawClipper_Initialize,
280     Main_DirectDrawClipper_IsClipListChanged,
281     Main_DirectDrawClipper_SetClipList,
282     Main_DirectDrawClipper_SetHwnd
283 };