gdi32: Use NtGdiExcludeClipRect for ExcludeClipRect implementation.
[wine.git] / dlls / oleacc / client.c
blob3b33be55a21c6cdd9118088254fba2d8080415c7
1 /*
2 * Copyright 2014 Piotr Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include "oleacc_private.h"
23 #include "wine/debug.h"
24 #include "wine/heap.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
28 typedef struct {
29 IAccessible IAccessible_iface;
30 IOleWindow IOleWindow_iface;
31 IEnumVARIANT IEnumVARIANT_iface;
33 LONG ref;
35 HWND hwnd;
36 HWND enum_pos;
37 } Client;
39 static inline Client* impl_from_Client(IAccessible *iface)
41 return CONTAINING_RECORD(iface, Client, IAccessible_iface);
44 static HRESULT WINAPI Client_QueryInterface(IAccessible *iface, REFIID riid, void **ppv)
46 Client *This = impl_from_Client(iface);
48 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
50 if(IsEqualIID(riid, &IID_IAccessible) ||
51 IsEqualIID(riid, &IID_IDispatch) ||
52 IsEqualIID(riid, &IID_IUnknown)) {
53 *ppv = iface;
54 }else if(IsEqualIID(riid, &IID_IOleWindow)) {
55 *ppv = &This->IOleWindow_iface;
56 }else if(IsEqualIID(riid, &IID_IEnumVARIANT)) {
57 *ppv = &This->IEnumVARIANT_iface;
58 }else {
59 WARN("no interface: %s\n", debugstr_guid(riid));
60 *ppv = NULL;
61 return E_NOINTERFACE;
64 IAccessible_AddRef(iface);
65 return S_OK;
68 static ULONG WINAPI Client_AddRef(IAccessible *iface)
70 Client *This = impl_from_Client(iface);
71 ULONG ref = InterlockedIncrement(&This->ref);
73 TRACE("(%p) ref = %u\n", This, ref);
74 return ref;
77 static ULONG WINAPI Client_Release(IAccessible *iface)
79 Client *This = impl_from_Client(iface);
80 ULONG ref = InterlockedDecrement(&This->ref);
82 TRACE("(%p) ref = %u\n", This, ref);
84 if(!ref)
85 heap_free(This);
86 return ref;
89 static HRESULT WINAPI Client_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
91 Client *This = impl_from_Client(iface);
92 FIXME("(%p)->(%p)\n", This, pctinfo);
93 return E_NOTIMPL;
96 static HRESULT WINAPI Client_GetTypeInfo(IAccessible *iface,
97 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
99 Client *This = impl_from_Client(iface);
100 FIXME("(%p)->(%u %x %p)\n", This, iTInfo, lcid, ppTInfo);
101 return E_NOTIMPL;
104 static HRESULT WINAPI Client_GetIDsOfNames(IAccessible *iface, REFIID riid,
105 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
107 Client *This = impl_from_Client(iface);
108 FIXME("(%p)->(%s %p %u %x %p)\n", This, debugstr_guid(riid),
109 rgszNames, cNames, lcid, rgDispId);
110 return E_NOTIMPL;
113 static HRESULT WINAPI Client_Invoke(IAccessible *iface, DISPID dispIdMember,
114 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
115 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
117 Client *This = impl_from_Client(iface);
118 FIXME("(%p)->(%x %s %x %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
119 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
120 return E_NOTIMPL;
123 static HRESULT WINAPI Client_get_accParent(IAccessible *iface, IDispatch **ppdispParent)
125 Client *This = impl_from_Client(iface);
127 TRACE("(%p)->(%p)\n", This, ppdispParent);
129 return AccessibleObjectFromWindow(This->hwnd, OBJID_WINDOW,
130 &IID_IDispatch, (void**)ppdispParent);
133 static HRESULT WINAPI Client_get_accChildCount(IAccessible *iface, LONG *pcountChildren)
135 Client *This = impl_from_Client(iface);
136 HWND cur;
138 TRACE("(%p)->(%p)\n", This, pcountChildren);
140 *pcountChildren = 0;
141 for(cur = GetWindow(This->hwnd, GW_CHILD); cur; cur = GetWindow(cur, GW_HWNDNEXT))
142 (*pcountChildren)++;
144 return S_OK;
147 static HRESULT WINAPI Client_get_accChild(IAccessible *iface,
148 VARIANT varChildID, IDispatch **ppdispChild)
150 Client *This = impl_from_Client(iface);
152 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varChildID), ppdispChild);
154 *ppdispChild = NULL;
155 return E_INVALIDARG;
158 static HRESULT WINAPI Client_get_accName(IAccessible *iface, VARIANT varID, BSTR *pszName)
160 Client *This = impl_from_Client(iface);
161 WCHAR name[1024];
162 UINT i, len;
164 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszName);
166 *pszName = NULL;
167 if(convert_child_id(&varID) != CHILDID_SELF || !IsWindow(This->hwnd))
168 return E_INVALIDARG;
170 len = SendMessageW(This->hwnd, WM_GETTEXT, ARRAY_SIZE(name), (LPARAM)name);
171 if(!len)
172 return S_FALSE;
174 for(i=0; i<len; i++) {
175 if(name[i] == '&') {
176 len--;
177 memmove(name+i, name+i+1, (len-i)*sizeof(WCHAR));
178 break;
182 *pszName = SysAllocStringLen(name, len);
183 return *pszName ? S_OK : E_OUTOFMEMORY;
186 static HRESULT WINAPI Client_get_accValue(IAccessible *iface, VARIANT varID, BSTR *pszValue)
188 Client *This = impl_from_Client(iface);
190 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszValue);
192 *pszValue = NULL;
193 if(convert_child_id(&varID) != CHILDID_SELF)
194 return E_INVALIDARG;
195 return S_FALSE;
198 static HRESULT WINAPI Client_get_accDescription(IAccessible *iface,
199 VARIANT varID, BSTR *pszDescription)
201 Client *This = impl_from_Client(iface);
203 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDescription);
205 *pszDescription = NULL;
206 if(convert_child_id(&varID) != CHILDID_SELF)
207 return E_INVALIDARG;
208 return S_FALSE;
211 static HRESULT WINAPI Client_get_accRole(IAccessible *iface, VARIANT varID, VARIANT *pvarRole)
213 Client *This = impl_from_Client(iface);
215 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarRole);
217 if(convert_child_id(&varID) != CHILDID_SELF) {
218 V_VT(pvarRole) = VT_EMPTY;
219 return E_INVALIDARG;
222 V_VT(pvarRole) = VT_I4;
223 V_I4(pvarRole) = ROLE_SYSTEM_CLIENT;
224 return S_OK;
227 static HRESULT WINAPI Client_get_accState(IAccessible *iface, VARIANT varID, VARIANT *pvarState)
229 Client *This = impl_from_Client(iface);
230 LONG style;
232 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pvarState);
234 if(convert_child_id(&varID) != CHILDID_SELF) {
235 V_VT(pvarState) = VT_EMPTY;
236 return E_INVALIDARG;
239 V_VT(pvarState) = VT_I4;
240 V_I4(pvarState) = 0;
242 style = GetWindowLongW(This->hwnd, GWL_STYLE);
243 if(style & WS_DISABLED)
244 V_I4(pvarState) |= STATE_SYSTEM_UNAVAILABLE;
245 else if(IsWindow(This->hwnd))
246 V_I4(pvarState) |= STATE_SYSTEM_FOCUSABLE;
247 if(GetFocus() == This->hwnd)
248 V_I4(pvarState) |= STATE_SYSTEM_FOCUSED;
249 if(!(style & WS_VISIBLE))
250 V_I4(pvarState) |= STATE_SYSTEM_INVISIBLE;
251 return S_OK;
254 static HRESULT WINAPI Client_get_accHelp(IAccessible *iface, VARIANT varID, BSTR *pszHelp)
256 Client *This = impl_from_Client(iface);
258 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszHelp);
260 *pszHelp = NULL;
261 if(convert_child_id(&varID) != CHILDID_SELF)
262 return E_INVALIDARG;
263 return S_FALSE;
266 static HRESULT WINAPI Client_get_accHelpTopic(IAccessible *iface,
267 BSTR *pszHelpFile, VARIANT varID, LONG *pidTopic)
269 Client *This = impl_from_Client(iface);
270 FIXME("(%p)->(%p %s %p)\n", This, pszHelpFile, debugstr_variant(&varID), pidTopic);
271 return E_NOTIMPL;
274 static HRESULT WINAPI Client_get_accKeyboardShortcut(IAccessible *iface,
275 VARIANT varID, BSTR *pszKeyboardShortcut)
277 Client *This = impl_from_Client(iface);
278 WCHAR name[1024];
279 UINT i, len;
281 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszKeyboardShortcut);
283 *pszKeyboardShortcut = NULL;
284 if(convert_child_id(&varID) != CHILDID_SELF)
285 return E_INVALIDARG;
287 len = SendMessageW(This->hwnd, WM_GETTEXT, ARRAY_SIZE(name), (LPARAM)name);
288 for(i=0; i<len; i++) {
289 if(name[i] == '&')
290 break;
292 if(i+1 >= len)
293 return S_FALSE;
295 *pszKeyboardShortcut = SysAllocString(L"Alt+!");
296 if(!*pszKeyboardShortcut)
297 return E_OUTOFMEMORY;
299 (*pszKeyboardShortcut)[4] = name[i+1];
300 return S_OK;
303 static HRESULT WINAPI Client_get_accFocus(IAccessible *iface, VARIANT *pvarID)
305 Client *This = impl_from_Client(iface);
306 FIXME("(%p)->(%p)\n", This, pvarID);
307 return E_NOTIMPL;
310 static HRESULT WINAPI Client_get_accSelection(IAccessible *iface, VARIANT *pvarID)
312 Client *This = impl_from_Client(iface);
313 FIXME("(%p)->(%p)\n", This, pvarID);
314 return E_NOTIMPL;
317 static HRESULT WINAPI Client_get_accDefaultAction(IAccessible *iface,
318 VARIANT varID, BSTR *pszDefaultAction)
320 Client *This = impl_from_Client(iface);
322 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(&varID), pszDefaultAction);
324 *pszDefaultAction = NULL;
325 if(convert_child_id(&varID) != CHILDID_SELF)
326 return E_INVALIDARG;
327 return S_FALSE;
330 static HRESULT WINAPI Client_accSelect(IAccessible *iface, LONG flagsSelect, VARIANT varID)
332 Client *This = impl_from_Client(iface);
333 FIXME("(%p)->(%x %s)\n", This, flagsSelect, debugstr_variant(&varID));
334 return E_NOTIMPL;
337 static HRESULT WINAPI Client_accLocation(IAccessible *iface, LONG *pxLeft,
338 LONG *pyTop, LONG *pcxWidth, LONG *pcyHeight, VARIANT varID)
340 Client *This = impl_from_Client(iface);
341 RECT rect;
342 POINT pt;
344 TRACE("(%p)->(%p %p %p %p %s)\n", This, pxLeft, pyTop,
345 pcxWidth, pcyHeight, debugstr_variant(&varID));
347 *pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
348 if(convert_child_id(&varID) != CHILDID_SELF)
349 return E_INVALIDARG;
351 if(!GetClientRect(This->hwnd, &rect))
352 return S_OK;
354 pt.x = rect.left;
355 pt.y = rect.top;
356 MapWindowPoints(This->hwnd, NULL, &pt, 1);
357 *pxLeft = pt.x;
358 *pyTop = pt.y;
360 pt.x = rect.right;
361 pt.y = rect.bottom;
362 MapWindowPoints(This->hwnd, NULL, &pt, 1);
363 *pcxWidth = pt.x - *pxLeft;
364 *pcyHeight = pt.y - *pyTop;
365 return S_OK;
368 static HRESULT WINAPI Client_accNavigate(IAccessible *iface,
369 LONG navDir, VARIANT varStart, VARIANT *pvarEnd)
371 Client *This = impl_from_Client(iface);
372 FIXME("(%p)->(%d %s %p)\n", This, navDir, debugstr_variant(&varStart), pvarEnd);
373 return E_NOTIMPL;
376 static HRESULT WINAPI Client_accHitTest(IAccessible *iface,
377 LONG xLeft, LONG yTop, VARIANT *pvarID)
379 Client *This = impl_from_Client(iface);
380 HWND child;
381 POINT pt;
383 TRACE("(%p)->(%d %d %p)\n", This, xLeft, yTop, pvarID);
385 V_VT(pvarID) = VT_I4;
386 V_I4(pvarID) = 0;
388 pt.x = xLeft;
389 pt.y = yTop;
390 if(!IsWindowVisible(This->hwnd) || !ScreenToClient(This->hwnd, &pt))
391 return S_OK;
393 child = ChildWindowFromPointEx(This->hwnd, pt, CWP_SKIPINVISIBLE);
394 if(!child || child==This->hwnd)
395 return S_OK;
397 V_VT(pvarID) = VT_DISPATCH;
398 return AccessibleObjectFromWindow(child, OBJID_WINDOW,
399 &IID_IDispatch, (void**)&V_DISPATCH(pvarID));
402 static HRESULT WINAPI Client_accDoDefaultAction(IAccessible *iface, VARIANT varID)
404 Client *This = impl_from_Client(iface);
405 FIXME("(%p)->(%s)\n", This, debugstr_variant(&varID));
406 return E_NOTIMPL;
409 static HRESULT WINAPI Client_put_accName(IAccessible *iface, VARIANT varID, BSTR pszName)
411 Client *This = impl_from_Client(iface);
412 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszName));
413 return E_NOTIMPL;
416 static HRESULT WINAPI Client_put_accValue(IAccessible *iface, VARIANT varID, BSTR pszValue)
418 Client *This = impl_from_Client(iface);
419 FIXME("(%p)->(%s %s)\n", This, debugstr_variant(&varID), debugstr_w(pszValue));
420 return E_NOTIMPL;
423 static const IAccessibleVtbl ClientVtbl = {
424 Client_QueryInterface,
425 Client_AddRef,
426 Client_Release,
427 Client_GetTypeInfoCount,
428 Client_GetTypeInfo,
429 Client_GetIDsOfNames,
430 Client_Invoke,
431 Client_get_accParent,
432 Client_get_accChildCount,
433 Client_get_accChild,
434 Client_get_accName,
435 Client_get_accValue,
436 Client_get_accDescription,
437 Client_get_accRole,
438 Client_get_accState,
439 Client_get_accHelp,
440 Client_get_accHelpTopic,
441 Client_get_accKeyboardShortcut,
442 Client_get_accFocus,
443 Client_get_accSelection,
444 Client_get_accDefaultAction,
445 Client_accSelect,
446 Client_accLocation,
447 Client_accNavigate,
448 Client_accHitTest,
449 Client_accDoDefaultAction,
450 Client_put_accName,
451 Client_put_accValue
454 static inline Client* impl_from_Client_OleWindow(IOleWindow *iface)
456 return CONTAINING_RECORD(iface, Client, IOleWindow_iface);
459 static HRESULT WINAPI Client_OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **ppv)
461 Client *This = impl_from_Client_OleWindow(iface);
462 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
465 static ULONG WINAPI Client_OleWindow_AddRef(IOleWindow *iface)
467 Client *This = impl_from_Client_OleWindow(iface);
468 return IAccessible_AddRef(&This->IAccessible_iface);
471 static ULONG WINAPI Client_OleWindow_Release(IOleWindow *iface)
473 Client *This = impl_from_Client_OleWindow(iface);
474 return IAccessible_Release(&This->IAccessible_iface);
477 static HRESULT WINAPI Client_OleWindow_GetWindow(IOleWindow *iface, HWND *phwnd)
479 Client *This = impl_from_Client_OleWindow(iface);
481 TRACE("(%p)->(%p)\n", This, phwnd);
483 *phwnd = This->hwnd;
484 return S_OK;
487 static HRESULT WINAPI Client_OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMode)
489 Client *This = impl_from_Client_OleWindow(iface);
490 FIXME("(%p)->(%x)\n", This, fEnterMode);
491 return E_NOTIMPL;
494 static const IOleWindowVtbl ClientOleWindowVtbl = {
495 Client_OleWindow_QueryInterface,
496 Client_OleWindow_AddRef,
497 Client_OleWindow_Release,
498 Client_OleWindow_GetWindow,
499 Client_OleWindow_ContextSensitiveHelp
502 static inline Client* impl_from_Client_EnumVARIANT(IEnumVARIANT *iface)
504 return CONTAINING_RECORD(iface, Client, IEnumVARIANT_iface);
507 static HRESULT WINAPI Client_EnumVARIANT_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
509 Client *This = impl_from_Client_EnumVARIANT(iface);
510 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, ppv);
513 static ULONG WINAPI Client_EnumVARIANT_AddRef(IEnumVARIANT *iface)
515 Client *This = impl_from_Client_EnumVARIANT(iface);
516 return IAccessible_AddRef(&This->IAccessible_iface);
519 static ULONG WINAPI Client_EnumVARIANT_Release(IEnumVARIANT *iface)
521 Client *This = impl_from_Client_EnumVARIANT(iface);
522 return IAccessible_Release(&This->IAccessible_iface);
525 static HRESULT WINAPI Client_EnumVARIANT_Next(IEnumVARIANT *iface,
526 ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
528 Client *This = impl_from_Client_EnumVARIANT(iface);
529 HWND cur = This->enum_pos, next;
530 ULONG fetched = 0;
531 HRESULT hr;
533 TRACE("(%p)->(%u %p %p)\n", This, celt, rgVar, pCeltFetched);
535 if(!celt) {
536 if(pCeltFetched)
537 *pCeltFetched = 0;
538 return S_OK;
541 if(!This->enum_pos)
542 next = GetWindow(This->hwnd, GW_CHILD);
543 else
544 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
546 while(next) {
547 cur = next;
549 V_VT(rgVar+fetched) = VT_DISPATCH;
550 hr = AccessibleObjectFromWindow(cur, OBJID_WINDOW,
551 &IID_IDispatch, (void**)&V_DISPATCH(rgVar+fetched));
552 if(FAILED(hr)) {
553 V_VT(rgVar+fetched) = VT_EMPTY;
554 while(fetched > 0) {
555 VariantClear(rgVar+fetched-1);
556 fetched--;
558 if(pCeltFetched)
559 *pCeltFetched = 0;
560 return hr;
562 fetched++;
563 if(fetched == celt)
564 break;
566 next = GetWindow(cur, GW_HWNDNEXT);
569 This->enum_pos = cur;
570 if(pCeltFetched)
571 *pCeltFetched = fetched;
572 return celt == fetched ? S_OK : S_FALSE;
575 static HRESULT WINAPI Client_EnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt)
577 Client *This = impl_from_Client_EnumVARIANT(iface);
578 HWND next;
580 TRACE("(%p)->(%u)\n", This, celt);
582 while(celt) {
583 if(!This->enum_pos)
584 next = GetWindow(This->hwnd, GW_CHILD);
585 else
586 next = GetWindow(This->enum_pos, GW_HWNDNEXT);
587 if(!next)
588 return S_FALSE;
590 This->enum_pos = next;
591 celt--;
594 return S_OK;
597 static HRESULT WINAPI Client_EnumVARIANT_Reset(IEnumVARIANT *iface)
599 Client *This = impl_from_Client_EnumVARIANT(iface);
601 TRACE("(%p)\n", This);
603 This->enum_pos = 0;
604 return S_OK;
607 static HRESULT WINAPI Client_EnumVARIANT_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
609 Client *This = impl_from_Client_EnumVARIANT(iface);
610 FIXME("(%p)->(%p)\n", This, ppEnum);
611 return E_NOTIMPL;
614 static const IEnumVARIANTVtbl ClientEnumVARIANTVtbl = {
615 Client_EnumVARIANT_QueryInterface,
616 Client_EnumVARIANT_AddRef,
617 Client_EnumVARIANT_Release,
618 Client_EnumVARIANT_Next,
619 Client_EnumVARIANT_Skip,
620 Client_EnumVARIANT_Reset,
621 Client_EnumVARIANT_Clone
624 HRESULT create_client_object(HWND hwnd, const IID *iid, void **obj)
626 Client *client;
627 HRESULT hres;
629 if(!IsWindow(hwnd))
630 return E_FAIL;
632 client = heap_alloc_zero(sizeof(Client));
633 if(!client)
634 return E_OUTOFMEMORY;
636 client->IAccessible_iface.lpVtbl = &ClientVtbl;
637 client->IOleWindow_iface.lpVtbl = &ClientOleWindowVtbl;
638 client->IEnumVARIANT_iface.lpVtbl = &ClientEnumVARIANTVtbl;
639 client->ref = 1;
640 client->hwnd = hwnd;
641 client->enum_pos = 0;
643 hres = IAccessible_QueryInterface(&client->IAccessible_iface, iid, obj);
644 IAccessible_Release(&client->IAccessible_iface);
645 return hres;