]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/accessibility/Accessible.java
05f69309b2277a917762fc50be6a66c807a12049
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / accessibility / Accessible.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.accessibility;
15
16 import java.util.*;
17 import java.util.List;
18
19 import org.eclipse.swt.*;
20 import org.eclipse.swt.graphics.*;
21 import org.eclipse.swt.internal.*;
22 import org.eclipse.swt.internal.ole.win32.*;
23 import org.eclipse.swt.internal.win32.*;
24 import org.eclipse.swt.ole.win32.*;
25 import org.eclipse.swt.widgets.*;
26
27 /**
28  * Instances of this class provide a bridge between application
29  * code and assistive technology clients. Many platforms provide
30  * default accessible behavior for most widgets, and this class
31  * allows that default behavior to be overridden. Applications
32  * can get the default Accessible object for a control by sending
33  * it <code>getAccessible</code>, and then add an accessible listener
34  * to override simple items like the name and help string, or they
35  * can add an accessible control listener to override complex items.
36  * As a rule of thumb, an application would only want to use the
37  * accessible control listener to implement accessibility for a
38  * custom control.
39  *
40  * @see Control#getAccessible
41  * @see AccessibleListener
42  * @see AccessibleEvent
43  * @see AccessibleControlListener
44  * @see AccessibleControlEvent
45  * @see <a href="http://www.eclipse.org/swt/snippets/#accessibility">Accessibility snippets</a>
46  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
47  *
48  * @since 2.0
49  */
50 public class Accessible {
51         static final int MAX_RELATION_TYPES = 15;
52         static final int TABLE_MODEL_CHANGE_SIZE = 5;
53         static final int TEXT_CHANGE_SIZE = 4;
54         static final int SCROLL_RATE = 100;
55         static final boolean DEBUG = false;
56         static final String PROPERTY_USEIA2 = "org.eclipse.swt.accessibility.UseIA2"; //$NON-NLS-1$
57         static boolean UseIA2 = true;
58         static int UniqueID = -0x10;
59         int refCount = 0, enumIndex = 0;
60         Runnable timer;
61         COMObject objIAccessible, objIEnumVARIANT, objIServiceProvider,
62                 objIAccessibleApplication, /*objIAccessibleComponent,*/ objIAccessibleEditableText, objIAccessibleHyperlink,
63                 objIAccessibleHypertext, /*objIAccessibleImage,*/ objIAccessibleTable2, objIAccessibleTableCell,
64                 objIAccessibleValue; /* objIAccessibleRelation is defined in Relation class */
65         IAccessible iaccessible;
66         List<AccessibleListener> accessibleListeners;
67         List<AccessibleControlListener> accessibleControlListeners;
68         List<AccessibleTextListener> accessibleTextListeners;
69         List<AccessibleActionListener> accessibleActionListeners;
70         List<AccessibleEditableTextListener> accessibleEditableTextListeners;
71         List<AccessibleHyperlinkListener> accessibleHyperlinkListeners;
72         List<AccessibleTableListener> accessibleTableListeners;
73         List<AccessibleTableCellListener> accessibleTableCellListeners;
74         List<AccessibleTextExtendedListener> accessibleTextExtendedListeners;
75         List<AccessibleValueListener> accessibleValueListeners;
76         List<AccessibleAttributeListener> accessibleAttributeListeners;
77         Relation relations[] = new Relation[MAX_RELATION_TYPES];
78         Object[] variants;
79         Accessible parent;
80         List<Accessible> children = new ArrayList<>();
81         Control control;
82         int uniqueID = -1;
83         int [] tableChange; // type, rowStart, rowCount, columnStart, columnCount
84         Object [] textDeleted; // type, start, end, text
85         Object [] textInserted; // type, start, end, text
86         ToolItem item;
87
88         static {
89                 String property = System.getProperty (PROPERTY_USEIA2);
90                 if (property != null && property.equalsIgnoreCase ("false")) { //$NON-NLS-1$
91                         UseIA2 = false;
92                 }
93         }
94
95         /**
96          * Constructs a new instance of this class given its parent.
97          *
98          * @param parent the Accessible parent, which must not be null
99          *
100          * @exception IllegalArgumentException <ul>
101          *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
102          * </ul>
103          *
104          * @see #dispose
105          * @see Control#getAccessible
106          *
107          * @since 3.6
108          */
109         public Accessible(Accessible parent) {
110                 this.parent = checkNull(parent);
111                 this.control = parent.control;
112                 parent.children.add(this);
113                 AddRef();
114         }
115
116         /**
117          * @since 3.5
118          * @deprecated
119          */
120         @Deprecated
121         protected Accessible() {
122         }
123
124         Accessible(Control control) {
125                 this.control = control;
126                 long[] ppvObject = new long[1];
127                 /* CreateStdAccessibleObject([in] hwnd, [in] idObject, [in] riidInterface, [out] ppvObject).
128                  * AddRef has already been called on ppvObject by the callee and must be released by the caller.
129                  */
130                 int result = (int)COM.CreateStdAccessibleObject(control.handle, OS.OBJID_CLIENT, COM.IIDIAccessible, ppvObject);
131                 /* The object needs to be checked, because if the CreateStdAccessibleObject()
132                  * symbol is not found, the return value is S_OK.
133                  */
134                 if (ppvObject[0] == 0) return;
135                 if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
136                 iaccessible = new IAccessible(ppvObject[0]);
137                 createIAccessible();
138                 AddRef();
139         }
140
141         Accessible(Accessible parent, long iaccessible_address) {
142                 this(parent);
143                 iaccessible = new IAccessible(iaccessible_address);
144         }
145
146         static Accessible checkNull (Accessible parent) {
147                 if (parent == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
148                 return parent;
149         }
150
151         void createIAccessible() {
152                 objIAccessible = new COMObject(new int[] {2,0,0,/*IA>>*/1,3,5,8,1,1,2,2,2,2,2,2,2,3,2,1,1,2,2,5,3,3,1,2,2,/*<<IA*/1,2,3,1,1,3,3,1,1,1,1,3,3,1,1,1,1,1}) {
153                         @Override
154                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
155                         @Override
156                         public long method1(long[] args) {return AddRef();}
157                         @Override
158                         public long method2(long[] args) {return Release();}
159                         // method3 GetTypeInfoCount - not implemented
160                         // method4 GetTypeInfo - not implemented
161                         // method5 GetIDsOfNames - not implemented
162                         // method6 Invoke - not implemented
163                         @Override
164                         public long method7(long[] args) {return get_accParent(args[0]);}
165                         @Override
166                         public long method8(long[] args) {return get_accChildCount(args[0]);}
167                         @Override
168                         public long method9(long[] args) {return get_accChild(args[0], args[1]);}
169                         @Override
170                         public long method10(long[] args) {return get_accName(args[0], args[1]);}
171                         @Override
172                         public long method11(long[] args) {return get_accValue(args[0], args[1]);}
173                         @Override
174                         public long method12(long[] args) {return get_accDescription(args[0], args[1]);}
175                         @Override
176                         public long method13(long[] args) {return get_accRole(args[0], args[1]);}
177                         @Override
178                         public long method14(long[] args) {return get_accState(args[0], args[1]);}
179                         @Override
180                         public long method15(long[] args) {return get_accHelp(args[0], args[1]);}
181                         @Override
182                         public long method16(long[] args) {return get_accHelpTopic(args[0], args[1], args[2]);}
183                         @Override
184                         public long method17(long[] args) {return get_accKeyboardShortcut(args[0], args[1]);}
185                         @Override
186                         public long method18(long[] args) {return get_accFocus(args[0]);}
187                         @Override
188                         public long method19(long[] args) {return get_accSelection(args[0]);}
189                         @Override
190                         public long method20(long[] args) {return get_accDefaultAction(args[0], args[1]);}
191                         @Override
192                         public long method21(long[] args) {return accSelect((int)args[0], args[1]);}
193                         @Override
194                         public long method22(long[] args) {return accLocation(args[0], args[1], args[2], args[3], args[4]);}
195                         @Override
196                         public long method23(long[] args) {return accNavigate((int)args[0], args[1], args[2]);}
197                         @Override
198                         public long method24(long[] args) {return accHitTest((int)args[0], (int)args[1], args[2]);}
199                         @Override
200                         public long method25(long[] args) {return accDoDefaultAction(args[0]);}
201                         @Override
202                         public long method26(long[] args) {return put_accName(args[0], args[1]);}
203                         @Override
204                         public long method27(long[] args) {return put_accValue(args[0], args[1]);}
205
206                         // IAccessible2 methods
207                         @Override
208                         public long method28(long[] args) {return get_nRelations(args[0]);}
209                         @Override
210                         public long method29(long[] args) {return get_relation((int)args[0], args[1]);}
211                         @Override
212                         public long method30(long[] args) {return get_relations((int)args[0], args[1], args[2]);}
213                         @Override
214                         public long method31(long[] args) {return get_role(args[0]);}
215                         @Override
216                         public long method32(long[] args) {return scrollTo((int)args[0]);}
217                         @Override
218                         public long method33(long[] args) {return scrollToPoint((int)args[0], (int)args[1], (int)args[2]);}
219                         @Override
220                         public long method34(long[] args) {return get_groupPosition(args[0], args[1], args[2]);}
221                         @Override
222                         public long method35(long[] args) {return get_states(args[0]);}
223                         @Override
224                         public long method36(long[] args) {return get_extendedRole(args[0]);}
225                         @Override
226                         public long method37(long[] args) {return get_localizedExtendedRole(args[0]);}
227                         @Override
228                         public long method38(long[] args) {return get_nExtendedStates(args[0]);}
229                         @Override
230                         public long method39(long[] args) {return get_extendedStates((int)args[0], args[1], args[2]);}
231                         @Override
232                         public long method40(long[] args) {return get_localizedExtendedStates((int)args[0], args[1], args[2]);}
233                         @Override
234                         public long method41(long[] args) {return get_uniqueID(args[0]);}
235                         @Override
236                         public long method42(long[] args) {return get_windowHandle(args[0]);}
237                         @Override
238                         public long method43(long[] args) {return get_indexInParent(args[0]);}
239                         @Override
240                         public long method44(long[] args) {return get_locale(args[0]);}
241                         @Override
242                         public long method45(long[] args) {return get_attributes(args[0]);}
243                 };
244         }
245
246         void createIAccessibleApplication() {
247                 objIAccessibleApplication = new COMObject(new int[] {2,0,0,1,1,1,1}) {
248                         @Override
249                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
250                         @Override
251                         public long method1(long[] args) {return AddRef();}
252                         @Override
253                         public long method2(long[] args) {return Release();}
254                         @Override
255                         public long method3(long[] args) {return get_appName(args[0]);}
256                         @Override
257                         public long method4(long[] args) {return get_appVersion(args[0]);}
258                         @Override
259                         public long method5(long[] args) {return get_toolkitName(args[0]);}
260                         @Override
261                         public long method6(long[] args) {return get_toolkitVersion(args[0]);}
262                 };
263         }
264
265         // This method is intentionally commented. We are not providing IAccessibleComponent at this time.
266 //      void createIAccessibleComponent() {
267 //              objIAccessibleComponent = new COMObject(new int[] {2,0,0,2,1,1}) {
268 //                      public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
269 //                      public long method1(long[] args) {return AddRef();}
270 //                      public long method2(long[] args) {return Release();}
271 //                      public long method3(long[] args) {return get_locationInParent(args[0], args[1]);}
272 //                      public long method4(long[] args) {return get_foreground(args[0]);}
273 //                      public long method5(long[] args) {return get_background(args[0]);}
274 //              };
275 //      }
276
277         void createIAccessibleEditableText() {
278                 objIAccessibleEditableText = new COMObject(new int[] {2,0,0,2,2,2,2,1,3,3}) {
279                         @Override
280                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
281                         @Override
282                         public long method1(long[] args) {return AddRef();}
283                         @Override
284                         public long method2(long[] args) {return Release();}
285                         @Override
286                         public long method3(long[] args) {return copyText((int)args[0], (int)args[1]);}
287                         @Override
288                         public long method4(long[] args) {return deleteText((int)args[0], (int)args[1]);}
289                         @Override
290                         public long method5(long[] args) {return insertText((int)args[0], args[1]);}
291                         @Override
292                         public long method6(long[] args) {return cutText((int)args[0], (int)args[1]);}
293                         @Override
294                         public long method7(long[] args) {return pasteText((int)args[0]);}
295                         @Override
296                         public long method8(long[] args) {return replaceText((int)args[0], (int)args[1], args[2]);}
297                         @Override
298                         public long method9(long[] args) {return setAttributes((int)args[0], (int)args[1], args[2]);}
299                 };
300         }
301
302         void createIAccessibleHyperlink() {
303                 objIAccessibleHyperlink = new COMObject(new int[] {2,0,0,/*IAA>>*/1,1,2,4,2,2,/*<<IAA*/2,2,1,1,1}) {
304                         @Override
305                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
306                         @Override
307                         public long method1(long[] args) {return AddRef();}
308                         @Override
309                         public long method2(long[] args) {return Release();}
310                         // IAccessibleAction
311                         @Override
312                         public long method3(long[] args) {return get_nActions(args[0]);}
313                         @Override
314                         public long method4(long[] args) {return doAction((int)args[0]);}
315                         @Override
316                         public long method5(long[] args) {return get_description((int)args[0], args[1]);}
317                         @Override
318                         public long method6(long[] args) {return get_keyBinding((int)args[0], (int)args[1], args[2], args[3]);}
319                         @Override
320                         public long method7(long[] args) {return get_name((int)args[0], args[1]);}
321                         @Override
322                         public long method8(long[] args) {return get_localizedName((int)args[0], args[1]);}
323                         // IAccessibleHyperlink
324                         @Override
325                         public long method9(long[] args) {return get_anchor((int)args[0], args[1]);}
326                         @Override
327                         public long method10(long[] args) {return get_anchorTarget((int)args[0], args[1]);}
328                         @Override
329                         public long method11(long[] args) {return get_startIndex(args[0]);}
330                         @Override
331                         public long method12(long[] args) {return get_endIndex(args[0]);}
332                         @Override
333                         public long method13(long[] args) {return get_valid(args[0]);}
334                 };
335         }
336
337         void createIAccessibleHypertext() {
338                 objIAccessibleHypertext = new COMObject(new int[] {2,0,0,/*IAT>>*/2,4,1,6,1,4,3,3,5,5,5,1,1,3,1,3,5,1,1,/*<<IAT*/1,2,2}) {
339                         @Override
340                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
341                         @Override
342                         public long method1(long[] args) {return AddRef();}
343                         @Override
344                         public long method2(long[] args) {return Release();}
345                         // IAccessibleText
346                         @Override
347                         public long method3(long[] args) {return addSelection((int)args[0], (int)args[1]);}
348                         @Override
349                         public long method4(long[] args) {return get_attributes((int)args[0], args[1], args[2], args[3]);}
350                         @Override
351                         public long method5(long[] args) {return get_caretOffset(args[0]);}
352                         @Override
353                         public long method6(long[] args) {return get_characterExtents((int)args[0], (int)args[1], args[2], args[3], args[4], args[5]);}
354                         @Override
355                         public long method7(long[] args) {return get_nSelections(args[0]);}
356                         @Override
357                         public long method8(long[] args) {return get_offsetAtPoint((int)args[0], (int)args[1], (int)args[2], args[3]);}
358                         @Override
359                         public long method9(long[] args) {return get_selection((int)args[0], args[1], args[2]);}
360                         @Override
361                         public long method10(long[] args) {return get_text((int)args[0], (int)args[1], args[2]);}
362                         @Override
363                         public long method11(long[] args) {return get_textBeforeOffset((int)args[0], (int)args[1], args[2], args[3], args[4]);}
364                         @Override
365                         public long method12(long[] args) {return get_textAfterOffset((int)args[0], (int)args[1], args[2], args[3], args[4]);}
366                         @Override
367                         public long method13(long[] args) {return get_textAtOffset((int)args[0], (int)args[1], args[2], args[3], args[4]);}
368                         @Override
369                         public long method14(long[] args) {return removeSelection((int)args[0]);}
370                         @Override
371                         public long method15(long[] args) {return setCaretOffset((int)args[0]);}
372                         @Override
373                         public long method16(long[] args) {return setSelection((int)args[0], (int)args[1], (int)args[2]);}
374                         @Override
375                         public long method17(long[] args) {return get_nCharacters(args[0]);}
376                         @Override
377                         public long method18(long[] args) {return scrollSubstringTo((int)args[0], (int)args[1], (int)args[2]);}
378                         @Override
379                         public long method19(long[] args) {return scrollSubstringToPoint((int)args[0], (int)args[1], (int)args[2], (int)args[3], (int)args[4]);}
380                         @Override
381                         public long method20(long[] args) {return get_newText(args[0]);}
382                         @Override
383                         public long method21(long[] args) {return get_oldText(args[0]);}
384                         // IAccessibleHypertext
385                         @Override
386                         public long method22(long[] args) {return get_nHyperlinks(args[0]);}
387                         @Override
388                         public long method23(long[] args) {return get_hyperlink((int)args[0], args[1]);}
389                         @Override
390                         public long method24(long[] args) {return get_hyperlinkIndex((int)args[0], args[1]);}
391                 };
392         }
393
394         // This method is intentionally commented. We are not providing IAccessibleImage at this time.
395 //      void createIAccessibleImage() {
396 //              objIAccessibleImage = new COMObject(new int[] {2,0,0,1,3,2}) {
397 //                      public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
398 //                      public long method1(long[] args) {return AddRef();}
399 //                      public long method2(long[] args) {return Release();}
400 //                      public long method3(long[] args) {return get_description(args[0]);}
401 //                      public long method4(long[] args) {return get_imagePosition((int)args[0], args[1], args[2]);}
402 //                      public long method5(long[] args) {return get_imageSize(args[0], args[1]);}
403 //              };
404 //      }
405
406         void createIAccessibleTable2() {
407                 objIAccessibleTable2 = new COMObject(new int[] {2,0,0,3,1,2,1,1,1,1,1,2,2,2,2,1,2,2,1,1,1,1,1}) {
408                         @Override
409                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
410                         @Override
411                         public long method1(long[] args) {return AddRef();}
412                         @Override
413                         public long method2(long[] args) {return Release();}
414                         @Override
415                         public long method3(long[] args) {return get_cellAt((int)args[0], (int)args[1], args[2]);}
416                         @Override
417                         public long method4(long[] args) {return get_caption(args[0]);}
418                         @Override
419                         public long method5(long[] args) {return get_columnDescription((int)args[0], args[1]);}
420                         @Override
421                         public long method6(long[] args) {return get_nColumns(args[0]);}
422                         @Override
423                         public long method7(long[] args) {return get_nRows(args[0]);}
424                         @Override
425                         public long method8(long[] args) {return get_nSelectedCells(args[0]);}
426                         @Override
427                         public long method9(long[] args) {return get_nSelectedColumns(args[0]);}
428                         @Override
429                         public long method10(long[] args) {return get_nSelectedRows(args[0]);}
430                         @Override
431                         public long method11(long[] args) {return get_rowDescription((int)args[0], args[1]);}
432                         @Override
433                         public long method12(long[] args) {return get_selectedCells(args[0], args[1]);}
434                         @Override
435                         public long method13(long[] args) {return get_selectedColumns(args[0], args[1]);}
436                         @Override
437                         public long method14(long[] args) {return get_selectedRows(args[0], args[1]);}
438                         @Override
439                         public long method15(long[] args) {return get_summary(args[0]);}
440                         @Override
441                         public long method16(long[] args) {return get_isColumnSelected((int)args[0], args[1]);}
442                         @Override
443                         public long method17(long[] args) {return get_isRowSelected((int)args[0], args[1]);}
444                         @Override
445                         public long method18(long[] args) {return selectRow((int)args[0]);}
446                         @Override
447                         public long method19(long[] args) {return selectColumn((int)args[0]);}
448                         @Override
449                         public long method20(long[] args) {return unselectRow((int)args[0]);}
450                         @Override
451                         public long method21(long[] args) {return unselectColumn((int)args[0]);}
452                         @Override
453                         public long method22(long[] args) {return get_modelChange(args[0]);}
454                 };
455         }
456
457         void createIAccessibleTableCell() {
458                 objIAccessibleTableCell = new COMObject(new int[] {2,0,0,1,2,1,1,2,1,1,5,1}) {
459                         @Override
460                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
461                         @Override
462                         public long method1(long[] args) {return AddRef();}
463                         @Override
464                         public long method2(long[] args) {return Release();}
465                         @Override
466                         public long method3(long[] args) {return get_columnExtent(args[0]);}
467                         @Override
468                         public long method4(long[] args) {return get_columnHeaderCells(args[0], args[1]);}
469                         @Override
470                         public long method5(long[] args) {return get_columnIndex(args[0]);}
471                         @Override
472                         public long method6(long[] args) {return get_rowExtent(args[0]);}
473                         @Override
474                         public long method7(long[] args) {return get_rowHeaderCells(args[0], args[1]);}
475                         @Override
476                         public long method8(long[] args) {return get_rowIndex(args[0]);}
477                         @Override
478                         public long method9(long[] args) {return get_isSelected(args[0]);}
479                         @Override
480                         public long method10(long[] args) {return get_rowColumnExtents(args[0], args[1], args[2], args[3], args[4]);}
481                         @Override
482                         public long method11(long[] args) {return get_table(args[0]);}
483                 };
484         }
485
486         void createIAccessibleValue() {
487                 objIAccessibleValue = new COMObject(new int[] {2,0,0,1,1,1,1}) {
488                         @Override
489                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
490                         @Override
491                         public long method1(long[] args) {return AddRef();}
492                         @Override
493                         public long method2(long[] args) {return Release();}
494                         @Override
495                         public long method3(long[] args) {return get_currentValue(args[0]);}
496                         @Override
497                         public long method4(long[] args) {return setCurrentValue(args[0]);}
498                         @Override
499                         public long method5(long[] args) {return get_maximumValue(args[0]);}
500                         @Override
501                         public long method6(long[] args) {return get_minimumValue(args[0]);}
502                 };
503         }
504
505         void createIEnumVARIANT() {
506                 objIEnumVARIANT = new COMObject(new int[] {2,0,0,3,1,0,1}) {
507                         @Override
508                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
509                         @Override
510                         public long method1(long[] args) {return AddRef();}
511                         @Override
512                         public long method2(long[] args) {return Release();}
513                         @Override
514                         public long method3(long[] args) {return Next((int)args[0], args[1], args[2]);}
515                         @Override
516                         public long method4(long[] args) {return Skip((int)args[0]);}
517                         @Override
518                         public long method5(long[] args) {return Reset();}
519                         @Override
520                         public long method6(long[] args) {return Clone(args[0]);}
521                 };
522         }
523
524         void createIServiceProvider() {
525                 objIServiceProvider = new COMObject(new int[] {2,0,0,3}) {
526                         @Override
527                         public long method0(long[] args) {return QueryInterface(args[0], args[1]);}
528                         @Override
529                         public long method1(long[] args) {return AddRef();}
530                         @Override
531                         public long method2(long[] args) {return Release();}
532                         @Override
533                         public long method3(long[] args) {return QueryService(args[0], args[1], args[2]);}
534                 };
535         }
536
537         /**
538          * Invokes platform specific functionality to allocate a new accessible object.
539          * <p>
540          * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
541          * API for <code>Accessible</code>. It is marked public only so that it
542          * can be shared within the packages provided by SWT. It is not
543          * available on all platforms, and should never be called from
544          * application code.
545          * </p>
546          *
547          * @param control the control to get the accessible object for
548          * @return the platform specific accessible object
549          *
550          * @noreference This method is not intended to be referenced by clients.
551          */
552         public static Accessible internal_new_Accessible(Control control) {
553                 return new Accessible(control);
554         }
555
556         /**
557          * Adds the listener to the collection of listeners who will
558          * be notified when an accessible client asks for certain strings,
559          * such as name, description, help, or keyboard shortcut. The
560          * listener is notified by sending it one of the messages defined
561          * in the <code>AccessibleListener</code> interface.
562          *
563          * @param listener the listener that should be notified when the receiver
564          * is asked for a name, description, help, or keyboard shortcut string
565          *
566          * @exception IllegalArgumentException <ul>
567          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
568          * </ul>
569          * @exception SWTException <ul>
570          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
571          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
572          * </ul>
573          *
574          * @see AccessibleListener
575          * @see #removeAccessibleListener
576          */
577         public void addAccessibleListener(AccessibleListener listener) {
578                 checkWidget();
579                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
580                 if (accessibleListeners == null) accessibleListeners = new ArrayList<>();
581                 accessibleListeners.add(listener);
582         }
583
584         /**
585          * Adds the listener to the collection of listeners who will
586          * be notified when an accessible client asks for custom control
587          * specific information. The listener is notified by sending it
588          * one of the messages defined in the <code>AccessibleControlListener</code>
589          * interface.
590          *
591          * @param listener the listener that should be notified when the receiver
592          * is asked for custom control specific information
593          *
594          * @exception IllegalArgumentException <ul>
595          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
596          * </ul>
597          * @exception SWTException <ul>
598          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
599          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
600          * </ul>
601          *
602          * @see AccessibleControlListener
603          * @see #removeAccessibleControlListener
604          */
605         public void addAccessibleControlListener(AccessibleControlListener listener) {
606                 checkWidget();
607                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
608                 if (accessibleControlListeners == null) accessibleControlListeners = new ArrayList<>();
609                 accessibleControlListeners.add(listener);
610         }
611
612         /**
613          * Adds the listener to the collection of listeners who will
614          * be notified when an accessible client asks for custom text control
615          * specific information. The listener is notified by sending it
616          * one of the messages defined in the <code>AccessibleTextListener</code>
617          * and <code>AccessibleTextExtendedListener</code> interfaces.
618          *
619          * @param listener the listener that should be notified when the receiver
620          * is asked for custom text control specific information
621          *
622          * @exception IllegalArgumentException <ul>
623          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
624          * </ul>
625          * @exception SWTException <ul>
626          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
627          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
628          * </ul>
629          *
630          * @see AccessibleTextListener
631          * @see AccessibleTextExtendedListener
632          * @see #removeAccessibleTextListener
633          *
634          * @since 3.0
635          */
636         public void addAccessibleTextListener (AccessibleTextListener listener) {
637                 checkWidget ();
638                 if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
639                 if (listener instanceof AccessibleTextExtendedListener) {
640                         if (accessibleTextExtendedListeners == null) accessibleTextExtendedListeners = new ArrayList<>();
641                         accessibleTextExtendedListeners.add ((AccessibleTextExtendedListener) listener);
642                 } else {
643                         if (accessibleTextListeners == null) accessibleTextListeners = new ArrayList<>();
644                         accessibleTextListeners.add (listener);
645                 }
646         }
647
648         /**
649          * Adds the listener to the collection of listeners that will be
650          * notified when an accessible client asks for any of the properties
651          * defined in the <code>AccessibleActionListener</code> interface.
652          *
653          * @param listener the listener that should be notified when the receiver
654          * is asked for <code>AccessibleActionListener</code> interface properties
655          *
656          * @exception IllegalArgumentException <ul>
657          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
658          * </ul>
659          * @exception SWTException <ul>
660          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
661          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
662          * </ul>
663          *
664          * @see AccessibleActionListener
665          * @see #removeAccessibleActionListener
666          *
667          * @since 3.6
668          */
669         public void addAccessibleActionListener(AccessibleActionListener listener) {
670                 checkWidget();
671                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
672                 if (accessibleActionListeners == null) accessibleActionListeners = new ArrayList<>();
673                 accessibleActionListeners.add(listener);
674         }
675
676         /**
677          * Adds the listener to the collection of listeners that will be
678          * notified when an accessible client asks for any of the properties
679          * defined in the <code>AccessibleEditableTextListener</code> interface.
680          *
681          * @param listener the listener that should be notified when the receiver
682          * is asked for <code>AccessibleEditableTextListener</code> interface properties
683          *
684          * @exception IllegalArgumentException <ul>
685          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
686          * </ul>
687          * @exception SWTException <ul>
688          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
689          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
690          * </ul>
691          *
692          * @see AccessibleEditableTextListener
693          * @see #removeAccessibleEditableTextListener
694          *
695          * @since 3.7
696          */
697         public void addAccessibleEditableTextListener(AccessibleEditableTextListener listener) {
698                 checkWidget();
699                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
700                 if (accessibleEditableTextListeners == null) accessibleEditableTextListeners = new ArrayList<>();
701                 accessibleEditableTextListeners.add(listener);
702         }
703
704         /**
705          * Adds the listener to the collection of listeners that will be
706          * notified when an accessible client asks for any of the properties
707          * defined in the <code>AccessibleHyperlinkListener</code> interface.
708          *
709          * @param listener the listener that should be notified when the receiver
710          * is asked for <code>AccessibleHyperlinkListener</code> interface properties
711          *
712          * @exception IllegalArgumentException <ul>
713          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
714          * </ul>
715          * @exception SWTException <ul>
716          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
717          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
718          * </ul>
719          *
720          * @see AccessibleHyperlinkListener
721          * @see #removeAccessibleHyperlinkListener
722          *
723          * @since 3.6
724          */
725         public void addAccessibleHyperlinkListener(AccessibleHyperlinkListener listener) {
726                 checkWidget();
727                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
728                 if (accessibleHyperlinkListeners == null) accessibleHyperlinkListeners = new ArrayList<>();
729                 accessibleHyperlinkListeners.add(listener);
730         }
731
732         /**
733          * Adds the listener to the collection of listeners that will be
734          * notified when an accessible client asks for any of the properties
735          * defined in the <code>AccessibleTableListener</code> interface.
736          *
737          * @param listener the listener that should be notified when the receiver
738          * is asked for <code>AccessibleTableListener</code> interface properties
739          *
740          * @exception IllegalArgumentException <ul>
741          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
742          * </ul>
743          * @exception SWTException <ul>
744          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
745          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
746          * </ul>
747          *
748          * @see AccessibleTableListener
749          * @see #removeAccessibleTableListener
750          *
751          * @since 3.6
752          */
753         public void addAccessibleTableListener(AccessibleTableListener listener) {
754                 checkWidget();
755                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
756                 if (accessibleTableListeners == null) accessibleTableListeners = new ArrayList<>();
757                 accessibleTableListeners.add(listener);
758         }
759
760         /**
761          * Adds the listener to the collection of listeners that will be
762          * notified when an accessible client asks for any of the properties
763          * defined in the <code>AccessibleTableCellListener</code> interface.
764          *
765          * @param listener the listener that should be notified when the receiver
766          * is asked for <code>AccessibleTableCellListener</code> interface properties
767          *
768          * @exception IllegalArgumentException <ul>
769          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
770          * </ul>
771          * @exception SWTException <ul>
772          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
773          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
774          * </ul>
775          *
776          * @see AccessibleTableCellListener
777          * @see #removeAccessibleTableCellListener
778          *
779          * @since 3.6
780          */
781         public void addAccessibleTableCellListener(AccessibleTableCellListener listener) {
782                 checkWidget();
783                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
784                 if (accessibleTableCellListeners == null) accessibleTableCellListeners = new ArrayList<>();
785                 accessibleTableCellListeners.add(listener);
786         }
787
788         /**
789          * Adds the listener to the collection of listeners that will be
790          * notified when an accessible client asks for any of the properties
791          * defined in the <code>AccessibleValueListener</code> interface.
792          *
793          * @param listener the listener that should be notified when the receiver
794          * is asked for <code>AccessibleValueListener</code> interface properties
795          *
796          * @exception IllegalArgumentException <ul>
797          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
798          * </ul>
799          * @exception SWTException <ul>
800          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
801          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
802          * </ul>
803          *
804          * @see AccessibleValueListener
805          * @see #removeAccessibleValueListener
806          *
807          * @since 3.6
808          */
809         public void addAccessibleValueListener(AccessibleValueListener listener) {
810                 checkWidget();
811                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
812                 if (accessibleValueListeners == null) accessibleValueListeners = new ArrayList<>();
813                 accessibleValueListeners.add(listener);
814         }
815
816         /**
817          * Adds the listener to the collection of listeners that will be
818          * notified when an accessible client asks for any of the properties
819          * defined in the <code>AccessibleAttributeListener</code> interface.
820          *
821          * @param listener the listener that should be notified when the receiver
822          * is asked for <code>AccessibleAttributeListener</code> interface properties
823          *
824          * @exception IllegalArgumentException <ul>
825          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
826          * </ul>
827          * @exception SWTException <ul>
828          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
829          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
830          * </ul>
831          *
832          * @see AccessibleAttributeListener
833          * @see #removeAccessibleAttributeListener
834          *
835          * @since 3.6
836          */
837         public void addAccessibleAttributeListener(AccessibleAttributeListener listener) {
838                 checkWidget();
839                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
840                 if (accessibleAttributeListeners == null) accessibleAttributeListeners = new ArrayList<>();
841                 accessibleAttributeListeners.add(listener);
842         }
843
844         /**
845          * Adds a relation with the specified type and target
846          * to the receiver's set of relations.
847          *
848          * @param type an <code>ACC</code> constant beginning with RELATION_* indicating the type of relation
849          * @param target the accessible that is the target for this relation
850          * @exception IllegalArgumentException ERROR_NULL_ARGUMENT - if the Accessible target is null
851          * @since 3.6
852          */
853         public void addRelation(int type, Accessible target) {
854                 checkWidget();
855                 if (target == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
856                 if (relations[type] == null) {
857                         relations[type] = new Relation(this, type);
858                 }
859                 relations[type].addTarget(target);
860         }
861
862         /**
863          * Disposes of the operating system resources associated with
864          * the receiver, and removes the receiver from its parent's
865          * list of children.
866          * <p>
867          * This method should be called when an accessible that was created
868          * with the public constructor <code>Accessible(Accessible parent)</code>
869          * is no longer needed. You do not need to call this when the receiver's
870          * control is disposed, because all <code>Accessible</code> instances
871          * associated with a control are released when the control is disposed.
872          * It is also not necessary to call this for instances of <code>Accessible</code>
873          * that were retrieved with <code>Control.getAccessible()</code>.
874          * </p>
875          *
876          * @since 3.6
877          */
878         public void dispose () {
879                 if (parent == null) return;
880                 Release();
881                 parent.children.remove(this);
882                 parent = null;
883         }
884
885         long getAddress() {
886                 /* The address of an Accessible is the address of its IAccessible COMObject. */
887                 if (objIAccessible == null) createIAccessible();
888                 return objIAccessible.getAddress();
889         }
890
891         /**
892          * Returns the control for this Accessible object.
893          *
894          * @return the receiver's control
895          * @since 3.0
896          */
897         public Control getControl() {
898                 return control;
899         }
900
901         /**
902          * Invokes platform specific functionality to dispose an accessible object.
903          * <p>
904          * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
905          * API for <code>Accessible</code>. It is marked public only so that it
906          * can be shared within the packages provided by SWT. It is not
907          * available on all platforms, and should never be called from
908          * application code.
909          * </p>
910          *
911          * @noreference This method is not intended to be referenced by clients.
912          */
913         public void internal_dispose_Accessible() {
914                 if (iaccessible != null) {
915                         iaccessible.Release();
916                 }
917                 iaccessible = null;
918                 Release();
919                 for (int i = 0; i < children.size(); i++) {
920                         Accessible child = children.get(i);
921                         child.dispose();
922                 }
923         }
924
925         /**
926          * Invokes platform specific functionality to handle a window message.
927          * <p>
928          * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
929          * API for <code>Accessible</code>. It is marked public only so that it
930          * can be shared within the packages provided by SWT. It is not
931          * available on all platforms, and should never be called from
932          * application code.
933          * </p>
934          *
935          * @noreference This method is not intended to be referenced by clients.
936          */
937         public long internal_WM_GETOBJECT (long wParam, long lParam) {
938                 if (objIAccessible == null) return 0;
939                 if ((int)lParam == OS.OBJID_CLIENT) {
940                         /* LresultFromObject([in] riid, [in] wParam, [in] pAcc)
941                          * The argument pAcc is owned by the caller so reference count does not
942                          * need to be incremented.
943                          */
944                         return COM.LresultFromObject(COM.IIDIAccessible, wParam, objIAccessible.getAddress());
945                 }
946                 return 0;
947         }
948
949         /**
950          * Removes the listener from the collection of listeners who will
951          * be notified when an accessible client asks for certain strings,
952          * such as name, description, help, or keyboard shortcut.
953          *
954          * @param listener the listener that should no longer be notified when the receiver
955          * is asked for a name, description, help, or keyboard shortcut string
956          *
957          * @exception IllegalArgumentException <ul>
958          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
959          * </ul>
960          * @exception SWTException <ul>
961          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
962          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
963          * </ul>
964          *
965          * @see AccessibleListener
966          * @see #addAccessibleListener
967          */
968         public void removeAccessibleListener(AccessibleListener listener) {
969                 checkWidget();
970                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
971                 if (accessibleListeners != null) {
972                         accessibleListeners.remove(listener);
973                         if (accessibleListeners.isEmpty()) accessibleListeners = null;
974                 }
975         }
976
977         /**
978          * Removes the listener from the collection of listeners who will
979          * be notified when an accessible client asks for custom control
980          * specific information.
981          *
982          * @param listener the listener that should no longer be notified when the receiver
983          * is asked for custom control specific information
984          *
985          * @exception IllegalArgumentException <ul>
986          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
987          * </ul>
988          * @exception SWTException <ul>
989          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
990          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
991          * </ul>
992          *
993          * @see AccessibleControlListener
994          * @see #addAccessibleControlListener
995          */
996         public void removeAccessibleControlListener(AccessibleControlListener listener) {
997                 checkWidget();
998                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
999                 if (accessibleControlListeners != null) {
1000                         accessibleControlListeners.remove(listener);
1001                         if (accessibleControlListeners.isEmpty()) accessibleControlListeners = null;
1002                 }
1003         }
1004
1005         /**
1006          * Removes the listener from the collection of listeners who will
1007          * be notified when an accessible client asks for custom text control
1008          * specific information.
1009          *
1010          * @param listener the listener that should no longer be notified when the receiver
1011          * is asked for custom text control specific information
1012          *
1013          * @exception IllegalArgumentException <ul>
1014          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1015          * </ul>
1016          * @exception SWTException <ul>
1017          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1018          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1019          * </ul>
1020          *
1021          * @see AccessibleTextListener
1022          * @see AccessibleTextExtendedListener
1023          * @see #addAccessibleTextListener
1024          *
1025          * @since 3.0
1026          */
1027         public void removeAccessibleTextListener (AccessibleTextListener listener) {
1028                 checkWidget ();
1029                 if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
1030                 if (listener instanceof AccessibleTextExtendedListener) {
1031                         if (accessibleTextExtendedListeners != null) {
1032                                 accessibleTextExtendedListeners.remove (listener);
1033                                 if (accessibleTextExtendedListeners.isEmpty()) accessibleTextExtendedListeners = null;
1034                         }
1035                 } else {
1036                         if (accessibleTextListeners != null) {
1037                                 accessibleTextListeners.remove (listener);
1038                                 if (accessibleTextListeners.isEmpty()) accessibleTextListeners = null;
1039                         }
1040                 }
1041         }
1042
1043         /**
1044          * Removes the listener from the collection of listeners that will be
1045          * notified when an accessible client asks for any of the properties
1046          * defined in the <code>AccessibleActionListener</code> interface.
1047          *
1048          * @param listener the listener that should no longer be notified when the receiver
1049          * is asked for <code>AccessibleActionListener</code> interface properties
1050          *
1051          * @exception IllegalArgumentException <ul>
1052          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1053          * </ul>
1054          * @exception SWTException <ul>
1055          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1056          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1057          * </ul>
1058          *
1059          * @see AccessibleActionListener
1060          * @see #addAccessibleActionListener
1061          *
1062          * @since 3.6
1063          */
1064         public void removeAccessibleActionListener(AccessibleActionListener listener) {
1065                 checkWidget();
1066                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
1067                 if (accessibleActionListeners != null) {
1068                         accessibleActionListeners.remove(listener);
1069                         if (accessibleActionListeners.isEmpty()) accessibleActionListeners = null;
1070                 }
1071         }
1072
1073         /**
1074          * Removes the listener from the collection of listeners that will be
1075          * notified when an accessible client asks for any of the properties
1076          * defined in the <code>AccessibleEditableTextListener</code> interface.
1077          *
1078          * @param listener the listener that should no longer be notified when the receiver
1079          * is asked for <code>AccessibleEditableTextListener</code> interface properties
1080          *
1081          * @exception IllegalArgumentException <ul>
1082          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1083          * </ul>
1084          * @exception SWTException <ul>
1085          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1086          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1087          * </ul>
1088          *
1089          * @see AccessibleEditableTextListener
1090          * @see #addAccessibleEditableTextListener
1091          *
1092          * @since 3.7
1093          */
1094         public void removeAccessibleEditableTextListener(AccessibleEditableTextListener listener) {
1095                 checkWidget();
1096                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
1097                 if (accessibleEditableTextListeners != null) {
1098                         accessibleEditableTextListeners.remove(listener);
1099                         if (accessibleEditableTextListeners.isEmpty()) accessibleEditableTextListeners = null;
1100                 }
1101         }
1102
1103         /**
1104          * Removes the listener from the collection of listeners that will be
1105          * notified when an accessible client asks for any of the properties
1106          * defined in the <code>AccessibleHyperlinkListener</code> interface.
1107          *
1108          * @param listener the listener that should no longer be notified when the receiver
1109          * is asked for <code>AccessibleHyperlinkListener</code> interface properties
1110          *
1111          * @exception IllegalArgumentException <ul>
1112          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1113          * </ul>
1114          * @exception SWTException <ul>
1115          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1116          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1117          * </ul>
1118          *
1119          * @see AccessibleHyperlinkListener
1120          * @see #addAccessibleHyperlinkListener
1121          *
1122          * @since 3.6
1123          */
1124         public void removeAccessibleHyperlinkListener(AccessibleHyperlinkListener listener) {
1125                 checkWidget();
1126                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
1127                 if (accessibleHyperlinkListeners != null) {
1128                         accessibleHyperlinkListeners.remove(listener);
1129                         if (accessibleHyperlinkListeners.isEmpty()) accessibleHyperlinkListeners = null;
1130                 }
1131         }
1132
1133         /**
1134          * Removes the listener from the collection of listeners that will be
1135          * notified when an accessible client asks for any of the properties
1136          * defined in the <code>AccessibleTableListener</code> interface.
1137          *
1138          * @param listener the listener that should no longer be notified when the receiver
1139          * is asked for <code>AccessibleTableListener</code> interface properties
1140          *
1141          * @exception IllegalArgumentException <ul>
1142          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1143          * </ul>
1144          * @exception SWTException <ul>
1145          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1146          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1147          * </ul>
1148          *
1149          * @see AccessibleTableListener
1150          * @see #addAccessibleTableListener
1151          *
1152          * @since 3.6
1153          */
1154         public void removeAccessibleTableListener(AccessibleTableListener listener) {
1155                 checkWidget();
1156                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
1157                 if (accessibleTableListeners != null) {
1158                         accessibleTableListeners.remove(listener);
1159                         if (accessibleTableListeners.isEmpty()) accessibleTableListeners = null;
1160                 }
1161         }
1162
1163         /**
1164          * Removes the listener from the collection of listeners that will be
1165          * notified when an accessible client asks for any of the properties
1166          * defined in the <code>AccessibleTableCellListener</code> interface.
1167          *
1168          * @param listener the listener that should no longer be notified when the receiver
1169          * is asked for <code>AccessibleTableCellListener</code> interface properties
1170          *
1171          * @exception IllegalArgumentException <ul>
1172          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1173          * </ul>
1174          * @exception SWTException <ul>
1175          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1176          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1177          * </ul>
1178          *
1179          * @see AccessibleTableCellListener
1180          * @see #addAccessibleTableCellListener
1181          *
1182          * @since 3.6
1183          */
1184         public void removeAccessibleTableCellListener(AccessibleTableCellListener listener) {
1185                 checkWidget();
1186                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
1187                 if (accessibleTableCellListeners != null) {
1188                         accessibleTableCellListeners.remove(listener);
1189                         if (accessibleTableCellListeners.isEmpty()) accessibleTableCellListeners = null;
1190                 }
1191         }
1192
1193         /**
1194          * Removes the listener from the collection of listeners that will be
1195          * notified when an accessible client asks for any of the properties
1196          * defined in the <code>AccessibleValueListener</code> interface.
1197          *
1198          * @param listener the listener that should no longer be notified when the receiver
1199          * is asked for <code>AccessibleValueListener</code> interface properties
1200          *
1201          * @exception IllegalArgumentException <ul>
1202          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1203          * </ul>
1204          * @exception SWTException <ul>
1205          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1206          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1207          * </ul>
1208          *
1209          * @see AccessibleValueListener
1210          * @see #addAccessibleValueListener
1211          *
1212          * @since 3.6
1213          */
1214         public void removeAccessibleValueListener(AccessibleValueListener listener) {
1215                 checkWidget();
1216                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
1217                 if (accessibleValueListeners != null) {
1218                         accessibleValueListeners.remove(listener);
1219                         if (accessibleValueListeners.isEmpty()) accessibleValueListeners = null;
1220                 }
1221         }
1222
1223         /**
1224          * Removes the listener from the collection of listeners that will be
1225          * notified when an accessible client asks for any of the properties
1226          * defined in the <code>AccessibleAttributeListener</code> interface.
1227          *
1228          * @param listener the listener that should no longer be notified when the receiver
1229          * is asked for <code>AccessibleAttributeListener</code> interface properties
1230          *
1231          * @exception IllegalArgumentException <ul>
1232          *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1233          * </ul>
1234          * @exception SWTException <ul>
1235          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1236          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1237          * </ul>
1238          *
1239          * @see AccessibleAttributeListener
1240          * @see #addAccessibleAttributeListener
1241          *
1242          * @since 3.6
1243          */
1244         public void removeAccessibleAttributeListener(AccessibleAttributeListener listener) {
1245                 checkWidget();
1246                 if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
1247                 if (accessibleAttributeListeners != null) {
1248                         accessibleAttributeListeners.remove(listener);
1249                         if (accessibleAttributeListeners.isEmpty()) accessibleAttributeListeners = null;
1250                 }
1251         }
1252
1253         /**
1254          * Removes the relation with the specified type and target
1255          * from the receiver's set of relations.
1256          *
1257          * @param type an <code>ACC</code> constant beginning with RELATION_* indicating the type of relation
1258          * @param target the accessible that is the target for this relation
1259          * @exception IllegalArgumentException ERROR_NULL_ARGUMENT - if the Accessible target is null
1260          * @since 3.6
1261          */
1262         public void removeRelation(int type, Accessible target) {
1263                 checkWidget();
1264                 if (target == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
1265                 Relation relation = relations[type];
1266                 if (relation != null) {
1267                         relation.removeTarget(target);
1268                         if (!relation.hasTargets()) {
1269                                 relations[type].Release();
1270                                 relations[type] = null;
1271                         }
1272                 }
1273         }
1274
1275         /**
1276          * Sends a message with event-specific data to accessible clients
1277          * indicating that something has changed within a custom control.
1278          *
1279          * @param event an <code>ACC</code> constant beginning with EVENT_* indicating the message to send
1280          * @param eventData an object containing event-specific data, or null if there is no event-specific data
1281          * (eventData is specified in the documentation for individual ACC.EVENT_* constants)
1282          *
1283          * @exception SWTException <ul>
1284          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1285          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1286          * </ul>
1287          *
1288          * @see ACC#EVENT_ACTION_CHANGED
1289          * @see ACC#EVENT_ATTRIBUTE_CHANGED
1290          * @see ACC#EVENT_DESCRIPTION_CHANGED
1291          * @see ACC#EVENT_DOCUMENT_LOAD_COMPLETE
1292          * @see ACC#EVENT_DOCUMENT_LOAD_STOPPED
1293          * @see ACC#EVENT_DOCUMENT_RELOAD
1294          * @see ACC#EVENT_HYPERLINK_ACTIVATED
1295          * @see ACC#EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED
1296          * @see ACC#EVENT_HYPERLINK_END_INDEX_CHANGED
1297          * @see ACC#EVENT_HYPERLINK_SELECTED_LINK_CHANGED
1298          * @see ACC#EVENT_HYPERLINK_START_INDEX_CHANGED
1299          * @see ACC#EVENT_HYPERTEXT_LINK_COUNT_CHANGED
1300          * @see ACC#EVENT_HYPERTEXT_LINK_SELECTED
1301          * @see ACC#EVENT_LOCATION_CHANGED
1302          * @see ACC#EVENT_NAME_CHANGED
1303          * @see ACC#EVENT_PAGE_CHANGED
1304          * @see ACC#EVENT_SECTION_CHANGED
1305          * @see ACC#EVENT_SELECTION_CHANGED
1306          * @see ACC#EVENT_STATE_CHANGED
1307          * @see ACC#EVENT_TABLE_CAPTION_CHANGED
1308          * @see ACC#EVENT_TABLE_CHANGED
1309          * @see ACC#EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED
1310          * @see ACC#EVENT_TABLE_COLUMN_HEADER_CHANGED
1311          * @see ACC#EVENT_TABLE_ROW_DESCRIPTION_CHANGED
1312          * @see ACC#EVENT_TABLE_ROW_HEADER_CHANGED
1313          * @see ACC#EVENT_TABLE_SUMMARY_CHANGED
1314          * @see ACC#EVENT_TEXT_ATTRIBUTE_CHANGED
1315          * @see ACC#EVENT_TEXT_CARET_MOVED
1316          * @see ACC#EVENT_TEXT_CHANGED
1317          * @see ACC#EVENT_TEXT_COLUMN_CHANGED
1318          * @see ACC#EVENT_TEXT_SELECTION_CHANGED
1319          * @see ACC#EVENT_VALUE_CHANGED
1320          *
1321          * @since 3.6
1322          */
1323         public void sendEvent(int event, Object eventData) {
1324                 checkWidget();
1325                 if (!isATRunning ()) return;
1326                 if (!UseIA2) return;
1327                 if (DEBUG) print(this + ".NotifyWinEvent " + getEventString(event) + " hwnd=" + control.handle + " childID=" + eventChildID());
1328                 switch (event) {
1329                         case ACC.EVENT_TABLE_CHANGED: {
1330                                 if (!(eventData instanceof int[] && ((int[])eventData).length == TABLE_MODEL_CHANGE_SIZE)) break;
1331                                 tableChange = (int[])eventData;
1332                                 OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID());
1333                                 break;
1334                         }
1335                         case ACC.EVENT_TEXT_CHANGED: {
1336                                 if (!(eventData instanceof Object[] && ((Object[])eventData).length == TEXT_CHANGE_SIZE)) break;
1337                                 Object[] data = (Object[])eventData;
1338                                 int type = ((Integer)data[0]).intValue();
1339                                 switch (type) {
1340                                         case ACC.DELETE:
1341                                                 textDeleted = (Object[])eventData;
1342                                                 OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_REMOVED, control.handle, OS.OBJID_CLIENT, eventChildID());
1343                                                 break;
1344                                         case ACC.INSERT:
1345                                                 textInserted = (Object[])eventData;
1346                                                 OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_INSERTED, control.handle, OS.OBJID_CLIENT, eventChildID());
1347                                                 break;
1348                                 }
1349                                 break;
1350                         }
1351                         case ACC.EVENT_HYPERTEXT_LINK_SELECTED: {
1352                                 if (!(eventData instanceof Integer)) break;
1353         //                      int index = ((Integer)eventData).intValue();
1354                                 // TODO: IA2 currently does not use the index, however the plan is to use it in future
1355                                 OS.NotifyWinEvent (COM.IA2_EVENT_HYPERTEXT_LINK_SELECTED, control.handle, OS.OBJID_CLIENT, eventChildID());
1356                                 break;
1357                         }
1358                         case ACC.EVENT_VALUE_CHANGED:
1359                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1360                         case ACC.EVENT_STATE_CHANGED:
1361                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_STATECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1362                         case ACC.EVENT_SELECTION_CHANGED:
1363                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1364                         case ACC.EVENT_TEXT_SELECTION_CHANGED:
1365                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1366                         case ACC.EVENT_LOCATION_CHANGED:
1367                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1368                         case ACC.EVENT_NAME_CHANGED:
1369                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_NAMECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1370                         case ACC.EVENT_DESCRIPTION_CHANGED:
1371                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_DESCRIPTIONCHANGE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1372                         case ACC.EVENT_DOCUMENT_LOAD_COMPLETE:
1373                                 OS.NotifyWinEvent (COM.IA2_EVENT_DOCUMENT_LOAD_COMPLETE, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1374                         case ACC.EVENT_DOCUMENT_LOAD_STOPPED:
1375                                 OS.NotifyWinEvent (COM.IA2_EVENT_DOCUMENT_LOAD_STOPPED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1376                         case ACC.EVENT_DOCUMENT_RELOAD:
1377                                 OS.NotifyWinEvent (COM.IA2_EVENT_DOCUMENT_RELOAD, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1378                         case ACC.EVENT_PAGE_CHANGED:
1379                                 OS.NotifyWinEvent (COM.IA2_EVENT_PAGE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1380                         case ACC.EVENT_SECTION_CHANGED:
1381                                 OS.NotifyWinEvent (COM.IA2_EVENT_SECTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1382                         case ACC.EVENT_ACTION_CHANGED:
1383                                 OS.NotifyWinEvent (COM.IA2_EVENT_ACTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1384                         case ACC.EVENT_HYPERLINK_START_INDEX_CHANGED:
1385                                 OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_START_INDEX_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1386                         case ACC.EVENT_HYPERLINK_END_INDEX_CHANGED:
1387                                 OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_END_INDEX_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1388                         case ACC.EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED:
1389                                 OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1390                         case ACC.EVENT_HYPERLINK_SELECTED_LINK_CHANGED:
1391                                 OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1392                         case ACC.EVENT_HYPERLINK_ACTIVATED:
1393                                 OS.NotifyWinEvent (COM.IA2_EVENT_HYPERLINK_ACTIVATED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1394                         case ACC.EVENT_HYPERTEXT_LINK_COUNT_CHANGED:
1395                                 OS.NotifyWinEvent (COM.IA2_EVENT_HYPERTEXT_LINK_COUNT_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1396                         case ACC.EVENT_ATTRIBUTE_CHANGED:
1397                                 OS.NotifyWinEvent (COM.IA2_EVENT_ATTRIBUTE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1398                         case ACC.EVENT_TABLE_CAPTION_CHANGED:
1399                                 OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_CAPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1400                         case ACC.EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED:
1401                                 OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1402                         case ACC.EVENT_TABLE_COLUMN_HEADER_CHANGED:
1403                                 OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1404                         case ACC.EVENT_TABLE_ROW_DESCRIPTION_CHANGED:
1405                                 OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1406                         case ACC.EVENT_TABLE_ROW_HEADER_CHANGED:
1407                                 OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_ROW_HEADER_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1408                         case ACC.EVENT_TABLE_SUMMARY_CHANGED:
1409                                 OS.NotifyWinEvent (COM.IA2_EVENT_TABLE_SUMMARY_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1410                         case ACC.EVENT_TEXT_ATTRIBUTE_CHANGED:
1411                                 OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_ATTRIBUTE_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1412                         case ACC.EVENT_TEXT_CARET_MOVED:
1413                                 OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_CARET_MOVED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1414                         case ACC.EVENT_TEXT_COLUMN_CHANGED:
1415                                 OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_COLUMN_CHANGED, control.handle, OS.OBJID_CLIENT, eventChildID()); break;
1416                 }
1417         }
1418
1419         /**
1420          * Sends a message with event-specific data and a childID
1421          * to accessible clients, indicating that something has changed
1422          * within a custom control.
1423          *
1424          * NOTE: This API is intended for applications that are still using childIDs.
1425          * Moving forward, applications should use accessible objects instead of childIDs.
1426          *
1427          * @param event an <code>ACC</code> constant beginning with EVENT_* indicating the message to send
1428          * @param eventData an object containing event-specific data, or null if there is no event-specific data
1429          * (eventData is specified in the documentation for individual ACC.EVENT_* constants)
1430          * @param childID an identifier specifying a child of the control
1431          *
1432          * @exception SWTException <ul>
1433          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1434          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1435          * </ul>
1436          *
1437          * @see ACC#EVENT_DESCRIPTION_CHANGED
1438          * @see ACC#EVENT_LOCATION_CHANGED
1439          * @see ACC#EVENT_NAME_CHANGED
1440          * @see ACC#EVENT_SELECTION_CHANGED
1441          * @see ACC#EVENT_STATE_CHANGED
1442          * @see ACC#EVENT_TEXT_SELECTION_CHANGED
1443          * @see ACC#EVENT_VALUE_CHANGED
1444          *
1445          * @since 3.8
1446          */
1447         public void sendEvent(int event, Object eventData, int childID) {
1448                 checkWidget();
1449                 if (!isATRunning ()) return;
1450                 if (!UseIA2) return;
1451                 int osChildID = childID == ACC.CHILDID_SELF ? eventChildID() : childIDToOs(childID);
1452                 if (DEBUG) print(this + ".NotifyWinEvent " + getEventString(event) + " hwnd=" + control.handle + " childID=" + osChildID);
1453                 switch (event) {
1454                         case ACC.EVENT_STATE_CHANGED:
1455                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_STATECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
1456                         case ACC.EVENT_NAME_CHANGED:
1457                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_NAMECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
1458                         case ACC.EVENT_VALUE_CHANGED:
1459                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
1460                         case ACC.EVENT_LOCATION_CHANGED:
1461                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
1462                         case ACC.EVENT_SELECTION_CHANGED:
1463                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, osChildID); break;
1464                         case ACC.EVENT_TEXT_SELECTION_CHANGED:
1465                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, osChildID); break;
1466                         case ACC.EVENT_DESCRIPTION_CHANGED:
1467                                 OS.NotifyWinEvent (COM.EVENT_OBJECT_DESCRIPTIONCHANGE, control.handle, OS.OBJID_CLIENT, osChildID); break;
1468                 }
1469         }
1470
1471
1472         /**
1473          * Sends a message to accessible clients that the child selection
1474          * within a custom container control has changed.
1475          *
1476          * @exception SWTException <ul>
1477          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1478          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1479          * </ul>
1480          *
1481          * @since 3.0
1482          */
1483         public void selectionChanged () {
1484                 checkWidget();
1485                 if (!isATRunning ()) return;
1486                 if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_SELECTIONWITHIN hwnd=" + control.handle + " childID=" + eventChildID());
1487                 OS.NotifyWinEvent (COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, OS.OBJID_CLIENT, eventChildID());
1488         }
1489
1490         /**
1491          * Sends a message to accessible clients indicating that the focus
1492          * has changed within a custom control.
1493          *
1494          * @param childID an identifier specifying a child of the control
1495          *
1496          * @exception SWTException <ul>
1497          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1498          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1499          * </ul>
1500          */
1501         public void setFocus(int childID) {
1502                 checkWidget();
1503                 if (!isATRunning ()) return;
1504                 int osChildID = childID == ACC.CHILDID_SELF ? eventChildID() : childIDToOs(childID);
1505                 if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_FOCUS hwnd=" + control.handle + " childID=" + osChildID);
1506                 OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, control.handle, OS.OBJID_CLIENT, osChildID);
1507         }
1508
1509         /**
1510          * Sends a message to accessible clients that the text
1511          * caret has moved within a custom control.
1512          *
1513          * @param index the new caret index within the control
1514          *
1515          * @exception SWTException <ul>
1516          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1517          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1518          * </ul>
1519          *
1520          * @since 3.0
1521          */
1522         public void textCaretMoved (int index) {
1523                 checkWidget();
1524                 if (timer == null) {
1525                         timer = new Runnable() {
1526                                 @Override
1527                                 public void run() {
1528                                         if (!isATRunning ()) return;
1529                                         if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_LOCATIONCHANGE hwnd=" + control.handle + " childID=" + eventChildID());
1530                                         OS.NotifyWinEvent (COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, OS.OBJID_CARET, eventChildID());
1531                                         if (!UseIA2) return;
1532                                         if (DEBUG) print(this + ".NotifyWinEvent IA2_EVENT_TEXT_CARET_MOVED hwnd=" + control.handle + " childID=" + eventChildID());
1533                                         OS.NotifyWinEvent (COM.IA2_EVENT_TEXT_CARET_MOVED, control.handle, OS.OBJID_CLIENT, eventChildID());
1534                                 }
1535                         };
1536                 }
1537                 control.getDisplay ().timerExec(SCROLL_RATE, timer);
1538         }
1539
1540         /**
1541          * Sends a message to accessible clients that the text
1542          * within a custom control has changed.
1543          *
1544          * @param type the type of change, one of <code>ACC.TEXT_INSERT</code>
1545          * or <code>ACC.TEXT_DELETE</code>
1546          * @param startIndex the text index within the control where the insertion or deletion begins
1547          * @param length the non-negative length in characters of the insertion or deletion
1548          *
1549          * @exception SWTException <ul>
1550          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1551          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1552          * </ul>
1553          *
1554          * @see ACC#TEXT_INSERT
1555          * @see ACC#TEXT_DELETE
1556          *
1557          * @since 3.0
1558          */
1559         public void textChanged (int type, int startIndex, int length) {
1560                 checkWidget();
1561                 if (!isATRunning ()) return;
1562                 AccessibleTextEvent event = new AccessibleTextEvent(this);
1563                 event.start = startIndex;
1564                 event.end = startIndex + length;
1565                 event.count = 0;
1566                 event.type = ACC.TEXT_BOUNDARY_ALL;
1567                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
1568                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
1569                         listener.getText(event);
1570                 }
1571                 if (event.result != null) {
1572                         Object[] eventData = new Object[] {
1573                                         Integer.valueOf(type),
1574                                         Integer.valueOf(startIndex),
1575                                         Integer.valueOf(startIndex + length),
1576                                         event.result};
1577                         sendEvent(ACC.EVENT_TEXT_CHANGED, eventData);
1578                         return;
1579                 }
1580                 if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_VALUECHANGE hwnd=" + control.handle + " childID=" + eventChildID());
1581                 OS.NotifyWinEvent (COM.EVENT_OBJECT_VALUECHANGE, control.handle, OS.OBJID_CLIENT, eventChildID());
1582         }
1583
1584         /**
1585          * Sends a message to accessible clients that the text
1586          * selection has changed within a custom control.
1587          *
1588          * @exception SWTException <ul>
1589          *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
1590          *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
1591          * </ul>
1592          *
1593          * @since 3.0
1594          */
1595         public void textSelectionChanged () {
1596                 checkWidget();
1597                 if (!isATRunning ()) return;
1598                 if (DEBUG) print(this + ".NotifyWinEvent EVENT_OBJECT_TEXTSELECTIONCHANGED hwnd=" + control.handle + " childID=" + eventChildID());
1599                 OS.NotifyWinEvent (COM.EVENT_OBJECT_TEXTSELECTIONCHANGED, control.handle, OS.OBJID_CLIENT, eventChildID());
1600         }
1601
1602         /* QueryInterface([in] iid, [out] ppvObject)
1603          * Ownership of ppvObject transfers from callee to caller so reference count on ppvObject
1604          * must be incremented before returning.  Caller is responsible for releasing ppvObject.
1605          */
1606         int QueryInterface(long iid, long ppvObject) {
1607                 if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
1608                 OS.MoveMemory(ppvObject, new long[] { 0 }, C.PTR_SIZEOF);
1609                 GUID guid = new GUID();
1610                 COM.MoveMemory(guid, iid, GUID.sizeof);
1611
1612                 if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) || COM.IsEqualGUID(guid, COM.IIDIAccessible)) {
1613                         if (objIAccessible == null) createIAccessible();
1614                         OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF);
1615                         AddRef();
1616                         if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIAccessible.getAddress() + hresult(COM.S_OK));
1617                         return COM.S_OK;
1618                 }
1619
1620                 if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) {
1621                         if (objIEnumVARIANT == null) createIEnumVARIANT();
1622                         OS.MoveMemory(ppvObject, new long[] { objIEnumVARIANT.getAddress() }, C.PTR_SIZEOF);
1623                         AddRef();
1624                         enumIndex = 0;
1625                         if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIEnumVARIANT.getAddress() + hresult(COM.S_OK));
1626                         return COM.S_OK;
1627                 }
1628
1629                 if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) {
1630                         if (!UseIA2) return COM.E_NOINTERFACE;
1631                         if (accessibleActionListenersSize() > 0 || accessibleAttributeListenersSize() > 0 ||
1632                                 accessibleHyperlinkListenersSize() > 0 || accessibleTableListenersSize() > 0 ||
1633                                 accessibleTableCellListenersSize() > 0 || accessibleTextExtendedListenersSize() > 0 ||
1634                                 accessibleValueListenersSize() > 0 || accessibleControlListenersSize() > 0 || getRelationCount() > 0
1635                                 || (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) || (control instanceof Composite)) {
1636                                 if (objIServiceProvider == null) createIServiceProvider();
1637                                 OS.MoveMemory(ppvObject, new long[] { objIServiceProvider.getAddress() }, C.PTR_SIZEOF);
1638                                 AddRef();
1639                                 if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning " + objIServiceProvider.getAddress() + hresult(COM.S_OK));
1640                                 return COM.S_OK;
1641                         }
1642                         if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE));
1643                         return COM.E_NOINTERFACE;
1644                 }
1645
1646                 int code = queryAccessible2Interfaces(guid, ppvObject);
1647                 if (code != COM.S_FALSE) {
1648                         if (DEBUG) print(this + ".QueryInterface guid=" + guidString(guid) + " returning" + hresult(code));
1649                         return code;
1650                 }
1651
1652                 if (iaccessible != null) {
1653                         /* Forward any other GUIDs to the OS proxy. */
1654                         long[] ppv = new long[1];
1655                         code = iaccessible.QueryInterface(guid, ppv);
1656                         OS.MoveMemory(ppvObject, ppv, C.PTR_SIZEOF);
1657                         if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning super" + hresult(code));
1658                         return code;
1659                 }
1660
1661                 if (DEBUG) if (interesting(guid)) print("QueryInterface guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE));
1662                 return COM.E_NOINTERFACE;
1663         }
1664
1665         int accessibleListenersSize() {
1666                 return accessibleListeners == null ? 0 : accessibleListeners.size();
1667         }
1668
1669         int accessibleControlListenersSize() {
1670                 return accessibleControlListeners == null ? 0 : accessibleControlListeners.size();
1671         }
1672
1673         int accessibleValueListenersSize() {
1674                 return accessibleValueListeners == null ? 0 : accessibleValueListeners.size();
1675         }
1676
1677         int accessibleTextExtendedListenersSize() {
1678                 return accessibleTextExtendedListeners == null ? 0 : accessibleTextExtendedListeners.size();
1679         }
1680
1681         int accessibleTextListenersSize() {
1682                 return accessibleTextListeners == null ? 0 : accessibleTextListeners.size();
1683         }
1684
1685         int accessibleTableCellListenersSize() {
1686                 return accessibleTableCellListeners == null ? 0 : accessibleTableCellListeners.size();
1687         }
1688
1689         int accessibleTableListenersSize() {
1690                 return accessibleTableListeners == null ? 0 : accessibleTableListeners.size();
1691         }
1692
1693         int accessibleHyperlinkListenersSize() {
1694                 return accessibleHyperlinkListeners == null ? 0 : accessibleHyperlinkListeners.size();
1695         }
1696
1697         int accessibleEditableTextListenersSize() {
1698                 return accessibleEditableTextListeners == null ? 0 : accessibleEditableTextListeners.size();
1699         }
1700
1701         int accessibleAttributeListenersSize() {
1702                 return accessibleAttributeListeners == null ? 0 : accessibleAttributeListeners.size();
1703         }
1704
1705         int accessibleActionListenersSize() {
1706                 return accessibleActionListeners == null ? 0 : accessibleActionListeners.size();
1707         }
1708
1709         int AddRef() {
1710                 refCount++;
1711                 return refCount;
1712         }
1713
1714         int Release() {
1715                 refCount--;
1716
1717                 if (refCount == 0) {
1718                         if (objIAccessible != null)
1719                                 objIAccessible.dispose();
1720                         objIAccessible = null;
1721
1722                         if (objIEnumVARIANT != null)
1723                                 objIEnumVARIANT.dispose();
1724                         objIEnumVARIANT = null;
1725
1726                         if (objIServiceProvider != null)
1727                                 objIServiceProvider.dispose();
1728                         objIServiceProvider = null;
1729
1730                         if (objIAccessibleApplication != null)
1731                                 objIAccessibleApplication.dispose();
1732                         objIAccessibleApplication = null;
1733
1734                         // The following lines are intentionally commented. We are not providing IAccessibleComponent at this time.
1735 //                      if (objIAccessibleComponent != null)
1736 //                              objIAccessibleComponent.dispose();
1737 //                      objIAccessibleComponent = null;
1738
1739                         if (objIAccessibleEditableText != null)
1740                                 objIAccessibleEditableText.dispose();
1741                         objIAccessibleEditableText = null;
1742
1743                         if (objIAccessibleHyperlink != null)
1744                                 objIAccessibleHyperlink.dispose();
1745                         objIAccessibleHyperlink = null;
1746
1747                         if (objIAccessibleHypertext != null)
1748                                 objIAccessibleHypertext.dispose();
1749                         objIAccessibleHypertext = null;
1750
1751                         // The following lines are intentionally commented. We are not providing IAccessibleImage at this time.
1752 //                      if (objIAccessibleImage != null)
1753 //                              objIAccessibleImage.dispose();
1754 //                      objIAccessibleImage = null;
1755
1756                         if (objIAccessibleTable2 != null)
1757                                 objIAccessibleTable2.dispose();
1758                         objIAccessibleTable2 = null;
1759
1760                         if (objIAccessibleTableCell != null)
1761                                 objIAccessibleTableCell.dispose();
1762                         objIAccessibleTableCell = null;
1763
1764                         if (objIAccessibleValue != null)
1765                                 objIAccessibleValue.dispose();
1766                         objIAccessibleValue = null;
1767
1768                         for (int i = 0; i < relations.length; i++) {
1769                                 if (relations[i] != null) relations[i].Release();
1770                         }
1771                         // TODO: also remove all relations for which 'this' is a target??
1772                 }
1773                 return refCount;
1774         }
1775
1776         /* QueryService([in] guidService, [in] riid, [out] ppvObject) */
1777         int QueryService(long guidService, long riid, long ppvObject) {
1778                 OS.MoveMemory(ppvObject, new long[] { 0 }, C.PTR_SIZEOF);
1779                 GUID service = new GUID();
1780                 COM.MoveMemory(service, guidService, GUID.sizeof);
1781                 GUID guid = new GUID();
1782                 COM.MoveMemory(guid, riid, GUID.sizeof);
1783
1784                 if (COM.IsEqualGUID(service, COM.IIDIAccessible)) {
1785                         if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDispatch) || COM.IsEqualGUID(guid, COM.IIDIAccessible)) {
1786                                 if (objIAccessible == null) createIAccessible();
1787                                 if (DEBUG) print(this + ".QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning " + objIAccessible.getAddress() + hresult(COM.S_OK));
1788                                 OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF);
1789                                 AddRef();
1790                                 return COM.S_OK;
1791                         }
1792                         int code = queryAccessible2Interfaces(guid, ppvObject);
1793                         if (code != COM.S_FALSE) {
1794                                 if (DEBUG) print(this + ".QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(code));
1795                                 return code;
1796                         }
1797                 }
1798
1799                 if (COM.IsEqualGUID(service, COM.IIDIAccessible2)) {
1800                         int code = queryAccessible2Interfaces(guid, ppvObject);
1801                         if (code != COM.S_FALSE) {
1802                                 if (DEBUG) print(this + ".*QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(code));
1803                                 return code;
1804                         }
1805                 }
1806
1807                 if (iaccessible != null) {
1808                         /* Forward any other GUIDs to the OS proxy. */
1809                         long [] ppv = new long [1];
1810                         int code = iaccessible.QueryInterface(COM.IIDIServiceProvider, ppv);
1811                         if (code == COM.S_OK) {
1812                                 IServiceProvider iserviceProvider = new IServiceProvider(ppv[0]);
1813                                 long [] ppvx = new long [1];
1814                                 code = iserviceProvider.QueryService(service, guid, ppvx);
1815                                 OS.MoveMemory(ppvObject, ppvx, C.PTR_SIZEOF);
1816                                 if (DEBUG) if (interesting(service) && interesting(guid)) print("QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning super" + hresult(code));
1817                                 return code;
1818                         }
1819                 }
1820
1821                 if (DEBUG) if (interesting(service) && interesting(guid)) print("QueryService service=" + guidString(service) + " guid=" + guidString(guid) + " returning" + hresult(COM.E_NOINTERFACE));
1822                 return COM.E_NOINTERFACE;
1823         }
1824
1825         int queryAccessible2Interfaces(GUID guid, long ppvObject) {
1826                 if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
1827                 if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) {
1828                         if (accessibleActionListenersSize() > 0 || accessibleAttributeListenersSize() > 0 ||
1829                                         accessibleHyperlinkListenersSize() > 0 || accessibleTableListenersSize() > 0 ||
1830                                         accessibleTableCellListenersSize() > 0 || accessibleTextExtendedListenersSize() > 0 ||
1831                                         accessibleValueListenersSize() > 0 || accessibleControlListenersSize() > 0 || getRelationCount() > 0
1832                                         || (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) || (control instanceof Composite)) {
1833                                 // NOTE: IAccessible2 vtable is shared with IAccessible
1834                                 if (objIAccessible == null) createIAccessible();
1835                                 OS.MoveMemory(ppvObject, new long[] { objIAccessible.getAddress() }, C.PTR_SIZEOF);
1836                                 AddRef();
1837                                 return COM.S_OK;
1838                         }
1839                         return COM.E_NOINTERFACE;
1840                 }
1841
1842                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) {
1843                         if (accessibleActionListenersSize() > 0) {
1844                                 // NOTE: IAccessibleAction vtable is shared with IAccessibleHyperlink
1845                                 if (objIAccessibleHyperlink == null) createIAccessibleHyperlink();
1846                                 OS.MoveMemory(ppvObject, new long[] { objIAccessibleHyperlink.getAddress() }, C.PTR_SIZEOF);
1847                                 AddRef();
1848                                 return COM.S_OK;
1849                         }
1850                         return COM.E_NOINTERFACE;
1851                 }
1852
1853                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) {
1854                         if (objIAccessibleApplication == null) createIAccessibleApplication();
1855                         OS.MoveMemory(ppvObject, new long[] { objIAccessibleApplication.getAddress() }, C.PTR_SIZEOF);
1856                         AddRef();
1857                         return COM.S_OK;
1858                 }
1859
1860                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) {
1861                         // The following lines are intentionally commented. We are not supporting IAccessibleComponent at this time.
1862 //                      if (accessibleControlListenersSize() > 0) { // TO DO: can we reduce the scope of this somehow?
1863 //                              if (objIAccessibleComponent == null) createIAccessibleComponent();
1864 //                              COM.MoveMemory(ppvObject, new long[] { objIAccessibleComponent.getAddress() }, OS.PTR_SIZEOF);
1865 //                              AddRef();
1866 //                              return COM.S_OK;
1867 //                      }
1868                         return COM.E_NOINTERFACE;
1869                 }
1870
1871                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) {
1872                         if (accessibleEditableTextListenersSize() > 0) {
1873                                 if (objIAccessibleEditableText == null) createIAccessibleEditableText();
1874                                 OS.MoveMemory(ppvObject, new long[] { objIAccessibleEditableText.getAddress() }, C.PTR_SIZEOF);
1875                                 AddRef();
1876                                 return COM.S_OK;
1877                         }
1878                         return COM.E_NOINTERFACE;
1879                 }
1880
1881                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) {
1882                         if (accessibleHyperlinkListenersSize() > 0) {
1883                                 if (objIAccessibleHyperlink == null) createIAccessibleHyperlink();
1884                                 OS.MoveMemory(ppvObject, new long[] { objIAccessibleHyperlink.getAddress() }, C.PTR_SIZEOF);
1885                                 AddRef();
1886                                 return COM.S_OK;
1887                         }
1888                         return COM.E_NOINTERFACE;
1889                 }
1890
1891                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) {
1892                         if (accessibleTextExtendedListenersSize() > 0) {
1893                                 if (objIAccessibleHypertext == null) createIAccessibleHypertext();
1894                                 OS.MoveMemory(ppvObject, new long[] { objIAccessibleHypertext.getAddress() }, C.PTR_SIZEOF);
1895                                 AddRef();
1896                                 return COM.S_OK;
1897                         }
1898                         return COM.E_NOINTERFACE;
1899                 }
1900
1901                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) {
1902                         // The following lines are intentionally commented. We are not supporting IAccessibleImage at this time.
1903 //                      if (getRole() == ACC.ROLE_GRAPHIC && (accessibleAccessibleListenersSize() > 0 || accessibleControlListenersSize() > 0)) {
1904 //                              if (objIAccessibleImage == null) createIAccessibleImage();
1905 //                              COM.MoveMemory(ppvObject, new long[] { objIAccessibleImage.getAddress() }, OS.PTR_SIZEOF);
1906 //                              AddRef();
1907 //                              return COM.S_OK;
1908 //                      }
1909                         return COM.E_NOINTERFACE;
1910                 }
1911
1912                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) {
1913                         // We are not supporting IAccessibleTable at this time.
1914                         return COM.E_NOINTERFACE;
1915                 }
1916
1917                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) {
1918                         if (accessibleTableListenersSize() > 0) {
1919                                 if (objIAccessibleTable2 == null) createIAccessibleTable2();
1920                                 OS.MoveMemory(ppvObject, new long[] { objIAccessibleTable2.getAddress() }, C.PTR_SIZEOF);
1921                                 AddRef();
1922                                 return COM.S_OK;
1923                         }
1924                         return COM.E_NOINTERFACE;
1925                 }
1926
1927                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) {
1928                         if (accessibleTableCellListenersSize() > 0) {
1929                                 if (objIAccessibleTableCell == null) createIAccessibleTableCell();
1930                                 OS.MoveMemory(ppvObject, new long[] { objIAccessibleTableCell.getAddress() }, C.PTR_SIZEOF);
1931                                 AddRef();
1932                                 return COM.S_OK;
1933                         }
1934                         return COM.E_NOINTERFACE;
1935                 }
1936
1937                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) {
1938                         if (accessibleTextExtendedListenersSize() > 0 || accessibleAttributeListenersSize() > 0) {
1939                                 // NOTE: IAccessibleText vtable is shared with IAccessibleHypertext
1940                                 if (objIAccessibleHypertext == null) createIAccessibleHypertext();
1941                                 OS.MoveMemory(ppvObject, new long[] { objIAccessibleHypertext.getAddress() }, C.PTR_SIZEOF);
1942                                 AddRef();
1943                                 return COM.S_OK;
1944                         }
1945                         return COM.E_NOINTERFACE;
1946                 }
1947
1948                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) {
1949                         if (accessibleValueListenersSize() > 0) {
1950                                 if (objIAccessibleValue == null) createIAccessibleValue();
1951                                 OS.MoveMemory(ppvObject, new long[] { objIAccessibleValue.getAddress() }, C.PTR_SIZEOF);
1952                                 AddRef();
1953                                 return COM.S_OK;
1954                         }
1955                         return COM.E_NOINTERFACE;
1956                 }
1957
1958                 return COM.S_FALSE;
1959         }
1960
1961         /* IAccessible::accDoDefaultAction([in] varChild) */
1962         int accDoDefaultAction(long varChild) {
1963                 if (DEBUG) print(this + ".IAccessible::accDoDefaultAction");
1964                 if (accessibleActionListenersSize() > 0) {
1965                         VARIANT v = getVARIANT(varChild);
1966                         if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
1967                         if (v.lVal == COM.CHILDID_SELF) return doAction(0);
1968                 }
1969                 int code = COM.DISP_E_MEMBERNOTFOUND;
1970                 if (iaccessible != null) {
1971                         /* If there were no action listeners, forward to the proxy. */
1972                         code = iaccessible.accDoDefaultAction(varChild);
1973                         if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
1974                 }
1975                 return code;
1976         }
1977
1978         /* IAccessible::accHitTest([in] xLeft, [in] yTop, [out] pvarChild) */
1979         int accHitTest(int xLeft, int yTop, long pvarChild) {
1980                 int osChild = ACC.CHILDID_NONE;
1981                 long osChildObject = 0;
1982                 if (iaccessible != null) {
1983                         /* Get the default child at point (left, top) from the OS. */
1984                         int code = iaccessible.accHitTest(xLeft, yTop, pvarChild);
1985                         if (code == COM.S_OK) {
1986                                 VARIANT v = getVARIANT(pvarChild);
1987                                 if (v.vt == COM.VT_I4) osChild = v.lVal;
1988                                 else if (v.vt == COM.VT_DISPATCH) {
1989                                         osChildObject = v.lVal; // TODO: don't use struct. lVal is an int.
1990                                         if (DEBUG) print(this + ".IAccessible::accHitTest() super returned VT_DISPATCH");
1991                                 }
1992                         }
1993                         if (accessibleControlListenersSize() == 0) {
1994                                 if (DEBUG) print(this + ".IAccessible::accHitTest returning childID=" + osChild + " from super" + hresult(code));
1995                                 return code;
1996                         }
1997                 }
1998
1999                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2000                 event.childID = osChild == ACC.CHILDID_NONE ? ACC.CHILDID_NONE : osToChildID(osChild);
2001                 // TODO: event.accessible = Accessible for osChildObject;
2002                 event.x = xLeft;
2003                 event.y = yTop;
2004                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2005                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2006                         listener.getChildAtPoint(event);
2007                 }
2008                 Accessible accessible = event.accessible;
2009                 if (accessible != null) {
2010                         if (DEBUG) print(this + ".IAccessible::accHitTest returning " + accessible.getAddress() + hresult(COM.S_OK));
2011                         accessible.AddRef();
2012                         setPtrVARIANT(pvarChild, COM.VT_DISPATCH, accessible.getAddress());
2013                         return COM.S_OK;
2014                 }
2015                 int childID = event.childID;
2016                 if (childID == ACC.CHILDID_NONE) {
2017                         if (osChildObject != 0) {
2018                                 if (DEBUG) print(this + ".IAccessible::accHitTest returning osChildObject " + osChildObject + " from super" + hresult(COM.S_OK));
2019                                 return COM.S_OK;
2020                         }
2021                         if (DEBUG) print(this + ".IAccessible::accHitTest returning VT_EMPTY" + hresult(COM.S_FALSE));
2022                         setIntVARIANT(pvarChild, COM.VT_EMPTY, 0);
2023                         return COM.S_FALSE;
2024                 }
2025                 if (DEBUG) print(this + ".IAccessible::accHitTest returning " + childIDToOs(childID) + hresult(COM.S_OK));
2026                 setIntVARIANT(pvarChild, COM.VT_I4, childIDToOs(childID));
2027                 return COM.S_OK;
2028         }
2029
2030         /* IAccessible::accLocation([out] pxLeft, [out] pyTop, [out] pcxWidth, [out] pcyHeight, [in] varChild) */
2031         int accLocation(long pxLeft, long pyTop, long pcxWidth, long pcyHeight, long varChild) {
2032                 VARIANT v = getVARIANT(varChild);
2033                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2034                 int osLeft = 0, osTop = 0, osWidth = 0, osHeight = 0;
2035                 if (iaccessible != null) {
2036                         /* Get the default location from the OS. */
2037                         int code = iaccessible.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varChild);
2038                         if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
2039                         if (accessibleControlListenersSize() == 0) {
2040                                 if (DEBUG) print(this + ".IAccessible::accLocation returning from super" + hresult(code));
2041                                 return code;
2042                         }
2043                         if (code == COM.S_OK) {
2044                                 int[] pLeft = new int[1], pTop = new int[1], pWidth = new int[1], pHeight = new int[1];
2045                                 OS.MoveMemory(pLeft, pxLeft, 4);
2046                                 OS.MoveMemory(pTop, pyTop, 4);
2047                                 OS.MoveMemory(pWidth, pcxWidth, 4);
2048                                 OS.MoveMemory(pHeight, pcyHeight, 4);
2049                                 osLeft = pLeft[0]; osTop = pTop[0]; osWidth = pWidth[0]; osHeight = pHeight[0];
2050                         }
2051                 }
2052
2053                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2054                 event.childID = osToChildID(v.lVal);
2055                 event.x = osLeft;
2056                 event.y = osTop;
2057                 event.width = osWidth;
2058                 event.height = osHeight;
2059                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2060                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2061                         listener.getLocation(event);
2062                 }
2063                 if (DEBUG) print(this + ".IAccessible::accLocation(" + v.lVal + ") returning x=" + event.x + " y=" + event.y + "w=" + event.width + "h=" + event.height + hresult(COM.S_OK));
2064                 OS.MoveMemory(pxLeft, new int[] { event.x }, 4);
2065                 OS.MoveMemory(pyTop, new int[] { event.y }, 4);
2066                 OS.MoveMemory(pcxWidth, new int[] { event.width }, 4);
2067                 OS.MoveMemory(pcyHeight, new int[] { event.height }, 4);
2068                 return COM.S_OK;
2069         }
2070
2071         /* IAccessible::accNavigate([in] navDir, [in] varStart, [out] pvarEndUpAt) */
2072         int accNavigate(int navDir, long varStart, long pvarEndUpAt) {
2073                 if (DEBUG) print(this + ".IAccessible::accNavigate");
2074                 /* MSAA: "The accNavigate method is deprecated and should not be used." */
2075                 int code = COM.DISP_E_MEMBERNOTFOUND;
2076                 if (iaccessible != null) {
2077                         /* Since many of the native controls still handle accNavigate,
2078                          * we will continue to send this through to the proxy. */
2079                         code = iaccessible.accNavigate(navDir, varStart, pvarEndUpAt);
2080                         if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
2081                 }
2082                 return code;
2083         }
2084
2085         // TODO: Consider supporting this in future.
2086         /* IAccessible::accSelect([in] flagsSelect, [in] varChild) */
2087         int accSelect(int flagsSelect, long varChild) {
2088                 int code = COM.DISP_E_MEMBERNOTFOUND;
2089                 if (iaccessible != null) {
2090                         /* Currently, we don't expose this as API. Forward to the proxy. */
2091                         code = iaccessible.accSelect(flagsSelect, varChild);
2092                         if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
2093                 }
2094                 if (DEBUG) print(this + ".IAccessible::accSelect(" + flagsSelect + ") returning" + hresult(code));
2095                 return code;
2096         }
2097
2098         /* IAccessible::get_accChild([in] varChild, [out] ppdispChild)
2099          * Ownership of ppdispChild transfers from callee to caller so reference count on ppdispChild
2100          * must be incremented before returning.  The caller is responsible for releasing ppdispChild.
2101          */
2102         int get_accChild(long varChild, long ppdispChild) {
2103                 VARIANT v = getVARIANT(varChild);
2104                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2105                 if (v.lVal == COM.CHILDID_SELF) {
2106                         if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning " + getAddress() + hresult(COM.S_OK));
2107                         AddRef();
2108                         OS.MoveMemory(ppdispChild, new long[] { getAddress() }, C.PTR_SIZEOF);
2109                         return COM.S_OK;
2110                 }
2111                 final int childID = osToChildID(v.lVal);
2112                 int code = COM.S_FALSE;
2113                 Accessible osAccessible = null;
2114                 if (iaccessible != null) {
2115                         /* Get the default child from the OS. */
2116                         code = iaccessible.get_accChild(varChild, ppdispChild);
2117                         if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
2118                         if (code == COM.S_OK && control instanceof ToolBar) {
2119                                 ToolBar toolBar = (ToolBar) control;
2120                                 final ToolItem item = toolBar.getItem(childID);
2121                                 if (item != null && (item.getStyle() & SWT.DROP_DOWN) != 0) {
2122                                         long[] addr = new long[1];
2123                                         OS.MoveMemory(addr, ppdispChild, C.PTR_SIZEOF);
2124                                         boolean found = false;
2125                                         for (int i = 0; i < children.size(); i++) {
2126                                                 Accessible accChild = children.get(i);
2127                                                 if (accChild.item == item) {
2128                                                         /*
2129                                                          * MSAA uses a new accessible for the child
2130                                                          * so we dispose the old and use the new.
2131                                                          */
2132                                                         accChild.dispose();
2133                                                         accChild.item = null;
2134                                                         found = true;
2135                                                         break;
2136                                                 }
2137                                         }
2138                                         osAccessible = new Accessible(this, addr[0]);
2139                                         osAccessible.item = item;
2140                                         if (!found) {
2141                                                 item.addListener(SWT.Dispose, e -> {
2142                                                         for (int i = 0; i < children.size(); i++) {
2143                                                                 Accessible accChild = children.get(i);
2144                                                                 if (accChild.item == item) {
2145                                                                         accChild.dispose();
2146                                                                 }
2147                                                         }
2148                                                 });
2149                                         }
2150                                         osAccessible.addAccessibleListener(new AccessibleAdapter() {
2151                                                 @Override
2152                                                 public void getName(AccessibleEvent e) {
2153                                                         if (e.childID == ACC.CHILDID_SELF) {
2154                                                                 AccessibleEvent event = new AccessibleEvent(Accessible.this);
2155                                                                 event.childID = childID;
2156                                                                 for (int i = 0; i < accessibleListenersSize(); i++) {
2157                                                                         AccessibleListener listener = accessibleListeners.get(i);
2158                                                                         listener.getName(event);
2159                                                                 }
2160                                                                 e.result = event.result;
2161                                                         }
2162                                                 }
2163                                         });
2164                                 }
2165                         }
2166                 }
2167
2168                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2169                 event.childID = childID;
2170                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2171                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2172                         listener.getChild(event);
2173                 }
2174                 Accessible accessible = event.accessible;
2175                 if (accessible == null) accessible = osAccessible;
2176                 if (accessible != null) {
2177                         if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning " + accessible.getAddress() + hresult(COM.S_OK));
2178                         accessible.AddRef();
2179                         OS.MoveMemory(ppdispChild, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
2180                         return COM.S_OK;
2181                 }
2182                 if (DEBUG) print(this + ".IAccessible::get_accChild(" + v.lVal + ") returning from super" + hresult(code));
2183                 return code;
2184         }
2185
2186         /* IAccessible::get_accChildCount([out] pcountChildren) */
2187         int get_accChildCount(long pcountChildren) {
2188                 int osChildCount = 0;
2189                 if (iaccessible != null) {
2190                         /* Get the default child count from the OS. */
2191                         int code = iaccessible.get_accChildCount(pcountChildren);
2192                         if (code == COM.S_OK) {
2193                                 int[] pChildCount = new int[1];
2194                                 OS.MoveMemory(pChildCount, pcountChildren, 4);
2195                                 osChildCount = pChildCount[0];
2196                         }
2197                         if (accessibleControlListenersSize() == 0) {
2198                                 if (DEBUG) print(this + ".IAccessible::get_accChildCount() returning " + osChildCount + " from super" + hresult(code));
2199                                 return code;
2200                         }
2201                 }
2202
2203                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2204                 event.childID = ACC.CHILDID_SELF;
2205                 event.detail = osChildCount;
2206                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2207                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2208                         listener.getChildCount(event);
2209                 }
2210                 if (DEBUG) print(this + ".IAccessible::get_accChildCount() returning " + event.detail + hresult(COM.S_OK));
2211                 OS.MoveMemory(pcountChildren, new int[] { event.detail }, 4);
2212                 return COM.S_OK;
2213         }
2214
2215         /* IAccessible::get_accDefaultAction([in] varChild, [out] pszDefaultAction) */
2216         int get_accDefaultAction(long varChild, long pszDefaultAction) {
2217                 if (DEBUG) print(this + ".IAccessible::get_accDefaultAction");
2218                 VARIANT v = getVARIANT(varChild);
2219                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2220                 int code = COM.DISP_E_MEMBERNOTFOUND;
2221                 String osDefaultAction = null;
2222                 if (iaccessible != null) {
2223                         /* Get the default defaultAction from the OS. */
2224                         code = iaccessible.get_accDefaultAction(varChild, pszDefaultAction);
2225                         if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
2226                         if (accessibleControlListenersSize() == 0) return code;
2227                         if (code == COM.S_OK) {
2228                                 long[] pDefaultAction = new long[1];
2229                                 OS.MoveMemory(pDefaultAction, pszDefaultAction, C.PTR_SIZEOF);
2230                                 int size = COM.SysStringByteLen(pDefaultAction[0]);
2231                                 if (size > 0) {
2232                                         char[] buffer = new char[(size + 1) /2];
2233                                         OS.MoveMemory(buffer, pDefaultAction[0], size);
2234                                         osDefaultAction = new String(buffer);
2235                                 }
2236                         }
2237                 }
2238
2239                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2240                 event.childID = osToChildID(v.lVal);
2241                 event.result = osDefaultAction;
2242                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2243                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2244                         listener.getDefaultAction(event);
2245                 }
2246                 if ((event.result == null || event.result.length() == 0) && v.lVal == COM.CHILDID_SELF) {
2247                         code = get_name(0, pszDefaultAction);
2248                 }
2249                 if (event.result == null) return code;
2250                 if (event.result.length() == 0) return COM.S_FALSE;
2251                 setString(pszDefaultAction, event.result);
2252                 return COM.S_OK;
2253         }
2254
2255         /* IAccessible::get_accDescription([in] varChild, [out] pszDescription) */
2256         int get_accDescription(long varChild, long pszDescription) {
2257                 /*
2258                  * MSAA: "The accDescription property is not supported in the transition to
2259                  * UI Automation. MSAA servers and applications should not use it."
2260                  *
2261                  * TODO: Description was exposed as SWT API. We will need to either deprecate this (?),
2262                  * or find a suitable replacement. Also, check description property on other platforms.
2263                  * If it is truly deprecated for MSAA, then perhaps it can be reused for IAccessibleImage.
2264                  * Note that the trick to expose tree columns (below) was not supported by screen readers,
2265                  * so it should be replaced.
2266                  */
2267                 VARIANT v = getVARIANT(varChild);
2268                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2269                 int code = COM.DISP_E_MEMBERNOTFOUND;
2270                 String osDescription = null;
2271                 if (iaccessible != null) {
2272                         /* Get the default description from the OS. */
2273                         code = iaccessible.get_accDescription(varChild, pszDescription);
2274                         if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
2275                         // TEMPORARY CODE - process tree even if there are no apps listening
2276                         if (accessibleListenersSize() == 0 && !(control instanceof Tree)) {
2277                                 if (DEBUG) print(this + ".IAccessible::get_accDescription(" + v.lVal + ") returning super" + hresult(code));
2278                                 return code;
2279                         }
2280                         if (code == COM.S_OK) {
2281                                 long[] pDescription = new long[1];
2282                                 OS.MoveMemory(pDescription, pszDescription, C.PTR_SIZEOF);
2283                                 int size = COM.SysStringByteLen(pDescription[0]);
2284                                 if (size > 0) {
2285                                         char[] buffer = new char[(size + 1) /2];
2286                                         OS.MoveMemory(buffer, pDescription[0], size);
2287                                         osDescription = new String(buffer);
2288                                 }
2289                         }
2290                 }
2291
2292                 AccessibleEvent event = new AccessibleEvent(this);
2293                 event.childID = osToChildID(v.lVal);
2294                 event.result = osDescription;
2295
2296                 // TEMPORARY CODE
2297                 /* Currently our tree columns are emulated using custom draw,
2298                  * so we need to create the description using the tree column
2299                  * header text and tree item text. */
2300                 if (v.lVal != COM.CHILDID_SELF) {
2301                         if (control instanceof Tree) {
2302                                 Tree tree = (Tree) control;
2303                                 int columnCount = tree.getColumnCount ();
2304                                 if (columnCount > 1) {
2305                                         long hwnd = control.handle, hItem = 0;
2306                                         hItem = OS.SendMessage (hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0);
2307                                         Widget widget = tree.getDisplay ().findWidget (hwnd, hItem);
2308                                         event.result = "";
2309                                         if (widget != null && widget instanceof TreeItem) {
2310                                                 TreeItem item = (TreeItem) widget;
2311                                                 for (int i = 1; i < columnCount; i++) {
2312                                                         if (tree.isDisposed() || item.isDisposed()) {
2313                                                                 event.result = "";
2314                                                                 return COM.S_OK;
2315                                                         }
2316                                                         event.result += tree.getColumn(i).getText() + ": " + item.getText(i);
2317                                                         if (i + 1 < columnCount) event.result += ", ";
2318                                                 }
2319                                         }
2320                                 }
2321                         }
2322                 }
2323                 for (int i = 0; i < accessibleListenersSize(); i++) {
2324                         AccessibleListener listener = accessibleListeners.get(i);
2325                         listener.getDescription(event);
2326                 }
2327                 if (DEBUG) print(this + ".IAccessible::get_accDescription(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
2328                 if (event.result == null) return code;
2329                 if (event.result.length() == 0) return COM.S_FALSE;
2330                 setString(pszDescription, event.result);
2331                 return COM.S_OK;
2332         }
2333
2334         /* IAccessible::get_accFocus([out] pvarChild)
2335          * Ownership of pvarChild transfers from callee to caller so reference count on pvarChild
2336          * must be incremented before returning.  The caller is responsible for releasing pvarChild.
2337          */
2338         int get_accFocus(long pvarChild) {
2339                 int osChild = ACC.CHILDID_NONE;
2340                 if (iaccessible != null) {
2341                         /* Get the default focus child from the OS. */
2342                         int code = iaccessible.get_accFocus(pvarChild);
2343                         if (code == COM.S_OK) {
2344                                 VARIANT v = getVARIANT(pvarChild);
2345                                 if (v.vt == COM.VT_I4) osChild = v.lVal;
2346                                 // TODO: need to check VT_DISPATCH (don't use struct)
2347                                 if (DEBUG) if (v.vt == COM.VT_DISPATCH) print("IAccessible::get_accFocus() super returned VT_DISPATCH");
2348                         }
2349                         if (accessibleControlListenersSize() == 0) {
2350                                 if (DEBUG) print(this + ".IAccessible::get_accFocus() returning childID=" + osChild + " from super" + hresult(code));
2351                                 return code;
2352                         }
2353                 }
2354
2355                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2356                 event.childID = osChild == ACC.CHILDID_NONE ? ACC.CHILDID_NONE : osToChildID(osChild);
2357                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2358                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2359                         listener.getFocus(event);
2360                 }
2361                 Accessible accessible = event.accessible;
2362                 if (accessible != null) {
2363                         if (DEBUG) print(this + ".IAccessible::get_accFocus() returning accessible " + accessible.getAddress() + hresult(COM.S_OK));
2364                         accessible.AddRef();
2365                         setPtrVARIANT(pvarChild, COM.VT_DISPATCH, accessible.getAddress());
2366                         return COM.S_OK;
2367                 }
2368                 int childID = event.childID;
2369                 if (childID == ACC.CHILDID_NONE) {
2370                         if (DEBUG) print(this + ".IAccessible::get_accFocus() returning VT_EMPTY" + hresult(COM.S_FALSE));
2371                         setIntVARIANT(pvarChild, COM.VT_EMPTY, 0);
2372                         return COM.S_FALSE;
2373                 }
2374                 if (childID == ACC.CHILDID_SELF) {
2375                         if (DEBUG) print(this + ".IAccessible::get_accFocus() returning CHILDID_SELF " + hresult(COM.S_OK));
2376                         AddRef();
2377                         setIntVARIANT(pvarChild, COM.VT_I4, COM.CHILDID_SELF);
2378                         return COM.S_OK;
2379                 }
2380                 if (DEBUG) print(this + ".IAccessible::get_accFocus() returning childID " + childIDToOs(childID) + hresult(COM.S_OK));
2381                 setIntVARIANT(pvarChild, COM.VT_I4, childIDToOs(childID));
2382                 return COM.S_OK;
2383         }
2384
2385         /* IAccessible::get_accHelp([in] varChild, [out] pszHelp) */
2386         int get_accHelp(long varChild, long pszHelp) {
2387                 if (DEBUG) print(this + ".IAccessible::get_accHelp");
2388                 VARIANT v = getVARIANT(varChild);
2389                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2390                 int code = COM.DISP_E_MEMBERNOTFOUND;
2391                 String osHelp = null;
2392                 if (iaccessible != null) {
2393                         /* Get the default help string from the OS. */
2394                         code = iaccessible.get_accHelp(varChild, pszHelp);
2395                         if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
2396                         if (accessibleListenersSize() == 0) return code;
2397                         if (code == COM.S_OK) {
2398                                 long[] pHelp = new long[1];
2399                                 OS.MoveMemory(pHelp, pszHelp, C.PTR_SIZEOF);
2400                                 int size = COM.SysStringByteLen(pHelp[0]);
2401                                 if (size > 0) {
2402                                         char[] buffer = new char[(size + 1) /2];
2403                                         OS.MoveMemory(buffer, pHelp[0], size);
2404                                         osHelp = new String(buffer);
2405                                 }
2406                         }
2407                 }
2408
2409                 AccessibleEvent event = new AccessibleEvent(this);
2410                 event.childID = osToChildID(v.lVal);
2411                 event.result = osHelp;
2412                 for (int i = 0; i < accessibleListenersSize(); i++) {
2413                         AccessibleListener listener = accessibleListeners.get(i);
2414                         listener.getHelp(event);
2415                 }
2416                 if (event.result == null) return code;
2417                 if (event.result.length() == 0) return COM.S_FALSE;
2418                 setString(pszHelp, event.result);
2419                 return COM.S_OK;
2420         }
2421
2422         /* IAccessible::get_accHelpTopic([out] pszHelpFile, [in] varChild, [out] pidTopic) */
2423         int get_accHelpTopic(long pszHelpFile, long varChild, long pidTopic) {
2424                 if (DEBUG) print(this + ".IAccessible::get_accHelpTopic");
2425                 /* MSAA: "The accHelpTopic property is deprecated and should not be used." */
2426                 int code = COM.DISP_E_MEMBERNOTFOUND;
2427                 if (iaccessible != null) {
2428                         /* Since it is possible that a native control might still handle get_accHelpTopic,
2429                          * we will continue to send this through to the proxy. */
2430                         code = iaccessible.get_accHelpTopic(pszHelpFile, varChild, pidTopic);
2431                         if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
2432                 }
2433                 return code;
2434         }
2435
2436         /* IAccessible::get_accKeyboardShortcut([in] varChild, [out] pszKeyboardShortcut) */
2437         int get_accKeyboardShortcut(long varChild, long pszKeyboardShortcut) {
2438                 if (DEBUG) print(this + ".IAccessible::get_accKeyboardShortcut");
2439                 VARIANT v = getVARIANT(varChild);
2440                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2441                 int code = COM.DISP_E_MEMBERNOTFOUND;
2442                 String osKeyboardShortcut = null;
2443                 if (iaccessible != null) {
2444                         /* Get the default keyboard shortcut from the OS. */
2445                         code = iaccessible.get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
2446                         if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
2447                         /* Process TabFolder even if there are no apps listening. */
2448                         if (accessibleListenersSize() == 0 && !(control instanceof TabFolder)) return code;
2449                         if (code == COM.S_OK) {
2450                                 long[] pKeyboardShortcut = new long[1];
2451                                 OS.MoveMemory(pKeyboardShortcut, pszKeyboardShortcut, C.PTR_SIZEOF);
2452                                 int size = COM.SysStringByteLen(pKeyboardShortcut[0]);
2453                                 if (size > 0) {
2454                                         char[] buffer = new char[(size + 1) /2];
2455                                         OS.MoveMemory(buffer, pKeyboardShortcut[0], size);
2456                                         osKeyboardShortcut = new String(buffer);
2457                                 }
2458                         }
2459                 }
2460
2461                 AccessibleEvent event = new AccessibleEvent(this);
2462                 event.childID = osToChildID(v.lVal);
2463                 event.result = osKeyboardShortcut;
2464                 /* SWT TabFolders use Ctrl+PageDown to switch pages (not Ctrl+Tab). */
2465                 if (v.lVal == COM.CHILDID_SELF && control instanceof TabFolder) {
2466                         event.result = SWT.getMessage ("SWT_SwitchPage_Shortcut"); //$NON-NLS-1$
2467                 }
2468                 for (int i = 0; i < accessibleListenersSize(); i++) {
2469                         AccessibleListener listener = accessibleListeners.get(i);
2470                         listener.getKeyboardShortcut(event);
2471                 }
2472                 if (event.result == null) return code;
2473                 if (event.result.length() == 0) return COM.S_FALSE;
2474                 setString(pszKeyboardShortcut, event.result);
2475                 return COM.S_OK;
2476         }
2477
2478         /* IAccessible::get_accName([in] varChild, [out] pszName) */
2479         int get_accName(long varChild, long pszName) {
2480                 if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
2481                 VARIANT v = getVARIANT(varChild);
2482                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2483                 int code = COM.S_FALSE;
2484                 String osName = null;
2485                 if (iaccessible != null) {
2486                         /* Get the default name from the OS. */
2487                         code = iaccessible.get_accName(varChild, pszName);
2488                         if (code == COM.S_OK) {
2489                                 long[] pName = new long[1];
2490                                 OS.MoveMemory(pName, pszName, C.PTR_SIZEOF);
2491                                 int size = COM.SysStringByteLen(pName[0]);
2492                                 if (size > 0) {
2493                                         char[] buffer = new char[(size + 1) /2];
2494                                         OS.MoveMemory(buffer, pName[0], size);
2495                                         osName = new String(buffer);
2496                                 }
2497                         }
2498                         if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
2499                         /* Process Text even if there are no apps listening. */
2500                         if (accessibleListenersSize() == 0 && !(control instanceof Text)) {
2501                                 if (DEBUG) print(this + ".IAccessible::get_accName(" + v.lVal + ") returning name=" + osName + " from super" + hresult(code));
2502                                 return code;
2503                         }
2504                 }
2505
2506                 AccessibleEvent event = new AccessibleEvent(this);
2507                 event.childID = osToChildID(v.lVal);
2508                 event.result = osName;
2509                 /*
2510                 * Bug in Windows:  A Text with SWT.SEARCH style uses EM_SETCUEBANNER
2511                 * to set the message text. This text should be used as the control's
2512                 * accessible name, however it is not. The fix is to return the message
2513                 * text here as the accName (unless there is a preceding label).
2514                 */
2515                 if (control instanceof Text && (control.getStyle() & SWT.SEARCH) != 0 && osName == null) {
2516                         event.result = ((Text) control).getMessage();
2517                 }
2518                 for (int i = 0; i < accessibleListenersSize(); i++) {
2519                         AccessibleListener listener = accessibleListeners.get(i);
2520                         listener.getName(event);
2521                 }
2522                 if (DEBUG) print(this + ".IAccessible::get_accName(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
2523                 if (event.result == null) return code;
2524                 if (event.result.length() == 0) return COM.S_FALSE;
2525                 setString(pszName, event.result);
2526                 return COM.S_OK;
2527         }
2528
2529         /* IAccessible::get_accParent([out] ppdispParent)
2530          * Ownership of ppdispParent transfers from callee to caller so reference count on ppdispParent
2531          * must be incremented before returning.  The caller is responsible for releasing ppdispParent.
2532          */
2533         int get_accParent(long ppdispParent) {
2534                 int code = COM.DISP_E_MEMBERNOTFOUND;
2535                 if (iaccessible != null) {
2536                         /* Currently, we don't expose this as API. Forward to the proxy. */
2537                         code = iaccessible.get_accParent(ppdispParent);
2538                 }
2539                 if (parent != null) {
2540                         /* For lightweight accessibles, return the accessible's parent. */
2541                         parent.AddRef();
2542                         OS.MoveMemory(ppdispParent, new long[] { parent.getAddress() }, C.PTR_SIZEOF);
2543                         code = COM.S_OK;
2544                 }
2545                 if (DEBUG) print(this + ".IAccessible::get_accParent() returning" + (parent != null ? " " + parent.getAddress() : " from super") + hresult(code));
2546                 return code;
2547         }
2548
2549         /* IAccessible::get_accRole([in] varChild, [out] pvarRole) */
2550         int get_accRole(long varChild, long pvarRole) {
2551                 if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
2552                 VARIANT v = getVARIANT(varChild);
2553                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2554                 int osRole = COM.ROLE_SYSTEM_CLIENT;
2555                 if (iaccessible != null) {
2556                         /* Get the default role from the OS. */
2557                         int code = iaccessible.get_accRole(varChild, pvarRole);
2558                         if (code == COM.S_OK) {
2559                                 VARIANT v2 = getVARIANT(pvarRole);
2560                                 if (v2.vt == COM.VT_I4) osRole = v2.lVal;
2561                         }
2562                 }
2563
2564                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2565                 event.childID = osToChildID(v.lVal);
2566                 event.detail = osToRole(osRole);
2567                 // TEMPORARY CODE
2568                 /* Currently our checkbox table and tree are emulated using state mask images,
2569                  * so we need to specify 'checkbox' role for the items. */
2570                 if (control instanceof Tree || control instanceof Table) {
2571                         if (v.lVal != COM.CHILDID_SELF && (control.getStyle() & SWT.CHECK) != 0) event.detail = ACC.ROLE_CHECKBUTTON;
2572                 }
2573                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2574                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2575                         listener.getRole(event);
2576                 }
2577                 if (DEBUG) print(this + ".IAccessible::get_accRole(" + v.lVal + ") returning " + getRoleString(roleToOs(event.detail)) + hresult(COM.S_OK));
2578                 setIntVARIANT(pvarRole, COM.VT_I4, roleToOs(event.detail));
2579                 return COM.S_OK;
2580         }
2581
2582         /* IAccessible::get_accSelection([out] pvarChildren)
2583          * Ownership of pvarChildren transfers from callee to caller so reference count on pvarChildren
2584          * must be incremented before returning.  The caller is responsible for releasing pvarChildren.
2585          */
2586         int get_accSelection(long pvarChildren) {
2587                 if (DEBUG) print(this + ".IAccessible::get_accSelection");
2588                 int osChild = ACC.CHILDID_NONE;
2589                 long osChildObject = 0;
2590                 if (iaccessible != null) {
2591                         /* Get the default selection from the OS. */
2592                         int code = iaccessible.get_accSelection(pvarChildren);
2593                         if (accessibleControlListenersSize() == 0) return code;
2594                         if (code == COM.S_OK) {
2595                                 VARIANT v = getVARIANT(pvarChildren);
2596                                 if (v.vt == COM.VT_I4) {
2597                                         osChild = osToChildID(v.lVal);
2598                                 } else if (v.vt == COM.VT_DISPATCH) {
2599                                         osChildObject = v.lVal; // TODO: don't use struct; lVal is an int
2600                                 } else if (v.vt == COM.VT_UNKNOWN) {
2601                                         osChild = ACC.CHILDID_MULTIPLE;
2602                                         // TODO: Should get IEnumVARIANT from punkVal field, and enumerate children...
2603                                 }
2604                         }
2605                 }
2606
2607                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2608                 event.childID = osChild;
2609                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2610                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2611                         listener.getSelection(event);
2612                 }
2613                 Accessible accessible = event.accessible;
2614                 if (accessible != null) {
2615                         accessible.AddRef();
2616                         setPtrVARIANT(pvarChildren, COM.VT_DISPATCH, accessible.getAddress());
2617                         return COM.S_OK;
2618                 }
2619                 int childID = event.childID;
2620                 if (childID == ACC.CHILDID_NONE) {
2621                         if (osChildObject != 0) return COM.S_OK;
2622                         setIntVARIANT(pvarChildren, COM.VT_EMPTY, 0);
2623                         return COM.S_FALSE;
2624                 }
2625                 if (childID == ACC.CHILDID_MULTIPLE) {
2626                         // TODO: return an enumeration for event.children (currently just returns enumeration from proxy)
2627                         //AddRef();
2628                         //setPtrVARIANT(pvarChildren, COM.VT_UNKNOWN, getAddress());
2629                         return COM.S_OK;
2630                 }
2631                 if (childID == ACC.CHILDID_SELF) {
2632                         AddRef();
2633                         setPtrVARIANT(pvarChildren, COM.VT_DISPATCH, getAddress());
2634                         return COM.S_OK;
2635                 }
2636                 setIntVARIANT(pvarChildren, COM.VT_I4, childIDToOs(childID));
2637                 return COM.S_OK;
2638         }
2639
2640         /* IAccessible::get_accState([in] varChild, [out] pvarState) */
2641         int get_accState(long varChild, long pvarState) {
2642                 if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
2643                 VARIANT v = getVARIANT(varChild);
2644                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2645                 int osState = 0;
2646                 if (iaccessible != null) {
2647                         /* Get the default state from the OS. */
2648                         int code = iaccessible.get_accState(varChild, pvarState);
2649                         if (code == COM.S_OK) {
2650                                 VARIANT v2 = getVARIANT(pvarState);
2651                                 if (v2.vt == COM.VT_I4) osState = v2.lVal;
2652                         }
2653                 }
2654
2655                 boolean grayed = false;
2656                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2657                 event.childID = osToChildID(v.lVal);
2658                 event.detail = osToState(osState);
2659                 // TEMPORARY CODE
2660                 /* Currently our checkbox table and tree are emulated using state mask
2661                  * images, so we need to determine if the item state is 'checked'. */
2662                 if (v.lVal != COM.CHILDID_SELF) {
2663                         if (control instanceof Tree && (control.getStyle() & SWT.CHECK) != 0) {
2664                                 long hwnd = control.handle;
2665                                 TVITEM tvItem = new TVITEM ();
2666                                 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
2667                                 tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
2668                                 tvItem.hItem = OS.SendMessage (hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0);
2669                                 long result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
2670                                 boolean checked = (result != 0) && (((tvItem.state >> 12) & 1) == 0);
2671                                 if (checked) event.detail |= ACC.STATE_CHECKED;
2672                                 grayed = tvItem.state >> 12 > 2;
2673                         } else if (control instanceof Table && (control.getStyle() & SWT.CHECK) != 0) {
2674                                 Table table = (Table) control;
2675                                 int index = event.childID;
2676                                 if (0 <= index && index < table.getItemCount()) {
2677                                         TableItem item = table.getItem(index);
2678                                         if (item.getChecked()) event.detail |= ACC.STATE_CHECKED;
2679                                         if (item.getGrayed()) grayed = true;
2680                                 }
2681                         }
2682                 }
2683                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2684                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2685                         listener.getState(event);
2686                 }
2687                 int state = stateToOs(event.detail);
2688                 if ((state & ACC.STATE_CHECKED) != 0 && grayed) {
2689                         state &= ~ COM.STATE_SYSTEM_CHECKED;
2690                         state |= COM.STATE_SYSTEM_MIXED;
2691                 }
2692                 if (DEBUG) print(this + ".IAccessible::get_accState(" + v.lVal + ") returning" + getStateString(state) + hresult(COM.S_OK));
2693                 setIntVARIANT(pvarState, COM.VT_I4, state);
2694                 return COM.S_OK;
2695         }
2696
2697         /* IAccessible::get_accValue([in] varChild, [out] pszValue) */
2698         int get_accValue(long varChild, long pszValue) {
2699                 if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
2700                 VARIANT v = getVARIANT(varChild);
2701                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2702                 int code = COM.DISP_E_MEMBERNOTFOUND;
2703                 String osValue = null;
2704                 if (iaccessible != null) {
2705                         /* Get the default value string from the OS. */
2706                         code = iaccessible.get_accValue(varChild, pszValue);
2707                         if (code == COM.S_OK) {
2708                                 long[] pValue = new long[1];
2709                                 OS.MoveMemory(pValue, pszValue, C.PTR_SIZEOF);
2710                                 int size = COM.SysStringByteLen(pValue[0]);
2711                                 if (size > 0) {
2712                                         char[] buffer = new char[(size + 1) /2];
2713                                         OS.MoveMemory(buffer, pValue[0], size);
2714                                         osValue = new String(buffer);
2715                                 }
2716                         }
2717                         if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
2718                         /* Process Text even if there are no apps listening. */
2719                         if (accessibleControlListenersSize() == 0 && !(control instanceof Text)) {
2720                                 if (DEBUG) print(this + ".IAccessible::get_accValue(" + v.lVal + ") returning value=" + osValue + " from super" + hresult(code));
2721                                 return code;
2722                         }
2723                 }
2724
2725                 AccessibleControlEvent event = new AccessibleControlEvent(this);
2726                 event.childID = osToChildID(v.lVal);
2727                 event.result = osValue;
2728                 /*
2729                 * Bug in Windows:  A Text with SWT.SEARCH style uses EM_SETCUEBANNER
2730                 * to set the message text. This text should be used as the control's
2731                 * accessible value when the control does not have focus, however it
2732                 * is not. The fix is to return the message text here as the accValue.
2733                 */
2734                 if (control instanceof Text && (control.getStyle() & SWT.SEARCH) != 0 && !control.isFocusControl()) {
2735                         event.result = ((Text) control).getMessage();
2736                 }
2737                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
2738                         AccessibleControlListener listener = accessibleControlListeners.get(i);
2739                         listener.getValue(event);
2740                 }
2741                 if (DEBUG) print(this + ".IAccessible::get_accValue(" + v.lVal + ") returning " + event.result + hresult(event.result == null ? code : COM.S_OK));
2742                 if (event.result == null) return code;
2743                 // empty string is a valid value, so do not test for it
2744                 setString(pszValue, event.result);
2745                 return COM.S_OK;
2746         }
2747
2748         /* put_accName([in] varChild, [in] szName) */
2749         int put_accName(long varChild, long szName) {
2750                 /* MSAA: "The IAccessible::put_accName method is no longer supported. Servers should return E_NOTIMPL." */
2751                 return COM.E_NOTIMPL;
2752         }
2753
2754         /* put_accValue([in] varChild, [in] szValue) */
2755         int put_accValue(long varChild, long szValue) {
2756                 /* MSAA: this method is supported for some UI elements (usually edit controls). */
2757                 VARIANT v = getVARIANT(varChild);
2758                 if (v.vt != COM.VT_I4) return COM.E_INVALIDARG;
2759                 int code = COM.DISP_E_MEMBERNOTFOUND;
2760                 if (v.lVal == COM.CHILDID_SELF && accessibleEditableTextListenersSize() > 0) {
2761                         /*
2762                          * If the object supports AccessibleEditableTextListener.replaceText,
2763                          * then give the object a chance to handle this event.
2764                          */
2765                         AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
2766                         event.start = 0;
2767                         event.end = getCharacterCount();
2768                         if (event.end >= 0) {
2769                                 int size = COM.SysStringByteLen(szValue);
2770                                 char [] buffer = new char [(size + 1) / 2];
2771                                 OS.MoveMemory (buffer, szValue, size);
2772                                 event.string = new String (buffer);
2773                                 for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
2774                                         AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
2775                                         listener.replaceText(event);
2776                                 }
2777                                 if (event.result != null && event.result.equals(ACC.OK)) code = COM.S_OK;
2778                                 if (DEBUG) print(this + ".IAccessible::put_accValue(" + v.lVal + ", \"" + event.string + "\") returning " + hresult(code));
2779                         }
2780                 }
2781                 if (code != COM.S_OK && iaccessible != null) {
2782                         /* If the object did not handle the event, then forward to the proxy. */
2783                         code = iaccessible.put_accValue(varChild, szValue);
2784                         if (code == COM.E_INVALIDARG) code = COM.DISP_E_MEMBERNOTFOUND; // proxy doesn't know about app childID
2785                         if (DEBUG) print(this + ".IAccessible::put_accValue(" + v.lVal + ") returning " + hresult(code) + " from proxy");
2786                 }
2787                 return code;
2788         }
2789
2790         /* IEnumVARIANT methods: Next, Skip, Reset, Clone */
2791         /* Retrieve the next celt items in the enumeration sequence.
2792          * If there are fewer than the requested number of elements left
2793          * in the sequence, retrieve the remaining elements.
2794          * The number of elements actually retrieved is returned in pceltFetched
2795          * (unless the caller passed in NULL for that parameter).
2796          */
2797
2798         /* IEnumVARIANT::Next([in] celt, [out] rgvar, [in, out] pceltFetched)
2799          * Ownership of rgvar transfers from callee to caller so reference count on rgvar
2800          * must be incremented before returning.  The caller is responsible for releasing rgvar.
2801          */
2802         int Next(int celt, long rgvar, long pceltFetched) {
2803                 if (DEBUG) print(this + ".IEnumVARIANT::Next");
2804                 /* If there are no listeners, query the proxy for
2805                  * its IEnumVariant, and get the Next items from it.
2806                  */
2807                 if (iaccessible != null && accessibleControlListenersSize() == 0) {
2808                         long[] ppvObject = new long[1];
2809                         int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
2810                         if (code != COM.S_OK) return code;
2811                         IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
2812                         int[] celtFetched = new int[1];
2813                         code = ienumvariant.Next(celt, rgvar, celtFetched);
2814                         ienumvariant.Release();
2815                         OS.MoveMemory(pceltFetched, celtFetched, 4);
2816                         return code;
2817                 }
2818
2819                 if (rgvar == 0) return COM.E_INVALIDARG;
2820                 if (pceltFetched == 0 && celt != 1) return COM.E_INVALIDARG;
2821                 if (enumIndex == 0) {
2822                         AccessibleControlEvent event = new AccessibleControlEvent(this);
2823                         event.childID = ACC.CHILDID_SELF;
2824                         for (int i = 0; i < accessibleControlListenersSize(); i++) {
2825                                 AccessibleControlListener listener = accessibleControlListeners.get(i);
2826                                 listener.getChildren(event);
2827                         }
2828                         variants = event.children;
2829                 }
2830                 Object[] nextItems = null;
2831                 if (variants != null && celt >= 1) {
2832                         int endIndex = enumIndex + celt - 1;
2833                         if (endIndex > (variants.length - 1)) endIndex = variants.length - 1;
2834                         if (enumIndex <= endIndex) {
2835                                 nextItems = new Object[endIndex - enumIndex + 1];
2836                                 for (int i = 0; i < nextItems.length; i++) {
2837                                         Object child = variants[enumIndex];
2838                                         if (child instanceof Integer) {
2839                                                 nextItems[i] = Integer.valueOf(childIDToOs(((Integer)child).intValue()));
2840                                         } else {
2841                                                 nextItems[i] = child;
2842                                         }
2843                                         enumIndex++;
2844                                 }
2845                         }
2846                 }
2847                 if (nextItems != null) {
2848                         for (int i = 0; i < nextItems.length; i++) {
2849                                 Object nextItem = nextItems[i];
2850                                 if (nextItem instanceof Integer) {
2851                                         int item = ((Integer) nextItem).intValue();
2852                                         setIntVARIANT(rgvar + i * VARIANT.sizeof, COM.VT_I4, item);
2853                                 } else {
2854                                         Accessible accessible = (Accessible) nextItem;
2855                                         accessible.AddRef();
2856                                         setPtrVARIANT(rgvar + i * VARIANT.sizeof, COM.VT_DISPATCH, accessible.getAddress());
2857                                 }
2858                         }
2859                         if (pceltFetched != 0)
2860                                 OS.MoveMemory(pceltFetched, new int[] {nextItems.length}, 4);
2861                         if (nextItems.length == celt) return COM.S_OK;
2862                 } else {
2863                         if (pceltFetched != 0)
2864                                 OS.MoveMemory(pceltFetched, new int[] {0}, 4);
2865                 }
2866                 return COM.S_FALSE;
2867         }
2868
2869         /* IEnumVARIANT::Skip([in] celt) over the specified number of elements in the enumeration sequence. */
2870         int Skip(int celt) {
2871                 if (DEBUG) print(this + ".IEnumVARIANT::Skip");
2872                 /* If there are no listeners, query the proxy
2873                  * for its IEnumVariant, and tell it to Skip.
2874                  */
2875                 if (iaccessible != null && accessibleControlListenersSize() == 0) {
2876                         long[] ppvObject = new long[1];
2877                         int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
2878                         if (code != COM.S_OK) return code;
2879                         IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
2880                         code = ienumvariant.Skip(celt);
2881                         ienumvariant.Release();
2882                         return code;
2883                 }
2884
2885                 if (celt < 1 ) return COM.E_INVALIDARG;
2886                 enumIndex += celt;
2887                 if (enumIndex > (variants.length - 1)) {
2888                         enumIndex = variants.length - 1;
2889                         return COM.S_FALSE;
2890                 }
2891                 return COM.S_OK;
2892         }
2893
2894         /* IEnumVARIANT::Reset() the enumeration sequence to the beginning. */
2895         int Reset() {
2896                 if (DEBUG) print(this + ".IEnumVARIANT::Reset");
2897                 /* If there are no listeners, query the proxy
2898                  * for its IEnumVariant, and tell it to Reset.
2899                  */
2900                 if (iaccessible != null && accessibleControlListenersSize() == 0) {
2901                         long[] ppvObject = new long[1];
2902                         int code = (int)iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
2903                         if (code != COM.S_OK) return code;
2904                         IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
2905                         code = ienumvariant.Reset();
2906                         ienumvariant.Release();
2907                         return code;
2908                 }
2909
2910                 enumIndex = 0;
2911                 return COM.S_OK;
2912         }
2913
2914         /* IEnumVARIANT::Clone([out] ppEnum)
2915          * Ownership of ppEnum transfers from callee to caller so reference count on ppEnum
2916          * must be incremented before returning.  The caller is responsible for releasing ppEnum.
2917          */
2918         int Clone(long ppEnum) {
2919                 if (DEBUG) print(this + ".IEnumVARIANT::Clone");
2920                 /* If there are no listeners, query the proxy for
2921                  * its IEnumVariant, and get the Clone from it.
2922                  */
2923                 if (iaccessible != null && accessibleControlListenersSize() == 0) {
2924                         long[] ppvObject = new long[1];
2925                         int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
2926                         if (code != COM.S_OK) return code;
2927                         IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
2928                         long [] pEnum = new long [1];
2929                         code = ienumvariant.Clone(pEnum);
2930                         ienumvariant.Release();
2931                         OS.MoveMemory(ppEnum, pEnum, C.PTR_SIZEOF);
2932                         return code;
2933                 }
2934
2935                 if (ppEnum == 0) return COM.E_INVALIDARG;
2936                 OS.MoveMemory(ppEnum, new long[] { objIEnumVARIANT.getAddress() }, C.PTR_SIZEOF);
2937                 AddRef();
2938                 return COM.S_OK;
2939         }
2940
2941         /* IAccessible2::get_nRelations([out] pNRelations) */
2942         int get_nRelations(long pNRelations) {
2943                 int count = getRelationCount();
2944                 if (DEBUG) print(this + ".IAccessible2::get_nRelations returning " + count + hresult(COM.S_OK));
2945                 OS.MoveMemory(pNRelations, new int [] { count }, 4);
2946                 return COM.S_OK;
2947         }
2948
2949         /* IAccessible2::get_relation([in] relationIndex, [out] ppRelation) */
2950         int get_relation(int relationIndex, long ppRelation) {
2951                 int i = -1;
2952                 for (int type = 0; type < MAX_RELATION_TYPES; type++) {
2953                         Relation relation = relations[type];
2954                         if (relation != null) i++;
2955                         if (i == relationIndex) {
2956                                 if (DEBUG) print(this + ".IAccessible2::get_relation(" + relationIndex + ") returning " + relation.getAddress() + hresult(COM.S_OK));
2957                                 relation.AddRef();
2958                                 OS.MoveMemory(ppRelation, new long[] { relation.getAddress() }, C.PTR_SIZEOF);
2959                                 return COM.S_OK;
2960                         }
2961                 }
2962                 if (DEBUG) print(this + ".IAccessible2::get_relation(" + relationIndex + ") returning" + hresult(COM.E_INVALIDARG));
2963                 return COM.E_INVALIDARG;
2964         }
2965
2966         /* IAccessible2::get_relations([in] maxRelations, [out] ppRelations, [out] pNRelations) */
2967         int get_relations(int maxRelations, long ppRelations, long pNRelations) {
2968                 int count = 0;
2969                 for (int type = 0; type < MAX_RELATION_TYPES; type++) {
2970                         if (count == maxRelations) break;
2971                         Relation relation = relations[type];
2972                         if (relation != null) {
2973                                 relation.AddRef();
2974                                 OS.MoveMemory(ppRelations + count * C.PTR_SIZEOF, new long[] { relation.getAddress() }, C.PTR_SIZEOF);
2975                                 count++;
2976                         }
2977                 }
2978                 if (DEBUG) print(this + ".IAccessible2::get_relations(" + maxRelations + ") returning " + count + hresult(COM.S_OK));
2979                 OS.MoveMemory(pNRelations, new int [] { count }, 4);
2980                 return COM.S_OK;
2981         }
2982
2983         /* IAccessible2::get_role([out] pRole) */
2984         int get_role(long pRole) {
2985                 int role = getRole();
2986                 if (role == 0) role = getDefaultRole();
2987                 if (DEBUG) print(this + ".IAccessible2::get_role() returning " + getRoleString(role) + hresult(COM.S_OK));
2988                 OS.MoveMemory(pRole, new int [] { role }, 4);
2989                 return COM.S_OK;
2990         }
2991
2992         /* IAccessible2::scrollTo([in] scrollType) */
2993         int scrollTo(int scrollType) {
2994                 if (DEBUG) print(this + ".IAccessible2::scrollTo");
2995                 if (scrollType < ACC.SCROLL_TYPE_LEFT_EDGE || scrollType > ACC.SCROLL_TYPE_ANYWHERE) return COM.E_INVALIDARG;
2996                 return COM.E_NOTIMPL;
2997         }
2998
2999         /* IAccessible2::scrollToPoint([in] coordinateType, [in] x, [in] y) */
3000         int scrollToPoint(int coordinateType, int x, int y) {
3001                 if (DEBUG) print(this + ".IAccessible2::scrollToPoint");
3002                 if (coordinateType != COM.IA2_COORDTYPE_SCREEN_RELATIVE) return COM.E_INVALIDARG;
3003                 return COM.E_NOTIMPL;
3004         }
3005
3006         /* IAccessible2::get_groupPosition([out] pGroupLevel, [out] pSimilarItemsInGroup, [out] pPositionInGroup) */
3007         int get_groupPosition(long pGroupLevel, long pSimilarItemsInGroup, long pPositionInGroup) {
3008                 if (control != null && control.isDisposed()) return COM.CO_E_OBJNOTCONNECTED;
3009                 AccessibleAttributeEvent event = new AccessibleAttributeEvent(this);
3010                 event.groupLevel = event.groupCount = event.groupIndex = -1;
3011                 for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
3012                         AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
3013                         listener.getAttributes(event);
3014                 }
3015                 int groupLevel = (event.groupLevel != -1) ? event.groupLevel : 0;
3016                 int similarItemsInGroup = (event.groupCount != -1) ? event.groupCount : 0;
3017                 int positionInGroup = (event.groupIndex != -1) ? event.groupIndex : 0;
3018                 if (similarItemsInGroup == 0 && positionInGroup == 0) {
3019                         /* Determine position and count for radio buttons. */
3020                         if (control instanceof Button && ((control.getStyle() & SWT.RADIO) != 0)) {
3021                                 Control [] children = control.getParent().getChildren();
3022                                 positionInGroup = 1;
3023                                 similarItemsInGroup = 1;
3024                                 for (int i = 0; i < children.length; i++) {
3025                                         Control child = children[i];
3026                                         if (child instanceof Button && ((child.getStyle() & SWT.RADIO) != 0)) {
3027                                                 if (child == control) positionInGroup = similarItemsInGroup;
3028                                                 else similarItemsInGroup++;
3029                                         }
3030                                 }
3031                         }
3032                 }
3033                 OS.MoveMemory(pGroupLevel, new int [] { groupLevel }, 4);
3034                 OS.MoveMemory(pSimilarItemsInGroup, new int [] { similarItemsInGroup }, 4);
3035                 OS.MoveMemory(pPositionInGroup, new int [] { positionInGroup }, 4);
3036                 if (DEBUG) print(this + ".IAccessible2::get_groupPosition() returning level=" + groupLevel + ", count=" + similarItemsInGroup + ", index=" + positionInGroup + hresult(groupLevel == 0 && similarItemsInGroup == 0 && positionInGroup == 0 ? COM.S_FALSE : COM.S_OK));
3037                 if (groupLevel == 0 && similarItemsInGroup == 0 && positionInGroup == 0) return COM.S_FALSE;
3038                 return COM.S_OK;
3039         }
3040
3041         /* IAccessible2::get_states([out] pStates) */
3042         int get_states(long pStates) {
3043                 AccessibleControlEvent event = new AccessibleControlEvent(this);
3044                 event.childID = ACC.CHILDID_SELF;
3045                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
3046                         AccessibleControlListener listener = accessibleControlListeners.get(i);
3047                         listener.getState(event);
3048                 }
3049                 int states = event.detail;
3050                 int ia2States = 0;
3051                 if ((states & ACC.STATE_ACTIVE) != 0) ia2States |= COM.IA2_STATE_ACTIVE;
3052                 if ((states & ACC.STATE_SINGLELINE) != 0) ia2States |= COM.IA2_STATE_SINGLE_LINE;
3053                 if ((states & ACC.STATE_MULTILINE) != 0) ia2States |= COM.IA2_STATE_MULTI_LINE;
3054                 if ((states & ACC.STATE_REQUIRED) != 0) ia2States |= COM.IA2_STATE_REQUIRED;
3055                 if ((states & ACC.STATE_INVALID_ENTRY) != 0) ia2States |= COM.IA2_STATE_INVALID_ENTRY;
3056                 if ((states & ACC.STATE_SUPPORTS_AUTOCOMPLETION) != 0) ia2States |= COM.IA2_STATE_SUPPORTS_AUTOCOMPLETION;
3057
3058                 /* If the role is text and there are TextExtendedListeners, then set IA2_STATE_EDITABLE.
3059                  * Note that IA2_STATE_EDITABLE is not the opposite of STATE_READONLY.
3060                  * Instead, it means: "has a caret, supports IAccessibleText, and is a text editing environment".
3061                  */
3062                 if (getRole() == ACC.ROLE_TEXT && accessibleTextExtendedListenersSize() > 0) {
3063                         ia2States |= COM.IA2_STATE_EDITABLE;
3064                 }
3065                 if (DEBUG) print(this + ".IAccessible2::get_states returning" + getIA2StatesString(ia2States) + hresult(COM.S_OK));
3066                 OS.MoveMemory(pStates, new int [] { ia2States }, 4);
3067                 return COM.S_OK;
3068         }
3069
3070         /* IAccessible2::get_extendedRole([out] pbstrExtendedRole) */
3071         int get_extendedRole(long pbstrExtendedRole) {
3072                 /* This feature is not supported. */
3073                 setString(pbstrExtendedRole, null);
3074                 return COM.S_FALSE;
3075         }
3076
3077         /* IAccessible2::get_localizedExtendedRole([out] pbstrLocalizedExtendedRole) */
3078         int get_localizedExtendedRole(long pbstrLocalizedExtendedRole) {
3079                 /* This feature is not supported. */
3080                 setString(pbstrLocalizedExtendedRole, null);
3081                 return COM.S_FALSE;
3082         }
3083
3084         /* IAccessible2::get_nExtendedStates([out] pNExtendedStates) */
3085         int get_nExtendedStates(long pNExtendedStates) {
3086                 /* This feature is not supported. */
3087                 OS.MoveMemory(pNExtendedStates, new int [] { 0 }, 4);
3088                 return COM.S_OK;
3089         }
3090
3091         /* IAccessible2::get_extendedStates([in] maxExtendedStates, [out] ppbstrExtendedStates, [out] pNExtendedStates) */
3092         int get_extendedStates(int maxExtendedStates, long ppbstrExtendedStates, long pNExtendedStates) {
3093                 /* This feature is not supported. */
3094                 setString(ppbstrExtendedStates, null);
3095                 OS.MoveMemory(pNExtendedStates, new int [] { 0 }, 4);
3096                 return COM.S_FALSE;
3097         }
3098
3099         /* IAccessible2::get_localizedExtendedStates([in] maxLocalizedExtendedStates, [out] ppbstrLocalizedExtendedStates, [out] pNLocalizedExtendedStates) */
3100         int get_localizedExtendedStates(int maxLocalizedExtendedStates, long ppbstrLocalizedExtendedStates, long pNLocalizedExtendedStates) {
3101                 /* This feature is not supported. */
3102                 setString(ppbstrLocalizedExtendedStates, null);
3103                 OS.MoveMemory(pNLocalizedExtendedStates, new int [] { 0 }, 4);
3104                 return COM.S_FALSE;
3105         }
3106
3107         /* IAccessible2::get_uniqueID([out] pUniqueID) */
3108         int get_uniqueID(long pUniqueID) {
3109                 if (uniqueID == -1) uniqueID = UniqueID--;
3110                 if (DEBUG) print(this + ".IAccessible2::get_uniqueID returning " + uniqueID + hresult(COM.S_OK));
3111                 OS.MoveMemory(pUniqueID, new long [] { uniqueID }, 4);
3112                 return COM.S_OK;
3113         }
3114
3115         /* IAccessible2::get_windowHandle([out] pWindowHandle) */
3116         int get_windowHandle(long pWindowHandle) {
3117                 if (DEBUG) print(this + ".IAccessible2::get_windowHandle returning " + control.handle + hresult(COM.S_OK));
3118                 OS.MoveMemory(pWindowHandle, new long [] { control.handle }, C.PTR_SIZEOF);
3119                 return COM.S_OK;
3120         }
3121
3122         /* IAccessible2::get_indexInParent([out] pIndexInParent) */
3123         int get_indexInParent(long pIndexInParent) {
3124                 AccessibleControlEvent event = new AccessibleControlEvent(this);
3125                 event.childID = ACC.CHILDID_CHILD_INDEX;
3126                 event.detail = -1;
3127                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
3128                         AccessibleControlListener listener = accessibleControlListeners.get(i);
3129                         listener.getChild(event);
3130                 }
3131                 int indexInParent = event.detail;
3132                 if (indexInParent == -1) {
3133 //                      /* The application did not implement CHILDID_CHILD_INDEX,
3134 //                       * so determine the index by looping through the parent's
3135 //                       * children looking for this Accessible. This may be slow,
3136 //                       * so applications are strongly encouraged to implement
3137 //                       * getChild for CHILDID_CHILD_INDEX.
3138 //                       */
3139 //                      // TODO: finish this. See also get_groupPosition
3140                         // this won't work because VARIANT.sizeof isn't big enough on 64-bit machines.
3141                         // just create an  long [] ppdispParent - it's not a variant anyhow...
3142 //                      long ppdispParent = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
3143 //                      int code = get_accParent(ppdispParent);
3144 //                      if (code == COM.S_OK) {
3145 //                              VARIANT v = getVARIANT(ppdispParent);
3146 //                              if (v.vt == COM.VT_DISPATCH) {
3147 //                                      IAccessible accParent = new IAccessible(v.lVal);
3148 //                                      long pcountChildren = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, 4);
3149 //                                      code = accParent.get_accChildCount(pcountChildren);
3150 //                                      if (code == COM.S_OK) {
3151 //                                              int [] childCount = new int[1];
3152 //                                              OS.MoveMemory(childCount, pcountChildren, 4);
3153 //                                              int[] pcObtained = new int[1];
3154 //                                              long rgVarChildren = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof * childCount[0]);
3155 //                                              System.out.println("Asking for AccessibleChildren");
3156 //                                              code = COM.AccessibleChildren(accParent.getAddress(), 0, childCount[0], rgVarChildren, pcObtained);
3157 //                                              if (code == COM.S_OK) {
3158 //                                                      System.out.println("Got this far - now what?");
3159 //                                              } else {
3160 //                                                      System.out.println("AccessibleChildren failed? code=" + code);
3161 //                                              }
3162 //                                              OS.GlobalFree(rgVarChildren);
3163 //                                      } else {
3164 //                                              System.out.println("get_accChildCount failed? code=" + code);
3165 //                                      }
3166 //                                      OS.GlobalFree (pcountChildren);
3167 //                              } else {
3168 //                                      System.out.println("get_accParent did not return VT_DISPATCH? It returned: " + v.vt);
3169 //                              }
3170 //                              COM.VariantClear(ppdispParent);
3171 //                              OS.GlobalFree (ppdispParent);
3172 //                      } else {
3173 //                              System.out.println("get_accParent failed? code=" + code);
3174 //                      }
3175                 }
3176
3177                 if (DEBUG) print(this + ".IAccessible2::get_indexInParent returning " + indexInParent + hresult(indexInParent == -1 ? COM.S_FALSE : COM.S_OK));
3178                 OS.MoveMemory(pIndexInParent, new int [] { indexInParent }, 4);
3179                 return indexInParent == -1 ? COM.S_FALSE : COM.S_OK;
3180         }
3181
3182         /* IAccessible2::get_locale([out] pLocale) */
3183         int get_locale(long pLocale) {
3184                 /* Return the default locale for the JVM. */
3185                 Locale locale = Locale.getDefault();
3186
3187                 char[] data = (locale.getLanguage()+"\0").toCharArray();
3188                 long ptr = COM.SysAllocString(data);
3189                 OS.MoveMemory(pLocale, new long[] {ptr}, C.PTR_SIZEOF);
3190
3191                 data = (locale.getCountry()+"\0").toCharArray();
3192                 ptr = COM.SysAllocString(data);
3193                 OS.MoveMemory(pLocale + C.PTR_SIZEOF, new long[] {ptr}, C.PTR_SIZEOF);
3194
3195                 data = (locale.getVariant()+"\0").toCharArray();
3196                 ptr = COM.SysAllocString(data);
3197                 OS.MoveMemory(pLocale + 2 * C.PTR_SIZEOF, new long[] {ptr}, C.PTR_SIZEOF);
3198
3199                 if (DEBUG) print(this + ".IAccessible2::get_locale() returning" + hresult(COM.S_OK));
3200                 return COM.S_OK;
3201         }
3202
3203         /* IAccessible2::get_attributes([out] pbstrAttributes) */
3204         int get_attributes(long pbstrAttributes) {
3205                 AccessibleAttributeEvent event = new AccessibleAttributeEvent(this);
3206                 for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
3207                         AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
3208                         listener.getAttributes(event);
3209                 }
3210                 String attributes = "";
3211                 attributes += "margin-left:" + event.leftMargin + ";";
3212                 attributes += "margin-top:" + event.topMargin + ";";
3213                 attributes += "margin-right:" + event.rightMargin + ";";
3214                 attributes += "margin-bottom:" + event.bottomMargin + ";";
3215                 if (event.tabStops != null) {
3216                         for (int i = 0; i < event.tabStops.length; i++) {
3217                                 attributes += "tab-stop:position=" + event.tabStops[i] + ";";
3218                         }
3219                 }
3220                 if (event.justify) attributes += "text-align:justify;";
3221                 attributes += "text-align:" + (event.alignment == SWT.LEFT ? "left" : event.alignment == SWT.RIGHT ? "right" : "center") + ";";
3222                 attributes += "text-indent:" + event.indent + ";";
3223                 if (event.attributes != null) {
3224                         for (int i = 0; i + 1 < event.attributes.length; i += 2) {
3225                                 attributes += event.attributes[i] + ":" + event.attributes[i+1] + ";";
3226                         }
3227                 }
3228
3229                 /* If the role is text, then specify the text model for JAWS. */
3230                 if (getRole() == ACC.ROLE_TEXT) {
3231                         attributes += "text-model:a1;";
3232                 }
3233                 if (DEBUG) print(this + ".IAccessible2::get_attributes() returning " + attributes + hresult(attributes.length() == 0 ? COM.S_FALSE : COM.S_OK));
3234                 setString(pbstrAttributes, attributes);
3235                 if (attributes.length() == 0) return COM.S_FALSE;
3236                 return COM.S_OK;
3237         }
3238
3239         /* IAccessibleAction::get_nActions([out] pNActions) */
3240         int get_nActions(long pNActions) {
3241                 AccessibleActionEvent event = new AccessibleActionEvent(this);
3242                 for (int i = 0; i < accessibleActionListenersSize(); i++) {
3243                         AccessibleActionListener listener = accessibleActionListeners.get(i);
3244                         listener.getActionCount(event);
3245                 }
3246                 if (DEBUG) print(this + ".IAccessibleAction::get_nActions() returning " + event.count + hresult(COM.S_OK));
3247                 OS.MoveMemory(pNActions, new int [] { event.count }, 4);
3248                 return COM.S_OK;
3249         }
3250
3251         /* IAccessibleAction::doAction([in] actionIndex) */
3252         int doAction(int actionIndex) {
3253                 AccessibleActionEvent event = new AccessibleActionEvent(this);
3254                 event.index = actionIndex;
3255                 for (int i = 0; i < accessibleActionListenersSize(); i++) {
3256                         AccessibleActionListener listener = accessibleActionListeners.get(i);
3257                         listener.doAction(event);
3258                 }
3259                 if (DEBUG) print(this + ".IAccessibleAction::doAction(" + actionIndex + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK));
3260                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
3261                 return COM.S_OK;
3262         }
3263
3264         /* IAccessibleAction::get_description([in] actionIndex, [out] pbstrDescription) */
3265         int get_description(int actionIndex, long pbstrDescription) {
3266                 AccessibleActionEvent event = new AccessibleActionEvent(this);
3267                 event.index = actionIndex;
3268                 for (int i = 0; i < accessibleActionListenersSize(); i++) {
3269                         AccessibleActionListener listener = accessibleActionListeners.get(i);
3270                         listener.getDescription(event);
3271                 }
3272                 if (DEBUG) print(this + ".IAccessibleAction::get_description(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
3273                 setString(pbstrDescription, event.result);
3274                 if (event.result == null || event.result.length() == 0) return COM.S_FALSE;
3275                 return COM.S_OK;
3276         }
3277
3278         /* IAccessibleAction::get_keyBinding([in] actionIndex, [in] nMaxBindings, [out] ppbstrKeyBindings, [out] pNBindings) */
3279         int get_keyBinding(int actionIndex, int nMaxBindings, long ppbstrKeyBindings, long pNBindings) {
3280                 AccessibleActionEvent event = new AccessibleActionEvent(this);
3281                 event.index = actionIndex;
3282                 for (int i = 0; i < accessibleActionListenersSize(); i++) {
3283                         AccessibleActionListener listener = accessibleActionListeners.get(i);
3284                         listener.getKeyBinding(event);
3285                 }
3286                 String keyBindings = event.result;
3287                 int length = 0;
3288                 if (keyBindings != null) length = keyBindings.length();
3289                 int i = 0, count = 0;
3290                 while (i < length) {
3291                         if (count == nMaxBindings) break;
3292                         int j = keyBindings.indexOf(';', i);
3293                         if (j == -1) j = length;
3294                         String keyBinding = keyBindings.substring(i, j);
3295                         if (keyBinding.length() > 0) {
3296                                 setString(ppbstrKeyBindings + count * C.PTR_SIZEOF, keyBinding);
3297                                 count++;
3298                         }
3299                         i = j + 1;
3300                 }
3301                 if (DEBUG) print(this + ".IAccessibleAction::get_keyBinding(index=" + actionIndex + " max=" + nMaxBindings + ") returning count=" + count + hresult(count == 0 ? COM.S_FALSE : COM.S_OK));
3302                 OS.MoveMemory(pNBindings, new int [] { count }, 4);
3303                 if (count == 0) {
3304                         setString(ppbstrKeyBindings, null);
3305                         return COM.S_FALSE;
3306                 }
3307                 return COM.S_OK;
3308         }
3309
3310         /* IAccessibleAction::get_name([in] actionIndex, [out] pbstrName) */
3311         int get_name(int actionIndex, long pbstrName) {
3312                 AccessibleActionEvent event = new AccessibleActionEvent(this);
3313                 event.index = actionIndex;
3314                 event.localized = false;
3315                 for (int i = 0; i < accessibleActionListenersSize(); i++) {
3316                         AccessibleActionListener listener = accessibleActionListeners.get(i);
3317                         listener.getName(event);
3318                 }
3319                 if (DEBUG) print(this + ".IAccessibleAction::get_name(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
3320                 if (event.result == null || event.result.length() == 0) {
3321                         setString(pbstrName, null);
3322                         return COM.S_FALSE;
3323                 }
3324                 setString(pbstrName, event.result);
3325                 return COM.S_OK;
3326         }
3327
3328         /* IAccessibleAction::get_localizedName([in] actionIndex, [out] pbstrLocalizedName) */
3329         int get_localizedName(int actionIndex, long pbstrLocalizedName) {
3330                 AccessibleActionEvent event = new AccessibleActionEvent(this);
3331                 event.index = actionIndex;
3332                 event.localized = true;
3333                 for (int i = 0; i < accessibleActionListenersSize(); i++) {
3334                         AccessibleActionListener listener = accessibleActionListeners.get(i);
3335                         listener.getName(event);
3336                 }
3337                 if (DEBUG) print(this + ".IAccessibleAction::get_localizedName(" + actionIndex + ") returning " + event.result + hresult(event.result == null || event.result.length() == 0 ? COM.S_FALSE : COM.S_OK));
3338                 if (event.result == null || event.result.length() == 0) {
3339                         setString(pbstrLocalizedName, null);
3340                         return COM.S_FALSE;
3341                 }
3342                 setString(pbstrLocalizedName, event.result);
3343                 return COM.S_OK;
3344         }
3345
3346         /* IAccessibleApplication::get_appName([out] pbstrName) */
3347         int get_appName(long pbstrName) {
3348                 String appName = Display.getAppName();
3349                 if (DEBUG) print(this + ".IAccessibleApplication::get_appName() returning " + appName + hresult(appName == null || appName.length() == 0 ? COM.S_FALSE : COM.S_OK));
3350                 if (appName == null || appName.length() == 0) {
3351                         setString(pbstrName, null);
3352                         return COM.S_FALSE;
3353                 }
3354                 setString(pbstrName, appName);
3355                 return COM.S_OK;
3356         }
3357
3358         /* IAccessibleApplication::get_appVersion([out] pbstrVersion) */
3359         int get_appVersion(long pbstrVersion) {
3360                 String appVersion = Display.getAppVersion();
3361                 if (DEBUG) print(this + ".IAccessibleApplication::get_appVersion() returning" + appVersion + hresult(appVersion == null || appVersion.length() == 0 ? COM.S_FALSE : COM.S_OK));
3362                 if (appVersion == null || appVersion.length() == 0) {
3363                         setString(pbstrVersion, null);
3364                         return COM.S_FALSE;
3365                 }
3366                 setString(pbstrVersion, appVersion);
3367                 return COM.S_OK;
3368         }
3369
3370         /* IAccessibleApplication::get_toolkitName([out] pbstrName) */
3371         int get_toolkitName(long pbstrName) {
3372                 String toolkitName = "SWT";
3373                 if (DEBUG) print(this + ".IAccessibleApplication::get_toolkitName() returning" + toolkitName + hresult(COM.S_OK));
3374                 setString(pbstrName, toolkitName);
3375                 return COM.S_OK;
3376         }
3377
3378         /* IAccessibleApplication::get_toolkitVersion([out] pbstrVersion) */
3379         int get_toolkitVersion(long pbstrVersion) {
3380                 String toolkitVersion = "" + SWT.getVersion(); //$NON-NLS-1$
3381                 if (DEBUG) print(this + ".IAccessibleApplication::get_toolkitVersion() returning" + toolkitVersion + hresult(COM.S_OK));
3382                 setString(pbstrVersion, toolkitVersion);
3383                 return COM.S_OK;
3384         }
3385
3386         // The following 3 method are intentionally commented. We are not providing IAccessibleComponent at this time.
3387 //      /* IAccessibleComponent::get_locationInParent([out] pX, [out] pY) */
3388 //      int get_locationInParent(long pX, long pY) {
3389 //              if (DEBUG) print(this + ".IAccessibleComponent::get_locationInParent");
3390 //              // TO DO: support transparently (hard for lightweight parents - screen vs. parent coords)
3391 //              AccessibleControlEvent event = new AccessibleControlEvent(this);
3392 //              for (int i = 0; i < accessibleControlListenersSize(); i++) {
3393 //                      AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i);
3394 //                      listener.getLocation (event);
3395 //              }
3396 //              COM.MoveMemory(pX, new int [] { event.x }, 4);
3397 //              COM.MoveMemory(pY, new int [] { event.y }, 4);
3398 //              return COM.S_OK;
3399 //      }
3400 //
3401 //      /* IAccessibleComponent::get_foreground([out] pForeground) */
3402 //      int get_foreground(long pForeground) {
3403 //              Color color = control.getForeground();
3404 //              if (DEBUG) print(this + ".IAccessibleComponent::get_foreground returning " + color.handle);
3405 //              COM.MoveMemory(pForeground, new int [] { color.handle }, 4);
3406 //              return COM.S_OK;
3407 //      }
3408 //
3409 //      /* IAccessibleComponent::get_background([out] pBackground) */
3410 //      int get_background(long pBackground) {
3411 //              Color color = control.getBackground();
3412 //              if (DEBUG) print(this + ".IAccessibleComponent::get_background returning " + color.handle);
3413 //              COM.MoveMemory(pBackground, new int [] { color.handle }, 4);
3414 //              return COM.S_OK;
3415 //      }
3416
3417         /* IAccessibleEditableText::copyText([in] startOffset, [in] endOffset) */
3418         int copyText(int startOffset, int endOffset) {
3419                 if (DEBUG) print(this + ".IAccessibleEditableText::copyText, start=" + startOffset + ", end=" + endOffset);
3420                 AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
3421                 event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
3422                 event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
3423                 for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
3424                         AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
3425                         listener.copyText(event);
3426                 }
3427                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
3428                 return COM.S_OK;
3429         }
3430
3431         /* IAccessibleEditableText::deleteText([in] startOffset, [in] endOffset) */
3432         int deleteText(int startOffset, int endOffset) {
3433                 if (DEBUG) print(this + ".IAccessibleEditableText::deleteText, start=" + startOffset + ", end=" + endOffset);
3434                 AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
3435                 event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
3436                 event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
3437                 event.string = "";
3438                 for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
3439                         AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
3440                         listener.replaceText(event);
3441                 }
3442                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
3443                 return COM.S_OK;
3444         }
3445
3446         /* IAccessibleEditableText::insertText([in] offset, [in] pbstrText) */
3447         int insertText(int offset, long pbstrText) {
3448                 if (DEBUG) print(this + ".IAccessibleEditableText::insertText, offset=" + offset + ", pbstrText=" + pbstrText);
3449                 AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
3450                 event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset;
3451                 event.end = event.start;
3452                 event.string = getString(pbstrText);
3453                 for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
3454                         AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
3455                         listener.replaceText(event);
3456                 }
3457                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
3458                 return COM.S_OK;
3459         }
3460
3461         /* IAccessibleEditableText::cutText([in] startOffset, [in] endOffset) */
3462         int cutText(int startOffset, int endOffset) {
3463                 if (DEBUG) print(this + ".IAccessibleEditableText::cutText, start=" + startOffset + ", end=" + endOffset);
3464                 AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
3465                 event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
3466                 event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
3467                 for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
3468                         AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
3469                         listener.cutText(event);
3470                 }
3471                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
3472                 return COM.S_OK;
3473         }
3474
3475         /* IAccessibleEditableText::pasteText([in] offset) */
3476         int pasteText(int offset) {
3477                 if (DEBUG) print(this + ".IAccessibleEditableText::pasteText, offset=" + offset);
3478                 AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
3479                 event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset;
3480                 event.end = event.start;
3481                 for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
3482                         AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
3483                         listener.pasteText(event);
3484                 }
3485                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
3486                 return COM.S_OK;
3487         }
3488
3489         /* IAccessibleEditableText::replaceText([in] startOffset, [in] endOffset, [in] pbstrText) */
3490         int replaceText(int startOffset, int endOffset, long pbstrText) {
3491                 if (DEBUG) print(this + ".IAccessibleEditableText::replaceText, start=" + startOffset + ", end=" + endOffset + ", pbstrText=" + pbstrText);
3492                 AccessibleEditableTextEvent event = new AccessibleEditableTextEvent(this);
3493                 event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
3494                 event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
3495                 event.string = getString(pbstrText);
3496                 for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
3497                         AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
3498                         listener.replaceText(event);
3499                 }
3500                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
3501                 return COM.S_OK;
3502         }
3503
3504         /* IAccessibleEditableText::setAttributes([in] startOffset, [in] endOffset, [in] pbstrAttributes) */
3505         int setAttributes(int startOffset, int endOffset, long pbstrAttributes) {
3506                 if (DEBUG) print(this + ".IAccessibleEditableText::setAttributes, start=" + startOffset + ", end=" + endOffset + ", pbstrAttributes=" + pbstrAttributes);
3507                 AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(this);
3508                 String string = getString(pbstrAttributes);
3509                 if (string != null && string.length() > 0) {
3510                         event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
3511                         event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
3512                         TextStyle style = new TextStyle();
3513                         FontData fontData = null;
3514                         int points = 10; // used for default rise
3515                         String [] attributes = new String [0];
3516                         int begin = 0;
3517                         int end = string.indexOf(';');
3518                         while (end != -1 && end < string.length()) {
3519                                 String keyValue = string.substring(begin, end).trim();
3520                                 int colonIndex = keyValue.indexOf(':');
3521                                 if (colonIndex != -1 && colonIndex + 1 < keyValue.length()) {
3522                                         String [] newAttributes = new String [attributes.length + 2];
3523                                         System.arraycopy (attributes, 0, newAttributes, 0, attributes.length);
3524                                         newAttributes[attributes.length] = keyValue.substring(0, colonIndex).trim();
3525                                         newAttributes[attributes.length + 1] = keyValue.substring(colonIndex + 1).trim();
3526                                         attributes = newAttributes;
3527                                 }
3528                                 begin = end + 1;
3529                                 end = string.indexOf(';', begin);
3530                         }
3531                         for (int i = 0; i+1 < attributes.length; i+=2) {
3532                                 String key = attributes[i];
3533                                 String value = attributes[i+1];
3534                                 if (key.equals("text-position")) {
3535                                         if (value.equals("super")) style.rise = points / 2;
3536                                         else if (value.equals("sub")) style.rise = - points / 2;
3537                                 } else if (key.equals("text-underline-type")) {
3538                                         style.underline = true;
3539                                         if (value.equals("double")) style.underlineStyle = SWT.UNDERLINE_DOUBLE;
3540                                         else if (value.equals("single")) {
3541                                                 if (style.underlineStyle != SWT.UNDERLINE_SQUIGGLE && style.underlineStyle != SWT.UNDERLINE_ERROR) {
3542                                                         style.underlineStyle = SWT.UNDERLINE_SINGLE;
3543                                                 }
3544                                         }
3545                                 } else if (key.equals("text-underline-style") && value.equals("wave")) {
3546                                         style.underline = true;
3547                                         style.underlineStyle = SWT.UNDERLINE_SQUIGGLE;
3548                                 } else if (key.equals("invalid") && value.equals("true")) {
3549                                         style.underline = true;
3550                                         style.underlineStyle = SWT.UNDERLINE_ERROR;
3551                                 } else if (key.equals("text-line-through-type")) {
3552                                         if (value.equals("single")) style.strikeout = true;
3553                                 } else if (key.equals("font-family")) {
3554                                         if (fontData == null) fontData = new FontData ();
3555                                         fontData.setName(value);
3556                                 } else if (key.equals("font-size")) {
3557                                         try {
3558                                                 String pts = value.endsWith("pt") ? value.substring(0, value.length() - 2) : value;
3559                                                 points = Integer.parseInt(pts);
3560                                                 if (fontData == null) fontData = new FontData ();
3561                                                 fontData.setHeight(points);
3562                                                 if (style.rise > 0) style.rise = points / 2;
3563                                                 else if (style.rise < 0) style.rise = - points / 2;
3564                                         } catch (NumberFormatException ex) {}
3565                                 } else if (key.equals("font-style")) {
3566                                         if (value.equals("italic")) {
3567                                                 if (fontData == null) fontData = new FontData ();
3568                                                 fontData.setStyle(fontData.getStyle() | SWT.ITALIC);
3569                                         }
3570                                 } else if (key.equals("font-weight")) {
3571                                         if (value.equals("bold")) {
3572                                                 if (fontData == null) fontData = new FontData ();
3573                                                 fontData.setStyle(fontData.getStyle() | SWT.BOLD);
3574                                         } else {
3575                                                 try {
3576                                                         int weight = Integer.parseInt(value);
3577                                                         if (fontData == null) fontData = new FontData ();
3578                                                         if (weight > 400) fontData.setStyle(fontData.getStyle() | SWT.BOLD);
3579                                                 } catch (NumberFormatException ex) {}
3580                                         }
3581                                 } else if (key.equals("color")) {
3582                                         style.foreground = colorFromString(value);
3583                                 } else if (key.equals("background-color")) {
3584                                         style.background = colorFromString(value);
3585                                 }
3586                         }
3587                         if (attributes.length > 0) {
3588                                 event.attributes = attributes;
3589                                 if (fontData != null) {
3590                                         style.font = new Font(control.getDisplay(), fontData);
3591                                 }
3592                                 if (!style.equals(new TextStyle())) event.textStyle = style;
3593                         }
3594                         for (int i = 0; i < accessibleEditableTextListenersSize(); i++) {
3595                                 AccessibleEditableTextListener listener = accessibleEditableTextListeners.get(i);
3596                                 listener.setTextAttributes(event);
3597                         }
3598                         if (style.font != null) {
3599                                 style.font.dispose();
3600                         }
3601                         if (style.foreground != null) {
3602                                 style.foreground.dispose();
3603                         }
3604                         if (style.background != null) {
3605                                 style.background.dispose();
3606                         }
3607                 }
3608                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
3609                 return COM.S_OK;
3610         }
3611
3612         /* IAccessibleHyperlink::get_anchor([in] index, [out] pAnchor) */
3613         int get_anchor(int index, long pAnchor) {
3614                 if (DEBUG) print(this + ".IAccessibleHyperlink::get_anchor");
3615                 AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this);
3616                 event.index = index;
3617                 for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) {
3618                         AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i);
3619                         listener.getAnchor(event);
3620                 }
3621                 Accessible accessible = event.accessible;
3622                 if (accessible != null) {
3623                         accessible.AddRef();
3624                         setPtrVARIANT(pAnchor, COM.VT_DISPATCH, accessible.getAddress());
3625                         return COM.S_OK;
3626                 }
3627                 setStringVARIANT(pAnchor, event.result);
3628                 if (event.result == null) return COM.S_FALSE;
3629                 return COM.S_OK;
3630         }
3631
3632         /* IAccessibleHyperlink::get_anchorTarget([in] index, [out] pAnchorTarget) */
3633         int get_anchorTarget(int index, long pAnchorTarget) {
3634                 if (DEBUG) print(this + ".IAccessibleHyperlink::get_anchorTarget");
3635                 AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this);
3636                 event.index = index;
3637                 for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) {
3638                         AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i);
3639                         listener.getAnchorTarget(event);
3640                 }
3641                 Accessible accessible = event.accessible;
3642                 if (accessible != null) {
3643                         accessible.AddRef();
3644                         setPtrVARIANT(pAnchorTarget, COM.VT_DISPATCH, accessible.getAddress());
3645                         return COM.S_OK;
3646                 }
3647                 setStringVARIANT(pAnchorTarget, event.result);
3648                 if (event.result == null) return COM.S_FALSE;
3649                 return COM.S_OK;
3650         }
3651
3652         /* IAccessibleHyperlink::get_startIndex([out] pIndex) */
3653         int get_startIndex(long pIndex) {
3654                 if (DEBUG) print(this + ".IAccessibleHyperlink::get_startIndex");
3655                 AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this);
3656                 for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) {
3657                         AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i);
3658                         listener.getStartIndex(event);
3659                 }
3660                 OS.MoveMemory(pIndex, new int [] { event.index }, 4);
3661                 return COM.S_OK;
3662         }
3663
3664         /* IAccessibleHyperlink::get_endIndex([out] pIndex) */
3665         int get_endIndex(long pIndex) {
3666                 if (DEBUG) print(this + ".IAccessibleHyperlink::get_endIndex");
3667                 AccessibleHyperlinkEvent event = new AccessibleHyperlinkEvent(this);
3668                 for (int i = 0; i < accessibleHyperlinkListenersSize(); i++) {
3669                         AccessibleHyperlinkListener listener = accessibleHyperlinkListeners.get(i);
3670                         listener.getEndIndex(event);
3671                 }
3672                 OS.MoveMemory(pIndex, new int [] { event.index }, 4);
3673                 return COM.S_OK;
3674         }
3675
3676         /* IAccessibleHyperlink::get_valid([out] pValid) */
3677         int get_valid(long pValid) {
3678                 /* Deprecated. */
3679                 return COM.E_NOTIMPL;
3680         }
3681
3682         /* IAccessibleHypertext::get_nHyperlinks([out] pHyperlinkCount) */
3683         int get_nHyperlinks(long pHyperlinkCount) {
3684                 if (DEBUG) print(this + ".IAccessibleHypertext::get_nHyperlinks");
3685                 AccessibleTextEvent event = new AccessibleTextEvent(this);
3686                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
3687                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
3688                         listener.getHyperlinkCount(event);
3689                 }
3690                 OS.MoveMemory(pHyperlinkCount, new int [] { event.count }, 4);
3691                 return COM.S_OK;
3692         }
3693
3694         /* IAccessibleHypertext::get_hyperlink([in] index, [out] ppHyperlink) */
3695         int get_hyperlink(int index, long ppHyperlink) {
3696                 if (DEBUG) print(this + ".IAccessibleHypertext::get_hyperlink");
3697                 AccessibleTextEvent event = new AccessibleTextEvent(this);
3698                 event.index = index;
3699                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
3700                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
3701                         listener.getHyperlink(event);
3702                 }
3703                 Accessible accessible = event.accessible;
3704                 if (accessible == null) {
3705                         setIntVARIANT(ppHyperlink, COM.VT_EMPTY, 0);
3706                         return COM.E_INVALIDARG;
3707                 }
3708                 accessible.AddRef();
3709                 OS.MoveMemory(ppHyperlink, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
3710                 return COM.S_OK;
3711         }
3712
3713         /* IAccessibleHypertext::get_hyperlinkIndex([in] charIndex, [out] pHyperlinkIndex) */
3714         int get_hyperlinkIndex(int charIndex, long pHyperlinkIndex) {
3715                 if (DEBUG) print(this + ".IAccessibleHypertext::get_hyperlinkIndex");
3716                 AccessibleTextEvent event = new AccessibleTextEvent(this);
3717                 event.offset = charIndex;
3718                 event.index = -1;
3719                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
3720                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
3721                         listener.getHyperlinkIndex(event);
3722                 }
3723                 OS.MoveMemory(pHyperlinkIndex, new int [] { event.index }, 4);
3724                 if (event.index == -1) return COM.S_FALSE;
3725                 return COM.S_OK;
3726         }
3727
3728         // The following 3 method are intentionally commented. We are not providing IAccessibleImage at this time.
3729 //      /* IAccessibleImage::get_description([out] pbstrDescription) */
3730 //      int get_description(long pbstrDescription) {
3731 //              if (DEBUG) print(this + ".IAccessibleImage::get_description");
3732 //              // TO DO: Does it make sense to just reuse description?
3733 //              AccessibleEvent event = new AccessibleEvent(this);
3734 //              event.childID = ACC.CHILDID_SELF;
3735 //              for (int i = 0; i < accessibleListenersSize(); i++) {
3736 //                      AccessibleListener listener = (AccessibleListener) accessibleListeners.get(i);
3737 //                      listener.getDescription(event);
3738 //              }
3739 //              setString(pbstrDescription, event.result);
3740 //              if (event.result == null) return COM.S_FALSE;
3741 //              return COM.S_OK;
3742 //      }
3743 //
3744 //      /* IAccessibleImage::get_imagePosition([in] coordinateType, [out] pX, [out] pY) */
3745 //      int get_imagePosition(int coordinateType, long pX, long pY) {
3746 //              if (DEBUG) print(this + ".IAccessibleImage::get_imagePosition");
3747 //              // TO DO: does it make sense to just reuse getLocation?
3748 //              AccessibleControlEvent event = new AccessibleControlEvent(this);
3749 //              event.childID = ACC.CHILDID_SELF;
3750 //              for (int i = 0; i < accessibleControlListenersSize(); i++) {
3751 //                      AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i);
3752 //                      listener.getLocation(event);
3753 //              }
3754 //              COM.MoveMemory(pX, new int [] { event.x }, 4);
3755 //              COM.MoveMemory(pY, new int [] { event.y }, 4);
3756 //              return COM.S_OK;
3757 //      }
3758 //
3759 //      /* IAccessibleImage::get_imageSize([out] pHeight, [out] pWidth) */
3760 //      int get_imageSize(long pHeight, long pWidth) {
3761 //              if (DEBUG) print(this + ".IAccessibleImage::get_imageSize");
3762 //              // TO DO: does it make sense to just reuse getLocation?
3763 //              AccessibleControlEvent event = new AccessibleControlEvent(this);
3764 //              for (int i = 0; i < accessibleControlListenersSize(); i++) {
3765 //                      AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.get(i);
3766 //                      listener.getLocation(event);
3767 //              }
3768 //              COM.MoveMemory(pHeight, new int [] { event.height }, 4);
3769 //              COM.MoveMemory(pWidth, new int [] { event.width }, 4);
3770 //              return COM.S_OK;
3771 //      }
3772
3773         /* IAccessibleTable2::get_cellAt([in] row, [in] column, [out] ppCell) */
3774         int get_cellAt(int row, int column, long ppCell) {
3775                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3776                 event.row = row;
3777                 event.column = column;
3778                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3779                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3780                         listener.getCell(event);
3781                 }
3782                 Accessible accessible = event.accessible;
3783                 if (DEBUG) print(this + ".IAccessibleTable2::get_cellAt(row=" + row + ", column=" + column + ") returning " + accessible);
3784                 if (accessible == null) return COM.E_INVALIDARG;
3785                 accessible.AddRef();
3786                 OS.MoveMemory(ppCell, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
3787                 return COM.S_OK;
3788         }
3789
3790         /* IAccessibleTable2::get_caption([out] ppAccessible) */
3791         int get_caption(long ppAccessible) {
3792                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3793                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3794                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3795                         listener.getCaption(event);
3796                 }
3797                 Accessible accessible = event.accessible;
3798                 if (DEBUG) print(this + ".IAccessibleTable2::get_caption() returning " + accessible);
3799                 if (accessible == null) {
3800                         OS.MoveMemory(ppAccessible, new long[] { 0 }, C.PTR_SIZEOF);
3801                         return COM.S_FALSE;
3802                 }
3803                 accessible.AddRef();
3804                 OS.MoveMemory(ppAccessible, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
3805                 return COM.S_OK;
3806         }
3807
3808         /* IAccessibleTable2::get_columnDescription([in] column, [out] pbstrDescription) */
3809         int get_columnDescription(int column, long pbstrDescription) {
3810                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3811                 event.column = column;
3812                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3813                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3814                         listener.getColumnDescription(event);
3815                 }
3816                 if (DEBUG) print(this + ".IAccessibleTable2::get_columnDescription(column=" + column + ") returning " + event.result);
3817                 setString(pbstrDescription, event.result);
3818                 if (event.result == null) return COM.S_FALSE;
3819                 return COM.S_OK;
3820         }
3821
3822         /* IAccessibleTable2::get_nColumns([out] pColumnCount) */
3823         int get_nColumns(long pColumnCount) {
3824                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3825                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3826                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3827                         listener.getColumnCount(event);
3828                 }
3829                 if (DEBUG) print(this + ".IAccessibleTable2::get_nColumns() returning " + event.count);
3830                 OS.MoveMemory(pColumnCount, new int [] { event.count }, 4);
3831                 return COM.S_OK;
3832         }
3833
3834         /* IAccessibleTable2::get_nRows([out] pRowCount) */
3835         int get_nRows(long pRowCount) {
3836                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3837                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3838                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3839                         listener.getRowCount(event);
3840                 }
3841                 if (DEBUG) print(this + ".IAccessibleTable2::get_nRows() returning " + event.count);
3842                 OS.MoveMemory(pRowCount, new int [] { event.count }, 4);
3843                 return COM.S_OK;
3844         }
3845
3846         /* IAccessibleTable2::get_nSelectedCells([out] pCellCount) */
3847         int get_nSelectedCells(long pCellCount) {
3848                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3849                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3850                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3851                         listener.getSelectedCellCount(event);
3852                 }
3853                 if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedCells() returning " + event.count);
3854                 OS.MoveMemory(pCellCount, new int [] { event.count }, 4);
3855                 return COM.S_OK;
3856         }
3857
3858         /* IAccessibleTable2::get_nSelectedColumns([out] pColumnCount) */
3859         int get_nSelectedColumns(long pColumnCount) {
3860                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3861                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3862                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3863                         listener.getSelectedColumnCount(event);
3864                 }
3865                 if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedColumns() returning " + event.count);
3866                 OS.MoveMemory(pColumnCount, new int [] { event.count }, 4);
3867                 return COM.S_OK;
3868         }
3869
3870         /* IAccessibleTable2::get_nSelectedRows([out] pRowCount) */
3871         int get_nSelectedRows(long pRowCount) {
3872                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3873                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3874                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3875                         listener.getSelectedRowCount(event);
3876                 }
3877                 if (DEBUG) print(this + ".IAccessibleTable2::get_nSelectedRows() returning " + event.count);
3878                 OS.MoveMemory(pRowCount, new int [] { event.count }, 4);
3879                 return COM.S_OK;
3880         }
3881
3882         /* IAccessibleTable2::get_rowDescription([in] row, [out] pbstrDescription) */
3883         int get_rowDescription(int row, long pbstrDescription) {
3884                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3885                 event.row = row;
3886                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3887                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3888                         listener.getRowDescription(event);
3889                 }
3890                 if (DEBUG) print(this + ".IAccessibleTable2::get_rowDescription(row=" + row + ") returning " + event.result);
3891                 setString(pbstrDescription, event.result);
3892                 if (event.result == null) return COM.S_FALSE;
3893                 return COM.S_OK;
3894         }
3895
3896         /* IAccessibleTable2::get_selectedCells([out] ppCells, [out] pNSelectedCells) */
3897         int get_selectedCells(long ppCells, long pNSelectedCells) {
3898                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3899                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3900                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3901                         listener.getSelectedCells(event);
3902                 }
3903                 if (DEBUG) print(this + ".IAccessibleTable2::get_selectedCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]"));
3904                 if (event.accessibles == null || event.accessibles.length == 0) {
3905                         OS.MoveMemory(ppCells, new long[] { 0 }, C.PTR_SIZEOF);
3906                         OS.MoveMemory(pNSelectedCells, new int [] { 0 }, 4);
3907                         return COM.S_FALSE;
3908                 }
3909                 int length = event.accessibles.length;
3910                 long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF);
3911                 int count = 0;
3912                 for (int i = 0; i < length; i++) {
3913                         Accessible accessible = event.accessibles[i];
3914                         if (accessible != null) {
3915                                 accessible.AddRef();
3916                                 OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
3917                                 count++;
3918                         }
3919                 }
3920                 OS.MoveMemory(ppCells, new long [] { pv }, C.PTR_SIZEOF);
3921                 OS.MoveMemory(pNSelectedCells, new int [] { count }, 4);
3922                 return COM.S_OK;
3923         }
3924
3925         /* IAccessibleTable2::get_selectedColumns([out] ppSelectedColumns, [out] pNColumns) */
3926         int get_selectedColumns(long ppSelectedColumns, long pNColumns) {
3927                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3928                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3929                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3930                         listener.getSelectedColumns(event);
3931                 }
3932                 int count = event.selected == null ? 0 : event.selected.length;
3933                 if (DEBUG) print(this + ".IAccessibleTable2::get_selectedColumns() returning " + (count == 0 ? "null" : "selected[" + count + "]"));
3934                 if (count == 0) {
3935                         OS.MoveMemory(ppSelectedColumns, new long[] { 0 }, C.PTR_SIZEOF);
3936                         OS.MoveMemory(pNColumns, new int [] { 0 }, 4);
3937                         return COM.S_FALSE;
3938                 }
3939                 long pv = OS.CoTaskMemAlloc(count * 4);
3940                 OS.MoveMemory(pv, event.selected, count * 4);
3941                 OS.MoveMemory(ppSelectedColumns, new long [] { pv }, C.PTR_SIZEOF);
3942                 OS.MoveMemory(pNColumns, new int [] { count }, 4);
3943                 return COM.S_OK;
3944         }
3945
3946         /* IAccessibleTable2::get_selectedRows([out] ppSelectedRows, [out] pNRows) */
3947         int get_selectedRows(long ppSelectedRows, long pNRows) {
3948                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3949                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3950                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3951                         listener.getSelectedRows(event);
3952                 }
3953                 int count = event.selected == null ? 0 : event.selected.length;
3954                 if (DEBUG) print(this + ".IAccessibleTable2::get_selectedRows() returning " + (count == 0 ? "null" : "selected[" + count + "]"));
3955                 if (count == 0) {
3956                         OS.MoveMemory(ppSelectedRows, new long[] { 0 }, C.PTR_SIZEOF);
3957                         OS.MoveMemory(pNRows, new int [] { 0 }, 4);
3958                         return COM.S_FALSE;
3959                 }
3960                 long pv = OS.CoTaskMemAlloc(count * 4);
3961                 OS.MoveMemory(pv, event.selected, count * 4);
3962                 OS.MoveMemory(ppSelectedRows, new long [] { pv }, C.PTR_SIZEOF);
3963                 OS.MoveMemory(pNRows, new int [] { count }, 4);
3964                 return COM.S_OK;
3965         }
3966
3967         /* IAccessibleTable2::get_summary([out] ppAccessible) */
3968         int get_summary(long ppAccessible) {
3969                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3970                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3971                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3972                         listener.getSummary(event);
3973                 }
3974                 Accessible accessible = event.accessible;
3975                 if (DEBUG) print(this + ".IAccessibleTable2::get_summary() returning " + accessible);
3976                 if (accessible == null) {
3977                         OS.MoveMemory(ppAccessible, new long[] { 0 }, C.PTR_SIZEOF);
3978                         return COM.S_FALSE;
3979                 }
3980                 accessible.AddRef();
3981                 OS.MoveMemory(ppAccessible, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
3982                 return COM.S_OK;
3983         }
3984
3985         /* IAccessibleTable2::get_isColumnSelected([in] column, [out] pIsSelected) */
3986         int get_isColumnSelected(int column, long pIsSelected) {
3987                 AccessibleTableEvent event = new AccessibleTableEvent(this);
3988                 event.column = column;
3989                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
3990                         AccessibleTableListener listener = accessibleTableListeners.get(i);
3991                         listener.isColumnSelected(event);
3992                 }
3993                 if (DEBUG) print(this + ".IAccessibleTable2::get_isColumnSelected() returning " + event.isSelected);
3994                 OS.MoveMemory(pIsSelected, new int [] {event.isSelected ? 1 : 0}, 4);
3995                 return COM.S_OK;
3996         }
3997
3998         /* IAccessibleTable2::get_isRowSelected([in] row, [out] pIsSelected) */
3999         int get_isRowSelected(int row, long pIsSelected) {
4000                 AccessibleTableEvent event = new AccessibleTableEvent(this);
4001                 event.row = row;
4002                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
4003                         AccessibleTableListener listener = accessibleTableListeners.get(i);
4004                         listener.isRowSelected(event);
4005                 }
4006                 if (DEBUG) print(this + ".IAccessibleTable2::get_isRowSelected() returning " + event.isSelected);
4007                 OS.MoveMemory(pIsSelected, new int [] {event.isSelected ? 1 : 0}, 4);
4008                 return COM.S_OK;
4009         }
4010
4011         /* IAccessibleTable2::selectRow([in] row) */
4012         int selectRow(int row) {
4013                 AccessibleTableEvent event = new AccessibleTableEvent(this);
4014                 event.row = row;
4015                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
4016                         AccessibleTableListener listener = accessibleTableListeners.get(i);
4017                         listener.setSelectedRow(event);
4018                 }
4019                 if (DEBUG) print(this + ".IAccessibleTable2::selectRow() returning " + (event.result == null ? "E_INVALIDARG" : event.result));
4020                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
4021                 return COM.S_OK;
4022         }
4023
4024         /* IAccessibleTable2::selectColumn([in] column) */
4025         int selectColumn(int column) {
4026                 AccessibleTableEvent event = new AccessibleTableEvent(this);
4027                 event.column = column;
4028                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
4029                         AccessibleTableListener listener = accessibleTableListeners.get(i);
4030                         listener.setSelectedColumn(event);
4031                 }
4032                 if (DEBUG) print(this + ".IAccessibleTable2::selectColumn() returning " + (event.result == null ? "E_INVALIDARG" : event.result));
4033                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
4034                 return COM.S_OK;
4035         }
4036
4037         /* IAccessibleTable2::unselectRow([in] row) */
4038         int unselectRow(int row) {
4039                 AccessibleTableEvent event = new AccessibleTableEvent(this);
4040                 event.row = row;
4041                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
4042                         AccessibleTableListener listener = accessibleTableListeners.get(i);
4043                         listener.deselectRow(event);
4044                 }
4045                 if (DEBUG) print(this + ".IAccessibleTable2::unselectRow() returning " + (event.result == null ? "E_INVALIDARG" : event.result));
4046                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
4047                 return COM.S_OK;
4048         }
4049
4050         /* IAccessibleTable2::unselectColumn([in] column) */
4051         int unselectColumn(int column) {
4052                 AccessibleTableEvent event = new AccessibleTableEvent(this);
4053                 event.column = column;
4054                 for (int i = 0; i < accessibleTableListenersSize(); i++) {
4055                         AccessibleTableListener listener = accessibleTableListeners.get(i);
4056                         listener.deselectColumn(event);
4057                 }
4058                 if (DEBUG) print(this + ".IAccessibleTable2::unselectColumn() returning " + (event.result == null ? "E_INVALIDARG" : event.result));
4059                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
4060                 return COM.S_OK;
4061         }
4062
4063         /* IAccessibleTable2::get_modelChange([out] pModelChange) */
4064         int get_modelChange(long pModelChange) {
4065                 if (DEBUG) print(this + ".IAccessibleTable2::get_modelChange() returning " + (tableChange == null ? "null" : "tableChange=" + tableChange[0] + ", " + tableChange[1] + ", " + tableChange[2] + ", " + tableChange[3]));
4066                 if (tableChange == null) {
4067                         OS.MoveMemory(pModelChange, new long [] { 0 }, C.PTR_SIZEOF);
4068                         return COM.S_FALSE;
4069                 }
4070                 OS.MoveMemory(pModelChange, tableChange, tableChange.length * 4);
4071                 return COM.S_OK;
4072         }
4073
4074         /* IAccessibleTableCell::get_columnExtent([out] pNColumnsSpanned) */
4075         int get_columnExtent(long pNColumnsSpanned) {
4076                 AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4077                 for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4078                         AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
4079                         listener.getColumnSpan(event);
4080                 }
4081                 if (DEBUG) print(this + ".IAccessibleTableCell::get_columnExtent() returning " + event.count);
4082                 OS.MoveMemory(pNColumnsSpanned, new int [] { event.count }, 4);
4083                 return COM.S_OK;
4084         }
4085
4086         /* IAccessibleTableCell::get_columnHeaderCells([out] ppCellAccessibles, [out] pNColumnHeaderCells) */
4087         int get_columnHeaderCells(long ppCellAccessibles, long pNColumnHeaderCells) {
4088                 AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4089                 for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4090                         AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
4091                         listener.getColumnHeaders(event);
4092                 }
4093                 if (DEBUG) print(this + ".IAccessibleTableCell::get_columnHeaderCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]"));
4094                 if (event.accessibles == null || event.accessibles.length == 0) {
4095                         OS.MoveMemory(ppCellAccessibles, new long[] { 0 }, C.PTR_SIZEOF);
4096                         OS.MoveMemory(pNColumnHeaderCells, new int [] { 0 }, 4);
4097                         return COM.S_FALSE;
4098                 }
4099                 int length = event.accessibles.length;
4100                 long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF);
4101                 int count = 0;
4102                 for (int i = 0; i < length; i++) {
4103                         Accessible accessible = event.accessibles[i];
4104                         if (accessible != null) {
4105                                 accessible.AddRef();
4106                                 OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
4107                                 count++;
4108                         }
4109                 }
4110                 OS.MoveMemory(ppCellAccessibles, new long [] { pv }, C.PTR_SIZEOF);
4111                 OS.MoveMemory(pNColumnHeaderCells, new int [] { count }, 4);
4112                 return COM.S_OK;
4113         }
4114
4115         /* IAccessibleTableCell::get_columnIndex([out] pColumnIndex) */
4116         int get_columnIndex(long pColumnIndex) {
4117                 AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4118                 for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4119                         AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
4120                         listener.getColumnIndex(event);
4121                 }
4122                 if (DEBUG) print(this + ".IAccessibleTableCell::get_columnIndex() returning " + event.index);
4123                 OS.MoveMemory(pColumnIndex, new int [] { event.index }, 4);
4124                 return COM.S_OK;
4125         }
4126
4127         /* IAccessibleTableCell::get_rowExtent([out] pNRowsSpanned) */
4128         int get_rowExtent(long pNRowsSpanned) {
4129                 AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4130                 for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4131                         AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
4132                         listener.getRowSpan(event);
4133                 }
4134                 if (DEBUG) print(this + ".IAccessibleTableCell::get_rowExtent() returning " + event.count);
4135                 OS.MoveMemory(pNRowsSpanned, new int [] { event.count }, 4);
4136                 return COM.S_OK;
4137         }
4138
4139         /* IAccessibleTableCell::get_rowHeaderCells([out] ppCellAccessibles, [out] pNRowHeaderCells) */
4140         int get_rowHeaderCells(long ppCellAccessibles, long pNRowHeaderCells) {
4141                 AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4142                 for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4143                         AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
4144                         listener.getRowHeaders(event);
4145                 }
4146                 if (DEBUG) print(this + ".IAccessibleTableCell::get_rowHeaderCells() returning " + (event.accessibles == null ? "null" : "accessibles[" + event.accessibles.length + "]"));
4147                 if (event.accessibles == null || event.accessibles.length == 0) {
4148                         OS.MoveMemory(ppCellAccessibles, new long[] { 0 }, C.PTR_SIZEOF);
4149                         OS.MoveMemory(pNRowHeaderCells, new int [] { 0 }, 4);
4150                         return COM.S_FALSE;
4151                 }
4152                 int length = event.accessibles.length;
4153                 long pv = OS.CoTaskMemAlloc(length * C.PTR_SIZEOF);
4154                 int count = 0;
4155                 for (int i = 0; i < length; i++) {
4156                         Accessible accessible = event.accessibles[i];
4157                         if (accessible != null) {
4158                                 accessible.AddRef();
4159                                 OS.MoveMemory(pv + i * C.PTR_SIZEOF, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
4160                                 count++;
4161                         }
4162                 }
4163                 OS.MoveMemory(ppCellAccessibles, new long [] { pv }, C.PTR_SIZEOF);
4164                 OS.MoveMemory(pNRowHeaderCells, new int [] { count }, 4);
4165                 return COM.S_OK;
4166         }
4167
4168         /* IAccessibleTableCell::get_rowIndex([out] pRowIndex) */
4169         int get_rowIndex(long pRowIndex) {
4170                 AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4171                 for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4172                         AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
4173                         listener.getRowIndex(event);
4174                 }
4175                 if (DEBUG) print(this + ".IAccessibleTableCell::get_rowIndex() returning " + event.index);
4176                 OS.MoveMemory(pRowIndex, new int [] { event.index }, 4);
4177                 return COM.S_OK;
4178         }
4179
4180         /* IAccessibleTableCell::get_isSelected([out] pIsSelected) */
4181         int get_isSelected(long pIsSelected) {
4182                 AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4183                 for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4184                         AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
4185                         listener.isSelected(event);
4186                 }
4187                 if (DEBUG) print(this + ".IAccessibleTableCell::get_isSelected() returning " + event.isSelected);
4188                 OS.MoveMemory(pIsSelected, new int [] {event.isSelected ? 1 : 0}, 4);
4189                 return COM.S_OK;
4190         }
4191
4192         /* IAccessibleTableCell::get_rowColumnExtents([out] pRow, [out] pColumn, [out] pRowExtents, [out] pColumnExtents, [out] pIsSelected) */
4193         int get_rowColumnExtents(long pRow, long pColumn, long pRowExtents, long pColumnExtents, long pIsSelected) {
4194                 if (DEBUG) print(this + ".IAccessibleTableCell::get_rowColumnExtents");
4195                 // TODO: should we implement this? It is just a convenience function.
4196                 return COM.DISP_E_MEMBERNOTFOUND;
4197 //              AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4198 //              for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4199 //                      AccessibleTableCellListener listener = (AccessibleTableCellListener) accessibleTableCellListeners.get(i);
4200 //                      listener.getRowColumnExtents(event);
4201 //              }
4202 //              COM.MoveMemory(pRow, new int [] { event.row }, 4);
4203 //              COM.MoveMemory(pColumn, new int [] { event.column }, 4);
4204 //              COM.MoveMemory(pRowExtents, new int [] { event.rowExtents }, 4);
4205 //              COM.MoveMemory(pColumnExtents, new int [] { event.columnExtents }, 4);
4206 //              return COM.S_OK;
4207         }
4208
4209         /* IAccessibleTableCell::get_table([out] ppTable) */
4210         int get_table(long ppTable) {
4211                 AccessibleTableCellEvent event = new AccessibleTableCellEvent(this);
4212                 for (int i = 0; i < accessibleTableCellListenersSize(); i++) {
4213                         AccessibleTableCellListener listener = accessibleTableCellListeners.get(i);
4214                         listener.getTable(event);
4215                 }
4216                 Accessible accessible = event.accessible;
4217                 if (DEBUG) print(this + ".IAccessibleTableCell::get_table() returning " + accessible);
4218                 if (accessible == null) {
4219                         // TODO: This is not supposed to return S_FALSE. We need to lookup the table role parent and return that.
4220                         OS.MoveMemory(ppTable, new long[] { 0 }, C.PTR_SIZEOF);
4221                         return COM.S_FALSE;
4222                 }
4223                 accessible.AddRef();
4224                 OS.MoveMemory(ppTable, new long[] { accessible.getAddress() }, C.PTR_SIZEOF);
4225                 return COM.S_OK;
4226         }
4227
4228         /* IAccessibleText::addSelection([in] startOffset, [in] endOffset) */
4229         int addSelection(int startOffset, int endOffset) {
4230                 if (DEBUG) print(this + ".IAccessibleText::addSelection(" + startOffset + ", " + endOffset + ")");
4231                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4232                 event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
4233                 event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
4234                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4235                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4236                         listener.addSelection(event);
4237                 }
4238                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
4239                 return COM.S_OK;
4240         }
4241
4242         /* IAccessibleText::get_attributes([in] offset, [out] pStartOffset, [out] pEndOffset, [out] pbstrTextAttributes) */
4243         int get_attributes(int offset, long pStartOffset, long pEndOffset, long pbstrTextAttributes) {
4244                 AccessibleTextAttributeEvent event = new AccessibleTextAttributeEvent(this);
4245                 event.offset = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset;
4246                 for (int i = 0; i < accessibleAttributeListenersSize(); i++) {
4247                         AccessibleAttributeListener listener = accessibleAttributeListeners.get(i);
4248                         listener.getTextAttributes(event);
4249                 }
4250                 String textAttributes = "";
4251                 TextStyle style = event.textStyle;
4252                 if (style != null) {
4253                         if (style.rise != 0) {
4254                                 textAttributes += "text-position:";
4255                                 if (style.rise > 0) textAttributes += "super";
4256                                 else textAttributes += "sub";
4257                         }
4258                         if (style.underline) {
4259                                 textAttributes += "text-underline-type:";
4260                                 switch (style.underlineStyle) {
4261                                         case SWT.UNDERLINE_SINGLE: textAttributes += "single;"; break;
4262                                         case SWT.UNDERLINE_DOUBLE: textAttributes += "double;"; break;
4263                                         case SWT.UNDERLINE_SQUIGGLE: textAttributes += "single;text-underline-style:wave;"; break;
4264                                         case SWT.UNDERLINE_ERROR: textAttributes += "single;text-underline-style:wave;invalid:true;"; break;
4265                                         default: textAttributes += "none;"; break;
4266                                 }
4267                                 // style.underlineColor is not currently part of the IA2 spec. If provided, it would be "text-underline-color:rgb(n,n,n);"
4268                         }
4269                         if (style.strikeout) {
4270                                 textAttributes += "text-line-through-type:single;";
4271                                 // style.strikeoutColor is not currently part of the IA2 spec. If provided, it would be "text-line-through-color:rgb(n,n,n);"
4272                         }
4273                         Font font = style.font;
4274                         if (font != null && !font.isDisposed()) {
4275                                 FontData fontData = font.getFontData()[0];
4276                                 textAttributes += "font-family:" + fontData.getName() + ";";
4277                                 textAttributes += "font-size:" + fontData.getHeight() + "pt;";
4278                                 textAttributes += "font-style:" + (fontData.data.lfItalic != 0 ? "italic" : "normal") + ";";
4279                                 textAttributes += "font-weight:" + fontData.data.lfWeight + ";";
4280                         }
4281                         Color color = style.foreground;
4282                         if (color != null && !color.isDisposed()) {
4283                                 textAttributes += "color:rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ");";
4284                         }
4285                         color = style.background;
4286                         if (color != null && !color.isDisposed()) {
4287                                 textAttributes += "background-color:rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ");";
4288                         }
4289                 }
4290                 if (event.attributes != null) {
4291                         for (int i = 0; i + 1 < event.attributes.length; i += 2) {
4292                                 textAttributes += event.attributes[i] + ":" + event.attributes[i+1] + ";";
4293                         }
4294                 }
4295                 if (DEBUG) print(this + ".IAccessibleText::get_attributes(" + offset + ") returning start = " + event.start + ", end = " + event.end + ", attributes = " + textAttributes);
4296                 OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
4297                 OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
4298                 setString(pbstrTextAttributes, textAttributes);
4299                 if (textAttributes.length() == 0) return COM.S_FALSE;
4300                 return COM.S_OK;
4301         }
4302
4303         /* IAccessibleText::get_caretOffset([out] pOffset) */
4304         int get_caretOffset(long pOffset) {
4305                 int offset = getCaretOffset();
4306                 if (DEBUG) print(this + ".IAccessibleText::get_caretOffset returning " + offset + hresult(offset == -1 ? COM.S_FALSE : COM.S_OK));
4307                 OS.MoveMemory(pOffset, new int [] { offset }, 4);
4308                 if (offset == -1) return COM.S_FALSE;
4309                 return COM.S_OK;
4310         }
4311
4312         /* IAccessibleText::get_characterExtents([in] offset, [in] coordType, [out] pX, [out] pY, [out] pWidth, [out] pHeight) */
4313         int get_characterExtents(int offset, int coordType, long pX, long pY, long pWidth, long pHeight) {
4314                 int length = getCharacterCount();
4315                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4316                 event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? length : offset < 0 ? 0 : offset;
4317                 event.end = offset == COM.IA2_TEXT_OFFSET_LENGTH || offset >= length ? length : offset + 1;
4318                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4319                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4320                         listener.getTextBounds(event);
4321                 }
4322                 /* Note: event.rectangles is not used here, because IAccessibleText::get_characterExtents is just for one character. */
4323                 if (DEBUG) print(this + ".IAccessibleText::get_characterExtents(" + offset + ") returning " + event.x + ", " + event.y + ", " + event.width + ", " + event.height);
4324                 OS.MoveMemory(pX, new int [] { event.x }, 4);
4325                 OS.MoveMemory(pY, new int [] { event.y }, 4);
4326                 OS.MoveMemory(pWidth, new int [] { event.width }, 4);
4327                 OS.MoveMemory(pHeight, new int [] { event.height }, 4);
4328                 if (event.width == 0 && event.height == 0) return COM.E_INVALIDARG;
4329                 return COM.S_OK;
4330         }
4331
4332         /* IAccessibleText::get_nSelections([out] pNSelections) */
4333         int get_nSelections(long pNSelections) {
4334                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4335                 event.count = -1;
4336                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4337                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4338                         listener.getSelectionCount(event);
4339                 }
4340                 if (event.count == -1) {
4341                         event.childID = ACC.CHILDID_SELF;
4342                         event.offset = -1;
4343                         event.length = 0;
4344                         for (int i = 0; i < accessibleTextListenersSize(); i++) {
4345                                 AccessibleTextListener listener = accessibleTextListeners.get(i);
4346                                 listener.getSelectionRange (event);
4347                         }
4348                         event.count = event.offset != -1 && event.length > 0 ? 1 : 0;
4349                 }
4350                 if (DEBUG) print(this + ".IAccessibleText::get_nSelections returning " + event.count);
4351                 OS.MoveMemory(pNSelections, new int [] { event.count }, 4);
4352                 return COM.S_OK;
4353         }
4354
4355         /* IAccessibleText::get_offsetAtPoint([in] x, [in] y, [in] coordType, [out] pOffset) */
4356         int get_offsetAtPoint(int x, int y, int coordType, long pOffset) {
4357                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4358                 event.x = x;
4359                 event.y = y;
4360                 event.offset = -1;
4361                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4362                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4363                         listener.getOffsetAtPoint(event);
4364                 }
4365                 if (DEBUG) print(this + ".IAccessibleText::get_offsetAtPoint(" + x + ", " + y + ") returning " + event.offset + hresult(event.offset == -1 ? COM.S_FALSE : COM.S_OK));
4366                 /*
4367                  * Note that the current IA2 spec says to return 0 when there's nothing to return,
4368                  * but since 0 is a valid return value, the spec is going to be updated to return -1.
4369                  */
4370                 OS.MoveMemory(pOffset, new int [] { event.offset }, 4);
4371                 if (event.offset == -1) return COM.S_FALSE;
4372                 return COM.S_OK;
4373         }
4374
4375         /* IAccessibleText::get_selection([in] selectionIndex, [out] pStartOffset, [out] pEndOffset) */
4376         int get_selection(int selectionIndex, long pStartOffset, long pEndOffset) {
4377                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4378                 event.index = selectionIndex;
4379                 event.start = -1;
4380                 event.end = -1;
4381                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4382                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4383                         listener.getSelection(event);
4384                 }
4385                 if (event.start == -1 && selectionIndex == 0) {
4386                         event.childID = ACC.CHILDID_SELF;
4387                         event.offset = -1;
4388                         event.length = 0;
4389                         for (int i = 0; i < accessibleTextListenersSize(); i++) {
4390                                 AccessibleTextListener listener = accessibleTextListeners.get(i);
4391                                 listener.getSelectionRange (event);
4392                         }
4393                         event.start = event.offset;
4394                         event.end = event.offset + event.length;
4395                 }
4396                 if (DEBUG) print(this + ".IAccessibleText::get_selection(" + selectionIndex + ") returning " + event.start + ", " + event.end);
4397                 OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
4398                 OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
4399                 /*
4400                  * Note that the current IA2 spec says to return 0,0 when there's nothing to return,
4401                  * but since 0 is a valid return value, the spec is going to be updated to return -1,-1.
4402                  */
4403                 if (event.start == -1) return COM.S_FALSE;
4404                 return COM.S_OK;
4405         }
4406
4407         /* IAccessibleText::get_text([in] startOffset, [in] endOffset, [out] pbstrText) */
4408         int get_text(int startOffset, int endOffset, long pbstrText) {
4409                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4410                 event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
4411                 event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
4412                 if (event.start > event.end) {
4413                         /* IA2 spec says that indices can be exchanged. */
4414                         int temp = event.start;
4415                         event.start = event.end;
4416                         event.end = temp;
4417                 }
4418                 event.count = 0;
4419                 event.type = ACC.TEXT_BOUNDARY_ALL;
4420                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4421                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4422                         listener.getText(event);
4423                 }
4424                 if (event.result == null) {
4425                         AccessibleControlEvent e = new AccessibleControlEvent(this);
4426                         e.childID = ACC.CHILDID_SELF;
4427                         for (int i = 0; i < accessibleControlListenersSize(); i++) {
4428                                 AccessibleControlListener listener = accessibleControlListeners.get(i);
4429                                 listener.getRole(e);
4430                                 listener.getValue(e);
4431                         }
4432                         // TODO: Consider passing the value through for other roles as well (i.e. combo, etc). Keep in sync with get_nCharacters.
4433                         if (e.detail == ACC.ROLE_TEXT) {
4434                                 event.result = e.result;
4435                         }
4436                 }
4437                 if (DEBUG) print(this + ".IAccessibleText::get_text(" + startOffset + ", " + endOffset + ") returning " + event.result + hresult(event.result == null ? COM.E_INVALIDARG : COM.S_OK));
4438                 setString(pbstrText, event.result);
4439                 if (event.result == null) return COM.E_INVALIDARG;
4440                 return COM.S_OK;
4441         }
4442
4443         /* IAccessibleText::get_textBeforeOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */
4444         int get_textBeforeOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) {
4445                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4446                 int charCount = getCharacterCount();
4447                 event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset;
4448                 event.end = event.start;
4449                 event.count = -1;
4450                 switch (boundaryType) {
4451                         case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
4452                         case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break;
4453                         case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
4454                         case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break;
4455                         case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break;
4456                         default: return COM.E_INVALIDARG;
4457                 }
4458                 int eventStart = event.start;
4459                 int eventEnd = event.end;
4460                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4461                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4462                         listener.getText(event);
4463                 }
4464                 if (event.end < charCount) {
4465                         switch (boundaryType) {
4466                                 case COM.IA2_TEXT_BOUNDARY_WORD:
4467                                 case COM.IA2_TEXT_BOUNDARY_SENTENCE:
4468                                 case COM.IA2_TEXT_BOUNDARY_PARAGRAPH:
4469                                 case COM.IA2_TEXT_BOUNDARY_LINE:
4470                                         int start = event.start;
4471                                         event.start = eventStart;
4472                                         event.end = eventEnd;
4473                                         event.count = 0;
4474                                         for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4475                                                 AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4476                                                 listener.getText(event);
4477                                         }
4478                                         event.end = event.start;
4479                                         event.start = start;
4480                                         event.type = ACC.TEXT_BOUNDARY_ALL;
4481                                         event.count = 0;
4482                                         for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4483                                                 AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4484                                                 listener.getText(event);
4485                                         }
4486                         }
4487                 }
4488                 if (DEBUG) print(this + ".IAccessibleText::get_textBeforeOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK));
4489                 OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
4490                 OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
4491                 setString(pbstrText, event.result);
4492                 if (event.result == null) return COM.S_FALSE;
4493                 return COM.S_OK;
4494         }
4495
4496         /* IAccessibleText::get_textAfterOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */
4497         int get_textAfterOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) {
4498                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4499                 int charCount = getCharacterCount();
4500                 event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset;
4501                 event.end = event.start;
4502                 event.count = 1;
4503                 switch (boundaryType) {
4504                         case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
4505                         case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break;
4506                         case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
4507                         case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break;
4508                         case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break;
4509                         default: return COM.E_INVALIDARG;
4510                 }
4511                 int eventStart = event.start;
4512                 int eventEnd = event.end;
4513                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4514                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4515                         listener.getText(event);
4516                 }
4517                 if (event.end < charCount) {
4518                         switch (boundaryType) {
4519                                 case COM.IA2_TEXT_BOUNDARY_WORD:
4520                                 case COM.IA2_TEXT_BOUNDARY_SENTENCE:
4521                                 case COM.IA2_TEXT_BOUNDARY_PARAGRAPH:
4522                                 case COM.IA2_TEXT_BOUNDARY_LINE:
4523                                         int start = event.start;
4524                                         event.start = eventStart;
4525                                         event.end = eventEnd;
4526                                         event.count = 2;
4527                                         for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4528                                                 AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4529                                                 listener.getText(event);
4530                                         }
4531                                         event.end = event.start;
4532                                         event.start = start;
4533                                         event.type = ACC.TEXT_BOUNDARY_ALL;
4534                                         event.count = 0;
4535                                         for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4536                                                 AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4537                                                 listener.getText(event);
4538                                         }
4539                         }
4540                 }
4541                 if (DEBUG) print(this + ".IAccessibleText::get_textAfterOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK));
4542                 OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
4543                 OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
4544                 setString(pbstrText, event.result);
4545                 if (event.result == null) return COM.S_FALSE;
4546                 return COM.S_OK;
4547         }
4548
4549         /* IAccessibleText::get_textAtOffset([in] offset, [in] boundaryType, [out] pStartOffset, [out] pEndOffset, [out] pbstrText) */
4550         int get_textAtOffset(int offset, int boundaryType, long pStartOffset, long pEndOffset, long pbstrText) {
4551                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4552                 int charCount = getCharacterCount();
4553                 event.start = offset == COM.IA2_TEXT_OFFSET_LENGTH ? charCount : offset == COM.IA2_TEXT_OFFSET_CARET ? getCaretOffset() : offset;
4554                 event.end = event.start;
4555                 event.count = 0;
4556                 switch (boundaryType) {
4557                         case COM.IA2_TEXT_BOUNDARY_CHAR: event.type = ACC.TEXT_BOUNDARY_CHAR; break;
4558                         case COM.IA2_TEXT_BOUNDARY_WORD: event.type = ACC.TEXT_BOUNDARY_WORD; break;
4559                         case COM.IA2_TEXT_BOUNDARY_SENTENCE: event.type = ACC.TEXT_BOUNDARY_SENTENCE; break;
4560                         case COM.IA2_TEXT_BOUNDARY_PARAGRAPH: event.type = ACC.TEXT_BOUNDARY_PARAGRAPH; break;
4561                         case COM.IA2_TEXT_BOUNDARY_LINE: event.type = ACC.TEXT_BOUNDARY_LINE; break;
4562                         case COM.IA2_TEXT_BOUNDARY_ALL: {
4563                                 event.type = ACC.TEXT_BOUNDARY_ALL;
4564                                 event.start = 0;
4565                                 event.end = charCount;
4566                                 event.count = 0;
4567                                 break;
4568                         }
4569                         default: return COM.E_INVALIDARG;
4570                 }
4571                 int eventStart = event.start;
4572                 int eventEnd = event.end;
4573                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4574                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4575                         listener.getText(event);
4576                 }
4577                 if (event.end < charCount) {
4578                         switch (boundaryType) {
4579                                 case COM.IA2_TEXT_BOUNDARY_WORD:
4580                                 case COM.IA2_TEXT_BOUNDARY_SENTENCE:
4581                                 case COM.IA2_TEXT_BOUNDARY_PARAGRAPH:
4582                                 case COM.IA2_TEXT_BOUNDARY_LINE:
4583                                         int start = event.start;
4584                                         event.start = eventStart;
4585                                         event.end = eventEnd;
4586                                         event.count = 1;
4587                                         for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4588                                                 AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4589                                                 listener.getText(event);
4590                                         }
4591                                         event.end = event.start;
4592                                         event.start = start;
4593                                         event.type = ACC.TEXT_BOUNDARY_ALL;
4594                                         event.count = 0;
4595                                         for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4596                                                 AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4597                                                 listener.getText(event);
4598                                         }
4599                         }
4600                 }
4601                 if (DEBUG) print(this + ".IAccessibleText::get_textAtOffset(" + offset + ") returning start=" + event.start + ", end=" + event.end + " " + event.result + hresult(event.result == null ? COM.S_FALSE : COM.S_OK));
4602                 OS.MoveMemory(pStartOffset, new int [] { event.start }, 4);
4603                 OS.MoveMemory(pEndOffset, new int [] { event.end }, 4);
4604                 setString(pbstrText, event.result);
4605                 if (event.result == null) return COM.S_FALSE;
4606                 return COM.S_OK;
4607         }
4608
4609         /* IAccessibleText::removeSelection([in] selectionIndex) */
4610         int removeSelection(int selectionIndex) {
4611                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4612                 event.index = selectionIndex;
4613                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4614                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4615                         listener.removeSelection(event);
4616                 }
4617                 if (DEBUG) print(this + ".IAccessibleText::removeSelection(" + selectionIndex + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK));
4618                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
4619                 return COM.S_OK;
4620         }
4621
4622         /* IAccessibleText::setCaretOffset([in] offset) */
4623         int setCaretOffset(int offset) {
4624                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4625                 event.offset = offset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : offset;
4626                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4627                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4628                         listener.setCaretOffset(event);
4629                 }
4630                 if (DEBUG) print(this + ".IAccessibleText::setCaretOffset(" + offset + ") returning" + hresult(event.result == null || !event.result.equals(ACC.OK) ? COM.E_INVALIDARG : COM.S_OK));
4631                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; // TODO: @retval E_FAIL if the caret cannot be set ?
4632                 return COM.S_OK;
4633         }
4634
4635         /* IAccessibleText::setSelection([in] selectionIndex, [in] startOffset, [in] endOffset) */
4636         int setSelection(int selectionIndex, int startOffset, int endOffset) {
4637                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4638                 event.index = selectionIndex;
4639                 event.start = startOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : startOffset;
4640                 event.end = endOffset == COM.IA2_TEXT_OFFSET_LENGTH ? getCharacterCount() : endOffset;
4641                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4642                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4643                         listener.setSelection(event);
4644                 }
4645                 if (DEBUG) print(this + ".IAccessibleText::setSelection(index=" + selectionIndex + ", start=" + event.start + ", end=" + event.end + ") returning " + (event.result.equals(ACC.OK) ? "OK" : "INVALIDARG"));
4646                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
4647                 return COM.S_OK;
4648         }
4649
4650         /* IAccessibleText::get_nCharacters([out] pNCharacters) */
4651         int get_nCharacters(long pNCharacters) {
4652                 int count = getCharacterCount();
4653                 OS.MoveMemory(pNCharacters, new int [] { count }, 4);
4654                 if (DEBUG) print(this + ".IAccessibleText::get_nCharacters returning " + count);
4655                 return COM.S_OK;
4656         }
4657
4658         /* IAccessibleText::scrollSubstringTo([in] startIndex, [in] endIndex, [in] scrollType) */
4659         int scrollSubstringTo(int startIndex, int endIndex, int scrollType) {
4660                 if (DEBUG) print(this + ".IAccessibleText::scrollSubstringTo");
4661                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4662                 event.start = startIndex;
4663                 event.end = endIndex;
4664                 switch (scrollType) {
4665                         case COM.IA2_SCROLL_TYPE_TOP_LEFT: event.type = ACC.SCROLL_TYPE_TOP_LEFT; break;
4666                         case COM.IA2_SCROLL_TYPE_BOTTOM_RIGHT: event.type = ACC.SCROLL_TYPE_BOTTOM_RIGHT; break;
4667                         case COM.IA2_SCROLL_TYPE_TOP_EDGE: event.type = ACC.SCROLL_TYPE_TOP_EDGE; break;
4668                         case COM.IA2_SCROLL_TYPE_BOTTOM_EDGE: event.type = ACC.SCROLL_TYPE_BOTTOM_EDGE; break;
4669                         case COM.IA2_SCROLL_TYPE_LEFT_EDGE: event.type = ACC.SCROLL_TYPE_LEFT_EDGE; break;
4670                         case COM.IA2_SCROLL_TYPE_RIGHT_EDGE: event.type = ACC.SCROLL_TYPE_RIGHT_EDGE; break;
4671                         case COM.IA2_SCROLL_TYPE_ANYWHERE: event.type = ACC.SCROLL_TYPE_ANYWHERE; break;
4672                 }
4673                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4674                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4675                         listener.scrollText(event);
4676                 }
4677                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG;
4678                 return COM.S_OK;
4679         }
4680
4681         /* IAccessibleText::scrollSubstringToPoint([in] startIndex, [in] endIndex, [in] coordinateType, [in] x, [in] y) */
4682         int scrollSubstringToPoint(int startIndex, int endIndex, int coordinateType, int x, int y) {
4683                 if (DEBUG) print(this + ".IAccessibleText::scrollSubstringToPoint");
4684                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4685                 event.start = startIndex;
4686                 event.end = endIndex;
4687                 event.type = ACC.SCROLL_TYPE_POINT;
4688                 event.x = x;
4689                 event.y = y;
4690                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
4691                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
4692                         listener.scrollText(event);
4693                 }
4694                 if (event.result == null || !event.result.equals(ACC.OK)) return COM.E_INVALIDARG; // TODO: @retval S_FALSE if the object is already at the specified location.
4695                 return COM.S_OK;
4696         }
4697
4698         /* IAccessibleText::get_newText([out] pNewText) */
4699         int get_newText(long pNewText) {
4700                 if (DEBUG) print(this + ".IAccessibleText::get_newText");
4701                 String text = null;
4702                 int start = 0;
4703                 int end = 0;
4704                 if (textInserted != null) {
4705                         text = (String) textInserted[3];
4706                         start = ((Integer)textInserted[1]).intValue();
4707                         end = ((Integer)textInserted[2]).intValue();
4708                 }
4709                 setString(pNewText, text);
4710                 OS.MoveMemory(pNewText + C.PTR_SIZEOF, new int [] {start}, 4);
4711                 OS.MoveMemory(pNewText + C.PTR_SIZEOF + 4, new int [] {end}, 4);
4712                 if (textInserted == null) return COM.S_FALSE;
4713                 return COM.S_OK;
4714         }
4715
4716         /* IAccessibleText::get_oldText([out] pOldText) */
4717         int get_oldText(long pOldText) {
4718                 if (DEBUG) print(this + ".IAccessibleText::get_oldText");
4719                 String text = null;
4720                 int start = 0;
4721                 int end = 0;
4722                 if (textDeleted != null) {
4723                         text = (String) textDeleted[3];
4724                         start = ((Integer)textDeleted[1]).intValue();
4725                         end = ((Integer)textDeleted[2]).intValue();
4726                 }
4727                 setString(pOldText, text);
4728                 OS.MoveMemory(pOldText + C.PTR_SIZEOF, new int [] {start}, 4);
4729                 OS.MoveMemory(pOldText + C.PTR_SIZEOF + 4, new int [] {end}, 4);
4730                 if (textDeleted == null) return COM.S_FALSE;
4731                 return COM.S_OK;
4732         }
4733
4734         /* IAccessibleValue::get_currentValue([out] pCurrentValue) */
4735         int get_currentValue(long pCurrentValue) {
4736                 AccessibleValueEvent event = new AccessibleValueEvent(this);
4737                 for (int i = 0; i < accessibleValueListenersSize(); i++) {
4738                         AccessibleValueListener listener = accessibleValueListeners.get(i);
4739                         listener.getCurrentValue(event);
4740                 }
4741                 if (DEBUG) print(this + ".IAccessibleValue::get_currentValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK));
4742                 setNumberVARIANT(pCurrentValue, event.value);
4743                 return COM.S_OK;
4744         }
4745
4746         /* IAccessibleValue::setCurrentValue([in] value) */
4747         int setCurrentValue(long value) {
4748                 if (DEBUG) print(this + ".IAccessibleValue::setCurrentValue");
4749                 AccessibleValueEvent event = new AccessibleValueEvent(this);
4750                 event.value = getNumberVARIANT(value);
4751                 for (int i = 0; i < accessibleValueListenersSize(); i++) {
4752                         AccessibleValueListener listener = accessibleValueListeners.get(i);
4753                         listener.setCurrentValue(event);
4754                 }
4755                 //if (event.value == null) return COM.S_FALSE;
4756                 return COM.S_OK;
4757         }
4758
4759         /* IAccessibleValue::get_maximumValue([out] pMaximumValue) */
4760         int get_maximumValue(long pMaximumValue) {
4761                 AccessibleValueEvent event = new AccessibleValueEvent(this);
4762                 for (int i = 0; i < accessibleValueListenersSize(); i++) {
4763                         AccessibleValueListener listener = accessibleValueListeners.get(i);
4764                         listener.getMaximumValue(event);
4765                 }
4766                 if (DEBUG) print(this + ".IAccessibleValue::get_maximumValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK));
4767                 setNumberVARIANT(pMaximumValue, event.value);
4768                 return COM.S_OK;
4769         }
4770
4771         /* IAccessibleValue::get_minimumValue([out] pMinimumValue) */
4772         int get_minimumValue(long pMinimumValue) {
4773                 AccessibleValueEvent event = new AccessibleValueEvent(this);
4774                 for (int i = 0; i < accessibleValueListenersSize(); i++) {
4775                         AccessibleValueListener listener = accessibleValueListeners.get(i);
4776                         listener.getMinimumValue(event);
4777                 }
4778                 if (DEBUG) print(this + ".IAccessibleValue::get_minimumValue returning " + event.value + hresult(event.value == null ? COM.S_FALSE : COM.S_OK));
4779                 setNumberVARIANT(pMinimumValue, event.value);
4780                 return COM.S_OK;
4781         }
4782
4783         int eventChildID() {
4784                 if (parent == null) return COM.CHILDID_SELF;
4785                 if (uniqueID == -1) uniqueID = UniqueID--;
4786                 return uniqueID;
4787         }
4788
4789         void checkUniqueID(int childID) {
4790                 /* If the application is using child ids, check whether there's a corresponding
4791                  * accessible, and if so, use the child id as that accessible's unique id. */
4792                 AccessibleControlEvent event = new AccessibleControlEvent(this);
4793                 event.childID = childID;
4794                 for (int l = 0; l < accessibleControlListenersSize(); l++) {
4795                         AccessibleControlListener listener = accessibleControlListeners.get(l);
4796                         listener.getChild(event);
4797                 }
4798                 Accessible accessible = event.accessible;
4799                 if (accessible != null && accessible.uniqueID == -1) {
4800                         accessible.uniqueID = childID;
4801                 }
4802         }
4803
4804         int childIDToOs(int childID) {
4805                 if (childID == ACC.CHILDID_SELF) return COM.CHILDID_SELF;
4806                 /* ChildIDs are 1-based indices. */
4807                 int osChildID = childID + 1;
4808                 if (control instanceof Tree) {
4809                         osChildID = (int)OS.SendMessage (control.handle, OS.TVM_MAPHTREEITEMTOACCID, childID, 0);
4810                 }
4811                 checkUniqueID(osChildID);
4812                 return osChildID;
4813         }
4814
4815         int osToChildID(int osChildID) {
4816                 if (osChildID == COM.CHILDID_SELF) return ACC.CHILDID_SELF;
4817                 /*
4818                 * Feature of Windows:
4819                 * Before Windows XP, tree item ids were 1-based indices.
4820                 * Windows XP and later use the tree item handle for the
4821                 * accessible child ID. For backward compatibility, we still
4822                 * take 1-based childIDs for tree items prior to Windows XP.
4823                 * All other childIDs are 1-based indices.
4824                 */
4825                 if (!(control instanceof Tree)) return osChildID - 1;
4826                 return (int)OS.SendMessage (control.handle, OS.TVM_MAPACCIDTOHTREEITEM, osChildID, 0);
4827         }
4828
4829         int stateToOs(int state) {
4830                 int osState = 0;
4831                 if ((state & ACC.STATE_SELECTED) != 0) osState |= COM.STATE_SYSTEM_SELECTED;
4832                 if ((state & ACC.STATE_SELECTABLE) != 0) osState |= COM.STATE_SYSTEM_SELECTABLE;
4833                 if ((state & ACC.STATE_MULTISELECTABLE) != 0) osState |= COM.STATE_SYSTEM_MULTISELECTABLE;
4834                 if ((state & ACC.STATE_FOCUSED) != 0) osState |= COM.STATE_SYSTEM_FOCUSED;
4835                 if ((state & ACC.STATE_FOCUSABLE) != 0) osState |= COM.STATE_SYSTEM_FOCUSABLE;
4836                 if ((state & ACC.STATE_PRESSED) != 0) osState |= COM.STATE_SYSTEM_PRESSED;
4837                 if ((state & ACC.STATE_CHECKED) != 0) osState |= COM.STATE_SYSTEM_CHECKED;
4838                 if ((state & ACC.STATE_EXPANDED) != 0) osState |= COM.STATE_SYSTEM_EXPANDED;
4839                 if ((state & ACC.STATE_COLLAPSED) != 0) osState |= COM.STATE_SYSTEM_COLLAPSED;
4840                 if ((state & ACC.STATE_HOTTRACKED) != 0) osState |= COM.STATE_SYSTEM_HOTTRACKED;
4841                 if ((state & ACC.STATE_BUSY) != 0) osState |= COM.STATE_SYSTEM_BUSY;
4842                 if ((state & ACC.STATE_READONLY) != 0) osState |= COM.STATE_SYSTEM_READONLY;
4843                 if ((state & ACC.STATE_INVISIBLE) != 0) osState |= COM.STATE_SYSTEM_INVISIBLE;
4844                 if ((state & ACC.STATE_OFFSCREEN) != 0) osState |= COM.STATE_SYSTEM_OFFSCREEN;
4845                 if ((state & ACC.STATE_SIZEABLE) != 0) osState |= COM.STATE_SYSTEM_SIZEABLE;
4846                 if ((state & ACC.STATE_LINKED) != 0) osState |= COM.STATE_SYSTEM_LINKED;
4847                 if ((state & ACC.STATE_DISABLED) != 0) osState |= COM.STATE_SYSTEM_UNAVAILABLE;
4848                 return osState;
4849         }
4850
4851         int osToState(int osState) {
4852                 int state = ACC.STATE_NORMAL;
4853                 if ((osState & COM.STATE_SYSTEM_SELECTED) != 0) state |= ACC.STATE_SELECTED;
4854                 if ((osState & COM.STATE_SYSTEM_SELECTABLE) != 0) state |= ACC.STATE_SELECTABLE;
4855                 if ((osState & COM.STATE_SYSTEM_MULTISELECTABLE) != 0) state |= ACC.STATE_MULTISELECTABLE;
4856                 if ((osState & COM.STATE_SYSTEM_FOCUSED) != 0) state |= ACC.STATE_FOCUSED;
4857                 if ((osState & COM.STATE_SYSTEM_FOCUSABLE) != 0) state |= ACC.STATE_FOCUSABLE;
4858                 if ((osState & COM.STATE_SYSTEM_PRESSED) != 0) state |= ACC.STATE_PRESSED;
4859                 if ((osState & COM.STATE_SYSTEM_CHECKED) != 0) state |= ACC.STATE_CHECKED;
4860                 if ((osState & COM.STATE_SYSTEM_EXPANDED) != 0) state |= ACC.STATE_EXPANDED;
4861                 if ((osState & COM.STATE_SYSTEM_COLLAPSED) != 0) state |= ACC.STATE_COLLAPSED;
4862                 if ((osState & COM.STATE_SYSTEM_HOTTRACKED) != 0) state |= ACC.STATE_HOTTRACKED;
4863                 if ((osState & COM.STATE_SYSTEM_BUSY) != 0) state |= ACC.STATE_BUSY;
4864                 if ((osState & COM.STATE_SYSTEM_READONLY) != 0) state |= ACC.STATE_READONLY;
4865                 if ((osState & COM.STATE_SYSTEM_INVISIBLE) != 0) state |= ACC.STATE_INVISIBLE;
4866                 if ((osState & COM.STATE_SYSTEM_OFFSCREEN) != 0) state |= ACC.STATE_OFFSCREEN;
4867                 if ((osState & COM.STATE_SYSTEM_SIZEABLE) != 0) state |= ACC.STATE_SIZEABLE;
4868                 if ((osState & COM.STATE_SYSTEM_LINKED) != 0) state |= ACC.STATE_LINKED;
4869                 if ((osState & COM.STATE_SYSTEM_UNAVAILABLE) != 0) state |= ACC.STATE_DISABLED;
4870                 return state;
4871         }
4872
4873         int roleToOs(int role) {
4874                 switch (role) {
4875                         case ACC.ROLE_CLIENT_AREA: return COM.ROLE_SYSTEM_CLIENT;
4876                         case ACC.ROLE_WINDOW: return COM.ROLE_SYSTEM_WINDOW;
4877                         case ACC.ROLE_MENUBAR: return COM.ROLE_SYSTEM_MENUBAR;
4878                         case ACC.ROLE_MENU: return COM.ROLE_SYSTEM_MENUPOPUP;
4879                         case ACC.ROLE_MENUITEM: return COM.ROLE_SYSTEM_MENUITEM;
4880                         case ACC.ROLE_SEPARATOR: return COM.ROLE_SYSTEM_SEPARATOR;
4881                         case ACC.ROLE_TOOLTIP: return COM.ROLE_SYSTEM_TOOLTIP;
4882                         case ACC.ROLE_SCROLLBAR: return COM.ROLE_SYSTEM_SCROLLBAR;
4883                         case ACC.ROLE_DIALOG: return COM.ROLE_SYSTEM_DIALOG;
4884                         case ACC.ROLE_LABEL: return COM.ROLE_SYSTEM_STATICTEXT;
4885                         case ACC.ROLE_PUSHBUTTON: return COM.ROLE_SYSTEM_PUSHBUTTON;
4886                         case ACC.ROLE_CHECKBUTTON: return COM.ROLE_SYSTEM_CHECKBUTTON;
4887                         case ACC.ROLE_RADIOBUTTON: return COM.ROLE_SYSTEM_RADIOBUTTON;
4888                         case ACC.ROLE_SPLITBUTTON: return COM.ROLE_SYSTEM_SPLITBUTTON;
4889                         case ACC.ROLE_COMBOBOX: return COM.ROLE_SYSTEM_COMBOBOX;
4890                         case ACC.ROLE_TEXT: return COM.ROLE_SYSTEM_TEXT;
4891                         case ACC.ROLE_TOOLBAR: return COM.ROLE_SYSTEM_TOOLBAR;
4892                         case ACC.ROLE_LIST: return COM.ROLE_SYSTEM_LIST;
4893                         case ACC.ROLE_LISTITEM: return COM.ROLE_SYSTEM_LISTITEM;
4894                         case ACC.ROLE_TABLE: return COM.ROLE_SYSTEM_TABLE;
4895                         case ACC.ROLE_TABLECELL: return COM.ROLE_SYSTEM_CELL;
4896                         case ACC.ROLE_TABLECOLUMNHEADER: return COM.ROLE_SYSTEM_COLUMNHEADER;
4897                         case ACC.ROLE_TABLEROWHEADER: return COM.ROLE_SYSTEM_ROWHEADER;
4898                         case ACC.ROLE_TREE: return COM.ROLE_SYSTEM_OUTLINE;
4899                         case ACC.ROLE_TREEITEM: return COM.ROLE_SYSTEM_OUTLINEITEM;
4900                         case ACC.ROLE_TABFOLDER: return COM.ROLE_SYSTEM_PAGETABLIST;
4901                         case ACC.ROLE_TABITEM: return COM.ROLE_SYSTEM_PAGETAB;
4902                         case ACC.ROLE_PROGRESSBAR: return COM.ROLE_SYSTEM_PROGRESSBAR;
4903                         case ACC.ROLE_SLIDER: return COM.ROLE_SYSTEM_SLIDER;
4904                         case ACC.ROLE_LINK: return COM.ROLE_SYSTEM_LINK;
4905                         case ACC.ROLE_ALERT: return COM.ROLE_SYSTEM_ALERT;
4906                         case ACC.ROLE_ANIMATION: return COM.ROLE_SYSTEM_ANIMATION;
4907                         case ACC.ROLE_COLUMN: return COM.ROLE_SYSTEM_COLUMN;
4908                         case ACC.ROLE_DOCUMENT: return COM.ROLE_SYSTEM_DOCUMENT;
4909                         case ACC.ROLE_GRAPHIC: return COM.ROLE_SYSTEM_GRAPHIC;
4910                         case ACC.ROLE_GROUP: return COM.ROLE_SYSTEM_GROUPING;
4911                         case ACC.ROLE_ROW: return COM.ROLE_SYSTEM_ROW;
4912                         case ACC.ROLE_SPINBUTTON: return COM.ROLE_SYSTEM_SPINBUTTON;
4913                         case ACC.ROLE_STATUSBAR: return COM.ROLE_SYSTEM_STATUSBAR;
4914                         case ACC.ROLE_CLOCK: return COM.ROLE_SYSTEM_CLOCK;
4915                         case ACC.ROLE_CALENDAR: return COM.ROLE_SYSTEM_DROPLIST;
4916
4917                         /* The rest are IA2 roles, so return the closest match. */
4918                         case ACC.ROLE_CANVAS: return COM.ROLE_SYSTEM_CLIENT;
4919                         case ACC.ROLE_CHECKMENUITEM: return COM.ROLE_SYSTEM_MENUITEM;
4920                         case ACC.ROLE_RADIOMENUITEM: return COM.ROLE_SYSTEM_MENUITEM;
4921                         case ACC.ROLE_DATETIME: return COM.ROLE_SYSTEM_DROPLIST;
4922                         case ACC.ROLE_FOOTER: return COM.ROLE_SYSTEM_CLIENT;
4923                         case ACC.ROLE_FORM: return COM.ROLE_SYSTEM_CLIENT;
4924                         case ACC.ROLE_HEADER: return COM.ROLE_SYSTEM_CLIENT;
4925                         case ACC.ROLE_HEADING: return COM.ROLE_SYSTEM_CLIENT;
4926                         case ACC.ROLE_PAGE: return COM.ROLE_SYSTEM_CLIENT;
4927                         case ACC.ROLE_PARAGRAPH: return COM.ROLE_SYSTEM_CLIENT;
4928                         case ACC.ROLE_SECTION: return COM.ROLE_SYSTEM_CLIENT;
4929                 }
4930                 return COM.ROLE_SYSTEM_CLIENT;
4931         }
4932
4933         int osToRole(int osRole) {
4934                 switch (osRole) {
4935                         case COM.ROLE_SYSTEM_CLIENT: return ACC.ROLE_CLIENT_AREA;
4936                         case COM.ROLE_SYSTEM_WINDOW: return ACC.ROLE_WINDOW;
4937                         case COM.ROLE_SYSTEM_MENUBAR: return ACC.ROLE_MENUBAR;
4938                         case COM.ROLE_SYSTEM_MENUPOPUP: return ACC.ROLE_MENU;
4939                         case COM.ROLE_SYSTEM_MENUITEM: return ACC.ROLE_MENUITEM;
4940                         case COM.ROLE_SYSTEM_SEPARATOR: return ACC.ROLE_SEPARATOR;
4941                         case COM.ROLE_SYSTEM_TOOLTIP: return ACC.ROLE_TOOLTIP;
4942                         case COM.ROLE_SYSTEM_SCROLLBAR: return ACC.ROLE_SCROLLBAR;
4943                         case COM.ROLE_SYSTEM_DIALOG: return ACC.ROLE_DIALOG;
4944                         case COM.ROLE_SYSTEM_STATICTEXT: return ACC.ROLE_LABEL;
4945                         case COM.ROLE_SYSTEM_PUSHBUTTON: return ACC.ROLE_PUSHBUTTON;
4946                         case COM.ROLE_SYSTEM_CHECKBUTTON: return ACC.ROLE_CHECKBUTTON;
4947                         case COM.ROLE_SYSTEM_RADIOBUTTON: return ACC.ROLE_RADIOBUTTON;
4948                         case COM.ROLE_SYSTEM_SPLITBUTTON: return ACC.ROLE_SPLITBUTTON;
4949                         case COM.ROLE_SYSTEM_COMBOBOX: return ACC.ROLE_COMBOBOX;
4950                         case COM.ROLE_SYSTEM_TEXT: return ACC.ROLE_TEXT;
4951                         case COM.ROLE_SYSTEM_TOOLBAR: return ACC.ROLE_TOOLBAR;
4952                         case COM.ROLE_SYSTEM_LIST: return ACC.ROLE_LIST;
4953                         case COM.ROLE_SYSTEM_LISTITEM: return ACC.ROLE_LISTITEM;
4954                         case COM.ROLE_SYSTEM_TABLE: return ACC.ROLE_TABLE;
4955                         case COM.ROLE_SYSTEM_CELL: return ACC.ROLE_TABLECELL;
4956                         case COM.ROLE_SYSTEM_COLUMNHEADER: return ACC.ROLE_TABLECOLUMNHEADER;
4957                         case COM.ROLE_SYSTEM_ROWHEADER: return ACC.ROLE_TABLEROWHEADER;
4958                         case COM.ROLE_SYSTEM_OUTLINE: return ACC.ROLE_TREE;
4959                         case COM.ROLE_SYSTEM_OUTLINEITEM: return ACC.ROLE_TREEITEM;
4960                         case COM.ROLE_SYSTEM_PAGETABLIST: return ACC.ROLE_TABFOLDER;
4961                         case COM.ROLE_SYSTEM_PAGETAB: return ACC.ROLE_TABITEM;
4962                         case COM.ROLE_SYSTEM_PROGRESSBAR: return ACC.ROLE_PROGRESSBAR;
4963                         case COM.ROLE_SYSTEM_SLIDER: return ACC.ROLE_SLIDER;
4964                         case COM.ROLE_SYSTEM_LINK: return ACC.ROLE_LINK;
4965                         case COM.ROLE_SYSTEM_ALERT: return ACC.ROLE_ALERT;
4966                         case COM.ROLE_SYSTEM_ANIMATION: return ACC.ROLE_ANIMATION;
4967                         case COM.ROLE_SYSTEM_COLUMN: return ACC.ROLE_COLUMN;
4968                         case COM.ROLE_SYSTEM_DOCUMENT: return ACC.ROLE_DOCUMENT;
4969                         case COM.ROLE_SYSTEM_GRAPHIC: return ACC.ROLE_GRAPHIC;
4970                         case COM.ROLE_SYSTEM_GROUPING: return ACC.ROLE_GROUP;
4971                         case COM.ROLE_SYSTEM_ROW: return ACC.ROLE_ROW;
4972                         case COM.ROLE_SYSTEM_SPINBUTTON: return ACC.ROLE_SPINBUTTON;
4973                         case COM.ROLE_SYSTEM_STATUSBAR: return ACC.ROLE_STATUSBAR;
4974                         case COM.ROLE_SYSTEM_CLOCK: return ACC.ROLE_CLOCK;
4975                         case COM.ROLE_SYSTEM_DROPLIST: return ACC.ROLE_CALENDAR;
4976                 }
4977                 return ACC.ROLE_CLIENT_AREA;
4978         }
4979
4980         /*
4981          * Return a Color given a string of the form "rgb(n,n,n)".
4982          */
4983         Color colorFromString(String rgbString) {
4984                 try {
4985                         int open = rgbString.indexOf('(');
4986                         int comma1 = rgbString.indexOf(',');
4987                         int comma2 = rgbString.indexOf(',', comma1 + 1);
4988                         int close = rgbString.indexOf(')');
4989                         int r = Integer.parseInt(rgbString.substring(open + 1, comma1));
4990                         int g = Integer.parseInt(rgbString.substring(comma1 + 1, comma2));
4991                         int b = Integer.parseInt(rgbString.substring(comma2 + 1, close));
4992                         return new Color(control.getDisplay(), r, g, b);
4993                 } catch (NumberFormatException ex) {}
4994                 return null;
4995         }
4996
4997         int getCaretOffset() {
4998                 AccessibleTextEvent event = new AccessibleTextEvent(this);
4999                 event.offset = -1;
5000                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
5001                         AccessibleTextListener listener = accessibleTextExtendedListeners.get(i);
5002                         listener.getCaretOffset (event);
5003                 }
5004                 if (event.offset == -1) {
5005                         for (int i = 0; i < accessibleTextListenersSize(); i++) {
5006                                 event.childID = ACC.CHILDID_SELF;
5007                                 AccessibleTextListener listener = accessibleTextListeners.get(i);
5008                                 listener.getCaretOffset (event);
5009                         }
5010                 }
5011                 return event.offset;
5012         }
5013
5014         int getCharacterCount() {
5015                 AccessibleTextEvent event = new AccessibleTextEvent(this);
5016                 event.count = -1;
5017                 for (int i = 0; i < accessibleTextExtendedListenersSize(); i++) {
5018                         AccessibleTextExtendedListener listener = accessibleTextExtendedListeners.get(i);
5019                         listener.getCharacterCount(event);
5020                 }
5021                 if (event.count == -1) {
5022                         AccessibleControlEvent e = new AccessibleControlEvent(this);
5023                         e.childID = ACC.CHILDID_SELF;
5024                         for (int i = 0; i < accessibleControlListenersSize(); i++) {
5025                                 AccessibleControlListener listener = accessibleControlListeners.get(i);
5026                                 listener.getRole(e);
5027                                 listener.getValue(e);
5028                         }
5029                         // TODO: Consider passing the value through for other roles as well (i.e. combo, etc). Keep in sync with get_text.
5030                         event.count = e.detail == ACC.ROLE_TEXT && e.result != null ? e.result.length() : 0;
5031                 }
5032                 return event.count;
5033         }
5034
5035         int getRelationCount() {
5036                 int count = 0;
5037                 for (int type = 0; type < MAX_RELATION_TYPES; type++) {
5038                         if (relations[type] != null) count++;
5039                 }
5040                 return count;
5041         }
5042
5043         int getRole() {
5044                 AccessibleControlEvent event = new AccessibleControlEvent(this);
5045                 event.childID = ACC.CHILDID_SELF;
5046                 for (int i = 0; i < accessibleControlListenersSize(); i++) {
5047                         AccessibleControlListener listener = accessibleControlListeners.get(i);
5048                         listener.getRole(event);
5049                 }
5050                 return event.detail;
5051         }
5052
5053         int getDefaultRole() {
5054                 int role;
5055                 role = COM.ROLE_SYSTEM_CLIENT;
5056                 if (iaccessible != null) {
5057                         /* Get the default role from the OS. */
5058                         long varChild = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
5059                         setIntVARIANT(varChild, COM.VT_I4, COM.CHILDID_SELF);
5060                         long pvarRole = OS.GlobalAlloc (OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
5061                         int code = iaccessible.get_accRole(varChild, pvarRole);
5062                         if (code == COM.S_OK) {
5063                                 VARIANT v = getVARIANT(pvarRole);
5064                                 if (v.vt == COM.VT_I4) role = v.lVal;
5065                         }
5066                         OS.GlobalFree(varChild);
5067                         OS.GlobalFree(pvarRole);
5068                 }
5069                 return role;
5070         }
5071
5072         String getString(long psz) {
5073                 long [] ptr = new long [1];
5074                 OS.MoveMemory (ptr, psz, C.PTR_SIZEOF);
5075                 int size = COM.SysStringByteLen(ptr [0]);
5076                 if (size == 0) return "";
5077                 char [] buffer = new char [(size + 1) / 2];
5078                 OS.MoveMemory (buffer, ptr [0], size);
5079                 return new String (buffer);
5080         }
5081
5082         VARIANT getVARIANT(long variant) {
5083                 VARIANT v = new VARIANT();
5084                 COM.MoveMemory(v, variant, VARIANT.sizeof);
5085                 return v;
5086         }
5087
5088         Number getNumberVARIANT(long variant) {
5089                 VARIANT v = new VARIANT();
5090                 COM.MoveMemory(v, variant, VARIANT.sizeof);
5091                 if (v.vt == COM.VT_I8) return Long.valueOf(v.lVal); // TODO: Fix this - v.lVal is an int - don't use struct
5092                 return Integer.valueOf(v.lVal);
5093         }
5094
5095         void setIntVARIANT(long variant, short vt, int lVal) {
5096                 if (vt == COM.VT_I4 || vt == COM.VT_EMPTY) {
5097                         OS.MoveMemory(variant, new short[] { vt }, 2);
5098                         OS.MoveMemory(variant + 8, new int[] { lVal }, 4);
5099                 }
5100         }
5101
5102         void setPtrVARIANT(long variant, short vt, long lVal) {
5103                 if (vt == COM.VT_DISPATCH || vt == COM.VT_UNKNOWN) {
5104                         OS.MoveMemory(variant, new short[] { vt }, 2);
5105                         OS.MoveMemory(variant + 8, new long [] { lVal }, C.PTR_SIZEOF);
5106                 }
5107         }
5108
5109         void setNumberVARIANT(long variant, Number number) {
5110                 if (number == null) {
5111                         OS.MoveMemory(variant, new short[] { COM.VT_EMPTY }, 2);
5112                         OS.MoveMemory(variant + 8, new int[] { 0 }, 4);
5113                 } else if (number instanceof Double) {
5114                         OS.MoveMemory(variant, new short[] { COM.VT_R8 }, 2);
5115                         OS.MoveMemory(variant + 8, new double[] { number.doubleValue() }, 8);
5116                 } else if (number instanceof Float) {
5117                         OS.MoveMemory(variant, new short[] { COM.VT_R4 }, 2);
5118                         OS.MoveMemory(variant + 8, new float[] { number.floatValue() }, 4);
5119                 } else if (number instanceof Long) {
5120                         OS.MoveMemory(variant, new short[] { COM.VT_I8 }, 2);
5121                         OS.MoveMemory(variant + 8, new long[] { number.longValue() }, 8);
5122                 } else {
5123                         OS.MoveMemory(variant, new short[] { COM.VT_I4 }, 2);
5124                         OS.MoveMemory(variant + 8, new int[] { number.intValue() }, 4);
5125                 }
5126         }
5127
5128         void setString(long psz, String string) {
5129                 long ptr = 0;
5130                 if (string != null) {
5131                         char[] data = (string + "\0").toCharArray();
5132                         ptr = COM.SysAllocString(data);
5133                 }
5134                 OS.MoveMemory(psz, new long [] { ptr }, C.PTR_SIZEOF);
5135         }
5136
5137         void setStringVARIANT(long variant, String string) {
5138                 long ptr = 0;
5139                 if (string != null) {
5140                         char[] data = (string + "\0").toCharArray();
5141                         ptr = COM.SysAllocString(data);
5142                 }
5143                 OS.MoveMemory(variant, new short[] { ptr == 0 ? COM.VT_EMPTY : COM.VT_BSTR }, 2);
5144                 OS.MoveMemory(variant + 8, new long [] { ptr }, C.PTR_SIZEOF);
5145         }
5146
5147         /* checkWidget was copied from Widget, and rewritten to work in this package */
5148         void checkWidget () {
5149                 if (!isValidThread ()) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
5150                 if (control.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED);
5151         }
5152
5153         boolean isATRunning () {
5154                 /*
5155                  * Currently there is no accurate way to check if AT is running from 'refCount'.
5156                  * JAWS screen reader cannot be detected using 'refCount' approach,
5157                  * because 'refCount' continues to be 1 even when JAWS is running.
5158                  */
5159                 // if (refCount <= 1) return false;
5160                 return true;
5161         }
5162
5163         /* isValidThread was copied from Widget, and rewritten to work in this package */
5164         boolean isValidThread () {
5165                 return control.getDisplay ().getThread () == Thread.currentThread ();
5166         }
5167
5168         // START DEBUG CODE
5169         static void print (String str) {
5170                 if (DEBUG) System.out.println (str);
5171         }
5172         String getRoleString(int role) {
5173                 if (DEBUG) switch (role) {
5174                         case COM.ROLE_SYSTEM_CLIENT: return "ROLE_SYSTEM_CLIENT";
5175                         case COM.ROLE_SYSTEM_WINDOW: return "ROLE_SYSTEM_WINDOW";
5176                         case COM.ROLE_SYSTEM_MENUBAR: return "ROLE_SYSTEM_MENUBAR";
5177                         case COM.ROLE_SYSTEM_MENUPOPUP: return "ROLE_SYSTEM_MENUPOPUP";
5178                         case COM.ROLE_SYSTEM_MENUITEM: return "ROLE_SYSTEM_MENUITEM";
5179                         case COM.ROLE_SYSTEM_SEPARATOR: return "ROLE_SYSTEM_SEPARATOR";
5180                         case COM.ROLE_SYSTEM_TOOLTIP: return "ROLE_SYSTEM_TOOLTIP";
5181                         case COM.ROLE_SYSTEM_SCROLLBAR: return "ROLE_SYSTEM_SCROLLBAR";
5182                         case COM.ROLE_SYSTEM_DIALOG: return "ROLE_SYSTEM_DIALOG";
5183                         case COM.ROLE_SYSTEM_STATICTEXT: return "ROLE_SYSTEM_STATICTEXT";
5184                         case COM.ROLE_SYSTEM_PUSHBUTTON: return "ROLE_SYSTEM_PUSHBUTTON";
5185                         case COM.ROLE_SYSTEM_CHECKBUTTON: return "ROLE_SYSTEM_CHECKBUTTON";
5186                         case COM.ROLE_SYSTEM_RADIOBUTTON: return "ROLE_SYSTEM_RADIOBUTTON";
5187                         case COM.ROLE_SYSTEM_SPLITBUTTON: return "ROLE_SYSTEM_SPLITBUTTON";
5188                         case COM.ROLE_SYSTEM_COMBOBOX: return "ROLE_SYSTEM_COMBOBOX";
5189                         case COM.ROLE_SYSTEM_TEXT: return "ROLE_SYSTEM_TEXT";
5190                         case COM.ROLE_SYSTEM_TOOLBAR: return "ROLE_SYSTEM_TOOLBAR";
5191                         case COM.ROLE_SYSTEM_LIST: return "ROLE_SYSTEM_LIST";
5192                         case COM.ROLE_SYSTEM_LISTITEM: return "ROLE_SYSTEM_LISTITEM";
5193                         case COM.ROLE_SYSTEM_TABLE: return "ROLE_SYSTEM_TABLE";
5194                         case COM.ROLE_SYSTEM_CELL: return "ROLE_SYSTEM_CELL";
5195                         case COM.ROLE_SYSTEM_COLUMNHEADER: return "ROLE_SYSTEM_COLUMNHEADER";
5196                         case COM.ROLE_SYSTEM_ROWHEADER: return "ROLE_SYSTEM_ROWHEADER";
5197                         case COM.ROLE_SYSTEM_OUTLINE: return "ROLE_SYSTEM_OUTLINE";
5198                         case COM.ROLE_SYSTEM_OUTLINEITEM: return "ROLE_SYSTEM_OUTLINEITEM";
5199                         case COM.ROLE_SYSTEM_PAGETABLIST: return "ROLE_SYSTEM_PAGETABLIST";
5200                         case COM.ROLE_SYSTEM_PAGETAB: return "ROLE_SYSTEM_PAGETAB";
5201                         case COM.ROLE_SYSTEM_PROGRESSBAR: return "ROLE_SYSTEM_PROGRESSBAR";
5202                         case COM.ROLE_SYSTEM_SLIDER: return "ROLE_SYSTEM_SLIDER";
5203                         case COM.ROLE_SYSTEM_LINK: return "ROLE_SYSTEM_LINK";
5204                         case COM.ROLE_SYSTEM_ALERT: return "ROLE_SYSTEM_ALERT";
5205                         case COM.ROLE_SYSTEM_ANIMATION: return "ROLE_SYSTEM_ANIMATION";
5206                         case COM.ROLE_SYSTEM_COLUMN: return "ROLE_SYSTEM_COLUMN";
5207                         case COM.ROLE_SYSTEM_DOCUMENT: return "ROLE_SYSTEM_DOCUMENT";
5208                         case COM.ROLE_SYSTEM_GRAPHIC: return "ROLE_SYSTEM_GRAPHIC";
5209                         case COM.ROLE_SYSTEM_GROUPING: return "ROLE_SYSTEM_GROUPING";
5210                         case COM.ROLE_SYSTEM_ROW: return "ROLE_SYSTEM_ROW";
5211                         case COM.ROLE_SYSTEM_SPINBUTTON: return "ROLE_SYSTEM_SPINBUTTON";
5212                         case COM.ROLE_SYSTEM_STATUSBAR: return "ROLE_SYSTEM_STATUSBAR";
5213                         case COM.ROLE_SYSTEM_CLOCK: return "ROLE_SYSTEM_CLOCK";
5214                         case COM.ROLE_SYSTEM_DROPLIST: return "ROLE_SYSTEM_DROPLIST";
5215                         // IA2 roles
5216                         case ACC.ROLE_CANVAS: return "IA2_ROLE_CANVAS";
5217                         case ACC.ROLE_CHECKMENUITEM: return "IA2_ROLE_CHECKMENUITEM";
5218                         case ACC.ROLE_RADIOMENUITEM: return "IA2_ROLE_RADIOMENUITEM";
5219                         case ACC.ROLE_DATETIME: return "IA2_ROLE_DATETIME";
5220                         case ACC.ROLE_FOOTER: return "IA2_ROLE_FOOTER";
5221                         case ACC.ROLE_FORM: return "IA2_ROLE_FORM";
5222                         case ACC.ROLE_HEADER: return "IA2_ROLE_HEADER";
5223                         case ACC.ROLE_HEADING: return "IA2_ROLE_HEADING";
5224                         case ACC.ROLE_PAGE: return "IA2_ROLE_PAGE";
5225                         case ACC.ROLE_PARAGRAPH: return "IA2_ROLE_PARAGRAPH";
5226                         case ACC.ROLE_SECTION: return "IA2_ROLE_SECTION";
5227                 }
5228                 return "Unknown role (" + role + ")";
5229         }
5230         String getStateString(int state) {
5231                 if (state == 0) return " no state bits set";
5232                 StringBuilder stateString = new StringBuilder();
5233                 if (DEBUG) {
5234                 if ((state & COM.STATE_SYSTEM_SELECTED) != 0) stateString.append(" STATE_SYSTEM_SELECTED");
5235                 if ((state & COM.STATE_SYSTEM_SELECTABLE) != 0) stateString.append(" STATE_SYSTEM_SELECTABLE");
5236                 if ((state & COM.STATE_SYSTEM_MULTISELECTABLE) != 0) stateString.append(" STATE_SYSTEM_MULTISELECTABLE");
5237                 if ((state & COM.STATE_SYSTEM_FOCUSED) != 0) stateString.append(" STATE_SYSTEM_FOCUSED");
5238                 if ((state & COM.STATE_SYSTEM_FOCUSABLE) != 0) stateString.append(" STATE_SYSTEM_FOCUSABLE");
5239                 if ((state & COM.STATE_SYSTEM_PRESSED) != 0) stateString.append(" STATE_SYSTEM_PRESSED");
5240                 if ((state & COM.STATE_SYSTEM_CHECKED) != 0) stateString.append(" STATE_SYSTEM_CHECKED");
5241                 if ((state & COM.STATE_SYSTEM_EXPANDED) != 0) stateString.append(" STATE_SYSTEM_EXPANDED");
5242                 if ((state & COM.STATE_SYSTEM_COLLAPSED) != 0) stateString.append(" STATE_SYSTEM_COLLAPSED");
5243                 if ((state & COM.STATE_SYSTEM_HOTTRACKED) != 0) stateString.append(" STATE_SYSTEM_HOTTRACKED");
5244                 if ((state & COM.STATE_SYSTEM_BUSY) != 0) stateString.append(" STATE_SYSTEM_BUSY");
5245                 if ((state & COM.STATE_SYSTEM_READONLY) != 0) stateString.append(" STATE_SYSTEM_READONLY");
5246                 if ((state & COM.STATE_SYSTEM_INVISIBLE) != 0) stateString.append(" STATE_SYSTEM_INVISIBLE");
5247                 if ((state & COM.STATE_SYSTEM_OFFSCREEN) != 0) stateString.append(" STATE_SYSTEM_OFFSCREEN");
5248                 if ((state & COM.STATE_SYSTEM_SIZEABLE) != 0) stateString.append(" STATE_SYSTEM_SIZEABLE");
5249                 if ((state & COM.STATE_SYSTEM_LINKED) != 0) stateString.append(" STATE_SYSTEM_LINKED");
5250                 if ((state & COM.STATE_SYSTEM_UNAVAILABLE) != 0) stateString.append(" STATE_SYSTEM_UNAVAILABLE");
5251                 if (stateString.length() == 0) stateString.append(" Unknown state[s] (" + Integer.toHexString(state) + ")");
5252                 }
5253                 return stateString.toString();
5254         }
5255         String getIA2StatesString(int ia2States) {
5256                 if (ia2States == 0) return " no state bits set";
5257                 StringBuilder stateString = new StringBuilder();
5258                 if (DEBUG) {
5259                 if ((ia2States & COM.IA2_STATE_ACTIVE) != 0) stateString.append(" IA2_STATE_ACTIVE");
5260                 if ((ia2States & COM.IA2_STATE_EDITABLE) != 0) stateString.append(" IA2_STATE_EDITABLE");
5261                 if ((ia2States & COM.IA2_STATE_SINGLE_LINE) != 0) stateString.append(" IA2_STATE_SINGLE_LINE");
5262                 if ((ia2States & COM.IA2_STATE_MULTI_LINE) != 0) stateString.append(" IA2_STATE_MULTI_LINE");
5263                 if ((ia2States & COM.IA2_STATE_REQUIRED) != 0) stateString.append(" IA2_STATE_REQUIRED");
5264                 if ((ia2States & COM.IA2_STATE_INVALID_ENTRY) != 0) stateString.append(" IA2_STATE_INVALID_ENTRY");
5265                 if ((ia2States & COM.IA2_STATE_SUPPORTS_AUTOCOMPLETION) != 0) stateString.append(" IA2_STATE_SUPPORTS_AUTOCOMPLETION");
5266                 if (stateString.length() == 0) stateString.append(" Unknown IA2 state[s] (" + ia2States + ")");
5267                 }
5268                 return stateString.toString();
5269         }
5270         String getEventString(int event) {
5271                 if (DEBUG) switch (event) {
5272                         case ACC.EVENT_TABLE_CHANGED: return "IA2_EVENT_TABLE_CHANGED";
5273                         case ACC.EVENT_TEXT_CHANGED: return "IA2_EVENT_TEXT_REMOVED or IA2_EVENT_TEXT_INSERTED";
5274                         case ACC.EVENT_HYPERTEXT_LINK_SELECTED: return "IA2_EVENT_HYPERTEXT_LINK_SELECTED";
5275                         case ACC.EVENT_VALUE_CHANGED: return "EVENT_OBJECT_VALUECHANGE";
5276                         case ACC.EVENT_STATE_CHANGED: return "EVENT_OBJECT_STATECHANGE";
5277                         case ACC.EVENT_SELECTION_CHANGED: return "EVENT_OBJECT_SELECTIONWITHIN";
5278                         case ACC.EVENT_TEXT_SELECTION_CHANGED: return "EVENT_OBJECT_TEXTSELECTIONCHANGED";
5279                         case ACC.EVENT_LOCATION_CHANGED: return "EVENT_OBJECT_LOCATIONCHANGE";
5280                         case ACC.EVENT_NAME_CHANGED: return "EVENT_OBJECT_NAMECHANGE";
5281                         case ACC.EVENT_DESCRIPTION_CHANGED: return "EVENT_OBJECT_DESCRIPTIONCHANGE";
5282                         case ACC.EVENT_DOCUMENT_LOAD_COMPLETE: return "IA2_EVENT_DOCUMENT_LOAD_COMPLETE";
5283                         case ACC.EVENT_DOCUMENT_LOAD_STOPPED: return "IA2_EVENT_DOCUMENT_LOAD_STOPPED";
5284                         case ACC.EVENT_DOCUMENT_RELOAD: return "IA2_EVENT_DOCUMENT_RELOAD";
5285                         case ACC.EVENT_PAGE_CHANGED: return "IA2_EVENT_PAGE_CHANGED";
5286                         case ACC.EVENT_SECTION_CHANGED: return "IA2_EVENT_SECTION_CHANGED";
5287                         case ACC.EVENT_ACTION_CHANGED: return "IA2_EVENT_ACTION_CHANGED";
5288                         case ACC.EVENT_HYPERLINK_START_INDEX_CHANGED: return "IA2_EVENT_HYPERLINK_START_INDEX_CHANGED";
5289                         case ACC.EVENT_HYPERLINK_END_INDEX_CHANGED: return "IA2_EVENT_HYPERLINK_END_INDEX_CHANGED";
5290                         case ACC.EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED: return "IA2_EVENT_HYPERLINK_ANCHOR_COUNT_CHANGED";
5291                         case ACC.EVENT_HYPERLINK_SELECTED_LINK_CHANGED: return "IA2_EVENT_HYPERLINK_SELECTED_LINK_CHANGED";
5292                         case ACC.EVENT_HYPERLINK_ACTIVATED: return "IA2_EVENT_HYPERLINK_ACTIVATED";
5293                         case ACC.EVENT_HYPERTEXT_LINK_COUNT_CHANGED: return "IA2_EVENT_HYPERTEXT_LINK_COUNT_CHANGED";
5294                         case ACC.EVENT_ATTRIBUTE_CHANGED: return "IA2_EVENT_ATTRIBUTE_CHANGED";
5295                         case ACC.EVENT_TABLE_CAPTION_CHANGED: return "IA2_EVENT_TABLE_CAPTION_CHANGED";
5296                         case ACC.EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED: return "IA2_EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED";
5297                         case ACC.EVENT_TABLE_COLUMN_HEADER_CHANGED: return "IA2_EVENT_TABLE_COLUMN_HEADER_CHANGED";
5298                         case ACC.EVENT_TABLE_ROW_DESCRIPTION_CHANGED: return "IA2_EVENT_TABLE_ROW_DESCRIPTION_CHANGED";
5299                         case ACC.EVENT_TABLE_ROW_HEADER_CHANGED: return "IA2_EVENT_TABLE_ROW_HEADER_CHANGED";
5300                         case ACC.EVENT_TABLE_SUMMARY_CHANGED: return "IA2_EVENT_TABLE_SUMMARY_CHANGED";
5301                         case ACC.EVENT_TEXT_ATTRIBUTE_CHANGED: return "IA2_EVENT_TEXT_ATTRIBUTE_CHANGED";
5302                         case ACC.EVENT_TEXT_CARET_MOVED: return "IA2_EVENT_TEXT_CARET_MOVED";
5303                         case ACC.EVENT_TEXT_COLUMN_CHANGED: return "IA2_EVENT_TEXT_COLUMN_CHANGED";
5304                 }
5305                 return "Unknown event (" + event + ")";
5306         }
5307         private String hresult(int code) {
5308                 if (DEBUG) switch (code) {
5309                         case COM.S_OK: return " S_OK";
5310                         case COM.S_FALSE: return " S_FALSE";
5311                         case COM.E_ACCESSDENIED: return " E_ACCESSDENIED";
5312                         case COM.E_FAIL: return " E_FAIL";
5313                         case COM.E_INVALIDARG: return " E_INVALIDARG";
5314                         case COM.E_NOINTERFACE: return " E_NOINTERFACE";
5315                         case COM.E_NOTIMPL: return " E_NOTIMPL";
5316                         case COM.E_NOTSUPPORTED: return " E_NOTSUPPORTED";
5317                         case COM.E_OUTOFMEMORY: return " E_OUTOFMEMORY";
5318                         case OS.E_POINTER: return " E_POINTER";
5319                         case COM.DISP_E_EXCEPTION: return " DISP_E_EXCEPTION";
5320                         case COM.DISP_E_MEMBERNOTFOUND: return " DISP_E_MEMBERNOTFOUND";
5321                         case COM.DISP_E_UNKNOWNINTERFACE: return " DISP_E_UNKNOWNINTERFACE";
5322                         case COM.DISP_E_UNKNOWNNAME: return " DISP_E_UNKNOWNNAME";
5323                 }
5324                 return " HRESULT=" + code;
5325         }
5326         boolean interesting(GUID guid) {
5327                 if (DEBUG) {
5328                 if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) return true;
5329                 if (COM.IsEqualGUID(guid, COM.IIDIAccessible)) return true;
5330                 if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) return true;
5331                 if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) return true;
5332                 if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) return true;
5333                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleRelation)) return true;
5334                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) return true;
5335                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) return true;
5336                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) return true;
5337                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) return true;
5338                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) return true;
5339                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) return true;
5340                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) return true;
5341                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) return true;
5342                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) return true;
5343                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) return true;
5344                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) return true;
5345                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) return true;
5346                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleContext)) return true;
5347                 }
5348                 return false;
5349         }
5350         String guidString(GUID guid) {
5351                 if (DEBUG) {
5352                 final GUID IIDIAccessibleHandler = IIDFromString("{03022430-ABC4-11D0-BDE2-00AA001A1953}"); //$NON-NLS-1$
5353                 final GUID IIDIAccessor = IIDFromString("{0C733A8C-2A1C-11CE-ADE5-00AA0044773D}"); //$NON-NLS-1$
5354                 final GUID IIDIAdviseSink2 = IIDFromString("{00000125-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5355                 final GUID IIDIBindCtx = IIDFromString("{0000000E-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5356                 final GUID IIDICreateErrorInfo = IIDFromString("{22F03340-547D-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
5357                 final GUID IIDICreateTypeInfo = IIDFromString("{00020405-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5358                 final GUID IIDICreateTypeLib = IIDFromString("{00020406-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5359                 final GUID IIDIDataAdviseHolder = IIDFromString("{00000110-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5360                 final GUID IIDIEnumConnectionPoints = IIDFromString("{B196B285-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
5361                 final GUID IIDIEnumConnections = IIDFromString("{B196B287-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
5362                 final GUID IIDIEnumMoniker = IIDFromString("{00000102-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5363                 final GUID IIDIEnumOLEVERB = IIDFromString("{00000104-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5364                 final GUID IIDIEnumSTATDATA = IIDFromString("{00000105-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5365                 final GUID IIDIEnumSTATSTG = IIDFromString("{0000000D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5366                 final GUID IIDIEnumString = IIDFromString("{00000101-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5367                 final GUID IIDIEnumUnknown = IIDFromString("{00000100-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5368                 final GUID IIDIErrorInfo = IIDFromString("{1CF2B120-547D-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
5369                 final GUID IIDIErrorLog = IIDFromString("{3127CA40-446E-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
5370                 final GUID IIDIExternalConnection = IIDFromString("{00000019-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5371                 final GUID IIDIFontDisp = IIDFromString("{BEF6E003-A874-101A-8BBA-00AA00300CAB}"); //$NON-NLS-1$
5372                 final GUID IIDILockBytes = IIDFromString("{0000000A-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5373                 final GUID IIDIMalloc = IIDFromString("{00000002-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5374                 final GUID IIDIMallocSpy = IIDFromString("{0000001D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5375                 final GUID IIDIMarshal = IIDFromString("{00000003-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5376                 final GUID IIDIMessageFilter = IIDFromString("{00000016-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5377                 final GUID IIDIMoniker = IIDFromString("{0000000F-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5378                 final GUID IIDIOleAdviseHolder = IIDFromString("{00000111-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5379                 final GUID IIDIOleCache = IIDFromString("{0000011E-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5380                 final GUID IIDIOleCache2 = IIDFromString("{00000128-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5381                 final GUID IIDIOleCacheControl = IIDFromString("{00000129-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5382                 final GUID IIDIOleItemContainer = IIDFromString("{0000011C-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5383                 final GUID IIDIParseDisplayName = IIDFromString("{0000011A-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5384                 final GUID IIDIPerPropertyBrowsing = IIDFromString("{376BD3AA-3845-101B-84ED-08002B2EC713}"); //$NON-NLS-1$
5385                 final GUID IIDIPersistMemory = IIDFromString("{BD1AE5E0-A6AE-11CE-BD37-504200C10000}"); //$NON-NLS-1$
5386                 final GUID IIDIPersistPropertyBag = IIDFromString("{37D84F60-42CB-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
5387                 final GUID IIDIPicture = IIDFromString("{7BF80980-BF32-101A-8BBB-00AA00300CAB}"); //$NON-NLS-1$
5388                 final GUID IIDIPictureDisp = IIDFromString("{7BF80981-BF32-101A-8BBB-00AA00300CAB}"); //$NON-NLS-1$
5389                 final GUID IIDIPropertyBag = IIDFromString("{55272A00-42CB-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
5390                 final GUID IIDIPropertyPage = IIDFromString("{B196B28D-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
5391                 final GUID IIDIPropertyPage2 = IIDFromString("{01E44665-24AC-101B-84ED-08002B2EC713}"); //$NON-NLS-1$
5392                 final GUID IIDIPropertyPageSite = IIDFromString("{B196B28C-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
5393                 final GUID IIDIPSFactoryBuffer = IIDFromString("{D5F569D0-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
5394                 final GUID IIDIRootStorage = IIDFromString("{00000012-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5395                 final GUID IIDIROTData = IIDFromString("{F29F6BC0-5021-11CE-AA15-00006901293F}"); //$NON-NLS-1$
5396                 final GUID IIDIRpcChannelBuffer = IIDFromString("{D5F56B60-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
5397                 final GUID IIDIRpcProxyBuffer = IIDFromString("{D5F56A34-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
5398                 final GUID IIDIRpcStubBuffer = IIDFromString("{D5F56AFC-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
5399                 final GUID IIDIRunnableObject = IIDFromString("{00000126-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5400                 final GUID IIDIRunningObjectTable = IIDFromString("{00000010-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5401                 final GUID IIDISimpleFrameSite = IIDFromString("{742B0E01-14E6-101B-914E-00AA00300CAB}"); //$NON-NLS-1$
5402                 final GUID IIDIStdMarshalInfo = IIDFromString("{00000018-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5403                 final GUID IIDISupportErrorInfo = IIDFromString("{DF0B3D60-548F-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
5404                 final GUID IIDITypeComp = IIDFromString("{00020403-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5405                 final GUID IIDITypeLib = IIDFromString("{00020402-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5406                 final GUID IIDIViewObject = IIDFromString("{0000010D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
5407                 final GUID IIDIdentityUnmarshal = IIDFromString("{0000001b-0000-0000-c000-000000000046}"); //$NON-NLS-1$
5408                 final GUID IIDInternalMSMarshaller = IIDFromString("{4c1e39e1-e3e3-4296-aa86-ec938d896e92}"); //$NON-NLS-1$
5409                 final GUID IIDIAccIdentity = IIDFromString("{7852B78D-1CFD-41C1-A615-9C0C85960B5F}"); //$NON-NLS-1$
5410                 final GUID IIDIAccPropServer = IIDFromString("{76C0DBBB-15E0-4E7B-B61B-20EEEA2001E0}"); //$NON-NLS-1$
5411                 final GUID IIDIAccPropServices = IIDFromString("{6E26E776-04F0-495D-80E4-3330352E3169}"); //$NON-NLS-1$
5412                 if (COM.IsEqualGUID(guid, COM.IID_IDropTargetHelper)) return "IID_IDropTargetHelper";
5413                 if (COM.IsEqualGUID(guid, COM.IIDJavaBeansBridge)) return "IIDJavaBeansBridge";
5414                 if (COM.IsEqualGUID(guid, COM.IIDShockwaveActiveXControl)) return "IIDShockwaveActiveXControl";
5415                 if (COM.IsEqualGUID(guid, COM.IIDIAccessible)) return "IIDIAccessible";
5416                 if (COM.IsEqualGUID(guid, IIDIAccessibleHandler)) return "IIDIAccessibleHandler";
5417                 if (COM.IsEqualGUID(guid, IIDIAccessor)) return "IIDIAccessor";
5418                 if (COM.IsEqualGUID(guid, COM.IIDIAdviseSink)) return "IIDIAdviseSink";
5419                 if (COM.IsEqualGUID(guid, IIDIAdviseSink2)) return "IIDIAdviseSink2";
5420                 if (COM.IsEqualGUID(guid, IIDIBindCtx)) return "IIDIBindCtx";
5421                 if (COM.IsEqualGUID(guid, COM.IIDIClassFactory)) return "IIDIClassFactory";
5422                 if (COM.IsEqualGUID(guid, COM.IIDIClassFactory2)) return "IIDIClassFactory2";
5423                 if (COM.IsEqualGUID(guid, COM.IIDIConnectionPointContainer)) return "IIDIConnectionPointContainer";
5424                 if (COM.IsEqualGUID(guid, IIDICreateErrorInfo)) return "IIDICreateErrorInfo";
5425                 if (COM.IsEqualGUID(guid, IIDICreateTypeInfo)) return "IIDICreateTypeInfo";
5426                 if (COM.IsEqualGUID(guid, IIDICreateTypeLib)) return "IIDICreateTypeLib";
5427                 if (COM.IsEqualGUID(guid, IIDIDataAdviseHolder)) return "IIDIDataAdviseHolder";
5428                 if (COM.IsEqualGUID(guid, COM.IIDIDataObject)) return "IIDIDataObject";
5429                 if (COM.IsEqualGUID(guid, COM.IIDIDispatch)) return "IIDIDispatch";
5430                 if (COM.IsEqualGUID(guid, COM.IIDIDispatchEx)) return "IIDIDispatchEx";
5431                 if (COM.IsEqualGUID(guid, COM.IIDIDocHostUIHandler)) return "IIDIDocHostUIHandler";
5432                 if (COM.IsEqualGUID(guid, COM.IIDIDocHostShowUI)) return "IIDIDocHostShowUI";
5433                 if (COM.IsEqualGUID(guid, COM.IIDIDropSource)) return "IIDIDropSource";
5434                 if (COM.IsEqualGUID(guid, COM.IIDIDropTarget)) return "IIDIDropTarget";
5435                 if (COM.IsEqualGUID(guid, IIDIEnumConnectionPoints)) return "IIDIEnumConnectionPoints";
5436                 if (COM.IsEqualGUID(guid, IIDIEnumConnections)) return "IIDIEnumConnections";
5437                 if (COM.IsEqualGUID(guid, COM.IIDIEnumFORMATETC)) return "IIDIEnumFORMATETC";
5438                 if (COM.IsEqualGUID(guid, IIDIEnumMoniker)) return "IIDIEnumMoniker";
5439                 if (COM.IsEqualGUID(guid, IIDIEnumOLEVERB)) return "IIDIEnumOLEVERB";
5440                 if (COM.IsEqualGUID(guid, IIDIEnumSTATDATA)) return "IIDIEnumSTATDATA";
5441                 if (COM.IsEqualGUID(guid, IIDIEnumSTATSTG)) return "IIDIEnumSTATSTG";
5442                 if (COM.IsEqualGUID(guid, IIDIEnumString)) return "IIDIEnumString";
5443                 if (COM.IsEqualGUID(guid, IIDIEnumUnknown)) return "IIDIEnumUnknown";
5444                 if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) return "IIDIEnumVARIANT";
5445                 if (COM.IsEqualGUID(guid, IIDIErrorInfo)) return "IIDIErrorInfo";
5446                 if (COM.IsEqualGUID(guid, IIDIErrorLog)) return "IIDIErrorLog";
5447                 if (COM.IsEqualGUID(guid, IIDIExternalConnection)) return "IIDIExternalConnection";
5448                 if (COM.IsEqualGUID(guid, IIDIFontDisp)) return "IIDIFontDisp";
5449         //      if (COM.IsEqualGUID(guid, COM.IIDIHTMLDocumentEvents2)) return "IIDIHTMLDocumentEvents2";
5450                 if (COM.IsEqualGUID(guid, COM.IIDIInternetSecurityManager)) return "IIDIInternetSecurityManager";
5451                 if (COM.IsEqualGUID(guid, COM.IIDIAuthenticate)) return "IIDIAuthenticate";
5452                 if (COM.IsEqualGUID(guid, COM.IIDIJScriptTypeInfo)) return "IIDIJScriptTypeInfo";
5453                 if (COM.IsEqualGUID(guid, IIDILockBytes)) return "IIDILockBytes";
5454                 if (COM.IsEqualGUID(guid, IIDIMalloc)) return "IIDIMalloc";
5455                 if (COM.IsEqualGUID(guid, IIDIMallocSpy)) return "IIDIMallocSpy";
5456                 if (COM.IsEqualGUID(guid, IIDIMarshal)) return "IIDIMarshal";
5457                 if (COM.IsEqualGUID(guid, IIDIMessageFilter)) return "IIDIMessageFilter";
5458                 if (COM.IsEqualGUID(guid, IIDIMoniker)) return "IIDIMoniker";
5459                 if (COM.IsEqualGUID(guid, IIDIOleAdviseHolder)) return "IIDIOleAdviseHolder";
5460                 if (COM.IsEqualGUID(guid, IIDIOleCache)) return "IIDIOleCache";
5461                 if (COM.IsEqualGUID(guid, IIDIOleCache2)) return "IIDIOleCache2";
5462                 if (COM.IsEqualGUID(guid, IIDIOleCacheControl)) return "IIDIOleCacheControl";
5463                 if (COM.IsEqualGUID(guid, COM.IIDIOleClientSite)) return "IIDIOleClientSite";
5464                 if (COM.IsEqualGUID(guid, COM.IIDIOleCommandTarget)) return "IIDIOleCommandTarget";
5465                 if (COM.IsEqualGUID(guid, COM.IIDIOleControl)) return "IIDIOleControl";
5466                 if (COM.IsEqualGUID(guid, COM.IIDIOleControlSite)) return "IIDIOleControlSite";
5467                 if (COM.IsEqualGUID(guid, COM.IIDIOleDocument)) return "IIDIOleDocument";
5468                 if (COM.IsEqualGUID(guid, COM.IIDIOleDocumentSite)) return "IIDIOleDocumentSite";
5469                 if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceFrame)) return "IIDIOleInPlaceFrame";
5470                 if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceObject)) return "IIDIOleInPlaceObject";
5471                 if (COM.IsEqualGUID(guid, COM.IIDIOleInPlaceSite)) return "IIDIOleInPlaceSite";
5472                 if (COM.IsEqualGUID(guid, IIDIOleItemContainer)) return "IIDIOleItemContainer";
5473                 if (COM.IsEqualGUID(guid, COM.IIDIOleLink)) return "IIDIOleLink";
5474                 if (COM.IsEqualGUID(guid, COM.IIDIOleObject)) return "IIDIOleObject";
5475                 if (COM.IsEqualGUID(guid, IIDIParseDisplayName)) return "IIDIParseDisplayName";
5476                 if (COM.IsEqualGUID(guid, IIDIPerPropertyBrowsing)) return "IIDIPerPropertyBrowsing";
5477                 if (COM.IsEqualGUID(guid, COM.IIDIPersist)) return "IIDIPersist";
5478                 if (COM.IsEqualGUID(guid, COM.IIDIPersistFile)) return "IIDIPersistFile";
5479                 if (COM.IsEqualGUID(guid, IIDIPersistMemory)) return "IIDIPersistMemory";
5480                 if (COM.IsEqualGUID(guid, IIDIPersistPropertyBag)) return "IIDIPersistPropertyBag";
5481                 if (COM.IsEqualGUID(guid, COM.IIDIPersistStorage)) return "IIDIPersistStorage";
5482                 if (COM.IsEqualGUID(guid, COM.IIDIPersistStreamInit)) return "IIDIPersistStreamInit";
5483                 if (COM.IsEqualGUID(guid, IIDIPicture)) return "IIDIPicture";
5484                 if (COM.IsEqualGUID(guid, IIDIPictureDisp)) return "IIDIPictureDisp";
5485                 if (COM.IsEqualGUID(guid, IIDIPropertyBag)) return "IIDIPropertyBag";
5486                 if (COM.IsEqualGUID(guid, COM.IIDIPropertyNotifySink)) return "IIDIPropertyNotifySink";
5487                 if (COM.IsEqualGUID(guid, IIDIPropertyPage)) return "IIDIPropertyPage";
5488                 if (COM.IsEqualGUID(guid, IIDIPropertyPage2)) return "IIDIPropertyPage2";
5489                 if (COM.IsEqualGUID(guid, IIDIPropertyPageSite)) return "IIDIPropertyPageSite";
5490                 if (COM.IsEqualGUID(guid, COM.IIDIProvideClassInfo)) return "IIDIProvideClassInfo";
5491                 if (COM.IsEqualGUID(guid, COM.IIDIProvideClassInfo2)) return "IIDIProvideClassInfo2";
5492                 if (COM.IsEqualGUID(guid, IIDIPSFactoryBuffer)) return "IIDIPSFactoryBuffer";
5493                 if (COM.IsEqualGUID(guid, IIDIRootStorage)) return "IIDIRootStorage";
5494                 if (COM.IsEqualGUID(guid, IIDIROTData)) return "IIDIROTData";
5495                 if (COM.IsEqualGUID(guid, IIDIRpcChannelBuffer)) return "IIDIRpcChannelBuffer";
5496                 if (COM.IsEqualGUID(guid, IIDIRpcProxyBuffer)) return "IIDIRpcProxyBuffer";
5497                 if (COM.IsEqualGUID(guid, IIDIRpcStubBuffer)) return "IIDIRpcStubBuffer";
5498                 if (COM.IsEqualGUID(guid, IIDIRunnableObject)) return "IIDIRunnableObject";
5499                 if (COM.IsEqualGUID(guid, IIDIRunningObjectTable)) return "IIDIRunningObjectTable";
5500                 if (COM.IsEqualGUID(guid, IIDISimpleFrameSite)) return "IIDISimpleFrameSite";
5501                 if (COM.IsEqualGUID(guid, COM.IIDIServiceProvider)) return "IIDIServiceProvider";
5502                 if (COM.IsEqualGUID(guid, COM.IIDISpecifyPropertyPages)) return "IIDISpecifyPropertyPages";
5503                 if (COM.IsEqualGUID(guid, IIDIStdMarshalInfo)) return "IIDIStdMarshalInfo";
5504                 if (COM.IsEqualGUID(guid, IIDISupportErrorInfo)) return "IIDISupportErrorInfo";
5505                 if (COM.IsEqualGUID(guid, IIDITypeComp)) return "IIDITypeComp";
5506                 if (COM.IsEqualGUID(guid, IIDITypeLib)) return "IIDITypeLib";
5507                 if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) return "IIDIUnknown";
5508                 if (COM.IsEqualGUID(guid, IIDIViewObject)) return "IIDIViewObject";
5509                 if (COM.IsEqualGUID(guid, COM.IIDIViewObject2)) return "IIDIViewObject2";
5510                 if (COM.IsEqualGUID(guid, COM.CGID_DocHostCommandHandler)) return "CGID_DocHostCommandHandler";
5511                 if (COM.IsEqualGUID(guid, COM.CGID_Explorer)) return "CGID_Explorer";
5512                 if (COM.IsEqualGUID(guid, COM.IIDIAccessible2)) return "IIDIAccessible2";
5513                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleRelation)) return "IIDIAccessibleRelation";
5514                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleAction)) return "IIDIAccessibleAction";
5515                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleComponent)) return "IIDIAccessibleComponent";
5516                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleValue)) return "IIDIAccessibleValue";
5517                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleText)) return "IIDIAccessibleText";
5518                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleEditableText)) return "IIDIAccessibleEditableText";
5519                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHyperlink)) return "IIDIAccessibleHyperlink";
5520                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleHypertext)) return "IIDIAccessibleHypertext";
5521                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable)) return "IIDIAccessibleTable";
5522                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTable2)) return "IIDIAccessibleTable2";
5523                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleTableCell)) return "IIDIAccessibleTableCell";
5524                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleImage)) return "IIDIAccessibleImage";
5525                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleApplication)) return "IIDIAccessibleApplication";
5526                 if (COM.IsEqualGUID(guid, COM.IIDIAccessibleContext)) return "IIDIAccessibleContext";
5527                 if (COM.IsEqualGUID(guid, IIDIdentityUnmarshal)) return "IIDIdentityUnmarshal";
5528                 if (COM.IsEqualGUID(guid, IIDInternalMSMarshaller)) return "IIDInternalMSMarshaller";
5529                 if (COM.IsEqualGUID(guid, IIDIAccIdentity)) return "IIDIAccIdentity";
5530                 if (COM.IsEqualGUID(guid, IIDIAccPropServer)) return "IIDIAccPropServer";
5531                 if (COM.IsEqualGUID(guid, IIDIAccPropServices)) return "IIDIAccPropServices";
5532                 }
5533                 return guid.toString();
5534         }
5535         static GUID IIDFromString(String lpsz) {
5536                 if (DEBUG) {
5537                 int length = lpsz.length();
5538                 char[] buffer = new char[length + 1];
5539                 lpsz.getChars(0, length, buffer, 0);
5540                 GUID lpiid = new GUID();
5541                 if (COM.IIDFromString(buffer, lpiid) == COM.S_OK) return lpiid;
5542                 }
5543                 return null;
5544         }
5545         @Override
5546         public String toString () {
5547                 String toString = super.toString();
5548                 if (DEBUG) {
5549                         int role = getRole();
5550                         if (role == 0) role = getDefaultRole();
5551                         return toString.substring(toString.lastIndexOf('.') + 1) + "(" + getRoleString(role) + ")";
5552                 }
5553                 return toString;
5554         }
5555         // END DEBUG CODE
5556 }