API cleanup: remove CoordinateType enum
[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
1032 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offset,
1033                                                                    enum IA2CoordinateType coordType,
1034                                                                    long *x,
1035                                                                    long *y,
1036                                                                    long *width,
1037                                                                    long *height)
1038 {
1039     accessibleDebugClientCalls(accessible);
1040     if (QAccessibleTextInterface *text = textInterface()) {
1041         QRect rect = text->characterRect(offset);
1042         mapFromScreenPos(coordType, rect.topLeft(), x, 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         QPoint screenPos = mapToScreenPos(coordType, x, y);
1068         *offset = text->offsetAtPoint(screenPos);
1069         return (*offset >=0 ? S_OK : S_FALSE);
1070     }
1071     return E_FAIL;
1072
1073 }
1074
1075 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionIndex,
1076                                                             long *startOffset,
1077                                                             long *endOffset)
1078 {
1079     accessibleDebugClientCalls(accessible);
1080     if (QAccessibleTextInterface *text = textInterface()) {
1081         text->selection(selectionIndex, (int*)startOffset, (int*)endOffset);
1082         return S_OK;
1083     }
1084     return E_FAIL;
1085 }
1086
1087 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_text(long startOffset,
1088                                                        long endOffset,
1089                                                        BSTR *text)
1090 {
1091     accessibleDebugClientCalls(accessible);
1092     if (QAccessibleTextInterface *textif = textInterface()) {
1093         const QString t = textif->text(startOffset, endOffset);
1094         if (!t.isEmpty()) {
1095             *text = QStringToBSTR(t);
1096             return S_OK;
1097         }
1098         return E_INVALIDARG;
1099     }
1100     return E_FAIL;
1101 }
1102
1103 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offset,
1104                                                enum IA2TextBoundaryType boundaryType,
1105                                                long *startOffset,
1106                                                long *endOffset,
1107                                                BSTR *text)
1108 {
1109     accessibleDebugClientCalls(accessible);
1110     if (QAccessibleTextInterface *textIface = textInterface()) {
1111         const QString txt = textIface->textBeforeOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1112         if (!txt.isEmpty()) {
1113             *text = QStringToBSTR(txt);
1114             return S_OK;
1115         }
1116         return S_FALSE;
1117     }
1118     return E_FAIL;
1119 }
1120
1121 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset(
1122     long offset,
1123     enum IA2TextBoundaryType boundaryType,
1124     long *startOffset,
1125     long *endOffset,
1126     BSTR *text)
1127 {
1128     accessibleDebugClientCalls(accessible);
1129     if (QAccessibleTextInterface *textIface = textInterface()) {
1130         const QString txt = textIface->textAfterOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1131         if (!txt.isEmpty()) {
1132             *text = QStringToBSTR(txt);
1133             return S_OK;
1134         }
1135         return S_FALSE;
1136     }
1137     return E_FAIL;
1138 }
1139
1140 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset,
1141                                                                enum IA2TextBoundaryType boundaryType,
1142                                                                long *startOffset,
1143                                                                long *endOffset,
1144                                                                BSTR *text)
1145 {
1146     accessibleDebugClientCalls(accessible);
1147     if (QAccessibleTextInterface *textIface = textInterface()) {
1148         const QString txt = textIface->textAtOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
1149         if (!txt.isEmpty()) {
1150             *text = QStringToBSTR(txt);
1151             return S_OK;
1152         }
1153         return S_FALSE;
1154     }
1155     return E_FAIL;
1156 }
1157
1158 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionIndex)
1159 {
1160     accessibleDebugClientCalls(accessible);
1161     if (QAccessibleTextInterface *textIface = textInterface()) {
1162         textIface->removeSelection(selectionIndex);
1163         return S_OK;
1164     }
1165     return E_FAIL;
1166 }
1167
1168 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCaretOffset(long offset)
1169 {
1170     accessibleDebugClientCalls(accessible);
1171     if (QAccessibleTextInterface *textIface = textInterface()) {
1172         textIface->setCursorPosition(offset);
1173         return S_OK;
1174     }
1175     return E_FAIL;
1176 }
1177
1178 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionIndex,
1179                                                            long startOffset,
1180                                                            long endOffset)
1181 {
1182     accessibleDebugClientCalls(accessible);
1183     if (QAccessibleTextInterface *textIface = textInterface()) {
1184         textIface->setSelection(selectionIndex, startOffset, endOffset);
1185         return S_OK;
1186     }
1187     return E_FAIL;
1188 }
1189
1190 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nCharacters(long *nCharacters)
1191 {
1192     accessibleDebugClientCalls(accessible);
1193     if (QAccessibleTextInterface *textIface = textInterface()) {
1194         *nCharacters = textIface->characterCount();
1195         return S_OK;
1196     }
1197     return E_FAIL;
1198 }
1199
1200 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringTo(long startIndex,
1201                                                                 long endIndex,
1202                                                                 enum IA2ScrollType scrollType)
1203 {
1204     accessibleDebugClientCalls(accessible);
1205     if (QAccessibleTextInterface *textIface = textInterface()) {
1206         Q_UNUSED(scrollType);   //###
1207         textIface->scrollToSubstring(startIndex, endIndex);
1208         return S_OK;
1209     }
1210     return E_FAIL;
1211 }
1212
1213 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringToPoint(long startIndex,
1214                                                                      long endIndex,
1215                                                                      enum IA2CoordinateType coordinateType,
1216                                                                      long x,
1217                                                                      long y)
1218 {
1219     Q_UNUSED(startIndex);
1220     Q_UNUSED(endIndex);
1221     Q_UNUSED(coordinateType);
1222     Q_UNUSED(x);
1223     Q_UNUSED(y);
1224
1225     return E_NOTIMPL;
1226 }
1227
1228 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_newText(IA2TextSegment *newText)
1229 {
1230     Q_UNUSED(newText);
1231     return E_NOTIMPL;
1232 }
1233
1234 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_oldText(IA2TextSegment *oldText)
1235 {
1236     Q_UNUSED(oldText);
1237     return E_NOTIMPL;
1238 }
1239
1240 /**************************************************************\
1241  *                         IAccessibleValue                    *
1242  **************************************************************/
1243 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *currentValue)
1244 {
1245     accessibleDebugClientCalls(accessible);
1246     if (!accessible->isValid())
1247         return E_FAIL;
1248     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1249         const QVariant var = valueIface->currentValue();
1250         if (QVariantToVARIANT(var, *currentValue, QByteArray(), false))
1251             return S_OK;
1252
1253     }
1254     currentValue->vt = VT_EMPTY;
1255     return S_FALSE;
1256 }
1257
1258 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value)
1259 {
1260     accessibleDebugClientCalls(accessible);
1261     if (!accessible->isValid())
1262         return E_FAIL;
1263     HRESULT hr = S_FALSE;
1264     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1265         hr = VariantChangeType(&value, &value, 0, VT_R8);
1266         if (SUCCEEDED(hr)) {
1267             // ### works only for numbers (not date, strings, etc)
1268             valueIface->setCurrentValue(QVariant(value.dblVal));
1269         }
1270     }
1271     return hr;
1272 }
1273
1274 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maximumValue)
1275 {
1276     accessibleDebugClientCalls(accessible);
1277     if (!accessible->isValid())
1278         return E_FAIL;
1279     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1280         const QVariant var = valueIface->maximumValue();
1281         if (QVariantToVARIANT(var, *maximumValue, QByteArray(), false))
1282             return S_OK;
1283     }
1284     maximumValue->vt = VT_EMPTY;
1285     return S_FALSE;
1286 }
1287
1288 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_minimumValue(VARIANT *minimumValue)
1289 {
1290     accessibleDebugClientCalls(accessible);
1291     if (!accessible->isValid())
1292         return E_FAIL;
1293     if (QAccessibleValueInterface *valueIface = valueInterface()) {
1294         const QVariant var = valueIface->minimumValue();
1295         if (QVariantToVARIANT(var, *minimumValue, QByteArray(), false))
1296             return S_OK;
1297     }
1298     minimumValue->vt = VT_EMPTY;
1299     return S_FALSE;
1300 }
1301
1302
1303 /**************************************************************\
1304  *                      IServiceProvider                       *
1305  **************************************************************/
1306 /*!
1307   \internal
1308   Reimplemented from IServiceProvider
1309 */
1310 HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidService, REFIID riid, void **iface)
1311 {
1312     if (!iface)
1313         return E_POINTER;
1314     Q_UNUSED(guidService);
1315     *iface = 0;
1316     accessibleDebug("QWindowsIA2Accessible::QS(): %s", IIDToString(riid).constData());
1317     if (riid == IID_IAccessible || riid == IID_IUnknown || riid == IID_IDispatch) {
1318         *iface = static_cast<IAccessible*>(this);
1319     } else if (/*guidService == IID_IAccessible && */riid == IID_IAccessible2) {
1320         *iface = static_cast<IAccessible2*>(this);
1321     } else  if (riid == IID_IAccessibleApplication) {
1322         *iface = new AccessibleApplication;
1323         return S_OK;
1324     } else {
1325         QueryInterface(riid, iface);
1326     }
1327     if (*iface) {
1328         AddRef();
1329         return S_OK;
1330     }
1331
1332     return E_NOINTERFACE;
1333 }
1334
1335
1336 /*!
1337   \internal
1338   private function..
1339   \a maxRelations max number of relations to return in \a relations
1340   \a relations the array of relations matching
1341   \a startIndex Index to start to return from,
1342                    it will return only that specific relation in \a relations
1343
1344   If \a relations is null, \a startIndex and \a maxRelations are ignored, causing
1345   it to return the number of relations in \a nRelations
1346 */
1347 HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations /* = 0*/)
1348 {
1349     if (nRelations)
1350         *nRelations = 0;
1351     typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationEntry;
1352     QVector<RelationEntry> rels = accessible->relations();
1353     QMap<QAccessible::Relation, QAccessibleInterface *> relationMap;
1354     for (QVector<RelationEntry>::const_iterator it = rels.constBegin(); it != rels.constEnd(); ++it)
1355     {
1356         RelationEntry e = *it;
1357         relationMap.insertMulti(e.second, e.first);
1358     }
1359
1360     QList<QAccessible::Relation> keys = relationMap.keys();
1361     const int numRelations = keys.count();
1362     if (relations) {
1363         for (int i = startIndex; i < qMin(startIndex + (int)maxRelations, numRelations); ++i) {
1364             QAccessible::Relation relation = keys.at(i);
1365             QList<QAccessibleInterface*> targets = relationMap.values(relation);
1366             AccessibleRelation *rel = new AccessibleRelation(targets, relation);
1367             *relations = rel;
1368             ++relations;
1369         }
1370     }
1371     if (nRelations)
1372         *nRelations = numRelations;
1373
1374     return numRelations > 0 ? S_OK : S_FALSE;
1375 }
1376
1377
1378
1379
1380 /*!
1381   \internal
1382   helper to wrap a QList<QAccessibleInterface*> inside an array of IAccessible*
1383   The IAccessible* array is returned as a IUnknown*
1384 */
1385 HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount)
1386 {
1387     const int count = inputCells.count();
1388     // Server allocates array
1389     IUnknown **outputCells = count ? (IUnknown**)::CoTaskMemAlloc(sizeof(IUnknown*) * count ) : (IUnknown**)0;
1390     for (int i = 0; i < count; ++i)
1391         outputCells[i] = QWindowsAccessibility::wrap(inputCells.at(i));
1392
1393     *outputAccessibles = outputCells;
1394     *nCellCount = count;
1395     return count > 0 ? S_OK : S_FALSE;
1396 }
1397
1398 uint QWindowsIA2Accessible::uniqueID() const
1399 {
1400     uint uid = 0;
1401     if (QObject *obj = accessible->object())
1402         uid = qHash(obj);
1403
1404     if (!uid) {
1405         QAccessibleInterface *acc = accessible;
1406         QVector<int> indexOfNodes;
1407         while (acc && !acc->object()) {
1408             QAccessibleInterface *par = acc->parent();
1409             indexOfNodes.append(par->indexOfChild(acc));
1410             if (acc != accessible)
1411                 delete acc;
1412             acc = par;
1413         }
1414         if (acc) {
1415             if (acc->object()) {
1416                 uid = qHash(acc->object());
1417                 for (int i = 0; i < indexOfNodes.count(); ++i)
1418                     uid = qHash(uid + indexOfNodes.at(i));
1419
1420             }
1421             if (acc != accessible)
1422                 delete acc;
1423         }
1424     }
1425     return uid;
1426 }
1427
1428
1429 #define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid)
1430
1431 QByteArray QWindowsIA2Accessible::IIDToString(REFIID id)
1432 {
1433     IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown);
1434     IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch);
1435     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible);
1436     IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow);
1437     IF_EQUAL_RETURN_IIDSTRING(id, IID_IServiceProvider);
1438     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible2);
1439     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleAction);
1440     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleApplication);
1441     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleComponent);
1442     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleEditableText);
1443     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHyperlink);
1444     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHypertext);
1445     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleImage);
1446     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleRelation);
1447     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable);
1448     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable2);
1449     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTableCell);
1450     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleText);
1451     IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleValue);
1452
1453     // else...
1454     QByteArray strGuid;
1455 #if 0   // Can be useful for debugging, but normally we'd like to reduce the noise a bit...
1456     OLECHAR szGuid[39]={0};
1457     ::StringFromGUID2(id, szGuid, 39);
1458     strGuid.reserve(40);
1459     ::WideCharToMultiByte(CP_UTF8, 0, szGuid, 39, strGuid.data(), 39, NULL, NULL);
1460     strGuid[38] = '\0';
1461 #endif
1462     return strGuid;
1463 }
1464
1465
1466 QT_END_NAMESPACE
1467
1468 #endif //QT_NO_ACCESSIBILITY