AccessInfo.cpp revision 13237:b7f007bedafb
1/*
2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include "AccessBridgeCalls.h"
27#include "AccessInfo.h"
28#include <stdio.h>
29#include <time.h>
30
31LogStringCallbackFP g_LogStringCallback = NULL;
32
33/*
34 * returns formatted date and time
35 */
36char *getTimeAndDate() {
37    static char datebuf[64];
38    struct tm *newtime;
39    char am_pm[] = "AM";
40    time_t long_time;
41
42    time( &long_time );                /* Get time as long integer. */
43    newtime = localtime( &long_time ); /* Convert to local time. */
44
45    if( newtime->tm_hour > 12 )        /* Set up extension. */
46        strcpy( am_pm, "PM" );
47    if( newtime->tm_hour > 12 )        /* Convert from 24-hour */
48                newtime->tm_hour -= 12;    /*   to 12-hour clock.  */
49    if( newtime->tm_hour == 0 )        /*Set hour to 12 if midnight. */
50        newtime->tm_hour = 12;
51
52    sprintf(datebuf, "%.19s %s\n", asctime( newtime ), am_pm );
53    return (char *)datebuf;
54}
55
56
57/*
58 * displays a message in a dialog and writes the message to a logfile
59 */
60void displayAndLog(HWND hDlg, int nIDDlgItem, FILE *logfile, char *msg, ...) {
61
62    if (hDlg == NULL || msg == NULL) {
63        return;
64    }
65
66    char tmpbuf[HUGE_BUFSIZE];
67    va_list argprt;
68
69    va_start(argprt, msg);
70    vsprintf(tmpbuf, msg, argprt);
71
72    SetDlgItemText(hDlg, nIDDlgItem, tmpbuf);
73
74    fprintf(logfile, "\n****************************************\n");
75    fprintf(logfile, "%s\n", getTimeAndDate());
76    fprintf(logfile, "%s\n", tmpbuf);
77    fflush(logfile);
78
79    if ( NULL != g_LogStringCallback )
80    {
81        g_LogStringCallback (tmpbuf);
82    }
83}
84
85/*
86 * writes a text string to a logfile
87 */
88void logString(FILE *logfile, char *msg, ...) {
89
90    if (logfile == NULL || msg == NULL) {
91        return;
92    }
93
94    char tmpbuf[LINE_BUFSIZE];
95    va_list argprt;
96
97    va_start(argprt, msg);
98    vsprintf(tmpbuf, msg, argprt);
99
100    fprintf(logfile, tmpbuf);
101    fprintf(logfile, "\n");
102    fflush(logfile);
103}
104
105/*
106 * safely appends a message to a buffer
107 */
108BOOL appendToBuffer(char *buf, size_t buflen, char *msg, ...) {
109
110    static char warning[] =
111        "\nNot enough buffer space; remaining information truncated.\n";
112    size_t warningLength = strlen(warning) + 1;
113
114    if (buf == NULL || msg == NULL) {
115        return FALSE;
116    }
117
118    char tmpbuf[LARGE_BUFSIZE];
119    va_list argprt;
120
121    va_start(argprt, msg);
122    vsprintf(tmpbuf, msg, argprt);
123
124    // verify there's enough space in the buffer
125    size_t spaceRemaining = buflen - strlen(buf) - 1;
126    if (spaceRemaining <= warningLength) {
127        strncat(buf, warning, spaceRemaining);
128        return FALSE;
129    }
130    strncat(buf, tmpbuf, spaceRemaining);
131    return TRUE;
132}
133
134/**
135 * returns accessibility information for an AccessibleContext
136 */
137char *getAccessibleInfo(long vmID, AccessibleContext ac, char *buffer,
138                        int bufsize) {
139    return getAccessibleInfo(vmID, ac, 0, 0, buffer, bufsize);
140}
141
142/**
143 * returns accessibility information at the specified coordinates in an
144 * AccessibleContext
145 */
146char *getAccessibleInfo(long vmID, AccessibleContext ac, int x, int y,
147                        char *buffer, int bufsize) {
148
149    wchar_t tmpBuf[LINE_BUFSIZE];
150    wchar_t name[LINE_BUFSIZE];
151    int i, j;
152    long start;
153    long end;
154
155    if (buffer == NULL || bufsize <= 0) {
156        return NULL;
157    }
158    buffer[0] = NULL;
159
160    /* ===== AccessBridge / J2SE version information ===== */
161
162    AccessBridgeVersionInfo versionInfo;
163    BOOL result = GetVersionInfo(vmID, &versionInfo);
164
165    if (result == FALSE) {
166        appendToBuffer( buffer, bufsize,
167                        "\r\nERROR: cannot get version information", bufsize );
168    } else {
169        appendToBuffer(buffer, bufsize, "Version Information:");
170        appendToBuffer( buffer, bufsize,
171                        "\r\n    Java virtual machine version: %ls",
172                        versionInfo.VMversion );
173        appendToBuffer( buffer, bufsize,
174                        "\r\n    Access Bridge Java class version: %ls",
175                        versionInfo.bridgeJavaClassVersion );
176        appendToBuffer( buffer, bufsize,
177                        "\r\n    Access Bridge Java DLL version: %ls",
178                        versionInfo.bridgeJavaDLLVersion );
179        appendToBuffer( buffer, bufsize,
180                        "\r\n    Access Bridge Windows DLL version: %ls",
181                        versionInfo.bridgeWinDLLVersion );
182    }
183
184    if (ac == (AccessibleContext) 0) {
185        return buffer;
186    }
187
188
189    /* ===== core AccessibleContext information ===== */
190
191    AccessibleContextInfo info;
192    if (GetAccessibleContextInfo(vmID, ac, &info) == FALSE) {
193        appendToBuffer( buffer, bufsize,
194                        "\r\nERROR: GetAccessibleContextInfo failed ", bufsize );
195    } else {
196        appendToBuffer( buffer, bufsize,
197                        "\r\n\r\nAccessibleContext information", bufsize );
198        if (x >= 0 && y >= 0) {
199            appendToBuffer(buffer, bufsize, " at mouse point [%d, %d]:", x, y);
200        } else {
201            appendToBuffer(buffer, bufsize, ":", bufsize);
202        }
203
204        appendToBuffer(buffer, bufsize, "\r\n    Name:  %ls", info.name);
205        if ( getVirtualAccessibleName( vmID, ac, name,
206                                       (sizeof(name) / sizeof(wchar_t)) ) == FALSE ) {
207            appendToBuffer( buffer, bufsize,
208                            "\r\n\r\nERROR: getVirtualAccessibleName", bufsize );
209        } else {
210            appendToBuffer(buffer, bufsize, "\r\n    Virtual Name:  %ls", name);
211        }
212        appendToBuffer( buffer, bufsize, "\r\n    Description:  %ls",
213                        info.description );
214        appendToBuffer(buffer, bufsize, "\r\n    Role:  %ls", info.role);
215        appendToBuffer( buffer, bufsize, "\r\n    Role in en_US locale:  %ls",
216                        info.role_en_US );
217        appendToBuffer(buffer, bufsize, "\r\n    States:  %ls", info.states);
218        appendToBuffer( buffer, bufsize, "\r\n    States in en_US locale:  %ls",
219                        info.states_en_US );
220        appendToBuffer( buffer, bufsize, "\r\n    Index in parent:  %d",
221                        info.indexInParent );
222        appendToBuffer( buffer, bufsize, "\r\n    Children count:  %d",
223                        info.childrenCount );
224        appendToBuffer( buffer, bufsize,
225                        "\r\n    Bounding rectangle:  [%d, %d, %d, %d]",
226                        info.x, info.y, info.x + info.width,
227                        info.y + info.height );
228
229        /*  top-level window info */
230        AccessibleContext topAC  = getTopLevelObject(vmID, ac);
231        if (topAC == NULL) {
232            appendToBuffer( buffer, bufsize,
233                            "\r\nERROR: getTopLevelObject failed", bufsize );
234        } else {
235            AccessibleContextInfo topInfo;
236            if (GetAccessibleContextInfo(vmID, topAC, &topInfo) == FALSE) {
237                appendToBuffer(
238                    buffer, bufsize,
239                    "\r\nERROR: GetAccessibleContextInfo failed for top-level window ",
240                    bufsize );
241            } else {
242                if (getVirtualAccessibleName(vmID, topAC, name,
243                        (sizeof(name) / sizeof(wchar_t)) ) == FALSE) {
244                    appendToBuffer( buffer, bufsize,
245                                    "\r\n\r\nERROR: getVirtualAccessibleName",
246                                    bufsize );
247                } else {
248                    appendToBuffer( buffer, bufsize,
249                                    "\r\n    Top-level window name:  %ls",
250                                    name );
251                }
252                appendToBuffer( buffer, bufsize,
253                                "\r\n    Top-level window role:  %ls",
254                                topInfo.role ) ;
255            }
256            ReleaseJavaObject(vmID, topAC);
257
258        }
259
260        /* ===== AccessibleParent information ===== */
261
262        AccessibleContext parentAC = GetAccessibleParentFromContext(vmID, ac);
263        if (parentAC == NULL) {
264            appendToBuffer(buffer, bufsize, "\r\n    No parent", bufsize);
265        } else {
266            AccessibleContextInfo parentInfo;
267            if (GetAccessibleContextInfo(vmID, parentAC, &parentInfo) == FALSE) {
268                appendToBuffer( buffer, bufsize,
269                    "\r\nERROR: GetAccessibleContextInfo failed for parent",
270                    bufsize );
271            } else {
272                appendToBuffer( buffer, bufsize, "\r\n    Parent name:  %ls",
273                                parentInfo.name );
274                if ( getVirtualAccessibleName( vmID, parentAC, name,
275                        (sizeof(name) / sizeof(wchar_t)) ) == FALSE ) {
276                    appendToBuffer( buffer, bufsize,
277                                    "\r\n\r\nERROR: getVirtualAccessibleName",
278                                    bufsize );
279                } else {
280                    appendToBuffer( buffer, bufsize,
281                                    "\r\n    Parent virtual name:  %ls", name );
282                }
283                appendToBuffer( buffer, bufsize, "\r\n    Parent role:  %ls",
284                                parentInfo.role );
285            }
286            ReleaseJavaObject(vmID, parentAC);
287        }
288
289
290        /* ====== visible children ===== */
291        int nChildren = getVisibleChildrenCount(vmID, ac);
292        if (nChildren == -1) {
293            appendToBuffer( buffer, bufsize,
294                            "\r\nERROR: GetVisibleChildrenCount failed",
295                            bufsize );
296        } else {
297            appendToBuffer( buffer, bufsize,
298                            "\r\n    Visible descendents count:  %d",
299                            nChildren );
300        }
301
302        if (nChildren > 0) {
303            VisibleChildrenInfo visibleChildrenInfo;
304            if (getVisibleChildren(vmID, ac, 0, &visibleChildrenInfo) == FALSE) {
305                appendToBuffer( buffer, bufsize,
306                                "\r\nERROR: GetVisibleChildren failed",
307                                bufsize );
308            } else {
309                AccessibleContextInfo childACInfo;
310                for ( int child = 0;
311                      child < visibleChildrenInfo.returnedChildrenCount;
312                      child++ ) {
313                    AccessibleContext childAC =
314                        visibleChildrenInfo.children[child];
315                    if (GetAccessibleContextInfo(vmID, childAC, &childACInfo)) {
316                        if ( getVirtualAccessibleName( vmID, childAC, name,
317                                (sizeof(name) / sizeof(wchar_t))) == FALSE) {
318                            appendToBuffer( buffer, bufsize,
319                                "\r\n\r\nERROR: getVirtualAccessibleName",
320                                bufsize );
321                        } else {
322                            appendToBuffer( buffer, bufsize,
323                                "\r\n    Descendent %d name:  %ls", child,
324                                name );
325                        }
326                        appendToBuffer( buffer, bufsize,
327                                        "\r\n    Descendent %d role:  %ls",
328                                        child, childACInfo.role );
329                    }
330                    ReleaseJavaObject(vmID, childAC);
331                }
332            }
333        }
334
335        /* ===== AccessibleSelection ===== */
336
337        if (info.accessibleSelection == TRUE) {
338
339            int selCount;
340            AccessibleContext selectedAC;
341
342            appendToBuffer( buffer, bufsize,
343                            "\r\n\r\nAccessible Selection information:",
344                            bufsize );
345
346            if ((selCount = GetAccessibleSelectionCountFromContext(vmID, ac)) != -1) {
347                appendToBuffer( buffer, bufsize, "\r\n    Selection count:  %d",
348                                selCount );
349
350                for (i = 0; i < selCount; i++) {
351                    if ( ( selectedAC =
352                            GetAccessibleSelectionFromContext(vmID, ac, i) ) == NULL ) {
353                        appendToBuffer( buffer, bufsize,
354                            "\r\nERROR: GetAccessibleSelectionFromContext failed forselection %d",
355                            i );
356                    } else {
357                        if (GetAccessibleContextInfo(vmID, selectedAC, &info) == FALSE) {
358                            appendToBuffer( buffer, bufsize,
359                                "\r\nERROR: GetAccessibleContextInfo failed for selection %d", i);
360                        } else {
361                            if ( getVirtualAccessibleName( vmID, selectedAC, name,
362                                    (sizeof(name) / sizeof(wchar_t)) ) == FALSE ) {
363                                appendToBuffer( buffer, bufsize,
364                                    "\r\n\r\nERROR: getVirtualAccessibleName", bufsize);
365                            } else {
366                                appendToBuffer( buffer, bufsize,
367                                    "\r\n    Selection %d name: %ls", i, name );
368                            }
369                            appendToBuffer( buffer, bufsize,
370                                "\r\n    Selection %d role: %ls", i, info.role);
371                            appendToBuffer( buffer, bufsize,
372                                "\r\n    Index in parent of selection %d: %d",
373                                i, info.indexInParent );
374                        }
375                        ReleaseJavaObject(vmID, selectedAC);
376                    }
377                }
378            }
379        }
380
381        // ====== Accessible KeyBindings, Icons and Actions ======
382
383        AccessibleKeyBindings keyBindings;
384        if (getAccessibleKeyBindings(vmID, ac, &keyBindings) == TRUE &&
385            keyBindings.keyBindingsCount > 0) {
386
387            appendToBuffer( buffer, bufsize,
388                            "\r\n\r\nAccessibleKeyBinding info:", bufsize );
389            appendToBuffer( buffer, bufsize,
390                            "\r\n    Number of key bindings:  %d",
391                            keyBindings.keyBindingsCount );
392
393            for (j = 0; j < keyBindings.keyBindingsCount; j++) {
394
395                appendToBuffer( buffer, bufsize,
396                                "\r\n    Key binding %d character: %c", j,
397                                keyBindings.keyBindingInfo[j].character );
398                appendToBuffer( buffer, bufsize,
399                                "\r\n    Key binding %d modifiers: %d", j,
400                                keyBindings.keyBindingInfo[j].modifiers );
401            }
402        }
403
404        AccessibleIcons icons;
405        if (getAccessibleIcons(vmID, ac, &icons) == TRUE &&
406            icons.iconsCount > 0) {
407
408            appendToBuffer( buffer, bufsize,
409                            "\r\n\r\nAccessibleIcons info:", bufsize );
410            appendToBuffer( buffer, bufsize,
411                            "\r\n    Number of icons:  %d", icons.iconsCount );
412
413            for (j = 0; j < icons.iconsCount; j++) {
414
415                appendToBuffer( buffer, bufsize,
416                                "\r\n    Icon %d description: %ls", j,
417                                icons.iconInfo[j].description );
418                appendToBuffer( buffer, bufsize,
419                                "\r\n    Icon %d height: %d", j,
420                                icons.iconInfo[j].height );
421                appendToBuffer( buffer, bufsize,
422                                "\r\n    Icon %d width: %d", j,
423                                icons.iconInfo[j].width );
424            }
425        }
426
427        AccessibleActions actions;
428        if (getAccessibleActions(vmID, ac, &actions) == TRUE &&
429            actions.actionsCount > 0) {
430
431            appendToBuffer( buffer, bufsize, "\r\n\r\nAccessibleActions info:",
432                            bufsize );
433            appendToBuffer( buffer, bufsize, "\r\n    Number of actions:  %d",
434                            actions.actionsCount );
435
436            for (j = 0; j < actions.actionsCount; j++) {
437                appendToBuffer( buffer, bufsize, "\r\n    Action %d name: %ls",
438                                j, actions.actionInfo[j].name );
439            }
440        }
441
442        /* ===== AccessibleRelationSet ===== */
443
444        AccessibleRelationSetInfo relationSetInfo;
445        if (getAccessibleRelationSet(vmID, ac, &relationSetInfo) == FALSE) {
446            appendToBuffer( buffer, bufsize,
447                            "\r\nGetAccessibleRelationSet failed.", bufsize );
448        } else {
449            int i;
450            AccessibleContextInfo relInfo;
451
452            if (relationSetInfo.relationCount > 0) {
453                appendToBuffer( buffer, bufsize,
454                                "\r\n\r\nAccessibleRelationSet information:",
455                                bufsize );
456                appendToBuffer( buffer, bufsize,
457                                "\r\n    Number of relations:  %d",
458                                relationSetInfo.relationCount );
459            }
460            for (i = 0; i < relationSetInfo.relationCount; i++) {
461                AccessibleRelationInfo relationInfo =
462                    relationSetInfo.relations[i];
463
464                appendToBuffer( buffer, bufsize,
465                                "\r\n    Relation %d key:  %ls", i,
466                                relationInfo.key );
467                appendToBuffer( buffer, bufsize,
468                                "\r\n    Relation %d target count:  %d", i,
469                                relationInfo.targetCount );
470                for (j = 0; j < relationInfo.targetCount; j++) {
471                    if (GetAccessibleContextInfo(
472                            vmID, relationInfo.targets[j], &relInfo ) == FALSE) {
473                        appendToBuffer( buffer, bufsize,
474                            "\r\nERROR: GetAccessibleContextInfo failed.",
475                            bufsize );
476                    } else {
477                        // Core AccessibleContext information for relation target
478                        if ( getVirtualAccessibleName( vmID, relationInfo.targets[j],
479                                name, (sizeof(name) / sizeof(wchar_t)) ) == FALSE ) {
480                            appendToBuffer( buffer, bufsize,
481                                "\r\n\r\nERROR: getVirtualAccessibleName", bufsize );
482                        } else {
483                            appendToBuffer( buffer, bufsize,
484                                            "\r\n        Target %d name:  %ls",
485                                            j, name );
486                        }
487                        appendToBuffer( buffer, bufsize,
488                                        "\r\n        Target %d role:  %ls", j,
489                                        relInfo.role);
490                    }
491                    ReleaseJavaObject(vmID, relationInfo.targets[j]);
492
493                }
494            }
495        }
496
497        /* ===== AccessibleValue ===== */
498
499        if (info.accessibleInterfaces & cAccessibleValueInterface) {
500
501            appendToBuffer( buffer, bufsize,
502                            "\r\n\r\nAccessible Value information:", bufsize);
503
504            if ( GetCurrentAccessibleValueFromContext( vmID, ac, tmpBuf,
505                    (sizeof(tmpBuf) / sizeof(wchar_t)) ) == TRUE ) {
506                appendToBuffer( buffer, bufsize, "\r\n    Current Value:  %ls",
507                                tmpBuf );
508            }
509            if ( GetMaximumAccessibleValueFromContext( vmID, ac, tmpBuf,
510                    (sizeof(tmpBuf) / sizeof(wchar_t))) == TRUE ) {
511                appendToBuffer( buffer, bufsize,
512                                "\r\n    Maximum Value:  %ls", tmpBuf );
513            }
514            if ( GetMinimumAccessibleValueFromContext( vmID, ac, tmpBuf,
515                 (sizeof(tmpBuf) / sizeof(wchar_t)) ) == TRUE ) {
516                appendToBuffer( buffer, bufsize,
517                                "\r\n    Minimum Value:  %ls", tmpBuf );
518            }
519        }
520
521
522        /* ===== AccessibleTable ===== */
523
524        AccessibleTableInfo tableInfo;
525
526        if ( (info.accessibleInterfaces & cAccessibleTableInterface) ==
527             cAccessibleTableInterface ) {
528            if (getAccessibleTableInfo(vmID, ac, &tableInfo) != TRUE) {
529                appendToBuffer( buffer, bufsize,
530                                "\r\nERROR: getAccessibleTableInfo failed",
531                                bufsize );
532            } else {
533                appendToBuffer( buffer, bufsize,
534                                "\r\n\r\nAccessibleTable info:", bufsize );
535
536                int trow = getAccessibleTableRow( vmID,
537                                                  tableInfo.accessibleTable, 3 );
538                appendToBuffer( buffer, bufsize,
539                                "\r\n    getAccessibleTableRow:  %d", trow);
540
541                int tcol =
542                    getAccessibleTableColumn(vmID, tableInfo.accessibleTable, 2);
543                appendToBuffer( buffer, bufsize,
544                                "\r\n    getAccessibleTableColumn:  %d", tcol );
545
546                int tindex = getAccessibleTableIndex( vmID,
547                                                      tableInfo.accessibleTable,
548                                                      2, 3 );
549                appendToBuffer( buffer, bufsize,
550                                "\r\n    getAccessibleTableIndex:  %d",
551                                tindex );
552
553                // Core info
554                appendToBuffer( buffer, bufsize,
555                                "\r\n    table row count:  %d",
556                                tableInfo.rowCount );
557                appendToBuffer( buffer, bufsize,
558                                "\r\n    table column count:  %d",
559                                tableInfo.columnCount );
560
561                AccessibleTableCellInfo tableCellInfo;
562                for (int i = 0; i < tableInfo.rowCount; i++) {
563                    for (int j = 0; j < tableInfo.columnCount; j++) {
564
565                        if ( !getAccessibleTableCellInfo( vmID,
566                                                         tableInfo.accessibleTable,
567                                                         i, j,
568                                                         &tableCellInfo ) ) {
569
570                            appendToBuffer(
571                                buffer, bufsize,
572                                "\r\nERROR: GetAccessibleTableCellInfo failed.",
573                                bufsize );
574                        } else {
575                            appendToBuffer( buffer, bufsize,
576                                "\r\n\r\n    AccessibleTable cell[%d,%d] info:",
577                                i, j );
578                            appendToBuffer( buffer, bufsize,
579                                "\r\n    Index: %ld", tableCellInfo.index );
580                            appendToBuffer( buffer, bufsize,
581                                "\r\n    Row extent: %ld",
582                                tableCellInfo.rowExtent );
583                            appendToBuffer( buffer, bufsize,
584                                "\r\n    Column extent: %ld",
585                                tableCellInfo.columnExtent );
586                            appendToBuffer( buffer, bufsize,
587                                "\r\n    Is selected?: %ld",
588                                tableCellInfo.isSelected );
589
590                            AccessibleContextInfo cellACInfo;
591                            if ( !GetAccessibleContextInfo(
592                                    vmID,
593                                    tableCellInfo.accessibleContext,
594                                    &cellACInfo ) ) {
595                                appendToBuffer( buffer, bufsize,
596                                    "\r\nERROR: GetAccessibleContextInfo failed for table cell [%d,%d].",
597                                    i, j );
598                            } else {
599                                if ( !getVirtualAccessibleName( vmID,
600                                        tableCellInfo.accessibleContext, name,
601                                        (sizeof(name) / sizeof(wchar_t)) ) ) {
602                                    appendToBuffer( buffer, bufsize,
603                                        "\r\n\r\nERROR: getVirtualAccessibleName",
604                                        bufsize );
605                                } else {
606                                    appendToBuffer( buffer, bufsize,
607                                                    "\r\n    Name:  %ls", name );
608                                }
609                                appendToBuffer( buffer, bufsize,
610                                                "\r\n    Role:  %ls",
611                                                cellACInfo.role );
612                            }
613                            ReleaseJavaObject( vmID,
614                                               tableCellInfo.accessibleContext );
615                        }
616                    }
617                }
618
619                // Get the column headers
620                AccessibleTableInfo columnInfo;
621                if ( !getAccessibleTableColumnHeader(vmID, ac, &columnInfo)) {
622                    appendToBuffer( buffer, bufsize,
623                        "\r\nERROR: getAccessibleTableColumnHeader failed.",
624                        bufsize );
625                } else {
626                    appendToBuffer( buffer, bufsize,
627                        "\r\n\r\nAccessibleTable column header info:", bufsize );
628
629                    // Core info
630                    appendToBuffer( buffer, bufsize,
631                                    "\r\n    Column header row count:  %d",
632                                    columnInfo.rowCount );
633                    appendToBuffer( buffer, bufsize,
634                                    "\r\n    Column header column count:  %d",
635                                    columnInfo.columnCount );
636
637                }
638
639                // Get the selected rows
640                int numSelections =
641                    getAccessibleTableRowSelectionCount( vmID,
642                                                         tableInfo.accessibleTable );
643                appendToBuffer( buffer, bufsize,
644                                "\r\n\r\nRow selection count:  %d",
645                                numSelections );
646                jint *selections = new jint[numSelections];
647
648                if ( !getAccessibleTableRowSelections( vmID,
649                                                       tableInfo.accessibleTable,
650                                                       numSelections,
651                                                       selections ) ) {
652                    appendToBuffer( buffer, bufsize,
653                        "\r\nERROR: getAccessibleTableRowSelections failed.",
654                        bufsize );
655                } else {
656                    appendToBuffer(buffer, bufsize, "  \r\n  Row selections: ");
657                    for (int j = 0; j < numSelections; j++) {
658                        appendToBuffer(buffer, bufsize, " %d", selections[j]);
659                    }
660                }
661
662                // Get column header info
663                for (int i = 0; i < columnInfo.columnCount; i++) {
664                    if ( !getAccessibleTableCellInfo( vmID,
665                                                      columnInfo.accessibleTable,
666                                                      0, i, &tableCellInfo ) ) {
667
668                        appendToBuffer( buffer, bufsize,
669                            "\r\nERROR: GetAccessibleTableCellInfo failed.",
670                            bufsize );
671                    } else {
672                        appendToBuffer( buffer, bufsize,
673                            "\r\n\r\nColumn header [0,%d] cell info.", i );
674                        appendToBuffer( buffer, bufsize,
675                            "\r\n    Index: %ld", tableCellInfo.index );
676                        appendToBuffer( buffer, bufsize,
677                            "\r\n    Row extent: %ld",
678                            tableCellInfo.rowExtent );
679                        appendToBuffer( buffer, bufsize,
680                            "\r\n    Column extent: %ld",
681                            tableCellInfo.columnExtent );
682                        appendToBuffer( buffer, bufsize,
683                            "\r\n    Is selected: %ld",
684                            tableCellInfo.isSelected );
685
686                        AccessibleContextInfo cellACInfo;
687                        if ( !GetAccessibleContextInfo( vmID,
688                                tableCellInfo.accessibleContext, &cellACInfo ) ) {
689                            appendToBuffer( buffer, bufsize,
690                                "\r\nERROR: GetAccessibleContextInfo failed.",
691                                bufsize );
692                        } else {
693                            if ( !getVirtualAccessibleName( vmID,
694                                    tableCellInfo.accessibleContext, name,
695                                    (sizeof(name) / sizeof(wchar_t)) ) ) {
696                                appendToBuffer( buffer, bufsize,
697                                    "\r\n\r\nERROR: getVirtualAccessibleName",
698                                    bufsize );
699                            } else {
700                                appendToBuffer( buffer, bufsize,
701                                    "\r\n    Name:  %ls", name );
702                            }
703                            appendToBuffer( buffer, bufsize,
704                                "\r\n    Role:  %ls", cellACInfo.role );
705                        }
706                        ReleaseJavaObject(vmID, tableCellInfo.accessibleContext);
707                    }
708                }
709            }
710        }
711
712        /* ===== AccessibleText ===== */
713
714        if (info.accessibleText == TRUE) {
715            AccessibleTextInfo textInfo;
716            AccessibleTextItemsInfo textItems;
717            AccessibleTextSelectionInfo textSelection;
718            AccessibleTextRectInfo rectInfo;
719            AccessibleTextAttributesInfo attributeInfo;
720
721            appendToBuffer( buffer, bufsize,
722                            "\r\n\r\nAccessible Text information:", bufsize);
723
724            if (GetAccessibleTextInfo(vmID, ac, &textInfo, x, y) == TRUE) {
725                appendToBuffer( buffer, bufsize,
726                    "\r\n    Mouse point at text index:  %d",
727                    textInfo.indexAtPoint );
728                appendToBuffer( buffer, bufsize,
729                    "\r\n    Caret at text index:  %d",
730                    textInfo.caretIndex );
731                appendToBuffer( buffer, bufsize,
732                    "\r\n    Char count:  %d",
733                    textInfo.charCount );
734            }
735            if ( GetAccessibleTextSelectionInfo(vmID, ac, &textSelection) ) {
736
737                appendToBuffer( buffer, bufsize,
738                    "\r\n    Selection start index:  %d",
739                    textSelection.selectionStartIndex );
740                appendToBuffer( buffer, bufsize,
741                    "\r\n    Selection end index:  %d",
742                    textSelection.selectionEndIndex );
743                appendToBuffer( buffer, bufsize,
744                    "\r\n    Selected text:  %ls",
745                    textSelection.selectedText );
746            }
747
748            /* ===== AccessibleText information at the mouse point ===== */
749
750            appendToBuffer( buffer, bufsize,
751                "\r\n\r\n    At mouse point index: %d", textInfo.indexAtPoint);
752
753            if (GetAccessibleTextRect(vmID, ac, &rectInfo, textInfo.indexAtPoint)) {
754
755                appendToBuffer( buffer, bufsize,
756                    "\r\n        Character bounding rectangle: [%d, %d, %d, %d]",
757                    rectInfo.x, rectInfo.y, rectInfo.width, rectInfo.height );
758            }
759
760            if ( GetAccessibleTextLineBounds( vmID, ac, textInfo.indexAtPoint,
761                                              &start, &end ) ) {
762                if ( GetAccessibleTextRange( vmID, ac, start, end, tmpBuf,
763                        (sizeof(tmpBuf) / sizeof(wchar_t)) ) ) {
764                    appendToBuffer( buffer, bufsize,
765                        "\r\n        Line bounds: [%d, %d]", start, end);
766                }
767            }
768            if ( GetAccessibleTextItems( vmID, ac, &textItems,
769                                         textInfo.indexAtPoint ) ) {
770
771                appendToBuffer( buffer, bufsize,
772                    "\r\n        Character:  %lc", textItems.letter );
773                appendToBuffer( buffer, bufsize,
774                    "\r\n        Word:  %ls", textItems.word );
775                appendToBuffer( buffer, bufsize,
776                    "\r\n        Sentence:  %ls", textItems.sentence );
777            }
778
779            /* ===== AccessibleText attributes ===== */
780
781            if (GetAccessibleTextAttributes(vmID, ac,
782                                            textInfo.indexAtPoint,
783                                            &attributeInfo)) {
784
785                appendToBuffer( buffer, bufsize, "\r\n        Core attributes: %s",
786                        attributeInfo.bold ? "bold" : "not bold" );
787                appendToBuffer( buffer, bufsize, ", %s",
788                        attributeInfo.italic ? "italic" : "not italic" );
789                appendToBuffer( buffer, bufsize, ", %s",
790                        attributeInfo.underline ? "underline" : "not underline" );
791                appendToBuffer( buffer, bufsize, ", %s",
792                        attributeInfo.strikethrough ? "strikethrough" :
793                                                      "not strikethrough" );
794                appendToBuffer( buffer, bufsize, ",  %s",
795                        attributeInfo.superscript ? "superscript" :
796                                                    "not superscript" );
797                appendToBuffer( buffer, bufsize, ", %s",
798                        attributeInfo.subscript ? "subscript" : "not subscript" );
799
800                appendToBuffer( buffer, bufsize,
801                    "\r\n        Background color:  %ls",
802                    attributeInfo.backgroundColor );
803                appendToBuffer( buffer, bufsize,
804                    "\r\n        Foreground color:  %ls",
805                    attributeInfo.foregroundColor );
806                appendToBuffer( buffer, bufsize,
807                    "\r\n        Font family:  %ls",
808                    attributeInfo.fontFamily );
809                appendToBuffer( buffer, bufsize,
810                    "\r\n        Font size:  %d",
811                    attributeInfo.fontSize );
812
813                appendToBuffer( buffer, bufsize,
814                    "\r\n        First line indent:  %f",
815                    attributeInfo.firstLineIndent );
816                appendToBuffer( buffer, bufsize,
817                    "\r\n        Left indent:  %f",
818                    attributeInfo.leftIndent );
819                appendToBuffer( buffer, bufsize,
820                    "\r\n        Right indent:  %f",
821                    attributeInfo.rightIndent );
822                appendToBuffer( buffer, bufsize,
823                    "\r\n        Line spacing:  %f",
824                    attributeInfo.lineSpacing );
825                appendToBuffer( buffer, bufsize,
826                    "\r\n        Space above:  %f",
827                    attributeInfo.spaceAbove );
828                appendToBuffer( buffer, bufsize,
829                    "\r\n        Space below:  %f",
830                    attributeInfo.spaceBelow );
831
832                appendToBuffer( buffer, bufsize,
833                    "\r\n        Full attribute string:  %ls",
834                    attributeInfo.fullAttributesString );
835
836                // get the attribute run length
837                short runLength = -1;
838                if ( getTextAttributesInRange( vmID, ac, textInfo.indexAtPoint,
839                                               textInfo.indexAtPoint + 100,
840                                               &attributeInfo, &runLength ) ) {
841                    appendToBuffer( buffer, bufsize,
842                        "\r\n        Attribute run:  %d", runLength );
843                } else {
844                    appendToBuffer( buffer, bufsize,
845                        "\r\n        getTextAttributesInRangeFailed" );
846                }
847            }
848
849            /* ===== AccessibleText information at the caret index ===== */
850
851            appendToBuffer( buffer, bufsize,
852                "\r\n\r\n    At caret index: %d", textInfo.caretIndex);
853
854            if (getCaretLocation(vmID, ac, &rectInfo, textInfo.caretIndex)) {
855                appendToBuffer( buffer, bufsize,
856                    "\r\n        Caret bounding rectangle: [%d, %d, %d, %d]",
857                    rectInfo.x, rectInfo.y, rectInfo.width, rectInfo.height );
858            }
859
860            if (GetAccessibleTextRect(vmID, ac, &rectInfo, textInfo.caretIndex)) {
861
862                appendToBuffer( buffer, bufsize,
863                    "\r\n        Character bounding rectangle: [%d, %d, %d, %d]",
864                    rectInfo.x, rectInfo.y, rectInfo.width, rectInfo.height );
865            }
866
867            if ( GetAccessibleTextLineBounds( vmID, ac, textInfo.caretIndex,
868                                              &start, &end ) ) {
869                if ( GetAccessibleTextRange( vmID, ac, start, end, tmpBuf,
870                                             (sizeof(tmpBuf) / sizeof(wchar_t)) ) ) {
871
872                    appendToBuffer( buffer, bufsize,
873                        "\r\n        Line bounds: [%d, %d]", start, end);
874                }
875            }
876            if (GetAccessibleTextItems(vmID, ac, &textItems, textInfo.caretIndex)) {
877
878                appendToBuffer( buffer, bufsize,
879                    "\r\n        Character:  %lc", textItems.letter );
880                appendToBuffer( buffer, bufsize,
881                    "\r\n        Word:  %ls", textItems.word );
882                appendToBuffer( buffer, bufsize,
883                    "\r\n        Sentence:  %ls", textItems.sentence );
884            }
885
886            /* ===== AccessibleText attributes ===== */
887
888            if (GetAccessibleTextAttributes(vmID, ac, textInfo.caretIndex, &attributeInfo)) {
889
890                appendToBuffer( buffer, bufsize, "\r\n        Core attributes: %s",
891                    attributeInfo.bold ? "bold" : "not bold" );
892                appendToBuffer( buffer, bufsize, ", %s",
893                    attributeInfo.italic ? "italic" : "not italic" );
894                appendToBuffer( buffer, bufsize, ", %s",
895                    attributeInfo.underline ? "underline" : "not underline" );
896                appendToBuffer( buffer, bufsize, ", %s",
897                    attributeInfo.strikethrough ? "strikethrough" :
898                                                  "not strikethrough" );
899                appendToBuffer( buffer, bufsize, ",  %s",
900                    attributeInfo.superscript ? "superscript" :
901                                                "not superscript" );
902                appendToBuffer( buffer, bufsize, ", %s",
903                    attributeInfo.subscript ? "subscript" : "not subscript");
904
905                appendToBuffer( buffer, bufsize,
906                    "\r\n        Background color:  %ls",
907                    attributeInfo.backgroundColor );
908                appendToBuffer( buffer, bufsize,
909                    "\r\n        Foreground color:  %ls",
910                    attributeInfo.foregroundColor );
911                appendToBuffer( buffer, bufsize,
912                    "\r\n        Font family:  %ls", attributeInfo.fontFamily );
913                appendToBuffer( buffer, bufsize,
914                    "\r\n        Font size:  %d", attributeInfo.fontSize);
915
916
917                appendToBuffer( buffer, bufsize,
918                    "\r\n        First line indent:  %f",
919                    attributeInfo.firstLineIndent );
920                appendToBuffer( buffer, bufsize,
921                    "\r\n        Left indent:  %f", attributeInfo.leftIndent );
922                appendToBuffer( buffer, bufsize,
923                    "\r\n        Right indent:  %f", attributeInfo.rightIndent );
924                appendToBuffer( buffer, bufsize,
925                    "\r\n        Line spacing:  %f", attributeInfo.lineSpacing );
926                appendToBuffer( buffer, bufsize,
927                    "\r\n        Space above:  %f", attributeInfo.spaceAbove );
928                appendToBuffer( buffer, bufsize,
929                    "\r\n        Space below:  %f", attributeInfo.spaceBelow );
930                appendToBuffer( buffer, bufsize,
931                    "\r\n        Full attribute string:  %ls",
932                    attributeInfo.fullAttributesString );
933                // get the attribute run length
934                short runLength = -1;
935                if ( getTextAttributesInRange( vmID, ac, textInfo.caretIndex,
936                                               textInfo.caretIndex + 100,
937                                               &attributeInfo, &runLength ) ) {
938                    appendToBuffer( buffer, bufsize,
939                        "\r\n        Attribute run:  %d", runLength);
940                } else {
941                    appendToBuffer( buffer, bufsize,
942                        "\r\n        getTextAttributesInRangeFailed" );
943                }
944            }
945        }
946    }
947    return buffer;
948}
949