f22349714fa016895f0be0ecca81bcf6c2b9e379
[profile/ivi/qtbase.git] / src / plugins / platforms / windows / accessible / iaccessible2.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <QtCore/QtConfig>
42 #ifndef QT_NO_ACCESSIBILITY
43
44 #include "iaccessible2.h"
45 #include "qwindowsaccessibility.h"
46
47 #include <QtGui/qaccessible2.h>
48 #include <QtWidgets/qapplication.h>
49 #include <QtCore/qdebug.h>
50
51 QT_BEGIN_NAMESPACE
52
53 /**************************************************************\
54  *                     AccessibleApplication                  *
55  **************************************************************/
56 //  IUnknown
57 HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOID *iface)
58 {
59     *iface = 0;
60     if (id == IID_IUnknown) {
61         accessibleDebug("AccessibleApplication::QI(): IID_IUnknown");
62         *iface = (IUnknown*)this;
63     } else if (id == IID_IAccessibleApplication) {
64         accessibleDebug("AccessibleApplication::QI(): IID_IAccessibleApplication");
65         *iface = static_cast<IAccessibleApplication*>(this);
66     }
67
68     if (*iface) {
69         AddRef();
70         return S_OK;
71     }
72     return E_NOINTERFACE;
73 }
74
75 ULONG STDMETHODCALLTYPE AccessibleApplication::AddRef()
76 {
77     return ++m_ref;
78 }
79
80 ULONG STDMETHODCALLTYPE AccessibleApplication::Release()
81 {
82     if (!--m_ref) {
83         delete this;
84         return 0;
85     }
86     return m_ref;
87 }
88
89 /* IAccessibleApplication */
90 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name)
91 {
92     const QString appName = QGuiApplication::applicationName();
93     *name = QStringToBSTR(appName);
94     return S_OK;
95 }
96
97 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appVersion(/* [retval][out] */ BSTR *version)
98 {
99     const QString appName = QGuiApplication::applicationVersion();
100     *version = QStringToBSTR(appName);
101     return S_OK;
102 }
103
104 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out] */ BSTR *name)
105 {
106     *name = ::SysAllocString(L"Qt");
107     return S_OK;
108 }
109
110 HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version)
111 {
112     *version = ::SysAllocString(QT_UNICODE_LITERAL(QT_VERSION_STR));
113     return S_OK;
114 }
115
116
117
118 /*!
119   \internal
120   Client allocates and deallocates array
121   (see "Special Consideration when using Arrays", in Accessible2.idl)
122   */
123 HRESULT STDMETHODCALLTYPE AccessibleRelation::get_target(
124     /* [in] */ long targetIndex,
125     /* [retval][out] */ IUnknown **target)
126 {
127     if (targetIndex >= 0 && targetIndex < m_targets.count()) {
128         QAccessibleInterface *iface = m_targets.at(targetIndex);
129         *target = QWindowsAccessibility::wrap(iface);
130         if (*target)
131             return S_OK;
132         return E_FAIL;
133     }
134     return E_INVALIDARG;
135 }
136
137 /*!
138   \internal
139   Client allocates and deallocates \a targets array
140   (see "Special Consideration when using Arrays", in Accessible2.idl)
141   */
142 HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets(
143     /* [in] */ long maxTargets,     // Hmmm, ignore ???
144     /* [length_is][size_is][out] */ IUnknown **targets,
145     /* [retval][out] */ long *nTargets)
146 {
147
148     const int numTargets = qMin((int)maxTargets, m_targets.count());
149     for (int i = 0; i < numTargets; ++i) {
150         QAccessibleInterface *iface = m_targets.at(i);
151         IAccessible *iacc = QWindowsAccessibility::wrap(iface);
152         if (!iacc)
153             return E_FAIL;
154         *targets = iacc;
155         ++targets;
156     }
157     *nTargets = numTargets;
158     // \a targets array is allocated by client.
159     return numTargets > 0 ? S_OK : S_FALSE;
160 }
161
162
163 /**************************************************************\
164  *                                                             *
165  *                        IUnknown                             *
166  *                                                             *
167  **************************************************************/
168 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface)
169 {
170     *iface = 0;
171
172     QByteArray strIID = IIDToString(id);
173     if (!strIID.isEmpty()) {
174         QString ss; QDebug dbg(&ss); dbg << accessible;
175         accessibleDebug("QWindowsIA2Accessible::QI() - IID:%s, iface:%s ", strIID.constData(), qPrintable(ss));
176     }
177     if (id == IID_IUnknown) {
178         *iface = (IUnknown*)(IDispatch*)this;
179     } else if (id == IID_IDispatch) {
180         *iface = (IDispatch*)this;
181     } else if (id == IID_IAccessible) {
182         *iface = (IAccessible*)this;
183     } else if (id == IID_IOleWindow) {
184         *iface = (IOleWindow*)this;
185     } else if (id == IID_IServiceProvider) {
186         *iface = (IServiceProvider*)this;
187     } else if (id == IID_IAccessible2) {
188         *iface = (IAccessible2*)this;
189     } else if (id == IID_IAccessibleAction) {
190         if (accessible->actionInterface())
191             *iface = (IAccessibleAction*)this;
192     } else if (id == IID_IAccessibleComponent) {
193         *iface = (IAccessibleComponent*)this;
194     } else if (id == IID_IAccessibleEditableText) {
195         //if (accessible->editableTextInterface()) {
196             //*iface = (IAccessibleEditableText*)this;
197         //}
198     } else if (id == IID_IAccessibleHyperlink) {
199         //*iface = (IAccessibleHyperlink*)this;
200     } else if (id == IID_IAccessibleHypertext) {
201         //*iface = (IAccessibleHypertext*)this;
202     } else if (id == IID_IAccessibleImage) {
203         //*iface = (IAccessibleImage*)this;
204     } else if (id == IID_IAccessibleRelation) {
205         *iface = (IAccessibleRelation*)this;
206     } else if (id == IID_IAccessibleTable) {
207         //*iface = (IAccessibleTable*)this; // not supported
208     } else if (id == IID_IAccessibleTable2) {
209         if (accessible->tableInterface())
210             *iface = (IAccessibleTable2*)this;
211     } else if (id == IID_IAccessibleTableCell) {
212         if (accessible->tableCellInterface())
213             *iface = (IAccessibleTableCell*)this;
214     } else if (id == IID_IAccessibleText) {
215         if (accessible->textInterface())
216             *iface = (IAccessibleText*)this;
217     } else if (id == IID_IAccessibleValue) {
218         if (accessible->valueInterface())
219             *iface = (IAccessibleValue*)this;
220     }
221     if (*iface) {
222         AddRef();
223         return S_OK;
224     }
225
226     return E_NOINTERFACE;
227 }
228
229 ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::AddRef()
230 {
231     return ++ref;
232 }
233
234 ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::Release()
235 {
236     if (!--ref) {
237         delete this;
238         return 0;
239     }
240     return ref;
241 }
242
243
244
245 /**************************************************************\
246  *                                                             *
247  *                        IAccessible2                         *
248  *                                                             *
249  **************************************************************/
250 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRelations(long *nRelations)
251 {
252     accessibleDebugClientCalls(accessible);
253     if (!nRelations)
254       return E_INVALIDARG;
255     if (!accessible->isValid())
256         return E_FAIL;
257
258     return getRelationsHelper(0, 0, 0, nRelations);
259 }
260
261 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relation(long relationIndex, IAccessibleRelation **relation)
262 {
263     accessibleDebugClientCalls(accessible);
264     if (!relation)
265       return E_INVALIDARG;
266     if (!accessible->isValid())
267         return E_FAIL;
268
269     return getRelationsHelper(relation, relationIndex,  1);
270 }
271
272 /*!
273   \internal
274   Client allocates and deallocates array
275   (see "Special Consideration when using Arrays", in Accessible2.idl)
276   */
277 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relations(long maxRelations,
278                                         IAccessibleRelation **relations,
279                                         long *nRelations)
280 {
281     accessibleDebugClientCalls(accessible);
282     if (!accessible->isValid())
283         return E_FAIL;
284
285     return getRelationsHelper(relations, 0, maxRelations, nRelations);
286 }
287
288
289 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role)
290 {
291     accessibleDebugClientCalls(accessible);
292     //### Change QAccessibleInterface::role() to return both MSAA and IA2 roles.
293     // When that is completed, we must patch the MSAA bridge not not return any
294     // IA2-specific roles from get_accRole().
295     if (!accessible->isValid())
296         return E_FAIL;
297
298     *ia2role = accessible->role();
299     return S_OK;
300 }
301
302
303 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollTo(enum IA2ScrollType /*scrollType*/)
304 {
305     //### Ignore for now
306     return E_NOTIMPL;
307 }
308
309
310 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollToPoint(enum IA2CoordinateType /*coordinateType*/, long /*x*/, long /*y*/)
311 {
312     //### Ignore for now
313     return E_NOTIMPL;
314 }
315
316
317 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_groupPosition(long *groupLevel,
318                                             long *similarItemsInGroup,
319                                             long *positionInGroup)
320 {
321     // ### Ignore for now. Not sure what this is used for.....
322     *groupLevel = 0;            // Not applicable
323     *similarItemsInGroup = 0;   // Not applicable
324     *positionInGroup = 0;       // Not applicable
325     return S_FALSE;
326 }
327
328
329 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_states(AccessibleStates *states)
330 {
331     accessibleDebugClientCalls(accessible);
332     if (!accessible->isValid())
333         return E_FAIL;
334     if (!states)
335         return E_POINTER;
336     QAccessible::State st = accessible->state();
337     AccessibleStates ia2states = 0;
338     if (st.active)
339         ia2states |= IA2_STATE_ACTIVE;
340     if (st.invalid)
341         ia2states |= IA2_STATE_DEFUNCT;
342     if (st.editable)
343         ia2states |= IA2_STATE_EDITABLE;
344     if (st.multiLine)
345         ia2states |= IA2_STATE_MULTI_LINE;
346     if (st.selectableText)
347         ia2states |= IA2_STATE_SELECTABLE_TEXT;
348     if (st.supportsAutoCompletion)
349         ia2states |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
350
351     *states = ia2states;
352     return S_OK;
353 }
354
355
356 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedRole(BSTR *extendedRole)
357 {
358     //###
359     *extendedRole = 0;
360     return E_NOTIMPL;   // mozilla does this
361     //return S_FALSE;
362 }
363
364
365 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedRole(BSTR *localizedExtendedRole)
366 {
367     //###
368     *localizedExtendedRole = 0;
369     return E_NOTIMPL;   // mozilla does this
370     //return S_FALSE;
371 }
372
373
374 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nExtendedStates(long *nExtendedStates)
375 {
376     // Who will ever intepret these values into something meaningful??
377     *nExtendedStates = 0;
378     return E_NOTIMPL;   // mozilla does this
379     //return S_FALSE;
380 }
381
382
383 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedStates(long /*maxExtendedStates*/,
384                                              BSTR **extendedStates,
385                                              long *nExtendedStates)
386 {
387     *extendedStates = 0;
388     *nExtendedStates = 0;
389     return E_NOTIMPL;   // mozilla does this
390     //return S_FALSE;
391 }
392
393
394 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedStates(long /*maxLocalizedExtendedStates*/,
395                                                       BSTR **localizedExtendedStates,
396                                                       long *nLocalizedExtendedStates)
397 {
398     *localizedExtendedStates = 0;
399     *nLocalizedExtendedStates = 0;
400     return E_NOTIMPL;   // mozilla does this
401     //return S_FALSE;
402 }
403
404
405 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_uniqueID(long *outUniqueID)
406 {
407     accessibleDebugClientCalls(accessible);
408     if (!accessible->isValid())
409         return E_FAIL;
410     // ### FIXME SERIOUSLY, NOT A STABLE SOLUTION IF NODES ARE DELETED ETC
411     // Return 0 if no object and no parent. This is really an error case.
412     uint uid = uniqueID();
413     accessibleDebug("uniqueID: %08x", uid);
414
415     *outUniqueID = (long)uid;
416     return uid ? S_OK : S_FALSE;
417 }
418
419
420 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_windowHandle(HWND *windowHandle)
421 {
422     accessibleDebugClientCalls(accessible);
423     if (!accessible->isValid())
424         return E_FAIL;
425     return GetWindow(windowHandle);
426 }
427
428
429 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexInParent)
430 {
431     accessibleDebugClientCalls(accessible);
432     if (!accessible->isValid())
433         return E_FAIL;
434     if (!indexInParent)
435       return E_INVALIDARG;
436     QAccessibleInterface *par = accessible->parent();
437     if (!par) {
438         *indexInParent = -1;
439         return S_FALSE;
440     }
441     int indexOfChild = par->indexOfChild(accessible);
442     delete par;
443     Q_ASSERT(indexOfChild >= 0);
444     *indexInParent = indexOfChild;
445     return S_OK;
446 }
447
448 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale)
449 {
450     accessibleDebugClientCalls(accessible);
451     if (!accessible->isValid())
452         return E_FAIL;
453     IA2Locale res;
454     QLocale l;
455     res.country = QStringToBSTR(QLocale::countryToString(l.country()));
456     res.language = QStringToBSTR(QLocale::languageToString(l.language()));
457     *locale = res;
458     return S_OK;
459 }
460
461
462 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(BSTR *attributes)
463 {
464     accessibleDebugClientCalls(accessible);
465     if (!accessible->isValid())
466         return E_FAIL;
467     *attributes = 0;//QStringToBSTR(QString());
468     return S_FALSE;
469 }
470
471 /**************************************************************\
472  *                      IAccessibleAction                      *
473  **************************************************************/
474 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions)
475 {
476     accessibleDebugClientCalls(accessible);
477     if (!accessible->isValid())
478         return E_FAIL;
479     *nActions = 0;
480
481     if (QAccessibleActionInterface *actionIface = actionInterface())
482         *nActions = actionIface->actionNames().count();
483     return S_OK;
484 }
485
486 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex)
487 {
488     accessibleDebugClientCalls(accessible);
489     if (!accessible->isValid())
490         return E_FAIL;
491     if (QAccessibleActionInterface *actionIface = actionInterface()) {
492         const QStringList actionNames = actionIface->actionNames();
493         if (actionIndex < 0 || actionIndex >= actionNames.count())
494             return E_INVALIDARG;
495         const QString actionName = actionNames.at(actionIndex);
496         actionIface->doAction(actionName);
497         return S_OK;
498     }
499     return S_FALSE;
500 }
501
502 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description)
503 {
504     accessibleDebugClientCalls(accessible);
505     if (!accessible->isValid())
506         return E_FAIL;
507     *description = 0;
508     if (QAccessibleActionInterface *actionIface = actionInterface()) {
509         const QStringList actionNames = actionIface->actionNames();
510         if (actionIndex < 0 || actionIndex >= actionNames.count())
511             return E_INVALIDARG;
512         const QString actionName = actionNames.at(actionIndex);
513         *description = QStringToBSTR(actionIface->localizedActionDescription(actionName));
514     }
515     return *description ? S_OK : S_FALSE;
516 }
517
518 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings)
519 {
520     accessibleDebugClientCalls(accessible);
521     if (!accessible->isValid())
522         return E_FAIL;
523     Q_UNUSED(nMaxBindings);
524     BSTR *arrayOfBindingsToReturn = 0;
525     int numBindings = 0;
526     if (QAccessibleActionInterface *actionIface = actionInterface()) {
527         const QStringList actionNames = actionIface->actionNames();
528         if (actionIndex < 0 || actionIndex >= actionNames.count())
529             return E_INVALIDARG;
530         const QString actionName = actionNames.at(actionIndex);
531         const QStringList keyBindings = actionIface->keyBindingsForAction(actionName);
532         numBindings = keyBindings.count();
533         if (numBindings > 0) {
534             // The IDL documents that the client must free with CoTaskMemFree
535             arrayOfBindingsToReturn = (BSTR*)::CoTaskMemAlloc(sizeof(BSTR) * numBindings);
536             for (int i = 0; i < numBindings; ++i)
537                 arrayOfBindingsToReturn[i] = QStringToBSTR(keyBindings.at(i));
538         }
539     }
540     *keyBindings = arrayOfBindingsToReturn;
541     *nBindings = numBindings;
542
543     return numBindings ? S_OK : S_FALSE;
544 }
545
546 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR *name)
547 {
548     accessibleDebugClientCalls(accessible);
549     if (!accessible->isValid())
550         return E_FAIL;
551     *name = 0;
552     if (QAccessibleActionInterface *actionIface = actionInterface()) {
553         const QStringList actionNames = actionIface->actionNames();
554         if (actionIndex < 0 || actionIndex >= actionNames.count())
555             return E_INVALIDARG;
556         const QString actionName = actionNames.at(actionIndex);
557         *name = QStringToBSTR(actionName);
558     }
559     return *name ? S_OK : S_FALSE;
560 }
561
562 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIndex, BSTR *localizedName)
563 {
564     accessibleDebugClientCalls(accessible);
565     if (!accessible->isValid())
566         return E_FAIL;
567     *localizedName = 0;
568     if (QAccessibleActionInterface *actionIface = actionInterface()) {
569         const QStringList actionNames = actionIface->actionNames();
570         if (actionIndex < 0 || actionIndex >= actionNames.count())
571             return E_INVALIDARG;
572
573         const QString actionName = actionNames.at(actionIndex);
574         *localizedName = QStringToBSTR(actionIface->localizedActionName(actionName));
575     }
576     return *localizedName ? S_OK : S_FALSE;
577 }
578
579 /**************************************************************\
580  *                     IAccessibleComponent                    *
581  **************************************************************/
582 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, long *y)
583 {
584     accessibleDebugClientCalls(accessible);
585     if (!accessible->isValid())
586         return E_FAIL;
587
588     QPoint topLeft = accessible->rect().topLeft();
589
590     if (QAccessibleInterface *parentIface = accessible->parent())
591         topLeft -= parentIface->rect().topLeft();
592
593     *x = topLeft.x();
594     *y = topLeft.y();
595     return S_OK;
596 }
597
598 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foreground)
599 {
600     accessibleDebugClientCalls(accessible);
601     if (!accessible->isValid())
602         return E_FAIL;
603
604     // IA2Color is a typedef for long
605     *foreground = (IA2Color)accessible->foregroundColor().rgb();
606     return S_OK;
607 }
608
609 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *background)
610 {
611     accessibleDebugClientCalls(accessible);
612     if (!accessible->isValid())
613         return E_FAIL;
614
615     // IA2Color is a typedef for long
616     *background = (IA2Color)accessible->backgroundColor().rgb();
617     return S_OK;
618 }
619
620 /**************************************************************\
621  *                     IAccessibleTable2                      *
622  **************************************************************/
623 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long column, IUnknown **cell)
624 {
625     accessibleDebugClientCalls(accessible);
626     if (!accessible->isValid())
627         return E_FAIL;
628
629     *cell = 0;
630     if (QAccessibleTableInterface *tableIface = tableInterface()) {
631         if (QAccessibleInterface *qtCell = tableIface->cellAt(row, column)) {
632             *cell = QWindowsAccessibility::wrap(qtCell);
633         }
634     }
635     accessibleDebug("found cell? %p", *cell);
636     return *cell ? S_OK : S_FALSE;
637 }
638
639 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caption( IUnknown **captionInterface)
640 {
641     accessibleDebugClientCalls(accessible);
642     if (!accessible->isValid())
643         return E_FAIL;
644
645     *captionInterface = 0;
646     if (QAccessibleTableInterface *tableIface = tableInterface()) {
647         if (QAccessibleInterface *iface = tableIface->caption())
648             *captionInterface = QWindowsAccessibility::wrap(iface);
649     }
650     return *captionInterface ? S_OK : S_FALSE;
651 }
652
653 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnDescription( long column, BSTR *description)
654 {
655     accessibleDebugClientCalls(accessible);
656     if (!accessible->isValid())
657         return E_FAIL;
658
659     *description = 0;
660     if (QAccessibleTableInterface *tableIface = tableInterface()) {
661         const QString qtDesc = tableIface->columnDescription(column);
662         if (!qtDesc.isEmpty())
663             *description = QStringToBSTR(qtDesc);
664     }
665     return *description ? S_OK : S_FALSE;
666 }
667
668 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nColumns( long *columnCount)
669 {
670     accessibleDebugClientCalls(accessible);
671     if (!accessible->isValid())
672         return E_FAIL;
673
674     if (QAccessibleTableInterface *tableIface = tableInterface()) {
675         *columnCount = tableIface->columnCount();
676         return S_OK;
677     }
678     return E_FAIL;
679 }
680
681 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRows(long *rowCount)
682 {
683     accessibleDebugClientCalls(accessible);
684     if (!accessible->isValid())
685         return E_FAIL;
686
687     if (QAccessibleTableInterface *tableIface = tableInterface()) {
688         *rowCount = tableIface->rowCount();
689         return S_OK;
690     }
691     return E_FAIL;
692 }
693
694 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedCells(long *cellCount)
695 {
696     accessibleDebugClientCalls(accessible);
697     if (!accessible->isValid())
698         return E_FAIL;
699
700     if (QAccessibleTableInterface *tableIface = tableInterface()) {
701         *cellCount = tableIface->selectedCellCount();
702         return S_OK;
703     }
704     return E_FAIL;
705 }
706
707 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedColumns(long *columnCount)
708 {
709     accessibleDebugClientCalls(accessible);
710     if (!accessible->isValid())
711         return E_FAIL;
712
713     if (QAccessibleTableInterface *tableIface = tableInterface()) {
714         *columnCount = tableIface->selectedColumnCount();
715         return S_OK;
716     }
717     return E_FAIL;
718 }
719
720 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedRows(long *rowCount)
721 {
722     accessibleDebugClientCalls(accessible);
723     if (!accessible->isValid())
724         return E_FAIL;
725
726     if (QAccessibleTableInterface *tableIface = tableInterface()) {
727         *rowCount = tableIface->selectedRowCount();
728         return S_OK;
729     }
730     return E_FAIL;
731 }
732
733 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowDescription(long row, BSTR *description)
734 {
735     accessibleDebugClientCalls(accessible);
736     if (!accessible->isValid())
737         return E_FAIL;
738
739     *description = 0;
740     if (QAccessibleTableInterface *tableIface = tableInterface()) {
741         const QString qtDesc = tableIface->columnDescription(row);
742         if (!qtDesc.isEmpty())
743             *description = QStringToBSTR(qtDesc);
744     }
745     return *description ? S_OK : S_FALSE;
746 }
747
748 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedCells(IUnknown ***cells, long *nSelectedCells)
749 {
750     accessibleDebugClientCalls(accessible);
751     Q_UNUSED(cells);
752     Q_UNUSED(nSelectedCells);
753     if (!accessible->isValid())
754         return E_FAIL;
755
756     QList<QAccessibleInterface*> selectedCells = tableInterface()->selectedCells();
757     return wrapListOfCells(selectedCells, cells, nSelectedCells);
758 }
759
760 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **selectedColumns, long *nColumns)
761 {
762     accessibleDebugClientCalls(accessible);
763     if (!accessible->isValid())
764         return E_FAIL;
765
766     if (QAccessibleTableInterface *tableIface = tableInterface()) {
767         const QList<int> selectedIndices = tableIface->selectedColumns();
768         const int &count = selectedIndices.count();
769         long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0);
770         for (int i = 0; i < count; ++i)
771             selected[i] = selectedIndices.at(i);
772         *selectedColumns = selected;
773         *nColumns = count;
774         return count ? S_OK : S_FALSE;
775     }
776     return E_FAIL;
777
778 }
779
780 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selectedRows, long *nRows)
781 {
782     accessibleDebugClientCalls(accessible);
783     if (!accessible->isValid())
784         return E_FAIL;
785
786     if (QAccessibleTableInterface *tableIface = tableInterface()) {
787         const QList<int> selectedIndices = tableIface->selectedRows();
788         const int &count = selectedIndices.count();
789         long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0);
790         for (int i = 0; i < count; ++i)
791             selected[i] = selectedIndices.at(i);
792         *selectedRows = selected;
793         *nRows = count;
794         return count ? S_OK : S_FALSE;
795     }
796     return E_FAIL;
797
798 }
799
800 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_summary(IUnknown **summaryInterface)
801 {
802     accessibleDebugClientCalls(accessible);
803     if (!accessible->isValid())
804         return E_FAIL;
805
806     *summaryInterface = 0;
807     if (QAccessibleTableInterface *tableIface = tableInterface()) {
808         if (QAccessibleInterface *iface = tableIface->summary())
809             *summaryInterface = QWindowsAccessibility::wrap(iface);
810     }
811     return *summaryInterface ? S_OK : S_FALSE;
812 }
813
814 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isColumnSelected(long column, boolean *isSelected)
815 {
816     accessibleDebugClientCalls(accessible);
817     if (!accessible->isValid())
818         return E_FAIL;
819
820     if (QAccessibleTableInterface *tableIface = tableInterface()) {
821         *isSelected = tableIface->isColumnSelected(column);
822         return S_OK;
823     }
824     return E_FAIL;
825 }
826
827 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isRowSelected(long row, boolean *isSelected)
828 {
829     accessibleDebugClientCalls(accessible);
830     if (!accessible->isValid())
831         return E_FAIL;
832
833     if (QAccessibleTableInterface *tableIface = tableInterface()) {
834         *isSelected = tableIface->isRowSelected(row);
835         return S_OK;
836     }
837     return E_FAIL;
838 }
839
840 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectRow(long row)
841 {
842     accessibleDebugClientCalls(accessible);
843     if (!accessible->isValid())
844         return E_FAIL;
845
846     if (QAccessibleTableInterface *tableIface = tableInterface()) {
847         bool ok = tableIface->selectRow(row);
848         return ok ? S_OK : E_INVALIDARG;    //### Not sure of the return value if it fails???
849     }
850     return E_FAIL;
851 }
852
853 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectColumn(long column)
854 {
855     accessibleDebugClientCalls(accessible);
856     if (!accessible->isValid())
857         return E_FAIL;
858
859     if (QAccessibleTableInterface *tableIface = tableInterface()) {
860         bool ok = tableIface->selectColumn(column);
861         return ok ? S_OK : E_INVALIDARG;    //### Not sure of the return value if it fails???
862     }
863     return E_FAIL;
864 }
865
866 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectRow(long row)
867 {
868     accessibleDebugClientCalls(accessible);
869     if (!accessible->isValid())
870         return E_FAIL;
871
872     if (QAccessibleTableInterface *tableIface = tableInterface()) {
873         bool ok = tableIface->unselectRow(row);
874         return ok ? S_OK : E_INVALIDARG;    //### Not sure of the return value if it fails???
875     }
876     return E_FAIL;
877 }
878
879 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectColumn(long column)
880 {
881     accessibleDebugClientCalls(accessible);
882     if (!accessible->isValid())
883         return E_FAIL;
884
885     if (QAccessibleTableInterface *tableIface = tableInterface()) {
886         bool ok = tableIface->unselectColumn(column);
887         return ok ? S_OK : E_INVALIDARG;    //### Not sure of the return value if it fails???
888     }
889     return E_FAIL;
890 }
891
892 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_modelChange( IA2TableModelChange * /*modelChange*/)
893 {
894     accessibleDebugClientCalls(accessible);
895     if (!accessible->isValid())
896         return E_FAIL;
897     return E_NOTIMPL;
898 }
899
900 /**************************************************************\
901  *                     IAccessibleTableCell                   *
902 \**************************************************************/
903 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnExtent(long *nColumnsSpanned)
904 {
905     accessibleDebugClientCalls(accessible);
906     if (!accessible->isValid())
907         return E_FAIL;
908
909     *nColumnsSpanned = tableCellInterface()->columnExtent();
910     return S_OK;
911 }
912
913 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnHeaderCells(IUnknown ***cellAccessibles,
914                                                                     long *nColumnHeaderCells)
915 {
916     accessibleDebugClientCalls(accessible);
917     if (!accessible->isValid())
918         return E_FAIL;
919     const QList<QAccessibleInterface*> headerCells = tableCellInterface()->columnHeaderCells();
920     return wrapListOfCells(headerCells, cellAccessibles, nColumnHeaderCells);
921 }
922
923 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnIndex(long *columnIndex)
924 {
925     accessibleDebugClientCalls(accessible);
926     if (!accessible->isValid())
927         return E_FAIL;
928     *columnIndex = tableCellInterface()->columnIndex();
929     return S_OK;
930 }
931
932 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowExtent(long *nRowsSpanned)
933 {
934     accessibleDebugClientCalls(accessible);
935     if (!accessible->isValid())
936         return E_FAIL;
937     *nRowsSpanned = tableCellInterface()->rowExtent();
938     return S_OK;
939 }
940
941 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowHeaderCells(IUnknown ***cellAccessibles,
942                                                                  long *nRowHeaderCells)
943 {
944     accessibleDebugClientCalls(accessible);
945     if (!accessible->isValid())
946         return E_FAIL;
947     const QList<QAccessibleInterface*> headerCells = tableCellInterface()->rowHeaderCells();
948     return wrapListOfCells(headerCells, cellAccessibles, nRowHeaderCells);
949 }
950
951 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowIndex(long *rowIndex)
952 {
953     accessibleDebugClientCalls(accessible);
954     if (!accessible->isValid())
955         return E_FAIL;
956     *rowIndex = tableCellInterface()->rowIndex();
957     return S_OK;
958 }
959
960 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isSelected( boolean *isSelected)
961 {
962     accessibleDebugClientCalls(accessible);
963     if (!accessible->isValid())
964         return E_FAIL;
965     *isSelected = tableCellInterface()->isSelected();
966     return S_OK;
967 }
968
969 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, long *column,
970                                                long *rowExtents, long *columnExtents,
971                                                boolean *isSelected)
972 {
973     accessibleDebugClientCalls(accessible);
974     if (!accessible->isValid())
975         return E_FAIL;
976
977     tableCellInterface()->rowColumnExtents((int*)row, (int*)column, (int*)rowExtents, (int*)columnExtents, (bool*)isSelected);
978     return S_OK;
979 }
980
981 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_table(IUnknown **table)
982 {
983     accessibleDebugClientCalls(accessible);
984     if (!accessible->isValid())
985         return E_FAIL;
986
987     QAccessibleInterface *tableIface = tableCellInterface()->table();
988
989     *table = QWindowsAccessibility::wrap(tableIface);
990     return S_OK;
991 }
992
993 /**************************************************************\
994  *                     IAccessibleText                        *
995 \**************************************************************/
996 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::addSelection(long startOffset,
997                                                            long endOffset)
998 {
999     accessibleDebugClientCalls(accessible);
1000     if (QAccessibleTextInterface *text = textInterface()) {
1001         text->addSelection(startOffset, endOffset);
1002         return S_OK;
1003     }
1004     return E_FAIL;
1005 }
1006
1007 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset,
1008                                                              long *startOffset,
1009                                                              long *endOffset,
1010                                                              BSTR *textAttributes)
1011 {
1012     accessibleDebugClientCalls(accessible);
1013     if (QAccessibleTextInterface *text = textInterface()) {
1014         const QString attrs = text->attributes(offset, (int*)startOffset, (int*)endOffset);
1015         *textAttributes = QStringToBSTR(attrs);
1016         return S_OK;
1017     }
1018     return E_FAIL;
1019 }
1020
1021 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caretOffset(long *offset)
1022 {
1023     accessibleDebugClientCalls(accessible);
1024     if (QAccessibleTextInterface *text = textInterface()) {
1025         *offset = text->cursorPosition();
1026         return S_OK;
1027     }
1028     return E_FAIL;
1029 }
1030
1031 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offset,
1032                                                                    enum IA2CoordinateType coordType,
1033                                                                    long *x,
1034                                                                    long *y,
1035                                                                    long *width,
1036                                                                    long *height)
1037 {
1038     accessibleDebugClientCalls(accessible);
1039     if (QAccessibleTextInterface *text = textInterface()) {
1040         const QRect rect = text->characterRect(offset, (QAccessible2::CoordinateType)coordType);
1041         *x = rect.x();
1042         *y = rect.y();
1043         *width = rect.width();
1044         *height = rect.height();
1045         return S_OK;
1046     }
1047     return E_FAIL;
1048 }
1049
1050 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelections(long *nSelections)
1051 {
1052     accessibleDebugClientCalls(accessible);
1053     if (QAccessibleTextInterface *text = textInterface()) {
1054         *nSelections = text->selectionCount();
1055         return S_OK;
1056     }
1057     return E_FAIL;
1058 }
1059
1060 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_offsetAtPoint(long x,
1061                                                                 long y,
1062                                                                 enum IA2CoordinateType coordType,
1063                                                                 long *offset)
1064 {
1065     accessibleDebugClientCalls(accessible);
1066     if (QAccessibleTextInterface *text = textInterface()) {
1067         *offset = text->offsetAtPoint(QPoint(x,y), (QAccessible2::CoordinateType)coordType);
1068         return (*offset >=0 ? S_OK : S_FALSE);
1069     }
1070     return E_FAIL;
1071
1072 }
1073
1074 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionIndex,
1075                                                             long *startOffset,
1076                                                             long *endOffset)
1077 {
1078     accessibleDebugClientCalls(accessible);
1079     if (QAccessibleTextInterface *text = textInterface()) {
1080         text->selection(selectionIndex, (int*)startOffset, (int*)endOffset);
1081         return S_OK;
1082     }
1083     return E_FAIL;
1084 }
1085
1086 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_text(long startOffset,
1087                                                        long endOffset,
1088                                                        BSTR *text)
1089 {
1090     accessibleDebugClientCalls(accessible);
1091     if (QAccessibleTextInterface *textif = textInterface()) {
1092         const QString t = textif->text(startOffset, endOffset);
1093         if (!t.isEmpty()) {
1094             *text = QStringToBSTR(t);
1095             return S_OK;
1096         }
1097         return E_INVALIDARG;
1098     }
1099     return E_FAIL;
1100 }
1101
1102 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offset,
1103                                                enum IA2TextBoundaryType boundaryType,
1104                                                long *startOffset,
1105                                                long *endOffset,
1106                                                BSTR *text)
1107 {
1108     accessibleDebugClientCalls(accessible);
1109     if (QAccessibleTextInterface *textIface = textInterface()) {
1110         const QString txt = textIface->textBeforeOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1111         if (!txt.isEmpty()) {
1112             *text = QStringToBSTR(txt);
1113             return S_OK;
1114         }
1115         return S_FALSE;
1116     }
1117     return E_FAIL;
1118 }
1119
1120 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset(
1121     long offset,
1122     enum IA2TextBoundaryType boundaryType,
1123     long *startOffset,
1124     long *endOffset,
1125     BSTR *text)
1126 {
1127     accessibleDebugClientCalls(accessible);
1128     if (QAccessibleTextInterface *textIface = textInterface()) {
1129         const QString txt = textIface->textAfterOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1130         if (!txt.isEmpty()) {
1131             *text = QStringToBSTR(txt);
1132             return S_OK;
1133         }
1134         return S_FALSE;
1135     }
1136     return E_FAIL;
1137 }
1138
1139 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset,
1140                                                                enum IA2TextBoundaryType boundaryType,
1141                                                                long *startOffset,
1142                                                                long *endOffset,
1143                                                                BSTR *text)
1144 {
1145     accessibleDebugClientCalls(accessible);
1146     if (QAccessibleTextInterface *textIface = textInterface()) {
1147         const QString txt = textIface->textAtOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1148         if (!txt.isEmpty()) {
1149             *text = QStringToBSTR(txt);
1150             return S_OK;
1151         }
1152         return S_FALSE;
1153     }
1154     return E_FAIL;
1155 }
1156
1157 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionIndex)
1158 {
1159     accessibleDebugClientCalls(accessible);
1160     if (QAccessibleTextInterface *textIface = textInterface()) {
1161         textIface->removeSelection(selectionIndex);
1162         return S_OK;
1163     }
1164     return E_FAIL;
1165 }
1166
1167 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCaretOffset(long offset)
1168 {
1169     accessibleDebugClientCalls(accessible);
1170     if (QAccessibleTextInterface *textIface = textInterface()) {
1171         textIface->setCursorPosition(offset);
1172         return S_OK;
1173     }
1174     return E_FAIL;
1175 }
1176
1177 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionIndex,
1178                                                            long startOffset,
1179                                                            long endOffset)
1180 {
1181     accessibleDebugClientCalls(accessible);
1182     if (QAccessibleTextInterface *textIface = textInterface()) {
1183         textIface->setSelection(selectionIndex, startOffset, endOffset);
1184         return S_OK;
1185     }
1186     return E_FAIL;
1187 }
1188
1189 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nCharacters(long *nCharacters)
1190 {
1191     accessibleDebugClientCalls(accessible);
1192     if (QAccessibleTextInterface *textIface = textInterface()) {
1193         *nCharacters = textIface->characterCount();
1194         return S_OK;
1195     }
1196     return E_FAIL;
1197 }
1198
1199 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringTo(long startIndex,
1200                                                                 long endIndex,
1201                                                                 enum IA2ScrollType scrollType)
1202 {
1203     accessibleDebugClientCalls(accessible);
1204     if (QAccessibleTextInterface *textIface = textInterface()) {
1205         Q_UNUSED(scrollType);   //###
1206         textIface->scrollToSubstring(startIndex, endIndex);
1207         return S_OK;
1208     }
1209     return E_FAIL;
1210 }
1211
1212 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringToPoint(long startIndex,
1213                                                                      long endIndex,
1214                                                                      enum IA2CoordinateType coordinateType,
1215                                                                      long x,
1216                                                                      long y)
1217 {
1218     Q_UNUSED(startIndex);
1219     Q_UNUSED(endIndex);
1220     Q_UNUSED(coordinateType);
1221     Q_UNUSED(x);
1222     Q_UNUSED(y);
1223
1224     return E_NOTIMPL;
1225 }
1226
1227 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_newText(IA2TextSegment *newText)
1228 {
1229     Q_UNUSED(newText);
1230     return E_NOTIMPL;
1231 }
1232
1233 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_oldText(IA2TextSegment *oldText)
1234 {
1235     Q_UNUSED(oldText);
1236     return E_NOTIMPL;
1237 }
1238
1239 /**************************************************************\
1240  *                         IAccessibleValue                    *
1241  **************************************************************/
1242 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *currentValue)
1243 {
1244     accessibleDebugClientCalls(accessible);
1245     if (!accessible->isValid())
1246         return E_FAIL;
1247     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1248         const QVariant var = valueIface->currentValue();
1249         if (QVariantToVARIANT(var, *currentValue, QByteArray(), false))
1250             return S_OK;
1251
1252     }
1253     currentValue->vt = VT_EMPTY;
1254     return S_FALSE;
1255 }
1256
1257 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value)
1258 {
1259     accessibleDebugClientCalls(accessible);
1260     if (!accessible->isValid())
1261         return E_FAIL;
1262     HRESULT hr = S_FALSE;
1263     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1264         hr = VariantChangeType(&value, &value, 0, VT_R8);
1265         if (SUCCEEDED(hr)) {
1266             // ### works only for numbers (not date, strings, etc)
1267             valueIface->setCurrentValue(QVariant(value.dblVal));
1268         }
1269     }
1270     return hr;
1271 }
1272
1273 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maximumValue)
1274 {
1275     accessibleDebugClientCalls(accessible);
1276     if (!accessible->isValid())
1277         return E_FAIL;
1278     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1279         const QVariant var = valueIface->maximumValue();
1280         if (QVariantToVARIANT(var, *maximumValue, QByteArray(), false))
1281             return S_OK;
1282     }
1283     maximumValue->vt = VT_EMPTY;
1284     return S_FALSE;
1285 }
1286
1287 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_minimumValue(VARIANT *minimumValue)
1288 {
1289     accessibleDebugClientCalls(accessible);
1290     if (!accessible->isValid())
1291         return E_FAIL;
1292     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1293         const QVariant var = valueIface->minimumValue();
1294         if (QVariantToVARIANT(var, *minimumValue, QByteArray(), false))
1295             return S_OK;
1296     }
1297     minimumValue->vt = VT_EMPTY;
1298     return S_FALSE;
1299 }
1300
1301
1302 /**************************************************************\
1303  *                      IServiceProvider                       *
1304  **************************************************************/
1305 /*!
1306   \internal
1307   Reimplemented from IServiceProvider
1308 */
1309 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidService, REFIID riid, void **iface)
1310 {
1311     if (!iface)
1312         return E_POINTER;
1313     Q_UNUSED(guidService);
1314     *iface = 0;
1315     accessibleDebug("QWindowsIA2Accessible::QS(): %s", IIDToString(riid).constData());
1316     if (riid == IID_IAccessible || riid == IID_IUnknown || riid == IID_IDispatch) {
1317         *iface = static_cast<IAccessible*>(this);
1318     } else if (/*guidService == IID_IAccessible && */riid == IID_IAccessible2) {
1319         *iface = static_cast<IAccessible2*>(this);
1320     } else  if (riid == IID_IAccessibleApplication) {
1321         *iface = new AccessibleApplication;
1322         return S_OK;
1323     } else {
1324         QueryInterface(riid, iface);
1325     }
1326     if (*iface) {
1327         AddRef();
1328         return S_OK;
1329     }
1330
1331     return E_NOINTERFACE;
1332 }
1333
1334
1335 /*!
1336   \internal
1337   private function..
1338   \a maxRelations max number of relations to return in \a relations
1339   \a relations the array of relations matching
1340   \a startIndex Index to start to return from,
1341                    it will return only that specific relation in \a relations
1342
1343   If \a relations is null, \a startIndex and \a maxRelations are ignored, causing
1344   it to return the number of relations in \a nRelations
1345 */
1346 HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations /* = 0*/)
1347 {
1348     if (nRelations)
1349         *nRelations = 0;
1350     typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationEntry;
1351     QVector<RelationEntry> rels = accessible->relations();
1352     QMap<QAccessible::Relation, QAccessibleInterface *> relationMap;
1353     for (QVector<RelationEntry>::const_iterator it = rels.constBegin(); it != rels.constEnd(); ++it)
1354     {
1355         RelationEntry e = *it;
1356         relationMap.insertMulti(e.second, e.first);
1357     }
1358
1359     QList<QAccessible::Relation> keys = relationMap.keys();
1360     const int numRelations = keys.count();
1361     if (relations) {
1362         for (int i = startIndex; i < qMin(startIndex + (int)maxRelations, numRelations); ++i) {
1363             QAccessible::Relation relation = keys.at(i);
1364             QList<QAccessibleInterface*> targets = relationMap.values(relation);
1365             AccessibleRelation *rel = new AccessibleRelation(targets, relation);
1366             *relations = rel;
1367             ++relations;
1368         }
1369     }
1370     if (nRelations)
1371         *nRelations = numRelations;
1372
1373     return numRelations > 0 ? S_OK : S_FALSE;
1374 }
1375
1376
1377
1378
1379 /*!
1380   \internal
1381   helper to wrap a QList<QAccessibleInterface*> inside an array of IAccessible*
1382   The IAccessible* array is returned as a IUnknown*
1383 */
1384 HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount)
1385 {
1386     const int count = inputCells.count();
1387     // Server allocates array
1388     IUnknown **outputCells = count ? (IUnknown**)::CoTaskMemAlloc(sizeof(IUnknown*) * count ) : (IUnknown**)0;
1389     for (int i = 0; i < count; ++i)
1390         outputCells[i] = QWindowsAccessibility::wrap(inputCells.at(i));
1391
1392     *outputAccessibles = outputCells;
1393     *nCellCount = count;
1394     return count > 0 ? S_OK : S_FALSE;
1395 }
1396
1397 uint QWindowsIA2Accessible::uniqueID() const
1398 {
1399     uint uid = 0;
1400     if (QObject *obj = accessible->object())
1401         uid = qHash(obj);
1402
1403     if (!uid) {
1404         QAccessibleInterface *acc = accessible;
1405         QVector<int> indexOfNodes;
1406         while (acc && !acc->object()) {
1407             QAccessibleInterface *par = acc->parent();
1408             indexOfNodes.append(par->indexOfChild(acc));
1409             if (acc != accessible)
1410                 delete acc;
1411             acc = par;
1412         }
1413         if (acc) {
1414             if (acc->object()) {
1415                 uid = qHash(acc->object());
1416                 for (int i = 0; i < indexOfNodes.count(); ++i)
1417                     uid = qHash(uid + indexOfNodes.at(i));
1418
1419             }
1420             if (acc != accessible)
1421                 delete acc;
1422         }
1423     }
1424     return uid;
1425 }
1426
1427
1428 #define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid)
1429
1430 QByteArray QWindowsIA2Accessible::IIDToString(REFIID id)
1431 {
1432     IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown);
1433     IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch);
1434     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible);
1435     IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow);
1436     IF_EQUAL_RETURN_IIDSTRING(id, IID_IServiceProvider);
1437     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible2);
1438     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleAction);
1439     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleApplication);
1440     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleComponent);
1441     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleEditableText);
1442     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHyperlink);
1443     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHypertext);
1444     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleImage);
1445     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleRelation);
1446     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable);
1447     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable2);
1448     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTableCell);
1449     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleText);
1450     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleValue);
1451
1452     // else...
1453     QByteArray strGuid;
1454 #if 0   // Can be useful for debugging, but normally we'd like to reduce the noise a bit...
1455     OLECHAR szGuid[39]={0};
1456     ::StringFromGUID2(id, szGuid, 39);
1457     strGuid.reserve(40);
1458     ::WideCharToMultiByte(CP_UTF8, 0, szGuid, 39, strGuid.data(), 39, NULL, NULL);
1459     strGuid[38] = '\0';
1460 #endif
1461     return strGuid;
1462 }
1463
1464
1465 QT_END_NAMESPACE
1466
1467 #endif //QT_NO_ACCESSIBILITY